Skip to content

Commit a09e9c9

Browse files
committed
Decode SourceFile out of order.
1 parent f20ceb1 commit a09e9c9

File tree

4 files changed

+154
-149
lines changed

4 files changed

+154
-149
lines changed

compiler/rustc_metadata/src/rmeta/decoder.rs

Lines changed: 94 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ use rustc_span::symbol::{sym, Ident, Symbol};
3737
use rustc_span::{self, BytePos, ExpnId, Pos, Span, SyntaxContext, DUMMY_SP};
3838

3939
use proc_macro::bridge::client::ProcMacro;
40+
use std::cell::RefCell;
4041
use std::io;
4142
use std::iter::TrustedLen;
4243
use std::mem;
@@ -99,7 +100,7 @@ pub(crate) struct CrateMetadata {
99100
/// Proc macro descriptions for this crate, if it's a proc macro crate.
100101
raw_proc_macros: Option<&'static [ProcMacro]>,
101102
/// Source maps for code from the crate.
102-
source_map_import_info: OnceCell<Vec<ImportedSourceFile>>,
103+
source_map_import_info: RefCell<Vec<Option<ImportedSourceFile>>>,
103104
/// For every definition in this crate, maps its `DefPathHash` to its `DefIndex`.
104105
def_path_hash_map: DefPathHashMapRef<'static>,
105106
/// Likewise for ExpnHash.
@@ -143,7 +144,8 @@ pub(crate) struct CrateMetadata {
143144
}
144145

145146
/// Holds information about a rustc_span::SourceFile imported from another crate.
146-
/// See `imported_source_files()` for more information.
147+
/// See `imported_source_file()` for more information.
148+
#[derive(Clone)]
147149
struct ImportedSourceFile {
148150
/// This SourceFile's byte-offset within the source_map of its original crate
149151
original_start_pos: rustc_span::BytePos,
@@ -528,7 +530,7 @@ impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for Span {
528530
};
529531

530532
// Index of the file in the corresponding crate's list of encoded files.
531-
let metadata_index = usize::decode(decoder);
533+
let metadata_index = u32::decode(decoder);
532534

533535
// There are two possibilities here:
534536
// 1. This is a 'local span', which is located inside a `SourceFile`
@@ -556,10 +558,10 @@ impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for Span {
556558
// to be based on the *foreign* crate (e.g. crate C), not the crate
557559
// we are writing metadata for (e.g. crate B). This allows us to
558560
// treat the 'local' and 'foreign' cases almost identically during deserialization:
559-
// we can call `imported_source_files` for the proper crate, and binary search
561+
// we can call `imported_source_file` for the proper crate, and binary search
560562
// through the returned slice using our span.
561-
let imported_source_files = if tag == TAG_VALID_SPAN_LOCAL {
562-
decoder.cdata().imported_source_files(sess)
563+
let source_file = if tag == TAG_VALID_SPAN_LOCAL {
564+
decoder.cdata().imported_source_file(metadata_index, sess)
563565
} else {
564566
// When we encode a proc-macro crate, all `Span`s should be encoded
565567
// with `TAG_VALID_SPAN_LOCAL`
@@ -587,13 +589,9 @@ impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for Span {
587589
decoder.last_source_file_index = 0;
588590

589591
let foreign_data = decoder.cdata().cstore.get_crate_data(cnum);
590-
foreign_data.imported_source_files(sess)
592+
foreign_data.imported_source_file(metadata_index, sess)
591593
};
592594

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];
596-
597595
// Make sure our binary search above is correct.
598596
debug_assert!(
599597
lo >= source_file.original_start_pos && lo <= source_file.original_end_pos,
@@ -1438,7 +1436,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
14381436
///
14391437
/// Proc macro crates don't currently export spans, so this function does not have
14401438
/// to work for them.
1441-
fn imported_source_files(self, sess: &Session) -> &'a [ImportedSourceFile] {
1439+
fn imported_source_file(self, source_file_index: u32, sess: &Session) -> ImportedSourceFile {
14421440
fn filter<'a>(sess: &Session, path: Option<&'a Path>) -> Option<&'a Path> {
14431441
path.filter(|_| {
14441442
// Only spend time on further checks if we have what to translate *to*.
@@ -1526,94 +1524,97 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
15261524
}
15271525
};
15281526

1529-
self.cdata.source_map_import_info.get_or_init(|| {
1530-
let external_source_map = self.root.source_map.decode(self);
1531-
1532-
external_source_map
1533-
.enumerate()
1534-
.map(|(source_file_index, source_file_to_import)| {
1535-
// We can't reuse an existing SourceFile, so allocate a new one
1536-
// containing the information we need.
1537-
let rustc_span::SourceFile {
1538-
mut name,
1539-
src_hash,
1540-
start_pos,
1541-
end_pos,
1542-
lines,
1543-
multibyte_chars,
1544-
non_narrow_chars,
1545-
normalized_pos,
1546-
name_hash,
1547-
..
1548-
} = source_file_to_import;
1549-
1550-
// If this file is under $sysroot/lib/rustlib/src/ but has not been remapped
1551-
// during rust bootstrapping by `remap-debuginfo = true`, and the user
1552-
// wish to simulate that behaviour by -Z simulate-remapped-rust-src-base,
1553-
// then we change `name` to a similar state as if the rust was bootstrapped
1554-
// with `remap-debuginfo = true`.
1555-
// This is useful for testing so that tests about the effects of
1556-
// `try_to_translate_virtual_to_real` don't have to worry about how the
1557-
// compiler is bootstrapped.
1558-
if let Some(virtual_dir) =
1559-
&sess.opts.unstable_opts.simulate_remapped_rust_src_base
1560-
{
1561-
if let Some(real_dir) = &sess.opts.real_rust_source_base_dir {
1562-
if let rustc_span::FileName::Real(ref mut old_name) = name {
1563-
if let rustc_span::RealFileName::LocalPath(local) = old_name {
1564-
if let Ok(rest) = local.strip_prefix(real_dir) {
1565-
*old_name = rustc_span::RealFileName::Remapped {
1566-
local_path: None,
1567-
virtual_name: virtual_dir.join(rest),
1568-
};
1569-
}
1527+
let mut import_info = self.cdata.source_map_import_info.borrow_mut();
1528+
for _ in import_info.len()..=(source_file_index as usize) {
1529+
import_info.push(None);
1530+
}
1531+
import_info[source_file_index as usize]
1532+
.get_or_insert_with(|| {
1533+
let source_file_to_import = self
1534+
.root
1535+
.source_map
1536+
.get(self, source_file_index)
1537+
.expect("missing source file")
1538+
.decode(self);
1539+
1540+
// We can't reuse an existing SourceFile, so allocate a new one
1541+
// containing the information we need.
1542+
let rustc_span::SourceFile {
1543+
mut name,
1544+
src_hash,
1545+
start_pos,
1546+
end_pos,
1547+
lines,
1548+
multibyte_chars,
1549+
non_narrow_chars,
1550+
normalized_pos,
1551+
name_hash,
1552+
..
1553+
} = source_file_to_import;
1554+
1555+
// If this file is under $sysroot/lib/rustlib/src/ but has not been remapped
1556+
// during rust bootstrapping by `remap-debuginfo = true`, and the user
1557+
// wish to simulate that behaviour by -Z simulate-remapped-rust-src-base,
1558+
// then we change `name` to a similar state as if the rust was bootstrapped
1559+
// with `remap-debuginfo = true`.
1560+
// This is useful for testing so that tests about the effects of
1561+
// `try_to_translate_virtual_to_real` don't have to worry about how the
1562+
// compiler is bootstrapped.
1563+
if let Some(virtual_dir) = &sess.opts.unstable_opts.simulate_remapped_rust_src_base
1564+
{
1565+
if let Some(real_dir) = &sess.opts.real_rust_source_base_dir {
1566+
if let rustc_span::FileName::Real(ref mut old_name) = name {
1567+
if let rustc_span::RealFileName::LocalPath(local) = old_name {
1568+
if let Ok(rest) = local.strip_prefix(real_dir) {
1569+
*old_name = rustc_span::RealFileName::Remapped {
1570+
local_path: None,
1571+
virtual_name: virtual_dir.join(rest),
1572+
};
15701573
}
15711574
}
15721575
}
15731576
}
1577+
}
15741578

1575-
// If this file's path has been remapped to `/rustc/$hash`,
1576-
// we might be able to reverse that (also see comments above,
1577-
// on `try_to_translate_virtual_to_real`).
1578-
try_to_translate_virtual_to_real(&mut name);
1579-
1580-
let source_length = (end_pos - start_pos).to_usize();
1581-
1582-
let local_version = sess.source_map().new_imported_source_file(
1583-
name,
1584-
src_hash,
1585-
name_hash,
1586-
source_length,
1587-
self.cnum,
1588-
lines,
1589-
multibyte_chars,
1590-
non_narrow_chars,
1591-
normalized_pos,
1592-
start_pos,
1593-
end_pos,
1594-
source_file_index
1595-
.try_into()
1596-
.expect("cannot import more than U32_MAX files"),
1597-
);
1598-
debug!(
1599-
"CrateMetaData::imported_source_files alloc \
1579+
// If this file's path has been remapped to `/rustc/$hash`,
1580+
// we might be able to reverse that (also see comments above,
1581+
// on `try_to_translate_virtual_to_real`).
1582+
try_to_translate_virtual_to_real(&mut name);
1583+
1584+
let source_length = (end_pos - start_pos).to_usize();
1585+
1586+
let local_version = sess.source_map().new_imported_source_file(
1587+
name,
1588+
src_hash,
1589+
name_hash,
1590+
source_length,
1591+
self.cnum,
1592+
lines,
1593+
multibyte_chars,
1594+
non_narrow_chars,
1595+
normalized_pos,
1596+
start_pos,
1597+
end_pos,
1598+
source_file_index,
1599+
);
1600+
debug!(
1601+
"CrateMetaData::imported_source_files alloc \
16001602
source_file {:?} original (start_pos {:?} end_pos {:?}) \
16011603
translated (start_pos {:?} end_pos {:?})",
1602-
local_version.name,
1603-
start_pos,
1604-
end_pos,
1605-
local_version.start_pos,
1606-
local_version.end_pos
1607-
);
1604+
local_version.name,
1605+
start_pos,
1606+
end_pos,
1607+
local_version.start_pos,
1608+
local_version.end_pos
1609+
);
16081610

1609-
ImportedSourceFile {
1610-
original_start_pos: start_pos,
1611-
original_end_pos: end_pos,
1612-
translated_source_file: local_version,
1613-
}
1614-
})
1615-
.collect()
1616-
})
1611+
ImportedSourceFile {
1612+
original_start_pos: start_pos,
1613+
original_end_pos: end_pos,
1614+
translated_source_file: local_version,
1615+
}
1616+
})
1617+
.clone()
16171618
}
16181619

16191620
fn get_generator_diagnostic_data(
@@ -1676,7 +1677,7 @@ impl CrateMetadata {
16761677
trait_impls,
16771678
incoherent_impls: Default::default(),
16781679
raw_proc_macros,
1679-
source_map_import_info: OnceCell::new(),
1680+
source_map_import_info: RefCell::new(Vec::new()),
16801681
def_path_hash_map,
16811682
expn_hash_map: Default::default(),
16821683
alloc_decoding_state,

compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -675,6 +675,9 @@ impl CrateStore for CStore {
675675
}
676676

677677
fn import_source_files(&self, sess: &Session, cnum: CrateNum) {
678-
self.get_crate_data(cnum).imported_source_files(sess);
678+
let cdata = self.get_crate_data(cnum);
679+
for file_index in 0..cdata.root.source_map.size() {
680+
cdata.imported_source_file(file_index as u32, sess);
681+
}
679682
}
680683
}

0 commit comments

Comments
 (0)