Skip to content

Commit 7333484

Browse files
committed
Auto merge of #137152 - saethlin:bss-const-allocs, r=<try>
Add a .bss-like scheme for encoded const allocs r? ghost This check if all bytes are zero feel like it should be too slow, and instead we should have a flag that we track, but that seems hard. Let's see how this perfs first. Also we can probably stash the "it's all zero actually" flag inside one of the other struct members that's already not using an entire byte. This optimization doesn't fire all that often, so it's possible that by sticking it in the varint length field, this PR actually makes rmeta size worse.
2 parents 5bc6231 + b84f6fe commit 7333484

File tree

1 file changed

+49
-2
lines changed

1 file changed

+49
-2
lines changed

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

Lines changed: 49 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use provenance_map::*;
1515
use rustc_abi::{Align, HasDataLayout, Size};
1616
use rustc_ast::Mutability;
1717
use rustc_data_structures::intern::Interned;
18-
use rustc_macros::{HashStable, TyDecodable, TyEncodable};
18+
use rustc_macros::HashStable;
1919

2020
use super::{
2121
AllocId, BadBytesAccess, CtfeProvenance, InterpErrorKind, InterpResult, Pointer,
@@ -77,7 +77,7 @@ impl AllocBytes for Box<[u8]> {
7777
/// module provides higher-level access.
7878
// Note: for performance reasons when interning, some of the `Allocation` fields can be partially
7979
// hashed. (see the `Hash` impl below for more details), so the impl is not derived.
80-
#[derive(Clone, Eq, PartialEq, TyEncodable, TyDecodable)]
80+
#[derive(Clone, Eq, PartialEq)]
8181
#[derive(HashStable)]
8282
pub struct Allocation<Prov: Provenance = CtfeProvenance, Extra = (), Bytes = Box<[u8]>> {
8383
/// The actual bytes of the allocation.
@@ -101,6 +101,53 @@ pub struct Allocation<Prov: Provenance = CtfeProvenance, Extra = (), Bytes = Box
101101
pub extra: Extra,
102102
}
103103

104+
use rustc_serialize::{Decodable, Encodable};
105+
use rustc_type_ir::{TyDecoder, TyEncoder};
106+
107+
impl<Prov: Provenance, Extra, Bytes, E: TyEncoder> Encodable<E> for Allocation<Prov, Extra, Bytes>
108+
where
109+
Bytes: AllocBytes,
110+
ProvenanceMap<Prov>: Encodable<E>,
111+
Extra: Encodable<E>,
112+
{
113+
fn encode(&self, encoder: &mut E) {
114+
let len = self.bytes.len() << 1;
115+
let all_zero = self.bytes.iter().all(|b| *b == 0);
116+
encoder.emit_usize(len | all_zero as usize);
117+
if !all_zero {
118+
encoder.emit_raw_bytes(&self.bytes);
119+
}
120+
self.provenance.encode(encoder);
121+
self.init_mask.encode(encoder);
122+
self.align.encode(encoder);
123+
self.mutability.encode(encoder);
124+
self.extra.encode(encoder);
125+
}
126+
}
127+
128+
impl<Prov: Provenance, Extra, Bytes, D: TyDecoder> Decodable<D> for Allocation<Prov, Extra, Bytes>
129+
where
130+
Bytes: AllocBytes,
131+
ProvenanceMap<Prov>: Decodable<D>,
132+
Extra: Decodable<D>,
133+
{
134+
fn decode(decoder: &mut D) -> Self {
135+
let len = decoder.read_usize();
136+
let all_zero = (len & 0b1) == 1;
137+
let len = len >> 1;
138+
let bytes = if all_zero { vec![0u8; len] } else { decoder.read_raw_bytes(len).to_vec() };
139+
140+
let provenance = Decodable::decode(decoder);
141+
let init_mask = Decodable::decode(decoder);
142+
let align = Decodable::decode(decoder);
143+
let mutability = Decodable::decode(decoder);
144+
let extra = Decodable::decode(decoder);
145+
let bytes = Bytes::from_bytes(bytes, align);
146+
147+
Self { bytes, provenance, init_mask, align, mutability, extra }
148+
}
149+
}
150+
104151
/// This is the maximum size we will hash at a time, when interning an `Allocation` and its
105152
/// `InitMask`. Note, we hash that amount of bytes twice: at the start, and at the end of a buffer.
106153
/// Used when these two structures are large: we only partially hash the larger fields in that

0 commit comments

Comments
 (0)