Auto merge of #113850 - cjgillot:span-shorthand, r=compiler-errors
Encode shorthands for spans in metadata. Spans occupy a typically large proportion of metadata. This PR deduplicates encoded spans in order to reduce encoded length.
This commit is contained in:
commit
fdfcdad4fa
@ -34,7 +34,7 @@
|
|||||||
use rustc_session::Session;
|
use rustc_session::Session;
|
||||||
use rustc_span::hygiene::ExpnIndex;
|
use rustc_span::hygiene::ExpnIndex;
|
||||||
use rustc_span::symbol::{kw, Ident, Symbol};
|
use rustc_span::symbol::{kw, Ident, Symbol};
|
||||||
use rustc_span::{self, BytePos, ExpnId, Pos, Span, SyntaxContext, DUMMY_SP};
|
use rustc_span::{self, BytePos, ExpnId, Pos, Span, SpanData, SyntaxContext, DUMMY_SP};
|
||||||
|
|
||||||
use proc_macro::bridge::client::ProcMacro;
|
use proc_macro::bridge::client::ProcMacro;
|
||||||
use std::iter::TrustedLen;
|
use std::iter::TrustedLen;
|
||||||
@ -513,11 +513,26 @@ fn decode(decoder: &mut DecodeContext<'a, 'tcx>) -> 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 mode = SpanEncodingMode::decode(decoder);
|
||||||
|
let data = match mode {
|
||||||
|
SpanEncodingMode::Direct => SpanData::decode(decoder),
|
||||||
|
SpanEncodingMode::Shorthand(position) => decoder.with_position(position, |decoder| {
|
||||||
|
let mode = SpanEncodingMode::decode(decoder);
|
||||||
|
debug_assert!(matches!(mode, SpanEncodingMode::Direct));
|
||||||
|
SpanData::decode(decoder)
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
Span::new(data.lo, data.hi, data.ctxt, data.parent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for SpanData {
|
||||||
|
fn decode(decoder: &mut DecodeContext<'a, 'tcx>) -> SpanData {
|
||||||
let ctxt = SyntaxContext::decode(decoder);
|
let ctxt = SyntaxContext::decode(decoder);
|
||||||
let tag = u8::decode(decoder);
|
let tag = u8::decode(decoder);
|
||||||
|
|
||||||
if tag == TAG_PARTIAL_SPAN {
|
if tag == TAG_PARTIAL_SPAN {
|
||||||
return DUMMY_SP.with_ctxt(ctxt);
|
return DUMMY_SP.with_ctxt(ctxt).data();
|
||||||
}
|
}
|
||||||
|
|
||||||
debug_assert!(tag == TAG_VALID_SPAN_LOCAL || tag == TAG_VALID_SPAN_FOREIGN);
|
debug_assert!(tag == TAG_VALID_SPAN_LOCAL || tag == TAG_VALID_SPAN_FOREIGN);
|
||||||
@ -612,7 +627,7 @@ fn decode(decoder: &mut DecodeContext<'a, 'tcx>) -> Span {
|
|||||||
let hi = hi + source_file.translated_source_file.start_pos;
|
let hi = hi + source_file.translated_source_file.start_pos;
|
||||||
|
|
||||||
// Do not try to decode parent for foreign spans.
|
// Do not try to decode parent for foreign spans.
|
||||||
Span::new(lo, hi, ctxt, None)
|
SpanData { lo, hi, ctxt, parent: None }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,7 +37,7 @@
|
|||||||
use rustc_session::cstore::{ForeignModule, LinkagePreference, NativeLib};
|
use rustc_session::cstore::{ForeignModule, LinkagePreference, NativeLib};
|
||||||
use rustc_span::hygiene::{ExpnIndex, HygieneEncodeContext, MacroKind};
|
use rustc_span::hygiene::{ExpnIndex, HygieneEncodeContext, MacroKind};
|
||||||
use rustc_span::symbol::{sym, Symbol};
|
use rustc_span::symbol::{sym, Symbol};
|
||||||
use rustc_span::{self, ExternalSource, FileName, SourceFile, Span, SyntaxContext};
|
use rustc_span::{self, ExternalSource, FileName, SourceFile, Span, SpanData, SyntaxContext};
|
||||||
use std::borrow::Borrow;
|
use std::borrow::Borrow;
|
||||||
use std::collections::hash_map::Entry;
|
use std::collections::hash_map::Entry;
|
||||||
use std::hash::Hash;
|
use std::hash::Hash;
|
||||||
@ -53,6 +53,7 @@ pub(super) struct EncodeContext<'a, 'tcx> {
|
|||||||
tables: TableBuilders,
|
tables: TableBuilders,
|
||||||
|
|
||||||
lazy_state: LazyState,
|
lazy_state: LazyState,
|
||||||
|
span_shorthands: FxHashMap<Span, usize>,
|
||||||
type_shorthands: FxHashMap<Ty<'tcx>, usize>,
|
type_shorthands: FxHashMap<Ty<'tcx>, usize>,
|
||||||
predicate_shorthands: FxHashMap<ty::PredicateKind<'tcx>, usize>,
|
predicate_shorthands: FxHashMap<ty::PredicateKind<'tcx>, usize>,
|
||||||
|
|
||||||
@ -177,8 +178,20 @@ fn encode(&self, s: &mut EncodeContext<'a, 'tcx>) {
|
|||||||
|
|
||||||
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>) {
|
||||||
let span = self.data();
|
match s.span_shorthands.entry(*self) {
|
||||||
|
Entry::Occupied(o) => SpanEncodingMode::Shorthand(*o.get()).encode(s),
|
||||||
|
Entry::Vacant(v) => {
|
||||||
|
let position = s.opaque.position();
|
||||||
|
v.insert(position);
|
||||||
|
SpanEncodingMode::Direct.encode(s);
|
||||||
|
self.data().encode(s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for SpanData {
|
||||||
|
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,
|
||||||
// since we don't load proc-macro dependencies during serialization.
|
// since we don't load proc-macro dependencies during serialization.
|
||||||
// This means that any hygiene information from macros used *within*
|
// This means that any hygiene information from macros used *within*
|
||||||
@ -213,7 +226,7 @@ fn encode(&self, s: &mut EncodeContext<'a, 'tcx>) {
|
|||||||
if s.is_proc_macro {
|
if s.is_proc_macro {
|
||||||
SyntaxContext::root().encode(s);
|
SyntaxContext::root().encode(s);
|
||||||
} else {
|
} else {
|
||||||
span.ctxt.encode(s);
|
self.ctxt.encode(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.is_dummy() {
|
if self.is_dummy() {
|
||||||
@ -221,18 +234,18 @@ fn encode(&self, s: &mut EncodeContext<'a, 'tcx>) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// The Span infrastructure should make sure that this invariant holds:
|
// The Span infrastructure should make sure that this invariant holds:
|
||||||
debug_assert!(span.lo <= span.hi);
|
debug_assert!(self.lo <= self.hi);
|
||||||
|
|
||||||
if !s.source_file_cache.0.contains(span.lo) {
|
if !s.source_file_cache.0.contains(self.lo) {
|
||||||
let source_map = s.tcx.sess.source_map();
|
let source_map = s.tcx.sess.source_map();
|
||||||
let source_file_index = source_map.lookup_source_file_idx(span.lo);
|
let source_file_index = source_map.lookup_source_file_idx(self.lo);
|
||||||
s.source_file_cache =
|
s.source_file_cache =
|
||||||
(source_map.files()[source_file_index].clone(), source_file_index);
|
(source_map.files()[source_file_index].clone(), source_file_index);
|
||||||
}
|
}
|
||||||
let (ref source_file, source_file_index) = s.source_file_cache;
|
let (ref source_file, source_file_index) = s.source_file_cache;
|
||||||
debug_assert!(source_file.contains(span.lo));
|
debug_assert!(source_file.contains(self.lo));
|
||||||
|
|
||||||
if !source_file.contains(span.hi) {
|
if !source_file.contains(self.hi) {
|
||||||
// Unfortunately, macro expansion still sometimes generates Spans
|
// Unfortunately, macro expansion still sometimes generates Spans
|
||||||
// that malformed in this way.
|
// that malformed in this way.
|
||||||
return TAG_PARTIAL_SPAN.encode(s);
|
return TAG_PARTIAL_SPAN.encode(s);
|
||||||
@ -286,11 +299,11 @@ fn encode(&self, s: &mut EncodeContext<'a, 'tcx>) {
|
|||||||
|
|
||||||
// Encode the start position relative to the file start, so we profit more from the
|
// Encode the start position relative to the file start, so we profit more from the
|
||||||
// variable-length integer encoding.
|
// variable-length integer encoding.
|
||||||
let lo = span.lo - source_file.start_pos;
|
let lo = self.lo - source_file.start_pos;
|
||||||
|
|
||||||
// Encode length which is usually less than span.hi and profits more
|
// Encode length which is usually less than span.hi and profits more
|
||||||
// from the variable-length integer encoding that we use.
|
// from the variable-length integer encoding that we use.
|
||||||
let len = span.hi - span.lo;
|
let len = self.hi - self.lo;
|
||||||
|
|
||||||
tag.encode(s);
|
tag.encode(s);
|
||||||
lo.encode(s);
|
lo.encode(s);
|
||||||
@ -2182,6 +2195,7 @@ fn encode_metadata_impl(tcx: TyCtxt<'_>, path: &Path) {
|
|||||||
feat: tcx.features(),
|
feat: tcx.features(),
|
||||||
tables: Default::default(),
|
tables: Default::default(),
|
||||||
lazy_state: LazyState::NoNode,
|
lazy_state: LazyState::NoNode,
|
||||||
|
span_shorthands: Default::default(),
|
||||||
type_shorthands: Default::default(),
|
type_shorthands: Default::default(),
|
||||||
predicate_shorthands: Default::default(),
|
predicate_shorthands: Default::default(),
|
||||||
source_file_cache,
|
source_file_cache,
|
||||||
|
@ -66,6 +66,12 @@ pub(crate) fn rustc_version(cfg_version: &'static str) -> String {
|
|||||||
/// unsigned integer, and further followed by the rustc version string.
|
/// unsigned integer, and further followed by the rustc version string.
|
||||||
pub const METADATA_HEADER: &[u8] = &[b'r', b'u', b's', b't', 0, 0, 0, METADATA_VERSION];
|
pub const METADATA_HEADER: &[u8] = &[b'r', b'u', b's', b't', 0, 0, 0, METADATA_VERSION];
|
||||||
|
|
||||||
|
#[derive(Encodable, Decodable)]
|
||||||
|
enum SpanEncodingMode {
|
||||||
|
Shorthand(usize),
|
||||||
|
Direct,
|
||||||
|
}
|
||||||
|
|
||||||
/// A value of type T referred to by its absolute position
|
/// A value of type T referred to by its absolute position
|
||||||
/// in the metadata, and which can be decoded lazily.
|
/// in the metadata, and which can be decoded lazily.
|
||||||
///
|
///
|
||||||
|
Loading…
Reference in New Issue
Block a user