Skip to content

incr.comp.: Use an array instead of a hashmap for storing result hashes. #46842

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Dec 23, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/librustc/dep_graph/dep_node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,7 @@ macro_rules! define_dep_nodes {

DepNode {
kind: DepKind::$variant,
hash: Fingerprint::zero(),
hash: Fingerprint::ZERO,
}
}
)*
Expand Down Expand Up @@ -308,7 +308,7 @@ macro_rules! define_dep_nodes {
assert!(!kind.has_params());
DepNode {
kind,
hash: Fingerprint::zero(),
hash: Fingerprint::ZERO,
}
}

Expand Down
110 changes: 73 additions & 37 deletions src/librustc/dep_graph/graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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>>>
}


Expand Down Expand Up @@ -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()),
Expand All @@ -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())),
}
}

Expand Down Expand Up @@ -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.
Expand All @@ -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)
}
Expand Down Expand Up @@ -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)
}
}
}
}
Expand Down Expand Up @@ -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()
Expand Down Expand Up @@ -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 ...
{
Expand Down
4 changes: 4 additions & 0 deletions src/librustc/dep_graph/prev.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,4 +62,8 @@ impl PreviousDepGraph {
-> Fingerprint {
self.data.nodes[dep_node_index].1
}

pub fn node_count(&self) -> usize {
self.index.len()
}
}
34 changes: 20 additions & 14 deletions src/librustc/hir/map/collector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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> {
Expand Down Expand Up @@ -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,
Expand All @@ -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();

Expand All @@ -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>) {
Expand Down Expand Up @@ -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;
Expand Down
7 changes: 6 additions & 1 deletion src/librustc/hir/map/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down
6 changes: 2 additions & 4 deletions src/librustc/ich/fingerprint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,8 @@ use rustc_data_structures::stable_hasher;
pub struct Fingerprint(u64, u64);

impl Fingerprint {
#[inline]
pub fn zero() -> Fingerprint {
Fingerprint(0, 0)
}

pub const ZERO: Fingerprint = Fingerprint(0, 0);

#[inline]
pub fn from_smaller_hash(hash: u64) -> Fingerprint {
Expand Down
4 changes: 2 additions & 2 deletions src/librustc/ty/maps/plumbing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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);
Expand Down
9 changes: 9 additions & 0 deletions src/librustc/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -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);
Expand All @@ -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
};
Expand Down
6 changes: 4 additions & 2 deletions src/librustc_incremental/persist/dirty_clean.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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 {
Expand Down
Loading