about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Woerister <michaelwoerister@posteo>2017-12-19 18:01:19 +0100
committerMichael Woerister <michaelwoerister@posteo>2017-12-20 11:14:31 +0100
commite6e5589db4c835c00df96714894ad150f8963fd6 (patch)
treea3ee5a73d963584357bd374d86cce16f96628c6f
parentb39c4bc12358078f77ddd01288b24252f757f37d (diff)
downloadrust-e6e5589db4c835c00df96714894ad150f8963fd6.tar.gz
rust-e6e5589db4c835c00df96714894ad150f8963fd6.zip
incr.comp.: Use an IndexVec instead of a hashmap for storing result hashes.
-rw-r--r--src/librustc/dep_graph/graph.rs110
-rw-r--r--src/librustc/dep_graph/prev.rs4
-rw-r--r--src/librustc/hir/map/collector.rs34
-rw-r--r--src/librustc/hir/map/mod.rs7
-rw-r--r--src/librustc/ty/maps/plumbing.rs4
-rw-r--r--src/librustc/ty/mod.rs9
-rw-r--r--src/librustc_incremental/persist/dirty_clean.rs6
-rw-r--r--src/librustc_trans/base.rs5
-rw-r--r--src/librustc_trans_utils/link.rs5
-rw-r--r--src/librustc_trans_utils/trans_crate.rs6
10 files changed, 124 insertions, 66 deletions
diff --git a/src/librustc/dep_graph/graph.rs b/src/librustc/dep_graph/graph.rs
index 96d6b0f79cf..5fa0cedfe74 100644
--- a/src/librustc/dep_graph/graph.rs
+++ b/src/librustc/dep_graph/graph.rs
@@ -34,14 +34,11 @@ use super::prev::PreviousDepGraph;
 pub struct DepGraph {
     data: Option<Rc<DepGraphData>>,
 
-    // At the moment we are using DepNode as key here. In the future it might
-    // be possible to use an IndexVec<DepNodeIndex, _> here. At the moment there
-    // are a few problems with that:
-    // - Some fingerprints are needed even if incr. comp. is disabled -- yet
-    //   we need to have a dep-graph to generate DepNodeIndices.
-    // - The architecture is still in flux and it's not clear what how to best
-    //   implement things.
-    fingerprints: Rc<RefCell<FxHashMap<DepNode, Fingerprint>>>
+    // A vector mapping depnodes from the current graph to their associated
+    // result value fingerprints. Do not rely on the length of this vector
+    // being the same as the number of nodes in the graph. The vector can
+    // contain an arbitrary number of zero-entries at the end.
+    fingerprints: Rc<RefCell<IndexVec<DepNodeIndex, Fingerprint>>>
 }
 
 
@@ -97,6 +94,11 @@ struct DepGraphData {
 impl DepGraph {
 
     pub fn new(prev_graph: PreviousDepGraph) -> DepGraph {
+        // Pre-allocate the fingerprints array. We over-allocate a little so
+        // that we hopefully don't have to re-allocate during this compilation
+        // session.
+        let fingerprints = IndexVec::from_elem_n(Fingerprint::zero(),
+                                                 (prev_graph.node_count() * 115) / 100);
         DepGraph {
             data: Some(Rc::new(DepGraphData {
                 previous_work_products: RefCell::new(FxHashMap()),
@@ -107,14 +109,14 @@ impl DepGraph {
                 colors: RefCell::new(FxHashMap()),
                 loaded_from_cache: RefCell::new(FxHashMap()),
             })),
-            fingerprints: Rc::new(RefCell::new(FxHashMap())),
+            fingerprints: Rc::new(RefCell::new(fingerprints)),
         }
     }
 
     pub fn new_disabled() -> DepGraph {
         DepGraph {
             data: None,
-            fingerprints: Rc::new(RefCell::new(FxHashMap())),
+            fingerprints: Rc::new(RefCell::new(IndexVec::new())),
         }
     }
 
@@ -231,12 +233,16 @@ impl DepGraph {
 
             // Store the current fingerprint
             {
-                let old_value = self.fingerprints
-                                    .borrow_mut()
-                                    .insert(key, current_fingerprint);
-                debug_assert!(old_value.is_none(),
+                let mut fingerprints = self.fingerprints.borrow_mut();
+
+                if dep_node_index.index() >= fingerprints.len() {
+                    fingerprints.resize(dep_node_index.index() + 1, Fingerprint::zero());
+                }
+
+                debug_assert!(fingerprints[dep_node_index] == Fingerprint::zero(),
                               "DepGraph::with_task() - Duplicate fingerprint \
                                insertion for {:?}", key);
+                fingerprints[dep_node_index] = current_fingerprint;
             }
 
             // Determine the color of the new DepNode.
@@ -262,13 +268,15 @@ impl DepGraph {
                 let result = task(cx, arg);
                 let mut stable_hasher = StableHasher::new();
                 result.hash_stable(&mut hcx, &mut stable_hasher);
-                let old_value = self.fingerprints
-                                    .borrow_mut()
-                                    .insert(key, stable_hasher.finish());
-                debug_assert!(old_value.is_none(),
-                              "DepGraph::with_task() - Duplicate fingerprint \
-                               insertion for {:?}", key);
-                (result, DepNodeIndex::INVALID)
+                let fingerprint = stable_hasher.finish();
+
+                let mut fingerprints = self.fingerprints.borrow_mut();
+                let dep_node_index = DepNodeIndex::new(fingerprints.len());
+                fingerprints.push(fingerprint);
+                debug_assert!(fingerprints[dep_node_index] == fingerprint,
+                              "DepGraph::with_task() - Assigned fingerprint to \
+                               unexpected index for {:?}", key);
+                (result, dep_node_index)
             } else {
                 (task(cx, arg), DepNodeIndex::INVALID)
             }
@@ -328,11 +336,29 @@ impl DepGraph {
     }
 
     #[inline]
-    pub fn fingerprint_of(&self, dep_node: &DepNode) -> Fingerprint {
-        match self.fingerprints.borrow().get(dep_node) {
+    pub fn dep_node_index_of(&self, dep_node: &DepNode) -> DepNodeIndex {
+        self.data
+            .as_ref()
+            .unwrap()
+            .current
+            .borrow_mut()
+            .node_to_node_index
+            .get(dep_node)
+            .cloned()
+            .unwrap()
+    }
+
+    #[inline]
+    pub fn fingerprint_of(&self, dep_node_index: DepNodeIndex) -> Fingerprint {
+        match self.fingerprints.borrow().get(dep_node_index) {
             Some(&fingerprint) => fingerprint,
             None => {
-                bug!("Could not find current fingerprint for {:?}", dep_node)
+                if let Some(ref data) = self.data {
+                    let dep_node = data.current.borrow().nodes[dep_node_index];
+                    bug!("Could not find current fingerprint for {:?}", dep_node)
+                } else {
+                    bug!("Could not find current fingerprint for {:?}", dep_node_index)
+                }
             }
         }
     }
@@ -420,14 +446,17 @@ impl DepGraph {
     }
 
     pub fn serialize(&self) -> SerializedDepGraph {
-        let fingerprints = self.fingerprints.borrow();
+        let mut fingerprints = self.fingerprints.borrow_mut();
         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)
+        // Make sure we don't run out of bounds below.
+        if current_dep_graph.nodes.len() > fingerprints.len() {
+            fingerprints.resize(current_dep_graph.nodes.len(), Fingerprint::zero());
+        }
+
+        let nodes: IndexVec<_, (DepNode, Fingerprint)> =
+            current_dep_graph.nodes.iter_enumerated().map(|(idx, &dep_node)| {
+            (dep_node, fingerprints[idx])
         }).collect();
 
         let total_edge_count: usize = current_dep_graph.edges.iter()
@@ -610,13 +639,20 @@ impl DepGraph {
 
         // ... 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);
-        let old_fingerprint = self.fingerprints
-                                  .borrow_mut()
-                                  .insert(*dep_node, fingerprint);
-        debug_assert!(old_fingerprint.is_none(),
-                      "DepGraph::try_mark_green() - Duplicate fingerprint \
-                      insertion for {:?}", dep_node);
+        {
+            let fingerprint = data.previous.fingerprint_by_index(prev_dep_node_index);
+            let mut fingerprints = self.fingerprints.borrow_mut();
+
+            if dep_node_index.index() >= fingerprints.len() {
+                fingerprints.resize(dep_node_index.index() + 1, Fingerprint::zero());
+            }
+
+            debug_assert!(fingerprints[dep_node_index] == Fingerprint::zero(),
+                "DepGraph::try_mark_green() - Duplicate fingerprint \
+                insertion for {:?}", dep_node);
+
+            fingerprints[dep_node_index] = fingerprint;
+        }
 
         // ... emitting any stored diagnostic ...
         {
diff --git a/src/librustc/dep_graph/prev.rs b/src/librustc/dep_graph/prev.rs
index 6c43b5c5ff1..50e1ee88a46 100644
--- a/src/librustc/dep_graph/prev.rs
+++ b/src/librustc/dep_graph/prev.rs
@@ -62,4 +62,8 @@ impl PreviousDepGraph {
                                 -> Fingerprint {
         self.data.nodes[dep_node_index].1
     }
+
+    pub fn node_count(&self) -> usize {
+        self.index.len()
+    }
 }
diff --git a/src/librustc/hir/map/collector.rs b/src/librustc/hir/map/collector.rs
index 02a1e33eeb9..68b103111ca 100644
--- a/src/librustc/hir/map/collector.rs
+++ b/src/librustc/hir/map/collector.rs
@@ -12,6 +12,7 @@ use super::*;
 
 use dep_graph::{DepGraph, DepKind, DepNodeIndex};
 use hir::intravisit::{Visitor, NestedVisitorMap};
+use hir::svh::Svh;
 use middle::cstore::CrateStore;
 use session::CrateDisambiguator;
 use std::iter::repeat;
@@ -44,7 +45,7 @@ pub(super) struct NodeCollector<'a, 'hir> {
 
     // We are collecting DepNode::HirBody hashes here so we can compute the
     // crate hash from then later on.
-    hir_body_nodes: Vec<DefPathHash>,
+    hir_body_nodes: Vec<(DefPathHash, DepNodeIndex)>,
 }
 
 impl<'a, 'hir> NodeCollector<'a, 'hir> {
@@ -99,7 +100,7 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> {
             );
         }
 
-        let hir_body_nodes = vec![root_mod_def_path_hash];
+        let hir_body_nodes = vec![(root_mod_def_path_hash, root_mod_full_dep_index)];
 
         let mut collector = NodeCollector {
             krate,
@@ -123,13 +124,12 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> {
                                                   crate_disambiguator: CrateDisambiguator,
                                                   cstore: &CrateStore,
                                                   commandline_args_hash: u64)
-                                                  -> Vec<MapEntry<'hir>> {
+                                                  -> (Vec<MapEntry<'hir>>, Svh) {
         let mut node_hashes: Vec<_> = self
             .hir_body_nodes
             .iter()
-            .map(|&def_path_hash| {
-                let dep_node = def_path_hash.to_dep_node(DepKind::HirBody);
-                (def_path_hash, self.dep_graph.fingerprint_of(&dep_node))
+            .map(|&(def_path_hash, dep_node_index)| {
+                (def_path_hash, self.dep_graph.fingerprint_of(dep_node_index))
             })
             .collect();
 
@@ -147,13 +147,19 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> {
             (name1, dis1).cmp(&(name2, dis2))
         });
 
-        self.dep_graph.with_task(DepNode::new_no_params(DepKind::Krate),
-                                 &self.hcx,
-                                 ((node_hashes, upstream_crates),
-                                  (commandline_args_hash,
-                                   crate_disambiguator.to_fingerprint())),
-                                 identity_fn);
-        self.map
+        let (_, crate_dep_node_index) = self
+            .dep_graph
+            .with_task(DepNode::new_no_params(DepKind::Krate),
+                       &self.hcx,
+                       ((node_hashes, upstream_crates),
+                        (commandline_args_hash,
+                         crate_disambiguator.to_fingerprint())),
+                       identity_fn);
+
+        let svh = Svh::new(self.dep_graph
+                               .fingerprint_of(crate_dep_node_index)
+                               .to_smaller_hash());
+        (self.map, svh)
     }
 
     fn insert_entry(&mut self, id: NodeId, entry: MapEntry<'hir>) {
@@ -255,7 +261,7 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> {
             identity_fn
         ).1;
 
-        self.hir_body_nodes.push(def_path_hash);
+        self.hir_body_nodes.push((def_path_hash, self.current_full_dep_index));
 
         self.current_dep_node_owner = dep_node_owner;
         self.currently_in_body = false;
diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs
index 014e5771656..33debf6aeb0 100644
--- a/src/librustc/hir/map/mod.rs
+++ b/src/librustc/hir/map/mod.rs
@@ -26,6 +26,7 @@ use syntax_pos::Span;
 
 use hir::*;
 use hir::print::Nested;
+use hir::svh::Svh;
 use util::nodemap::{DefIdMap, FxHashMap};
 
 use arena::TypedArena;
@@ -241,6 +242,9 @@ pub struct Map<'hir> {
     /// deref. This is a gratuitous micro-optimization.
     pub dep_graph: DepGraph,
 
+    /// The SVH of the local crate.
+    pub crate_hash: Svh,
+
     /// NodeIds are sequential integers from 0, so we can be
     /// super-compact by storing them in a vector. Not everything with
     /// a NodeId is in the map, but empirically the occupancy is about
@@ -1048,7 +1052,7 @@ pub fn map_crate<'hir>(sess: &::session::Session,
                        forest: &'hir mut Forest,
                        definitions: &'hir Definitions)
                        -> Map<'hir> {
-    let map = {
+    let (map, crate_hash) = {
         let hcx = ::ich::StableHashingContext::new(sess, &forest.krate, definitions, cstore);
 
         let mut collector = NodeCollector::root(&forest.krate,
@@ -1087,6 +1091,7 @@ pub fn map_crate<'hir>(sess: &::session::Session,
     let map = Map {
         forest,
         dep_graph: forest.dep_graph.clone(),
+        crate_hash,
         map,
         hir_to_node_id,
         definitions,
diff --git a/src/librustc/ty/maps/plumbing.rs b/src/librustc/ty/maps/plumbing.rs
index 8875439be6b..5d7a050267f 100644
--- a/src/librustc/ty/maps/plumbing.rs
+++ b/src/librustc/ty/maps/plumbing.rs
@@ -438,7 +438,7 @@ macro_rules! define_maps {
                     use rustc_data_structures::stable_hasher::{StableHasher, HashStable};
                     use ich::Fingerprint;
 
-                    assert!(Some(tcx.dep_graph.fingerprint_of(dep_node)) ==
+                    assert!(Some(tcx.dep_graph.fingerprint_of(dep_node_index)) ==
                             tcx.dep_graph.prev_fingerprint_of(dep_node),
                             "Fingerprint for green query instance not loaded \
                              from cache: {:?}", dep_node);
@@ -452,7 +452,7 @@ macro_rules! define_maps {
                     let new_hash: Fingerprint = hasher.finish();
                     debug!("END verify_ich({:?})", dep_node);
 
-                    let old_hash = tcx.dep_graph.fingerprint_of(dep_node);
+                    let old_hash = tcx.dep_graph.fingerprint_of(dep_node_index);
 
                     assert!(new_hash == old_hash, "Found unstable fingerprints \
                         for {:?}", dep_node);
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index 220e1e971ac..815f89a408e 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -19,6 +19,7 @@ use hir::{map as hir_map, FreevarMap, TraitMap};
 use hir::def::{Def, CtorKind, ExportMap};
 use hir::def_id::{CrateNum, DefId, DefIndex, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE};
 use hir::map::DefPathData;
+use hir::svh::Svh;
 use ich::StableHashingContext;
 use middle::const_val::ConstVal;
 use middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem, FnOnceTraitLangItem};
@@ -2659,6 +2660,13 @@ fn original_crate_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     tcx.crate_name.clone()
 }
 
+fn crate_hash<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                        crate_num: CrateNum)
+                        -> Svh {
+    assert_eq!(crate_num, LOCAL_CRATE);
+    tcx.hir.crate_hash
+}
+
 pub fn provide(providers: &mut ty::maps::Providers) {
     context::provide(providers);
     erase_regions::provide(providers);
@@ -2674,6 +2682,7 @@ pub fn provide(providers: &mut ty::maps::Providers) {
         trait_of_item,
         crate_disambiguator,
         original_crate_name,
+        crate_hash,
         trait_impls_of: trait_def::trait_impls_of_provider,
         ..*providers
     };
diff --git a/src/librustc_incremental/persist/dirty_clean.rs b/src/librustc_incremental/persist/dirty_clean.rs
index 7c3f903f228..b17503137f5 100644
--- a/src/librustc_incremental/persist/dirty_clean.rs
+++ b/src/librustc_incremental/persist/dirty_clean.rs
@@ -480,7 +480,8 @@ impl<'a, 'tcx> DirtyCleanVisitor<'a, 'tcx> {
     fn assert_dirty(&self, item_span: Span, dep_node: DepNode) {
         debug!("assert_dirty({:?})", dep_node);
 
-        let current_fingerprint = self.tcx.dep_graph.fingerprint_of(&dep_node);
+        let dep_node_index = self.tcx.dep_graph.dep_node_index_of(&dep_node);
+        let current_fingerprint = self.tcx.dep_graph.fingerprint_of(dep_node_index);
         let prev_fingerprint = self.tcx.dep_graph.prev_fingerprint_of(&dep_node);
 
         if Some(current_fingerprint) == prev_fingerprint {
@@ -494,7 +495,8 @@ impl<'a, 'tcx> DirtyCleanVisitor<'a, 'tcx> {
     fn assert_clean(&self, item_span: Span, dep_node: DepNode) {
         debug!("assert_clean({:?})", dep_node);
 
-        let current_fingerprint = self.tcx.dep_graph.fingerprint_of(&dep_node);
+        let dep_node_index = self.tcx.dep_graph.dep_node_index_of(&dep_node);
+        let current_fingerprint = self.tcx.dep_graph.fingerprint_of(dep_node_index);
         let prev_fingerprint = self.tcx.dep_graph.prev_fingerprint_of(&dep_node);
 
         if Some(current_fingerprint) != prev_fingerprint {
diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs
index 79b3d314e12..5b2ca29ac40 100644
--- a/src/librustc_trans/base.rs
+++ b/src/librustc_trans/base.rs
@@ -43,7 +43,7 @@ use rustc::middle::cstore::{EncodedMetadata};
 use rustc::ty::{self, Ty, TyCtxt};
 use rustc::ty::layout::{self, Align, TyLayout, LayoutOf};
 use rustc::ty::maps::Providers;
-use rustc::dep_graph::{DepNode, DepKind, DepConstructor};
+use rustc::dep_graph::{DepNode, DepConstructor};
 use rustc::middle::cstore::{self, LinkMeta, LinkagePreference};
 use rustc::util::common::{time, print_time_passes_entry};
 use rustc::session::config::{self, NoDebugInfo};
@@ -709,8 +709,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));
+    let crate_hash = tcx.crate_hash(LOCAL_CRATE);
     let link_meta = link::build_link_meta(crate_hash);
     let exported_symbol_node_ids = find_exported_symbols(tcx);
 
diff --git a/src/librustc_trans_utils/link.rs b/src/librustc_trans_utils/link.rs
index c1e670cc7ca..643494e411d 100644
--- a/src/librustc_trans_utils/link.rs
+++ b/src/librustc_trans_utils/link.rs
@@ -8,7 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use rustc::ich::Fingerprint;
 use rustc::session::config::{self, OutputFilenames, Input, OutputType};
 use rustc::session::Session;
 use rustc::middle::cstore::{self, LinkMeta};
@@ -50,9 +49,9 @@ fn is_writeable(p: &Path) -> bool {
     }
 }
 
-pub fn build_link_meta(crate_hash: Fingerprint) -> LinkMeta {
+pub fn build_link_meta(crate_hash: Svh) -> LinkMeta {
     let r = LinkMeta {
-        crate_hash: Svh::new(crate_hash.to_smaller_hash()),
+        crate_hash,
     };
     info!("{:?}", r);
     return r;
diff --git a/src/librustc_trans_utils/trans_crate.rs b/src/librustc_trans_utils/trans_crate.rs
index 800c3063c02..122914fa40b 100644
--- a/src/librustc_trans_utils/trans_crate.rs
+++ b/src/librustc_trans_utils/trans_crate.rs
@@ -41,7 +41,7 @@ use rustc::ty::TyCtxt;
 use rustc::ty::maps::Providers;
 use rustc::middle::cstore::EncodedMetadata;
 use rustc::middle::cstore::MetadataLoader as MetadataLoaderTrait;
-use rustc::dep_graph::{DepGraph, DepNode, DepKind};
+use rustc::dep_graph::DepGraph;
 use rustc_back::target::Target;
 use link::{build_link_meta, out_filename};
 
@@ -197,9 +197,7 @@ impl TransCrate for MetadataOnlyTransCrate {
         let _ = tcx.native_libraries(LOCAL_CRATE);
         tcx.sess.abort_if_errors();
 
-        let crate_hash = tcx.dep_graph
-                        .fingerprint_of(&DepNode::new_no_params(DepKind::Krate));
-        let link_meta = build_link_meta(crate_hash);
+        let link_meta = build_link_meta(tcx.crate_hash(LOCAL_CRATE));
         let exported_symbols = ::find_exported_symbols(tcx);
         let metadata = tcx.encode_metadata(&link_meta, &exported_symbols);