about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc/dep_graph/graph.rs128
-rw-r--r--src/librustc/dep_graph/mod.rs13
-rw-r--r--src/librustc/dep_graph/prev.rs46
-rw-r--r--src/librustc/dep_graph/serialized.rs71
-rw-r--r--src/librustc_driver/driver.rs12
-rw-r--r--src/librustc_incremental/lib.rs1
-rw-r--r--src/librustc_incremental/persist/fs.rs5
-rw-r--r--src/librustc_incremental/persist/load.rs35
-rw-r--r--src/librustc_incremental/persist/mod.rs1
-rw-r--r--src/librustc_incremental/persist/save.rs13
-rw-r--r--src/librustc_trans/base.rs3
11 files changed, 264 insertions, 64 deletions
diff --git a/src/librustc/dep_graph/graph.rs b/src/librustc/dep_graph/graph.rs
index b823ea71d14..2ac3884dce1 100644
--- a/src/librustc/dep_graph/graph.rs
+++ b/src/librustc/dep_graph/graph.rs
@@ -25,6 +25,8 @@ use super::query::DepGraphQuery;
 use super::raii;
 use super::safe::DepGraphSafe;
 use super::edges::{self, DepGraphEdges};
+use super::serialized::{SerializedDepGraph, SerializedDepNodeIndex};
+use super::prev::PreviousDepGraph;
 
 #[derive(Clone)]
 pub struct DepGraph {
@@ -68,6 +70,10 @@ struct DepGraphData {
     /// current one anymore.
     current: RefCell<CurrentDepGraph>,
 
+    /// The dep-graph from the previous compilation session. It contains all
+    /// nodes and edges as well as all fingerprints of nodes that have them.
+    previous: PreviousDepGraph,
+
     /// 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
@@ -81,19 +87,24 @@ struct DepGraphData {
 }
 
 impl DepGraph {
-    pub fn new(enabled: bool) -> DepGraph {
+
+    pub fn new(prev_graph: PreviousDepGraph) -> DepGraph {
         DepGraph {
-            data: if enabled {
-                Some(Rc::new(DepGraphData {
-                    previous_work_products: RefCell::new(FxHashMap()),
-                    work_products: RefCell::new(FxHashMap()),
-                    edges: RefCell::new(DepGraphEdges::new()),
-                    dep_node_debug: RefCell::new(FxHashMap()),
-                    current: RefCell::new(CurrentDepGraph::new()),
-                }))
-            } else {
-                None
-            },
+            data: Some(Rc::new(DepGraphData {
+                previous_work_products: RefCell::new(FxHashMap()),
+                work_products: RefCell::new(FxHashMap()),
+                edges: RefCell::new(DepGraphEdges::new()),
+                dep_node_debug: RefCell::new(FxHashMap()),
+                current: RefCell::new(CurrentDepGraph::new()),
+                previous: prev_graph,
+            })),
+            fingerprints: Rc::new(RefCell::new(FxHashMap())),
+        }
+    }
+
+    pub fn new_disabled() -> DepGraph {
+        DepGraph {
+            data: None,
             fingerprints: Rc::new(RefCell::new(FxHashMap())),
         }
     }
@@ -231,7 +242,16 @@ 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);
+
+            let mut current = data.current.borrow_mut();
+            debug_assert!(current.node_to_node_index.contains_key(&v),
+                          "DepKind {:?} should be pre-allocated but isn't.",
+                          v.kind);
+            if let Some(&dep_node_index_new) = current.node_to_node_index.get(&v) {
+                current.read_index(dep_node_index_new);
+            } else {
+                bug!("DepKind {:?} should be pre-allocated but isn't.", v.kind)
+            }
         }
     }
 
@@ -254,22 +274,12 @@ impl DepGraph {
         self.data.as_ref().unwrap().edges.borrow_mut().add_node(node);
     }
 
-    pub fn alloc_input_node(&self, node: DepNode) -> DepNodeIndex {
-        if let Some(ref data) = self.data {
-            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
-        }
+    pub fn fingerprint_of(&self, dep_node: &DepNode) -> Fingerprint {
+        self.fingerprints.borrow()[dep_node]
     }
 
-    pub fn fingerprint_of(&self, dep_node: &DepNode) -> Option<Fingerprint> {
-        self.fingerprints.borrow().get(dep_node).cloned()
+    pub fn prev_fingerprint_of(&self, dep_node: &DepNode) -> Fingerprint {
+        self.data.as_ref().unwrap().previous.fingerprint_of(dep_node)
     }
 
     /// Indicates that a previous work product exists for `v`. This is
@@ -338,6 +348,44 @@ impl DepGraph {
     pub(super) fn dep_node_debug_str(&self, dep_node: DepNode) -> Option<String> {
         self.data.as_ref().and_then(|t| t.dep_node_debug.borrow().get(&dep_node).cloned())
     }
+
+    pub fn serialize(&self) -> SerializedDepGraph {
+        let fingerprints = self.fingerprints.borrow();
+        let current_dep_graph = self.data.as_ref().unwrap().current.borrow();
+
+        let nodes: IndexVec<_, _> = current_dep_graph.nodes.iter().map(|dep_node| {
+            let fingerprint = fingerprints.get(dep_node)
+                                          .cloned()
+                                          .unwrap_or(Fingerprint::zero());
+            (*dep_node, fingerprint)
+        }).collect();
+
+        let total_edge_count: usize = current_dep_graph.edges.iter()
+                                                             .map(|v| v.len())
+                                                             .sum();
+
+        let mut edge_list_indices = IndexVec::with_capacity(nodes.len());
+        let mut edge_list_data = Vec::with_capacity(total_edge_count);
+
+        for (current_dep_node_index, edges) in current_dep_graph.edges.iter_enumerated() {
+            let start = edge_list_data.len() as u32;
+            // This should really just be a memcpy :/
+            edge_list_data.extend(edges.iter().map(|i| SerializedDepNodeIndex(i.index)));
+            let end = edge_list_data.len() as u32;
+
+            debug_assert_eq!(current_dep_node_index.index(), edge_list_indices.len());
+            edge_list_indices.push((start, end));
+        }
+
+        debug_assert!(edge_list_data.len() <= ::std::u32::MAX as usize);
+        debug_assert_eq!(edge_list_data.len(), total_edge_count);
+
+        SerializedDepGraph {
+            nodes,
+            edge_list_indices,
+            edge_list_data,
+        }
+    }
 }
 
 /// A "work product" is an intermediate result that we save into the
@@ -478,11 +526,6 @@ impl CurrentDepGraph {
         }
     }
 
-    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 {
@@ -521,27 +564,6 @@ impl CurrentDepGraph {
         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)]
diff --git a/src/librustc/dep_graph/mod.rs b/src/librustc/dep_graph/mod.rs
index 1a4c5381abf..cd77e06bdd6 100644
--- a/src/librustc/dep_graph/mod.rs
+++ b/src/librustc/dep_graph/mod.rs
@@ -13,18 +13,17 @@ mod dep_node;
 mod dep_tracking_map;
 mod edges;
 mod graph;
+mod prev;
 mod query;
 mod raii;
 mod safe;
+mod serialized;
 
 pub use self::dep_tracking_map::{DepTrackingMap, DepTrackingMapConfig};
-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::graph::DepNodeIndex;
+pub use self::dep_node::{DepNode, DepKind, DepConstructor, WorkProductId};
+pub use self::graph::{DepGraph, WorkProduct, DepNodeIndex};
+pub use self::prev::PreviousDepGraph;
 pub use self::query::DepGraphQuery;
 pub use self::safe::AssertDepGraphSafe;
 pub use self::safe::DepGraphSafe;
-
-pub use self::dep_node::{DepKind, DepConstructor};
+pub use self::serialized::SerializedDepGraph;
diff --git a/src/librustc/dep_graph/prev.rs b/src/librustc/dep_graph/prev.rs
new file mode 100644
index 00000000000..882ca0414cc
--- /dev/null
+++ b/src/librustc/dep_graph/prev.rs
@@ -0,0 +1,46 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use ich::Fingerprint;
+use rustc_data_structures::fx::FxHashMap;
+use super::dep_node::DepNode;
+use super::serialized::{SerializedDepGraph, SerializedDepNodeIndex};
+
+#[derive(Debug, RustcEncodable, RustcDecodable)]
+pub struct PreviousDepGraph {
+    data: SerializedDepGraph,
+    index: FxHashMap<DepNode, SerializedDepNodeIndex>,
+}
+
+impl PreviousDepGraph {
+    pub fn new(data: SerializedDepGraph) -> PreviousDepGraph {
+        let index: FxHashMap<_, _> = data.nodes
+            .iter_enumerated()
+            .map(|(idx, &(dep_node, _))| (dep_node, idx))
+            .collect();
+        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]));
+    }
+
+    pub fn fingerprint_of(&self, dep_node: &DepNode) -> Fingerprint {
+        let node_index = self.index[dep_node];
+        self.data.nodes[node_index].1
+    }
+}
diff --git a/src/librustc/dep_graph/serialized.rs b/src/librustc/dep_graph/serialized.rs
new file mode 100644
index 00000000000..21beac9214e
--- /dev/null
+++ b/src/librustc/dep_graph/serialized.rs
@@ -0,0 +1,71 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! The data that we will serialize and deserialize.
+
+use dep_graph::DepNode;
+use ich::Fingerprint;
+use rustc_data_structures::indexed_vec::{IndexVec, Idx};
+
+/// The index of a DepNode in the SerializedDepGraph::nodes array.
+#[derive(Copy, Clone, Hash, Eq, PartialEq, Ord, PartialOrd, Debug,
+         RustcEncodable, RustcDecodable)]
+pub struct SerializedDepNodeIndex(pub u32);
+
+impl SerializedDepNodeIndex {
+    #[inline]
+    pub fn new(idx: usize) -> SerializedDepNodeIndex {
+        assert!(idx <= ::std::u32::MAX as usize);
+        SerializedDepNodeIndex(idx as u32)
+    }
+}
+
+impl Idx for SerializedDepNodeIndex {
+    #[inline]
+    fn new(idx: usize) -> Self {
+        assert!(idx <= ::std::u32::MAX as usize);
+        SerializedDepNodeIndex(idx as u32)
+    }
+
+    #[inline]
+    fn index(self) -> usize {
+        self.0 as usize
+    }
+}
+
+/// Data for use when recompiling the **current crate**.
+#[derive(Debug, RustcEncodable, RustcDecodable)]
+pub struct SerializedDepGraph {
+    /// The set of all DepNodes in the graph
+    pub nodes: IndexVec<SerializedDepNodeIndex, (DepNode, Fingerprint)>,
+    /// For each DepNode, stores the list of edges originating from that
+    /// DepNode. Encoded as a [start, end) pair indexing into edge_list_data,
+    /// which holds the actual DepNodeIndices of the target nodes.
+    pub edge_list_indices: IndexVec<SerializedDepNodeIndex, (u32, u32)>,
+    /// A flattened list of all edge targets in the graph. Edge sources are
+    /// implicit in edge_list_indices.
+    pub edge_list_data: Vec<SerializedDepNodeIndex>,
+}
+
+impl SerializedDepGraph {
+
+    pub fn new() -> SerializedDepGraph {
+        SerializedDepGraph {
+            nodes: IndexVec::new(),
+            edge_list_indices: IndexVec::new(),
+            edge_list_data: Vec::new(),
+        }
+    }
+
+    pub fn edge_targets_from(&self, source: SerializedDepNodeIndex) -> &[SerializedDepNodeIndex] {
+        let targets = self.edge_list_indices[source];
+        &self.edge_list_data[targets.0 as usize..targets.1 as usize]
+    }
+}
diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs
index ce4ab2c8a1d..bcfbc1980cf 100644
--- a/src/librustc_driver/driver.rs
+++ b/src/librustc_driver/driver.rs
@@ -643,7 +643,16 @@ pub fn phase_2_configure_and_expand<F>(sess: &Session,
         &crate_name,
         &disambiguator.as_str(),
     );
-    let dep_graph = DepGraph::new(sess.opts.build_dep_graph());
+
+    let dep_graph = if sess.opts.build_dep_graph() {
+        let prev_dep_graph = time(time_passes, "load prev dep-graph (new)", || {
+            rustc_incremental::load_dep_graph_new(sess)
+        });
+
+        DepGraph::new(prev_dep_graph)
+    } else {
+        DepGraph::new_disabled()
+    };
 
     time(time_passes, "recursion limit", || {
         middle::recursion_limit::update_limits(sess, &krate);
@@ -713,7 +722,6 @@ pub fn phase_2_configure_and_expand<F>(sess: &Session,
     // item, much like we do for macro expansion. In other words, the hash reflects not just
     // its contents but the results of name resolution on those contents. Hopefully we'll push
     // this back at some point.
-    let _ignore = dep_graph.in_ignore();
     let mut crate_loader = CrateLoader::new(sess, &cstore, crate_name);
     let resolver_arenas = Resolver::arenas();
     let mut resolver = Resolver::new(sess,
diff --git a/src/librustc_incremental/lib.rs b/src/librustc_incremental/lib.rs
index 6817856fdb1..0fba6d8e9c6 100644
--- a/src/librustc_incremental/lib.rs
+++ b/src/librustc_incremental/lib.rs
@@ -32,6 +32,7 @@ mod persist;
 
 pub use assert_dep_graph::assert_dep_graph;
 pub use persist::load_dep_graph;
+pub use persist::load_dep_graph_new;
 pub use persist::save_dep_graph;
 pub use persist::save_trans_partition;
 pub use persist::save_work_products;
diff --git a/src/librustc_incremental/persist/fs.rs b/src/librustc_incremental/persist/fs.rs
index f3f35a50fe0..ccd2fdb6089 100644
--- a/src/librustc_incremental/persist/fs.rs
+++ b/src/librustc_incremental/persist/fs.rs
@@ -132,6 +132,7 @@ use std::__rand::{thread_rng, Rng};
 
 const LOCK_FILE_EXT: &'static str = ".lock";
 const DEP_GRAPH_FILENAME: &'static str = "dep-graph.bin";
+const DEP_GRAPH_NEW_FILENAME: &'static str = "dep-graph-new.bin";
 const WORK_PRODUCTS_FILENAME: &'static str = "work-products.bin";
 const METADATA_HASHES_FILENAME: &'static str = "metadata.bin";
 
@@ -145,6 +146,10 @@ pub fn dep_graph_path(sess: &Session) -> PathBuf {
     in_incr_comp_dir_sess(sess, DEP_GRAPH_FILENAME)
 }
 
+pub fn dep_graph_path_new(sess: &Session) -> PathBuf {
+    in_incr_comp_dir_sess(sess, DEP_GRAPH_NEW_FILENAME)
+}
+
 pub fn work_products_path(sess: &Session) -> PathBuf {
     in_incr_comp_dir_sess(sess, WORK_PRODUCTS_FILENAME)
 }
diff --git a/src/librustc_incremental/persist/load.rs b/src/librustc_incremental/persist/load.rs
index 0d6257e4245..9e2036c522f 100644
--- a/src/librustc_incremental/persist/load.rs
+++ b/src/librustc_incremental/persist/load.rs
@@ -433,3 +433,38 @@ fn process_edge<'a, 'tcx, 'edges>(
         }
     }
 }
+
+pub fn load_dep_graph_new(sess: &Session) -> PreviousDepGraph {
+    use rustc::dep_graph::SerializedDepGraph as SerializedDepGraphNew;
+
+    let empty = PreviousDepGraph::new(SerializedDepGraphNew::new());
+
+    if sess.opts.incremental.is_none() {
+        return empty
+    }
+
+    if let Some(bytes) = load_data(sess, &dep_graph_path_new(sess)) {
+        let mut decoder = Decoder::new(&bytes, 0);
+        let prev_commandline_args_hash = u64::decode(&mut decoder)
+            .expect("Error reading commandline arg hash from cached dep-graph");
+
+        if prev_commandline_args_hash != sess.opts.dep_tracking_hash() {
+            if sess.opts.debugging_opts.incremental_info {
+                eprintln!("incremental: completely ignoring cache because of \
+                           differing commandline arguments");
+            }
+            // We can't reuse the cache, purge it.
+            debug!("load_dep_graph_new: differing commandline arg hashes");
+
+            // No need to do any further work
+            return empty
+        }
+
+        let dep_graph = SerializedDepGraphNew::decode(&mut decoder)
+            .expect("Error reading cached dep-graph");
+
+        PreviousDepGraph::new(dep_graph)
+    } else {
+        empty
+    }
+}
diff --git a/src/librustc_incremental/persist/mod.rs b/src/librustc_incremental/persist/mod.rs
index fb330813226..6514cb8555a 100644
--- a/src/librustc_incremental/persist/mod.rs
+++ b/src/librustc_incremental/persist/mod.rs
@@ -26,6 +26,7 @@ pub use self::fs::prepare_session_directory;
 pub use self::fs::finalize_session_directory;
 pub use self::fs::in_incr_comp_dir;
 pub use self::load::load_dep_graph;
+pub use self::load::load_dep_graph_new;
 pub use self::save::save_dep_graph;
 pub use self::save::save_work_products;
 pub use self::work_product::save_trans_partition;
diff --git a/src/librustc_incremental/persist/save.rs b/src/librustc_incremental/persist/save.rs
index e2d03fcb0e1..bc8cfd7da35 100644
--- a/src/librustc_incremental/persist/save.rs
+++ b/src/librustc_incremental/persist/save.rs
@@ -174,6 +174,19 @@ fn save_in<F>(sess: &Session, path_buf: PathBuf, encode: F)
     }
 }
 
+fn encode_dep_graph_new(tcx: TyCtxt,
+                        encoder: &mut Encoder)
+                        -> io::Result<()> {
+    // First encode the commandline arguments hash
+    tcx.sess.opts.dep_tracking_hash().encode(encoder)?;
+
+    // Encode the graph data.
+    let serialized_graph = tcx.dep_graph.serialize();
+    serialized_graph.encode(encoder)?;
+
+    Ok(())
+}
+
 pub fn encode_dep_graph(tcx: TyCtxt,
                         preds: &Predecessors,
                         encoder: &mut Encoder)
diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs
index bfa18d84d27..74d610d1d12 100644
--- a/src/librustc_trans/base.rs
+++ b/src/librustc_trans/base.rs
@@ -942,8 +942,7 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
 
     let crate_hash = tcx.dep_graph
-                        .fingerprint_of(&DepNode::new_no_params(DepKind::Krate))
-                        .unwrap();
+                        .fingerprint_of(&DepNode::new_no_params(DepKind::Krate));
     let link_meta = link::build_link_meta(crate_hash);
     let exported_symbol_node_ids = find_exported_symbols(tcx);