Skip to content

Commit

Permalink
Use unrolled loop
Browse files Browse the repository at this point in the history
  • Loading branch information
tesuji committed Apr 2, 2020
1 parent 041e170 commit 89bc236
Showing 1 changed file with 43 additions and 9 deletions.
52 changes: 43 additions & 9 deletions src/libstd/sys/windows/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,20 +81,54 @@ pub fn decode_error_kind(errno: i32) -> ErrorKind {
}
}

pub fn wmemchr(needle: u16, haystack: &[u16]) -> Option<usize> {
extern "C" {
fn wmemchr(s: *const u16, c: u16, n: usize) -> *mut u16;
}
let len = haystack.len();
pub fn unrolled_find_u16s(needle: u16, haystack: &[u16]) -> Option<usize> {
let ptr = haystack.as_ptr();
let p = unsafe { wmemchr(ptr, needle, len) };
if p.is_null() { None } else { Some((p as usize - ptr as usize) / 2) }
let mut len = haystack.len();
let mut start = &haystack[..];

// For performance reasons unfold the loop eight times.
while len >= 8 {
if start[0] == needle {
return Some((start.as_ptr() as usize - ptr as usize) / 2);
}
if start[1] == needle {
return Some((start[1..].as_ptr() as usize - ptr as usize) / 2);
}
if start[2] == needle {
return Some((start[2..].as_ptr() as usize - ptr as usize) / 2);
}
if start[3] == needle {
return Some((start[3..].as_ptr() as usize - ptr as usize) / 2);
}
if start[4] == needle {
return Some((start[4..].as_ptr() as usize - ptr as usize) / 2);
}
if start[5] == needle {
return Some((start[5..].as_ptr() as usize - ptr as usize) / 2);
}
if start[6] == needle {
return Some((start[6..].as_ptr() as usize - ptr as usize) / 2);
}
if start[7] == needle {
return Some((start[7..].as_ptr() as usize - ptr as usize) / 2);
}

start = &start[8..];
len -= 8;
}

for (i, c) in start.iter().enumerate() {
if *c == needle {
return Some((start.as_ptr() as usize - ptr as usize) / 2 + i);
}
}
None
}

pub fn to_u16s<S: AsRef<OsStr>>(s: S) -> crate::io::Result<Vec<u16>> {
fn inner(s: &OsStr) -> crate::io::Result<Vec<u16>> {
let mut maybe_result: Vec<u16> = s.encode_wide().collect();
if wmemchr(0, &maybe_result).is_some() {
if unrolled_find_u16s(0, &maybe_result).is_some() {
return Err(crate::io::Error::new(
ErrorKind::InvalidInput,
"strings passed to WinAPI cannot contain NULs",
Expand Down Expand Up @@ -224,7 +258,7 @@ fn wide_char_to_multi_byte(
}

pub fn truncate_utf16_at_nul(v: &[u16]) -> &[u16] {
match wmemchr(0, v) {
match unrolled_find_u16s(0, v) {
// don't include the 0
Some(i) => &v[..i],
None => v,
Expand Down

0 comments on commit 89bc236

Please sign in to comment.