Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rustc_metadata: Give decoder access to whole crate store #69677

Merged
merged 2 commits into from
Mar 10, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 20 additions & 4 deletions src/librustc_metadata/creader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,21 @@ impl<'a> LoadError<'a> {
}
}

/// A reference to `CrateMetadata` that can also give access to whole crate store when necessary.
#[derive(Clone, Copy)]
crate struct CrateMetadataRef<'a> {
pub cdata: &'a CrateMetadata,
pub cstore: &'a CStore,
}

impl std::ops::Deref for CrateMetadataRef<'_> {
type Target = CrateMetadata;

fn deref(&self) -> &Self::Target {
self.cdata
}
}

fn dump_crates(cstore: &CStore) {
info!("resolved crates:");
cstore.iter_crate_data(|cnum, data| {
Expand All @@ -100,10 +115,11 @@ impl CStore {
CrateNum::new(self.metas.len() - 1)
}

crate fn get_crate_data(&self, cnum: CrateNum) -> &CrateMetadata {
self.metas[cnum]
crate fn get_crate_data(&self, cnum: CrateNum) -> CrateMetadataRef<'_> {
let cdata = self.metas[cnum]
.as_ref()
.unwrap_or_else(|| panic!("Failed to get crate data for {:?}", cnum))
.unwrap_or_else(|| panic!("Failed to get crate data for {:?}", cnum));
CrateMetadataRef { cdata, cstore: self }
}

fn set_crate_data(&mut self, cnum: CrateNum, data: CrateMetadata) {
Expand Down Expand Up @@ -217,7 +233,7 @@ impl<'a> CrateLoader<'a> {
// We're also sure to compare *paths*, not actual byte slices. The
// `source` stores paths which are normalized which may be different
// from the strings on the command line.
let source = self.cstore.get_crate_data(cnum).source();
let source = self.cstore.get_crate_data(cnum).cdata.source();
if let Some(entry) = self.sess.opts.externs.get(&name.as_str()) {
// Only use `--extern crate_name=path` here, not `--extern crate_name`.
if let Some(mut files) = entry.files() {
Expand Down
207 changes: 105 additions & 102 deletions src/librustc_metadata/rmeta/decoder.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// Decoding metadata from a single crate's metadata

use crate::creader::CrateMetadataRef;
use crate::rmeta::table::{FixedSizeEncoding, Table};
use crate::rmeta::*;

Expand Down Expand Up @@ -125,7 +126,7 @@ struct ImportedSourceFile {

pub(super) struct DecodeContext<'a, 'tcx> {
opaque: opaque::Decoder<'a>,
cdata: Option<&'a CrateMetadata>,
cdata: Option<CrateMetadataRef<'a>>,
sess: Option<&'tcx Session>,
tcx: Option<TyCtxt<'tcx>>,

Expand All @@ -141,7 +142,7 @@ pub(super) struct DecodeContext<'a, 'tcx> {
/// Abstract over the various ways one can create metadata decoders.
pub(super) trait Metadata<'a, 'tcx>: Copy {
fn raw_bytes(self) -> &'a [u8];
fn cdata(self) -> Option<&'a CrateMetadata> {
fn cdata(self) -> Option<CrateMetadataRef<'a>> {
None
}
fn sess(self) -> Option<&'tcx Session> {
Expand All @@ -162,7 +163,7 @@ pub(super) trait Metadata<'a, 'tcx>: Copy {
lazy_state: LazyState::NoNode,
alloc_decoding_session: self
.cdata()
.map(|cdata| cdata.alloc_decoding_state.new_decoding_session()),
.map(|cdata| cdata.cdata.alloc_decoding_state.new_decoding_session()),
}
}
}
Expand All @@ -185,33 +186,33 @@ impl<'a, 'tcx> Metadata<'a, 'tcx> for (&'a MetadataBlob, &'tcx Session) {
}
}

impl<'a, 'tcx> Metadata<'a, 'tcx> for &'a CrateMetadata {
impl<'a, 'tcx> Metadata<'a, 'tcx> for &'a CrateMetadataRef<'a> {
fn raw_bytes(self) -> &'a [u8] {
self.blob.raw_bytes()
}
fn cdata(self) -> Option<&'a CrateMetadata> {
Some(self)
fn cdata(self) -> Option<CrateMetadataRef<'a>> {
Some(*self)
}
}

impl<'a, 'tcx> Metadata<'a, 'tcx> for (&'a CrateMetadata, &'tcx Session) {
impl<'a, 'tcx> Metadata<'a, 'tcx> for (&'a CrateMetadataRef<'a>, &'tcx Session) {
fn raw_bytes(self) -> &'a [u8] {
self.0.raw_bytes()
}
fn cdata(self) -> Option<&'a CrateMetadata> {
Some(self.0)
fn cdata(self) -> Option<CrateMetadataRef<'a>> {
Some(*self.0)
}
fn sess(self) -> Option<&'tcx Session> {
Some(&self.1)
}
}

impl<'a, 'tcx> Metadata<'a, 'tcx> for (&'a CrateMetadata, TyCtxt<'tcx>) {
impl<'a, 'tcx> Metadata<'a, 'tcx> for (&'a CrateMetadataRef<'a>, TyCtxt<'tcx>) {
fn raw_bytes(self) -> &'a [u8] {
self.0.raw_bytes()
}
fn cdata(self) -> Option<&'a CrateMetadata> {
Some(self.0)
fn cdata(self) -> Option<CrateMetadataRef<'a>> {
Some(*self.0)
}
fn tcx(self) -> Option<TyCtxt<'tcx>> {
Some(self.1)
Expand Down Expand Up @@ -242,7 +243,7 @@ impl<'a, 'tcx> DecodeContext<'a, 'tcx> {
self.tcx.expect("missing TyCtxt in DecodeContext")
}

fn cdata(&self) -> &'a CrateMetadata {
fn cdata(&self) -> CrateMetadataRef<'a> {
self.cdata.expect("missing CrateMetadata in DecodeContext")
}

Expand Down Expand Up @@ -558,50 +559,7 @@ impl CrateRoot<'_> {
}
}

impl<'a, 'tcx> CrateMetadata {
crate fn new(
sess: &Session,
blob: MetadataBlob,
root: CrateRoot<'static>,
raw_proc_macros: Option<&'static [ProcMacro]>,
cnum: CrateNum,
cnum_map: CrateNumMap,
dep_kind: DepKind,
source: CrateSource,
private_dep: bool,
host_hash: Option<Svh>,
) -> CrateMetadata {
let def_path_table = record_time(&sess.perf_stats.decode_def_path_tables_time, || {
root.def_path_table.decode((&blob, sess))
});
let trait_impls = root
.impls
.decode((&blob, sess))
.map(|trait_impls| (trait_impls.trait_id, trait_impls.impls))
.collect();
let alloc_decoding_state =
AllocDecodingState::new(root.interpret_alloc_index.decode(&blob).collect());
let dependencies = Lock::new(cnum_map.iter().cloned().collect());
CrateMetadata {
blob,
root,
def_path_table,
trait_impls,
raw_proc_macros,
source_map_import_info: Once::new(),
alloc_decoding_state,
dep_node_index: AtomicCell::new(DepNodeIndex::INVALID),
cnum,
cnum_map,
dependencies,
dep_kind: Lock::new(dep_kind),
source,
private_dep,
host_hash,
extern_crate: Lock::new(None),
}
}

impl<'a, 'tcx> CrateMetadataRef<'a> {
fn is_proc_macro(&self, id: DefIndex) -> bool {
self.root.proc_macro_data.and_then(|data| data.decode(self).find(|x| *x == id)).is_some()
}
Expand All @@ -622,10 +580,6 @@ impl<'a, 'tcx> CrateMetadata {
})
}

fn local_def_id(&self, index: DefIndex) -> DefId {
DefId { krate: self.cnum, index }
}

fn raw_proc_macro(&self, id: DefIndex) -> &ProcMacro {
// DefIndex's in root.proc_macro_data have a one-to-one correspondence
// with items in 'raw_proc_macros'.
Expand Down Expand Up @@ -1191,18 +1145,6 @@ impl<'a, 'tcx> CrateMetadata {
.collect()
}

// Translate a DefId from the current compilation environment to a DefId
// for an external crate.
fn reverse_translate_def_id(&self, did: DefId) -> Option<DefId> {
for (local, &global) in self.cnum_map.iter_enumerated() {
if global == did.krate {
return Some(DefId { krate: local, index: did.index });
}
}

None
}

fn get_inherent_implementations_for_type(
&self,
tcx: TyCtxt<'tcx>,
Expand Down Expand Up @@ -1409,11 +1351,6 @@ impl<'a, 'tcx> CrateMetadata {
DefPath::make(self.cnum, id, |parent| self.def_key(parent))
}

#[inline]
fn def_path_hash(&self, index: DefIndex) -> DefPathHash {
self.def_path_table.def_path_hash(index)
}

/// Imports the source_map from an external crate into the source_map of the crate
/// currently being compiled (the "local crate").
///
Expand All @@ -1440,10 +1377,10 @@ impl<'a, 'tcx> CrateMetadata {
/// Proc macro crates don't currently export spans, so this function does not have
/// to work for them.
fn imported_source_files(
&'a self,
&self,
local_source_map: &source_map::SourceMap,
) -> &[ImportedSourceFile] {
self.source_map_import_info.init_locking(|| {
) -> &'a [ImportedSourceFile] {
self.cdata.source_map_import_info.init_locking(|| {
let external_source_map = self.root.source_map.decode(self);

external_source_map
Expand Down Expand Up @@ -1516,29 +1453,50 @@ impl<'a, 'tcx> CrateMetadata {
.collect()
})
}
}

/// Get the `DepNodeIndex` corresponding this crate. The result of this
/// method is cached in the `dep_node_index` field.
fn get_crate_dep_node_index(&self, tcx: TyCtxt<'tcx>) -> DepNodeIndex {
let mut dep_node_index = self.dep_node_index.load();

if unlikely!(dep_node_index == DepNodeIndex::INVALID) {
// We have not cached the DepNodeIndex for this upstream crate yet,
// so use the dep-graph to find it out and cache it.
// Note that multiple threads can enter this block concurrently.
// That is fine because the DepNodeIndex remains constant
// throughout the whole compilation session, and multiple stores
// would always write the same value.

let def_path_hash = self.def_path_hash(CRATE_DEF_INDEX);
let dep_node = def_path_hash.to_dep_node(dep_graph::DepKind::CrateMetadata);

dep_node_index = tcx.dep_graph.dep_node_index_of(&dep_node);
assert!(dep_node_index != DepNodeIndex::INVALID);
self.dep_node_index.store(dep_node_index);
impl CrateMetadata {
crate fn new(
sess: &Session,
blob: MetadataBlob,
root: CrateRoot<'static>,
raw_proc_macros: Option<&'static [ProcMacro]>,
cnum: CrateNum,
cnum_map: CrateNumMap,
dep_kind: DepKind,
source: CrateSource,
private_dep: bool,
host_hash: Option<Svh>,
) -> CrateMetadata {
let def_path_table = record_time(&sess.perf_stats.decode_def_path_tables_time, || {
root.def_path_table.decode((&blob, sess))
});
let trait_impls = root
.impls
.decode((&blob, sess))
.map(|trait_impls| (trait_impls.trait_id, trait_impls.impls))
.collect();
let alloc_decoding_state =
AllocDecodingState::new(root.interpret_alloc_index.decode(&blob).collect());
let dependencies = Lock::new(cnum_map.iter().cloned().collect());
CrateMetadata {
blob,
root,
def_path_table,
trait_impls,
raw_proc_macros,
source_map_import_info: Once::new(),
alloc_decoding_state,
dep_node_index: AtomicCell::new(DepNodeIndex::INVALID),
cnum,
cnum_map,
dependencies,
dep_kind: Lock::new(dep_kind),
source,
private_dep,
host_hash,
extern_crate: Lock::new(None),
}

dep_node_index
}

crate fn dependencies(&self) -> LockGuard<'_, Vec<CrateNum>> {
Expand Down Expand Up @@ -1613,6 +1571,51 @@ impl<'a, 'tcx> CrateMetadata {
crate fn hash(&self) -> Svh {
self.root.hash
}

fn local_def_id(&self, index: DefIndex) -> DefId {
DefId { krate: self.cnum, index }
}

// Translate a DefId from the current compilation environment to a DefId
// for an external crate.
fn reverse_translate_def_id(&self, did: DefId) -> Option<DefId> {
for (local, &global) in self.cnum_map.iter_enumerated() {
if global == did.krate {
return Some(DefId { krate: local, index: did.index });
}
}

None
}

#[inline]
fn def_path_hash(&self, index: DefIndex) -> DefPathHash {
self.def_path_table.def_path_hash(index)
}

/// Get the `DepNodeIndex` corresponding this crate. The result of this
/// method is cached in the `dep_node_index` field.
fn get_crate_dep_node_index(&self, tcx: TyCtxt<'tcx>) -> DepNodeIndex {
let mut dep_node_index = self.dep_node_index.load();

if unlikely!(dep_node_index == DepNodeIndex::INVALID) {
// We have not cached the DepNodeIndex for this upstream crate yet,
// so use the dep-graph to find it out and cache it.
// Note that multiple threads can enter this block concurrently.
// That is fine because the DepNodeIndex remains constant
// throughout the whole compilation session, and multiple stores
// would always write the same value.

let def_path_hash = self.def_path_hash(CRATE_DEF_INDEX);
let dep_node = def_path_hash.to_dep_node(dep_graph::DepKind::CrateMetadata);

dep_node_index = tcx.dep_graph.dep_node_index_of(&dep_node);
assert!(dep_node_index != DepNodeIndex::INVALID);
self.dep_node_index.store(dep_node_index);
}

dep_node_index
}
}

// Cannot be implemented on 'ProcMacro', as libproc_macro
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_metadata/rmeta/decoder/cstore_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -517,7 +517,7 @@ impl CrateStore for CStore {
}

fn def_path_table(&self, cnum: CrateNum) -> &DefPathTable {
&self.get_crate_data(cnum).def_path_table
&self.get_crate_data(cnum).cdata.def_path_table
}

fn crates_untracked(&self) -> Vec<CrateNum> {
Expand Down