about summary refs log tree commit diff
diff options
context:
space:
mode:
authorUlrik Sverdrup <bluss@users.noreply.github.com>2016-11-21 23:26:31 +0100
committerUlrik Sverdrup <bluss@users.noreply.github.com>2016-11-21 23:26:31 +0100
commit20bd7f000fa788b9d38c5d664bb19b1ba38af850 (patch)
tree2256c777d7d36306c60b23b1f47e34fa0a72072d
parent5a3aa2f73cbb08c6e41418c5378791fa24a66146 (diff)
downloadrust-20bd7f000fa788b9d38c5d664bb19b1ba38af850.tar.gz
rust-20bd7f000fa788b9d38c5d664bb19b1ba38af850.zip
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.
-rw-r--r--src/libcore/str/mod.rs31
1 files changed, 16 insertions, 15 deletions
diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs
index 7f91da53142..48c0f0b2708 100644
--- a/src/libcore/str/mod.rs
+++ b/src/libcore/str/mod.rs
@@ -1217,6 +1217,11 @@ fn contains_nonascii(x: usize) -> bool {
 fn run_utf8_validation(v: &[u8]) -> Result<(), Utf8Error> {
     let mut offset = 0;
     let len = v.len();
+
+    let usize_bytes = mem::size_of::<usize>();
+    let ascii_block_size = 2 * usize_bytes;
+    let blocks_end = if len >= ascii_block_size { len - ascii_block_size + 1 } else { 0 };
+
     while offset < len {
         let old_offset = offset;
         macro_rules! err { () => {{
@@ -1282,26 +1287,22 @@ fn run_utf8_validation(v: &[u8]) -> Result<(), Utf8Error> {
             // Ascii case, try to skip forward quickly.
             // When the pointer is aligned, read 2 words of data per iteration
             // until we find a word containing a non-ascii byte.
-            let usize_bytes = mem::size_of::<usize>();
-            let bytes_per_iteration = 2 * usize_bytes;
             let ptr = v.as_ptr();
             let align = (ptr as usize + offset) & (usize_bytes - 1);
             if align == 0 {
-                if len >= bytes_per_iteration {
-                    while offset <= len - bytes_per_iteration {
-                        unsafe {
-                            let u = *(ptr.offset(offset as isize) as *const usize);
-                            let v = *(ptr.offset((offset + usize_bytes) as isize) as *const usize);
-
-                            // break if there is a nonascii byte
-                            let zu = contains_nonascii(u);
-                            let zv = contains_nonascii(v);
-                            if zu || zv {
-                                break;
-                            }
+                while offset < blocks_end {
+                    unsafe {
+                        let u = *(ptr.offset(offset as isize) as *const usize);
+                        let v = *(ptr.offset((offset + usize_bytes) as isize) as *const usize);
+
+                        // break if there is a nonascii byte
+                        let zu = contains_nonascii(u);
+                        let zv = contains_nonascii(v);
+                        if zu || zv {
+                            break;
                         }
-                        offset += bytes_per_iteration;
                     }
+                    offset += ascii_block_size;
                 }
                 // step from the point where the wordwise loop stopped
                 while offset < len && v[offset] < 128 {