diff --git a/src/librustc/dep_graph/graph.rs b/src/librustc/dep_graph/graph.rs index d9770db9d69..f76f9279e5b 100644 --- a/src/librustc/dep_graph/graph.rs +++ b/src/librustc/dep_graph/graph.rs @@ -59,6 +59,13 @@ impl DepNodeIndex { }; } +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] +pub enum DepNodeColor { + Red, + Green, + Gray +} + struct DepGraphData { /// The old, initial encoding of the dependency graph. This will soon go /// away. @@ -74,6 +81,8 @@ struct DepGraphData { /// nodes and edges as well as all fingerprints of nodes that have them. previous: PreviousDepGraph, + colors: RefCell>, + /// When we load, there may be `.o` files, cached mir, or other such /// things available to us. If we find that they are not dirty, we /// load the path to the file storing those work-products here into @@ -97,6 +106,7 @@ impl DepGraph { dep_node_debug: RefCell::new(FxHashMap()), current: RefCell::new(CurrentDepGraph::new()), previous: prev_graph, + colors: RefCell::new(FxHashMap()), })), fingerprints: Rc::new(RefCell::new(FxHashMap())), } @@ -192,11 +202,23 @@ impl DepGraph { let mut stable_hasher = StableHasher::new(); result.hash_stable(&mut hcx, &mut stable_hasher); + let current_fingerprint = stable_hasher.finish(); + assert!(self.fingerprints .borrow_mut() - .insert(key, stable_hasher.finish()) + .insert(key, current_fingerprint) .is_none()); + let prev_fingerprint = data.previous.fingerprint_of(&key); + + let color = if Some(current_fingerprint) == prev_fingerprint { + DepNodeColor::Green + } else { + DepNodeColor::Red + }; + + assert!(data.colors.borrow_mut().insert(key, color).is_none()); + (result, DepNodeIndex { legacy: dep_node_index_legacy, new: dep_node_index_new, @@ -228,7 +250,16 @@ impl DepGraph { data.current.borrow_mut().push_anon_task(); let result = op(); let dep_node_index_legacy = data.edges.borrow_mut().pop_anon_task(dep_kind); - let dep_node_index_new = data.current.borrow_mut().pop_anon_task(dep_kind); + let (new_dep_node, dep_node_index_new) = data.current + .borrow_mut() + .pop_anon_task(dep_kind); + if let Some(new_dep_node) = new_dep_node { + assert!(data.colors + .borrow_mut() + .insert(new_dep_node, DepNodeColor::Red) + .is_none()); + } + (result, DepNodeIndex { legacy: dep_node_index_legacy, new: dep_node_index_new, @@ -275,10 +306,22 @@ impl DepGraph { self.fingerprints.borrow()[dep_node] } - pub fn prev_fingerprint_of(&self, dep_node: &DepNode) -> Fingerprint { + pub fn prev_fingerprint_of(&self, dep_node: &DepNode) -> Option { self.data.as_ref().unwrap().previous.fingerprint_of(dep_node) } + pub fn node_color(&self, dep_node: &DepNode) -> DepNodeColor { + match self.data.as_ref().unwrap().colors.borrow().get(dep_node) { + Some(&color) => { + debug_assert!(color != DepNodeColor::Gray); + color + } + None => { + DepNodeColor::Gray + } + } + } + /// Indicates that a previous work product exists for `v`. This is /// invoked during initial start-up based on what nodes are clean /// (and what files exist in the incr. directory). @@ -485,7 +528,7 @@ impl CurrentDepGraph { }); } - fn pop_anon_task(&mut self, kind: DepKind) -> DepNodeIndexNew { + fn pop_anon_task(&mut self, kind: DepKind) -> (Option, DepNodeIndexNew) { let popped_node = self.task_stack.pop().unwrap(); if let OpenTask::Anon { @@ -514,10 +557,10 @@ impl CurrentDepGraph { }; if let Some(&index) = self.node_to_node_index.get(&target_dep_node) { - return index; + (None, index) + } else { + (Some(target_dep_node), self.alloc_node(target_dep_node, reads)) } - - self.alloc_node(target_dep_node, reads) } else { bug!("pop_anon_task() - Expected anonymous task to be popped") } diff --git a/src/librustc/dep_graph/prev.rs b/src/librustc/dep_graph/prev.rs index 882ca0414cc..0236f9c2292 100644 --- a/src/librustc/dep_graph/prev.rs +++ b/src/librustc/dep_graph/prev.rs @@ -39,8 +39,9 @@ impl PreviousDepGraph { .for_each(|&index| f(&self.data.nodes[index])); } - pub fn fingerprint_of(&self, dep_node: &DepNode) -> Fingerprint { - let node_index = self.index[dep_node]; - self.data.nodes[node_index].1 + pub fn fingerprint_of(&self, dep_node: &DepNode) -> Option { + self.index + .get(dep_node) + .map(|&node_index| self.data.nodes[node_index].1) } } diff --git a/src/librustc_incremental/persist/dirty_clean.rs b/src/librustc_incremental/persist/dirty_clean.rs index a6d39a91863..33a9cb58c51 100644 --- a/src/librustc_incremental/persist/dirty_clean.rs +++ b/src/librustc_incremental/persist/dirty_clean.rs @@ -122,7 +122,7 @@ impl<'a, 'tcx> DirtyCleanVisitor<'a, 'tcx> { let current_fingerprint = self.tcx.dep_graph.fingerprint_of(&dep_node); let prev_fingerprint = self.tcx.dep_graph.prev_fingerprint_of(&dep_node); - if current_fingerprint == prev_fingerprint { + if Some(current_fingerprint) == prev_fingerprint { let dep_node_str = self.dep_node_str(&dep_node); self.tcx.sess.span_err( item_span, @@ -136,7 +136,7 @@ impl<'a, 'tcx> DirtyCleanVisitor<'a, 'tcx> { let current_fingerprint = self.tcx.dep_graph.fingerprint_of(&dep_node); let prev_fingerprint = self.tcx.dep_graph.prev_fingerprint_of(&dep_node); - if current_fingerprint != prev_fingerprint { + if Some(current_fingerprint) != prev_fingerprint { let dep_node_str = self.dep_node_str(&dep_node); self.tcx.sess.span_err( item_span,