Skip to content

Commit 4b34a61

Browse files
Support relative offsets when encoding spans
The relative offset is often smaller than the absolute offset, and with the LEB128 encoding, this ends up cutting the overall metadata size considerably (~1.5 megabytes on libcore). We can support both relative and absolute encodings essentially for free since we already take a full byte to differentiate between direct and indirect encodings (so an extra variant is quite cheap).
1 parent 71696e5 commit 4b34a61

File tree

3 files changed

+21
-3
lines changed

3 files changed

+21
-3
lines changed

compiler/rustc_metadata/src/rmeta/decoder.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -507,10 +507,18 @@ impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for ExpnId {
507507

508508
impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for Span {
509509
fn decode(decoder: &mut DecodeContext<'a, 'tcx>) -> Span {
510+
let start = decoder.position();
510511
let mode = SpanEncodingMode::decode(decoder);
511512
let data = match mode {
512513
SpanEncodingMode::Direct => SpanData::decode(decoder),
513-
SpanEncodingMode::Shorthand(position) => decoder.with_position(position, |decoder| {
514+
SpanEncodingMode::RelativeOffset(offset) => {
515+
decoder.with_position(start - offset, |decoder| {
516+
let mode = SpanEncodingMode::decode(decoder);
517+
debug_assert!(matches!(mode, SpanEncodingMode::Direct));
518+
SpanData::decode(decoder)
519+
})
520+
}
521+
SpanEncodingMode::AbsoluteOffset(addr) => decoder.with_position(addr, |decoder| {
514522
let mode = SpanEncodingMode::decode(decoder);
515523
debug_assert!(matches!(mode, SpanEncodingMode::Direct));
516524
SpanData::decode(decoder)

compiler/rustc_metadata/src/rmeta/encoder.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,16 @@ impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for ExpnId {
169169
impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for Span {
170170
fn encode(&self, s: &mut EncodeContext<'a, 'tcx>) {
171171
match s.span_shorthands.entry(*self) {
172-
Entry::Occupied(o) => SpanEncodingMode::Shorthand(*o.get()).encode(s),
172+
Entry::Occupied(o) => {
173+
// If an offset is smaller than the absolute position, we encode with the offset.
174+
// This saves space since smaller numbers encode in less bits.
175+
let offset = s.opaque.position() - *o.get();
176+
if offset < *o.get() {
177+
SpanEncodingMode::RelativeOffset(offset).encode(s)
178+
} else {
179+
SpanEncodingMode::AbsoluteOffset(*o.get()).encode(s)
180+
}
181+
}
173182
Entry::Vacant(v) => {
174183
let position = s.opaque.position();
175184
v.insert(position);

compiler/rustc_metadata/src/rmeta/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,8 @@ pub const METADATA_HEADER: &[u8] = &[b'r', b'u', b's', b't', 0, 0, 0, METADATA_V
6868

6969
#[derive(Encodable, Decodable)]
7070
enum SpanEncodingMode {
71-
Shorthand(usize),
71+
RelativeOffset(usize),
72+
AbsoluteOffset(usize),
7273
Direct,
7374
}
7475

0 commit comments

Comments
 (0)