Avoid creating anonymous nodes with zero or one dependency.

This commit is contained in:
Camille GILLOT 2021-05-15 17:23:16 +02:00
parent 7f9ab0300c
commit 3a6d5c2beb
2 changed files with 49 additions and 26 deletions

View File

@ -229,6 +229,7 @@ pub fn build_dep_graph(
}
Some(DepGraph::new(
&sess.prof,
prev_graph,
prev_work_products,
encoder,

View File

@ -44,6 +44,7 @@ rustc_index::newtype_index! {
impl DepNodeIndex {
pub const INVALID: DepNodeIndex = DepNodeIndex::MAX;
pub const DUMMY_ANON: DepNodeIndex = DepNodeIndex::from_u32(0);
}
impl std::convert::From<DepNodeIndex> for QueryInvocationId {
@ -108,6 +109,7 @@ where
impl<K: DepKind> DepGraph<K> {
pub fn new(
profiler: &SelfProfilerRef,
prev_graph: SerializedDepGraph<K>,
prev_work_products: FxHashMap<WorkProductId, WorkProduct>,
encoder: FileEncoder,
@ -116,16 +118,23 @@ impl<K: DepKind> DepGraph<K> {
) -> DepGraph<K> {
let prev_graph_node_count = prev_graph.node_count();
let current =
CurrentDepGraph::new(prev_graph_node_count, encoder, record_graph, record_stats);
// Instantiate an *always green* node for dependency-less anonymous queries.
let _green_node_index = current.intern_new_node(
profiler,
DepNode { kind: DepKind::NULL, hash: current.anon_id_seed.into() },
smallvec![],
Fingerprint::ZERO,
);
debug_assert_eq!(_green_node_index, DepNodeIndex::DUMMY_ANON);
DepGraph {
data: Some(Lrc::new(DepGraphData {
previous_work_products: prev_work_products,
dep_node_debug: Default::default(),
current: CurrentDepGraph::new(
prev_graph_node_count,
encoder,
record_graph,
record_stats,
),
current,
emitting_diagnostics: Default::default(),
emitting_diagnostics_cond_var: Condvar::new(),
previous: prev_graph,
@ -287,30 +296,43 @@ impl<K: DepKind> DepGraph<K> {
let task_deps = Lock::new(TaskDeps::default());
let result = K::with_deps(Some(&task_deps), op);
let task_deps = task_deps.into_inner();
let task_deps = task_deps.reads;
// The dep node indices are hashed here instead of hashing the dep nodes of the
// dependencies. These indices may refer to different nodes per session, but this isn't
// a problem here because we that ensure the final dep node hash is per session only by
// combining it with the per session random number `anon_id_seed`. This hash only need
// to map the dependencies to a single value on a per session basis.
let mut hasher = StableHasher::new();
task_deps.reads.hash(&mut hasher);
let dep_node_index = match task_deps.len() {
0 => {
// Dependency-less anonymous nodes can safely be replaced by a dummy node.
DepNodeIndex::DUMMY_ANON
}
1 => {
// When there is only one dependency, don't bother creating a node.
task_deps[0]
}
_ => {
// The dep node indices are hashed here instead of hashing the dep nodes of the
// dependencies. These indices may refer to different nodes per session, but this isn't
// a problem here because we that ensure the final dep node hash is per session only by
// combining it with the per session random number `anon_id_seed`. This hash only need
// to map the dependencies to a single value on a per session basis.
let mut hasher = StableHasher::new();
task_deps.hash(&mut hasher);
let target_dep_node = DepNode {
kind: dep_kind,
// Fingerprint::combine() is faster than sending Fingerprint
// through the StableHasher (at least as long as StableHasher
// is so slow).
hash: data.current.anon_id_seed.combine(hasher.finish()).into(),
let target_dep_node = DepNode {
kind: dep_kind,
// Fingerprint::combine() is faster than sending Fingerprint
// through the StableHasher (at least as long as StableHasher
// is so slow).
hash: data.current.anon_id_seed.combine(hasher.finish()).into(),
};
data.current.intern_new_node(
cx.profiler(),
target_dep_node,
task_deps,
Fingerprint::ZERO,
)
}
};
let dep_node_index = data.current.intern_new_node(
cx.profiler(),
target_dep_node,
task_deps.reads,
Fingerprint::ZERO,
);
(result, dep_node_index)
} else {
(op(), self.next_virtual_depnode_index())