diff options
Diffstat (limited to 'compiler/rustc_query_system/src/dep_graph/serialized.rs')
| -rw-r--r-- | compiler/rustc_query_system/src/dep_graph/serialized.rs | 55 |
1 files changed, 40 insertions, 15 deletions
diff --git a/compiler/rustc_query_system/src/dep_graph/serialized.rs b/compiler/rustc_query_system/src/dep_graph/serialized.rs index 2c6fd7d494f..7750d6d1fef 100644 --- a/compiler/rustc_query_system/src/dep_graph/serialized.rs +++ b/compiler/rustc_query_system/src/dep_graph/serialized.rs @@ -50,6 +50,7 @@ use rustc_serialize::opaque::{FileEncodeResult, FileEncoder, IntEncodedWithFixed use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; use tracing::{debug, instrument}; +use super::graph::{DepNodeColor, DepNodeColorMap}; use super::query::DepGraphQuery; use super::{DepKind, DepNode, DepNodeIndex, Deps}; use crate::dep_graph::edges::EdgesVec; @@ -179,8 +180,8 @@ fn mask(bits: usize) -> usize { } impl SerializedDepGraph { - #[instrument(level = "debug", skip(d))] - pub fn decode<D: Deps>(d: &mut MemDecoder<'_>) -> Arc<SerializedDepGraph> { + #[instrument(level = "debug", skip(d, deps))] + pub fn decode<D: Deps>(d: &mut MemDecoder<'_>, deps: &D) -> Arc<SerializedDepGraph> { // The last 16 bytes are the node count and edge count. debug!("position: {:?}", d.position()); let (node_count, edge_count) = @@ -252,7 +253,18 @@ impl SerializedDepGraph { .collect(); for (idx, node) in nodes.iter_enumerated() { - index[node.kind.as_usize()].insert(node.hash, idx); + if index[node.kind.as_usize()].insert(node.hash, idx).is_some() { + // Side effect nodes can have duplicates + if node.kind != D::DEP_KIND_SIDE_EFFECT { + let name = deps.name(node.kind); + panic!( + "Error: A dep graph node ({name}) does not have an unique index. \ + Running a clean build on a nightly compiler with `-Z incremental-verify-ich` \ + can help narrow down the issue for reporting. A clean build may also work around the issue.\n + DepNode: {node:?}" + ) + } + } } Arc::new(SerializedDepGraph { @@ -430,7 +442,7 @@ impl NodeInfo { node: DepNode, fingerprint: Fingerprint, prev_index: SerializedDepNodeIndex, - prev_index_to_index: &IndexVec<SerializedDepNodeIndex, Option<DepNodeIndex>>, + colors: &DepNodeColorMap, previous: &SerializedDepGraph, ) -> usize { let edges = previous.edge_targets_from(prev_index); @@ -438,7 +450,7 @@ impl NodeInfo { // Find the highest edge in the new dep node indices let edge_max = - edges.clone().map(|i| prev_index_to_index[i].unwrap().as_u32()).max().unwrap_or(0); + edges.clone().map(|i| colors.current(i).unwrap().as_u32()).max().unwrap_or(0); let header = SerializedNodeHeader::<D>::new(node, fingerprint, edge_max, edge_count); e.write_array(header.bytes); @@ -449,7 +461,7 @@ impl NodeInfo { let bytes_per_index = header.bytes_per_index(); for node_index in edges { - let node_index = prev_index_to_index[node_index].unwrap(); + let node_index = colors.current(node_index).unwrap(); e.write_with(|dest| { *dest = node_index.as_u32().to_le_bytes(); bytes_per_index @@ -554,7 +566,7 @@ impl<D: Deps> EncoderState<D> { &mut self, prev_index: SerializedDepNodeIndex, record_graph: &Option<Lock<DepGraphQuery>>, - prev_index_to_index: &IndexVec<SerializedDepNodeIndex, Option<DepNodeIndex>>, + colors: &DepNodeColorMap, ) -> DepNodeIndex { let node = self.previous.index_to_node(prev_index); @@ -564,7 +576,7 @@ impl<D: Deps> EncoderState<D> { node, fingerprint, prev_index, - prev_index_to_index, + colors, &self.previous, ); @@ -574,7 +586,7 @@ impl<D: Deps> EncoderState<D> { |this| { this.previous .edge_targets_from(prev_index) - .map(|i| prev_index_to_index[i].unwrap()) + .map(|i| colors.current(i).unwrap()) .collect() }, record_graph, @@ -708,18 +720,31 @@ impl<D: Deps> GraphEncoder<D> { /// Encodes a node that was promoted from the previous graph. It reads the information directly from /// the previous dep graph and expects all edges to already have a new dep node index assigned. + /// + /// This will also ensure the dep node is marked green. #[inline] pub(crate) fn send_promoted( &self, prev_index: SerializedDepNodeIndex, - prev_index_to_index: &IndexVec<SerializedDepNodeIndex, Option<DepNodeIndex>>, + colors: &DepNodeColorMap, ) -> DepNodeIndex { let _prof_timer = self.profiler.generic_activity("incr_comp_encode_dep_graph"); - self.status.lock().as_mut().unwrap().encode_promoted_node( - prev_index, - &self.record_graph, - prev_index_to_index, - ) + + let mut status = self.status.lock(); + let status = status.as_mut().unwrap(); + + // Check colors inside the lock to avoid racing when `send_promoted` is called concurrently + // on the same index. + match colors.get(prev_index) { + None => { + let dep_node_index = + status.encode_promoted_node(prev_index, &self.record_graph, colors); + colors.insert(prev_index, DepNodeColor::Green(dep_node_index)); + dep_node_index + } + Some(DepNodeColor::Green(dep_node_index)) => dep_node_index, + Some(DepNodeColor::Red) => panic!(), + } } pub(crate) fn finish(&self) -> FileEncodeResult { |
