Add a very simple map implementation for sequential integer keys

Use it for the ast_map. Cuts 40% off the time spent prior to LLVM.
This commit is contained in:
Brian Anderson 2011-06-26 19:18:30 -07:00
parent 08b49a5d8f
commit 29a8219c4c
2 changed files with 104 additions and 1 deletions

View File

@ -11,7 +11,7 @@ tag ast_node {
type map = std::map::hashmap[node_id, ast_node];
fn map_crate(&crate c) -> map {
auto map = util::common::new_int_hash[ast_node]();
auto map = util::common::new_seq_int_hash[ast_node]();
auto v_map = @rec(visit_item=bind map_item(map, _, _, _),
visit_native_item=bind map_native_item(map, _, _, _),

View File

@ -4,6 +4,7 @@ import std::map::hashmap;
import std::uint;
import std::int;
import std::vec;
import std::option;
import std::option::none;
import std::option::some;
import front::ast;
@ -104,6 +105,108 @@ fn new_uint_hash[V]() -> std::map::hashmap[uint, V] {
ret std::map::mk_hashmap[uint, V](hasher, eqer);
}
fn new_seq_hash[K, V](fn(&K) -> uint key_idx,
fn(&uint) -> K idx_key) -> std::map::hashmap[K, V] {
fn ensure_size[V](&mutable vec[mutable option::t[V]] bkts, uint idx) {
auto bkt_len = vec::len(bkts);
if (idx >= bkt_len) {
auto needed = idx - bkt_len + 1u;
auto new = vec::init_elt_mut(option::none[V], needed);
bkts += new;
}
}
obj seq_hash[K, V](mutable uint nelts,
mutable vec[mutable option::t[V]] bkts,
fn(&K) -> uint key_idx,
fn(&uint) -> K idx_key) {
fn size() -> uint { nelts }
fn insert(&K key, &V value) -> bool {
auto idx = key_idx(key);
ensure_size(bkts, idx);
if (option::is_some(bkts.(idx))) {
bkts.(idx) = option::some(value);
ret false;
} else {
bkts.(idx) = option::some(value);
nelts += 1u;
ret true;
}
}
fn contains_key(&K key) -> bool {
auto idx = key_idx(key);
ensure_size(bkts, idx);
if (option::is_some(bkts.(idx))) {
ret true;
} else {
ret false;
}
}
fn get(&K key) -> V {
ret alt (self.find(key)) {
case (option::some(?v)) { v }
case (_) { fail }
};
}
fn find(&K key) -> option::t[V] {
auto idx = key_idx(key);
ensure_size(bkts, idx);
ret bkts.(idx);
}
fn remove(&K key) -> option::t[V] {
auto idx = key_idx(key);
ensure_size(bkts, idx);
auto val = bkts.(idx);
if (option::is_some(val)) {
bkts.(idx) = option::none;
nelts -= 1u;
}
ret val;
}
fn rehash() { }
iter items() -> @tup(K, V) {
auto idx = 0u;
auto bktsize = vec::len(bkts);
while (idx < bktsize) {
alt (bkts.(idx)) {
case (option::some(?v)) {
// FIXME: Appease alias analysis
auto value = v;
put @tup(idx_key(idx), value);
}
case (_) { }
}
idx += 1u;
}
}
}
let vec[mutable option::t[V]] bkts = [mutable];
ret seq_hash[K, V](0u, bkts, key_idx, idx_key);
}
// A specialized map for keys that are sequential ints
fn new_seq_int_hash[V]() -> std::map::hashmap[int, V] {
auto key_idx = fn(&int key) -> uint { key as uint };
auto idx_key = fn(&uint idx) -> int { idx as int };
ret new_seq_hash(key_idx, idx_key);
}
// A specialized map for keys that are sequential uints
fn new_seq_uint_hash[V]() -> std::map::hashmap[uint, V] {
auto key_idx = fn(&uint key) -> uint { key };
auto idx_key = fn(&uint idx) -> uint { idx };
ret new_seq_hash(key_idx, idx_key);
}
fn istr(int i) -> str { ret int::to_str(i, 10u); }
fn uistr(uint i) -> str { ret uint::to_str(i, 10u); }