Skip to content

Commit 56e28e9

Browse files
committed
Auto merge of rust-lang#110343 - saethlin:encode-initmask, r=lqd
Bypass the varint path when encoding InitMask The data in a `InitMask` is stored as `u64` but it is a large bitmask (not numbers) so varint encoding doesn't make sense.
2 parents 31656e7 + 69279c0 commit 56e28e9

File tree

1 file changed

+31
-1
lines changed
  • compiler/rustc_middle/src/mir/interpret/allocation

1 file changed

+31
-1
lines changed

compiler/rustc_middle/src/mir/interpret/allocation/init_mask.rs

+31-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@ use std::hash;
55
use std::iter;
66
use std::ops::Range;
77

8+
use rustc_serialize::{Decodable, Encodable};
89
use rustc_target::abi::Size;
10+
use rustc_type_ir::{TyDecoder, TyEncoder};
911

1012
use 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)]
186188
struct 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

Comments
 (0)