Skip to content

Commit 537ae41

Browse files
committed
Only use the new node hashmap for anonymous nodes.
1 parent 6fecd78 commit 537ae41

File tree

3 files changed

+35
-90
lines changed
  • compiler
    • rustc_codegen_cranelift/src/driver
    • rustc_codegen_ssa/src
    • rustc_query_system/src/dep_graph

3 files changed

+35
-90
lines changed

compiler/rustc_codegen_cranelift/src/driver/aot.rs

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -522,11 +522,5 @@ fn determine_cgu_reuse<'tcx>(tcx: TyCtxt<'tcx>, cgu: &CodegenUnit<'tcx>) -> CguR
522522
// know that later). If we are not doing LTO, there is only one optimized
523523
// version of each module, so we re-use that.
524524
let dep_node = cgu.codegen_dep_node(tcx);
525-
assert!(
526-
!tcx.dep_graph.dep_node_exists(&dep_node),
527-
"CompileCodegenUnit dep-node for CGU `{}` already exists before marking.",
528-
cgu.name()
529-
);
530-
531525
if tcx.try_mark_green(&dep_node) { CguReuse::PostLto } else { CguReuse::No }
532526
}

compiler/rustc_codegen_ssa/src/base.rs

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1009,12 +1009,6 @@ fn determine_cgu_reuse<'tcx>(tcx: TyCtxt<'tcx>, cgu: &CodegenUnit<'tcx>) -> CguR
10091009
// know that later). If we are not doing LTO, there is only one optimized
10101010
// version of each module, so we re-use that.
10111011
let dep_node = cgu.codegen_dep_node(tcx);
1012-
assert!(
1013-
!tcx.dep_graph.dep_node_exists(&dep_node),
1014-
"CompileCodegenUnit dep-node for CGU `{}` already exists before marking.",
1015-
cgu.name()
1016-
);
1017-
10181012
if tcx.try_mark_green(&dep_node) {
10191013
// We can re-use either the pre- or the post-thinlto state. If no LTO is
10201014
// being performed then we can use post-LTO artifacts, otherwise we must

compiler/rustc_query_system/src/dep_graph/graph.rs

Lines changed: 35 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -342,18 +342,6 @@ impl<K: DepKind> DepGraphData<K> {
342342
task: fn(Ctxt, A) -> R,
343343
hash_result: Option<fn(&mut StableHashingContext<'_>, &R) -> Fingerprint>,
344344
) -> (R, DepNodeIndex) {
345-
// If the following assertion triggers, it can have two reasons:
346-
// 1. Something is wrong with DepNode creation, either here or
347-
// in `DepGraph::try_mark_green()`.
348-
// 2. Two distinct query keys get mapped to the same `DepNode`
349-
// (see for example #48923).
350-
assert!(
351-
!self.dep_node_exists(&key),
352-
"forcing query with already existing `DepNode`\n\
353-
- query-key: {arg:?}\n\
354-
- dep-node: {key:?}"
355-
);
356-
357345
let with_deps = |task_deps| K::with_deps(task_deps, || task(cx, arg));
358346
let (result, edges) = if cx.dep_context().is_eval_always(key.kind) {
359347
(with_deps(TaskDepsRef::EvalAlways), smallvec![])
@@ -448,12 +436,32 @@ impl<K: DepKind> DepGraphData<K> {
448436
hash: self.current.anon_id_seed.combine(hasher.finish()).into(),
449437
};
450438

451-
self.current.intern_new_node(
452-
cx.profiler(),
453-
target_dep_node,
454-
task_deps,
455-
Fingerprint::ZERO,
456-
)
439+
// The DepNodes generated by the process above are not unique. 2 queries could
440+
// have exactly the same dependencies. However, deserialization does not handle
441+
// duplicated nodes, so we do the deduplication here directly.
442+
//
443+
// As anonymous nodes are a small quantity compared to the full dep-graph, the
444+
// memory impact of this `anon_node_to_index` map remains tolerable, and helps
445+
// us avoid useless growth of the graph with almost-equivalent nodes.
446+
match self
447+
.current
448+
.anon_node_to_index
449+
.get_shard_by_value(&target_dep_node)
450+
.lock()
451+
.entry(target_dep_node)
452+
{
453+
Entry::Occupied(entry) => *entry.get(),
454+
Entry::Vacant(entry) => {
455+
let dep_node_index = self.current.intern_new_node(
456+
cx.profiler(),
457+
target_dep_node,
458+
task_deps,
459+
Fingerprint::ZERO,
460+
);
461+
entry.insert(dep_node_index);
462+
dep_node_index
463+
}
464+
}
457465
}
458466
};
459467

@@ -624,25 +632,6 @@ impl<K: DepKind> DepGraph<K> {
624632
}
625633

626634
impl<K: DepKind> DepGraphData<K> {
627-
#[inline]
628-
pub fn dep_node_index_of_opt(&self, dep_node: &DepNode<K>) -> Option<DepNodeIndex> {
629-
if let Some(prev_index) = self.previous.node_to_index_opt(dep_node) {
630-
self.current.prev_index_to_index.lock()[prev_index]
631-
} else {
632-
self.current
633-
.new_node_to_index
634-
.get_shard_by_value(dep_node)
635-
.lock()
636-
.get(dep_node)
637-
.copied()
638-
}
639-
}
640-
641-
#[inline]
642-
pub fn dep_node_exists(&self, dep_node: &DepNode<K>) -> bool {
643-
self.dep_node_index_of_opt(dep_node).is_some()
644-
}
645-
646635
fn node_color(&self, dep_node: &DepNode<K>) -> Option<DepNodeColor> {
647636
if let Some(prev_index) = self.previous.node_to_index_opt(dep_node) {
648637
self.colors.get(prev_index)
@@ -675,11 +664,6 @@ impl<K: DepKind> DepGraphData<K> {
675664
}
676665

677666
impl<K: DepKind> DepGraph<K> {
678-
#[inline]
679-
pub fn dep_node_exists(&self, dep_node: &DepNode<K>) -> bool {
680-
self.data.as_ref().is_some_and(|data| data.dep_node_exists(dep_node))
681-
}
682-
683667
/// Checks whether a previous work product exists for `v` and, if
684668
/// so, return the path that leads to it. Used to skip doing work.
685669
pub fn previous_work_product(&self, v: &WorkProductId) -> Option<WorkProduct> {
@@ -761,7 +745,7 @@ impl<K: DepKind> DepGraphData<K> {
761745
}
762746
}
763747

764-
#[instrument(skip(self, qcx, parent_dep_node_index, frame), level = "debug")]
748+
#[instrument(skip(self, qcx, frame), level = "debug")]
765749
fn try_mark_parent_green<Qcx: QueryContext<DepKind = K>>(
766750
&self,
767751
qcx: Qcx,
@@ -860,10 +844,7 @@ impl<K: DepKind> DepGraphData<K> {
860844
let frame = MarkFrame { index: prev_dep_node_index, parent: frame };
861845

862846
#[cfg(not(parallel_compiler))]
863-
{
864-
debug_assert!(!self.dep_node_exists(dep_node));
865-
debug_assert!(self.colors.get(prev_dep_node_index).is_none());
866-
}
847+
debug_assert!(self.colors.get(prev_dep_node_index).is_none());
867848

868849
// We never try to mark eval_always nodes as green
869850
debug_assert!(!qcx.dep_context().is_eval_always(dep_node.kind));
@@ -1065,24 +1046,24 @@ rustc_index::newtype_index! {
10651046
/// largest in the compiler.
10661047
///
10671048
/// For this reason, we avoid storing `DepNode`s more than once as map
1068-
/// keys. The `new_node_to_index` map only contains nodes not in the previous
1049+
/// keys. The `anon_node_to_index` map only contains nodes of anonymous queries not in the previous
10691050
/// graph, and we map nodes in the previous graph to indices via a two-step
10701051
/// mapping. `SerializedDepGraph` maps from `DepNode` to `SerializedDepNodeIndex`,
10711052
/// and the `prev_index_to_index` vector (which is more compact and faster than
10721053
/// using a map) maps from `SerializedDepNodeIndex` to `DepNodeIndex`.
10731054
///
1074-
/// This struct uses three locks internally. The `data`, `new_node_to_index`,
1055+
/// This struct uses three locks internally. The `data`, `anon_node_to_index`,
10751056
/// and `prev_index_to_index` fields are locked separately. Operations that take
10761057
/// a `DepNodeIndex` typically just access the `data` field.
10771058
///
10781059
/// We only need to manipulate at most two locks simultaneously:
1079-
/// `new_node_to_index` and `data`, or `prev_index_to_index` and `data`. When
1080-
/// manipulating both, we acquire `new_node_to_index` or `prev_index_to_index`
1060+
/// `anon_node_to_index` and `data`, or `prev_index_to_index` and `data`. When
1061+
/// manipulating both, we acquire `anon_node_to_index` or `prev_index_to_index`
10811062
/// first, and `data` second.
10821063
pub(super) struct CurrentDepGraph<K: DepKind> {
10831064
encoder: Steal<GraphEncoder<K>>,
1084-
new_node_to_index: Sharded<FxHashMap<DepNode<K>, DepNodeIndex>>,
10851065
prev_index_to_index: Lock<IndexVec<SerializedDepNodeIndex, Option<DepNodeIndex>>>,
1066+
anon_node_to_index: Sharded<FxHashMap<DepNode<K>, DepNodeIndex>>,
10861067

10871068
/// This is used to verify that fingerprints do not change between the creation of a node
10881069
/// and its recomputation.
@@ -1162,7 +1143,7 @@ impl<K: DepKind> CurrentDepGraph<K> {
11621143
record_graph,
11631144
record_stats,
11641145
)),
1165-
new_node_to_index: Sharded::new(|| {
1146+
anon_node_to_index: Sharded::new(|| {
11661147
FxHashMap::with_capacity_and_hasher(
11671148
new_node_count_estimate / sharded::SHARDS,
11681149
Default::default(),
@@ -1199,16 +1180,7 @@ impl<K: DepKind> CurrentDepGraph<K> {
11991180
edges: EdgesVec,
12001181
current_fingerprint: Fingerprint,
12011182
) -> DepNodeIndex {
1202-
let dep_node_index = match self.new_node_to_index.get_shard_by_value(&key).lock().entry(key)
1203-
{
1204-
Entry::Occupied(entry) => *entry.get(),
1205-
Entry::Vacant(entry) => {
1206-
let dep_node_index =
1207-
self.encoder.borrow().send(profiler, key, current_fingerprint, edges);
1208-
entry.insert(dep_node_index);
1209-
dep_node_index
1210-
}
1211-
};
1183+
let dep_node_index = self.encoder.borrow().send(profiler, key, current_fingerprint, edges);
12121184

12131185
#[cfg(debug_assertions)]
12141186
self.record_edge(dep_node_index, key, current_fingerprint);
@@ -1296,8 +1268,6 @@ impl<K: DepKind> CurrentDepGraph<K> {
12961268
prev_graph: &SerializedDepGraph<K>,
12971269
prev_index: SerializedDepNodeIndex,
12981270
) -> DepNodeIndex {
1299-
self.debug_assert_not_in_new_nodes(prev_graph, prev_index);
1300-
13011271
let mut prev_index_to_index = self.prev_index_to_index.lock();
13021272

13031273
match prev_index_to_index[prev_index] {
@@ -1318,19 +1288,6 @@ impl<K: DepKind> CurrentDepGraph<K> {
13181288
}
13191289
}
13201290
}
1321-
1322-
#[inline]
1323-
fn debug_assert_not_in_new_nodes(
1324-
&self,
1325-
prev_graph: &SerializedDepGraph<K>,
1326-
prev_index: SerializedDepNodeIndex,
1327-
) {
1328-
let node = &prev_graph.index_to_node(prev_index);
1329-
debug_assert!(
1330-
!self.new_node_to_index.get_shard_by_value(node).lock().contains_key(node),
1331-
"node from previous graph present in new node collection"
1332-
);
1333-
}
13341291
}
13351292

13361293
/// The capacity of the `reads` field `SmallVec`

0 commit comments

Comments
 (0)