diff options
| author | Michael Woerister <michaelwoerister@posteo> | 2017-09-25 13:51:49 +0200 |
|---|---|---|
| committer | Michael Woerister <michaelwoerister@posteo> | 2017-10-02 15:36:47 +0200 |
| commit | 6db27d9f90223693e84d230e5654d4c1a5afe700 (patch) | |
| tree | 8c531466374214251f179d026e8de608fdc2bf3a /src/librustc/dep_graph | |
| parent | a948be81cda8ed8145f4e1d7cf6b0a59efb8e240 (diff) | |
| download | rust-6db27d9f90223693e84d230e5654d4c1a5afe700.tar.gz rust-6db27d9f90223693e84d230e5654d4c1a5afe700.zip | |
incr.comp.: Add minimal version of try_mark_green procedure.
Diffstat (limited to 'src/librustc/dep_graph')
| -rw-r--r-- | src/librustc/dep_graph/graph.rs | 146 | ||||
| -rw-r--r-- | src/librustc/dep_graph/mod.rs | 2 | ||||
| -rw-r--r-- | src/librustc/dep_graph/prev.rs | 31 |
3 files changed, 154 insertions, 25 deletions
diff --git a/src/librustc/dep_graph/graph.rs b/src/librustc/dep_graph/graph.rs index f76f9279e5b..071f233b188 100644 --- a/src/librustc/dep_graph/graph.rs +++ b/src/librustc/dep_graph/graph.rs @@ -16,6 +16,7 @@ use session::config::OutputType; use std::cell::{Ref, RefCell}; use std::hash::Hash; use std::rc::Rc; +use ty::TyCtxt; use util::common::{ProfileQueriesMsg, profq_msg}; use ich::Fingerprint; @@ -28,6 +29,7 @@ use super::edges::{self, DepGraphEdges}; use super::serialized::{SerializedDepGraph, SerializedDepNodeIndex}; use super::prev::PreviousDepGraph; + #[derive(Clone)] pub struct DepGraph { data: Option<Rc<DepGraphData>>, @@ -62,8 +64,7 @@ impl DepNodeIndex { #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] pub enum DepNodeColor { Red, - Green, - Gray + Green(DepNodeIndex) } struct DepGraphData { @@ -178,6 +179,8 @@ impl DepGraph { R: HashStable<HCX>, { if let Some(ref data) = self.data { + debug_assert!(!data.colors.borrow().contains_key(&key)); + data.edges.borrow_mut().push_task(key); data.current.borrow_mut().push_task(key); if cfg!(debug_assertions) { @@ -212,7 +215,10 @@ impl DepGraph { let prev_fingerprint = data.previous.fingerprint_of(&key); let color = if Some(current_fingerprint) == prev_fingerprint { - DepNodeColor::Green + DepNodeColor::Green(DepNodeIndex { + legacy: dep_node_index_legacy, + new: dep_node_index_new, + }) } else { DepNodeColor::Red }; @@ -310,18 +316,6 @@ impl DepGraph { 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). @@ -426,6 +420,128 @@ impl DepGraph { edge_list_data, } } + + pub fn node_color(&self, dep_node: &DepNode) -> Option<DepNodeColor> { + self.data.as_ref().and_then(|data| data.colors.borrow().get(dep_node).cloned()) + } + + pub fn try_mark_green(&self, + tcx: TyCtxt, + dep_node: &DepNode) + -> Option<DepNodeIndex> { + let data = self.data.as_ref().unwrap(); + + debug_assert!(!data.colors.borrow().contains_key(dep_node)); + debug_assert!(!data.current.borrow().node_to_node_index.contains_key(dep_node)); + + if dep_node.kind.is_input() { + // We should only hit try_mark_green() for inputs that do not exist + // anymore in the current compilation session. Existing inputs are + // eagerly marked as either red/green before any queries are + // executed. + debug_assert!(dep_node.extract_def_id(tcx).is_none()); + return None; + } + + let (prev_deps, prev_dep_node_index) = match data.previous.edges_from(dep_node) { + Some(prev) => { + // This DepNode and the corresponding query invocation existed + // in the previous compilation session too, so we can try to + // mark it as green by recursively marking all of its + // dependencies green. + prev + } + None => { + // This DepNode did not exist in the previous compilation session, + // so we cannot mark it as green. + return None + } + }; + + let mut current_deps = Vec::new(); + + for &dep_dep_node in prev_deps { + let dep_dep_node = &data.previous.index_to_node(dep_dep_node); + let dep_dep_node_color = data.colors.borrow().get(dep_dep_node).cloned(); + match dep_dep_node_color { + Some(DepNodeColor::Green(node_index)) => { + // This dependency has been marked as green before, we are + // still fine and can continue with checking the other + // dependencies. + current_deps.push(node_index); + } + Some(DepNodeColor::Red) => { + // We found a dependency the value of which has changed + // compared to the previous compilation session. We cannot + // mark the DepNode as green and also don't need to bother + // with checking any of the other dependencies. + return None + } + None => { + // We don't know the state of this dependency. Let's try to + // mark it green. + if let Some(node_index) = self.try_mark_green(tcx, dep_dep_node) { + current_deps.push(node_index); + } else { + // We failed to mark it green. This can have various + // reasons. + return None + } + } + } + } + + // If we got here without hitting a `return` that means that all + // dependencies of this DepNode could be marked as green. Therefore we + // can also mark this DepNode as green. We do so by... + + // ... allocating an entry for it in the current dependency graph and + // adding all the appropriate edges imported from the previous graph ... + let node_index_new = data.current + .borrow_mut() + .alloc_node(*dep_node, + current_deps.iter().map(|n| n.new).collect()); + let dep_node_index_legacy = { + let mut legacy_graph = data.edges.borrow_mut(); + legacy_graph.push_task(*dep_node); + for node_index in current_deps.into_iter().map(|n| n.legacy) { + legacy_graph.read_index(node_index); + } + legacy_graph.pop_task(*dep_node) + }; + + // ... copying the fingerprint from the previous graph too, so we don't + // have to recompute it ... + let fingerprint = data.previous.fingerprint_by_index(prev_dep_node_index); + assert!(self.fingerprints + .borrow_mut() + .insert(*dep_node, fingerprint) + .is_none()); + + let node_index = DepNodeIndex { + legacy: dep_node_index_legacy, + new: node_index_new, + }; + + // ... and finally storing a "Green" entry in the color map. + assert!(data.colors + .borrow_mut() + .insert(*dep_node, DepNodeColor::Green(node_index)) + .is_none()); + + Some(node_index) + } + + // Used in various assertions + pub fn is_green(&self, dep_node_index: DepNodeIndex) -> bool { + let dep_node = self.data.as_ref().unwrap().current.borrow().nodes[dep_node_index.new]; + self.data.as_ref().unwrap().colors.borrow().get(&dep_node).map(|&color| { + match color { + DepNodeColor::Red => false, + DepNodeColor::Green(_) => true, + } + }).unwrap_or(false) + } } /// A "work product" is an intermediate result that we save into the diff --git a/src/librustc/dep_graph/mod.rs b/src/librustc/dep_graph/mod.rs index cd77e06bdd6..a8f78336b37 100644 --- a/src/librustc/dep_graph/mod.rs +++ b/src/librustc/dep_graph/mod.rs @@ -21,7 +21,7 @@ mod serialized; pub use self::dep_tracking_map::{DepTrackingMap, DepTrackingMapConfig}; pub use self::dep_node::{DepNode, DepKind, DepConstructor, WorkProductId}; -pub use self::graph::{DepGraph, WorkProduct, DepNodeIndex}; +pub use self::graph::{DepGraph, WorkProduct, DepNodeIndex, DepNodeColor}; pub use self::prev::PreviousDepGraph; pub use self::query::DepGraphQuery; pub use self::safe::AssertDepGraphSafe; diff --git a/src/librustc/dep_graph/prev.rs b/src/librustc/dep_graph/prev.rs index 0236f9c2292..17001bbb0c3 100644 --- a/src/librustc/dep_graph/prev.rs +++ b/src/librustc/dep_graph/prev.rs @@ -28,20 +28,33 @@ impl PreviousDepGraph { PreviousDepGraph { data, index } } - pub fn with_edges_from<F>(&self, dep_node: &DepNode, mut f: F) - where - F: FnMut(&(DepNode, Fingerprint)), - { - let node_index = self.index[dep_node]; - self.data - .edge_targets_from(node_index) - .into_iter() - .for_each(|&index| f(&self.data.nodes[index])); + #[inline] + pub fn edges_from(&self, + dep_node: &DepNode) + -> Option<(&[SerializedDepNodeIndex], SerializedDepNodeIndex)> { + self.index + .get(dep_node) + .map(|&node_index| { + (self.data.edge_targets_from(node_index), node_index) + }) + } + + #[inline] + pub fn index_to_node(&self, dep_node_index: SerializedDepNodeIndex) -> DepNode { + self.data.nodes[dep_node_index].0 } + #[inline] pub fn fingerprint_of(&self, dep_node: &DepNode) -> Option<Fingerprint> { self.index .get(dep_node) .map(|&node_index| self.data.nodes[node_index].1) } + + #[inline] + pub fn fingerprint_by_index(&self, + dep_node_index: SerializedDepNodeIndex) + -> Fingerprint { + self.data.nodes[dep_node_index].1 + } } |
