Skip to content

Commit ca2dce9

Browse files
ICH: Replace old, transitive metadata hashing with direct hashing approach.
Instead of collecting all potential inputs to some metadata entry and hashing those, we directly hash the values we are storing in metadata. This is more accurate and doesn't suffer from quadratic blow-up when many entries have the same dependencies.
1 parent bc7af81 commit ca2dce9

File tree

27 files changed

+689
-341
lines changed

27 files changed

+689
-341
lines changed

src/librustc/ich/impls_ty.rs

+12-20
Original file line numberDiff line numberDiff line change
@@ -16,24 +16,9 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher,
1616
StableHasherResult};
1717
use std::hash as std_hash;
1818
use std::mem;
19+
use syntax_pos::symbol::InternedString;
1920
use ty;
2021

21-
impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ty::TyS<'tcx> {
22-
fn hash_stable<W: StableHasherResult>(&self,
23-
hcx: &mut StableHashingContext<'a, 'tcx>,
24-
hasher: &mut StableHasher<W>) {
25-
let ty::TyS {
26-
ref sty,
27-
28-
// The other fields just provide fast access to information that is
29-
// also contained in `sty`, so no need to hash them.
30-
..
31-
} = *self;
32-
33-
sty.hash_stable(hcx, hasher);
34-
}
35-
}
36-
3722
impl_stable_hash_for!(struct ty::ItemSubsts<'tcx> { substs });
3823

3924
impl<'a, 'tcx, T> HashStable<StableHashingContext<'a, 'tcx>> for &'tcx ty::Slice<T>
@@ -288,9 +273,14 @@ for ::middle::const_val::ConstVal<'tcx> {
288273
def_id.hash_stable(hcx, hasher);
289274
substs.hash_stable(hcx, hasher);
290275
}
291-
ConstVal::Struct(ref _name_value_map) => {
292-
// BTreeMap<ast::Name, ConstVal<'tcx>>),
293-
panic!("Ordering still unstable")
276+
ConstVal::Struct(ref name_value_map) => {
277+
let mut values: Vec<(InternedString, &ConstVal)> =
278+
name_value_map.iter()
279+
.map(|(name, val)| (name.as_str(), val))
280+
.collect();
281+
282+
values.sort_unstable_by_key(|&(ref name, _)| name.clone());
283+
values.hash_stable(hcx, hasher);
294284
}
295285
ConstVal::Tuple(ref value) => {
296286
value.hash_stable(hcx, hasher);
@@ -632,6 +622,8 @@ impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ty::TypeckTables<'
632622
ref fru_field_types,
633623

634624
ref cast_kinds,
625+
626+
// FIXME(#41184): This is still ignored at the moment.
635627
lints: _,
636628
ref used_trait_imports,
637629
tainted_by_errors,
@@ -672,7 +664,7 @@ impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ty::TypeckTables<'
672664
ich::hash_stable_nodemap(hcx, hasher, cast_kinds);
673665

674666
ich::hash_stable_hashset(hcx, hasher, used_trait_imports, |hcx, def_id| {
675-
hcx.tcx().def_path_hash(*def_id)
667+
hcx.def_path_hash(*def_id)
676668
});
677669

678670
tainted_by_errors.hash_stable(hcx, hasher);

src/librustc/middle/cstore.rs

+21-2
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ use hir::def_id::{CrateNum, DefId, DefIndex};
2727
use hir::map as hir_map;
2828
use hir::map::definitions::{Definitions, DefKey, DisambiguatedDefPathData};
2929
use hir::svh::Svh;
30+
use ich;
3031
use middle::lang_items;
3132
use ty::{self, TyCtxt};
3233
use session::Session;
@@ -161,6 +162,20 @@ pub struct ExternCrate {
161162
pub path_len: usize,
162163
}
163164

165+
pub struct EncodedMetadata {
166+
pub raw_data: Vec<u8>,
167+
pub hashes: Vec<EncodedMetadataHash>,
168+
}
169+
170+
/// The hash for some metadata that (when saving) will be exported
171+
/// from this crate, or which (when importing) was exported by an
172+
/// upstream crate.
173+
#[derive(Debug, RustcEncodable, RustcDecodable, Copy, Clone)]
174+
pub struct EncodedMetadataHash {
175+
pub def_index: DefIndex,
176+
pub hash: ich::Fingerprint,
177+
}
178+
164179
/// A store of Rust crates, through with their metadata
165180
/// can be accessed.
166181
pub trait CrateStore {
@@ -258,7 +273,8 @@ pub trait CrateStore {
258273
fn encode_metadata<'a, 'tcx>(&self,
259274
tcx: TyCtxt<'a, 'tcx, 'tcx>,
260275
link_meta: &LinkMeta,
261-
reachable: &NodeSet) -> Vec<u8>;
276+
reachable: &NodeSet)
277+
-> EncodedMetadata;
262278
fn metadata_encoding_version(&self) -> &[u8];
263279
}
264280

@@ -417,7 +433,10 @@ impl CrateStore for DummyCrateStore {
417433
fn encode_metadata<'a, 'tcx>(&self,
418434
tcx: TyCtxt<'a, 'tcx, 'tcx>,
419435
link_meta: &LinkMeta,
420-
reachable: &NodeSet) -> Vec<u8> { vec![] }
436+
reachable: &NodeSet)
437+
-> EncodedMetadata {
438+
bug!("encode_metadata")
439+
}
421440
fn metadata_encoding_version(&self) -> &[u8] { bug!("metadata_encoding_version") }
422441
}
423442

src/librustc/ty/mod.rs

+17
Original file line numberDiff line numberDiff line change
@@ -452,6 +452,23 @@ impl<'tcx> Hash for TyS<'tcx> {
452452
}
453453
}
454454

455+
impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ty::TyS<'tcx> {
456+
fn hash_stable<W: StableHasherResult>(&self,
457+
hcx: &mut StableHashingContext<'a, 'tcx>,
458+
hasher: &mut StableHasher<W>) {
459+
let ty::TyS {
460+
ref sty,
461+
462+
// The other fields just provide fast access to information that is
463+
// also contained in `sty`, so no need to hash them.
464+
flags: _,
465+
region_depth: _,
466+
} = *self;
467+
468+
sty.hash_stable(hcx, hasher);
469+
}
470+
}
471+
455472
pub type Ty<'tcx> = &'tcx TyS<'tcx>;
456473

457474
impl<'tcx> serialize::UseSpecializedEncodable for Ty<'tcx> {}

src/librustc/ty/util.rs

+19-11
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
use hir::def_id::{DefId, LOCAL_CRATE};
1414
use hir::map::DefPathData;
1515
use infer::InferCtxt;
16-
// use hir::map as hir_map;
16+
use ich::{StableHashingContext, NodeIdHashingMode};
1717
use traits::{self, Reveal};
1818
use ty::{self, Ty, TyCtxt, TypeAndMut, TypeFlags, TypeFoldable};
1919
use ty::ParameterEnvironment;
@@ -25,8 +25,8 @@ use util::nodemap::FxHashMap;
2525
use middle::lang_items;
2626

2727
use rustc_const_math::{ConstInt, ConstIsize, ConstUsize};
28-
use rustc_data_structures::stable_hasher::{StableHasher, StableHasherResult};
29-
28+
use rustc_data_structures::stable_hasher::{StableHasher, StableHasherResult,
29+
HashStable};
3030
use std::cell::RefCell;
3131
use std::cmp;
3232
use std::hash::Hash;
@@ -187,6 +187,22 @@ impl<'tcx> ParameterEnvironment<'tcx> {
187187
}
188188
}
189189

190+
impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
191+
/// Creates a hash of the type `Ty` which will be the same no matter what crate
192+
/// context it's calculated within. This is used by the `type_id` intrinsic.
193+
pub fn type_id_hash(self, ty: Ty<'tcx>) -> u64 {
194+
let mut hasher = StableHasher::new();
195+
let mut hcx = StableHashingContext::new(self);
196+
197+
hcx.while_hashing_spans(false, |hcx| {
198+
hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
199+
ty.hash_stable(hcx, &mut hasher);
200+
});
201+
});
202+
hasher.finish()
203+
}
204+
}
205+
190206
impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
191207
pub fn has_error_field(self, ty: Ty<'tcx>) -> bool {
192208
match ty.sty {
@@ -339,14 +355,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
339355
.collect()
340356
}
341357

342-
/// Creates a hash of the type `Ty` which will be the same no matter what crate
343-
/// context it's calculated within. This is used by the `type_id` intrinsic.
344-
pub fn type_id_hash(self, ty: Ty<'tcx>) -> u64 {
345-
let mut hasher = TypeIdHasher::new(self);
346-
hasher.visit_ty(ty);
347-
hasher.finish()
348-
}
349-
350358
/// Calculate the destructor of a given type.
351359
pub fn calculate_dtor(
352360
self,

src/librustc_data_structures/blake2b.rs

+27-7
Original file line numberDiff line numberDiff line change
@@ -29,16 +29,23 @@ pub struct Blake2bCtx {
2929
t: [u64; 2],
3030
c: usize,
3131
outlen: u16,
32-
finalized: bool
32+
finalized: bool,
33+
34+
#[cfg(debug_assertions)]
35+
fnv_hash: u64,
3336
}
3437

38+
#[cfg(debug_assertions)]
3539
impl ::std::fmt::Debug for Blake2bCtx {
36-
fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> {
37-
try!(write!(fmt, "hash: "));
38-
for v in &self.h {
39-
try!(write!(fmt, "{:x}", v));
40-
}
41-
Ok(())
40+
fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
41+
write!(fmt, "{:x}", self.fnv_hash)
42+
}
43+
}
44+
45+
#[cfg(not(debug_assertions))]
46+
impl ::std::fmt::Debug for Blake2bCtx {
47+
fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
48+
write!(fmt, "Enable debug_assertions() for more info.")
4249
}
4350
}
4451

@@ -157,6 +164,9 @@ fn blake2b_new(outlen: usize, key: &[u8]) -> Blake2bCtx {
157164
c: 0,
158165
outlen: outlen as u16,
159166
finalized: false,
167+
168+
#[cfg(debug_assertions)]
169+
fnv_hash: 0xcbf29ce484222325,
160170
};
161171

162172
ctx.h[0] ^= 0x01010000 ^ ((key.len() << 8) as u64) ^ (outlen as u64);
@@ -194,6 +204,16 @@ fn blake2b_update(ctx: &mut Blake2bCtx, mut data: &[u8]) {
194204
checked_mem_copy(data, &mut ctx.b[ctx.c .. ], bytes_to_copy);
195205
ctx.c += bytes_to_copy;
196206
}
207+
208+
#[cfg(debug_assertions)]
209+
{
210+
// compute additional FNV hash for simpler to read debug output
211+
const MAGIC_PRIME: u64 = 0x00000100000001b3;
212+
213+
for &byte in data {
214+
ctx.fnv_hash = (ctx.fnv_hash ^ byte as u64).wrapping_mul(MAGIC_PRIME);
215+
}
216+
}
197217
}
198218

199219
fn blake2b_final(ctx: &mut Blake2bCtx)

src/librustc_data_structures/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
#![feature(discriminant_value)]
4141
#![feature(specialization)]
4242
#![feature(manually_drop)]
43+
#![feature(struct_field_attributes)]
4344

4445
#![cfg_attr(unix, feature(libc))]
4546
#![cfg_attr(test, feature(test))]

src/librustc_data_structures/stable_hasher.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -40,13 +40,18 @@ fn write_signed_leb128_to_buf(buf: &mut [u8; 16], value: i64) -> usize {
4040
/// This hasher currently always uses the stable Blake2b algorithm
4141
/// and allows for variable output lengths through its type
4242
/// parameter.
43-
#[derive(Debug)]
4443
pub struct StableHasher<W> {
4544
state: Blake2bHasher,
4645
bytes_hashed: u64,
4746
width: PhantomData<W>,
4847
}
4948

49+
impl<W: StableHasherResult> ::std::fmt::Debug for StableHasher<W> {
50+
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
51+
write!(f, "{:?}", self.state)
52+
}
53+
}
54+
5055
pub trait StableHasherResult: Sized {
5156
fn finish(hasher: StableHasher<Self>) -> Self;
5257
}

src/librustc_driver/driver.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1083,6 +1083,7 @@ pub fn phase_4_translate_to_llvm<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
10831083
"serialize dep graph",
10841084
|| rustc_incremental::save_dep_graph(tcx,
10851085
&incremental_hashes_map,
1086+
&translation.metadata.hashes,
10861087
translation.link.crate_hash));
10871088
translation
10881089
}

src/librustc_incremental/persist/data.rs

+2-12
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
use rustc::dep_graph::{DepNode, WorkProduct, WorkProductId};
1414
use rustc::hir::def_id::DefIndex;
1515
use rustc::ich::Fingerprint;
16+
use rustc::middle::cstore::EncodedMetadataHash;
1617
use std::sync::Arc;
1718
use rustc_data_structures::fx::FxHashMap;
1819

@@ -98,7 +99,7 @@ pub struct SerializedMetadataHashes {
9899
/// where `X` refers to some item in this crate. That `X` will be
99100
/// a `DefPathIndex` that gets retracted to the current `DefId`
100101
/// (matching the one found in this structure).
101-
pub hashes: Vec<SerializedMetadataHash>,
102+
pub hashes: Vec<EncodedMetadataHash>,
102103

103104
/// For each DefIndex (as it occurs in SerializedMetadataHash), this
104105
/// map stores the DefPathIndex (as it occurs in DefIdDirectory), so
@@ -112,14 +113,3 @@ pub struct SerializedMetadataHashes {
112113
/// the DefIndex.
113114
pub index_map: FxHashMap<DefIndex, DefPathIndex>
114115
}
115-
116-
/// The hash for some metadata that (when saving) will be exported
117-
/// from this crate, or which (when importing) was exported by an
118-
/// upstream crate.
119-
#[derive(Debug, RustcEncodable, RustcDecodable)]
120-
pub struct SerializedMetadataHash {
121-
pub def_index: DefIndex,
122-
123-
/// the hash itself, computed by `calculate_item_hash`
124-
pub hash: Fingerprint,
125-
}

0 commit comments

Comments
 (0)