Skip to content

Commit 88e97f0

Browse files
authored
Rollup merge of #41056 - michaelwoerister:central-defpath-hashes, r=nikomatsakis
Handle DefPath hashing centrally as part of DefPathTable (+ save work during SVH calculation) In almost all cases where we construct a `DefPath`, we just hash it and throw it away again immediately. With this PR, the compiler will immediately compute and store the hash for each `DefPath` as it is allocated. This way we + can get rid of any subsequent `DefPath` hash caching (e.g. the `DefPathHashes`), + don't need to allocate a transient `Vec` for holding the `DefPath` (although I'm always surprised how little these small, dynamic allocations seem to hurt performance), and + we don't hash `DefPath` prefixes over and over again. That last part is because we construct the hash for `prefix::foo` by hashing `(hash(prefix), foo)` instead of hashing every component of prefix. The last commit of this PR is pretty neat, I think: ``` The SVH (Strict Version Hash) of a crate is currently computed by hashing the ICHes (Incremental Computation Hashes) of the crate's HIR. This is fine, expect that for incr. comp. we compute two ICH values for each HIR item, one for the complete item and one that just includes the item's interface. The two hashes are are needed for dependency tracking but if we are compiling non-incrementally and just need the ICH values for the SVH, one of them is enough, giving us the opportunity to save some work in this case. ``` r? @nikomatsakis This PR depends on #40878 to be merged first (you can ignore the first commit for reviewing, that's just #40878).
2 parents ef9eee7 + bb63872 commit 88e97f0

File tree

19 files changed

+161
-131
lines changed

19 files changed

+161
-131
lines changed

src/librustc/hir/lowering.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2697,7 +2697,7 @@ impl<'a> LoweringContext<'a> {
26972697
fn pat_ident_binding_mode(&mut self, span: Span, name: Name, bm: hir::BindingMode)
26982698
-> P<hir::Pat> {
26992699
let id = self.next_id();
2700-
let parent_def = self.parent_def;
2700+
let parent_def = self.parent_def.unwrap();
27012701
let def_id = {
27022702
let defs = self.resolver.definitions();
27032703
let def_path_data = DefPathData::Binding(name.as_str());

src/librustc/hir/map/def_collector.rs

Lines changed: 4 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,9 @@ impl<'a> DefCollector<'a> {
4040
}
4141
}
4242

43-
pub fn collect_root(&mut self) {
44-
let root = self.create_def_with_parent(None,
45-
CRATE_NODE_ID,
46-
DefPathData::CrateRoot,
47-
ITEM_LIKE_SPACE);
43+
pub fn collect_root(&mut self, crate_name: &str, crate_disambiguator: &str) {
44+
let root = self.definitions.create_root_def(crate_name,
45+
crate_disambiguator);
4846
assert_eq!(root, CRATE_DEF_INDEX);
4947
self.parent_def = Some(root);
5048
}
@@ -54,20 +52,11 @@ impl<'a> DefCollector<'a> {
5452
data: DefPathData,
5553
address_space: DefIndexAddressSpace)
5654
-> DefIndex {
57-
let parent_def = self.parent_def;
55+
let parent_def = self.parent_def.unwrap();
5856
debug!("create_def(node_id={:?}, data={:?}, parent_def={:?})", node_id, data, parent_def);
5957
self.definitions.create_def_with_parent(parent_def, node_id, data, address_space)
6058
}
6159

62-
fn create_def_with_parent(&mut self,
63-
parent: Option<DefIndex>,
64-
node_id: NodeId,
65-
data: DefPathData,
66-
address_space: DefIndexAddressSpace)
67-
-> DefIndex {
68-
self.definitions.create_def_with_parent(parent, node_id, data, address_space)
69-
}
70-
7160
pub fn with_parent<F: FnOnce(&mut Self)>(&mut self, parent_def: DefIndex, f: F) {
7261
let parent = self.parent_def;
7362
self.parent_def = Some(parent_def);

src/librustc/hir/map/definitions.rs

Lines changed: 93 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ use rustc_data_structures::indexed_vec::IndexVec;
2121
use rustc_data_structures::stable_hasher::StableHasher;
2222
use serialize::{Encodable, Decodable, Encoder, Decoder};
2323
use std::fmt::Write;
24-
use std::hash::{Hash, Hasher};
24+
use std::hash::Hash;
2525
use syntax::ast;
2626
use syntax::symbol::{Symbol, InternedString};
2727
use ty::TyCtxt;
@@ -34,6 +34,7 @@ use util::nodemap::NodeMap;
3434
pub struct DefPathTable {
3535
index_to_key: [Vec<DefKey>; 2],
3636
key_to_index: FxHashMap<DefKey, DefIndex>,
37+
def_path_hashes: [Vec<u64>; 2],
3738
}
3839

3940
// Unfortunately we have to provide a manual impl of Clone because of the
@@ -44,6 +45,8 @@ impl Clone for DefPathTable {
4445
index_to_key: [self.index_to_key[0].clone(),
4546
self.index_to_key[1].clone()],
4647
key_to_index: self.key_to_index.clone(),
48+
def_path_hashes: [self.def_path_hashes[0].clone(),
49+
self.def_path_hashes[1].clone()],
4750
}
4851
}
4952
}
@@ -52,6 +55,7 @@ impl DefPathTable {
5255

5356
fn allocate(&mut self,
5457
key: DefKey,
58+
def_path_hash: u64,
5559
address_space: DefIndexAddressSpace)
5660
-> DefIndex {
5761
let index = {
@@ -62,6 +66,9 @@ impl DefPathTable {
6266
index
6367
};
6468
self.key_to_index.insert(key, index);
69+
self.def_path_hashes[address_space.index()].push(def_path_hash);
70+
debug_assert!(self.def_path_hashes[address_space.index()].len() ==
71+
self.index_to_key[address_space.index()].len());
6572
index
6673
}
6774

@@ -71,6 +78,12 @@ impl DefPathTable {
7178
[index.as_array_index()].clone()
7279
}
7380

81+
#[inline(always)]
82+
pub fn def_path_hash(&self, index: DefIndex) -> u64 {
83+
self.def_path_hashes[index.address_space().index()]
84+
[index.as_array_index()]
85+
}
86+
7487
#[inline(always)]
7588
pub fn def_index_for_def_key(&self, key: &DefKey) -> Option<DefIndex> {
7689
self.key_to_index.get(key).cloned()
@@ -116,17 +129,28 @@ impl DefPathTable {
116129

117130
impl Encodable for DefPathTable {
118131
fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
132+
// Index to key
119133
self.index_to_key[DefIndexAddressSpace::Low.index()].encode(s)?;
120-
self.index_to_key[DefIndexAddressSpace::High.index()].encode(s)
134+
self.index_to_key[DefIndexAddressSpace::High.index()].encode(s)?;
135+
136+
// DefPath hashes
137+
self.def_path_hashes[DefIndexAddressSpace::Low.index()].encode(s)?;
138+
self.def_path_hashes[DefIndexAddressSpace::High.index()].encode(s)?;
139+
140+
Ok(())
121141
}
122142
}
123143

124144
impl Decodable for DefPathTable {
125145
fn decode<D: Decoder>(d: &mut D) -> Result<DefPathTable, D::Error> {
126146
let index_to_key_lo: Vec<DefKey> = Decodable::decode(d)?;
127-
let index_to_key_high: Vec<DefKey> = Decodable::decode(d)?;
147+
let index_to_key_hi: Vec<DefKey> = Decodable::decode(d)?;
128148

129-
let index_to_key = [index_to_key_lo, index_to_key_high];
149+
let def_path_hashes_lo: Vec<u64> = Decodable::decode(d)?;
150+
let def_path_hashes_hi: Vec<u64> = Decodable::decode(d)?;
151+
152+
let index_to_key = [index_to_key_lo, index_to_key_hi];
153+
let def_path_hashes = [def_path_hashes_lo, def_path_hashes_hi];
130154

131155
let mut key_to_index = FxHashMap();
132156

@@ -141,6 +165,7 @@ impl Decodable for DefPathTable {
141165
Ok(DefPathTable {
142166
index_to_key: index_to_key,
143167
key_to_index: key_to_index,
168+
def_path_hashes: def_path_hashes,
144169
})
145170
}
146171
}
@@ -184,6 +209,29 @@ pub struct DefKey {
184209
pub disambiguated_data: DisambiguatedDefPathData,
185210
}
186211

212+
impl DefKey {
213+
fn compute_stable_hash(&self, parent_hash: u64) -> u64 {
214+
let mut hasher = StableHasher::new();
215+
216+
// We hash a 0u8 here to disambiguate between regular DefPath hashes,
217+
// and the special "root_parent" below.
218+
0u8.hash(&mut hasher);
219+
parent_hash.hash(&mut hasher);
220+
self.disambiguated_data.hash(&mut hasher);
221+
hasher.finish()
222+
}
223+
224+
fn root_parent_stable_hash(crate_name: &str, crate_disambiguator: &str) -> u64 {
225+
let mut hasher = StableHasher::new();
226+
// Disambiguate this from a regular DefPath hash,
227+
// see compute_stable_hash() above.
228+
1u8.hash(&mut hasher);
229+
crate_name.hash(&mut hasher);
230+
crate_disambiguator.hash(&mut hasher);
231+
hasher.finish()
232+
}
233+
}
234+
187235
/// Pair of `DefPathData` and an integer disambiguator. The integer is
188236
/// normally 0, but in the event that there are multiple defs with the
189237
/// same `parent` and `data`, we use this field to disambiguate
@@ -271,19 +319,6 @@ impl DefPath {
271319

272320
s
273321
}
274-
275-
pub fn deterministic_hash(&self, tcx: TyCtxt) -> u64 {
276-
debug!("deterministic_hash({:?})", self);
277-
let mut state = StableHasher::new();
278-
self.deterministic_hash_to(tcx, &mut state);
279-
state.finish()
280-
}
281-
282-
pub fn deterministic_hash_to<H: Hasher>(&self, tcx: TyCtxt, state: &mut H) {
283-
tcx.original_crate_name(self.krate).as_str().hash(state);
284-
tcx.crate_disambiguator(self.krate).as_str().hash(state);
285-
self.data.hash(state);
286-
}
287322
}
288323

289324
#[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
@@ -338,6 +373,7 @@ impl Definitions {
338373
table: DefPathTable {
339374
index_to_key: [vec![], vec![]],
340375
key_to_index: FxHashMap(),
376+
def_path_hashes: [vec![], vec![]],
341377
},
342378
node_to_def_index: NodeMap(),
343379
def_index_to_node: [vec![], vec![]],
@@ -359,6 +395,11 @@ impl Definitions {
359395
self.table.def_key(index)
360396
}
361397

398+
#[inline(always)]
399+
pub fn def_path_hash(&self, index: DefIndex) -> u64 {
400+
self.table.def_path_hash(index)
401+
}
402+
362403
pub fn def_index_for_def_key(&self, key: DefKey) -> Option<DefIndex> {
363404
self.table.def_index_for_def_key(&key)
364405
}
@@ -398,12 +439,38 @@ impl Definitions {
398439
self.node_to_hir_id[node_id]
399440
}
400441

442+
/// Add a definition with a parent definition.
443+
pub fn create_root_def(&mut self,
444+
crate_name: &str,
445+
crate_disambiguator: &str)
446+
-> DefIndex {
447+
let key = DefKey {
448+
parent: None,
449+
disambiguated_data: DisambiguatedDefPathData {
450+
data: DefPathData::CrateRoot,
451+
disambiguator: 0
452+
}
453+
};
454+
455+
let parent_hash = DefKey::root_parent_stable_hash(crate_name,
456+
crate_disambiguator);
457+
let def_path_hash = key.compute_stable_hash(parent_hash);
458+
459+
// Create the definition.
460+
let address_space = super::ITEM_LIKE_SPACE;
461+
let index = self.table.allocate(key, def_path_hash, address_space);
462+
assert!(self.def_index_to_node[address_space.index()].is_empty());
463+
self.def_index_to_node[address_space.index()].push(ast::CRATE_NODE_ID);
464+
self.node_to_def_index.insert(ast::CRATE_NODE_ID, index);
465+
466+
index
467+
}
468+
401469
/// Add a definition with a parent definition.
402470
pub fn create_def_with_parent(&mut self,
403-
parent: Option<DefIndex>,
471+
parent: DefIndex,
404472
node_id: ast::NodeId,
405473
data: DefPathData,
406-
// is_owner: bool)
407474
address_space: DefIndexAddressSpace)
408475
-> DefIndex {
409476
debug!("create_def_with_parent(parent={:?}, node_id={:?}, data={:?})",
@@ -415,12 +482,13 @@ impl Definitions {
415482
data,
416483
self.table.def_key(self.node_to_def_index[&node_id]));
417484

418-
assert_eq!(parent.is_some(), data != DefPathData::CrateRoot);
485+
// The root node must be created with create_root_def()
486+
assert!(data != DefPathData::CrateRoot);
419487

420488
// Find a unique DefKey. This basically means incrementing the disambiguator
421489
// until we get no match.
422490
let mut key = DefKey {
423-
parent: parent,
491+
parent: Some(parent),
424492
disambiguated_data: DisambiguatedDefPathData {
425493
data: data,
426494
disambiguator: 0
@@ -431,10 +499,13 @@ impl Definitions {
431499
key.disambiguated_data.disambiguator += 1;
432500
}
433501

502+
let parent_hash = self.table.def_path_hash(parent);
503+
let def_path_hash = key.compute_stable_hash(parent_hash);
504+
434505
debug!("create_def_with_parent: after disambiguation, key = {:?}", key);
435506

436507
// Create the definition.
437-
let index = self.table.allocate(key, address_space);
508+
let index = self.table.allocate(key, def_path_hash, address_space);
438509
assert_eq!(index.as_array_index(),
439510
self.def_index_to_node[address_space.index()].len());
440511
self.def_index_to_node[address_space.index()].push(node_id);

src/librustc/ich/def_path_hash.rs

Lines changed: 0 additions & 36 deletions
This file was deleted.

src/librustc/ich/hcx.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
use hir;
1212
use hir::def_id::DefId;
13-
use ich::{self, CachingCodemapView, DefPathHashes};
13+
use ich::{self, CachingCodemapView};
1414
use session::config::DebugInfoLevel::NoDebugInfo;
1515
use ty;
1616

@@ -32,7 +32,6 @@ use rustc_data_structures::accumulate_vec::AccumulateVec;
3232
/// things (e.g. each DefId/DefPath is only hashed once).
3333
pub struct StableHashingContext<'a, 'tcx: 'a> {
3434
tcx: ty::TyCtxt<'a, 'tcx, 'tcx>,
35-
def_path_hashes: DefPathHashes<'a, 'tcx>,
3635
codemap: CachingCodemapView<'tcx>,
3736
hash_spans: bool,
3837
hash_bodies: bool,
@@ -64,7 +63,6 @@ impl<'a, 'tcx: 'a> StableHashingContext<'a, 'tcx> {
6463

6564
StableHashingContext {
6665
tcx: tcx,
67-
def_path_hashes: DefPathHashes::new(tcx),
6866
codemap: CachingCodemapView::new(tcx),
6967
hash_spans: hash_spans_initial,
7068
hash_bodies: true,
@@ -111,7 +109,7 @@ impl<'a, 'tcx: 'a> StableHashingContext<'a, 'tcx> {
111109

112110
#[inline]
113111
pub fn def_path_hash(&mut self, def_id: DefId) -> u64 {
114-
self.def_path_hashes.hash(def_id)
112+
self.tcx.def_path_hash(def_id)
115113
}
116114

117115
#[inline]

src/librustc/ich/mod.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,10 @@
1111
//! ICH - Incremental Compilation Hash
1212
1313
pub use self::fingerprint::Fingerprint;
14-
pub use self::def_path_hash::DefPathHashes;
1514
pub use self::caching_codemap_view::CachingCodemapView;
1615
pub use self::hcx::{StableHashingContext, NodeIdHashingMode};
1716

1817
mod fingerprint;
19-
mod def_path_hash;
2018
mod caching_codemap_view;
2119
mod hcx;
2220

src/librustc/middle/cstore.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,7 @@ pub trait CrateStore {
230230
-> Option<DefId>;
231231
fn def_key(&self, def: DefId) -> DefKey;
232232
fn def_path(&self, def: DefId) -> hir_map::DefPath;
233+
fn def_path_hash(&self, def: DefId) -> u64;
233234
fn struct_field_names(&self, def: DefId) -> Vec<ast::Name>;
234235
fn item_children(&self, did: DefId) -> Vec<def::Export>;
235236
fn load_macro(&self, did: DefId, sess: &Session) -> LoadedMacro;
@@ -377,6 +378,9 @@ impl CrateStore for DummyCrateStore {
377378
fn def_path(&self, def: DefId) -> hir_map::DefPath {
378379
bug!("relative_def_path")
379380
}
381+
fn def_path_hash(&self, def: DefId) -> u64 {
382+
bug!("wa")
383+
}
380384
fn struct_field_names(&self, def: DefId) -> Vec<ast::Name> { bug!("struct_field_names") }
381385
fn item_children(&self, did: DefId) -> Vec<def::Export> { bug!("item_children") }
382386
fn load_macro(&self, did: DefId, sess: &Session) -> LoadedMacro { bug!("load_macro") }

0 commit comments

Comments
 (0)