From c1df945a610bb6eddfe0dc5ff033722fa611ef09 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Tue, 3 Mar 2020 01:06:07 +0300 Subject: [PATCH 1/2] rustc_metadata: Give decoder access to whole crate store --- src/librustc_metadata/creader.rs | 24 ++++++++++-- src/librustc_metadata/rmeta/decoder.rs | 39 +++++++++++-------- .../rmeta/decoder/cstore_impl.rs | 2 +- 3 files changed, 43 insertions(+), 22 deletions(-) diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index 5254471051ffd..18b4c9ad5044c 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -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| { @@ -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) { @@ -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() { diff --git a/src/librustc_metadata/rmeta/decoder.rs b/src/librustc_metadata/rmeta/decoder.rs index a72ee0cbe4729..5dec7bfe60cbd 100644 --- a/src/librustc_metadata/rmeta/decoder.rs +++ b/src/librustc_metadata/rmeta/decoder.rs @@ -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::*; @@ -125,7 +126,7 @@ struct ImportedSourceFile { pub(super) struct DecodeContext<'a, 'tcx> { opaque: opaque::Decoder<'a>, - cdata: Option<&'a CrateMetadata>, + cdata: Option>, sess: Option<&'tcx Session>, tcx: Option>, @@ -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> { None } fn sess(self) -> Option<&'tcx Session> { @@ -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()), } } } @@ -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> { + 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> { + 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> { + Some(*self.0) } fn tcx(self) -> Option> { Some(self.1) @@ -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") } @@ -558,7 +559,7 @@ impl CrateRoot<'_> { } } -impl<'a, 'tcx> CrateMetadata { +impl CrateMetadata { crate fn new( sess: &Session, blob: MetadataBlob, @@ -601,7 +602,9 @@ impl<'a, 'tcx> CrateMetadata { 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() } @@ -1440,10 +1443,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 @@ -1540,7 +1543,9 @@ impl<'a, 'tcx> CrateMetadata { dep_node_index } +} +impl CrateMetadata { crate fn dependencies(&self) -> LockGuard<'_, Vec> { self.dependencies.borrow() } diff --git a/src/librustc_metadata/rmeta/decoder/cstore_impl.rs b/src/librustc_metadata/rmeta/decoder/cstore_impl.rs index be229350f3bcc..c890640d432a7 100644 --- a/src/librustc_metadata/rmeta/decoder/cstore_impl.rs +++ b/src/librustc_metadata/rmeta/decoder/cstore_impl.rs @@ -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 { From 41374d748b3c8bc39a78adf703d7d5560a4a8ab7 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Tue, 3 Mar 2020 22:56:27 +0300 Subject: [PATCH 2/2] rustc_metadata: Move some code from `impl CrateMetadataRef` to `impl CrateMetadata` --- src/librustc_metadata/rmeta/decoder.rs | 176 ++++++++++++------------- 1 file changed, 87 insertions(+), 89 deletions(-) diff --git a/src/librustc_metadata/rmeta/decoder.rs b/src/librustc_metadata/rmeta/decoder.rs index 5dec7bfe60cbd..e60ae5b6c25ee 100644 --- a/src/librustc_metadata/rmeta/decoder.rs +++ b/src/librustc_metadata/rmeta/decoder.rs @@ -559,51 +559,6 @@ impl CrateRoot<'_> { } } -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, - ) -> 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() @@ -625,10 +580,6 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { }) } - 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'. @@ -1194,18 +1145,6 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { .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 { - 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>, @@ -1412,11 +1351,6 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { 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"). /// @@ -1519,33 +1453,52 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { .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, + ) -> 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 } -} -impl CrateMetadata { crate fn dependencies(&self) -> LockGuard<'_, Vec> { self.dependencies.borrow() } @@ -1618,6 +1571,51 @@ impl 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 { + 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