Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 59e27c8

Browse files
committedMar 22, 2025
Remove prev_index_to_index field from CurrentDepGraph
1 parent b43f780 commit 59e27c8

File tree

2 files changed

+144
-185
lines changed

2 files changed

+144
-185
lines changed
 

‎compiler/rustc_query_system/src/dep_graph/graph.rs

Lines changed: 118 additions & 173 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ pub struct MarkFrame<'a> {
6666
parent: Option<&'a MarkFrame<'a>>,
6767
}
6868

69-
enum DepNodeColor {
69+
pub(super) enum DepNodeColor {
7070
Red,
7171
Green(DepNodeIndex),
7272
}
@@ -140,34 +140,25 @@ impl<D: Deps> DepGraph<D> {
140140
let colors = DepNodeColorMap::new(prev_graph_node_count);
141141

142142
// Instantiate a dependy-less node only once for anonymous queries.
143-
let _green_node_index = current.alloc_new_node(
143+
let _green_node_index = current.alloc_node(
144144
DepNode { kind: D::DEP_KIND_NULL, hash: current.anon_id_seed.into() },
145145
EdgesVec::new(),
146146
Fingerprint::ZERO,
147147
);
148148
assert_eq!(_green_node_index, DepNodeIndex::SINGLETON_DEPENDENCYLESS_ANON_NODE);
149149

150150
// Instantiate a dependy-less red node only once for anonymous queries.
151-
let (red_node_index, red_node_prev_index_and_color) = current.intern_node(
152-
&prev_graph,
151+
let red_node_index = current.alloc_node(
153152
DepNode { kind: D::DEP_KIND_RED, hash: Fingerprint::ZERO.into() },
154153
EdgesVec::new(),
155-
None,
154+
Fingerprint::ZERO,
156155
);
157156
assert_eq!(red_node_index, DepNodeIndex::FOREVER_RED_NODE);
158-
match red_node_prev_index_and_color {
159-
None => {
160-
// This is expected when we have no previous compilation session.
161-
assert!(prev_graph_node_count == 0);
162-
}
163-
Some((prev_red_node_index, DepNodeColor::Red)) => {
164-
assert_eq!(prev_red_node_index.as_usize(), red_node_index.as_usize());
165-
colors.insert(prev_red_node_index, DepNodeColor::Red);
166-
}
167-
Some((_, DepNodeColor::Green(_))) => {
168-
// There must be a logic error somewhere if we hit this branch.
169-
panic!("DepNodeIndex::FOREVER_RED_NODE evaluated to DepNodeColor::Green")
170-
}
157+
if prev_graph_node_count > 0 {
158+
colors.insert(
159+
SerializedDepNodeIndex::from_u32(DepNodeIndex::FOREVER_RED_NODE.as_u32()),
160+
DepNodeColor::Red,
161+
);
171162
}
172163

173164
DepGraph {
@@ -376,8 +367,7 @@ impl<D: Deps> DepGraphData<D> {
376367
};
377368

378369
let dcx = cx.dep_context();
379-
let dep_node_index =
380-
self.hash_result_and_intern_node(dcx, key, edges, &result, hash_result);
370+
let dep_node_index = self.hash_result_and_alloc_node(dcx, key, edges, &result, hash_result);
381371

382372
(result, dep_node_index)
383373
}
@@ -447,7 +437,7 @@ impl<D: Deps> DepGraphData<D> {
447437
// memory impact of this `anon_node_to_index` map remains tolerable, and helps
448438
// us avoid useless growth of the graph with almost-equivalent nodes.
449439
self.current.anon_node_to_index.get_or_insert_with(target_dep_node, || {
450-
self.current.alloc_new_node(target_dep_node, task_deps, Fingerprint::ZERO)
440+
self.current.alloc_node(target_dep_node, task_deps, Fingerprint::ZERO)
451441
})
452442
}
453443
};
@@ -456,7 +446,7 @@ impl<D: Deps> DepGraphData<D> {
456446
}
457447

458448
/// Intern the new `DepNode` with the dependencies up-to-now.
459-
fn hash_result_and_intern_node<Ctxt: DepContext<Deps = D>, R>(
449+
fn hash_result_and_alloc_node<Ctxt: DepContext<Deps = D>, R>(
460450
&self,
461451
cx: &Ctxt,
462452
node: DepNode,
@@ -468,22 +458,8 @@ impl<D: Deps> DepGraphData<D> {
468458
let current_fingerprint = hash_result.map(|hash_result| {
469459
cx.with_stable_hashing_context(|mut hcx| hash_result(&mut hcx, result))
470460
});
471-
472-
// Intern the new `DepNode` with the dependencies up-to-now.
473-
let (dep_node_index, prev_and_color) =
474-
self.current.intern_node(&self.previous, node, edges, current_fingerprint);
475-
461+
let dep_node_index = self.alloc_and_color_node(node, edges, current_fingerprint);
476462
hashing_timer.finish_with_query_invocation_id(dep_node_index.into());
477-
478-
if let Some((prev_index, color)) = prev_and_color {
479-
debug_assert!(
480-
self.colors.get(prev_index).is_none(),
481-
"DepGraph::with_task() - Duplicate DepNodeColor insertion for {node:?}",
482-
);
483-
484-
self.colors.insert(prev_index, color);
485-
}
486-
487463
dep_node_index
488464
}
489465
}
@@ -601,7 +577,7 @@ impl<D: Deps> DepGraph<D> {
601577
//
602578
// For sanity, we still check that the loaded stable hash and the new one match.
603579
if let Some(prev_index) = data.previous.node_to_index_opt(&node) {
604-
let dep_node_index = data.current.prev_index_to_index.lock()[prev_index];
580+
let dep_node_index = data.colors.current(prev_index);
605581
if let Some(dep_node_index) = dep_node_index {
606582
crate::query::incremental_verify_ich(
607583
cx,
@@ -637,7 +613,7 @@ impl<D: Deps> DepGraph<D> {
637613
}
638614
});
639615

640-
data.hash_result_and_intern_node(&cx, node, edges, result, hash_result)
616+
data.hash_result_and_alloc_node(&cx, node, edges, result, hash_result)
641617
} else {
642618
// Incremental compilation is turned off. We just execute the task
643619
// without tracking. We still provide a dep-node index that uniquely
@@ -655,13 +631,11 @@ impl<D: Deps> DepGraphData<D> {
655631
msg: impl FnOnce() -> S,
656632
) {
657633
if let Some(prev_index) = self.previous.node_to_index_opt(dep_node) {
658-
let current = self.current.prev_index_to_index.lock()[prev_index];
634+
let current = self.colors.get(prev_index);
659635
assert!(current.is_none(), "{}", msg())
660-
} else if let Some(nodes_newly_allocated_in_current_session) =
661-
&self.current.nodes_newly_allocated_in_current_session
662-
{
636+
} else if let Some(nodes_in_current_session) = &self.current.nodes_in_current_session {
663637
outline(|| {
664-
let seen = nodes_newly_allocated_in_current_session.lock().contains_key(dep_node);
638+
let seen = nodes_in_current_session.lock().contains_key(dep_node);
665639
assert!(!seen, "{}", msg());
666640
});
667641
}
@@ -738,15 +712,77 @@ impl<D: Deps> DepGraphData<D> {
738712
}
739713
}
740714

741-
// Promote the previous diagnostics to the current session.
742-
let index = self.current.promote_node_and_deps_to_current(&self.previous, prev_index);
743-
// FIXME: Can this race with a parallel compiler?
744-
qcx.store_side_effect(index, side_effect);
715+
// Manually recreate the node as `promote_node_and_deps_to_current` expects all
716+
// green dependencies.
717+
let dep_node_index = self.current.encoder.send(
718+
DepNode {
719+
kind: D::DEP_KIND_SIDE_EFFECT,
720+
hash: PackedFingerprint::from(Fingerprint::ZERO),
721+
},
722+
Fingerprint::ZERO,
723+
std::iter::once(DepNodeIndex::FOREVER_RED_NODE).collect(),
724+
);
725+
qcx.store_side_effect(dep_node_index, side_effect);
745726

746727
// Mark the node as green.
747-
self.colors.insert(prev_index, DepNodeColor::Green(index));
728+
self.colors.insert(prev_index, DepNodeColor::Green(dep_node_index));
748729
})
749730
}
731+
732+
fn alloc_and_color_node(
733+
&self,
734+
key: DepNode,
735+
edges: EdgesVec,
736+
fingerprint: Option<Fingerprint>,
737+
) -> DepNodeIndex {
738+
let dep_node_index =
739+
self.current.alloc_node(key, edges, fingerprint.unwrap_or(Fingerprint::ZERO));
740+
741+
if let Some(prev_index) = self.previous.node_to_index_opt(&key) {
742+
// Determine the color and index of the new `DepNode`.
743+
let color = if let Some(fingerprint) = fingerprint {
744+
if fingerprint == self.previous.fingerprint_by_index(prev_index) {
745+
// This is a green node: it existed in the previous compilation,
746+
// its query was re-executed, and it has the same result as before.
747+
DepNodeColor::Green(dep_node_index)
748+
} else {
749+
// This is a red node: it existed in the previous compilation, its query
750+
// was re-executed, but it has a different result from before.
751+
DepNodeColor::Red
752+
}
753+
} else {
754+
// This is a red node, effectively: it existed in the previous compilation
755+
// session, its query was re-executed, but it doesn't compute a result hash
756+
// (i.e. it represents a `no_hash` query), so we have no way of determining
757+
// whether or not the result was the same as before.
758+
DepNodeColor::Red
759+
};
760+
761+
debug_assert!(
762+
self.colors.get(prev_index).is_none(),
763+
"DepGraph::with_task() - Duplicate DepNodeColor insertion for {key:?}",
764+
);
765+
766+
self.colors.insert(prev_index, color);
767+
}
768+
769+
dep_node_index
770+
}
771+
772+
fn promote_node_and_deps_to_current(&self, prev_index: SerializedDepNodeIndex) -> DepNodeIndex {
773+
self.current.debug_assert_not_in_new_nodes(&self.previous, prev_index);
774+
775+
let dep_node_index = self.current.encoder.send_promoted(prev_index, &self.colors);
776+
777+
#[cfg(debug_assertions)]
778+
self.current.record_edge(
779+
dep_node_index,
780+
self.previous.index_to_node(prev_index),
781+
self.previous.fingerprint_by_index(prev_index),
782+
);
783+
784+
dep_node_index
785+
}
750786
}
751787

752788
impl<D: Deps> DepGraph<D> {
@@ -948,14 +984,10 @@ impl<D: Deps> DepGraphData<D> {
948984

949985
// We allocating an entry for the node in the current dependency graph and
950986
// adding all the appropriate edges imported from the previous graph
951-
let dep_node_index =
952-
self.current.promote_node_and_deps_to_current(&self.previous, prev_dep_node_index);
953-
954-
// ... emitting any stored diagnostic ...
987+
let dep_node_index = self.promote_node_and_deps_to_current(prev_dep_node_index);
955988

956989
// ... and finally storing a "Green" entry in the color map.
957990
// Multiple threads can all write the same color here
958-
self.colors.insert(prev_dep_node_index, DepNodeColor::Green(dep_node_index));
959991

960992
debug!("successfully marked {dep_node:?} as green");
961993
Some(dep_node_index)
@@ -1106,7 +1138,6 @@ rustc_index::newtype_index! {
11061138
/// first, and `data` second.
11071139
pub(super) struct CurrentDepGraph<D: Deps> {
11081140
encoder: GraphEncoder<D>,
1109-
prev_index_to_index: Lock<IndexVec<SerializedDepNodeIndex, Option<DepNodeIndex>>>,
11101141
anon_node_to_index: ShardedHashMap<DepNode, DepNodeIndex>,
11111142

11121143
/// This is used to verify that fingerprints do not change between the creation of a node
@@ -1123,9 +1154,8 @@ pub(super) struct CurrentDepGraph<D: Deps> {
11231154
/// This field is only `Some` if the `-Z incremental_verify_ich` option is present
11241155
/// or if `debug_assertions` are enabled.
11251156
///
1126-
/// The map contains all DepNodes that have been allocated in the current session so far and
1127-
/// for which there is no equivalent in the previous session.
1128-
nodes_newly_allocated_in_current_session: Option<Lock<FxHashMap<DepNode, DepNodeIndex>>>,
1157+
/// The map contains all DepNodes that have been allocated in the current session so far.
1158+
nodes_in_current_session: Option<Lock<FxHashMap<DepNode, DepNodeIndex>>>,
11291159

11301160
/// Anonymous `DepNode`s are nodes whose IDs we compute from the list of
11311161
/// their edges. This has the beneficial side-effect that multiple anonymous
@@ -1190,13 +1220,12 @@ impl<D: Deps> CurrentDepGraph<D> {
11901220
// FIXME: The count estimate is off as anon nodes are only a portion of the nodes.
11911221
new_node_count_estimate / sharded::shards(),
11921222
),
1193-
prev_index_to_index: Lock::new(IndexVec::from_elem_n(None, prev_graph_node_count)),
11941223
anon_id_seed,
11951224
#[cfg(debug_assertions)]
11961225
forbidden_edge,
11971226
#[cfg(debug_assertions)]
11981227
fingerprints: Lock::new(IndexVec::from_elem_n(None, new_node_count_estimate)),
1199-
nodes_newly_allocated_in_current_session: new_node_dbg.then(|| {
1228+
nodes_in_current_session: new_node_dbg.then(|| {
12001229
Lock::new(FxHashMap::with_capacity_and_hasher(
12011230
new_node_count_estimate,
12021231
Default::default(),
@@ -1219,7 +1248,7 @@ impl<D: Deps> CurrentDepGraph<D> {
12191248
/// Writes the node to the current dep-graph and allocates a `DepNodeIndex` for it.
12201249
/// Assumes that this is a node that has no equivalent in the previous dep-graph.
12211250
#[inline(always)]
1222-
fn alloc_new_node(
1251+
fn alloc_node(
12231252
&self,
12241253
key: DepNode,
12251254
edges: EdgesVec,
@@ -1230,15 +1259,9 @@ impl<D: Deps> CurrentDepGraph<D> {
12301259
#[cfg(debug_assertions)]
12311260
self.record_edge(dep_node_index, key, current_fingerprint);
12321261

1233-
if let Some(ref nodes_newly_allocated_in_current_session) =
1234-
self.nodes_newly_allocated_in_current_session
1235-
{
1262+
if let Some(ref nodes_in_current_session) = self.nodes_in_current_session {
12361263
outline(|| {
1237-
if nodes_newly_allocated_in_current_session
1238-
.lock()
1239-
.insert(key, dep_node_index)
1240-
.is_some()
1241-
{
1264+
if nodes_in_current_session.lock().insert(key, dep_node_index).is_some() {
12421265
panic!("Found duplicate dep-node {key:?}");
12431266
}
12441267
});
@@ -1247,102 +1270,20 @@ impl<D: Deps> CurrentDepGraph<D> {
12471270
dep_node_index
12481271
}
12491272

1250-
fn intern_node(
1251-
&self,
1252-
prev_graph: &SerializedDepGraph,
1253-
key: DepNode,
1254-
edges: EdgesVec,
1255-
fingerprint: Option<Fingerprint>,
1256-
) -> (DepNodeIndex, Option<(SerializedDepNodeIndex, DepNodeColor)>) {
1257-
if let Some(prev_index) = prev_graph.node_to_index_opt(&key) {
1258-
let get_dep_node_index = |fingerprint| {
1259-
let mut prev_index_to_index = self.prev_index_to_index.lock();
1260-
1261-
let dep_node_index = match prev_index_to_index[prev_index] {
1262-
Some(dep_node_index) => dep_node_index,
1263-
None => {
1264-
let dep_node_index = self.encoder.send(key, fingerprint, edges);
1265-
prev_index_to_index[prev_index] = Some(dep_node_index);
1266-
dep_node_index
1267-
}
1268-
};
1269-
1270-
#[cfg(debug_assertions)]
1271-
self.record_edge(dep_node_index, key, fingerprint);
1272-
1273-
dep_node_index
1274-
};
1275-
1276-
// Determine the color and index of the new `DepNode`.
1277-
if let Some(fingerprint) = fingerprint {
1278-
if fingerprint == prev_graph.fingerprint_by_index(prev_index) {
1279-
// This is a green node: it existed in the previous compilation,
1280-
// its query was re-executed, and it has the same result as before.
1281-
let dep_node_index = get_dep_node_index(fingerprint);
1282-
(dep_node_index, Some((prev_index, DepNodeColor::Green(dep_node_index))))
1283-
} else {
1284-
// This is a red node: it existed in the previous compilation, its query
1285-
// was re-executed, but it has a different result from before.
1286-
let dep_node_index = get_dep_node_index(fingerprint);
1287-
(dep_node_index, Some((prev_index, DepNodeColor::Red)))
1288-
}
1289-
} else {
1290-
// This is a red node, effectively: it existed in the previous compilation
1291-
// session, its query was re-executed, but it doesn't compute a result hash
1292-
// (i.e. it represents a `no_hash` query), so we have no way of determining
1293-
// whether or not the result was the same as before.
1294-
let dep_node_index = get_dep_node_index(Fingerprint::ZERO);
1295-
(dep_node_index, Some((prev_index, DepNodeColor::Red)))
1296-
}
1297-
} else {
1298-
let fingerprint = fingerprint.unwrap_or(Fingerprint::ZERO);
1299-
1300-
// This is a new node: it didn't exist in the previous compilation session.
1301-
let dep_node_index = self.alloc_new_node(key, edges, fingerprint);
1302-
1303-
(dep_node_index, None)
1304-
}
1305-
}
1306-
1307-
fn promote_node_and_deps_to_current(
1308-
&self,
1309-
prev_graph: &SerializedDepGraph,
1310-
prev_index: SerializedDepNodeIndex,
1311-
) -> DepNodeIndex {
1312-
self.debug_assert_not_in_new_nodes(prev_graph, prev_index);
1313-
1314-
let mut prev_index_to_index = self.prev_index_to_index.lock();
1315-
1316-
match prev_index_to_index[prev_index] {
1317-
Some(dep_node_index) => dep_node_index,
1318-
None => {
1319-
let dep_node_index = self.encoder.send_promoted(prev_index, &*prev_index_to_index);
1320-
prev_index_to_index[prev_index] = Some(dep_node_index);
1321-
#[cfg(debug_assertions)]
1322-
self.record_edge(
1323-
dep_node_index,
1324-
prev_graph.index_to_node(prev_index),
1325-
prev_graph.fingerprint_by_index(prev_index),
1326-
);
1327-
dep_node_index
1328-
}
1329-
}
1330-
}
1331-
13321273
#[inline]
13331274
fn debug_assert_not_in_new_nodes(
13341275
&self,
13351276
prev_graph: &SerializedDepGraph,
13361277
prev_index: SerializedDepNodeIndex,
13371278
) {
1338-
let node = &prev_graph.index_to_node(prev_index);
1339-
debug_assert!(
1340-
!self
1341-
.nodes_newly_allocated_in_current_session
1342-
.as_ref()
1343-
.map_or(false, |set| set.lock().contains_key(node)),
1344-
"node from previous graph present in new node collection"
1345-
);
1279+
if let Some(ref nodes_in_current_session) = self.nodes_in_current_session {
1280+
debug_assert!(
1281+
!nodes_in_current_session
1282+
.lock()
1283+
.contains_key(&prev_graph.index_to_node(prev_index)),
1284+
"node from previous graph present in new node collection"
1285+
);
1286+
}
13461287
}
13471288
}
13481289

@@ -1389,36 +1330,40 @@ impl Default for TaskDeps {
13891330
}
13901331
// A data structure that stores Option<DepNodeColor> values as a contiguous
13911332
// array, using one u32 per entry.
1392-
struct DepNodeColorMap {
1333+
pub(super) struct DepNodeColorMap {
13931334
values: IndexVec<SerializedDepNodeIndex, AtomicU32>,
13941335
}
13951336

1396-
const COMPRESSED_NONE: u32 = 0;
1397-
const COMPRESSED_RED: u32 = 1;
1398-
const COMPRESSED_FIRST_GREEN: u32 = 2;
1337+
const COMPRESSED_NONE: u32 = u32::MAX;
1338+
const COMPRESSED_RED: u32 = u32::MAX - 1;
13991339

14001340
impl DepNodeColorMap {
14011341
fn new(size: usize) -> DepNodeColorMap {
1342+
debug_assert!(COMPRESSED_RED > DepNodeIndex::MAX_AS_U32);
14021343
DepNodeColorMap { values: (0..size).map(|_| AtomicU32::new(COMPRESSED_NONE)).collect() }
14031344
}
14041345

14051346
#[inline]
1406-
fn get(&self, index: SerializedDepNodeIndex) -> Option<DepNodeColor> {
1347+
pub(super) fn current(&self, index: SerializedDepNodeIndex) -> Option<DepNodeIndex> {
1348+
let value = self.values[index].load(Ordering::Relaxed);
1349+
if value <= DepNodeIndex::MAX_AS_U32 { Some(DepNodeIndex::from_u32(value)) } else { None }
1350+
}
1351+
1352+
#[inline]
1353+
pub(super) fn get(&self, index: SerializedDepNodeIndex) -> Option<DepNodeColor> {
14071354
match self.values[index].load(Ordering::Acquire) {
14081355
COMPRESSED_NONE => None,
14091356
COMPRESSED_RED => Some(DepNodeColor::Red),
1410-
value => {
1411-
Some(DepNodeColor::Green(DepNodeIndex::from_u32(value - COMPRESSED_FIRST_GREEN)))
1412-
}
1357+
value => Some(DepNodeColor::Green(DepNodeIndex::from_u32(value))),
14131358
}
14141359
}
14151360

14161361
#[inline]
1417-
fn insert(&self, index: SerializedDepNodeIndex, color: DepNodeColor) {
1362+
pub(super) fn insert(&self, index: SerializedDepNodeIndex, color: DepNodeColor) {
14181363
self.values[index].store(
14191364
match color {
14201365
DepNodeColor::Red => COMPRESSED_RED,
1421-
DepNodeColor::Green(index) => index.as_u32() + COMPRESSED_FIRST_GREEN,
1366+
DepNodeColor::Green(index) => index.as_u32(),
14221367
},
14231368
Ordering::Release,
14241369
)
@@ -1454,16 +1399,16 @@ fn panic_on_forbidden_read<D: Deps>(data: &DepGraphData<D>, dep_node_index: DepN
14541399
let mut dep_node = None;
14551400

14561401
// First try to find the dep node among those that already existed in the
1457-
// previous session
1458-
for (prev_index, index) in data.current.prev_index_to_index.lock().iter_enumerated() {
1459-
if index == &Some(dep_node_index) {
1402+
// previous session and has been marked green
1403+
for prev_index in data.colors.values.indices() {
1404+
if data.colors.current(prev_index) == Some(dep_node_index) {
14601405
dep_node = Some(data.previous.index_to_node(prev_index));
14611406
break;
14621407
}
14631408
}
14641409

14651410
if dep_node.is_none()
1466-
&& let Some(nodes) = &data.current.nodes_newly_allocated_in_current_session
1411+
&& let Some(nodes) = &data.current.nodes_in_current_session
14671412
{
14681413
// Try to find it among the nodes allocated so far in this session
14691414
if let Some((node, _)) = nodes.lock().iter().find(|&(_, index)| *index == dep_node_index) {

‎compiler/rustc_query_system/src/dep_graph/serialized.rs

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ use rustc_serialize::opaque::{FileEncodeResult, FileEncoder, IntEncodedWithFixed
5050
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
5151
use tracing::{debug, instrument};
5252

53+
use super::graph::{DepNodeColor, DepNodeColorMap};
5354
use super::query::DepGraphQuery;
5455
use super::{DepKind, DepNode, DepNodeIndex, Deps};
5556
use crate::dep_graph::edges::EdgesVec;
@@ -441,15 +442,15 @@ impl NodeInfo {
441442
node: DepNode,
442443
fingerprint: Fingerprint,
443444
prev_index: SerializedDepNodeIndex,
444-
prev_index_to_index: &IndexVec<SerializedDepNodeIndex, Option<DepNodeIndex>>,
445+
colors: &DepNodeColorMap,
445446
previous: &SerializedDepGraph,
446447
) -> usize {
447448
let edges = previous.edge_targets_from(prev_index);
448449
let edge_count = edges.size_hint().0;
449450

450451
// Find the highest edge in the new dep node indices
451452
let edge_max =
452-
edges.clone().map(|i| prev_index_to_index[i].unwrap().as_u32()).max().unwrap_or(0);
453+
edges.clone().map(|i| colors.current(i).unwrap().as_u32()).max().unwrap_or(0);
453454

454455
let header = SerializedNodeHeader::<D>::new(node, fingerprint, edge_max, edge_count);
455456
e.write_array(header.bytes);
@@ -460,7 +461,7 @@ impl NodeInfo {
460461

461462
let bytes_per_index = header.bytes_per_index();
462463
for node_index in edges {
463-
let node_index = prev_index_to_index[node_index].unwrap();
464+
let node_index = colors.current(node_index).unwrap();
464465
e.write_with(|dest| {
465466
*dest = node_index.as_u32().to_le_bytes();
466467
bytes_per_index
@@ -565,7 +566,7 @@ impl<D: Deps> EncoderState<D> {
565566
&mut self,
566567
prev_index: SerializedDepNodeIndex,
567568
record_graph: &Option<Lock<DepGraphQuery>>,
568-
prev_index_to_index: &IndexVec<SerializedDepNodeIndex, Option<DepNodeIndex>>,
569+
colors: &DepNodeColorMap,
569570
) -> DepNodeIndex {
570571
let node = self.previous.index_to_node(prev_index);
571572

@@ -575,7 +576,7 @@ impl<D: Deps> EncoderState<D> {
575576
node,
576577
fingerprint,
577578
prev_index,
578-
prev_index_to_index,
579+
colors,
579580
&self.previous,
580581
);
581582

@@ -585,7 +586,7 @@ impl<D: Deps> EncoderState<D> {
585586
|this| {
586587
this.previous
587588
.edge_targets_from(prev_index)
588-
.map(|i| prev_index_to_index[i].unwrap())
589+
.map(|i| colors.current(i).unwrap())
589590
.collect()
590591
},
591592
record_graph,
@@ -719,18 +720,31 @@ impl<D: Deps> GraphEncoder<D> {
719720

720721
/// Encodes a node that was promoted from the previous graph. It reads the information directly from
721722
/// the previous dep graph and expects all edges to already have a new dep node index assigned.
723+
///
724+
/// This will also ensure the dep node is marked green.
722725
#[inline]
723726
pub(crate) fn send_promoted(
724727
&self,
725728
prev_index: SerializedDepNodeIndex,
726-
prev_index_to_index: &IndexVec<SerializedDepNodeIndex, Option<DepNodeIndex>>,
729+
colors: &DepNodeColorMap,
727730
) -> DepNodeIndex {
728731
let _prof_timer = self.profiler.generic_activity("incr_comp_encode_dep_graph");
729-
self.status.lock().as_mut().unwrap().encode_promoted_node(
730-
prev_index,
731-
&self.record_graph,
732-
prev_index_to_index,
733-
)
732+
733+
let mut status = self.status.lock();
734+
let status = status.as_mut().unwrap();
735+
736+
// Check colors inside the lock to avoid racing when `send_promoted` is called concurrently
737+
// on the same index.
738+
match colors.get(prev_index) {
739+
None => {
740+
let dep_node_index =
741+
status.encode_promoted_node(prev_index, &self.record_graph, colors);
742+
colors.insert(prev_index, DepNodeColor::Green(dep_node_index));
743+
dep_node_index
744+
}
745+
Some(DepNodeColor::Green(dep_node_index)) => dep_node_index,
746+
Some(DepNodeColor::Red) => panic!(),
747+
}
734748
}
735749

736750
pub(crate) fn finish(&self) -> FileEncodeResult {

0 commit comments

Comments
 (0)
This repository has been archived.