Skip to content

Commit f0cf23e

Browse files
committed
Auto merge of #46842 - michaelwoerister:fingerprint-vec, r=nikomatsakis
incr.comp.: Use an array instead of a hashmap for storing result hashes. Doing so should result in some of the core tracking components being faster. r? @nikomatsakis
2 parents 5165ee9 + b2f7239 commit f0cf23e

File tree

13 files changed

+129
-73
lines changed

13 files changed

+129
-73
lines changed

src/librustc/dep_graph/dep_node.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,7 @@ macro_rules! define_dep_nodes {
279279

280280
DepNode {
281281
kind: DepKind::$variant,
282-
hash: Fingerprint::zero(),
282+
hash: Fingerprint::ZERO,
283283
}
284284
}
285285
)*
@@ -308,7 +308,7 @@ macro_rules! define_dep_nodes {
308308
assert!(!kind.has_params());
309309
DepNode {
310310
kind,
311-
hash: Fingerprint::zero(),
311+
hash: Fingerprint::ZERO,
312312
}
313313
}
314314

src/librustc/dep_graph/graph.rs

+73-37
Original file line numberDiff line numberDiff line change
@@ -34,14 +34,11 @@ use super::prev::PreviousDepGraph;
3434
pub struct DepGraph {
3535
data: Option<Rc<DepGraphData>>,
3636

37-
// At the moment we are using DepNode as key here. In the future it might
38-
// be possible to use an IndexVec<DepNodeIndex, _> here. At the moment there
39-
// are a few problems with that:
40-
// - Some fingerprints are needed even if incr. comp. is disabled -- yet
41-
// we need to have a dep-graph to generate DepNodeIndices.
42-
// - The architecture is still in flux and it's not clear what how to best
43-
// implement things.
44-
fingerprints: Rc<RefCell<FxHashMap<DepNode, Fingerprint>>>
37+
// A vector mapping depnodes from the current graph to their associated
38+
// result value fingerprints. Do not rely on the length of this vector
39+
// being the same as the number of nodes in the graph. The vector can
40+
// contain an arbitrary number of zero-entries at the end.
41+
fingerprints: Rc<RefCell<IndexVec<DepNodeIndex, Fingerprint>>>
4542
}
4643

4744

@@ -97,6 +94,11 @@ struct DepGraphData {
9794
impl DepGraph {
9895

9996
pub fn new(prev_graph: PreviousDepGraph) -> DepGraph {
97+
// Pre-allocate the fingerprints array. We over-allocate a little so
98+
// that we hopefully don't have to re-allocate during this compilation
99+
// session.
100+
let fingerprints = IndexVec::from_elem_n(Fingerprint::ZERO,
101+
(prev_graph.node_count() * 115) / 100);
100102
DepGraph {
101103
data: Some(Rc::new(DepGraphData {
102104
previous_work_products: RefCell::new(FxHashMap()),
@@ -107,14 +109,14 @@ impl DepGraph {
107109
colors: RefCell::new(FxHashMap()),
108110
loaded_from_cache: RefCell::new(FxHashMap()),
109111
})),
110-
fingerprints: Rc::new(RefCell::new(FxHashMap())),
112+
fingerprints: Rc::new(RefCell::new(fingerprints)),
111113
}
112114
}
113115

114116
pub fn new_disabled() -> DepGraph {
115117
DepGraph {
116118
data: None,
117-
fingerprints: Rc::new(RefCell::new(FxHashMap())),
119+
fingerprints: Rc::new(RefCell::new(IndexVec::new())),
118120
}
119121
}
120122

@@ -231,12 +233,16 @@ impl DepGraph {
231233

232234
// Store the current fingerprint
233235
{
234-
let old_value = self.fingerprints
235-
.borrow_mut()
236-
.insert(key, current_fingerprint);
237-
debug_assert!(old_value.is_none(),
236+
let mut fingerprints = self.fingerprints.borrow_mut();
237+
238+
if dep_node_index.index() >= fingerprints.len() {
239+
fingerprints.resize(dep_node_index.index() + 1, Fingerprint::ZERO);
240+
}
241+
242+
debug_assert!(fingerprints[dep_node_index] == Fingerprint::ZERO,
238243
"DepGraph::with_task() - Duplicate fingerprint \
239244
insertion for {:?}", key);
245+
fingerprints[dep_node_index] = current_fingerprint;
240246
}
241247

242248
// Determine the color of the new DepNode.
@@ -262,13 +268,15 @@ impl DepGraph {
262268
let result = task(cx, arg);
263269
let mut stable_hasher = StableHasher::new();
264270
result.hash_stable(&mut hcx, &mut stable_hasher);
265-
let old_value = self.fingerprints
266-
.borrow_mut()
267-
.insert(key, stable_hasher.finish());
268-
debug_assert!(old_value.is_none(),
269-
"DepGraph::with_task() - Duplicate fingerprint \
270-
insertion for {:?}", key);
271-
(result, DepNodeIndex::INVALID)
271+
let fingerprint = stable_hasher.finish();
272+
273+
let mut fingerprints = self.fingerprints.borrow_mut();
274+
let dep_node_index = DepNodeIndex::new(fingerprints.len());
275+
fingerprints.push(fingerprint);
276+
debug_assert!(fingerprints[dep_node_index] == fingerprint,
277+
"DepGraph::with_task() - Assigned fingerprint to \
278+
unexpected index for {:?}", key);
279+
(result, dep_node_index)
272280
} else {
273281
(task(cx, arg), DepNodeIndex::INVALID)
274282
}
@@ -328,11 +336,29 @@ impl DepGraph {
328336
}
329337

330338
#[inline]
331-
pub fn fingerprint_of(&self, dep_node: &DepNode) -> Fingerprint {
332-
match self.fingerprints.borrow().get(dep_node) {
339+
pub fn dep_node_index_of(&self, dep_node: &DepNode) -> DepNodeIndex {
340+
self.data
341+
.as_ref()
342+
.unwrap()
343+
.current
344+
.borrow_mut()
345+
.node_to_node_index
346+
.get(dep_node)
347+
.cloned()
348+
.unwrap()
349+
}
350+
351+
#[inline]
352+
pub fn fingerprint_of(&self, dep_node_index: DepNodeIndex) -> Fingerprint {
353+
match self.fingerprints.borrow().get(dep_node_index) {
333354
Some(&fingerprint) => fingerprint,
334355
None => {
335-
bug!("Could not find current fingerprint for {:?}", dep_node)
356+
if let Some(ref data) = self.data {
357+
let dep_node = data.current.borrow().nodes[dep_node_index];
358+
bug!("Could not find current fingerprint for {:?}", dep_node)
359+
} else {
360+
bug!("Could not find current fingerprint for {:?}", dep_node_index)
361+
}
336362
}
337363
}
338364
}
@@ -420,14 +446,17 @@ impl DepGraph {
420446
}
421447

422448
pub fn serialize(&self) -> SerializedDepGraph {
423-
let fingerprints = self.fingerprints.borrow();
449+
let mut fingerprints = self.fingerprints.borrow_mut();
424450
let current_dep_graph = self.data.as_ref().unwrap().current.borrow();
425451

426-
let nodes: IndexVec<_, _> = current_dep_graph.nodes.iter().map(|dep_node| {
427-
let fingerprint = fingerprints.get(dep_node)
428-
.cloned()
429-
.unwrap_or(Fingerprint::zero());
430-
(*dep_node, fingerprint)
452+
// Make sure we don't run out of bounds below.
453+
if current_dep_graph.nodes.len() > fingerprints.len() {
454+
fingerprints.resize(current_dep_graph.nodes.len(), Fingerprint::ZERO);
455+
}
456+
457+
let nodes: IndexVec<_, (DepNode, Fingerprint)> =
458+
current_dep_graph.nodes.iter_enumerated().map(|(idx, &dep_node)| {
459+
(dep_node, fingerprints[idx])
431460
}).collect();
432461

433462
let total_edge_count: usize = current_dep_graph.edges.iter()
@@ -610,13 +639,20 @@ impl DepGraph {
610639

611640
// ... copying the fingerprint from the previous graph too, so we don't
612641
// have to recompute it ...
613-
let fingerprint = data.previous.fingerprint_by_index(prev_dep_node_index);
614-
let old_fingerprint = self.fingerprints
615-
.borrow_mut()
616-
.insert(*dep_node, fingerprint);
617-
debug_assert!(old_fingerprint.is_none(),
618-
"DepGraph::try_mark_green() - Duplicate fingerprint \
619-
insertion for {:?}", dep_node);
642+
{
643+
let fingerprint = data.previous.fingerprint_by_index(prev_dep_node_index);
644+
let mut fingerprints = self.fingerprints.borrow_mut();
645+
646+
if dep_node_index.index() >= fingerprints.len() {
647+
fingerprints.resize(dep_node_index.index() + 1, Fingerprint::ZERO);
648+
}
649+
650+
debug_assert!(fingerprints[dep_node_index] == Fingerprint::ZERO,
651+
"DepGraph::try_mark_green() - Duplicate fingerprint \
652+
insertion for {:?}", dep_node);
653+
654+
fingerprints[dep_node_index] = fingerprint;
655+
}
620656

621657
// ... emitting any stored diagnostic ...
622658
{

src/librustc/dep_graph/prev.rs

+4
Original file line numberDiff line numberDiff line change
@@ -62,4 +62,8 @@ impl PreviousDepGraph {
6262
-> Fingerprint {
6363
self.data.nodes[dep_node_index].1
6464
}
65+
66+
pub fn node_count(&self) -> usize {
67+
self.index.len()
68+
}
6569
}

src/librustc/hir/map/collector.rs

+20-14
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use super::*;
1212

1313
use dep_graph::{DepGraph, DepKind, DepNodeIndex};
1414
use hir::intravisit::{Visitor, NestedVisitorMap};
15+
use hir::svh::Svh;
1516
use middle::cstore::CrateStore;
1617
use session::CrateDisambiguator;
1718
use std::iter::repeat;
@@ -44,7 +45,7 @@ pub(super) struct NodeCollector<'a, 'hir> {
4445

4546
// We are collecting DepNode::HirBody hashes here so we can compute the
4647
// crate hash from then later on.
47-
hir_body_nodes: Vec<DefPathHash>,
48+
hir_body_nodes: Vec<(DefPathHash, DepNodeIndex)>,
4849
}
4950

5051
impl<'a, 'hir> NodeCollector<'a, 'hir> {
@@ -99,7 +100,7 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> {
99100
);
100101
}
101102

102-
let hir_body_nodes = vec![root_mod_def_path_hash];
103+
let hir_body_nodes = vec![(root_mod_def_path_hash, root_mod_full_dep_index)];
103104

104105
let mut collector = NodeCollector {
105106
krate,
@@ -123,13 +124,12 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> {
123124
crate_disambiguator: CrateDisambiguator,
124125
cstore: &CrateStore,
125126
commandline_args_hash: u64)
126-
-> Vec<MapEntry<'hir>> {
127+
-> (Vec<MapEntry<'hir>>, Svh) {
127128
let mut node_hashes: Vec<_> = self
128129
.hir_body_nodes
129130
.iter()
130-
.map(|&def_path_hash| {
131-
let dep_node = def_path_hash.to_dep_node(DepKind::HirBody);
132-
(def_path_hash, self.dep_graph.fingerprint_of(&dep_node))
131+
.map(|&(def_path_hash, dep_node_index)| {
132+
(def_path_hash, self.dep_graph.fingerprint_of(dep_node_index))
133133
})
134134
.collect();
135135

@@ -147,13 +147,19 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> {
147147
(name1, dis1).cmp(&(name2, dis2))
148148
});
149149

150-
self.dep_graph.with_task(DepNode::new_no_params(DepKind::Krate),
151-
&self.hcx,
152-
((node_hashes, upstream_crates),
153-
(commandline_args_hash,
154-
crate_disambiguator.to_fingerprint())),
155-
identity_fn);
156-
self.map
150+
let (_, crate_dep_node_index) = self
151+
.dep_graph
152+
.with_task(DepNode::new_no_params(DepKind::Krate),
153+
&self.hcx,
154+
((node_hashes, upstream_crates),
155+
(commandline_args_hash,
156+
crate_disambiguator.to_fingerprint())),
157+
identity_fn);
158+
159+
let svh = Svh::new(self.dep_graph
160+
.fingerprint_of(crate_dep_node_index)
161+
.to_smaller_hash());
162+
(self.map, svh)
157163
}
158164

159165
fn insert_entry(&mut self, id: NodeId, entry: MapEntry<'hir>) {
@@ -255,7 +261,7 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> {
255261
identity_fn
256262
).1;
257263

258-
self.hir_body_nodes.push(def_path_hash);
264+
self.hir_body_nodes.push((def_path_hash, self.current_full_dep_index));
259265

260266
self.current_dep_node_owner = dep_node_owner;
261267
self.currently_in_body = false;

src/librustc/hir/map/mod.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ use syntax_pos::Span;
2626

2727
use hir::*;
2828
use hir::print::Nested;
29+
use hir::svh::Svh;
2930
use util::nodemap::{DefIdMap, FxHashMap};
3031

3132
use arena::TypedArena;
@@ -241,6 +242,9 @@ pub struct Map<'hir> {
241242
/// deref. This is a gratuitous micro-optimization.
242243
pub dep_graph: DepGraph,
243244

245+
/// The SVH of the local crate.
246+
pub crate_hash: Svh,
247+
244248
/// NodeIds are sequential integers from 0, so we can be
245249
/// super-compact by storing them in a vector. Not everything with
246250
/// a NodeId is in the map, but empirically the occupancy is about
@@ -1048,7 +1052,7 @@ pub fn map_crate<'hir>(sess: &::session::Session,
10481052
forest: &'hir mut Forest,
10491053
definitions: &'hir Definitions)
10501054
-> Map<'hir> {
1051-
let map = {
1055+
let (map, crate_hash) = {
10521056
let hcx = ::ich::StableHashingContext::new(sess, &forest.krate, definitions, cstore);
10531057

10541058
let mut collector = NodeCollector::root(&forest.krate,
@@ -1087,6 +1091,7 @@ pub fn map_crate<'hir>(sess: &::session::Session,
10871091
let map = Map {
10881092
forest,
10891093
dep_graph: forest.dep_graph.clone(),
1094+
crate_hash,
10901095
map,
10911096
hir_to_node_id,
10921097
definitions,

src/librustc/ich/fingerprint.rs

+2-4
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,8 @@ use rustc_data_structures::stable_hasher;
1414
pub struct Fingerprint(u64, u64);
1515

1616
impl Fingerprint {
17-
#[inline]
18-
pub fn zero() -> Fingerprint {
19-
Fingerprint(0, 0)
20-
}
17+
18+
pub const ZERO: Fingerprint = Fingerprint(0, 0);
2119

2220
#[inline]
2321
pub fn from_smaller_hash(hash: u64) -> Fingerprint {

src/librustc/ty/maps/plumbing.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -438,7 +438,7 @@ macro_rules! define_maps {
438438
use rustc_data_structures::stable_hasher::{StableHasher, HashStable};
439439
use ich::Fingerprint;
440440

441-
assert!(Some(tcx.dep_graph.fingerprint_of(dep_node)) ==
441+
assert!(Some(tcx.dep_graph.fingerprint_of(dep_node_index)) ==
442442
tcx.dep_graph.prev_fingerprint_of(dep_node),
443443
"Fingerprint for green query instance not loaded \
444444
from cache: {:?}", dep_node);
@@ -452,7 +452,7 @@ macro_rules! define_maps {
452452
let new_hash: Fingerprint = hasher.finish();
453453
debug!("END verify_ich({:?})", dep_node);
454454

455-
let old_hash = tcx.dep_graph.fingerprint_of(dep_node);
455+
let old_hash = tcx.dep_graph.fingerprint_of(dep_node_index);
456456

457457
assert!(new_hash == old_hash, "Found unstable fingerprints \
458458
for {:?}", dep_node);

src/librustc/ty/mod.rs

+9
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ use hir::{map as hir_map, FreevarMap, TraitMap};
1919
use hir::def::{Def, CtorKind, ExportMap};
2020
use hir::def_id::{CrateNum, DefId, DefIndex, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE};
2121
use hir::map::DefPathData;
22+
use hir::svh::Svh;
2223
use ich::StableHashingContext;
2324
use middle::const_val::ConstVal;
2425
use middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem, FnOnceTraitLangItem};
@@ -2669,6 +2670,13 @@ fn original_crate_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
26692670
tcx.crate_name.clone()
26702671
}
26712672

2673+
fn crate_hash<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
2674+
crate_num: CrateNum)
2675+
-> Svh {
2676+
assert_eq!(crate_num, LOCAL_CRATE);
2677+
tcx.hir.crate_hash
2678+
}
2679+
26722680
pub fn provide(providers: &mut ty::maps::Providers) {
26732681
context::provide(providers);
26742682
erase_regions::provide(providers);
@@ -2684,6 +2692,7 @@ pub fn provide(providers: &mut ty::maps::Providers) {
26842692
trait_of_item,
26852693
crate_disambiguator,
26862694
original_crate_name,
2695+
crate_hash,
26872696
trait_impls_of: trait_def::trait_impls_of_provider,
26882697
..*providers
26892698
};

src/librustc_incremental/persist/dirty_clean.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -480,7 +480,8 @@ impl<'a, 'tcx> DirtyCleanVisitor<'a, 'tcx> {
480480
fn assert_dirty(&self, item_span: Span, dep_node: DepNode) {
481481
debug!("assert_dirty({:?})", dep_node);
482482

483-
let current_fingerprint = self.tcx.dep_graph.fingerprint_of(&dep_node);
483+
let dep_node_index = self.tcx.dep_graph.dep_node_index_of(&dep_node);
484+
let current_fingerprint = self.tcx.dep_graph.fingerprint_of(dep_node_index);
484485
let prev_fingerprint = self.tcx.dep_graph.prev_fingerprint_of(&dep_node);
485486

486487
if Some(current_fingerprint) == prev_fingerprint {
@@ -494,7 +495,8 @@ impl<'a, 'tcx> DirtyCleanVisitor<'a, 'tcx> {
494495
fn assert_clean(&self, item_span: Span, dep_node: DepNode) {
495496
debug!("assert_clean({:?})", dep_node);
496497

497-
let current_fingerprint = self.tcx.dep_graph.fingerprint_of(&dep_node);
498+
let dep_node_index = self.tcx.dep_graph.dep_node_index_of(&dep_node);
499+
let current_fingerprint = self.tcx.dep_graph.fingerprint_of(dep_node_index);
498500
let prev_fingerprint = self.tcx.dep_graph.prev_fingerprint_of(&dep_node);
499501

500502
if Some(current_fingerprint) != prev_fingerprint {

0 commit comments

Comments
 (0)