]> git.lizzy.rs Git - rust.git/commitdiff
ICH: Use 128-bit Blake2b hash instead of 64-bit SipHash for incr. comp. fingerprints.
authorMichael Woerister <michaelwoerister@posteo.net>
Fri, 7 Oct 2016 13:13:11 +0000 (09:13 -0400)
committerMichael Woerister <michaelwoerister@posteo.net>
Mon, 17 Oct 2016 16:40:25 +0000 (12:40 -0400)
14 files changed:
src/librustc_data_structures/blake2b.rs [new file with mode: 0644]
src/librustc_data_structures/lib.rs
src/librustc_incremental/calculate_svh/hasher.rs
src/librustc_incremental/calculate_svh/mod.rs
src/librustc_incremental/ich/fingerprint.rs [new file with mode: 0644]
src/librustc_incremental/ich/mod.rs [new file with mode: 0644]
src/librustc_incremental/lib.rs
src/librustc_incremental/persist/data.rs
src/librustc_incremental/persist/dirty_clean.rs
src/librustc_incremental/persist/hash.rs
src/librustc_incremental/persist/load.rs
src/librustc_incremental/persist/preds.rs
src/librustc_incremental/persist/save.rs
src/librustc_trans/back/link.rs

diff --git a/src/librustc_data_structures/blake2b.rs b/src/librustc_data_structures/blake2b.rs
new file mode 100644 (file)
index 0000000..996df2e
--- /dev/null
@@ -0,0 +1,286 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+
+// An implementation of the Blake2b cryptographic hash function.
+// The implementation closely follows: https://tools.ietf.org/html/rfc7693
+//
+// "BLAKE2 is a cryptographic hash function faster than MD5, SHA-1, SHA-2, and
+//  SHA-3, yet is at least as secure as the latest standard SHA-3."
+// according to their own website :)
+//
+// Indeed this implementation is two to three times as fast as our SHA-256
+// implementation. If you have the luxury of being able to use crates from
+// crates.io, you can go there and find still faster implementations.
+
+pub struct Blake2bCtx {
+    b: [u8; 128],
+    h: [u64; 8],
+    t: [u64; 2],
+    c: usize,
+    outlen: usize,
+}
+
+impl ::std::fmt::Debug for Blake2bCtx {
+    fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> {
+        write!(fmt, "{:?}", self.h)
+    }
+}
+
+#[inline(always)]
+fn b2b_g(v: &mut [u64; 16],
+         a: usize,
+         b: usize,
+         c: usize,
+         d: usize,
+         x: u64,
+         y: u64)
+{
+    v[a] = v[a].wrapping_add(v[b]).wrapping_add(x);
+    v[d] = (v[d] ^ v[a]).rotate_right(32);
+    v[c] = v[c].wrapping_add(v[d]);
+    v[b] = (v[b] ^ v[c]).rotate_right(24);
+    v[a] = v[a].wrapping_add(v[b]).wrapping_add(y);
+    v[d] = (v[d] ^ v[a]).rotate_right(16);
+    v[c] = v[c].wrapping_add(v[d]);
+    v[b] = (v[b] ^ v[c]).rotate_right(63);
+}
+
+// Initialization vector
+const BLAKE2B_IV: [u64; 8] = [
+   0x6A09E667F3BCC908, 0xBB67AE8584CAA73B,
+   0x3C6EF372FE94F82B, 0xA54FF53A5F1D36F1,
+   0x510E527FADE682D1, 0x9B05688C2B3E6C1F,
+   0x1F83D9ABFB41BD6B, 0x5BE0CD19137E2179
+];
+
+fn blake2b_compress(ctx: &mut Blake2bCtx, last: bool) {
+
+    const SIGMA: [[usize; 16]; 12] = [
+        [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ],
+        [14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 ],
+        [11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 ],
+        [7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 ],
+        [9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 ],
+        [2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 ],
+        [12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 ],
+        [13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 ],
+        [6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 ],
+        [10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0 ],
+        [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ],
+        [14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 ]
+    ];
+
+    let mut v: [u64; 16] = [
+        ctx.h[0],
+        ctx.h[1],
+        ctx.h[2],
+        ctx.h[3],
+        ctx.h[4],
+        ctx.h[5],
+        ctx.h[6],
+        ctx.h[7],
+
+        BLAKE2B_IV[0],
+        BLAKE2B_IV[1],
+        BLAKE2B_IV[2],
+        BLAKE2B_IV[3],
+        BLAKE2B_IV[4],
+        BLAKE2B_IV[5],
+        BLAKE2B_IV[6],
+        BLAKE2B_IV[7],
+    ];
+
+    v[12] ^= ctx.t[0]; // low 64 bits of offset
+    v[13] ^= ctx.t[1]; // high 64 bits
+    if last {
+        v[14] = !v[14];
+    }
+
+    {
+        // Re-interpret the input buffer in the state as u64s
+        let m: &mut [u64; 16] = unsafe {
+            let b: &mut [u8; 128] = &mut ctx.b;
+            ::std::mem::transmute(b)
+        };
+
+        // It's OK to modify the buffer in place since this is the last time
+        // this data will be accessed before it's overwritten
+        if cfg!(target_endian = "big") {
+            for word in &mut m[..] {
+                *word = word.to_be();
+            }
+        }
+
+        for i in 0 .. 12 {
+            b2b_g(&mut v, 0, 4,  8, 12, m[SIGMA[i][ 0]], m[SIGMA[i][ 1]]);
+            b2b_g(&mut v, 1, 5,  9, 13, m[SIGMA[i][ 2]], m[SIGMA[i][ 3]]);
+            b2b_g(&mut v, 2, 6, 10, 14, m[SIGMA[i][ 4]], m[SIGMA[i][ 5]]);
+            b2b_g(&mut v, 3, 7, 11, 15, m[SIGMA[i][ 6]], m[SIGMA[i][ 7]]);
+            b2b_g(&mut v, 0, 5, 10, 15, m[SIGMA[i][ 8]], m[SIGMA[i][ 9]]);
+            b2b_g(&mut v, 1, 6, 11, 12, m[SIGMA[i][10]], m[SIGMA[i][11]]);
+            b2b_g(&mut v, 2, 7,  8, 13, m[SIGMA[i][12]], m[SIGMA[i][13]]);
+            b2b_g(&mut v, 3, 4,  9, 14, m[SIGMA[i][14]], m[SIGMA[i][15]]);
+        }
+    }
+
+    for i in 0 .. 8 {
+        ctx.h[i] ^= v[i] ^ v[i + 8];
+    }
+}
+
+pub fn blake2b_new(outlen: usize, key: &[u8]) -> Blake2bCtx {
+    assert!(outlen > 0 && outlen <= 64 && key.len() <= 64);
+
+    let mut ctx = Blake2bCtx {
+        b: [0; 128],
+        h: BLAKE2B_IV,
+        t: [0; 2],
+        c: 0,
+        outlen: outlen,
+    };
+
+    ctx.h[0] ^= 0x01010000 ^ ((key.len() << 8) as u64) ^ (outlen as u64);
+
+    if key.len() > 0 {
+       blake2b_update(&mut ctx, key);
+       ctx.c = ctx.b.len();
+    }
+
+    ctx
+}
+
+pub fn blake2b_update(ctx: &mut Blake2bCtx, mut data: &[u8])
+{
+    let mut bytes_to_copy = data.len();
+    let mut space_in_buffer = ctx.b.len() - ctx.c;
+
+    while bytes_to_copy > space_in_buffer {
+        checked_mem_copy(data, &mut ctx.b[ctx.c .. ], space_in_buffer);
+
+        ctx.t[0] = ctx.t[0].wrapping_add(ctx.b.len() as u64);
+        if ctx.t[0] < (ctx.b.len() as u64) {
+            ctx.t[1] += 1;
+        }
+        blake2b_compress(ctx, false);
+        ctx.c = 0;
+
+        data = &data[space_in_buffer .. ];
+        bytes_to_copy -= space_in_buffer;
+        space_in_buffer = ctx.b.len();
+    }
+
+    if bytes_to_copy > 0 {
+        checked_mem_copy(data, &mut ctx.b[ctx.c .. ], bytes_to_copy);
+        ctx.c += bytes_to_copy;
+    }
+}
+
+pub fn blake2b_final(mut ctx: Blake2bCtx, out: &mut [u8])
+{
+    ctx.t[0] = ctx.t[0].wrapping_add(ctx.c as u64);
+    if ctx.t[0] < ctx.c as u64 {
+        ctx.t[1] += 1;
+    }
+
+    while ctx.c < 128 {
+        ctx.b[ctx.c] = 0;
+        ctx.c += 1;
+    }
+
+    blake2b_compress(&mut ctx, true);
+
+    if cfg!(target_endian = "big") {
+        // Make sure that the data is in memory in little endian format, as is
+        // demanded by BLAKE2
+        for word in &mut ctx.h {
+            *word = word.to_le();
+        }
+    }
+
+    checked_mem_copy(&ctx.h, out, ctx.outlen);
+}
+
+#[inline(always)]
+fn checked_mem_copy<T1, T2>(from: &[T1], to: &mut [T2], byte_count: usize) {
+    let from_size = from.len() * ::std::mem::size_of::<T1>();
+    let to_size = to.len() * ::std::mem::size_of::<T2>();
+    assert!(from_size >= byte_count);
+    assert!(to_size >= byte_count);
+    let from_byte_ptr = from.as_ptr() as * const u8;
+    let to_byte_ptr = to.as_mut_ptr() as * mut u8;
+    unsafe {
+        ::std::ptr::copy_nonoverlapping(from_byte_ptr, to_byte_ptr, byte_count);
+    }
+}
+
+pub fn blake2b(out: &mut [u8], key: &[u8],  data: &[u8])
+{
+    let mut ctx = blake2b_new(out.len(), key);
+    blake2b_update(&mut ctx, data);
+    blake2b_final(ctx, out);
+}
+
+#[cfg(test)]
+fn selftest_seq(out: &mut [u8], seed: u32)
+{
+   let mut a: u32 = 0xDEAD4BADu32.wrapping_mul(seed);
+   let mut b: u32 = 1;
+
+   for i in 0 .. out.len() {
+       let t: u32 = a.wrapping_add(b);
+       a = b;
+       b = t;
+       out[i] = ((t >> 24) & 0xFF) as u8;
+   }
+}
+
+#[test]
+fn blake2b_selftest()
+{
+    // grand hash of hash results
+    const BLAKE2B_RES: [u8; 32] = [
+        0xC2, 0x3A, 0x78, 0x00, 0xD9, 0x81, 0x23, 0xBD,
+        0x10, 0xF5, 0x06, 0xC6, 0x1E, 0x29, 0xDA, 0x56,
+        0x03, 0xD7, 0x63, 0xB8, 0xBB, 0xAD, 0x2E, 0x73,
+        0x7F, 0x5E, 0x76, 0x5A, 0x7B, 0xCC, 0xD4, 0x75
+    ];
+
+    // parameter sets
+    const B2B_MD_LEN: [usize; 4] = [20, 32, 48, 64];
+    const B2B_IN_LEN: [usize; 6] = [0, 3, 128, 129, 255, 1024];
+
+    let mut data = [0u8; 1024];
+    let mut md = [0u8; 64];
+    let mut key = [0u8; 64];
+
+    let mut ctx = blake2b_new(32, &[]);
+
+    for i in 0 .. 4 {
+       let outlen = B2B_MD_LEN[i];
+       for j in 0 .. 6 {
+            let inlen = B2B_IN_LEN[j];
+
+            selftest_seq(&mut data[.. inlen], inlen as u32); // unkeyed hash
+            blake2b(&mut md[.. outlen], &[], &data[.. inlen]);
+            blake2b_update(&mut ctx, &md[.. outlen]); // hash the hash
+
+            selftest_seq(&mut key[0 .. outlen], outlen as u32); // keyed hash
+            blake2b(&mut md[.. outlen], &key[.. outlen], &data[.. inlen]);
+            blake2b_update(&mut ctx, &md[.. outlen]); // hash the hash
+       }
+    }
+
+    // compute and compare the hash of hashes
+    blake2b_final(ctx, &mut md[..]);
+    for i in 0 .. 32 {
+        assert_eq!(md[i], BLAKE2B_RES[i]);
+    }
+}
index c8f4d766153cf9788b26ff8d00963b5a7abc5340..26b9f48ad04dd4041eb879e9b34dfad2098120c5 100644 (file)
@@ -42,6 +42,7 @@
 extern crate libc;
 
 pub mod bitslice;
+pub mod blake2b;
 pub mod bitvec;
 pub mod graph;
 pub mod ivar;
index 28db39d667c4c864012fc34c8537b4b8af05bc53..d92a8d375e0d3d76d1ec52560c30f38fc40627c4 100644 (file)
@@ -9,20 +9,20 @@
 // except according to those terms.
 
 use std::hash::Hasher;
-use std::collections::hash_map::DefaultHasher;
+use std::mem;
+use rustc_data_structures::blake2b;
+use ich::Fingerprint;
 
 #[derive(Debug)]
 pub struct IchHasher {
-    // FIXME: this should use SHA1, not DefaultHasher. DefaultHasher is not
-    // built to avoid collisions.
-    state: DefaultHasher,
+    state: blake2b::Blake2bCtx,
     bytes_hashed: u64,
 }
 
 impl IchHasher {
     pub fn new() -> IchHasher {
         IchHasher {
-            state: DefaultHasher::new(),
+            state: blake2b::blake2b_new(mem::size_of::<Fingerprint>(), &[]),
             bytes_hashed: 0
         }
     }
@@ -30,17 +30,43 @@ pub fn new() -> IchHasher {
     pub fn bytes_hashed(&self) -> u64 {
         self.bytes_hashed
     }
+
+    pub fn finish(self) -> Fingerprint {
+        let mut fingerprint = Fingerprint::zero();
+        blake2b::blake2b_final(self.state, &mut fingerprint.0);
+        fingerprint
+    }
 }
 
 impl Hasher for IchHasher {
-    #[inline]
     fn finish(&self) -> u64 {
-        self.state.finish()
+        bug!("Use other finish() implementation to get the full 128-bit hash.");
     }
 
     #[inline]
     fn write(&mut self, bytes: &[u8]) {
-        self.state.write(bytes);
+        blake2b::blake2b_update(&mut self.state, bytes);
         self.bytes_hashed += bytes.len() as u64;
     }
+
+    #[inline]
+    fn write_u16(&mut self, i: u16) {
+        self.write(&unsafe { mem::transmute::<_, [u8; 2]>(i.to_le()) })
+    }
+
+    #[inline]
+    fn write_u32(&mut self, i: u32) {
+        self.write(&unsafe { mem::transmute::<_, [u8; 4]>(i.to_le()) })
+    }
+
+    #[inline]
+    fn write_u64(&mut self, i: u64) {
+        self.write(&unsafe { mem::transmute::<_, [u8; 8]>(i.to_le()) })
+    }
+
+    #[inline]
+    fn write_usize(&mut self, i: usize) {
+        // always hash as u64, so we don't depend on the size of `usize`
+        self.write_u64(i as u64);
+    }
 }
index 12627e02debd0d723427d028e1cad35a042a8603..3b0b37bb01ce31a57f76890506572b0dbd76d715 100644 (file)
@@ -29,7 +29,7 @@
 
 use syntax::ast;
 use std::cell::RefCell;
-use std::hash::{Hash, Hasher};
+use std::hash::Hash;
 use rustc::dep_graph::DepNode;
 use rustc::hir;
 use rustc::hir::def_id::{CRATE_DEF_INDEX, DefId};
 use self::svh_visitor::StrictVersionHashVisitor;
 use self::caching_codemap_view::CachingCodemapView;
 use self::hasher::IchHasher;
+use ich::Fingerprint;
 
 mod def_path_hash;
 mod svh_visitor;
 mod caching_codemap_view;
-mod hasher;
+pub mod hasher;
 
 pub struct IncrementalHashesMap {
-    hashes: FnvHashMap<DepNode<DefId>, u64>,
+    hashes: FnvHashMap<DepNode<DefId>, Fingerprint>,
 
     // These are the metadata hashes for the current crate as they were stored
     // during the last compilation session. They are only loaded if
     // -Z query-dep-graph was specified and are needed for auto-tests using
     // the #[rustc_metadata_dirty] and #[rustc_metadata_clean] attributes to
     // check whether some metadata hash has changed in between two revisions.
-    pub prev_metadata_hashes: RefCell<FnvHashMap<DefId, u64>>,
+    pub prev_metadata_hashes: RefCell<FnvHashMap<DefId, Fingerprint>>,
 }
 
 impl IncrementalHashesMap {
@@ -68,11 +69,12 @@ pub fn new() -> IncrementalHashesMap {
         }
     }
 
-    pub fn insert(&mut self, k: DepNode<DefId>, v: u64) -> Option<u64> {
+    pub fn insert(&mut self, k: DepNode<DefId>, v: Fingerprint) -> Option<Fingerprint> {
         self.hashes.insert(k, v)
     }
 
-    pub fn iter<'a>(&'a self) -> ::std::collections::hash_map::Iter<'a, DepNode<DefId>, u64> {
+    pub fn iter<'a>(&'a self)
+                    -> ::std::collections::hash_map::Iter<'a, DepNode<DefId>, Fingerprint> {
         self.hashes.iter()
     }
 
@@ -82,9 +84,9 @@ pub fn len(&self) -> usize {
 }
 
 impl<'a> ::std::ops::Index<&'a DepNode<DefId>> for IncrementalHashesMap {
-    type Output = u64;
+    type Output = Fingerprint;
 
-    fn index(&self, index: &'a DepNode<DefId>) -> &u64 {
+    fn index(&self, index: &'a DepNode<DefId>) -> &Fingerprint {
         &self.hashes[index]
     }
 }
@@ -141,12 +143,13 @@ fn calculate_def_id<W>(&mut self, def_id: DefId, mut walk_op: W)
                                                    &mut self.def_path_hashes,
                                                    &mut self.codemap,
                                                    self.hash_spans));
+        let bytes_hashed = state.bytes_hashed();
         let item_hash = state.finish();
         self.hashes.insert(DepNode::Hir(def_id), item_hash);
         debug!("calculate_item_hash: def_id={:?} hash={:?}", def_id, item_hash);
 
         let bytes_hashed = self.tcx.sess.perf_stats.incr_comp_bytes_hashed.get() +
-                           state.bytes_hashed();
+                           bytes_hashed;
         self.tcx.sess.perf_stats.incr_comp_bytes_hashed.set(bytes_hashed);
     }
 
diff --git a/src/librustc_incremental/ich/fingerprint.rs b/src/librustc_incremental/ich/fingerprint.rs
new file mode 100644 (file)
index 0000000..005ac38
--- /dev/null
@@ -0,0 +1,81 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use rustc_serialize::{Encodable, Decodable, Encoder, Decoder};
+
+const FINGERPRINT_LENGTH: usize = 16;
+
+#[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Clone, Copy)]
+pub struct Fingerprint(pub [u8; FINGERPRINT_LENGTH]);
+
+impl Fingerprint {
+    #[inline]
+    pub fn zero() -> Fingerprint {
+        Fingerprint([0; FINGERPRINT_LENGTH])
+    }
+
+    pub fn from_smaller_hash(hash: u64) -> Fingerprint {
+        let mut result = Fingerprint::zero();
+        result.0[0] = (hash >>  0) as u8;
+        result.0[1] = (hash >>  8) as u8;
+        result.0[2] = (hash >> 16) as u8;
+        result.0[3] = (hash >> 24) as u8;
+        result.0[4] = (hash >> 32) as u8;
+        result.0[5] = (hash >> 40) as u8;
+        result.0[6] = (hash >> 48) as u8;
+        result.0[7] = (hash >> 56) as u8;
+        result
+    }
+
+    pub fn to_smaller_hash(&self) -> u64 {
+        ((self.0[0] as u64) <<  0) |
+        ((self.0[1] as u64) <<  8) |
+        ((self.0[2] as u64) << 16) |
+        ((self.0[3] as u64) << 24) |
+        ((self.0[4] as u64) << 32) |
+        ((self.0[5] as u64) << 40) |
+        ((self.0[6] as u64) << 48) |
+        ((self.0[7] as u64) << 56)
+    }
+}
+
+impl Encodable for Fingerprint {
+    #[inline]
+    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
+        for &byte in &self.0[..] {
+            s.emit_u8(byte)?;
+        }
+        Ok(())
+    }
+}
+
+impl Decodable for Fingerprint {
+    #[inline]
+    fn decode<D: Decoder>(d: &mut D) -> Result<Fingerprint, D::Error> {
+        let mut result = Fingerprint([0u8; FINGERPRINT_LENGTH]);
+        for byte in &mut result.0[..] {
+            *byte = d.read_u8()?;
+        }
+        Ok(result)
+    }
+}
+
+impl ::std::fmt::Display for Fingerprint {
+    fn fmt(&self, formatter: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> {
+        for i in 0 .. self.0.len() {
+            if i > 0 {
+                write!(formatter, "::")?;
+            }
+
+            write!(formatter, "{}", self.0[i])?;
+        }
+        Ok(())
+    }
+}
diff --git a/src/librustc_incremental/ich/mod.rs b/src/librustc_incremental/ich/mod.rs
new file mode 100644 (file)
index 0000000..8edd043
--- /dev/null
@@ -0,0 +1,13 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+pub use self::fingerprint::Fingerprint;
+
+mod fingerprint;
index 67104e912f90ecc9a0a7ecfa9739b5eb1c584976..577e50699bffd5310d0011feb112ea830a84fed9 100644 (file)
@@ -45,6 +45,7 @@
 mod assert_dep_graph;
 mod calculate_svh;
 mod persist;
+pub mod ich;
 
 pub use assert_dep_graph::assert_dep_graph;
 pub use calculate_svh::compute_incremental_hashes_map;
index 57e7a0bc21a4ec6ca979af5e442555cd9b76c02f..734ffe6a94412024405564a6685cc5048ede21da 100644 (file)
@@ -14,6 +14,7 @@
 use rustc::hir::def_id::DefIndex;
 use std::sync::Arc;
 use rustc_data_structures::fnv::FnvHashMap;
+use ich::Fingerprint;
 
 use super::directory::DefPathIndex;
 
@@ -60,7 +61,7 @@ pub struct SerializedHash {
 
     /// the hash as of previous compilation, computed by code in
     /// `hash` module
-    pub hash: u64,
+    pub hash: Fingerprint,
 }
 
 #[derive(Debug, RustcEncodable, RustcDecodable)]
@@ -116,5 +117,5 @@ pub struct SerializedMetadataHash {
     pub def_index: DefIndex,
 
     /// the hash itself, computed by `calculate_item_hash`
-    pub hash: u64,
+    pub hash: Fingerprint,
 }
index 95452021d878487019c154621f070c4021399aaa..0418148ffc7df6f374e559b26bd654b316092a68 100644 (file)
@@ -51,6 +51,7 @@
 use syntax::parse::token::InternedString;
 use syntax_pos::Span;
 use rustc::ty::TyCtxt;
+use ich::Fingerprint;
 
 use {ATTR_DIRTY, ATTR_CLEAN, ATTR_DIRTY_METADATA, ATTR_CLEAN_METADATA};
 
@@ -186,8 +187,8 @@ fn visit_item(&mut self, item: &'tcx hir::Item) {
 }
 
 pub fn check_dirty_clean_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                                  prev_metadata_hashes: &FnvHashMap<DefId, u64>,
-                                  current_metadata_hashes: &FnvHashMap<DefId, u64>) {
+                                  prev_metadata_hashes: &FnvHashMap<DefId, Fingerprint>,
+                                  current_metadata_hashes: &FnvHashMap<DefId, Fingerprint>) {
     if !tcx.sess.opts.debugging_opts.query_dep_graph {
         return;
     }
@@ -204,8 +205,8 @@ pub fn check_dirty_clean_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
 pub struct DirtyCleanMetadataVisitor<'a, 'tcx:'a, 'm> {
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
-    prev_metadata_hashes: &'m FnvHashMap<DefId, u64>,
-    current_metadata_hashes: &'m FnvHashMap<DefId, u64>,
+    prev_metadata_hashes: &'m FnvHashMap<DefId, Fingerprint>,
+    current_metadata_hashes: &'m FnvHashMap<DefId, Fingerprint>,
 }
 
 impl<'a, 'tcx, 'm> Visitor<'tcx> for DirtyCleanMetadataVisitor<'a, 'tcx, 'm> {
index ca173db15fcac37e303aff0beb9b16bb3a29bfd5..e365cbbd3a9a10b417a4301cf77f96eaab44e1f9 100644 (file)
@@ -18,6 +18,7 @@
 use rustc_serialize::opaque::Decoder;
 
 use IncrementalHashesMap;
+use ich::Fingerprint;
 use super::data::*;
 use super::fs::*;
 use super::file_format;
@@ -25,7 +26,7 @@
 pub struct HashContext<'a, 'tcx: 'a> {
     pub tcx: TyCtxt<'a, 'tcx, 'tcx>,
     incremental_hashes_map: &'a IncrementalHashesMap,
-    item_metadata_hashes: FnvHashMap<DefId, u64>,
+    item_metadata_hashes: FnvHashMap<DefId, Fingerprint>,
     crate_hashes: FnvHashMap<CrateNum, Svh>,
 }
 
@@ -50,7 +51,7 @@ pub fn is_hashable(dep_node: &DepNode<DefId>) -> bool {
         }
     }
 
-    pub fn hash(&mut self, dep_node: &DepNode<DefId>) -> Option<u64> {
+    pub fn hash(&mut self, dep_node: &DepNode<DefId>) -> Option<Fingerprint> {
         match *dep_node {
             DepNode::Krate => {
                 Some(self.incremental_hashes_map[dep_node])
@@ -89,7 +90,7 @@ pub fn hash(&mut self, dep_node: &DepNode<DefId>) -> Option<u64> {
         }
     }
 
-    fn metadata_hash(&mut self, def_id: DefId) -> u64 {
+    fn metadata_hash(&mut self, def_id: DefId) -> Fingerprint {
         debug!("metadata_hash(def_id={:?})", def_id);
 
         assert!(!def_id.is_local());
@@ -102,14 +103,15 @@ fn metadata_hash(&mut self, def_id: DefId) -> u64 {
 
             // check whether we did not find detailed metadata for this
             // krate; in that case, we just use the krate's overall hash
-            if let Some(&hash) = self.crate_hashes.get(&def_id.krate) {
-                debug!("metadata_hash: def_id={:?} crate_hash={:?}", def_id, hash);
+            if let Some(&svh) = self.crate_hashes.get(&def_id.krate) {
+                debug!("metadata_hash: def_id={:?} crate_hash={:?}", def_id, svh);
 
                 // micro-"optimization": avoid a cache miss if we ask
                 // for metadata from this particular def-id again.
-                self.item_metadata_hashes.insert(def_id, hash.as_u64());
+                let fingerprint = svh_to_fingerprint(svh);
+                self.item_metadata_hashes.insert(def_id, fingerprint);
 
-                return hash.as_u64();
+                return fingerprint;
             }
 
             // otherwise, load the data and repeat.
@@ -206,3 +208,7 @@ fn load_from_data(&mut self,
         Ok(())
     }
 }
+
+fn svh_to_fingerprint(svh: Svh) -> Fingerprint {
+    Fingerprint::from_smaller_hash(svh.as_u64())
+}
index db8d3125e510bf3f388e90f7c9054058485d5be2..1f43e79ace3ae67a6df3f2473770689c06d9a88f 100644 (file)
@@ -22,6 +22,7 @@
 use std::path::{Path};
 
 use IncrementalHashesMap;
+use ich::Fingerprint;
 use super::data::*;
 use super::directory::*;
 use super::dirty_clean;
@@ -315,7 +316,7 @@ fn delete_dirty_work_product(tcx: TyCtxt,
 
 fn load_prev_metadata_hashes(tcx: TyCtxt,
                              retraced: &RetracedDefIdDirectory,
-                             output: &mut FnvHashMap<DefId, u64>) {
+                             output: &mut FnvHashMap<DefId, Fingerprint>) {
     if !tcx.sess.opts.debugging_opts.query_dep_graph {
         return
     }
index af13484e4288d54174ee0763d4beb44717cebd27..fe1d627253f286a16c455bae6450be9dfb5cbdfe 100644 (file)
@@ -14,6 +14,7 @@
 use rustc_data_structures::graph::{DepthFirstTraversal, INCOMING, NodeIndex};
 
 use super::hash::*;
+use ich::Fingerprint;
 
 /// A data-structure that makes it easy to enumerate the hashable
 /// predecessors of any given dep-node.
@@ -26,7 +27,7 @@ pub struct Predecessors<'query> {
 
     // - Keys: some hashable node
     // - Values: the hash thereof
-    pub hashes: FnvHashMap<&'query DepNode<DefId>, u64>,
+    pub hashes: FnvHashMap<&'query DepNode<DefId>, Fingerprint>,
 }
 
 impl<'q> Predecessors<'q> {
index bc542b71ac670c76d49d16ee85d5587b4c788f15..bc156b0e8913b21a159a1825eb43ecd93858ad82 100644 (file)
 use rustc_data_structures::fnv::FnvHashMap;
 use rustc_serialize::Encodable as RustcEncodable;
 use rustc_serialize::opaque::Encoder;
-use std::hash::{Hash, Hasher};
+use std::hash::Hash;
 use std::io::{self, Cursor, Write};
 use std::fs::{self, File};
 use std::path::PathBuf;
-use std::collections::hash_map::DefaultHasher;
 
 use IncrementalHashesMap;
+use ich::Fingerprint;
 use super::data::*;
 use super::directory::*;
 use super::hash::*;
@@ -30,6 +30,7 @@
 use super::fs::*;
 use super::dirty_clean;
 use super::file_format;
+use calculate_svh::hasher::IchHasher;
 
 pub fn save_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                 incremental_hashes_map: &IncrementalHashesMap,
@@ -185,7 +186,7 @@ pub fn encode_metadata_hashes(tcx: TyCtxt,
                               svh: Svh,
                               preds: &Predecessors,
                               builder: &mut DefIdDirectoryBuilder,
-                              current_metadata_hashes: &mut FnvHashMap<DefId, u64>,
+                              current_metadata_hashes: &mut FnvHashMap<DefId, Fingerprint>,
                               encoder: &mut Encoder)
                               -> io::Result<()> {
     // For each `MetaData(X)` node where `X` is local, accumulate a
@@ -233,7 +234,7 @@ pub fn encode_metadata_hashes(tcx: TyCtxt,
         // is the det. hash of the def-path. This is convenient
         // because we can sort this to get a stable ordering across
         // compilations, even if the def-ids themselves have changed.
-        let mut hashes: Vec<(DepNode<u64>, u64)> = sources.iter()
+        let mut hashes: Vec<(DepNode<u64>, Fingerprint)> = sources.iter()
             .map(|dep_node| {
                 let hash_dep_node = dep_node.map_def(|&def_id| Some(def_id_hash(def_id))).unwrap();
                 let hash = preds.hashes[dep_node];
@@ -242,7 +243,7 @@ pub fn encode_metadata_hashes(tcx: TyCtxt,
             .collect();
 
         hashes.sort();
-        let mut state = DefaultHasher::new();
+        let mut state = IchHasher::new();
         hashes.hash(&mut state);
         let hash = state.finish();
 
index 5a8c5cb4b82c6f3543abc27ac041b773edcfe113..e46bdbb5ccf4ae9399151e621a7caacd548afeca 100644 (file)
@@ -130,7 +130,7 @@ pub fn build_link_meta(incremental_hashes_map: &IncrementalHashesMap,
                        -> LinkMeta {
     let r = LinkMeta {
         crate_name: name.to_owned(),
-        crate_hash: Svh::new(incremental_hashes_map[&DepNode::Krate]),
+        crate_hash: Svh::new(incremental_hashes_map[&DepNode::Krate].to_smaller_hash()),
     };
     info!("{:?}", r);
     return r;