Skip to content

Commit 086d9ee

Browse files
committed
Auto merge of #119455 - Mark-Simulacrum:relative-spans, r=<try>
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 2a3e635 + 6367cf9 commit 086d9ee

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
@@ -512,7 +512,11 @@ impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for Span {
512512
let data = if tag.kind() == SpanKind::Indirect {
513513
// Skip past the tag we just peek'd.
514514
decoder.read_u8();
515-
let offset_or_position = decoder.read_usize();
515+
// indirect tag lengths are safe to access, since they're (0, 8)
516+
let bytes_needed = tag.length().unwrap().0 as usize;
517+
let mut total = [0u8; usize::BITS as usize / 8];
518+
total[..bytes_needed].copy_from_slice(decoder.read_raw_bytes(bytes_needed));
519+
let offset_or_position = usize::from_le_bytes(total);
516520
let position = if tag.is_relative_offset() {
517521
start - offset_or_position
518522
} else {

compiler/rustc_metadata/src/rmeta/encoder.rs

+16-4
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,10 @@ impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for ExpnId {
166166
}
167167
}
168168

169+
fn bytes_needed(n: usize) -> usize {
170+
(usize::BITS - n.leading_zeros()).div_ceil(u8::BITS) as usize
171+
}
172+
169173
impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for Span {
170174
fn encode(&self, s: &mut EncodeContext<'a, 'tcx>) {
171175
match s.span_shorthands.entry(*self) {
@@ -177,11 +181,19 @@ impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for Span {
177181
// previously saved offset must be smaller than the current position.
178182
let offset = s.opaque.position() - last_location;
179183
if offset < last_location {
180-
SpanTag::indirect(true).encode(s);
181-
offset.encode(s);
184+
let needed = bytes_needed(offset);
185+
SpanTag::indirect(true, needed as u8).encode(s);
186+
s.opaque.write_with(|dest| {
187+
*dest = offset.to_le_bytes();
188+
needed
189+
});
182190
} else {
183-
SpanTag::indirect(false).encode(s);
184-
last_location.encode(s);
191+
let needed = bytes_needed(last_location);
192+
SpanTag::indirect(false, needed as u8).encode(s);
193+
s.opaque.write_with(|dest| {
194+
*dest = last_location.to_le_bytes();
195+
needed
196+
});
185197
}
186198
}
187199
Entry::Vacant(v) => {

compiler/rustc_metadata/src/rmeta/mod.rs

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

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

0 commit comments

Comments
 (0)