libcore: Remove mutable fields from hash
This commit is contained in:
parent
2961997f16
commit
4dc1c2976d
6 changed files with 160 additions and 111 deletions
|
@ -19,12 +19,16 @@
|
|||
* CPRNG like rand::rng.
|
||||
*/
|
||||
|
||||
use io;
|
||||
use io::Writer;
|
||||
#[cfg(stage0)]
|
||||
use cast;
|
||||
use rt::io::Writer;
|
||||
use to_bytes::IterBytes;
|
||||
use uint;
|
||||
use vec;
|
||||
|
||||
// Alias `SipState` to `State`.
|
||||
pub use State = hash::SipState;
|
||||
|
||||
/**
|
||||
* Types that can meaningfully be hashed should implement this.
|
||||
*
|
||||
|
@ -65,20 +69,32 @@ impl<A:Hash> HashUtil for A {
|
|||
|
||||
/// Streaming hash-functions should implement this.
|
||||
pub trait Streaming {
|
||||
fn input(&self, (&const [u8]));
|
||||
fn input(&mut self, &[u8]);
|
||||
// These can be refactored some when we have default methods.
|
||||
fn result_bytes(&self) -> ~[u8];
|
||||
fn result_str(&self) -> ~str;
|
||||
fn result_u64(&self) -> u64;
|
||||
fn reset(&self);
|
||||
fn result_bytes(&mut self) -> ~[u8];
|
||||
fn result_str(&mut self) -> ~str;
|
||||
fn result_u64(&mut self) -> u64;
|
||||
fn reset(&mut self);
|
||||
}
|
||||
|
||||
// XXX: Ugly workaround for bootstrapping.
|
||||
#[cfg(stage0)]
|
||||
fn transmute_for_stage0<'a>(bytes: &'a [const u8]) -> &'a [u8] {
|
||||
unsafe {
|
||||
cast::transmute(bytes)
|
||||
}
|
||||
}
|
||||
#[cfg(not(stage0))]
|
||||
fn transmute_for_stage0<'a>(bytes: &'a [u8]) -> &'a [u8] {
|
||||
bytes
|
||||
}
|
||||
|
||||
impl<A:IterBytes> Hash for A {
|
||||
#[inline(always)]
|
||||
fn hash_keyed(&self, k0: u64, k1: u64) -> u64 {
|
||||
let s = &State(k0, k1);
|
||||
let mut s = State::new(k0, k1);
|
||||
for self.iter_bytes(true) |bytes| {
|
||||
s.input(bytes);
|
||||
s.input(transmute_for_stage0(bytes));
|
||||
}
|
||||
s.result_u64()
|
||||
}
|
||||
|
@ -86,32 +102,56 @@ impl<A:IterBytes> Hash for A {
|
|||
|
||||
fn hash_keyed_2<A: IterBytes,
|
||||
B: IterBytes>(a: &A, b: &B, k0: u64, k1: u64) -> u64 {
|
||||
let s = &State(k0, k1);
|
||||
for a.iter_bytes(true) |bytes| { s.input(bytes); }
|
||||
for b.iter_bytes(true) |bytes| { s.input(bytes); }
|
||||
let mut s = State::new(k0, k1);
|
||||
for a.iter_bytes(true) |bytes| {
|
||||
s.input(transmute_for_stage0(bytes));
|
||||
}
|
||||
for b.iter_bytes(true) |bytes| {
|
||||
s.input(transmute_for_stage0(bytes));
|
||||
}
|
||||
s.result_u64()
|
||||
}
|
||||
|
||||
fn hash_keyed_3<A: IterBytes,
|
||||
B: IterBytes,
|
||||
C: IterBytes>(a: &A, b: &B, c: &C, k0: u64, k1: u64) -> u64 {
|
||||
let s = &State(k0, k1);
|
||||
for a.iter_bytes(true) |bytes| { s.input(bytes); }
|
||||
for b.iter_bytes(true) |bytes| { s.input(bytes); }
|
||||
for c.iter_bytes(true) |bytes| { s.input(bytes); }
|
||||
let mut s = State::new(k0, k1);
|
||||
for a.iter_bytes(true) |bytes| {
|
||||
s.input(transmute_for_stage0(bytes));
|
||||
}
|
||||
for b.iter_bytes(true) |bytes| {
|
||||
s.input(transmute_for_stage0(bytes));
|
||||
}
|
||||
for c.iter_bytes(true) |bytes| {
|
||||
s.input(transmute_for_stage0(bytes));
|
||||
}
|
||||
s.result_u64()
|
||||
}
|
||||
|
||||
fn hash_keyed_4<A: IterBytes,
|
||||
B: IterBytes,
|
||||
C: IterBytes,
|
||||
D: IterBytes>(a: &A, b: &B, c: &C, d: &D, k0: u64, k1: u64)
|
||||
-> u64 {
|
||||
let s = &State(k0, k1);
|
||||
for a.iter_bytes(true) |bytes| { s.input(bytes); }
|
||||
for b.iter_bytes(true) |bytes| { s.input(bytes); }
|
||||
for c.iter_bytes(true) |bytes| { s.input(bytes); }
|
||||
for d.iter_bytes(true) |bytes| { s.input(bytes); }
|
||||
D: IterBytes>(
|
||||
a: &A,
|
||||
b: &B,
|
||||
c: &C,
|
||||
d: &D,
|
||||
k0: u64,
|
||||
k1: u64)
|
||||
-> u64 {
|
||||
let mut s = State::new(k0, k1);
|
||||
for a.iter_bytes(true) |bytes| {
|
||||
s.input(transmute_for_stage0(bytes));
|
||||
}
|
||||
for b.iter_bytes(true) |bytes| {
|
||||
s.input(transmute_for_stage0(bytes));
|
||||
}
|
||||
for c.iter_bytes(true) |bytes| {
|
||||
s.input(transmute_for_stage0(bytes));
|
||||
}
|
||||
for d.iter_bytes(true) |bytes| {
|
||||
s.input(transmute_for_stage0(bytes));
|
||||
}
|
||||
s.result_u64()
|
||||
}
|
||||
|
||||
|
@ -119,58 +159,68 @@ fn hash_keyed_5<A: IterBytes,
|
|||
B: IterBytes,
|
||||
C: IterBytes,
|
||||
D: IterBytes,
|
||||
E: IterBytes>(a: &A, b: &B, c: &C, d: &D, e: &E,
|
||||
k0: u64, k1: u64) -> u64 {
|
||||
let s = &State(k0, k1);
|
||||
for a.iter_bytes(true) |bytes| { s.input(bytes); }
|
||||
for b.iter_bytes(true) |bytes| { s.input(bytes); }
|
||||
for c.iter_bytes(true) |bytes| { s.input(bytes); }
|
||||
for d.iter_bytes(true) |bytes| { s.input(bytes); }
|
||||
for e.iter_bytes(true) |bytes| { s.input(bytes); }
|
||||
E: IterBytes>(
|
||||
a: &A,
|
||||
b: &B,
|
||||
c: &C,
|
||||
d: &D,
|
||||
e: &E,
|
||||
k0: u64,
|
||||
k1: u64)
|
||||
-> u64 {
|
||||
let mut s = State::new(k0, k1);
|
||||
for a.iter_bytes(true) |bytes| {
|
||||
s.input(transmute_for_stage0(bytes));
|
||||
}
|
||||
for b.iter_bytes(true) |bytes| {
|
||||
s.input(transmute_for_stage0(bytes));
|
||||
}
|
||||
for c.iter_bytes(true) |bytes| {
|
||||
s.input(transmute_for_stage0(bytes));
|
||||
}
|
||||
for d.iter_bytes(true) |bytes| {
|
||||
s.input(transmute_for_stage0(bytes));
|
||||
}
|
||||
for e.iter_bytes(true) |bytes| {
|
||||
s.input(transmute_for_stage0(bytes));
|
||||
}
|
||||
s.result_u64()
|
||||
}
|
||||
|
||||
// Implement State as SipState
|
||||
|
||||
pub type State = SipState;
|
||||
|
||||
#[inline(always)]
|
||||
pub fn State(k0: u64, k1: u64) -> State {
|
||||
SipState(k0, k1)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn default_state() -> State {
|
||||
State(0,0)
|
||||
State::new(0, 0)
|
||||
}
|
||||
|
||||
struct SipState {
|
||||
k0: u64,
|
||||
k1: u64,
|
||||
mut length: uint, // how many bytes we've processed
|
||||
mut v0: u64, // hash state
|
||||
mut v1: u64,
|
||||
mut v2: u64,
|
||||
mut v3: u64,
|
||||
mut tail: [u8, ..8], // unprocessed bytes
|
||||
mut ntail: uint, // how many bytes in tail are valid
|
||||
length: uint, // how many bytes we've processed
|
||||
v0: u64, // hash state
|
||||
v1: u64,
|
||||
v2: u64,
|
||||
v3: u64,
|
||||
tail: [u8, ..8], // unprocessed bytes
|
||||
ntail: uint, // how many bytes in tail are valid
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn SipState(key0: u64, key1: u64) -> SipState {
|
||||
let state = SipState {
|
||||
k0 : key0,
|
||||
k1 : key1,
|
||||
mut length : 0u,
|
||||
mut v0 : 0u64,
|
||||
mut v1 : 0u64,
|
||||
mut v2 : 0u64,
|
||||
mut v3 : 0u64,
|
||||
mut tail : [0u8,0,0,0,0,0,0,0],
|
||||
mut ntail : 0u,
|
||||
};
|
||||
(&state).reset();
|
||||
state
|
||||
impl SipState {
|
||||
#[inline(always)]
|
||||
fn new(key0: u64, key1: u64) -> SipState {
|
||||
let mut state = SipState {
|
||||
k0: key0,
|
||||
k1: key1,
|
||||
length: 0,
|
||||
v0: 0,
|
||||
v1: 0,
|
||||
v2: 0,
|
||||
v3: 0,
|
||||
tail: [ 0, 0, 0, 0, 0, 0, 0, 0 ],
|
||||
ntail: 0,
|
||||
};
|
||||
state.reset();
|
||||
state
|
||||
}
|
||||
}
|
||||
|
||||
// sadly, these macro definitions can't appear later,
|
||||
|
@ -207,12 +257,10 @@ macro_rules! compress (
|
|||
)
|
||||
|
||||
|
||||
impl io::Writer for SipState {
|
||||
|
||||
impl Writer for SipState {
|
||||
// Methods for io::writer
|
||||
#[inline(always)]
|
||||
fn write(&self, msg: &const [u8]) {
|
||||
|
||||
fn write(&mut self, msg: &[u8]) {
|
||||
let length = msg.len();
|
||||
self.length += length;
|
||||
|
||||
|
@ -272,29 +320,19 @@ impl io::Writer for SipState {
|
|||
self.ntail = left;
|
||||
}
|
||||
|
||||
fn seek(&self, _x: int, _s: io::SeekStyle) {
|
||||
fail!();
|
||||
}
|
||||
fn tell(&self) -> uint {
|
||||
self.length
|
||||
}
|
||||
fn flush(&self) -> int {
|
||||
0
|
||||
}
|
||||
fn get_type(&self) -> io::WriterType {
|
||||
io::File
|
||||
fn flush(&mut self) {
|
||||
// No-op
|
||||
}
|
||||
}
|
||||
|
||||
impl Streaming for SipState {
|
||||
|
||||
#[inline(always)]
|
||||
fn input(&self, buf: &const [u8]) {
|
||||
fn input(&mut self, buf: &[u8]) {
|
||||
self.write(buf);
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn result_u64(&self) -> u64 {
|
||||
fn result_u64(&mut self) -> u64 {
|
||||
let mut v0 = self.v0;
|
||||
let mut v1 = self.v1;
|
||||
let mut v2 = self.v2;
|
||||
|
@ -324,7 +362,7 @@ impl Streaming for SipState {
|
|||
return (v0 ^ v1 ^ v2 ^ v3);
|
||||
}
|
||||
|
||||
fn result_bytes(&self) -> ~[u8] {
|
||||
fn result_bytes(&mut self) -> ~[u8] {
|
||||
let h = self.result_u64();
|
||||
~[(h >> 0) as u8,
|
||||
(h >> 8) as u8,
|
||||
|
@ -337,7 +375,7 @@ impl Streaming for SipState {
|
|||
]
|
||||
}
|
||||
|
||||
fn result_str(&self) -> ~str {
|
||||
fn result_str(&mut self) -> ~str {
|
||||
let r = self.result_bytes();
|
||||
let mut s = ~"";
|
||||
for vec::each(r) |b| {
|
||||
|
@ -347,7 +385,7 @@ impl Streaming for SipState {
|
|||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn reset(&self) {
|
||||
fn reset(&mut self) {
|
||||
self.length = 0;
|
||||
self.v0 = self.k0 ^ 0x736f6d6570736575;
|
||||
self.v1 = self.k1 ^ 0x646f72616e646f6d;
|
||||
|
@ -529,4 +567,4 @@ mod tests {
|
|||
val & !(0xff << (byte * 8))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,9 +22,9 @@ use util::ppaux;
|
|||
|
||||
use core::hash::Streaming;
|
||||
use core::hash;
|
||||
use core::io::WriterUtil;
|
||||
use core::libc::{c_int, c_uint};
|
||||
use core::os::consts::{macos, freebsd, linux, android, win32};
|
||||
use core::rt::io::Writer;
|
||||
use core::run;
|
||||
use syntax::ast;
|
||||
use syntax::ast_map::{path, path_mod, path_name};
|
||||
|
@ -41,6 +41,11 @@ pub enum output_type {
|
|||
output_type_exe,
|
||||
}
|
||||
|
||||
fn write_string<W:Writer>(writer: &mut W, string: &str) {
|
||||
let buffer = str::as_bytes_slice(string);
|
||||
writer.write(buffer);
|
||||
}
|
||||
|
||||
pub fn llvm_err(sess: Session, msg: ~str) -> ! {
|
||||
unsafe {
|
||||
let cstr = llvm::LLVMRustGetLastError();
|
||||
|
@ -458,9 +463,11 @@ pub mod write {
|
|||
*
|
||||
*/
|
||||
|
||||
pub fn build_link_meta(sess: Session, c: &ast::crate, output: &Path,
|
||||
symbol_hasher: &hash::State) -> LinkMeta {
|
||||
|
||||
pub fn build_link_meta(sess: Session,
|
||||
c: &ast::crate,
|
||||
output: &Path,
|
||||
symbol_hasher: &mut hash::State)
|
||||
-> LinkMeta {
|
||||
struct ProvidedMetas {
|
||||
name: Option<@str>,
|
||||
vers: Option<@str>,
|
||||
|
@ -498,7 +505,7 @@ pub fn build_link_meta(sess: Session, c: &ast::crate, output: &Path,
|
|||
}
|
||||
|
||||
// This calculates CMH as defined above
|
||||
fn crate_meta_extras_hash(symbol_hasher: &hash::State,
|
||||
fn crate_meta_extras_hash(symbol_hasher: &mut hash::State,
|
||||
cmh_items: ~[@ast::meta_item],
|
||||
dep_hashes: ~[~str]) -> @str {
|
||||
fn len_and_str(s: &str) -> ~str {
|
||||
|
@ -511,17 +518,17 @@ pub fn build_link_meta(sess: Session, c: &ast::crate, output: &Path,
|
|||
|
||||
let cmh_items = attr::sort_meta_items(cmh_items);
|
||||
|
||||
fn hash(symbol_hasher: &hash::State, m: &@ast::meta_item) {
|
||||
fn hash(symbol_hasher: &mut hash::State, m: &@ast::meta_item) {
|
||||
match m.node {
|
||||
ast::meta_name_value(key, value) => {
|
||||
symbol_hasher.write_str(len_and_str(*key));
|
||||
symbol_hasher.write_str(len_and_str_lit(value));
|
||||
write_string(symbol_hasher, len_and_str(*key));
|
||||
write_string(symbol_hasher, len_and_str_lit(value));
|
||||
}
|
||||
ast::meta_word(name) => {
|
||||
symbol_hasher.write_str(len_and_str(*name));
|
||||
write_string(symbol_hasher, len_and_str(*name));
|
||||
}
|
||||
ast::meta_list(name, ref mis) => {
|
||||
symbol_hasher.write_str(len_and_str(*name));
|
||||
write_string(symbol_hasher, len_and_str(*name));
|
||||
for mis.each |m_| {
|
||||
hash(symbol_hasher, m_);
|
||||
}
|
||||
|
@ -535,7 +542,7 @@ pub fn build_link_meta(sess: Session, c: &ast::crate, output: &Path,
|
|||
}
|
||||
|
||||
for dep_hashes.each |dh| {
|
||||
symbol_hasher.write_str(len_and_str(*dh));
|
||||
write_string(symbol_hasher, len_and_str(*dh));
|
||||
}
|
||||
|
||||
// tjc: allocation is unfortunate; need to change core::hash
|
||||
|
@ -596,23 +603,26 @@ pub fn build_link_meta(sess: Session, c: &ast::crate, output: &Path,
|
|||
}
|
||||
}
|
||||
|
||||
pub fn truncated_hash_result(symbol_hasher: &hash::State) -> ~str {
|
||||
pub fn truncated_hash_result(symbol_hasher: &mut hash::State) -> ~str {
|
||||
symbol_hasher.result_str()
|
||||
}
|
||||
|
||||
|
||||
// This calculates STH for a symbol, as defined above
|
||||
pub fn symbol_hash(tcx: ty::ctxt, symbol_hasher: &hash::State, t: ty::t,
|
||||
link_meta: LinkMeta) -> @str {
|
||||
pub fn symbol_hash(tcx: ty::ctxt,
|
||||
symbol_hasher: &mut hash::State,
|
||||
t: ty::t,
|
||||
link_meta: LinkMeta)
|
||||
-> @str {
|
||||
// NB: do *not* use abbrevs here as we want the symbol names
|
||||
// to be independent of one another in the crate.
|
||||
|
||||
symbol_hasher.reset();
|
||||
symbol_hasher.write_str(link_meta.name);
|
||||
symbol_hasher.write_str(~"-");
|
||||
symbol_hasher.write_str(link_meta.extras_hash);
|
||||
symbol_hasher.write_str(~"-");
|
||||
symbol_hasher.write_str(encoder::encoded_ty(tcx, t));
|
||||
write_string(symbol_hasher, link_meta.name);
|
||||
write_string(symbol_hasher, ~"-");
|
||||
write_string(symbol_hasher, link_meta.extras_hash);
|
||||
write_string(symbol_hasher, ~"-");
|
||||
write_string(symbol_hasher, encoder::encoded_ty(tcx, t));
|
||||
let mut hash = truncated_hash_result(symbol_hasher);
|
||||
// Prefix with _ so that it never blends into adjacent digits
|
||||
str::unshift_char(&mut hash, '_');
|
||||
|
|
|
@ -2987,9 +2987,8 @@ pub fn trans_crate(sess: session::Session,
|
|||
emap2: resolve::ExportMap2,
|
||||
maps: astencode::Maps) -> (ModuleRef, LinkMeta) {
|
||||
|
||||
let symbol_hasher = @hash::default_state();
|
||||
let link_meta =
|
||||
link::build_link_meta(sess, crate, output, symbol_hasher);
|
||||
let symbol_hasher = @mut hash::default_state();
|
||||
let link_meta = link::build_link_meta(sess, crate, output, symbol_hasher);
|
||||
let reachable = reachable::find_reachable(
|
||||
&crate.node.module,
|
||||
emap2,
|
||||
|
|
|
@ -207,7 +207,7 @@ pub struct CrateContext {
|
|||
adt_reprs: @mut HashMap<ty::t, @adt::Repr>,
|
||||
names: namegen,
|
||||
next_addrspace: addrspace_gen,
|
||||
symbol_hasher: @hash::State,
|
||||
symbol_hasher: @mut hash::State,
|
||||
type_hashcodes: @mut HashMap<ty::t, @str>,
|
||||
type_short_names: @mut HashMap<ty::t, ~str>,
|
||||
all_llvm_symbols: @mut HashSet<@~str>,
|
||||
|
|
|
@ -230,6 +230,7 @@ pub fn future_writer_factory(
|
|||
let markdown_ch = markdown_ch.clone();
|
||||
do task::spawn || {
|
||||
let (writer, future) = future_writer();
|
||||
let mut future = future;
|
||||
writer_ch.send(writer);
|
||||
let s = future.get();
|
||||
markdown_ch.send((copy page, s));
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
use core::*;
|
||||
use core::cmp::Ord;
|
||||
use core::hash::Streaming;
|
||||
use core::rt::io::Writer;
|
||||
use rustc::driver::{driver, session};
|
||||
use rustc::driver::session::{lib_crate, unknown_crate};
|
||||
use rustc::metadata::filesearch;
|
||||
|
@ -367,9 +368,9 @@ pub fn error(msg: ~str) {
|
|||
}
|
||||
|
||||
pub fn hash(data: ~str) -> ~str {
|
||||
let hasher = &hash::default_state();
|
||||
|
||||
hasher.write_str(data);
|
||||
let mut hasher = hash::default_state();
|
||||
let buffer = str::as_bytes_slice(data);
|
||||
hasher.write(buffer);
|
||||
hasher.result_str()
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue