Auto merge of #119455 - Mark-Simulacrum:relative-spans, r=cjgillot
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.
This commit is contained in:
commit
80399064af
3 changed files with 24 additions and 6 deletions
|
@ -504,7 +504,11 @@ impl<'a, 'tcx> SpanDecoder for DecodeContext<'a, 'tcx> {
|
||||||
let data = if tag.kind() == SpanKind::Indirect {
|
let data = if tag.kind() == SpanKind::Indirect {
|
||||||
// Skip past the tag we just peek'd.
|
// Skip past the tag we just peek'd.
|
||||||
self.read_u8();
|
self.read_u8();
|
||||||
let offset_or_position = self.read_usize();
|
// indirect tag lengths are safe to access, since they're (0, 8)
|
||||||
|
let bytes_needed = tag.length().unwrap().0 as usize;
|
||||||
|
let mut total = [0u8; usize::BITS as usize / 8];
|
||||||
|
total[..bytes_needed].copy_from_slice(self.read_raw_bytes(bytes_needed));
|
||||||
|
let offset_or_position = usize::from_le_bytes(total);
|
||||||
let position = if tag.is_relative_offset() {
|
let position = if tag.is_relative_offset() {
|
||||||
start - offset_or_position
|
start - offset_or_position
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -172,11 +172,19 @@ impl<'a, 'tcx> SpanEncoder for EncodeContext<'a, 'tcx> {
|
||||||
// previously saved offset must be smaller than the current position.
|
// previously saved offset must be smaller than the current position.
|
||||||
let offset = self.opaque.position() - last_location;
|
let offset = self.opaque.position() - last_location;
|
||||||
if offset < last_location {
|
if offset < last_location {
|
||||||
SpanTag::indirect(true).encode(self);
|
let needed = bytes_needed(offset);
|
||||||
offset.encode(self);
|
SpanTag::indirect(true, needed as u8).encode(self);
|
||||||
|
self.opaque.write_with(|dest| {
|
||||||
|
*dest = offset.to_le_bytes();
|
||||||
|
needed
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
SpanTag::indirect(false).encode(self);
|
let needed = bytes_needed(last_location);
|
||||||
last_location.encode(self);
|
SpanTag::indirect(false, needed as u8).encode(self);
|
||||||
|
self.opaque.write_with(|dest| {
|
||||||
|
*dest = last_location.to_le_bytes();
|
||||||
|
needed
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Entry::Vacant(v) => {
|
Entry::Vacant(v) => {
|
||||||
|
@ -212,6 +220,10 @@ impl<'a, 'tcx> SpanEncoder for EncodeContext<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn bytes_needed(n: usize) -> usize {
|
||||||
|
(usize::BITS - n.leading_zeros()).div_ceil(u8::BITS) as usize
|
||||||
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for SpanData {
|
impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for SpanData {
|
||||||
fn encode(&self, s: &mut EncodeContext<'a, 'tcx>) {
|
fn encode(&self, s: &mut EncodeContext<'a, 'tcx>) {
|
||||||
// Don't serialize any `SyntaxContext`s from a proc-macro crate,
|
// Don't serialize any `SyntaxContext`s from a proc-macro crate,
|
||||||
|
|
|
@ -530,11 +530,13 @@ impl SpanTag {
|
||||||
SpanTag(data)
|
SpanTag(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn indirect(relative: bool) -> SpanTag {
|
fn indirect(relative: bool, length_bytes: u8) -> SpanTag {
|
||||||
let mut tag = SpanTag(SpanKind::Indirect as u8);
|
let mut tag = SpanTag(SpanKind::Indirect as u8);
|
||||||
if relative {
|
if relative {
|
||||||
tag.0 |= 0b100;
|
tag.0 |= 0b100;
|
||||||
}
|
}
|
||||||
|
assert!(length_bytes <= 8);
|
||||||
|
tag.0 |= length_bytes << 3;
|
||||||
tag
|
tag
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue