Skip to content

Commit 89bc236

Browse files
committed
Use unrolled loop
1 parent 041e170 commit 89bc236

File tree

1 file changed

+43
-9
lines changed

1 file changed

+43
-9
lines changed

src/libstd/sys/windows/mod.rs

+43-9
Original file line numberDiff line numberDiff line change
@@ -81,20 +81,54 @@ pub fn decode_error_kind(errno: i32) -> ErrorKind {
8181
}
8282
}
8383

84-
pub fn wmemchr(needle: u16, haystack: &[u16]) -> Option<usize> {
85-
extern "C" {
86-
fn wmemchr(s: *const u16, c: u16, n: usize) -> *mut u16;
87-
}
88-
let len = haystack.len();
84+
pub fn unrolled_find_u16s(needle: u16, haystack: &[u16]) -> Option<usize> {
8985
let ptr = haystack.as_ptr();
90-
let p = unsafe { wmemchr(ptr, needle, len) };
91-
if p.is_null() { None } else { Some((p as usize - ptr as usize) / 2) }
86+
let mut len = haystack.len();
87+
let mut start = &haystack[..];
88+
89+
// For performance reasons unfold the loop eight times.
90+
while len >= 8 {
91+
if start[0] == needle {
92+
return Some((start.as_ptr() as usize - ptr as usize) / 2);
93+
}
94+
if start[1] == needle {
95+
return Some((start[1..].as_ptr() as usize - ptr as usize) / 2);
96+
}
97+
if start[2] == needle {
98+
return Some((start[2..].as_ptr() as usize - ptr as usize) / 2);
99+
}
100+
if start[3] == needle {
101+
return Some((start[3..].as_ptr() as usize - ptr as usize) / 2);
102+
}
103+
if start[4] == needle {
104+
return Some((start[4..].as_ptr() as usize - ptr as usize) / 2);
105+
}
106+
if start[5] == needle {
107+
return Some((start[5..].as_ptr() as usize - ptr as usize) / 2);
108+
}
109+
if start[6] == needle {
110+
return Some((start[6..].as_ptr() as usize - ptr as usize) / 2);
111+
}
112+
if start[7] == needle {
113+
return Some((start[7..].as_ptr() as usize - ptr as usize) / 2);
114+
}
115+
116+
start = &start[8..];
117+
len -= 8;
118+
}
119+
120+
for (i, c) in start.iter().enumerate() {
121+
if *c == needle {
122+
return Some((start.as_ptr() as usize - ptr as usize) / 2 + i);
123+
}
124+
}
125+
None
92126
}
93127

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

226260
pub fn truncate_utf16_at_nul(v: &[u16]) -> &[u16] {
227-
match wmemchr(0, v) {
261+
match unrolled_find_u16s(0, v) {
228262
// don't include the 0
229263
Some(i) => &v[..i],
230264
None => v,

0 commit comments

Comments
 (0)