From bec7b766fbbc9b56a1608e2573390e3894519840 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 28 Feb 2014 14:34:26 -0800 Subject: [PATCH 1/2] rustc: Move to FNV hashing for node/def ids This leverages the new hashing framework and hashmap implementation to provide a much speedier hashing algorithm for node ids and def ids. The hash algorithm used is currentl FNV hashing, but it's quite easy to swap out. I originally implemented hashing as the identity function, but this actually ended up in slowing down rustc compiling libstd from 8s to 13s. I would suspect that this is a result of a large number of collisions. With FNV hashing, we get these timings (compiling with --no-trans, in seconds): | | before | after | |-----------|---------:|--------:| | libstd | 8.324 | 6.703 | | stdtest | 47.674 | 46.857 | | libsyntax | 9.918 | 8.400 | --- src/librustc/driver/driver.rs | 5 +- src/librustc/lib.rs | 3 +- src/librustc/metadata/encoder.rs | 11 +- src/librustc/middle/cfg/construct.rs | 6 +- src/librustc/middle/cfg/mod.rs | 4 +- src/librustc/middle/const_eval.rs | 17 ++-- src/librustc/middle/dataflow.rs | 6 +- src/librustc/middle/dead.rs | 7 +- src/librustc/middle/freevars.rs | 14 +-- src/librustc/middle/liveness.rs | 20 ++-- src/librustc/middle/moves.rs | 14 +-- src/librustc/middle/privacy.rs | 20 ++-- src/librustc/middle/reachable.rs | 9 +- src/librustc/middle/region.rs | 13 +-- src/librustc/middle/resolve.rs | 25 ++--- src/librustc/middle/resolve_lifetime.rs | 6 +- src/librustc/middle/trans/base.rs | 7 +- src/librustc/middle/trans/common.rs | 7 +- src/librustc/middle/trans/context.rs | 37 +++---- src/librustc/middle/trans/expr.rs | 5 +- src/librustc/middle/ty.rs | 127 ++++++++++++------------ src/librustc/middle/typeck/check/mod.rs | 21 ++-- src/librustc/middle/typeck/mod.rs | 12 +-- src/librustc/util/nodemap.rs | 80 +++++++++++++++ src/librustdoc/html/render.rs | 5 +- src/librustdoc/passes.rs | 3 +- src/libsyntax/util/nodemap.rs | 75 ++++++++++++++ 27 files changed, 364 insertions(+), 195 deletions(-) create mode 100644 src/librustc/util/nodemap.rs create mode 100644 src/libsyntax/util/nodemap.rs diff --git a/src/librustc/driver/driver.rs b/src/librustc/driver/driver.rs index c4f3bb2105900..58eb2119c6af9 100644 --- a/src/librustc/driver/driver.rs +++ b/src/librustc/driver/driver.rs @@ -27,6 +27,7 @@ use middle::{trans, freevars, kind, ty, typeck, lint, astencode, reachable}; use middle; use util::common::time; use util::ppaux; +use util::nodemap::NodeSet; use serialize::{json, Encodable}; @@ -38,7 +39,7 @@ use std::os; use std::vec; use std::vec_ng::Vec; use std::vec_ng; -use collections::{HashMap, HashSet}; +use collections::HashMap; use getopts::{optopt, optmulti, optflag, optflagopt, opt}; use MaybeHasArg = getopts::Maybe; use OccurOptional = getopts::Optional; @@ -258,7 +259,7 @@ pub struct CrateAnalysis { public_items: middle::privacy::PublicItems, ty_cx: ty::ctxt, maps: astencode::Maps, - reachable: @RefCell> + reachable: @RefCell, } /// Run the resolution, typechecking, region checking and other diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index 2e68fdd14237b..d1560abf773d1 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -29,7 +29,7 @@ This API is completely unstable and subject to change. #[allow(deprecated)]; #[feature(macro_rules, globs, struct_variant, managed_boxes)]; -#[feature(quote)]; +#[feature(quote, default_type_params)]; extern crate extra; extern crate flate; @@ -125,6 +125,7 @@ pub mod util { pub mod common; pub mod ppaux; pub mod sha2; + pub mod nodemap; } pub mod lib { diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs index 80bb5d23aa446..7d5688ba19ba3 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -23,6 +23,7 @@ use middle::astencode; use middle::ty; use middle::typeck; use middle; +use util::nodemap::{NodeMap, NodeSet}; use serialize::Encodable; use std::cast; @@ -31,7 +32,7 @@ use std::hash; use std::hash::Hash; use std::io::MemWriter; use std::str; -use collections::{HashMap, HashSet}; +use collections::HashMap; use syntax::abi::AbiSet; use syntax::ast::*; use syntax::ast; @@ -69,8 +70,8 @@ pub struct EncodeParams<'a> { diag: @SpanHandler, tcx: ty::ctxt, reexports2: middle::resolve::ExportMap2, - item_symbols: &'a RefCell>, - non_inlineable_statics: &'a RefCell>, + item_symbols: &'a RefCell>, + non_inlineable_statics: &'a RefCell, link_meta: &'a LinkMeta, cstore: @cstore::CStore, encode_inlined_item: EncodeInlinedItem<'a>, @@ -97,8 +98,8 @@ pub struct EncodeContext<'a> { tcx: ty::ctxt, stats: @Stats, reexports2: middle::resolve::ExportMap2, - item_symbols: &'a RefCell>, - non_inlineable_statics: &'a RefCell>, + item_symbols: &'a RefCell>, + non_inlineable_statics: &'a RefCell, link_meta: &'a LinkMeta, cstore: &'a cstore::CStore, encode_inlined_item: EncodeInlinedItem<'a>, diff --git a/src/librustc/middle/cfg/construct.rs b/src/librustc/middle/cfg/construct.rs index 8a83147facebc..099ef284d95b1 100644 --- a/src/librustc/middle/cfg/construct.rs +++ b/src/librustc/middle/cfg/construct.rs @@ -12,15 +12,15 @@ use middle::cfg::*; use middle::graph; use middle::typeck; use middle::ty; -use collections::HashMap; use syntax::ast; use syntax::ast_util; use syntax::opt_vec; +use util::nodemap::NodeMap; struct CFGBuilder { tcx: ty::ctxt, method_map: typeck::MethodMap, - exit_map: HashMap, + exit_map: NodeMap, graph: CFGGraph, loop_scopes: ~[LoopScope], } @@ -35,7 +35,7 @@ pub fn construct(tcx: ty::ctxt, method_map: typeck::MethodMap, blk: &ast::Block) -> CFG { let mut cfg_builder = CFGBuilder { - exit_map: HashMap::new(), + exit_map: NodeMap::new(), graph: graph::Graph::new(), tcx: tcx, method_map: method_map, diff --git a/src/librustc/middle/cfg/mod.rs b/src/librustc/middle/cfg/mod.rs index d6d54b604c8c5..bdf39e3e8ec63 100644 --- a/src/librustc/middle/cfg/mod.rs +++ b/src/librustc/middle/cfg/mod.rs @@ -18,14 +18,14 @@ Uses `Graph` as the underlying representation. use middle::graph; use middle::ty; use middle::typeck; -use collections::HashMap; use syntax::ast; use syntax::opt_vec::OptVec; +use util::nodemap::NodeMap; mod construct; pub struct CFG { - exit_map: HashMap, + exit_map: NodeMap, graph: CFGGraph, entry: CFGIndex, exit: CFGIndex, diff --git a/src/librustc/middle/const_eval.rs b/src/librustc/middle/const_eval.rs index cd52f24b8eaee..effdbd8e45176 100644 --- a/src/librustc/middle/const_eval.rs +++ b/src/librustc/middle/const_eval.rs @@ -16,6 +16,7 @@ use middle::astencode; use middle::ty; use middle::typeck::astconv; use middle; +use util::nodemap::{DefIdMap, NodeMap}; use syntax::ast::*; use syntax::parse::token::InternedString; @@ -66,7 +67,7 @@ pub enum constness { non_const } -type constness_cache = HashMap; +type constness_cache = DefIdMap; pub fn join(a: constness, b: constness) -> constness { match (a, b) { @@ -134,9 +135,9 @@ pub fn lookup_variant_by_id(tcx: ty::ctxt, } let maps = astencode::Maps { root_map: @RefCell::new(HashMap::new()), - method_map: @RefCell::new(HashMap::new()), - vtable_map: @RefCell::new(HashMap::new()), - capture_map: @RefCell::new(HashMap::new()) + method_map: @RefCell::new(NodeMap::new()), + vtable_map: @RefCell::new(NodeMap::new()), + capture_map: @RefCell::new(NodeMap::new()) }; let e = match csearch::maybe_get_item_ast(tcx, enum_def, |a, b, c, d| astencode::decode_inlined_item(a, b, @@ -184,9 +185,9 @@ pub fn lookup_const_by_id(tcx: ty::ctxt, def_id: ast::DefId) } let maps = astencode::Maps { root_map: @RefCell::new(HashMap::new()), - method_map: @RefCell::new(HashMap::new()), - vtable_map: @RefCell::new(HashMap::new()), - capture_map: @RefCell::new(HashMap::new()) + method_map: @RefCell::new(NodeMap::new()), + vtable_map: @RefCell::new(NodeMap::new()), + capture_map: @RefCell::new(NodeMap::new()) }; let e = match csearch::maybe_get_item_ast(tcx, def_id, |a, b, c, d| astencode::decode_inlined_item(a, b, maps, c, d)) { @@ -305,7 +306,7 @@ pub fn process_crate(krate: &ast::Crate, tcx: ty::ctxt) { let mut v = ConstEvalVisitor { tcx: tcx, - ccache: HashMap::new(), + ccache: DefIdMap::new(), }; visit::walk_crate(&mut v, krate, ()); tcx.sess.abort_if_errors(); diff --git a/src/librustc/middle/dataflow.rs b/src/librustc/middle/dataflow.rs index 74acc10abc030..700a3d5a4a4c0 100644 --- a/src/librustc/middle/dataflow.rs +++ b/src/librustc/middle/dataflow.rs @@ -20,7 +20,6 @@ use std::io; use std::uint; use std::vec; -use collections::HashMap; use syntax::ast; use syntax::ast_util; use syntax::ast_util::IdRange; @@ -28,6 +27,7 @@ use syntax::print::{pp, pprust}; use middle::ty; use middle::typeck; use util::ppaux::Repr; +use util::nodemap::NodeMap; #[deriving(Clone)] pub struct DataFlowContext { @@ -45,7 +45,7 @@ pub struct DataFlowContext { priv words_per_id: uint, // mapping from node to bitset index. - priv nodeid_to_bitset: HashMap, + priv nodeid_to_bitset: NodeMap, // Bit sets per id. The following three fields (`gens`, `kills`, // and `on_entry`) all have the same structure. For each id in @@ -139,7 +139,7 @@ impl DataFlowContext { tcx: tcx, method_map: method_map, words_per_id: words_per_id, - nodeid_to_bitset: HashMap::new(), + nodeid_to_bitset: NodeMap::new(), bits_per_id: bits_per_id, oper: oper, gens: gens, diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs index a0a34ff4f32b5..eaf665119d3e2 100644 --- a/src/librustc/middle/dead.rs +++ b/src/librustc/middle/dead.rs @@ -16,6 +16,7 @@ use middle::lint::{allow, contains_lint, DeadCode}; use middle::privacy; use middle::ty; use middle::typeck; +use util::nodemap::NodeSet; use collections::HashSet; use syntax::ast; @@ -252,7 +253,7 @@ impl Visitor<()> for LifeSeeder { fn create_and_seed_worklist(tcx: ty::ctxt, exported_items: &privacy::ExportedItems, - reachable_symbols: &HashSet, + reachable_symbols: &NodeSet, krate: &ast::Crate) -> ~[ast::NodeId] { let mut worklist = ~[]; @@ -286,7 +287,7 @@ fn create_and_seed_worklist(tcx: ty::ctxt, fn find_live(tcx: ty::ctxt, method_map: typeck::MethodMap, exported_items: &privacy::ExportedItems, - reachable_symbols: &HashSet, + reachable_symbols: &NodeSet, krate: &ast::Crate) -> ~HashSet { let worklist = create_and_seed_worklist(tcx, exported_items, @@ -409,7 +410,7 @@ impl Visitor<()> for DeadVisitor { pub fn check_crate(tcx: ty::ctxt, method_map: typeck::MethodMap, exported_items: &privacy::ExportedItems, - reachable_symbols: &HashSet, + reachable_symbols: &NodeSet, krate: &ast::Crate) { let live_symbols = find_live(tcx, method_map, exported_items, reachable_symbols, krate); diff --git a/src/librustc/middle/freevars.rs b/src/librustc/middle/freevars.rs index 9ff67377c5902..b41398b440156 100644 --- a/src/librustc/middle/freevars.rs +++ b/src/librustc/middle/freevars.rs @@ -15,8 +15,8 @@ use middle::resolve; use middle::ty; +use util::nodemap::{NodeMap, NodeSet}; -use collections::HashMap; use syntax::codemap::Span; use syntax::{ast, ast_util}; use syntax::visit; @@ -30,10 +30,10 @@ pub struct freevar_entry { span: Span //< First span where it is accessed (there can be multiple) } pub type freevar_info = @~[@freevar_entry]; -pub type freevar_map = HashMap; +pub type freevar_map = NodeMap; struct CollectFreevarsVisitor { - seen: HashMap, + seen: NodeSet, refs: ~[@freevar_entry], def_map: resolve::DefMap, } @@ -65,12 +65,12 @@ impl Visitor for CollectFreevarsVisitor { } if i == depth { // Made it to end of loop let dnum = ast_util::def_id_of_def(def).node; - if !self.seen.contains_key(&dnum) { + if !self.seen.contains(&dnum) { self.refs.push(@freevar_entry { def: def, span: expr.span, }); - self.seen.insert(dnum, ()); + self.seen.insert(dnum); } } } @@ -89,7 +89,7 @@ impl Visitor for CollectFreevarsVisitor { // of the AST, we take a walker function that we invoke with a visitor // in order to start the search. fn collect_freevars(def_map: resolve::DefMap, blk: &ast::Block) -> freevar_info { - let seen = HashMap::new(); + let seen = NodeSet::new(); let refs = ~[]; let mut v = CollectFreevarsVisitor { @@ -129,7 +129,7 @@ pub fn annotate_freevars(def_map: resolve::DefMap, krate: &ast::Crate) -> freevar_map { let mut visitor = AnnotateFreevarsVisitor { def_map: def_map, - freevars: HashMap::new(), + freevars: NodeMap::new(), }; visit::walk_crate(&mut visitor, krate, ()); diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index f12c8ad0c829c..3ae85bbd6c7ac 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -108,6 +108,7 @@ use middle::pat_util; use middle::ty; use middle::typeck; use middle::moves; +use util::nodemap::NodeMap; use std::cast::transmute; use std::cell::{Cell, RefCell}; @@ -116,7 +117,6 @@ use std::io; use std::str; use std::uint; use std::vec; -use collections::HashMap; use syntax::ast::*; use syntax::codemap::Span; use syntax::parse::token::special_idents; @@ -258,9 +258,9 @@ pub struct IrMaps { num_live_nodes: Cell, num_vars: Cell, - live_node_map: RefCell>, - variable_map: RefCell>, - capture_info_map: RefCell>, + live_node_map: RefCell>, + variable_map: RefCell>, + capture_info_map: RefCell>, var_kinds: RefCell<~[VarKind]>, lnks: RefCell<~[LiveNodeKind]>, } @@ -275,9 +275,9 @@ fn IrMaps(tcx: ty::ctxt, capture_map: capture_map, num_live_nodes: Cell::new(0), num_vars: Cell::new(0), - live_node_map: RefCell::new(HashMap::new()), - variable_map: RefCell::new(HashMap::new()), - capture_info_map: RefCell::new(HashMap::new()), + live_node_map: RefCell::new(NodeMap::new()), + variable_map: RefCell::new(NodeMap::new()), + capture_info_map: RefCell::new(NodeMap::new()), var_kinds: RefCell::new(~[]), lnks: RefCell::new(~[]), } @@ -584,7 +584,7 @@ static ACC_READ: uint = 1u; static ACC_WRITE: uint = 2u; static ACC_USE: uint = 4u; -pub type LiveNodeMap = @RefCell>; +pub type LiveNodeMap = @RefCell>; pub struct Liveness { tcx: ty::ctxt, @@ -613,8 +613,8 @@ fn Liveness(ir: @IrMaps, specials: Specials) -> Liveness { ir.num_vars.get(), invalid_users())), loop_scope: @RefCell::new(~[]), - break_ln: @RefCell::new(HashMap::new()), - cont_ln: @RefCell::new(HashMap::new()), + break_ln: @RefCell::new(NodeMap::new()), + cont_ln: @RefCell::new(NodeMap::new()), } } diff --git a/src/librustc/middle/moves.rs b/src/librustc/middle/moves.rs index dc4325fdd72ae..41ea80cff28e7 100644 --- a/src/librustc/middle/moves.rs +++ b/src/librustc/middle/moves.rs @@ -135,10 +135,10 @@ use util::ppaux; use util::ppaux::Repr; use util::common::indenter; use util::ppaux::UserString; +use util::nodemap::{NodeMap, NodeSet}; use std::cell::RefCell; use std::rc::Rc; -use collections::{HashSet, HashMap}; use syntax::ast::*; use syntax::ast_util; use syntax::visit; @@ -159,9 +159,9 @@ pub struct CaptureVar { mode: CaptureMode // How variable is being accessed } -pub type CaptureMap = @RefCell>>; +pub type CaptureMap = @RefCell>>; -pub type MovesMap = @RefCell>; +pub type MovesMap = @RefCell; /** * Set of variable node-ids that are moved. @@ -169,7 +169,7 @@ pub type MovesMap = @RefCell>; * Note: The `VariableMovesMap` stores expression ids that * are moves, whereas this set stores the ids of the variables * that are moved at some point */ -pub type MovedVariablesSet = @RefCell>; +pub type MovedVariablesSet = @RefCell; /** See the section Output on the module comment for explanation. */ #[deriving(Clone)] @@ -215,9 +215,9 @@ pub fn compute_moves(tcx: ty::ctxt, tcx: tcx, method_map: method_map, move_maps: MoveMaps { - moves_map: @RefCell::new(HashSet::new()), - capture_map: @RefCell::new(HashMap::new()), - moved_variables_set: @RefCell::new(HashSet::new()) + moves_map: @RefCell::new(NodeSet::new()), + capture_map: @RefCell::new(NodeMap::new()), + moved_variables_set: @RefCell::new(NodeSet::new()) } }; let visit_cx = &mut visit_cx; diff --git a/src/librustc/middle/privacy.rs b/src/librustc/middle/privacy.rs index 3d90566ee7931..182a52817b258 100644 --- a/src/librustc/middle/privacy.rs +++ b/src/librustc/middle/privacy.rs @@ -13,7 +13,6 @@ //! which are available for use externally when compiled as a library. use std::mem::replace; -use collections::{HashSet, HashMap}; use metadata::csearch; use middle::lint; @@ -21,6 +20,7 @@ use middle::resolve; use middle::ty; use middle::typeck::{MethodMap, MethodOrigin, MethodParam}; use middle::typeck::{MethodStatic, MethodObject}; +use util::nodemap::{NodeMap, NodeSet}; use syntax::ast; use syntax::ast_map; @@ -35,12 +35,12 @@ use syntax::visit::Visitor; type Context<'a> = (&'a MethodMap, &'a resolve::ExportMap2); /// A set of AST nodes exported by the crate. -pub type ExportedItems = HashSet; +pub type ExportedItems = NodeSet; /// A set of AST nodes that are fully public in the crate. This map is used for /// documentation purposes (reexporting a private struct inlines the doc, /// reexporting a public struct doesn't inline the doc). -pub type PublicItems = HashSet; +pub type PublicItems = NodeSet; /// Result of a checking operation - None => no errors were found. Some => an /// error and contains the span and message for reporting that error and @@ -52,7 +52,7 @@ type CheckResult = Option<(Span, ~str, Option<(Span, ~str)>)>; //////////////////////////////////////////////////////////////////////////////// struct ParentVisitor { - parents: HashMap, + parents: NodeMap, curparent: ast::NodeId, } @@ -161,7 +161,7 @@ struct EmbargoVisitor<'a> { // all nodes which are reexported *and* reachable from external crates. This // means that the destination of the reexport is exported, and hence the // destination must also be exported. - reexports: HashSet, + reexports: NodeSet, // These two fields are closely related to one another in that they are only // used for generation of the 'PublicItems' set, not for privacy checking at @@ -349,7 +349,7 @@ struct PrivacyVisitor<'a> { in_fn: bool, in_foreign: bool, method_map: &'a MethodMap, - parents: HashMap, + parents: NodeMap, external_exports: resolve::ExternalExports, last_private_map: resolve::LastPrivateMap, } @@ -1424,7 +1424,7 @@ pub fn check_crate(tcx: ty::ctxt, krate: &ast::Crate) -> (ExportedItems, PublicItems) { // Figure out who everyone's parent is let mut visitor = ParentVisitor { - parents: HashMap::new(), + parents: NodeMap::new(), curparent: ast::DUMMY_NODE_ID, }; visit::walk_crate(&mut visitor, krate, ()); @@ -1456,9 +1456,9 @@ pub fn check_crate(tcx: ty::ctxt, // items which are reachable from external crates based on visibility. let mut visitor = EmbargoVisitor { tcx: tcx, - exported_items: HashSet::new(), - public_items: HashSet::new(), - reexports: HashSet::new(), + exported_items: NodeSet::new(), + public_items: NodeSet::new(), + reexports: NodeSet::new(), exp_map2: exp_map2, prev_exported: true, prev_public: true, diff --git a/src/librustc/middle/reachable.rs b/src/librustc/middle/reachable.rs index 305c60d8215c9..4ade65294d9e4 100644 --- a/src/librustc/middle/reachable.rs +++ b/src/librustc/middle/reachable.rs @@ -18,6 +18,7 @@ use middle::ty; use middle::typeck; use middle::privacy; +use util::nodemap::NodeSet; use std::cell::RefCell; use collections::HashSet; @@ -88,7 +89,7 @@ struct ReachableContext { // methods they've been resolved to. method_map: typeck::MethodMap, // The set of items which must be exported in the linkage sense. - reachable_symbols: @RefCell>, + reachable_symbols: @RefCell, // A worklist of item IDs. Each item ID in this worklist will be inlined // and will be scanned for further references. worklist: @RefCell<~[ast::NodeId]>, @@ -98,7 +99,7 @@ struct MarkSymbolVisitor { worklist: @RefCell<~[ast::NodeId]>, method_map: typeck::MethodMap, tcx: ty::ctxt, - reachable_symbols: @RefCell>, + reachable_symbols: @RefCell, } impl Visitor<()> for MarkSymbolVisitor { @@ -188,7 +189,7 @@ impl ReachableContext { ReachableContext { tcx: tcx, method_map: method_map, - reachable_symbols: @RefCell::new(HashSet::new()), + reachable_symbols: @RefCell::new(NodeSet::new()), worklist: @RefCell::new(~[]), } } @@ -395,7 +396,7 @@ impl ReachableContext { pub fn find_reachable(tcx: ty::ctxt, method_map: typeck::MethodMap, exported_items: &privacy::ExportedItems) - -> @RefCell> { + -> @RefCell { let reachable_context = ReachableContext::new(tcx, method_map); // Step 1: Seed the worklist with all nodes which were found to be public as diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs index 9e1552ae35e1b..07b68900ba5f1 100644 --- a/src/librustc/middle/region.rs +++ b/src/librustc/middle/region.rs @@ -24,6 +24,7 @@ Most of the documentation on regions can be found in use driver::session::Session; use middle::ty::{FreeRegion}; use middle::ty; +use util::nodemap::NodeMap; use std::cell::RefCell; use collections::{HashMap, HashSet}; @@ -74,10 +75,10 @@ The region maps encode information about region relationships. for dynamic checks and/or arbitrary amounts of stack space. */ pub struct RegionMaps { - priv scope_map: RefCell>, - priv var_map: RefCell>, + priv scope_map: RefCell>, + priv var_map: RefCell>, priv free_region_map: RefCell>, - priv rvalue_scopes: RefCell>, + priv rvalue_scopes: RefCell>, priv terminating_scopes: RefCell>, } @@ -910,10 +911,10 @@ impl<'a> Visitor for RegionResolutionVisitor<'a> { pub fn resolve_crate(sess: Session, krate: &ast::Crate) -> RegionMaps { let maps = RegionMaps { - scope_map: RefCell::new(HashMap::new()), - var_map: RefCell::new(HashMap::new()), + scope_map: RefCell::new(NodeMap::new()), + var_map: RefCell::new(NodeMap::new()), free_region_map: RefCell::new(HashMap::new()), - rvalue_scopes: RefCell::new(HashMap::new()), + rvalue_scopes: RefCell::new(NodeMap::new()), terminating_scopes: RefCell::new(HashSet::new()), }; { diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs index 0e61629f17864..46faf5b040fcf 100644 --- a/src/librustc/middle/resolve.rs +++ b/src/librustc/middle/resolve.rs @@ -16,6 +16,7 @@ use metadata::decoder::{DefLike, DlDef, DlField, DlImpl}; use middle::lang_items::LanguageItems; use middle::lint::{UnnecessaryQualification, UnusedImports}; use middle::pat_util::pat_bindings; +use util::nodemap::{NodeMap, DefIdSet}; use syntax::ast::*; use syntax::ast; @@ -36,7 +37,7 @@ use std::mem::replace; use collections::{HashMap, HashSet}; // Definition mapping -pub type DefMap = @RefCell>; +pub type DefMap = @RefCell>; struct binding_info { span: Span, @@ -47,11 +48,11 @@ struct binding_info { type BindingMap = HashMap; // Trait method resolution -pub type TraitMap = HashMap; +pub type TraitMap = NodeMap<~[DefId]>; // This is the replacement export map. It maps a module to all of the exports // within. -pub type ExportMap2 = @RefCell>; +pub type ExportMap2 = @RefCell>; pub struct Export2 { name: ~str, // The name of the target. @@ -60,10 +61,10 @@ pub struct Export2 { // This set contains all exported definitions from external crates. The set does // not contain any entries from local crates. -pub type ExternalExports = HashSet; +pub type ExternalExports = DefIdSet; // FIXME: dox -pub type LastPrivateMap = HashMap; +pub type LastPrivateMap = NodeMap; pub enum LastPrivate { LastMod(PrivateDep), @@ -457,7 +458,7 @@ struct Module { // // There will be an anonymous module created around `g` with the ID of the // entry block for `f`. - anonymous_children: RefCell>, + anonymous_children: RefCell>, // The status of resolving each import in this module. import_resolutions: RefCell>, @@ -489,7 +490,7 @@ impl Module { children: RefCell::new(HashMap::new()), imports: RefCell::new(~[]), external_module_children: RefCell::new(HashMap::new()), - anonymous_children: RefCell::new(HashMap::new()), + anonymous_children: RefCell::new(NodeMap::new()), import_resolutions: RefCell::new(HashMap::new()), glob_count: Cell::new(0), resolved_import_count: Cell::new(0), @@ -827,12 +828,12 @@ fn Resolver(session: Session, namespaces: ~[ TypeNS, ValueNS ], - def_map: @RefCell::new(HashMap::new()), - export_map2: @RefCell::new(HashMap::new()), - trait_map: HashMap::new(), + def_map: @RefCell::new(NodeMap::new()), + export_map2: @RefCell::new(NodeMap::new()), + trait_map: NodeMap::new(), used_imports: HashSet::new(), - external_exports: HashSet::new(), - last_private: HashMap::new(), + external_exports: DefIdSet::new(), + last_private: NodeMap::new(), emit_errors: true, }; diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs index 4e780f45111b5..c8e28d45e3cf1 100644 --- a/src/librustc/middle/resolve_lifetime.rs +++ b/src/librustc/middle/resolve_lifetime.rs @@ -19,7 +19,7 @@ use driver::session; use std::cell::RefCell; -use collections::HashMap; +use util::nodemap::NodeMap; use syntax::ast; use syntax::codemap::Span; use syntax::opt_vec::OptVec; @@ -31,7 +31,7 @@ use syntax::visit::Visitor; // maps the id of each lifetime reference to the lifetime decl // that it corresponds to -pub type NamedRegionMap = HashMap; +pub type NamedRegionMap = NodeMap; struct LifetimeContext { sess: session::Session, @@ -49,7 +49,7 @@ pub fn krate(sess: session::Session, krate: &ast::Crate) -> @RefCell { let mut ctxt = LifetimeContext { sess: sess, - named_region_map: @RefCell::new(HashMap::new()) + named_region_map: @RefCell::new(NodeMap::new()) }; visit::walk_crate(&mut ctxt, krate, &RootScope); sess.abort_if_errors(); diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index 6a1fe8611e521..625b130d47af9 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -70,6 +70,7 @@ use middle::typeck; use util::common::indenter; use util::ppaux::{Repr, ty_to_str}; use util::sha2::Sha256; +use util::nodemap::NodeMap; use arena::TypedArena; use std::c_str::ToCStr; @@ -1245,9 +1246,9 @@ pub fn new_fn_ctxt<'a>(ccx: @CrateContext, llreturn: Cell::new(None), personality: Cell::new(None), caller_expects_out_pointer: uses_outptr, - llargs: RefCell::new(HashMap::new()), - lllocals: RefCell::new(HashMap::new()), - llupvars: RefCell::new(HashMap::new()), + llargs: RefCell::new(NodeMap::new()), + lllocals: RefCell::new(NodeMap::new()), + llupvars: RefCell::new(NodeMap::new()), id: id, param_substs: param_substs, span: sp, diff --git a/src/librustc/middle/trans/common.rs b/src/librustc/middle/trans/common.rs index de36074d2e690..90f3765183388 100644 --- a/src/librustc/middle/trans/common.rs +++ b/src/librustc/middle/trans/common.rs @@ -29,6 +29,7 @@ use middle::ty::substs; use middle::ty; use middle::typeck; use util::ppaux::Repr; +use util::nodemap::NodeMap; use arena::TypedArena; use std::c_str::ToCStr; @@ -253,14 +254,14 @@ pub struct FunctionContext<'a> { caller_expects_out_pointer: bool, // Maps arguments to allocas created for them in llallocas. - llargs: RefCell>, + llargs: RefCell>, // Maps the def_ids for local variables to the allocas created for // them in llallocas. - lllocals: RefCell>, + lllocals: RefCell>, // Same as above, but for closure upvars - llupvars: RefCell>, + llupvars: RefCell>, // The NodeId of the function, or -1 if it doesn't correspond to // a user-defined function. diff --git a/src/librustc/middle/trans/context.rs b/src/librustc/middle/trans/context.rs index 5011ee8be6e4d..652336ecc000b 100644 --- a/src/librustc/middle/trans/context.rs +++ b/src/librustc/middle/trans/context.rs @@ -27,6 +27,7 @@ use middle::trans::debuginfo; use middle::trans::type_::Type; use middle::ty; use util::sha2::Sha256; +use util::nodemap::{NodeMap, NodeSet, DefIdMap}; use std::cell::{Cell, RefCell}; use std::c_str::ToCStr; @@ -45,10 +46,10 @@ pub struct CrateContext { tn: TypeNames, externs: RefCell, intrinsics: HashMap<&'static str, ValueRef>, - item_vals: RefCell>, + item_vals: RefCell>, exp_map2: resolve::ExportMap2, - reachable: @RefCell>, - item_symbols: RefCell>, + reachable: @RefCell, + item_symbols: RefCell>, link_meta: LinkMeta, drop_glues: RefCell>, tydescs: RefCell>, @@ -56,17 +57,17 @@ pub struct CrateContext { // created. finished_tydescs: Cell, // Track mapping of external ids to local items imported for inlining - external: RefCell>>, + external: RefCell>>, // Backwards version of the `external` map (inlined items to where they // came from) - external_srcs: RefCell>, + external_srcs: RefCell>, // A set of static items which cannot be inlined into other crates. This // will pevent in IIItem() structures from being encoded into the metadata // that is generated - non_inlineable_statics: RefCell>, + non_inlineable_statics: RefCell, // Cache instances of monomorphized functions monomorphized: RefCell>, - monomorphizing: RefCell>, + monomorphizing: RefCell>, // Cache generated vtables vtables: RefCell>, // Cache of constant strings, @@ -83,10 +84,10 @@ pub struct CrateContext { const_globals: RefCell>, // Cache of emitted const values - const_values: RefCell>, + const_values: RefCell>, // Cache of external const values - extern_const_values: RefCell>, + extern_const_values: RefCell>, impl_method_cache: RefCell>, @@ -125,7 +126,7 @@ impl CrateContext { maps: astencode::Maps, symbol_hasher: Sha256, link_meta: LinkMeta, - reachable: @RefCell>) + reachable: @RefCell) -> CrateContext { unsafe { let llcx = llvm::LLVMContextCreate(); @@ -185,24 +186,24 @@ impl CrateContext { tn: tn, externs: RefCell::new(HashMap::new()), intrinsics: intrinsics, - item_vals: RefCell::new(HashMap::new()), + item_vals: RefCell::new(NodeMap::new()), exp_map2: emap2, reachable: reachable, - item_symbols: RefCell::new(HashMap::new()), + item_symbols: RefCell::new(NodeMap::new()), link_meta: link_meta, drop_glues: RefCell::new(HashMap::new()), tydescs: RefCell::new(HashMap::new()), finished_tydescs: Cell::new(false), - external: RefCell::new(HashMap::new()), - external_srcs: RefCell::new(HashMap::new()), - non_inlineable_statics: RefCell::new(HashSet::new()), + external: RefCell::new(DefIdMap::new()), + external_srcs: RefCell::new(NodeMap::new()), + non_inlineable_statics: RefCell::new(NodeSet::new()), monomorphized: RefCell::new(HashMap::new()), - monomorphizing: RefCell::new(HashMap::new()), + monomorphizing: RefCell::new(DefIdMap::new()), vtables: RefCell::new(HashMap::new()), const_cstr_cache: RefCell::new(HashMap::new()), const_globals: RefCell::new(HashMap::new()), - const_values: RefCell::new(HashMap::new()), - extern_const_values: RefCell::new(HashMap::new()), + const_values: RefCell::new(NodeMap::new()), + extern_const_values: RefCell::new(DefIdMap::new()), impl_method_cache: RefCell::new(HashMap::new()), closure_bare_wrapper_cache: RefCell::new(HashMap::new()), module_data: RefCell::new(HashMap::new()), diff --git a/src/librustc/middle/trans/expr.rs b/src/librustc/middle/trans/expr.rs index fbb7decb30223..db9f3ed5a8157 100644 --- a/src/librustc/middle/trans/expr.rs +++ b/src/librustc/middle/trans/expr.rs @@ -66,11 +66,10 @@ use middle::ty::{AutoPtr, AutoBorrowVec, AutoBorrowVecRef, AutoBorrowFn}; use middle::ty; use util::common::indenter; use util::ppaux::Repr; +use util::nodemap::NodeMap; use middle::trans::machine::llsize_of; - use middle::trans::type_::Type; -use collections::HashMap; use std::vec; use syntax::ast; use syntax::ast_map; @@ -944,7 +943,7 @@ pub fn trans_local_var<'a>(bcx: &'a Block<'a>, }; fn take_local<'a>(bcx: &'a Block<'a>, - table: &HashMap>, + table: &NodeMap>, nid: ast::NodeId) -> Datum { let datum = match table.find(&nid) { diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index ecbf9342ec09b..a83a03c9838fd 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -30,6 +30,7 @@ use util::ppaux::{note_and_explain_region, bound_region_ptr_to_str}; use util::ppaux::{trait_store_to_str, ty_to_str, vstore_to_str}; use util::ppaux::{Repr, UserString}; use util::common::{indenter}; +use util::nodemap::{NodeMap, NodeSet, DefIdMap, DefIdSet}; use std::cast; use std::cell::{Cell, RefCell}; @@ -178,11 +179,9 @@ impl cmp::Eq for intern_key { } } -impl Hash for intern_key { - fn hash(&self, s: &mut sip::SipState) { - unsafe { - (*self.sty).hash(s) - } +impl Hash for intern_key { + fn hash(&self, s: &mut W) { + unsafe { (*self.sty).hash(s) } } } @@ -250,7 +249,9 @@ pub type ctxt = @ctxt_; /// later on. pub struct ctxt_ { diag: @syntax::diagnostic::SpanHandler, - interner: RefCell>, + // Specifically use a speedy hash algorithm for this hash map, it's used + // quite often. + interner: RefCell>, next_id: Cell, cstore: @metadata::cstore::CStore, sess: session::Session, @@ -269,94 +270,94 @@ pub struct ctxt_ { // of this node. This only applies to nodes that refer to entities // parameterized by type parameters, such as generic fns, types, or // other items. - node_type_substs: RefCell>, + node_type_substs: RefCell>, // Maps from a method to the method "descriptor" - methods: RefCell>, + methods: RefCell>, // Maps from a trait def-id to a list of the def-ids of its methods - trait_method_def_ids: RefCell>, + trait_method_def_ids: RefCell>, // A cache for the trait_methods() routine - trait_methods_cache: RefCell>, + trait_methods_cache: RefCell>, - impl_trait_cache: RefCell>>, + impl_trait_cache: RefCell>>, - trait_refs: RefCell>, - trait_defs: RefCell>, + trait_refs: RefCell>, + trait_defs: RefCell>, map: ast_map::Map, - intrinsic_defs: RefCell>, + intrinsic_defs: RefCell>, freevars: RefCell, tcache: type_cache, rcache: creader_cache, short_names_cache: RefCell>, needs_unwind_cleanup_cache: RefCell>, tc_cache: RefCell>, - ast_ty_to_ty_cache: RefCell>, - enum_var_cache: RefCell>, - ty_param_defs: RefCell>, - adjustments: RefCell>, + ast_ty_to_ty_cache: RefCell>, + enum_var_cache: RefCell>, + ty_param_defs: RefCell>, + adjustments: RefCell>, normalized_cache: RefCell>, lang_items: @middle::lang_items::LanguageItems, // A mapping of fake provided method def_ids to the default implementation - provided_method_sources: RefCell>, - supertraits: RefCell>, + provided_method_sources: RefCell>, + supertraits: RefCell>, // Maps from def-id of a type or region parameter to its // (inferred) variance. - item_variance_map: RefCell>, + item_variance_map: RefCell>, // A mapping from the def ID of an enum or struct type to the def ID // of the method that implements its destructor. If the type is not // present in this map, it does not have a destructor. This map is // populated during the coherence phase of typechecking. - destructor_for_type: RefCell>, + destructor_for_type: RefCell>, // A method will be in this list if and only if it is a destructor. - destructors: RefCell>, + destructors: RefCell, // Maps a trait onto a list of impls of that trait. - trait_impls: RefCell>>, + trait_impls: RefCell>>, // Maps a def_id of a type to a list of its inherent impls. // Contains implementations of methods that are inherent to a type. // Methods in these implementations don't need to be exported. - inherent_impls: RefCell>>, + inherent_impls: RefCell>>, // Maps a def_id of an impl to an Impl structure. // Note that this contains all of the impls that we know about, // including ones in other crates. It's not clear that this is the best // way to do it. - impls: RefCell>, + impls: RefCell>, // Set of used unsafe nodes (functions or blocks). Unsafe nodes not // present in this set can be warned about. - used_unsafe: RefCell>, + used_unsafe: RefCell, // Set of nodes which mark locals as mutable which end up getting used at // some point. Local variable definitions not in this set can be warned // about. - used_mut_nodes: RefCell>, + used_mut_nodes: RefCell, // vtable resolution information for impl declarations impl_vtables: typeck::impl_vtable_map, // The set of external nominal types whose implementations have been read. // This is used for lazy resolution of methods. - populated_external_types: RefCell>, + populated_external_types: RefCell, // The set of external traits whose implementations have been read. This // is used for lazy resolution of traits. - populated_external_traits: RefCell>, + populated_external_traits: RefCell, // Borrows upvar_borrow_map: RefCell, // These two caches are used by const_eval when decoding external statics // and variants that are found. - extern_const_statics: RefCell>>, - extern_const_variants: RefCell>>, + extern_const_statics: RefCell>>, + extern_const_variants: RefCell>>, } pub enum tbox_flag { @@ -1068,7 +1069,7 @@ pub struct ty_param_substs_and_ty { ty: ty::t } -pub type type_cache = RefCell>; +pub type type_cache = RefCell>; pub type node_type_table = RefCell>; @@ -1083,51 +1084,51 @@ pub fn mk_ctxt(s: session::Session, @ctxt_ { named_region_map: named_region_map, - item_variance_map: RefCell::new(HashMap::new()), + item_variance_map: RefCell::new(DefIdMap::new()), diag: s.diagnostic(), - interner: RefCell::new(HashMap::new()), + interner: RefCell::new(HashMap::with_hasher(::util::nodemap::FnvHasher)), next_id: Cell::new(primitives::LAST_PRIMITIVE_ID), cstore: s.cstore, sess: s, def_map: dm, region_maps: region_maps, node_types: RefCell::new(HashMap::new()), - node_type_substs: RefCell::new(HashMap::new()), - trait_refs: RefCell::new(HashMap::new()), - trait_defs: RefCell::new(HashMap::new()), + node_type_substs: RefCell::new(NodeMap::new()), + trait_refs: RefCell::new(NodeMap::new()), + trait_defs: RefCell::new(DefIdMap::new()), map: map, - intrinsic_defs: RefCell::new(HashMap::new()), + intrinsic_defs: RefCell::new(DefIdMap::new()), freevars: RefCell::new(freevars), - tcache: RefCell::new(HashMap::new()), + tcache: RefCell::new(DefIdMap::new()), rcache: RefCell::new(HashMap::new()), short_names_cache: RefCell::new(HashMap::new()), needs_unwind_cleanup_cache: RefCell::new(HashMap::new()), tc_cache: RefCell::new(HashMap::new()), - ast_ty_to_ty_cache: RefCell::new(HashMap::new()), - enum_var_cache: RefCell::new(HashMap::new()), - methods: RefCell::new(HashMap::new()), - trait_method_def_ids: RefCell::new(HashMap::new()), - trait_methods_cache: RefCell::new(HashMap::new()), - impl_trait_cache: RefCell::new(HashMap::new()), - ty_param_defs: RefCell::new(HashMap::new()), - adjustments: RefCell::new(HashMap::new()), + ast_ty_to_ty_cache: RefCell::new(NodeMap::new()), + enum_var_cache: RefCell::new(DefIdMap::new()), + methods: RefCell::new(DefIdMap::new()), + trait_method_def_ids: RefCell::new(DefIdMap::new()), + trait_methods_cache: RefCell::new(DefIdMap::new()), + impl_trait_cache: RefCell::new(DefIdMap::new()), + ty_param_defs: RefCell::new(NodeMap::new()), + adjustments: RefCell::new(NodeMap::new()), normalized_cache: RefCell::new(HashMap::new()), lang_items: lang_items, - provided_method_sources: RefCell::new(HashMap::new()), - supertraits: RefCell::new(HashMap::new()), - destructor_for_type: RefCell::new(HashMap::new()), - destructors: RefCell::new(HashSet::new()), - trait_impls: RefCell::new(HashMap::new()), - inherent_impls: RefCell::new(HashMap::new()), - impls: RefCell::new(HashMap::new()), - used_unsafe: RefCell::new(HashSet::new()), - used_mut_nodes: RefCell::new(HashSet::new()), - impl_vtables: RefCell::new(HashMap::new()), - populated_external_types: RefCell::new(HashSet::new()), - populated_external_traits: RefCell::new(HashSet::new()), + provided_method_sources: RefCell::new(DefIdMap::new()), + supertraits: RefCell::new(DefIdMap::new()), + destructor_for_type: RefCell::new(DefIdMap::new()), + destructors: RefCell::new(DefIdSet::new()), + trait_impls: RefCell::new(DefIdMap::new()), + inherent_impls: RefCell::new(DefIdMap::new()), + impls: RefCell::new(DefIdMap::new()), + used_unsafe: RefCell::new(NodeSet::new()), + used_mut_nodes: RefCell::new(NodeSet::new()), + impl_vtables: RefCell::new(DefIdMap::new()), + populated_external_types: RefCell::new(DefIdSet::new()), + populated_external_traits: RefCell::new(DefIdSet::new()), upvar_borrow_map: RefCell::new(HashMap::new()), - extern_const_statics: RefCell::new(HashMap::new()), - extern_const_variants: RefCell::new(HashMap::new()), + extern_const_statics: RefCell::new(DefIdMap::new()), + extern_const_variants: RefCell::new(DefIdMap::new()), } } @@ -3787,7 +3788,7 @@ pub fn trait_ref_supertraits(cx: ctxt, trait_ref: &ty::TraitRef) -> ~[@TraitRef] fn lookup_locally_or_in_crate_store( descr: &str, def_id: ast::DefId, - map: &mut HashMap, + map: &mut DefIdMap, load_external: || -> V) -> V { /*! * Helper for looking things up in the various maps diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index fe8d4caf9053c..6a41f63a779d3 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -111,6 +111,7 @@ use middle::lang_items::TypeIdLangItem; use util::common::{block_query, indenter, loop_query}; use util::ppaux; use util::ppaux::{UserString, Repr}; +use util::nodemap::NodeMap; use std::cell::{Cell, RefCell}; use collections::HashMap; @@ -153,13 +154,13 @@ pub mod method; /// share the inherited fields. pub struct Inherited { infcx: infer::InferCtxt, - locals: @RefCell>, + locals: @RefCell>, param_env: ty::ParameterEnvironment, // Temporary tables: - node_types: RefCell>, - node_type_substs: RefCell>, - adjustments: RefCell>, + node_types: RefCell>, + node_type_substs: RefCell>, + adjustments: RefCell>, method_map: MethodMap, vtable_map: vtable_map, upvar_borrow_map: RefCell, @@ -258,13 +259,13 @@ impl Inherited { -> Inherited { Inherited { infcx: infer::new_infer_ctxt(tcx), - locals: @RefCell::new(HashMap::new()), + locals: @RefCell::new(NodeMap::new()), param_env: param_env, - node_types: RefCell::new(HashMap::new()), - node_type_substs: RefCell::new(HashMap::new()), - adjustments: RefCell::new(HashMap::new()), - method_map: @RefCell::new(HashMap::new()), - vtable_map: @RefCell::new(HashMap::new()), + node_types: RefCell::new(NodeMap::new()), + node_type_substs: RefCell::new(NodeMap::new()), + adjustments: RefCell::new(NodeMap::new()), + method_map: @RefCell::new(NodeMap::new()), + vtable_map: @RefCell::new(NodeMap::new()), upvar_borrow_map: RefCell::new(HashMap::new()), } } diff --git a/src/librustc/middle/typeck/mod.rs b/src/librustc/middle/typeck/mod.rs index 4030ca5a87f3c..aee2b24e60f4c 100644 --- a/src/librustc/middle/typeck/mod.rs +++ b/src/librustc/middle/typeck/mod.rs @@ -68,9 +68,9 @@ use middle::ty; use util::common::time; use util::ppaux::Repr; use util::ppaux; +use util::nodemap::{DefIdMap, NodeMap}; use std::cell::RefCell; -use collections::HashMap; use std::rc::Rc; use collections::List; use syntax::codemap::Span; @@ -150,7 +150,7 @@ pub struct MethodCallee { // maps from an expression id that corresponds to a method call to the details // of the method to be invoked -pub type MethodMap = @RefCell>; +pub type MethodMap = @RefCell>; pub type vtable_param_res = @~[vtable_origin]; // Resolutions for bounds of all parameters, left to right, for a given path. @@ -194,7 +194,7 @@ impl Repr for vtable_origin { } } -pub type vtable_map = @RefCell>; +pub type vtable_map = @RefCell>; // Information about the vtable resolutions for a trait impl. @@ -216,7 +216,7 @@ impl Repr for impl_res { } } -pub type impl_vtable_map = RefCell>; +pub type impl_vtable_map = RefCell>; pub struct CrateCtxt { // A mapping from method call sites to traits that have that method. @@ -441,8 +441,8 @@ pub fn check_crate(tcx: ty::ctxt, let time_passes = tcx.sess.time_passes(); let ccx = @CrateCtxt { trait_map: trait_map, - method_map: @RefCell::new(HashMap::new()), - vtable_map: @RefCell::new(HashMap::new()), + method_map: @RefCell::new(NodeMap::new()), + vtable_map: @RefCell::new(NodeMap::new()), tcx: tcx }; diff --git a/src/librustc/util/nodemap.rs b/src/librustc/util/nodemap.rs new file mode 100644 index 0000000000000..84b579a1fb07c --- /dev/null +++ b/src/librustc/util/nodemap.rs @@ -0,0 +1,80 @@ +// Copyright 2014 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! An efficient hash map for node IDs + +use collections::{HashMap, HashSet}; +use std::hash::{Hasher, Hash}; +use std::io; +use syntax::ast; + +pub type NodeMap = HashMap; +pub type DefIdMap = HashMap; +pub type NodeSet = HashSet; +pub type DefIdSet = HashSet; + +// Hacks to get good names +pub mod NodeMap { + use collections::HashMap; + pub fn new() -> super::NodeMap { + HashMap::with_hasher(super::FnvHasher) + } +} +pub mod NodeSet { + use collections::HashSet; + pub fn new() -> super::NodeSet { + HashSet::with_hasher(super::FnvHasher) + } +} +pub mod DefIdMap { + use collections::HashMap; + pub fn new() -> super::DefIdMap { + HashMap::with_hasher(super::FnvHasher) + } +} +pub mod DefIdSet { + use collections::HashSet; + pub fn new() -> super::DefIdSet { + HashSet::with_hasher(super::FnvHasher) + } +} + +/// A speedy hash algorithm for node ids and def ids. The hashmap in +/// libcollections by default uses SipHash which isn't quite as speedy as we +/// want. In the compiler we're not really worried about DOS attempts, so we +/// just default to a non-cryptographic hash. +/// +/// This uses FNV hashing, as described here: +/// http://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function +#[deriving(Clone)] +pub struct FnvHasher; + +struct FnvState(u64); + +impl Hasher for FnvHasher { + fn hash>(&self, t: &T) -> u64 { + let mut state = FnvState(0xcbf29ce484222325); + t.hash(&mut state); + let FnvState(ret) = state; + return ret; + } +} + +impl Writer for FnvState { + fn write(&mut self, bytes: &[u8]) -> io::IoResult<()> { + let FnvState(mut hash) = *self; + for byte in bytes.iter() { + hash = hash * 0x100000001b3; + hash = hash ^ (*byte as u64); + } + *self = FnvState(hash); + Ok(()) + } +} diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 0c3e835402136..1029cc7444de3 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -46,6 +46,7 @@ use serialize::json::ToJson; use syntax::ast; use syntax::attr; use syntax::parse::token::InternedString; +use rustc::util::nodemap::NodeSet; use clean; use doctree; @@ -158,7 +159,7 @@ pub struct Cache { priv parent_stack: ~[ast::NodeId], priv search_index: ~[IndexItem], priv privmod: bool, - priv public_items: HashSet, + priv public_items: NodeSet, } /// Helper struct to render all source code to HTML pages @@ -235,7 +236,7 @@ pub fn run(mut krate: clean::Crate, dst: Path) -> io::IoResult<()> { // Crawl the crate to build various caches used for the output let mut cache = local_data::get(::analysiskey, |analysis| { let public_items = analysis.map(|a| a.public_items.clone()); - let public_items = public_items.unwrap_or(HashSet::new()); + let public_items = public_items.unwrap_or(NodeSet::new()); Cache { impls: HashMap::new(), typarams: HashMap::new(), diff --git a/src/librustdoc/passes.rs b/src/librustdoc/passes.rs index b8cc271ca9cb0..fdd637b1d0f78 100644 --- a/src/librustdoc/passes.rs +++ b/src/librustdoc/passes.rs @@ -13,6 +13,7 @@ use collections::HashSet; use std::local_data; use std::uint; use syntax::ast; +use rustc::util::nodemap::NodeSet; use clean; use clean::Item; @@ -110,7 +111,7 @@ pub fn strip_private(krate: clean::Crate) -> plugins::PluginResult { struct Stripper<'a> { retained: &'a mut HashSet, - exported_items: &'a HashSet, + exported_items: &'a NodeSet, } impl<'a> fold::DocFolder for Stripper<'a> { diff --git a/src/libsyntax/util/nodemap.rs b/src/libsyntax/util/nodemap.rs new file mode 100644 index 0000000000000..e9ace61eb9570 --- /dev/null +++ b/src/libsyntax/util/nodemap.rs @@ -0,0 +1,75 @@ +// Copyright 2014 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! An efficient hash map for node IDs + +use collections::hashmap; +use collections::{HashMap, HashSet}; +use std::hash::{Hasher, Hash}; +use std::iter; +use ast; + +pub type NodeMap = HashMap; +pub type DefIdMap = HashMap; +pub type NodeSet = HashSet; +pub type DefIdSet = HashSet; + +#[deriving(Clone)] +struct NodeHasher; + +impl Hasher for NodeHasher { + fn hash>(&self, t: &T) -> u64 { + let mut last = 0; + t.hash(&mut last); + return last + } +} + +impl Hash for ast::NodeId { + fn hash(&self, state: &mut u64) { + *state = self.get() as u64; + } +} + +impl Hash for ast::DefId { + fn hash(&self, state: &mut u64) { + let ast::DefId { krate, node } = *self; + // assert that these two types are each 32 bits + let krate: u32 = krate; + let node: u32 = node; + *state = (krate << 32) as u64 | (node as u64); + } +} + +// Hacks to get good names +pub mod NodeMap { + use collections::HashMap; + pub fn new() -> super::NodeMap { + HashMap::with_hasher(super::NodeHasher) + } +} +pub mod NodeSet { + use collections::HashSet; + pub fn new() -> super::NodeSet { + HashSet::with_hasher(super::NodeHasher) + } +} +pub mod DefIdMap { + use collections::HashMap; + pub fn new() -> super::DefIdMap { + HashMap::with_hasher(super::NodeHasher) + } +} +pub mod DefIdSet { + use collections::HashSet; + pub fn new() -> super::DefIdSet { + HashSet::with_hasher(super::NodeHasher) + } +} From 0a8413292845f527b8cf6bb2d02c9923f782ff37 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 28 Feb 2014 23:17:38 -0800 Subject: [PATCH 2/2] syntax: Conditionally deriving(Hash) with Writers If #[feature(default_type_parameters)] is enabled for a crate, then deriving(Hash) will expand with Hash instead of Hash so more hash algorithms can be used. --- src/librustc/driver/driver.rs | 6 ++- src/librustc/front/test.rs | 7 ++- src/librustc/middle/ty.rs | 21 ++++++++- src/librustc/util/nodemap.rs | 49 ++++++++++++++++++- src/libsyntax/ext/base.rs | 6 +-- src/libsyntax/ext/deriving/hash.rs | 20 ++++++-- src/libsyntax/ext/expand.rs | 39 ++++++++++++---- src/libsyntax/lib.rs | 2 +- src/libsyntax/util/nodemap.rs | 75 ------------------------------ 9 files changed, 128 insertions(+), 97 deletions(-) delete mode 100644 src/libsyntax/util/nodemap.rs diff --git a/src/librustc/driver/driver.rs b/src/librustc/driver/driver.rs index 58eb2119c6af9..5b335d163d8d0 100644 --- a/src/librustc/driver/driver.rs +++ b/src/librustc/driver/driver.rs @@ -224,8 +224,12 @@ pub fn phase_2_configure_and_expand(sess: Session, front::config::strip_unconfigured_items(krate)); krate = time(time_passes, "expansion", krate, |krate| { + let cfg = syntax::ext::expand::ExpansionConfig { + loader: loader, + deriving_hash_type_parameter: sess.features.default_type_params.get() + }; syntax::ext::expand::expand_crate(sess.parse_sess, - loader, + cfg, krate) }); // dump the syntax-time crates diff --git a/src/librustc/front/test.rs b/src/librustc/front/test.rs index 493fd3522d523..ecbb704684b38 100644 --- a/src/librustc/front/test.rs +++ b/src/librustc/front/test.rs @@ -28,6 +28,7 @@ use syntax::attr; use syntax::codemap::{DUMMY_SP, Span, ExpnInfo, NameAndSpan, MacroAttribute}; use syntax::codemap; use syntax::ext::base::ExtCtxt; +use syntax::ext::expand::ExpansionConfig; use syntax::fold::Folder; use syntax::fold; use syntax::opt_vec; @@ -165,7 +166,11 @@ fn generate_test_harness(sess: session::Session, krate: ast::Crate) let loader = &mut Loader::new(sess); let mut cx: TestCtxt = TestCtxt { sess: sess, - ext_cx: ExtCtxt::new(sess.parse_sess, sess.opts.cfg.clone(), loader), + ext_cx: ExtCtxt::new(sess.parse_sess, sess.opts.cfg.clone(), + ExpansionConfig { + loader: loader, + deriving_hash_type_parameter: false, + }), path: RefCell::new(~[]), testfns: RefCell::new(~[]), is_test_crate: is_test_crate(&krate), diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index a83a03c9838fd..9442a2144bdab 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -179,6 +179,13 @@ impl cmp::Eq for intern_key { } } +#[cfg(stage0)] +impl Hash for intern_key { + fn hash(&self, s: &mut sip::SipState) { + unsafe { (*self.sty).hash(s) } + } +} +#[cfg(not(stage0))] impl Hash for intern_key { fn hash(&self, s: &mut W) { unsafe { (*self.sty).hash(s) } @@ -251,6 +258,9 @@ pub struct ctxt_ { diag: @syntax::diagnostic::SpanHandler, // Specifically use a speedy hash algorithm for this hash map, it's used // quite often. + #[cfg(stage0)] + interner: RefCell>, + #[cfg(not(stage0))] interner: RefCell>, next_id: Cell, cstore: @metadata::cstore::CStore, @@ -1081,12 +1091,19 @@ pub fn mk_ctxt(s: session::Session, region_maps: middle::region::RegionMaps, lang_items: @middle::lang_items::LanguageItems) -> ctxt { - + #[cfg(stage0)] + fn hasher() -> HashMap { + HashMap::new() + } + #[cfg(not(stage0))] + fn hasher() -> HashMap { + HashMap::with_hasher(::util::nodemap::FnvHasher) + } @ctxt_ { named_region_map: named_region_map, item_variance_map: RefCell::new(DefIdMap::new()), diag: s.diagnostic(), - interner: RefCell::new(HashMap::with_hasher(::util::nodemap::FnvHasher)), + interner: RefCell::new(hasher()), next_id: Cell::new(primitives::LAST_PRIMITIVE_ID), cstore: s.cstore, sess: s, diff --git a/src/librustc/util/nodemap.rs b/src/librustc/util/nodemap.rs index 84b579a1fb07c..fe24733aba27d 100644 --- a/src/librustc/util/nodemap.rs +++ b/src/librustc/util/nodemap.rs @@ -15,30 +15,38 @@ use std::hash::{Hasher, Hash}; use std::io; use syntax::ast; +#[cfg(not(stage0))] pub type NodeMap = HashMap; +#[cfg(not(stage0))] pub type DefIdMap = HashMap; +#[cfg(not(stage0))] pub type NodeSet = HashSet; +#[cfg(not(stage0))] pub type DefIdSet = HashSet; // Hacks to get good names +#[cfg(not(stage0))] pub mod NodeMap { use collections::HashMap; pub fn new() -> super::NodeMap { HashMap::with_hasher(super::FnvHasher) } } +#[cfg(not(stage0))] pub mod NodeSet { use collections::HashSet; pub fn new() -> super::NodeSet { HashSet::with_hasher(super::FnvHasher) } } +#[cfg(not(stage0))] pub mod DefIdMap { use collections::HashMap; pub fn new() -> super::DefIdMap { HashMap::with_hasher(super::FnvHasher) } } +#[cfg(not(stage0))] pub mod DefIdSet { use collections::HashSet; pub fn new() -> super::DefIdSet { @@ -46,6 +54,45 @@ pub mod DefIdSet { } } +#[cfg(stage0)] +pub type NodeMap = HashMap; +#[cfg(stage0)] +pub type DefIdMap = HashMap; +#[cfg(stage0)] +pub type NodeSet = HashSet; +#[cfg(stage0)] +pub type DefIdSet = HashSet; + +// Hacks to get good names +#[cfg(stage0)] +pub mod NodeMap { + use collections::HashMap; + pub fn new() -> super::NodeMap { + HashMap::new() + } +} +#[cfg(stage0)] +pub mod NodeSet { + use collections::HashSet; + pub fn new() -> super::NodeSet { + HashSet::new() + } +} +#[cfg(stage0)] +pub mod DefIdMap { + use collections::HashMap; + pub fn new() -> super::DefIdMap { + HashMap::new() + } +} +#[cfg(stage0)] +pub mod DefIdSet { + use collections::HashSet; + pub fn new() -> super::DefIdSet { + HashSet::new() + } +} + /// A speedy hash algorithm for node ids and def ids. The hashmap in /// libcollections by default uses SipHash which isn't quite as speedy as we /// want. In the compiler we're not really worried about DOS attempts, so we @@ -56,7 +103,7 @@ pub mod DefIdSet { #[deriving(Clone)] pub struct FnvHasher; -struct FnvState(u64); +pub struct FnvState(u64); impl Hasher for FnvHasher { fn hash>(&self, t: &T) -> u64 { diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index 79068d4046965..459c0d1d0e3c5 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -283,7 +283,7 @@ pub struct ExtCtxt<'a> { parse_sess: @parse::ParseSess, cfg: ast::CrateConfig, backtrace: Option<@ExpnInfo>, - loader: &'a mut CrateLoader, + ecfg: expand::ExpansionConfig<'a>, mod_path: Vec , trace_mac: bool @@ -291,13 +291,13 @@ pub struct ExtCtxt<'a> { impl<'a> ExtCtxt<'a> { pub fn new<'a>(parse_sess: @parse::ParseSess, cfg: ast::CrateConfig, - loader: &'a mut CrateLoader) -> ExtCtxt<'a> { + ecfg: expand::ExpansionConfig<'a>) -> ExtCtxt<'a> { ExtCtxt { parse_sess: parse_sess, cfg: cfg, backtrace: None, - loader: loader, mod_path: Vec::new(), + ecfg: ecfg, trace_mac: false } } diff --git a/src/libsyntax/ext/deriving/hash.rs b/src/libsyntax/ext/deriving/hash.rs index 1d6cfab120d2d..299989d5fe667 100644 --- a/src/libsyntax/ext/deriving/hash.rs +++ b/src/libsyntax/ext/deriving/hash.rs @@ -22,19 +22,31 @@ pub fn expand_deriving_hash(cx: &mut ExtCtxt, item: @Item, push: |@Item|) { + let (path, generics, args) = if cx.ecfg.deriving_hash_type_parameter { + (Path::new_(vec!("std", "hash", "Hash"), None, + vec!(~Literal(Path::new_local("__H"))), true), + LifetimeBounds { + lifetimes: Vec::new(), + bounds: vec!(("__H", vec!(Path::new(vec!("std", "io", "Writer"))))), + }, + Path::new_local("__H")) + } else { + (Path::new(vec!("std", "hash", "Hash")), + LifetimeBounds::empty(), + Path::new(vec!("std", "hash", "sip", "SipState"))) + }; let hash_trait_def = TraitDef { span: span, attributes: Vec::new(), - path: Path::new(vec!("std", "hash", "Hash")), + path: path, additional_bounds: Vec::new(), - generics: LifetimeBounds::empty(), + generics: generics, methods: vec!( MethodDef { name: "hash", generics: LifetimeBounds::empty(), explicit_self: borrowed_explicit_self(), - args: vec!(Ptr(~Literal(Path::new(vec!("std", "hash", "sip", "SipState"))), - Borrowed(None, MutMutable))), + args: vec!(Ptr(~Literal(args), Borrowed(None, MutMutable))), ret_ty: nil_ty(), inline: true, const_nonmatching: false, diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 8b23de235b804..12eaa759ede9f 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -443,7 +443,7 @@ pub fn expand_view_item(vi: &ast::ViewItem, } fn load_extern_macros(krate: &ast::ViewItem, fld: &mut MacroExpander) { - let MacroCrate { lib, cnum } = fld.cx.loader.load_crate(krate); + let MacroCrate { lib, cnum } = fld.cx.ecfg.loader.load_crate(krate); let crate_name = match krate.node { ast::ViewItemExternMod(name, _, _) => name, @@ -451,7 +451,7 @@ fn load_extern_macros(krate: &ast::ViewItem, fld: &mut MacroExpander) { }; let name = format!("<{} macros>", token::get_ident(crate_name)); - let exported_macros = fld.cx.loader.get_exported_macros(cnum); + let exported_macros = fld.cx.ecfg.loader.get_exported_macros(cnum); for source in exported_macros.iter() { let item = parse::parse_item_from_source_str(name.clone(), (*source).clone(), @@ -468,7 +468,7 @@ fn load_extern_macros(krate: &ast::ViewItem, fld: &mut MacroExpander) { // Make sure the path contains a / or the linker will search for it. let path = os::make_absolute(&path); - let registrar = match fld.cx.loader.get_registrar_symbol(cnum) { + let registrar = match fld.cx.ecfg.loader.get_registrar_symbol(cnum) { Some(registrar) => registrar, None => return }; @@ -823,10 +823,15 @@ impl<'a> Folder for MacroExpander<'a> { } } +pub struct ExpansionConfig<'a> { + loader: &'a mut CrateLoader, + deriving_hash_type_parameter: bool, +} + pub fn expand_crate(parse_sess: @parse::ParseSess, - loader: &mut CrateLoader, + cfg: ExpansionConfig, c: Crate) -> Crate { - let mut cx = ExtCtxt::new(parse_sess, c.config.clone(), loader); + let mut cx = ExtCtxt::new(parse_sess, c.config.clone(), cfg); let mut expander = MacroExpander { extsbox: syntax_expander_table(), cx: &mut cx, @@ -995,7 +1000,11 @@ mod test { Vec::new(),sess); // should fail: let mut loader = ErrLoader; - expand_crate(sess,&mut loader,crate_ast); + let cfg = ::syntax::ext::expand::ExpansionConfig { + loader: &mut loader, + deriving_hash_type_parameter: false, + }; + expand_crate(sess,cfg,crate_ast); } // make sure that macros can leave scope for modules @@ -1010,7 +1019,11 @@ mod test { Vec::new(),sess); // should fail: let mut loader = ErrLoader; - expand_crate(sess,&mut loader,crate_ast); + let cfg = ::syntax::ext::expand::ExpansionConfig { + loader: &mut loader, + deriving_hash_type_parameter: false, + }; + expand_crate(sess,cfg,crate_ast); } // macro_escape modules shouldn't cause macros to leave scope @@ -1024,7 +1037,11 @@ mod test { Vec::new(), sess); // should fail: let mut loader = ErrLoader; - expand_crate(sess, &mut loader, crate_ast); + let cfg = ::syntax::ext::expand::ExpansionConfig { + loader: &mut loader, + deriving_hash_type_parameter: false, + }; + expand_crate(sess, cfg, crate_ast); } #[test] fn test_contains_flatten (){ @@ -1062,7 +1079,11 @@ mod test { let (crate_ast,ps) = string_to_crate_and_sess(crate_str); // the cfg argument actually does matter, here... let mut loader = ErrLoader; - expand_crate(ps,&mut loader,crate_ast) + let cfg = ::syntax::ext::expand::ExpansionConfig { + loader: &mut loader, + deriving_hash_type_parameter: false, + }; + expand_crate(ps,cfg,crate_ast) } //fn expand_and_resolve(crate_str: @str) -> ast::crate { diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs index 0d7e54bb69d36..0d465e8475c9c 100644 --- a/src/libsyntax/lib.rs +++ b/src/libsyntax/lib.rs @@ -26,7 +26,7 @@ This API is completely unstable and subject to change. html_favicon_url = "http://www.rust-lang.org/favicon.ico", html_root_url = "http://static.rust-lang.org/doc/master")]; -#[feature(macro_rules, globs, managed_boxes)]; +#[feature(macro_rules, globs, managed_boxes, default_type_params)]; #[allow(unknown_features)];// Note: remove it after a snapshot. #[feature(quote)]; diff --git a/src/libsyntax/util/nodemap.rs b/src/libsyntax/util/nodemap.rs deleted file mode 100644 index e9ace61eb9570..0000000000000 --- a/src/libsyntax/util/nodemap.rs +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright 2014 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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! An efficient hash map for node IDs - -use collections::hashmap; -use collections::{HashMap, HashSet}; -use std::hash::{Hasher, Hash}; -use std::iter; -use ast; - -pub type NodeMap = HashMap; -pub type DefIdMap = HashMap; -pub type NodeSet = HashSet; -pub type DefIdSet = HashSet; - -#[deriving(Clone)] -struct NodeHasher; - -impl Hasher for NodeHasher { - fn hash>(&self, t: &T) -> u64 { - let mut last = 0; - t.hash(&mut last); - return last - } -} - -impl Hash for ast::NodeId { - fn hash(&self, state: &mut u64) { - *state = self.get() as u64; - } -} - -impl Hash for ast::DefId { - fn hash(&self, state: &mut u64) { - let ast::DefId { krate, node } = *self; - // assert that these two types are each 32 bits - let krate: u32 = krate; - let node: u32 = node; - *state = (krate << 32) as u64 | (node as u64); - } -} - -// Hacks to get good names -pub mod NodeMap { - use collections::HashMap; - pub fn new() -> super::NodeMap { - HashMap::with_hasher(super::NodeHasher) - } -} -pub mod NodeSet { - use collections::HashSet; - pub fn new() -> super::NodeSet { - HashSet::with_hasher(super::NodeHasher) - } -} -pub mod DefIdMap { - use collections::HashMap; - pub fn new() -> super::DefIdMap { - HashMap::with_hasher(super::NodeHasher) - } -} -pub mod DefIdSet { - use collections::HashSet; - pub fn new() -> super::DefIdSet { - HashSet::with_hasher(super::NodeHasher) - } -}