Skip to content

Commit 8039906

Browse files
committed
Auto merge of #119455 - Mark-Simulacrum:relative-spans, r=cjgillot
Embed length of offset/position into Span tag byte This cuts the average bytes/relative span from 3.5 to 3.2 on libcore, ultimately saving ~400kb of data.
2 parents b77e018 + 51dfe49 commit 8039906

File tree

3 files changed

+24
-6
lines changed

3 files changed

+24
-6
lines changed

compiler/rustc_metadata/src/rmeta/decoder.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -504,7 +504,11 @@ impl<'a, 'tcx> SpanDecoder for DecodeContext<'a, 'tcx> {
504504
let data = if tag.kind() == SpanKind::Indirect {
505505
// Skip past the tag we just peek'd.
506506
self.read_u8();
507-
let offset_or_position = self.read_usize();
507+
// indirect tag lengths are safe to access, since they're (0, 8)
508+
let bytes_needed = tag.length().unwrap().0 as usize;
509+
let mut total = [0u8; usize::BITS as usize / 8];
510+
total[..bytes_needed].copy_from_slice(self.read_raw_bytes(bytes_needed));
511+
let offset_or_position = usize::from_le_bytes(total);
508512
let position = if tag.is_relative_offset() {
509513
start - offset_or_position
510514
} else {

compiler/rustc_metadata/src/rmeta/encoder.rs

+16-4
Original file line numberDiff line numberDiff line change
@@ -172,11 +172,19 @@ impl<'a, 'tcx> SpanEncoder for EncodeContext<'a, 'tcx> {
172172
// previously saved offset must be smaller than the current position.
173173
let offset = self.opaque.position() - last_location;
174174
if offset < last_location {
175-
SpanTag::indirect(true).encode(self);
176-
offset.encode(self);
175+
let needed = bytes_needed(offset);
176+
SpanTag::indirect(true, needed as u8).encode(self);
177+
self.opaque.write_with(|dest| {
178+
*dest = offset.to_le_bytes();
179+
needed
180+
});
177181
} else {
178-
SpanTag::indirect(false).encode(self);
179-
last_location.encode(self);
182+
let needed = bytes_needed(last_location);
183+
SpanTag::indirect(false, needed as u8).encode(self);
184+
self.opaque.write_with(|dest| {
185+
*dest = last_location.to_le_bytes();
186+
needed
187+
});
180188
}
181189
}
182190
Entry::Vacant(v) => {
@@ -212,6 +220,10 @@ impl<'a, 'tcx> SpanEncoder for EncodeContext<'a, 'tcx> {
212220
}
213221
}
214222

223+
fn bytes_needed(n: usize) -> usize {
224+
(usize::BITS - n.leading_zeros()).div_ceil(u8::BITS) as usize
225+
}
226+
215227
impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for SpanData {
216228
fn encode(&self, s: &mut EncodeContext<'a, 'tcx>) {
217229
// Don't serialize any `SyntaxContext`s from a proc-macro crate,

compiler/rustc_metadata/src/rmeta/mod.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -530,11 +530,13 @@ impl SpanTag {
530530
SpanTag(data)
531531
}
532532

533-
fn indirect(relative: bool) -> SpanTag {
533+
fn indirect(relative: bool, length_bytes: u8) -> SpanTag {
534534
let mut tag = SpanTag(SpanKind::Indirect as u8);
535535
if relative {
536536
tag.0 |= 0b100;
537537
}
538+
assert!(length_bytes <= 8);
539+
tag.0 |= length_bytes << 3;
538540
tag
539541
}
540542

0 commit comments

Comments
 (0)