@@ -563,22 +563,12 @@ impl<Tag, Extra> Allocation<Tag, Extra> {
563563
564564 let mut ranges = smallvec:: SmallVec :: < [ u64 ; 1 ] > :: new ( ) ;
565565 let initial = self . init_mask . get ( range. start ) ;
566- let mut cur_len = 1 ;
567- let mut cur = initial;
568566
569- for i in 1 ..range. size . bytes ( ) {
570- // FIXME: optimize to bitshift the current uninitialized block's bits and read the top bit.
571- if self . init_mask . get ( range. start + Size :: from_bytes ( i) ) == cur {
572- cur_len += 1 ;
573- } else {
574- ranges. push ( cur_len) ;
575- cur_len = 1 ;
576- cur = !cur;
577- }
567+ for chunk in self . init_mask . range_as_init_chunks ( range. start , range. end ( ) ) {
568+ let len = chunk. range ( ) . end . bytes ( ) - chunk. range ( ) . start . bytes ( ) ;
569+ ranges. push ( len) ;
578570 }
579571
580- ranges. push ( cur_len) ;
581-
582572 InitMaskCompressed { ranges, initial }
583573 }
584574
@@ -830,45 +820,65 @@ impl InitMask {
830820 }
831821}
832822
823+ /// A contiguous chunk of initialized or uninitialized memory.
824+ pub enum InitChunk {
825+ Init ( Range < Size > ) ,
826+ Uninit ( Range < Size > ) ,
827+ }
828+
829+ impl InitChunk {
830+ #[ inline]
831+ pub fn range ( & self ) -> Range < Size > {
832+ match self {
833+ Self :: Init ( r) => r. clone ( ) ,
834+ Self :: Uninit ( r) => r. clone ( ) ,
835+ }
836+ }
837+ }
838+
833839/// Yields [`InitChunk`]s. See [`InitMask::range_as_init_chunks`].
834840pub struct InitChunkIter < ' a > {
835841 init_mask : & ' a InitMask ,
842+ /// Whether the last chunk was initialized.
843+ is_init : bool ,
836844 /// The current byte index into `init_mask`.
837845 start : Size ,
838846 /// The end byte index into `init_mask`.
839847 end : Size ,
840848}
841849
842- /// A contiguous chunk of initialized or uninitialized memory.
843- pub enum InitChunk {
844- Init ( Range < Size > ) ,
845- Uninit ( Range < Size > ) ,
846- }
847-
848850impl < ' a > InitChunkIter < ' a > {
851+ #[ inline]
849852 fn new ( init_mask : & ' a InitMask , start : Size , end : Size ) -> Self {
850853 assert ! ( start <= end) ;
851854 assert ! ( end <= init_mask. len) ;
852- Self { init_mask, start, end }
855+
856+ let is_init = if start < end { init_mask. get ( start) } else { false } ;
857+
858+ Self { init_mask, is_init, start, end }
853859 }
854860}
855861
856862impl < ' a > Iterator for InitChunkIter < ' a > {
857863 type Item = InitChunk ;
858864
865+ #[ inline]
859866 fn next ( & mut self ) -> Option < Self :: Item > {
860867 if self . start >= self . end {
861868 return None ;
862869 }
863870
864- let is_init = self . init_mask . get ( self . start ) ;
865871 let end_of_chunk =
866- find_bit ( & self . init_mask , self . start , self . end , !is_init) . unwrap_or ( self . end ) ;
872+ find_bit ( & self . init_mask , self . start , self . end , !self . is_init ) . unwrap_or ( self . end ) ;
867873 let range = self . start ..end_of_chunk;
868874
875+ let ret =
876+ Some ( if self . is_init { InitChunk :: Init ( range) } else { InitChunk :: Uninit ( range) } ) ;
877+
878+ self . is_init = !self . is_init ;
869879 self . start = end_of_chunk;
870880
871- Some ( if is_init { InitChunk :: Init ( range ) } else { InitChunk :: Uninit ( range ) } )
881+ ret
872882 }
873883}
874884
0 commit comments