about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Woerister <michaelwoerister@posteo>2017-08-21 16:44:05 +0200
committerMichael Woerister <michaelwoerister@posteo>2017-09-23 19:47:12 +0200
commitfecd92a7fe0b77adbb7f1a3d43fee436006fa6a5 (patch)
treee499be5d171e170b49f87d2fc2365ff1387490ec
parenta83c3e777145bd2fd127857b3b73d5a174e1f2dd (diff)
downloadrust-fecd92a7fe0b77adbb7f1a3d43fee436006fa6a5.tar.gz
rust-fecd92a7fe0b77adbb7f1a3d43fee436006fa6a5.zip
incr.comp.: Initial implemenation of append-only dep-graph.
-rw-r--r--src/librustc/dep_graph/edges.rs6
-rw-r--r--src/librustc/dep_graph/graph.rs272
-rw-r--r--src/librustc/dep_graph/mod.rs3
-rw-r--r--src/librustc/dep_graph/raii.rs41
-rw-r--r--src/librustc/hir/map/collector.rs9
5 files changed, 287 insertions, 44 deletions
diff --git a/src/librustc/dep_graph/edges.rs b/src/librustc/dep_graph/edges.rs
index 29c0ba66f3f..b12db11cb6a 100644
--- a/src/librustc/dep_graph/edges.rs
+++ b/src/librustc/dep_graph/edges.rs
@@ -17,7 +17,7 @@ use std::mem;
 use super::{DepGraphQuery, DepKind, DepNode};
 use super::debug::EdgeFilter;
 
-pub struct DepGraphEdges {
+pub(super) struct DepGraphEdges {
     nodes: Vec<DepNode>,
     indices: FxHashMap<DepNode, DepNodeIndex>,
     edges: FxHashSet<(DepNodeIndex, DepNodeIndex)>,
@@ -31,8 +31,8 @@ pub struct DepGraphEdges {
 }
 
 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
-pub struct DepNodeIndex {
-    index: u32
+pub(super) struct DepNodeIndex {
+    index: u32,
 }
 
 impl DepNodeIndex {
diff --git a/src/librustc/dep_graph/graph.rs b/src/librustc/dep_graph/graph.rs
index 90a29b63482..b823ea71d14 100644
--- a/src/librustc/dep_graph/graph.rs
+++ b/src/librustc/dep_graph/graph.rs
@@ -8,11 +8,13 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher,
                                            StableHashingContextProvider};
+use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_data_structures::indexed_vec::{Idx, IndexVec};
 use session::config::OutputType;
 use std::cell::{Ref, RefCell};
+use std::hash::Hash;
 use std::rc::Rc;
 use util::common::{ProfileQueriesMsg, profq_msg};
 
@@ -22,7 +24,7 @@ use super::dep_node::{DepNode, DepKind, WorkProductId};
 use super::query::DepGraphQuery;
 use super::raii;
 use super::safe::DepGraphSafe;
-use super::edges::{DepGraphEdges, DepNodeIndex};
+use super::edges::{self, DepGraphEdges};
 
 #[derive(Clone)]
 pub struct DepGraph {
@@ -38,10 +40,34 @@ pub struct DepGraph {
     fingerprints: Rc<RefCell<FxHashMap<DepNode, Fingerprint>>>
 }
 
+/// As a temporary measure, while transitioning to the new DepGraph
+/// implementation, we maintain the old and the new dep-graph encoding in
+/// parallel, so a DepNodeIndex actually contains two indices, one for each
+/// version.
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
+pub struct DepNodeIndex {
+    legacy: edges::DepNodeIndex,
+    new: DepNodeIndexNew,
+}
+
+impl DepNodeIndex {
+    pub const INVALID: DepNodeIndex = DepNodeIndex {
+        legacy: edges::DepNodeIndex::INVALID,
+        new: DepNodeIndexNew::INVALID,
+    };
+}
+
 struct DepGraphData {
-    /// The actual graph data.
+    /// The old, initial encoding of the dependency graph. This will soon go
+    /// away.
     edges: RefCell<DepGraphEdges>,
 
+    /// The new encoding of the dependency graph, optimized for red/green
+    /// tracking. The `current` field is the dependency graph of only the
+    /// current compilation session: We don't merge the previous dep-graph into
+    /// current one anymore.
+    current: RefCell<CurrentDepGraph>,
+
     /// 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
@@ -63,6 +89,7 @@ impl DepGraph {
                     work_products: RefCell::new(FxHashMap()),
                     edges: RefCell::new(DepGraphEdges::new()),
                     dep_node_debug: RefCell::new(FxHashMap()),
+                    current: RefCell::new(CurrentDepGraph::new()),
                 }))
             } else {
                 None
@@ -82,7 +109,8 @@ impl DepGraph {
     }
 
     pub fn in_ignore<'graph>(&'graph self) -> Option<raii::IgnoreTask<'graph>> {
-        self.data.as_ref().map(|data| raii::IgnoreTask::new(&data.edges))
+        self.data.as_ref().map(|data| raii::IgnoreTask::new(&data.edges,
+                                                            &data.current))
     }
 
     pub fn with_ignore<OP,R>(&self, op: OP) -> R
@@ -130,6 +158,7 @@ impl DepGraph {
     {
         if let Some(ref data) = self.data {
             data.edges.borrow_mut().push_task(key);
+            data.current.borrow_mut().push_task(key);
             if cfg!(debug_assertions) {
                 profq_msg(ProfileQueriesMsg::TaskBegin(key.clone()))
             };
@@ -145,7 +174,9 @@ impl DepGraph {
             if cfg!(debug_assertions) {
                 profq_msg(ProfileQueriesMsg::TaskEnd)
             };
-            let dep_node_index = data.edges.borrow_mut().pop_task(key);
+
+            let dep_node_index_legacy = data.edges.borrow_mut().pop_task(key);
+            let dep_node_index_new = data.current.borrow_mut().pop_task(key);
 
             let mut stable_hasher = StableHasher::new();
             result.hash_stable(&mut hcx, &mut stable_hasher);
@@ -155,7 +186,10 @@ impl DepGraph {
                         .insert(key, stable_hasher.finish())
                         .is_none());
 
-            (result, dep_node_index)
+            (result, DepNodeIndex {
+                legacy: dep_node_index_legacy,
+                new: dep_node_index_new,
+            })
         } else {
             if key.kind.fingerprint_needed_for_crate_hash() {
                 let mut hcx = cx.create_stable_hashing_context();
@@ -180,9 +214,14 @@ impl DepGraph {
     {
         if let Some(ref data) = self.data {
             data.edges.borrow_mut().push_anon_task();
+            data.current.borrow_mut().push_anon_task();
             let result = op();
-            let dep_node = data.edges.borrow_mut().pop_anon_task(dep_kind);
-            (result, dep_node)
+            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);
+            (result, DepNodeIndex {
+                legacy: dep_node_index_legacy,
+                new: dep_node_index_new,
+            })
         } else {
             (op(), DepNodeIndex::INVALID)
         }
@@ -192,13 +231,15 @@ impl DepGraph {
     pub fn read(&self, v: DepNode) {
         if let Some(ref data) = self.data {
             data.edges.borrow_mut().read(v);
+            data.current.borrow_mut().read(v);
         }
     }
 
     #[inline]
     pub fn read_index(&self, v: DepNodeIndex) {
         if let Some(ref data) = self.data {
-            data.edges.borrow_mut().read_index(v);
+            data.edges.borrow_mut().read_index(v.legacy);
+            data.current.borrow_mut().read_index(v.new);
         }
     }
 
@@ -215,7 +256,13 @@ impl DepGraph {
 
     pub fn alloc_input_node(&self, node: DepNode) -> DepNodeIndex {
         if let Some(ref data) = self.data {
-            data.edges.borrow_mut().add_node(node)
+            let dep_node_index_legacy = data.edges.borrow_mut().add_node(node);
+            let dep_node_index_new = data.current.borrow_mut()
+                                                 .alloc_node(node, Vec::new());
+            DepNodeIndex {
+                legacy: dep_node_index_legacy,
+                new: dep_node_index_new,
+            }
         } else {
             DepNodeIndex::INVALID
         }
@@ -335,3 +382,208 @@ pub struct WorkProduct {
     /// Saved files associated with this CGU
     pub saved_files: Vec<(OutputType, String)>,
 }
+
+pub(super) struct CurrentDepGraph {
+    nodes: IndexVec<DepNodeIndexNew, DepNode>,
+    edges: IndexVec<DepNodeIndexNew, Vec<DepNodeIndexNew>>,
+    node_to_node_index: FxHashMap<DepNode, DepNodeIndexNew>,
+
+    task_stack: Vec<OpenTask>,
+}
+
+impl CurrentDepGraph {
+    fn new() -> CurrentDepGraph {
+        CurrentDepGraph {
+            nodes: IndexVec::new(),
+            edges: IndexVec::new(),
+            node_to_node_index: FxHashMap(),
+            task_stack: Vec::new(),
+        }
+    }
+
+    pub(super) fn push_ignore(&mut self) {
+        self.task_stack.push(OpenTask::Ignore);
+    }
+
+    pub(super) fn pop_ignore(&mut self) {
+        let popped_node = self.task_stack.pop().unwrap();
+        debug_assert_eq!(popped_node, OpenTask::Ignore);
+    }
+
+    pub(super) fn push_task(&mut self, key: DepNode) {
+        self.task_stack.push(OpenTask::Regular {
+            node: key,
+            reads: Vec::new(),
+            read_set: FxHashSet(),
+        });
+    }
+
+    pub(super) fn pop_task(&mut self, key: DepNode) -> DepNodeIndexNew {
+        let popped_node = self.task_stack.pop().unwrap();
+
+        if let OpenTask::Regular {
+            node,
+            read_set: _,
+            reads
+        } = popped_node {
+            debug_assert_eq!(node, key);
+            self.alloc_node(node, reads)
+        } else {
+            bug!("pop_task() - Expected regular task to be popped")
+        }
+    }
+
+    fn push_anon_task(&mut self) {
+        self.task_stack.push(OpenTask::Anon {
+            reads: Vec::new(),
+            read_set: FxHashSet(),
+        });
+    }
+
+    fn pop_anon_task(&mut self, kind: DepKind) -> DepNodeIndexNew {
+        let popped_node = self.task_stack.pop().unwrap();
+
+        if let OpenTask::Anon {
+            read_set: _,
+            reads
+        } = popped_node {
+            let mut fingerprint = Fingerprint::zero();
+            let mut hasher = StableHasher::new();
+
+            for &read in reads.iter() {
+                let read_dep_node = self.nodes[read];
+
+                ::std::mem::discriminant(&read_dep_node.kind).hash(&mut hasher);
+
+                // Fingerprint::combine() is faster than sending Fingerprint
+                // through the StableHasher (at least as long as StableHasher
+                // is so slow).
+                fingerprint = fingerprint.combine(read_dep_node.hash);
+            }
+
+            fingerprint = fingerprint.combine(hasher.finish());
+
+            let target_dep_node = DepNode {
+                kind,
+                hash: fingerprint,
+            };
+
+            if let Some(&index) = self.node_to_node_index.get(&target_dep_node) {
+                return index;
+            }
+
+            self.alloc_node(target_dep_node, reads)
+        } else {
+            bug!("pop_anon_task() - Expected anonymous task to be popped")
+        }
+    }
+
+    fn read(&mut self, source: DepNode) {
+        let dep_node_index = self.maybe_alloc_node(source);
+        self.read_index(dep_node_index);
+    }
+
+    fn read_index(&mut self, source: DepNodeIndexNew) {
+        match self.task_stack.last_mut() {
+            Some(&mut OpenTask::Regular {
+                ref mut reads,
+                ref mut read_set,
+                node: _,
+            }) => {
+                if read_set.insert(source) {
+                    reads.push(source);
+                }
+            }
+            Some(&mut OpenTask::Anon {
+                ref mut reads,
+                ref mut read_set,
+            }) => {
+                if read_set.insert(source) {
+                    reads.push(source);
+                }
+            }
+            Some(&mut OpenTask::Ignore) | None => {
+                // ignore
+            }
+        }
+    }
+
+    fn alloc_node(&mut self,
+                  dep_node: DepNode,
+                  edges: Vec<DepNodeIndexNew>)
+                  -> DepNodeIndexNew {
+        debug_assert_eq!(self.edges.len(), self.nodes.len());
+        debug_assert_eq!(self.node_to_node_index.len(), self.nodes.len());
+        debug_assert!(!self.node_to_node_index.contains_key(&dep_node));
+        let dep_node_index = DepNodeIndexNew::new(self.nodes.len());
+        self.nodes.push(dep_node);
+        self.node_to_node_index.insert(dep_node, dep_node_index);
+        self.edges.push(edges);
+        dep_node_index
+    }
+
+    fn maybe_alloc_node(&mut self,
+                        dep_node: DepNode)
+                        -> DepNodeIndexNew {
+        debug_assert_eq!(self.edges.len(), self.nodes.len());
+        debug_assert_eq!(self.node_to_node_index.len(), self.nodes.len());
+
+        let CurrentDepGraph {
+            ref mut node_to_node_index,
+            ref mut nodes,
+            ref mut edges,
+            ..
+        } = *self;
+
+        *node_to_node_index.entry(dep_node).or_insert_with(|| {
+            let next_id = nodes.len();
+            nodes.push(dep_node);
+            edges.push(Vec::new());
+            DepNodeIndexNew::new(next_id)
+        })
+    }
+}
+
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
+pub(super) struct DepNodeIndexNew {
+    index: u32,
+}
+
+impl Idx for DepNodeIndexNew {
+    fn new(idx: usize) -> Self {
+        DepNodeIndexNew::new(idx)
+    }
+    fn index(self) -> usize {
+        self.index()
+    }
+}
+
+impl DepNodeIndexNew {
+
+    const INVALID: DepNodeIndexNew = DepNodeIndexNew {
+        index: ::std::u32::MAX,
+    };
+
+    fn new(v: usize) -> DepNodeIndexNew {
+        assert!((v & 0xFFFF_FFFF) == v);
+        DepNodeIndexNew { index: v as u32 }
+    }
+
+    fn index(self) -> usize {
+        self.index as usize
+    }
+}
+
+#[derive(Clone, Debug, PartialEq)]
+enum OpenTask {
+    Regular {
+        node: DepNode,
+        reads: Vec<DepNodeIndexNew>,
+        read_set: FxHashSet<DepNodeIndexNew>,
+    },
+    Anon {
+        reads: Vec<DepNodeIndexNew>,
+        read_set: FxHashSet<DepNodeIndexNew>,
+    },
+    Ignore,
+}
diff --git a/src/librustc/dep_graph/mod.rs b/src/librustc/dep_graph/mod.rs
index ac0c88ced93..1a4c5381abf 100644
--- a/src/librustc/dep_graph/mod.rs
+++ b/src/librustc/dep_graph/mod.rs
@@ -22,10 +22,9 @@ pub use self::dep_node::DepNode;
 pub use self::dep_node::WorkProductId;
 pub use self::graph::DepGraph;
 pub use self::graph::WorkProduct;
-pub use self::edges::DepNodeIndex;
+pub use self::graph::DepNodeIndex;
 pub use self::query::DepGraphQuery;
 pub use self::safe::AssertDepGraphSafe;
 pub use self::safe::DepGraphSafe;
-pub use self::raii::DepTask;
 
 pub use self::dep_node::{DepKind, DepConstructor};
diff --git a/src/librustc/dep_graph/raii.rs b/src/librustc/dep_graph/raii.rs
index ce261ca68e8..6e9e4f4a18b 100644
--- a/src/librustc/dep_graph/raii.rs
+++ b/src/librustc/dep_graph/raii.rs
@@ -8,50 +8,33 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use super::DepNode;
 use super::edges::DepGraphEdges;
+use super::graph::CurrentDepGraph;
 
 use std::cell::RefCell;
 
-pub struct DepTask<'graph> {
-    graph: &'graph RefCell<DepGraphEdges>,
-    key: DepNode,
-}
-
-impl<'graph> DepTask<'graph> {
-    pub fn new(graph: &'graph RefCell<DepGraphEdges>,
-               key: DepNode)
-               -> DepTask<'graph> {
-        graph.borrow_mut().push_task(key);
-        DepTask {
-            graph,
-            key,
-        }
-    }
-}
-
-impl<'graph> Drop for DepTask<'graph> {
-    fn drop(&mut self) {
-        self.graph.borrow_mut().pop_task(self.key);
-    }
-}
-
 pub struct IgnoreTask<'graph> {
-    graph: &'graph RefCell<DepGraphEdges>,
+    legacy_graph: &'graph RefCell<DepGraphEdges>,
+    new_graph: &'graph RefCell<CurrentDepGraph>,
 }
 
 impl<'graph> IgnoreTask<'graph> {
-    pub fn new(graph: &'graph RefCell<DepGraphEdges>) -> IgnoreTask<'graph> {
-        graph.borrow_mut().push_ignore();
+    pub(super) fn new(legacy_graph: &'graph RefCell<DepGraphEdges>,
+                      new_graph: &'graph RefCell<CurrentDepGraph>)
+                      -> IgnoreTask<'graph> {
+        legacy_graph.borrow_mut().push_ignore();
+        new_graph.borrow_mut().push_ignore();
         IgnoreTask {
-            graph
+            legacy_graph,
+            new_graph,
         }
     }
 }
 
 impl<'graph> Drop for IgnoreTask<'graph> {
     fn drop(&mut self) {
-        self.graph.borrow_mut().pop_ignore();
+        self.legacy_graph.borrow_mut().pop_ignore();
+        self.new_graph.borrow_mut().pop_ignore();
     }
 }
 
diff --git a/src/librustc/hir/map/collector.rs b/src/librustc/hir/map/collector.rs
index 51433238f2c..80fadcda277 100644
--- a/src/librustc/hir/map/collector.rs
+++ b/src/librustc/hir/map/collector.rs
@@ -88,6 +88,15 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> {
             ).1;
         }
 
+        {
+            dep_graph.with_task(
+                DepNode::new_no_params(DepKind::AllLocalTraitImpls),
+                &hcx,
+                &krate.trait_impls,
+                identity_fn
+            );
+        }
+
         let hir_body_nodes = vec![root_mod_def_path_hash];
 
         let mut collector = NodeCollector {