Skip to content

Commit 1c568bb

Browse files
committed
Reuse the index from promoted nodes when coloring executed tasks
1 parent da83217 commit 1c568bb

File tree

2 files changed

+88
-36
lines changed

2 files changed

+88
-36
lines changed

Diff for: compiler/rustc_query_system/src/dep_graph/graph.rs

+50-33
Original file line numberDiff line numberDiff line change
@@ -141,15 +141,15 @@ impl<D: Deps> DepGraph<D> {
141141
let colors = DepNodeColorMap::new(prev_graph_node_count);
142142

143143
// Instantiate a node with zero dependencies only once for anonymous queries.
144-
let _green_node_index = current.alloc_node(
144+
let _green_node_index = current.alloc_new_node(
145145
DepNode { kind: D::DEP_KIND_ANON_ZERO_DEPS, hash: current.anon_id_seed.into() },
146146
EdgesVec::new(),
147147
Fingerprint::ZERO,
148148
);
149149
assert_eq!(_green_node_index, DepNodeIndex::SINGLETON_ZERO_DEPS_ANON_NODE);
150150

151151
// Instantiate a dependy-less red node only once for anonymous queries.
152-
let red_node_index = current.alloc_node(
152+
let red_node_index = current.alloc_new_node(
153153
DepNode { kind: D::DEP_KIND_RED, hash: Fingerprint::ZERO.into() },
154154
EdgesVec::new(),
155155
Fingerprint::ZERO,
@@ -438,7 +438,7 @@ impl<D: Deps> DepGraphData<D> {
438438
// memory impact of this `anon_node_to_index` map remains tolerable, and helps
439439
// us avoid useless growth of the graph with almost-equivalent nodes.
440440
self.current.anon_node_to_index.get_or_insert_with(target_dep_node, || {
441-
self.current.alloc_node(target_dep_node, task_deps, Fingerprint::ZERO)
441+
self.current.alloc_new_node(target_dep_node, task_deps, Fingerprint::ZERO)
442442
})
443443
}
444444
};
@@ -680,8 +680,8 @@ impl<D: Deps> DepGraphData<D> {
680680
qcx: Qcx,
681681
diagnostic: &DiagInner,
682682
) -> DepNodeIndex {
683-
// Use `send` so we get an unique index, even though the dep node is not.
684-
let dep_node_index = self.current.encoder.send(
683+
// Use `send_new` so we get an unique index, even though the dep node is not.
684+
let dep_node_index = self.current.encoder.send_new(
685685
DepNode {
686686
kind: D::DEP_KIND_SIDE_EFFECT,
687687
hash: PackedFingerprint::from(Fingerprint::ZERO),
@@ -713,20 +713,22 @@ impl<D: Deps> DepGraphData<D> {
713713
}
714714
}
715715

716-
// Manually recreate the node as `promote_node_and_deps_to_current` expects all
717-
// green dependencies.
718-
let dep_node_index = self.current.encoder.send(
716+
// Use `send_and_color` as `promote_node_and_deps_to_current` expects all
717+
// green dependencies. `send_and_color` will also prevent multiple nodes
718+
// being encoded for concurrent calls.
719+
let dep_node_index = self.current.encoder.send_and_color(
720+
prev_index,
721+
&self.colors,
719722
DepNode {
720723
kind: D::DEP_KIND_SIDE_EFFECT,
721724
hash: PackedFingerprint::from(Fingerprint::ZERO),
722725
},
723726
Fingerprint::ZERO,
724727
std::iter::once(DepNodeIndex::FOREVER_RED_NODE).collect(),
728+
true,
725729
);
730+
// This will just overwrite the same value for concurrent calls.
726731
qcx.store_side_effect(dep_node_index, side_effect);
727-
728-
// Mark the node as green.
729-
self.colors.insert(prev_index, DepNodeColor::Green(dep_node_index));
730732
})
731733
}
732734

@@ -736,38 +738,43 @@ impl<D: Deps> DepGraphData<D> {
736738
edges: EdgesVec,
737739
fingerprint: Option<Fingerprint>,
738740
) -> DepNodeIndex {
739-
let dep_node_index =
740-
self.current.alloc_node(key, edges, fingerprint.unwrap_or(Fingerprint::ZERO));
741-
742741
if let Some(prev_index) = self.previous.node_to_index_opt(&key) {
743742
// Determine the color and index of the new `DepNode`.
744-
let color = if let Some(fingerprint) = fingerprint {
743+
let is_green = if let Some(fingerprint) = fingerprint {
745744
if fingerprint == self.previous.fingerprint_by_index(prev_index) {
746745
// This is a green node: it existed in the previous compilation,
747746
// its query was re-executed, and it has the same result as before.
748-
DepNodeColor::Green(dep_node_index)
747+
true
749748
} else {
750749
// This is a red node: it existed in the previous compilation, its query
751750
// was re-executed, but it has a different result from before.
752-
DepNodeColor::Red
751+
false
753752
}
754753
} else {
755754
// This is a red node, effectively: it existed in the previous compilation
756755
// session, its query was re-executed, but it doesn't compute a result hash
757756
// (i.e. it represents a `no_hash` query), so we have no way of determining
758757
// whether or not the result was the same as before.
759-
DepNodeColor::Red
758+
false
760759
};
761760

762-
debug_assert!(
763-
self.colors.get(prev_index).is_none(),
764-
"DepGraph::with_task() - Duplicate DepNodeColor insertion for {key:?}",
761+
let fingerprint = fingerprint.unwrap_or(Fingerprint::ZERO);
762+
763+
let dep_node_index = self.current.encoder.send_and_color(
764+
prev_index,
765+
&self.colors,
766+
key,
767+
fingerprint,
768+
edges,
769+
is_green,
765770
);
766771

767-
self.colors.insert(prev_index, color);
768-
}
772+
self.current.record_node(dep_node_index, key, fingerprint);
769773

770-
dep_node_index
774+
dep_node_index
775+
} else {
776+
self.current.alloc_new_node(key, edges, fingerprint.unwrap_or(Fingerprint::ZERO))
777+
}
771778
}
772779

773780
fn promote_node_and_deps_to_current(&self, prev_index: SerializedDepNodeIndex) -> DepNodeIndex {
@@ -1246,19 +1253,15 @@ impl<D: Deps> CurrentDepGraph<D> {
12461253
assert_eq!(previous, fingerprint, "Unstable fingerprints for {:?}", key);
12471254
}
12481255

1249-
/// Writes the node to the current dep-graph and allocates a `DepNodeIndex` for it.
1250-
/// Assumes that this is a node that has no equivalent in the previous dep-graph.
12511256
#[inline(always)]
1252-
fn alloc_node(
1257+
fn record_node(
12531258
&self,
1259+
dep_node_index: DepNodeIndex,
12541260
key: DepNode,
1255-
edges: EdgesVec,
1256-
current_fingerprint: Fingerprint,
1257-
) -> DepNodeIndex {
1258-
let dep_node_index = self.encoder.send(key, current_fingerprint, edges);
1259-
1261+
_current_fingerprint: Fingerprint,
1262+
) {
12601263
#[cfg(debug_assertions)]
1261-
self.record_edge(dep_node_index, key, current_fingerprint);
1264+
self.record_edge(dep_node_index, key, _current_fingerprint);
12621265

12631266
if let Some(ref nodes_in_current_session) = self.nodes_in_current_session {
12641267
outline(|| {
@@ -1267,6 +1270,20 @@ impl<D: Deps> CurrentDepGraph<D> {
12671270
}
12681271
});
12691272
}
1273+
}
1274+
1275+
/// Writes the node to the current dep-graph and allocates a `DepNodeIndex` for it.
1276+
/// Assumes that this is a node that has no equivalent in the previous dep-graph.
1277+
#[inline(always)]
1278+
fn alloc_new_node(
1279+
&self,
1280+
key: DepNode,
1281+
edges: EdgesVec,
1282+
current_fingerprint: Fingerprint,
1283+
) -> DepNodeIndex {
1284+
let dep_node_index = self.encoder.send_new(key, current_fingerprint, edges);
1285+
1286+
self.record_node(dep_node_index, key, current_fingerprint);
12701287

12711288
dep_node_index
12721289
}

Diff for: compiler/rustc_query_system/src/dep_graph/serialized.rs

+38-3
Original file line numberDiff line numberDiff line change
@@ -707,7 +707,8 @@ impl<D: Deps> GraphEncoder<D> {
707707
}
708708
}
709709

710-
pub(crate) fn send(
710+
/// Encodes a node that does not exists in the previous graph.
711+
pub(crate) fn send_new(
711712
&self,
712713
node: DepNode,
713714
fingerprint: Fingerprint,
@@ -718,6 +719,40 @@ impl<D: Deps> GraphEncoder<D> {
718719
self.status.lock().as_mut().unwrap().encode_node(&node, &self.record_graph)
719720
}
720721

722+
/// Encodes a node that exists in the previous graph, but was re-executed.
723+
///
724+
/// This will also ensure the dep node is colored either red or green.
725+
pub(crate) fn send_and_color(
726+
&self,
727+
prev_index: SerializedDepNodeIndex,
728+
colors: &DepNodeColorMap,
729+
node: DepNode,
730+
fingerprint: Fingerprint,
731+
edges: EdgesVec,
732+
is_green: bool,
733+
) -> DepNodeIndex {
734+
let _prof_timer = self.profiler.generic_activity("incr_comp_encode_dep_graph");
735+
let node = NodeInfo { node, fingerprint, edges };
736+
737+
let mut status = self.status.lock();
738+
let status = status.as_mut().unwrap();
739+
740+
// Check colors inside the lock to avoid racing when `send_promoted` is called concurrently
741+
// on the same index.
742+
match colors.get(prev_index) {
743+
None => {
744+
let dep_node_index = status.encode_node(&node, &self.record_graph);
745+
colors.insert(
746+
prev_index,
747+
if is_green { DepNodeColor::Green(dep_node_index) } else { DepNodeColor::Red },
748+
);
749+
dep_node_index
750+
}
751+
Some(DepNodeColor::Green(dep_node_index)) => dep_node_index,
752+
Some(DepNodeColor::Red) => panic!(),
753+
}
754+
}
755+
721756
/// Encodes a node that was promoted from the previous graph. It reads the information directly from
722757
/// the previous dep graph and expects all edges to already have a new dep node index assigned.
723758
///
@@ -733,8 +768,8 @@ impl<D: Deps> GraphEncoder<D> {
733768
let mut status = self.status.lock();
734769
let status = status.as_mut().unwrap();
735770

736-
// Check colors inside the lock to avoid racing when `send_promoted` is called concurrently
737-
// on the same index.
771+
// Check colors inside the lock to avoid racing when `send_promoted` or `send_and_color`
772+
// is called concurrently on the same index.
738773
match colors.get(prev_index) {
739774
None => {
740775
let dep_node_index =

0 commit comments

Comments
 (0)