@@ -5,7 +5,9 @@ use std::hash;
5
5
use std:: iter;
6
6
use std:: ops:: Range ;
7
7
8
+ use rustc_serialize:: { Decodable , Encodable } ;
8
9
use rustc_target:: abi:: Size ;
10
+ use rustc_type_ir:: { TyDecoder , TyEncoder } ;
9
11
10
12
use super :: AllocRange ;
11
13
@@ -182,11 +184,39 @@ impl InitMask {
182
184
/// The actual materialized blocks of the bitmask, when we can't keep the `InitMask` lazy.
183
185
// Note: for performance reasons when interning, some of the fields can be partially
184
186
// 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 ) ]
186
188
struct InitMaskMaterialized {
187
189
blocks : Vec < Block > ,
188
190
}
189
191
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
+
190
220
// Const allocations are only hashed for interning. However, they can be large, making the hashing
191
221
// expensive especially since it uses `FxHash`: it's better suited to short keys, not potentially
192
222
// big buffers like the allocation's init mask. We can partially hash some fields when they're
0 commit comments