@@ -2337,14 +2337,30 @@ impl<'a, T> IntoIterator for &'a mut [T] {
23372337 }
23382338}
23392339
2340+ // Inlining is_empty and len makes a huge performance difference
2341+ macro_rules! is_empty {
2342+ // The way we encode the length of a ZST iterator, this works both for ZST
2343+ // and non-ZST.
2344+ ( $self: expr) => { $self. ptr == $self. end}
2345+ }
2346+ macro_rules! len {
2347+ ( $T: ty, $self: expr) => { {
2348+ if mem:: size_of:: <$T>( ) == 0 {
2349+ ( $self. end as usize ) . wrapping_sub( $self. ptr as usize )
2350+ } else {
2351+ $self. end. offset_from( $self. ptr) as usize
2352+ }
2353+ } }
2354+ }
2355+
23402356// The shared definition of the `Iter` and `IterMut` iterators
23412357macro_rules! iterator {
23422358 ( struct $name: ident -> $ptr: ty, $elem: ty, $raw_mut: tt, $( $mut_: tt ) * ) => {
23432359 impl <' a, T > $name<' a, T > {
23442360 // Helper function for creating a slice from the iterator.
23452361 #[ inline( always) ]
23462362 fn make_slice( & self ) -> & ' a [ T ] {
2347- unsafe { from_raw_parts( self . ptr, self . len( ) ) }
2363+ unsafe { from_raw_parts( self . ptr, len! ( T , self ) ) }
23482364 }
23492365
23502366 // Helper function for moving the start of the iterator forwards by `offset` elements,
@@ -2382,20 +2398,12 @@ macro_rules! iterator {
23822398 impl <' a, T > ExactSizeIterator for $name<' a, T > {
23832399 #[ inline( always) ]
23842400 fn len( & self ) -> usize {
2385- let diff = ( self . end as usize ) . wrapping_sub( self . ptr as usize ) ;
2386- if mem:: size_of:: <T >( ) == 0 {
2387- // end is really ptr+len, so we are already done
2388- diff
2389- } else {
2390- diff / mem:: size_of:: <T >( )
2391- }
2401+ unsafe { len!( T , self ) }
23922402 }
23932403
23942404 #[ inline( always) ]
23952405 fn is_empty( & self ) -> bool {
2396- // The way we encode the length of a ZST iterator, this works both for ZST
2397- // and non-ZST.
2398- self . ptr == self . end
2406+ is_empty!( self )
23992407 }
24002408 }
24012409
@@ -2411,7 +2419,7 @@ macro_rules! iterator {
24112419 if mem:: size_of:: <T >( ) != 0 {
24122420 assume( !self . end. is_null( ) ) ;
24132421 }
2414- if self . is_empty( ) {
2422+ if is_empty! ( self ) {
24152423 None
24162424 } else {
24172425 Some ( & $( $mut_ ) * * self . post_inc_start( 1 ) )
@@ -2421,7 +2429,7 @@ macro_rules! iterator {
24212429
24222430 #[ inline]
24232431 fn size_hint( & self ) -> ( usize , Option <usize >) {
2424- let exact = self . len( ) ;
2432+ let exact = unsafe { len! ( T , self ) } ;
24252433 ( exact, Some ( exact) )
24262434 }
24272435
@@ -2432,7 +2440,7 @@ macro_rules! iterator {
24322440
24332441 #[ inline]
24342442 fn nth( & mut self , n: usize ) -> Option <$elem> {
2435- if n >= self . len( ) {
2443+ if n >= unsafe { len! ( T , self ) } {
24362444 // This iterator is now empty.
24372445 if mem:: size_of:: <T >( ) == 0 {
24382446 // We have to do it this way as `ptr` may never be 0, but `end`
@@ -2463,13 +2471,13 @@ macro_rules! iterator {
24632471 // manual unrolling is needed when there are conditional exits from the loop
24642472 let mut accum = init;
24652473 unsafe {
2466- while self . len( ) >= 4 {
2474+ while len! ( T , self ) >= 4 {
24672475 accum = f( accum, & $( $mut_ ) * * self . post_inc_start( 1 ) ) ?;
24682476 accum = f( accum, & $( $mut_ ) * * self . post_inc_start( 1 ) ) ?;
24692477 accum = f( accum, & $( $mut_ ) * * self . post_inc_start( 1 ) ) ?;
24702478 accum = f( accum, & $( $mut_ ) * * self . post_inc_start( 1 ) ) ?;
24712479 }
2472- while !self . is_empty( ) {
2480+ while !is_empty! ( self ) {
24732481 accum = f( accum, & $( $mut_ ) * * self . post_inc_start( 1 ) ) ?;
24742482 }
24752483 }
@@ -2539,7 +2547,7 @@ macro_rules! iterator {
25392547 if mem:: size_of:: <T >( ) != 0 {
25402548 assume( !self . end. is_null( ) ) ;
25412549 }
2542- if self . is_empty( ) {
2550+ if is_empty! ( self ) {
25432551 None
25442552 } else {
25452553 Some ( & $( $mut_ ) * * self . pre_dec_end( 1 ) )
@@ -2554,13 +2562,14 @@ macro_rules! iterator {
25542562 // manual unrolling is needed when there are conditional exits from the loop
25552563 let mut accum = init;
25562564 unsafe {
2557- while self . len( ) >= 4 {
2565+ while len! ( T , self ) >= 4 {
25582566 accum = f( accum, & $( $mut_ ) * * self . pre_dec_end( 1 ) ) ?;
25592567 accum = f( accum, & $( $mut_ ) * * self . pre_dec_end( 1 ) ) ?;
25602568 accum = f( accum, & $( $mut_ ) * * self . pre_dec_end( 1 ) ) ?;
25612569 accum = f( accum, & $( $mut_ ) * * self . pre_dec_end( 1 ) ) ?;
25622570 }
2563- while !self . is_empty( ) {
2571+ // inlining is_empty everywhere makes a huge performance difference
2572+ while !is_empty!( self ) {
25642573 accum = f( accum, & $( $mut_ ) * * self . pre_dec_end( 1 ) ) ?;
25652574 }
25662575 }
@@ -2760,7 +2769,7 @@ impl<'a, T> IterMut<'a, T> {
27602769 /// ```
27612770 #[ stable( feature = "iter_to_slice" , since = "1.4.0" ) ]
27622771 pub fn into_slice ( self ) -> & ' a mut [ T ] {
2763- unsafe { from_raw_parts_mut ( self . ptr , self . len ( ) ) }
2772+ unsafe { from_raw_parts_mut ( self . ptr , len ! ( T , self ) ) }
27642773 }
27652774}
27662775
0 commit comments