From 4dc1c2976d03b6e0fc114019341be51593ef49b2 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Fri, 3 May 2013 11:30:30 -0700 Subject: [PATCH] libcore: Remove mutable fields from hash --- src/libcore/hash.rs | 208 ++++++++++++++++------------ src/librustc/back/link.rs | 48 ++++--- src/librustc/middle/trans/base.rs | 5 +- src/librustc/middle/trans/common.rs | 2 +- src/librustdoc/markdown_writer.rs | 1 + src/librustpkg/util.rs | 7 +- 6 files changed, 160 insertions(+), 111 deletions(-) diff --git a/src/libcore/hash.rs b/src/libcore/hash.rs index ba1f8cebdb01..486f0e096e8a 100644 --- a/src/libcore/hash.rs +++ b/src/libcore/hash.rs @@ -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 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 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 Hash for A { fn hash_keyed_2(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: &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: &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: &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)) } } -} \ No newline at end of file +} diff --git a/src/librustc/back/link.rs b/src/librustc/back/link.rs index c34c7fe303ee..3b5c90ec1f96 100644 --- a/src/librustc/back/link.rs +++ b/src/librustc/back/link.rs @@ -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(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, '_'); diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index 34f798ec7a63..76ad7d740536 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -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, diff --git a/src/librustc/middle/trans/common.rs b/src/librustc/middle/trans/common.rs index b004ba9d41f3..c1309b422880 100644 --- a/src/librustc/middle/trans/common.rs +++ b/src/librustc/middle/trans/common.rs @@ -207,7 +207,7 @@ pub struct CrateContext { adt_reprs: @mut HashMap, names: namegen, next_addrspace: addrspace_gen, - symbol_hasher: @hash::State, + symbol_hasher: @mut hash::State, type_hashcodes: @mut HashMap, type_short_names: @mut HashMap, all_llvm_symbols: @mut HashSet<@~str>, diff --git a/src/librustdoc/markdown_writer.rs b/src/librustdoc/markdown_writer.rs index b9a2ee7ccb7c..fc5a9a60df29 100644 --- a/src/librustdoc/markdown_writer.rs +++ b/src/librustdoc/markdown_writer.rs @@ -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)); diff --git a/src/librustpkg/util.rs b/src/librustpkg/util.rs index 0762fa4ad7fd..5e43cb439607 100644 --- a/src/librustpkg/util.rs +++ b/src/librustpkg/util.rs @@ -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() }