@@ -5,7 +5,9 @@ use std::hash;
55use std:: iter;
66use std:: ops:: Range ;
77
8+ use rustc_serialize:: { Decodable , Encodable } ;
89use rustc_target:: abi:: Size ;
10+ use rustc_type_ir:: { TyDecoder , TyEncoder } ;
911
1012use super :: AllocRange ;
1113
@@ -182,11 +184,39 @@ impl InitMask {
182184/// The actual materialized blocks of the bitmask, when we can't keep the `InitMask` lazy.
183185// Note: for performance reasons when interning, some of the fields can be partially
184186// hashed. (see the `Hash` impl below for more details), so the impl is not derived.
185- #[ derive( Clone , Debug , Eq , PartialEq , TyEncodable , TyDecodable , HashStable ) ]
187+ #[ derive( Clone , Debug , Eq , PartialEq , HashStable ) ]
186188struct InitMaskMaterialized {
187189 blocks : Vec < Block > ,
188190}
189191
192+ // `Block` is a `u64`, but it is a bitmask not a numeric value. If we were to just derive
193+ // Encodable and Decodable we would apply varint encoding to the bitmasks, which is slower
194+ // and also produces more output when the high bits of each `u64` are occupied.
195+ // Note: There is probably a remaining optimization for masks that do not use an entire
196+ // `Block`.
197+ impl < E : TyEncoder > Encodable < E > for InitMaskMaterialized {
198+ fn encode ( & self , encoder : & mut E ) {
199+ encoder. emit_usize ( self . blocks . len ( ) ) ;
200+ for block in & self . blocks {
201+ encoder. emit_raw_bytes ( & block. to_le_bytes ( ) ) ;
202+ }
203+ }
204+ }
205+
206+ // This implementation is deliberately not derived, see the matching `Encodable` impl.
207+ impl < D : TyDecoder > Decodable < D > for InitMaskMaterialized {
208+ fn decode ( decoder : & mut D ) -> Self {
209+ let num_blocks = decoder. read_usize ( ) ;
210+ let mut blocks = Vec :: with_capacity ( num_blocks) ;
211+ for _ in 0 ..num_blocks {
212+ let bytes = decoder. read_raw_bytes ( 8 ) ;
213+ let block = u64:: from_le_bytes ( bytes. try_into ( ) . unwrap ( ) ) ;
214+ blocks. push ( block) ;
215+ }
216+ InitMaskMaterialized { blocks }
217+ }
218+ }
219+
190220// Const allocations are only hashed for interning. However, they can be large, making the hashing
191221// expensive especially since it uses `FxHash`: it's better suited to short keys, not potentially
192222// big buffers like the allocation's init mask. We can partially hash some fields when they're
0 commit comments