Skip to content

Commit 15755f3

Browse files
committed
Auto merge of #119302 - Mark-Simulacrum:relative-spans, r=WaffleLapkin
Support encoding spans with relative offsets 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).
2 parents ca9ff83 + 9c5293c commit 15755f3

File tree

3 files changed

+24
-3
lines changed

3 files changed

+24
-3
lines changed

compiler/rustc_metadata/src/rmeta/decoder.rs

+9-1
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

+13-1
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,19 @@ 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 last_location = *o.get();
176+
// This cannot underflow. Metadata is written with increasing position(), so any
177+
// previously saved offset must be smaller than the current position.
178+
let offset = s.opaque.position() - last_location;
179+
if offset < last_location {
180+
SpanEncodingMode::RelativeOffset(offset).encode(s)
181+
} else {
182+
SpanEncodingMode::AbsoluteOffset(last_location).encode(s)
183+
}
184+
}
173185
Entry::Vacant(v) => {
174186
let position = s.opaque.position();
175187
v.insert(position);

compiler/rustc_metadata/src/rmeta/mod.rs

+2-1
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)