@@ -3029,7 +3029,7 @@ fn contains_nonascii(v: usize) -> bool {
30293029///
30303030/// - Read the first word with an unaligned load.
30313031/// - Align the pointer, read subsequent words until end with aligned loads.
3032- /// - If there's a tail, the last `usize` from `s` with an unaligned load.
3032+ /// - Read the last `usize` from `s` with an unaligned load.
30333033///
30343034/// If any of these loads produces something for which `contains_nonascii`
30353035/// (above) returns true, then we know the answer is false.
@@ -3077,7 +3077,10 @@ fn is_ascii(s: &[u8]) -> bool {
30773077 // `align_offset` though.
30783078 debug_assert_eq ! ( ( word_ptr as usize ) % mem:: align_of:: <usize >( ) , 0 ) ;
30793079
3080- while byte_pos <= len - USIZE_SIZE {
3080+ // Read subsequent words until the last aligned word, excluding the last
3081+ // aligned word by itself to be done in tail check later, to ensure that
3082+ // tail is always one `usize` at most to extra branch `byte_pos == len`.
3083+ while byte_pos < len - USIZE_SIZE {
30813084 debug_assert ! (
30823085 // Sanity check that the read is in bounds
30833086 ( word_ptr as usize + USIZE_SIZE ) <= ( start. wrapping_add( len) as usize ) &&
@@ -3098,15 +3101,9 @@ fn is_ascii(s: &[u8]) -> bool {
30983101 word_ptr = unsafe { word_ptr. add ( 1 ) } ;
30993102 }
31003103
3101- // If we have anything left over, it should be at-most 1 usize worth of bytes,
3102- // which we check with a read_unaligned.
3103- if byte_pos == len {
3104- return true ;
3105- }
3106-
31073104 // Sanity check to ensure there really is only one `usize` left. This should
31083105 // be guaranteed by our loop condition.
3109- debug_assert ! ( byte_pos < len && len - byte_pos < USIZE_SIZE ) ;
3106+ debug_assert ! ( byte_pos <= len && len - byte_pos <= USIZE_SIZE ) ;
31103107
31113108 // SAFETY: This relies on `len >= USIZE_SIZE`, which we check at the start.
31123109 let last_word = unsafe { ( start. add ( len - USIZE_SIZE ) as * const usize ) . read_unaligned ( ) } ;
0 commit comments