@@ -100,8 +100,7 @@ impl AllocationExtra<(), ()> for () {
100100impl < Tag , Extra > Allocation < Tag , Extra > {
101101 /// Creates a read-only allocation initialized by the given bytes
102102 pub fn from_bytes ( slice : & [ u8 ] , align : Align , extra : Extra ) -> Self {
103- let mut undef_mask = UndefMask :: new ( Size :: ZERO ) ;
104- undef_mask. grow ( Size :: from_bytes ( slice. len ( ) as u64 ) , true ) ;
103+ let undef_mask = UndefMask :: new ( Size :: from_bytes ( slice. len ( ) as u64 ) , true ) ;
105104 Self {
106105 bytes : slice. to_owned ( ) ,
107106 relocations : Relocations :: new ( ) ,
@@ -121,7 +120,7 @@ impl<Tag, Extra> Allocation<Tag, Extra> {
121120 Allocation {
122121 bytes : vec ! [ 0 ; size. bytes( ) as usize ] ,
123122 relocations : Relocations :: new ( ) ,
124- undef_mask : UndefMask :: new ( size) ,
123+ undef_mask : UndefMask :: new ( size, false ) ,
125124 align,
126125 mutability : Mutability :: Mutable ,
127126 extra,
@@ -625,12 +624,12 @@ impl_stable_hash_for!(struct mir::interpret::UndefMask{blocks, len});
625624impl UndefMask {
626625 pub const BLOCK_SIZE : u64 = 64 ;
627626
628- pub fn new ( size : Size ) -> Self {
627+ pub fn new ( size : Size , state : bool ) -> Self {
629628 let mut m = UndefMask {
630629 blocks : vec ! [ ] ,
631630 len : Size :: ZERO ,
632631 } ;
633- m. grow ( size, false ) ;
632+ m. grow ( size, state ) ;
634633 m
635634 }
636635
@@ -667,25 +666,40 @@ impl UndefMask {
667666 let ( blocka, bita) = bit_index ( start) ;
668667 let ( blockb, bitb) = bit_index ( end) ;
669668 if blocka == blockb {
670- // within a single block
671- for i in bita .. bitb {
672- self . set_bit ( blocka, i, new_state) ;
669+ // first set all bits but the first `bita`
670+ // then unset the last `64 - bitb` bits
671+ let range = if bitb == 0 {
672+ u64:: max_value ( ) << bita
673+ } else {
674+ ( u64:: max_value ( ) << bita) & ( u64:: max_value ( ) >> ( 64 - bitb) )
675+ } ;
676+ if new_state {
677+ self . blocks [ blocka] |= range;
678+ } else {
679+ self . blocks [ blocka] &= !range;
673680 }
674681 return ;
675682 }
676683 // across block boundaries
677- for i in bita .. Self :: BLOCK_SIZE as usize {
678- self . set_bit ( blocka, i, new_state) ;
679- }
680- for i in 0 .. bitb {
681- self . set_bit ( blockb, i, new_state) ;
682- }
683- // fill in all the other blocks (much faster than one bit at a time)
684684 if new_state {
685+ // set bita..64 to 1
686+ self . blocks [ blocka] |= u64:: max_value ( ) << bita;
687+ // set 0..bitb to 1
688+ if bitb != 0 {
689+ self . blocks [ blockb] |= u64:: max_value ( ) >> ( 64 - bitb) ;
690+ }
691+ // fill in all the other blocks (much faster than one bit at a time)
685692 for block in ( blocka + 1 ) .. blockb {
686693 self . blocks [ block] = u64:: max_value ( ) ;
687694 }
688695 } else {
696+ // set bita..64 to 0
697+ self . blocks [ blocka] &= !( u64:: max_value ( ) << bita) ;
698+ // set 0..bitb to 0
699+ if bitb != 0 {
700+ self . blocks [ blockb] &= !( u64:: max_value ( ) >> ( 64 - bitb) ) ;
701+ }
702+ // fill in all the other blocks (much faster than one bit at a time)
689703 for block in ( blocka + 1 ) .. blockb {
690704 self . blocks [ block] = 0 ;
691705 }
@@ -695,7 +709,7 @@ impl UndefMask {
695709 #[ inline]
696710 pub fn get ( & self , i : Size ) -> bool {
697711 let ( block, bit) = bit_index ( i) ;
698- ( self . blocks [ block] & 1 << bit) != 0
712+ ( self . blocks [ block] & ( 1 << bit) ) != 0
699713 }
700714
701715 #[ inline]
@@ -714,6 +728,9 @@ impl UndefMask {
714728 }
715729
716730 pub fn grow ( & mut self , amount : Size , new_state : bool ) {
731+ if amount. bytes ( ) == 0 {
732+ return ;
733+ }
717734 let unused_trailing_bits = self . blocks . len ( ) as u64 * Self :: BLOCK_SIZE - self . len . bytes ( ) ;
718735 if amount. bytes ( ) > unused_trailing_bits {
719736 let additional_blocks = amount. bytes ( ) / Self :: BLOCK_SIZE + 1 ;
0 commit comments