Skip to content

Commit f20ceb1

Browse files
committed
Encode index of SourceFile along with span.
1 parent 55f4641 commit f20ceb1

File tree

5 files changed

+65
-69
lines changed

5 files changed

+65
-69
lines changed

compiler/rustc_metadata/src/rmeta/decoder.rs

Lines changed: 11 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -527,6 +527,9 @@ impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for Span {
527527
bug!("Cannot decode Span without Session.")
528528
};
529529

530+
// Index of the file in the corresponding crate's list of encoded files.
531+
let metadata_index = usize::decode(decoder);
532+
530533
// There are two possibilities here:
531534
// 1. This is a 'local span', which is located inside a `SourceFile`
532535
// that came from this crate. In this case, we use the source map data
@@ -587,27 +590,9 @@ impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for Span {
587590
foreign_data.imported_source_files(sess)
588591
};
589592

590-
let source_file = {
591-
// Optimize for the case that most spans within a translated item
592-
// originate from the same source_file.
593-
let last_source_file = &imported_source_files[decoder.last_source_file_index];
594-
595-
if lo >= last_source_file.original_start_pos && lo <= last_source_file.original_end_pos
596-
{
597-
last_source_file
598-
} else {
599-
let index = imported_source_files
600-
.binary_search_by_key(&lo, |source_file| source_file.original_start_pos)
601-
.unwrap_or_else(|index| index - 1);
602-
603-
// Don't try to cache the index for foreign spans,
604-
// as this would require a map from CrateNums to indices
605-
if tag == TAG_VALID_SPAN_LOCAL {
606-
decoder.last_source_file_index = index;
607-
}
608-
&imported_source_files[index]
609-
}
610-
};
593+
// Optimize for the case that most spans within a translated item
594+
// originate from the same source_file.
595+
let source_file = &imported_source_files[metadata_index];
611596

612597
// Make sure our binary search above is correct.
613598
debug_assert!(
@@ -1545,7 +1530,8 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
15451530
let external_source_map = self.root.source_map.decode(self);
15461531

15471532
external_source_map
1548-
.map(|source_file_to_import| {
1533+
.enumerate()
1534+
.map(|(source_file_index, source_file_to_import)| {
15491535
// We can't reuse an existing SourceFile, so allocate a new one
15501536
// containing the information we need.
15511537
let rustc_span::SourceFile {
@@ -1605,6 +1591,9 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
16051591
normalized_pos,
16061592
start_pos,
16071593
end_pos,
1594+
source_file_index
1595+
.try_into()
1596+
.expect("cannot import more than U32_MAX files"),
16081597
);
16091598
debug!(
16101599
"CrateMetaData::imported_source_files alloc \

compiler/rustc_metadata/src/rmeta/encoder.rs

Lines changed: 49 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ use rustc_hir::definitions::DefPathData;
1717
use rustc_hir::intravisit::{self, Visitor};
1818
use rustc_hir::lang_items;
1919
use rustc_hir::{AnonConst, GenericParamKind};
20-
use rustc_index::bit_set::GrowableBitSet;
2120
use rustc_middle::hir::nested_filter;
2221
use rustc_middle::middle::dependency_format::Linkage;
2322
use rustc_middle::middle::exported_symbols::{
@@ -66,13 +65,10 @@ pub(super) struct EncodeContext<'a, 'tcx> {
6665
// The indices (into the `SourceMap`'s `MonotonicVec`)
6766
// of all of the `SourceFiles` that we need to serialize.
6867
// When we serialize a `Span`, we insert the index of its
69-
// `SourceFile` into the `GrowableBitSet`.
70-
//
71-
// This needs to be a `GrowableBitSet` and not a
72-
// regular `BitSet` because we may actually import new `SourceFiles`
73-
// during metadata encoding, due to executing a query
74-
// with a result containing a foreign `Span`.
75-
required_source_files: Option<GrowableBitSet<usize>>,
68+
// `SourceFile` into the `FxIndexSet`.
69+
// The order inside the `FxIndexSet` is used as on-disk
70+
// order of `SourceFiles`, and encoded inside `Span`s.
71+
required_source_files: Option<FxIndexSet<usize>>,
7672
is_proc_macro: bool,
7773
hygiene_ctxt: &'a HygieneEncodeContext,
7874
}
@@ -245,10 +241,6 @@ impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for Span {
245241
return TAG_PARTIAL_SPAN.encode(s);
246242
}
247243

248-
let source_files = s.required_source_files.as_mut().expect("Already encoded SourceMap!");
249-
// Record the fact that we need to encode the data for this `SourceFile`
250-
source_files.insert(s.source_file_cache.1);
251-
252244
// There are two possible cases here:
253245
// 1. This span comes from a 'foreign' crate - e.g. some crate upstream of the
254246
// crate we are writing metadata for. When the metadata for *this* crate gets
@@ -265,30 +257,38 @@ impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for Span {
265257
// if we're a proc-macro crate.
266258
// This allows us to avoid loading the dependencies of proc-macro crates: all of
267259
// the information we need to decode `Span`s is stored in the proc-macro crate.
268-
let (tag, lo, hi) = if s.source_file_cache.0.is_imported() && !s.is_proc_macro {
269-
// To simplify deserialization, we 'rebase' this span onto the crate it originally came from
270-
// (the crate that 'owns' the file it references. These rebased 'lo' and 'hi' values
271-
// are relative to the source map information for the 'foreign' crate whose CrateNum
272-
// we write into the metadata. This allows `imported_source_files` to binary
273-
// search through the 'foreign' crate's source map information, using the
274-
// deserialized 'lo' and 'hi' values directly.
275-
//
276-
// All of this logic ensures that the final result of deserialization is a 'normal'
277-
// Span that can be used without any additional trouble.
278-
let external_start_pos = {
279-
// Introduce a new scope so that we drop the 'lock()' temporary
280-
match &*s.source_file_cache.0.external_src.lock() {
281-
ExternalSource::Foreign { original_start_pos, .. } => *original_start_pos,
282-
src => panic!("Unexpected external source {:?}", src),
283-
}
284-
};
285-
let lo = (span.lo - s.source_file_cache.0.start_pos) + external_start_pos;
286-
let hi = (span.hi - s.source_file_cache.0.start_pos) + external_start_pos;
260+
let (tag, lo, hi, metadata_index) =
261+
if s.source_file_cache.0.is_imported() && !s.is_proc_macro {
262+
// To simplify deserialization, we 'rebase' this span onto the crate it originally came from
263+
// (the crate that 'owns' the file it references. These rebased 'lo' and 'hi' values
264+
// are relative to the source map information for the 'foreign' crate whose CrateNum
265+
// we write into the metadata. This allows `imported_source_files` to binary
266+
// search through the 'foreign' crate's source map information, using the
267+
// deserialized 'lo' and 'hi' values directly.
268+
//
269+
// All of this logic ensures that the final result of deserialization is a 'normal'
270+
// Span that can be used without any additional trouble.
271+
let (external_start_pos, metadata_index) = {
272+
// Introduce a new scope so that we drop the 'lock()' temporary
273+
match &*s.source_file_cache.0.external_src.lock() {
274+
ExternalSource::Foreign { original_start_pos, metadata_index, .. } => {
275+
(*original_start_pos, *metadata_index as usize)
276+
}
277+
src => panic!("Unexpected external source {:?}", src),
278+
}
279+
};
280+
let lo = (span.lo - s.source_file_cache.0.start_pos) + external_start_pos;
281+
let hi = (span.hi - s.source_file_cache.0.start_pos) + external_start_pos;
287282

288-
(TAG_VALID_SPAN_FOREIGN, lo, hi)
289-
} else {
290-
(TAG_VALID_SPAN_LOCAL, span.lo, span.hi)
291-
};
283+
(TAG_VALID_SPAN_FOREIGN, lo, hi, metadata_index)
284+
} else {
285+
// Record the fact that we need to encode the data for this `SourceFile`
286+
let source_files =
287+
s.required_source_files.as_mut().expect("Already encoded SourceMap!");
288+
let (source_file_index, _) = source_files.insert_full(s.source_file_cache.1);
289+
290+
(TAG_VALID_SPAN_LOCAL, span.lo, span.hi, source_file_index)
291+
};
292292

293293
tag.encode(s);
294294
lo.encode(s);
@@ -298,6 +298,9 @@ impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for Span {
298298
let len = hi - lo;
299299
len.encode(s);
300300

301+
// Encode the index of the `SourceFile` for the span, in order to make decoding faster.
302+
metadata_index.encode(s);
303+
301304
if tag == TAG_VALID_SPAN_FOREIGN {
302305
// This needs to be two lines to avoid holding the `s.source_file_cache`
303306
// while calling `cnum.encode(s)`
@@ -460,18 +463,17 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
460463

461464
let working_directory = &self.tcx.sess.opts.working_dir;
462465

463-
let adapted = all_source_files
466+
// Only serialize `SourceFile`s that were used during the encoding of a `Span`.
467+
//
468+
// The order in which we encode source files is important here: the on-disk format for
469+
// `Span` contains the index of the corresponding `SourceFile`.
470+
let adapted = required_source_files
464471
.iter()
465-
.enumerate()
466-
.filter(|(idx, source_file)| {
467-
// Only serialize `SourceFile`s that were used
468-
// during the encoding of a `Span`
469-
required_source_files.contains(*idx) &&
470-
// Don't serialize imported `SourceFile`s, unless
471-
// we're in a proc-macro crate.
472-
(!source_file.is_imported() || self.is_proc_macro)
473-
})
474-
.map(|(_, source_file)| {
472+
.map(|&source_file_index| &all_source_files[source_file_index])
473+
.map(|source_file| {
474+
// Don't serialize imported `SourceFile`s, unless we're in a proc-macro crate.
475+
assert!(!source_file.is_imported() || self.is_proc_macro);
476+
475477
// At export time we expand all source file paths to absolute paths because
476478
// downstream compilation sessions can have a different compiler working
477479
// directory, so relative paths from this or any other upstream crate
@@ -2228,7 +2230,7 @@ fn encode_metadata_impl(tcx: TyCtxt<'_>, path: &Path) {
22282230

22292231
let source_map_files = tcx.sess.source_map().files();
22302232
let source_file_cache = (source_map_files[0].clone(), 0);
2231-
let required_source_files = Some(GrowableBitSet::with_capacity(source_map_files.len()));
2233+
let required_source_files = Some(FxIndexSet::default());
22322234
drop(source_map_files);
22332235

22342236
let hygiene_ctxt = HygieneEncodeContext::default();

compiler/rustc_span/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1098,6 +1098,8 @@ pub enum ExternalSource {
10981098
original_start_pos: BytePos,
10991099
/// The end of this SourceFile within the source_map of its original crate.
11001100
original_end_pos: BytePos,
1101+
/// Index of the file inside metadata.
1102+
metadata_index: u32,
11011103
},
11021104
}
11031105

compiler/rustc_span/src/source_map.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -337,6 +337,7 @@ impl SourceMap {
337337
mut file_local_normalized_pos: Vec<NormalizedPos>,
338338
original_start_pos: BytePos,
339339
original_end_pos: BytePos,
340+
metadata_index: u32,
340341
) -> Lrc<SourceFile> {
341342
let start_pos = self
342343
.allocate_address_space(source_len)
@@ -383,6 +384,7 @@ impl SourceMap {
383384
kind: ExternalSourceKind::AbsentOk,
384385
original_start_pos,
385386
original_end_pos,
387+
metadata_index,
386388
}),
387389
start_pos,
388390
end_pos,

compiler/rustc_span/src/source_map/tests.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,7 @@ fn t10() {
252252
normalized_pos,
253253
start_pos,
254254
end_pos,
255+
0,
255256
);
256257

257258
assert!(

0 commit comments

Comments
 (0)