stdlib: Stop incurring vtable dispatch costs when hashmaps are used

This required changing almost all users of hashmaps to import the hashmap interface first.

The `size` member in the hashmap structure was renamed to `count` to work around a name conflict.
This commit is contained in:
Patrick Walton 2012-03-07 16:48:57 -08:00
parent c245d9e980
commit c9375fed8d
50 changed files with 96 additions and 47 deletions

View File

@ -16,6 +16,7 @@ import io::writer_util;
import std::json;
import result;
import std::map;
import std::map::hashmap;
import std::os;
import std::run;
import str;

View File

@ -5,6 +5,7 @@ import result::{ok, err};
import io;
import io::{reader_util, writer_util};
import map;
import map::hashmap;
export json;
export error;
@ -36,7 +37,7 @@ enum json {
/* Variant: list */
list([json]),
/* Variant: dict */
dict(map::map<str,json>),
dict(map::hashmap<str,json>),
/* Variant: null */
null,
}

View File

@ -4,6 +4,10 @@ Module: map
A map type
*/
import chained::hashmap;
export hashmap, hashfn, eqfn, set, map, chained, mk_hashmap, new_str_hash;
export new_bytes_hash, new_int_hash, new_uint_hash, set_add;
/* Section: Types */
/*
@ -23,14 +27,13 @@ Equality
type eqfn<K> = fn@(K, K) -> bool;
/*
Type: hashset
Type: set
A convenience type to treat a map as a set
A convenience type to treat a hashmap as a set
*/
type set<K> = map<K, ()>;
type set<K> = hashmap<K, ()>;
// Temporary alias to make migration easier
type hashmap<K, V> = map<K, V>;
type hashmap<K, V> = chained::t<K, V>;
/*
IFace: map
@ -103,8 +106,7 @@ iface map<K: copy, V: copy> {
}
// FIXME: package this up and export it as a datatype usable for
// external code that doesn't want to pay the cost of a box and vtable
// lookups.
// external code that doesn't want to pay the cost of a box.
mod chained {
type entry<K, V> = {
hash: uint,
@ -118,8 +120,8 @@ mod chained {
absent
}
type t<K, V> = {
mutable size: uint,
type t<K, V> = @{
mutable count: uint,
mutable chains: [mutable chain<K,V>],
hasher: hashfn<K>,
eqer: eqfn<K>
@ -185,7 +187,7 @@ mod chained {
let hash = tbl.hasher(k);
alt search_tbl(tbl, k, hash) {
not_found {
tbl.size += 1u;
tbl.count += 1u;
let idx = hash % vec::len(tbl.chains);
let old_chain = tbl.chains[idx];
tbl.chains[idx] = present(@{
@ -229,13 +231,13 @@ mod chained {
}
found_first(idx, entry) {
tbl.size -= 1u;
tbl.count -= 1u;
tbl.chains[idx] = entry.next;
ret core::option::some(entry.value);
}
found_after(eprev, entry) {
tbl.size -= 1u;
tbl.count -= 1u;
eprev.next = entry.next;
ret core::option::some(entry.value);
}
@ -291,12 +293,12 @@ mod chained {
}
}
impl <K: copy, V: copy> of map<K, V> for t<K, V> {
fn size() -> uint { self.size }
impl hashmap<K: copy, V: copy> of map<K, V> for t<K, V> {
fn size() -> uint { self.count }
fn insert(k: K, v: V) -> bool {
let nchains = vec::len(self.chains);
let load = {num: (self.size + 1u) as int, den: nchains as int};
let load = {num: (self.count + 1u) as int, den: nchains as int};
// Structural consts would be nice. This is a const 3/4
// load factor that we compare against.
if !util::rational_leq(load, {num:3, den:4}) { rehash(self); }
@ -318,13 +320,13 @@ mod chained {
fn values(blk: fn(V)) { items(self) { |_k, v| blk(v) } }
}
fn mk<K: copy, V: copy>(hasher: hashfn<K>, eqer: eqfn<K>) -> map<K,V> {
fn mk<K: copy, V: copy>(hasher: hashfn<K>, eqer: eqfn<K>) -> t<K,V> {
let initial_capacity: uint = 32u; // 2^5
let slf: t<K, V> = {mutable size: 0u,
mutable chains: chains(initial_capacity),
hasher: hasher,
eqer: eqer};
slf as map::<K, V>
let slf: t<K, V> = @{mutable count: 0u,
mutable chains: chains(initial_capacity),
hasher: hasher,
eqer: eqer};
slf
}
}
@ -339,7 +341,7 @@ hasher - The hash function for key type K
eqer - The equality function for key type K
*/
fn mk_hashmap<K: copy, V: copy>(hasher: hashfn<K>, eqer: eqfn<K>)
-> map<K, V> {
-> hashmap<K, V> {
chained::mk(hasher, eqer)
}
@ -348,7 +350,7 @@ Function: new_str_hash
Construct a hashmap for string keys
*/
fn new_str_hash<V: copy>() -> map<str, V> {
fn new_str_hash<V: copy>() -> hashmap<str, V> {
ret mk_hashmap(str::hash, str::eq);
}
@ -357,7 +359,7 @@ Function: new_bytes_hash
Construct a hashmap for byte string keys
*/
fn new_bytes_hash<V: copy>() -> map<[u8], V> {
fn new_bytes_hash<V: copy>() -> hashmap<[u8], V> {
ret mk_hashmap(vec::u8::hash, vec::u8::eq);
}
@ -366,7 +368,7 @@ Function: new_int_hash
Construct a hashmap for int keys
*/
fn new_int_hash<V: copy>() -> map<int, V> {
fn new_int_hash<V: copy>() -> hashmap<int, V> {
fn hash_int(&&x: int) -> uint { int::hash(x) }
fn eq_int(&&a: int, &&b: int) -> bool { ret a == b; }
ret mk_hashmap(hash_int, eq_int);
@ -377,7 +379,7 @@ Function: new_uint_hash
Construct a hashmap for uint keys
*/
fn new_uint_hash<V: copy>() -> map<uint, V> {
fn new_uint_hash<V: copy>() -> hashmap<uint, V> {
fn hash_uint(&&x: uint) -> uint { uint::hash(x) }
fn eq_uint(&&a: uint, &&b: uint) -> bool { ret a == b; }
ret mk_hashmap(hash_uint, eq_uint);

View File

@ -1,3 +1,4 @@
import map::hashmap;
export loop_new, loop_delete, run, close, run_in_bg;
export async_init, async_send;
export timer_init, timer_start, timer_stop;
@ -129,17 +130,17 @@ fn loop_new() -> uv_loop unsafe {
process_operation);
// all state goes here
let handles: map::map<[u8], *ctypes::void> =
let handles: map::hashmap<[u8], *ctypes::void> =
map::new_bytes_hash();
let id_to_handle: map::map<[u8], uv_handle> =
let id_to_handle: map::hashmap<[u8], uv_handle> =
map::new_bytes_hash();
let after_cbs: map::map<[u8], fn~(uv_handle)> =
let after_cbs: map::hashmap<[u8], fn~(uv_handle)> =
map::new_bytes_hash();
let close_callbacks: map::map<[u8], fn~()> =
let close_callbacks: map::hashmap<[u8], fn~()> =
map::new_bytes_hash();
let async_cbs: map::map<[u8], fn~(uv_handle)> =
let async_cbs: map::hashmap<[u8], fn~(uv_handle)> =
map::new_bytes_hash();
let timer_cbs: map::map<[u8], fn~(uv_handle)> =
let timer_cbs: map::hashmap<[u8], fn~(uv_handle)> =
map::new_bytes_hash();
// the main loop that this task blocks on.

View File

@ -7,6 +7,7 @@ import middle::ty;
import metadata::{encoder, cstore};
import middle::trans::common::crate_ctxt;
import std::fs;
import std::map::hashmap;
import std::run;
import std::sha1::sha1;
import syntax::ast;

View File

@ -1,4 +1,5 @@
import std::{os, fs, os_fs, map};
import std::map::hashmap;
import metadata::cstore;
import driver::session;
import util::filesearch;

View File

@ -1,6 +1,7 @@
// Functions dealing with attributes and meta_items
import std::map;
import std::map::hashmap;
import syntax::{ast, ast_util};
import driver::session::session;

View File

@ -1,4 +1,5 @@
import str::sbuf;
import std::map::hashmap;
import ctypes::{c_int, c_uint, unsigned, longlong, ulonglong};

View File

@ -4,15 +4,15 @@ import syntax::visit;
import syntax::ast_util;
import syntax::ast_util::inlined_item_methods;
import syntax::codemap::span;
import std::map::map;
import std::smallintmap::map;
import std::ebml;
import std::ebml::writer;
import std::map::hashmap;
import std::serialization;
import std::serialization::serializer;
import std::serialization::deserializer;
import std::serialization::serializer_helpers;
import std::serialization::deserializer_helpers;
import std::smallintmap::map;
import middle::trans::common::maps;
import middle::{ty, typeck, last_use, ast_map};
import middle::typeck::method_origin;

View File

@ -6,6 +6,7 @@ import middle::{ty, ast_map};
import option::{some, none};
import driver::session;
import middle::trans::common::maps;
import std::map::hashmap;
export get_symbol;
export get_type_param_count;

View File

@ -2,6 +2,7 @@
// crates and libraries
import std::map;
import std::map::hashmap;
import syntax::ast;
import util::common::*;

View File

@ -1,6 +1,7 @@
// Decoding metadata from a single crate's metadata
import std::{ebml, map, io};
import std::map::hashmap;
import io::writer_util;
import syntax::{ast, ast_util};
import driver::session::session;

View File

@ -1,6 +1,7 @@
// Metadata encoding
import std::{io, ebml, map, list};
import std::map::hashmap;
import io::writer_util;
import ebml::writer;
import syntax::ast::*;

View File

@ -10,10 +10,11 @@ import syntax::ast::*;
import syntax::visit;
import syntax::ast_util::def_id_of_def;
import front::attr;
import std::map::hashmap;
export map, find_reachable;
type map = std::map::map<node_id, ()>;
type map = std::map::hashmap<node_id, ()>;
type ctx = {ccx: middle::trans::common::crate_ctxt,
rmap: map};

View File

@ -5,6 +5,7 @@ import syntax::ast::*;
import syntax::ast_util;
import syntax::ast_util::respan;
import middle::ty;
import std::map::hashmap;
export parse_ty_data, parse_def_id;
export parse_bounds_data;

View File

@ -5,6 +5,7 @@ import syntax::codemap::span;
import syntax::visit;
import visit::vt;
import std::list;
import std::map::hashmap;
import std::util::unreachable;
import option::is_none;
import list::list;

View File

@ -1,4 +1,5 @@
import std::map;
import std::map::hashmap;
import syntax::ast::*;
import syntax::ast_util;
import syntax::ast_util::inlined_item_methods;
@ -35,7 +36,7 @@ enum ast_node {
node_res_ctor(@item),
}
type map = std::map::map<node_id, ast_node>;
type map = std::map::hashmap<node_id, ast_node>;
type ctx = {map: map, mutable path: path, mutable local_id: uint};
type vt = visit::vt<ctx>;

View File

@ -1,6 +1,7 @@
import syntax::{ast, ast_util};
import driver::session::session;
import std::map;
import std::map::hashmap;
export capture_mode;
export capture_var;

View File

@ -8,6 +8,7 @@ import syntax::visit;
import driver::session::session;
import middle::ty;
import middle::ty::*;
import std::map::hashmap;
fn check_crate(tcx: ty::ctxt, crate: @crate) {
visit::visit_crate(*crate, (), visit::mk_vt(@{

View File

@ -1,6 +1,7 @@
import syntax::ast::*;
import syntax::{visit, ast_util};
import driver::session::session;
import std::map::hashmap;
fn check_crate(sess: session, crate: @crate, method_map: typeck::method_map) {
visit::visit_crate(*crate, false, visit::mk_vt(@{

View File

@ -1,3 +1,4 @@
import std::map::hashmap;
import syntax::ast;
import syntax::visit;
import syntax::print::pprust::expr_to_str;

View File

@ -3,6 +3,7 @@ import syntax::ast::*;
import syntax::codemap::span;
import ty::{kind, kind_copyable, kind_sendable, kind_noncopyable};
import driver::session::session;
import std::map::hashmap;
// Kind analysis pass. There are three kinds:
//

View File

@ -4,6 +4,7 @@ import syntax::codemap::span;
import std::list::{is_not_empty, list, nil, cons, tail};
import std::util::unreachable;
import std::list;
import std::map::hashmap;
// Last use analysis pass.
//

View File

@ -3,6 +3,7 @@ import middle::ty::ctxt;
import syntax::{ast, visit};
import front::attr;
import std::io;
import std::map::hashmap;
import io::writer_util;
enum option {

View File

@ -2,6 +2,7 @@ import syntax::ast::*;
import syntax::visit;
import syntax::ast_util;
import driver::session::session;
import std::map::hashmap;
enum deref_t { unbox(bool), field, index, }

View File

@ -4,6 +4,7 @@ import syntax::ast_util::respan;
import syntax::fold;
import syntax::fold::*;
import syntax::codemap::span;
import std::map::hashmap;
export walk_pat;
export pat_binding_ids, pat_bindings, pat_id_map;

View File

@ -12,6 +12,7 @@ import syntax::codemap::span;
import syntax::print::pprust::pat_to_str;
import back::abi;
import resolve::def_map;
import std::map::hashmap;
import common::*;

View File

@ -18,6 +18,7 @@ import util::ppaux::ty_to_str;
import shape::{size_of};
import ast_map::{path, path_mod, path_name};
import driver::session::session;
import std::map::hashmap;
// ___Good to know (tm)__________________________________________________
//

View File

@ -11,6 +11,7 @@ import lib::llvm::llvm;
import lib::llvm::{ValueRef, TypeRef};
import lib::llvm::llvm::LLVMGetParam;
import ast_map::{path, path_mod, path_name};
import std::map::hashmap;
// Translation functionality related to impls and ifaces
//

View File

@ -9,6 +9,7 @@ import common::*;
import build::*;
import base::*;
import type_of::*;
import std::map::hashmap;
export link_name, trans_native_mod, register_crust_fn, trans_crust_fn;

View File

@ -3,6 +3,7 @@ import lib::llvm::{TypeRef};
import syntax::ast;
import lib::llvm::llvm;
import driver::session::session;
import std::map::hashmap;
import ty::*;

View File

@ -4,7 +4,7 @@ import syntax::ast::*;
import syntax::ast_util::*;
import syntax::{visit, codemap};
import codemap::span;
import std::map::{new_int_hash};
import std::map::{hashmap, new_int_hash};
import syntax::print::pprust::path_to_str;
import tstate::ann::{pre_and_post, pre_and_post_state, empty_ann, prestate,
poststate, precond, postcond,

View File

@ -12,6 +12,7 @@ import tstate::ann::{pre_and_post, precond, postcond, prestate, poststate,
import tritv::*;
import util::common::*;
import driver::session::session;
import std::map::hashmap;
fn bit_num(fcx: fn_ctxt, c: tsconstr) -> uint {
let d = tsconstr_to_def_id(c);

View File

@ -14,6 +14,7 @@ import collect_locals::mk_f_to_fn_info;
import pre_post_conditions::fn_pre_post;
import states::find_pre_post_state_fn;
import driver::session::session;
import std::map::hashmap;
fn check_unused_vars(fcx: fn_ctxt) {

View File

@ -8,6 +8,7 @@ import syntax::codemap::span;
import syntax::ast_util::respan;
import driver::session::session;
import aux::*;
import std::map::hashmap;
type ctxt = {cs: @mutable [sp_constr], tcx: ty::ctxt};

View File

@ -13,6 +13,7 @@ import util::common::{new_def_hash, log_expr, field_exprs,
has_nonlocal_exits, log_stmt};
import syntax::codemap::span;
import driver::session::session;
import std::map::hashmap;
fn find_pre_post_mod(_m: _mod) -> _mod {
#debug("implement find_pre_post_mod!");

View File

@ -10,6 +10,7 @@ import syntax::codemap::span;
import middle::ty::{expr_ty, type_is_bot};
import util::common::*;
import driver::session::session;
import std::map::hashmap;
fn forbid_upvar(fcx: fn_ctxt, rhs_id: node_id, sp: span, t: oper_type) {
alt t {

View File

@ -7,6 +7,7 @@
Rustdoc from its non-sendableness."
)];
import std::map::hashmap;
import rustc::driver::session;
import rustc::driver::driver;
import rustc::driver::diagnostic;

View File

@ -8,6 +8,7 @@
import rustc::syntax::ast;
import rustc::middle::ast_map;
import std::map::hashmap;
export mk_pass;

View File

@ -1,5 +1,6 @@
#[doc = "Prunes things with the #[doc(hidden)] attribute"];
import std::map::hashmap;
export mk_pass;
fn mk_pass() -> pass {

View File

@ -3,6 +3,7 @@
import rustc::syntax::ast;
import rustc::syntax::ast_util;
import rustc::middle::ast_map;
import std::map::hashmap;
export mk_pass;

View File

@ -1,6 +1,7 @@
#[doc = "Finds docs for reexported items and duplicates them"];
import std::map;
import std::map::hashmap;
import rustc::syntax::ast;
import rustc::syntax::ast_util;
import rustc::util::common;

View File

@ -4,6 +4,7 @@
import rustc::syntax::ast;
import rustc::syntax::print::pprust;
import rustc::middle::ast_map;
import std::map::hashmap;
export mk_pass;

View File

@ -50,7 +50,7 @@ type ast_pat = str;
type ast_ty = str;
type ast_item = str;
type tp_map = map<ast::node_id, ty::t>;
type tp_map = hashmap<ast::node_id, ty::t>;
type serialize_ctx = {
crate: @ast::crate,

View File

@ -14,6 +14,7 @@
use std;
import std::io::writer_util;
import std::map::hashmap;
type cmplx = {re: f64, im: f64};
type line = {i: uint, b: [u8]};

View File

@ -13,6 +13,7 @@ use std;
import option = option;
import option::{some, none};
import std::{map, io, time};
import std::map::hashmap;
import io::reader_util;
import comm::chan;

View File

@ -1,10 +1,12 @@
use std;
import std::map;
import std::map::hashmap;
import std::map::map;
// Test that iface types printed in error msgs include the type arguments.
fn main() {
let x: map<uint,str> = map::new_str_hash::<str>();
let x: map<str,str> = map::new_str_hash::<str>() as map::<str,str>;
let y: map<uint,str> = x;
//!^ ERROR mismatched types: expected `std::map::map<uint,str>`
}

View File

@ -2,6 +2,7 @@
use std;
import std::map;
import std::map::hashmap;
import uint;
fn main() {

View File

@ -12,6 +12,7 @@ import option::none;
import str;
import vec;
import std::map;
import std::map::hashmap;
import task;
import comm::chan;
import comm::port;

View File

@ -1,5 +1,6 @@
use std;
import std::map;
import std::map::hashmap;
fn main() {
let m = map::new_bytes_hash();