提交 9dbd7be7 编写于 作者: M Michael Woerister

Cache the DepNodeIndex of upstream crates in order to avoid multiple locks and...

Cache the DepNodeIndex of upstream crates in order to avoid multiple locks and table lookups on each access of crate metadata.
上级 275cf4bc
......@@ -30,7 +30,7 @@ pub struct DepNodeIndex { .. }
}
impl DepNodeIndex {
const INVALID: DepNodeIndex = DepNodeIndex::MAX;
pub const INVALID: DepNodeIndex = DepNodeIndex::MAX;
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
......
......@@ -3,10 +3,11 @@
use crate::cstore::{self, CStore, CrateSource, MetadataBlob};
use crate::locator::{self, CratePaths};
use crate::schema::{CrateRoot, CrateDep};
use rustc_data_structures::sync::{Lrc, RwLock, Lock};
use rustc_data_structures::sync::{Lrc, RwLock, Lock, AtomicCell};
use rustc::hir::def_id::CrateNum;
use rustc_data_structures::svh::Svh;
use rustc::dep_graph::DepNodeIndex;
use rustc::middle::cstore::DepKind;
use rustc::mir::interpret::AllocDecodingState;
use rustc::session::{Session, CrateDisambiguator};
......@@ -271,7 +272,8 @@ fn register_crate(
},
private_dep,
span,
raw_proc_macros
raw_proc_macros,
dep_node_index: AtomicCell::new(DepNodeIndex::INVALID),
};
let cmeta = Lrc::new(cmeta);
......
......@@ -2,6 +2,7 @@
// crates and libraries
use crate::schema;
use rustc::dep_graph::DepNodeIndex;
use rustc::hir::def_id::{CrateNum, DefIndex};
use rustc::hir::map::definitions::DefPathTable;
use rustc::middle::cstore::{DepKind, ExternCrate, MetadataLoader};
......@@ -9,7 +10,7 @@
use rustc_index::vec::IndexVec;
use rustc::util::nodemap::{FxHashMap, NodeMap};
use rustc_data_structures::sync::{Lrc, RwLock, Lock};
use rustc_data_structures::sync::{Lrc, RwLock, Lock, AtomicCell};
use syntax::ast;
use syntax::ext::base::SyntaxExtension;
use syntax_pos;
......@@ -83,6 +84,13 @@ pub struct CrateMetadata {
pub span: Span,
pub raw_proc_macros: Option<&'static [ProcMacro]>,
/// The `DepNodeIndex` of the `DepNode` representing this upstream crate.
/// It is initialized on the first access in `get_crate_dep_node_index()`.
/// Do not access the value directly, as it might not have been initialized
/// yet.
/// The field must always be initialized to `DepNodeIndex::INVALID`.
pub(super) dep_node_index: AtomicCell<DepNodeIndex>,
}
pub struct CStore {
......
......@@ -51,19 +51,15 @@ pub fn provide_extern<$lt>(providers: &mut Providers<$lt>) {
let ($def_id, $other) = def_id_arg.into_args();
assert!(!$def_id.is_local());
let def_path_hash = $tcx.def_path_hash(DefId {
krate: $def_id.krate,
index: CRATE_DEF_INDEX
});
let dep_node = def_path_hash
.to_dep_node(rustc::dep_graph::DepKind::CrateMetadata);
// The DepNodeIndex of the DepNode::CrateMetadata should be
// cached somewhere, so that we can use read_index().
$tcx.dep_graph.read(dep_node);
let $cdata = $tcx.crate_data_as_rc_any($def_id.krate);
let $cdata = $cdata.downcast_ref::<cstore::CrateMetadata>()
.expect("CrateStore created data is not a CrateMetadata");
if $tcx.dep_graph.is_fully_enabled() {
let crate_dep_node_index = $cdata.get_crate_dep_node_index($tcx);
$tcx.dep_graph.read_index(crate_dep_node_index);
}
$compute
})*
......
......@@ -13,6 +13,7 @@
use rustc::hir::def_id::{CrateNum, DefId, DefIndex, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE};
use rustc_data_structures::fingerprint::Fingerprint;
use rustc_data_structures::fx::FxHashMap;
use rustc::dep_graph::{DepNodeIndex, DepKind};
use rustc::middle::lang_items;
use rustc::mir::{self, interpret};
use rustc::mir::interpret::AllocDecodingSession;
......@@ -1365,6 +1366,30 @@ pub fn imported_source_files(&'a self,
// This shouldn't borrow twice, but there is no way to downgrade RefMut to Ref.
self.source_map_import_info.borrow()
}
/// Get the `DepNodeIndex` corresponding this crate. The result of this
/// method is cached in the `dep_node_index` field.
pub(super) fn get_crate_dep_node_index(&self, tcx: TyCtxt<'tcx>) -> DepNodeIndex {
let mut dep_node_index = self.dep_node_index.load();
if 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(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
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册