Skip to content

Commit

Permalink
Auto merge of rust-lang#119302 - Mark-Simulacrum:relative-spans, r=Wa…
Browse files Browse the repository at this point in the history
…ffleLapkin

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).
  • Loading branch information
bors committed Dec 27, 2023
2 parents ca9ff83 + 9c5293c commit 15755f3
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 3 deletions.
10 changes: 9 additions & 1 deletion compiler/rustc_metadata/src/rmeta/decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -507,10 +507,18 @@ impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for ExpnId {

impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for Span {
fn decode(decoder: &mut DecodeContext<'a, 'tcx>) -> Span {
let start = decoder.position();
let mode = SpanEncodingMode::decode(decoder);
let data = match mode {
SpanEncodingMode::Direct => SpanData::decode(decoder),
SpanEncodingMode::Shorthand(position) => decoder.with_position(position, |decoder| {
SpanEncodingMode::RelativeOffset(offset) => {
decoder.with_position(start - offset, |decoder| {
let mode = SpanEncodingMode::decode(decoder);
debug_assert!(matches!(mode, SpanEncodingMode::Direct));
SpanData::decode(decoder)
})
}
SpanEncodingMode::AbsoluteOffset(addr) => decoder.with_position(addr, |decoder| {
let mode = SpanEncodingMode::decode(decoder);
debug_assert!(matches!(mode, SpanEncodingMode::Direct));
SpanData::decode(decoder)
Expand Down
14 changes: 13 additions & 1 deletion compiler/rustc_metadata/src/rmeta/encoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,19 @@ impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for ExpnId {
impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for Span {
fn encode(&self, s: &mut EncodeContext<'a, 'tcx>) {
match s.span_shorthands.entry(*self) {
Entry::Occupied(o) => SpanEncodingMode::Shorthand(*o.get()).encode(s),
Entry::Occupied(o) => {
// If an offset is smaller than the absolute position, we encode with the offset.
// This saves space since smaller numbers encode in less bits.
let last_location = *o.get();
// This cannot underflow. Metadata is written with increasing position(), so any
// previously saved offset must be smaller than the current position.
let offset = s.opaque.position() - last_location;
if offset < last_location {
SpanEncodingMode::RelativeOffset(offset).encode(s)
} else {
SpanEncodingMode::AbsoluteOffset(last_location).encode(s)
}
}
Entry::Vacant(v) => {
let position = s.opaque.position();
v.insert(position);
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_metadata/src/rmeta/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,8 @@ pub const METADATA_HEADER: &[u8] = &[b'r', b'u', b's', b't', 0, 0, 0, METADATA_V

#[derive(Encodable, Decodable)]
enum SpanEncodingMode {
Shorthand(usize),
RelativeOffset(usize),
AbsoluteOffset(usize),
Direct,
}

Expand Down

0 comments on commit 15755f3

Please sign in to comment.