Skip to content

Commit 20bd7f0

Browse files
committed
utf8 validation: Compute block end upfront
Simplify the conditional used for ensuring that the whole word loop is only used if there are at least two whole words left to read. This makes the function slightly smaller and simpler, a 0-5% reduction in runtime for various test cases.
1 parent 5a3aa2f commit 20bd7f0

File tree

1 file changed

+16
-15
lines changed

1 file changed

+16
-15
lines changed

src/libcore/str/mod.rs

+16-15
Original file line numberDiff line numberDiff line change
@@ -1217,6 +1217,11 @@ fn contains_nonascii(x: usize) -> bool {
12171217
fn run_utf8_validation(v: &[u8]) -> Result<(), Utf8Error> {
12181218
let mut offset = 0;
12191219
let len = v.len();
1220+
1221+
let usize_bytes = mem::size_of::<usize>();
1222+
let ascii_block_size = 2 * usize_bytes;
1223+
let blocks_end = if len >= ascii_block_size { len - ascii_block_size + 1 } else { 0 };
1224+
12201225
while offset < len {
12211226
let old_offset = offset;
12221227
macro_rules! err { () => {{
@@ -1282,26 +1287,22 @@ fn run_utf8_validation(v: &[u8]) -> Result<(), Utf8Error> {
12821287
// Ascii case, try to skip forward quickly.
12831288
// When the pointer is aligned, read 2 words of data per iteration
12841289
// until we find a word containing a non-ascii byte.
1285-
let usize_bytes = mem::size_of::<usize>();
1286-
let bytes_per_iteration = 2 * usize_bytes;
12871290
let ptr = v.as_ptr();
12881291
let align = (ptr as usize + offset) & (usize_bytes - 1);
12891292
if align == 0 {
1290-
if len >= bytes_per_iteration {
1291-
while offset <= len - bytes_per_iteration {
1292-
unsafe {
1293-
let u = *(ptr.offset(offset as isize) as *const usize);
1294-
let v = *(ptr.offset((offset + usize_bytes) as isize) as *const usize);
1295-
1296-
// break if there is a nonascii byte
1297-
let zu = contains_nonascii(u);
1298-
let zv = contains_nonascii(v);
1299-
if zu || zv {
1300-
break;
1301-
}
1293+
while offset < blocks_end {
1294+
unsafe {
1295+
let u = *(ptr.offset(offset as isize) as *const usize);
1296+
let v = *(ptr.offset((offset + usize_bytes) as isize) as *const usize);
1297+
1298+
// break if there is a nonascii byte
1299+
let zu = contains_nonascii(u);
1300+
let zv = contains_nonascii(v);
1301+
if zu || zv {
1302+
break;
13021303
}
1303-
offset += bytes_per_iteration;
13041304
}
1305+
offset += ascii_block_size;
13051306
}
13061307
// step from the point where the wordwise loop stopped
13071308
while offset < len && v[offset] < 128 {

0 commit comments

Comments
 (0)