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).
This commit is contained in:
parent
71696e516d
commit
9c5293c27b
@ -507,10 +507,18 @@ impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for ExpnId {
|
|||||||
|
|
||||||
impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for Span {
|
impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for Span {
|
||||||
fn decode(decoder: &mut DecodeContext<'a, 'tcx>) -> Span {
|
fn decode(decoder: &mut DecodeContext<'a, 'tcx>) -> Span {
|
||||||
|
let start = decoder.position();
|
||||||
let mode = SpanEncodingMode::decode(decoder);
|
let mode = SpanEncodingMode::decode(decoder);
|
||||||
let data = match mode {
|
let data = match mode {
|
||||||
SpanEncodingMode::Direct => SpanData::decode(decoder),
|
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);
|
let mode = SpanEncodingMode::decode(decoder);
|
||||||
debug_assert!(matches!(mode, SpanEncodingMode::Direct));
|
debug_assert!(matches!(mode, SpanEncodingMode::Direct));
|
||||||
SpanData::decode(decoder)
|
SpanData::decode(decoder)
|
||||||
|
@ -169,7 +169,19 @@ impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for ExpnId {
|
|||||||
impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for Span {
|
impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for Span {
|
||||||
fn encode(&self, s: &mut EncodeContext<'a, 'tcx>) {
|
fn encode(&self, s: &mut EncodeContext<'a, 'tcx>) {
|
||||||
match s.span_shorthands.entry(*self) {
|
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) => {
|
Entry::Vacant(v) => {
|
||||||
let position = s.opaque.position();
|
let position = s.opaque.position();
|
||||||
v.insert(position);
|
v.insert(position);
|
||||||
|
@ -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)]
|
#[derive(Encodable, Decodable)]
|
||||||
enum SpanEncodingMode {
|
enum SpanEncodingMode {
|
||||||
Shorthand(usize),
|
RelativeOffset(usize),
|
||||||
|
AbsoluteOffset(usize),
|
||||||
Direct,
|
Direct,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user