Skip to content

Commit 68acb39

Browse files
committed
Auto merge of #119791 - Mark-Simulacrum:cut-leb128, r=cjgillot
Remove a large amount of leb128-coded integers This removes ~41%[^1] of the leb128-encoded integers serialized during libcore compilation by changing enum tags to opportunistically use `u8` where feasible instead of the leb128 coding via `usize`. This should have effectively zero impact on metadata file sizes, since almost all or all enum tags fit into the 7 bits available in leb128 for single-byte encodings. Perf results indicate this is basically neutral across the board except for an improvement in bootstrap time. [^1]: More than half the remaining integers still fit into <= 128, so the leb128 coding still makes sense. 32% are zero, and 46% are <= 4.
2 parents d73bd3f + 1d2005b commit 68acb39

File tree

4 files changed

+61
-42
lines changed

4 files changed

+61
-42
lines changed

compiler/rustc_macros/src/serialize.rs

+24-6
Original file line numberDiff line numberDiff line change
@@ -76,8 +76,17 @@ fn decodable_body(
7676
ty_name,
7777
variants.len()
7878
);
79+
let tag = if variants.len() < u8::MAX as usize {
80+
quote! {
81+
::rustc_serialize::Decoder::read_u8(__decoder) as usize
82+
}
83+
} else {
84+
quote! {
85+
::rustc_serialize::Decoder::read_usize(__decoder)
86+
}
87+
};
7988
quote! {
80-
match ::rustc_serialize::Decoder::read_usize(__decoder) {
89+
match #tag {
8190
#match_inner
8291
n => panic!(#message, n),
8392
}
@@ -206,11 +215,20 @@ fn encodable_body(
206215
variant_idx += 1;
207216
result
208217
});
209-
quote! {
210-
let disc = match *self {
211-
#encode_inner
212-
};
213-
::rustc_serialize::Encoder::emit_usize(__encoder, disc);
218+
if variant_idx < u8::MAX as usize {
219+
quote! {
220+
let disc = match *self {
221+
#encode_inner
222+
};
223+
::rustc_serialize::Encoder::emit_u8(__encoder, disc as u8);
224+
}
225+
} else {
226+
quote! {
227+
let disc = match *self {
228+
#encode_inner
229+
};
230+
::rustc_serialize::Encoder::emit_usize(__encoder, disc);
231+
}
214232
}
215233
};
216234

compiler/rustc_serialize/src/serialize.rs

+15-18
Original file line numberDiff line numberDiff line change
@@ -70,14 +70,6 @@ pub trait Encoder {
7070
}
7171

7272
fn emit_raw_bytes(&mut self, s: &[u8]);
73-
74-
fn emit_enum_variant<F>(&mut self, v_id: usize, f: F)
75-
where
76-
F: FnOnce(&mut Self),
77-
{
78-
self.emit_usize(v_id);
79-
f(self);
80-
}
8173
}
8274

8375
// Note: all the methods in this trait are infallible, which may be surprising.
@@ -132,10 +124,6 @@ pub trait Decoder {
132124

133125
fn read_raw_bytes(&mut self, len: usize) -> &[u8];
134126

135-
// Although there is an `emit_enum_variant` method in `Encoder`, the code
136-
// patterns in decoding are different enough to encoding that there is no
137-
// need for a corresponding `read_enum_variant` method here.
138-
139127
fn peek_byte(&self) -> u8;
140128
fn position(&self) -> usize;
141129
}
@@ -372,15 +360,18 @@ impl<'a, D: Decoder> Decodable<D> for Cow<'a, str> {
372360
impl<S: Encoder, T: Encodable<S>> Encodable<S> for Option<T> {
373361
fn encode(&self, s: &mut S) {
374362
match *self {
375-
None => s.emit_enum_variant(0, |_| {}),
376-
Some(ref v) => s.emit_enum_variant(1, |s| v.encode(s)),
363+
None => s.emit_u8(0),
364+
Some(ref v) => {
365+
s.emit_u8(1);
366+
v.encode(s);
367+
}
377368
}
378369
}
379370
}
380371

381372
impl<D: Decoder, T: Decodable<D>> Decodable<D> for Option<T> {
382373
fn decode(d: &mut D) -> Option<T> {
383-
match d.read_usize() {
374+
match d.read_u8() {
384375
0 => None,
385376
1 => Some(Decodable::decode(d)),
386377
_ => panic!("Encountered invalid discriminant while decoding `Option`."),
@@ -391,15 +382,21 @@ impl<D: Decoder, T: Decodable<D>> Decodable<D> for Option<T> {
391382
impl<S: Encoder, T1: Encodable<S>, T2: Encodable<S>> Encodable<S> for Result<T1, T2> {
392383
fn encode(&self, s: &mut S) {
393384
match *self {
394-
Ok(ref v) => s.emit_enum_variant(0, |s| v.encode(s)),
395-
Err(ref v) => s.emit_enum_variant(1, |s| v.encode(s)),
385+
Ok(ref v) => {
386+
s.emit_u8(0);
387+
v.encode(s);
388+
}
389+
Err(ref v) => {
390+
s.emit_u8(1);
391+
v.encode(s);
392+
}
396393
}
397394
}
398395
}
399396

400397
impl<D: Decoder, T1: Decodable<D>, T2: Decodable<D>> Decodable<D> for Result<T1, T2> {
401398
fn decode(d: &mut D) -> Result<T1, T2> {
402-
match d.read_usize() {
399+
match d.read_u8() {
403400
0 => Ok(T1::decode(d)),
404401
1 => Err(T2::decode(d)),
405402
_ => panic!("Encountered invalid discriminant while decoding `Result`."),

compiler/rustc_span/src/lib.rs

+12-11
Original file line numberDiff line numberDiff line change
@@ -203,18 +203,19 @@ impl Hash for RealFileName {
203203
impl<S: Encoder> Encodable<S> for RealFileName {
204204
fn encode(&self, encoder: &mut S) {
205205
match *self {
206-
RealFileName::LocalPath(ref local_path) => encoder.emit_enum_variant(0, |encoder| {
206+
RealFileName::LocalPath(ref local_path) => {
207+
encoder.emit_u8(0);
207208
local_path.encode(encoder);
208-
}),
209-
210-
RealFileName::Remapped { ref local_path, ref virtual_name } => encoder
211-
.emit_enum_variant(1, |encoder| {
212-
// For privacy and build reproducibility, we must not embed host-dependant path
213-
// in artifacts if they have been remapped by --remap-path-prefix
214-
assert!(local_path.is_none());
215-
local_path.encode(encoder);
216-
virtual_name.encode(encoder);
217-
}),
209+
}
210+
211+
RealFileName::Remapped { ref local_path, ref virtual_name } => {
212+
encoder.emit_u8(1);
213+
// For privacy and build reproducibility, we must not embed host-dependant path
214+
// in artifacts if they have been remapped by --remap-path-prefix
215+
assert!(local_path.is_none());
216+
local_path.encode(encoder);
217+
virtual_name.encode(encoder);
218+
}
218219
}
219220
}
220221
}

compiler/rustc_target/src/spec/mod.rs

+10-7
Original file line numberDiff line numberDiff line change
@@ -3396,19 +3396,22 @@ impl Hash for TargetTriple {
33963396
impl<S: Encoder> Encodable<S> for TargetTriple {
33973397
fn encode(&self, s: &mut S) {
33983398
match self {
3399-
TargetTriple::TargetTriple(triple) => s.emit_enum_variant(0, |s| s.emit_str(triple)),
3400-
TargetTriple::TargetJson { path_for_rustdoc: _, triple, contents } => s
3401-
.emit_enum_variant(1, |s| {
3402-
s.emit_str(triple);
3403-
s.emit_str(contents)
3404-
}),
3399+
TargetTriple::TargetTriple(triple) => {
3400+
s.emit_u8(0);
3401+
s.emit_str(triple);
3402+
}
3403+
TargetTriple::TargetJson { path_for_rustdoc: _, triple, contents } => {
3404+
s.emit_u8(1);
3405+
s.emit_str(triple);
3406+
s.emit_str(contents);
3407+
}
34053408
}
34063409
}
34073410
}
34083411

34093412
impl<D: Decoder> Decodable<D> for TargetTriple {
34103413
fn decode(d: &mut D) -> Self {
3411-
match d.read_usize() {
3414+
match d.read_u8() {
34123415
0 => TargetTriple::TargetTriple(d.read_str().to_owned()),
34133416
1 => TargetTriple::TargetJson {
34143417
path_for_rustdoc: PathBuf::new(),

0 commit comments

Comments
 (0)