Index: runtime/vm/hash_map.h |
diff --git a/runtime/vm/hash_map.h b/runtime/vm/hash_map.h |
index 0c41f1221c8873d3f5d8269a113f53e769587e92..22efc32ba391194cb447380a797d310900acde9d 100644 |
--- a/runtime/vm/hash_map.h |
+++ b/runtime/vm/hash_map.h |
@@ -7,7 +7,7 @@ |
namespace dart { |
-template <typename T> |
+template <typename KeyValueTrait> |
class DirectChainedHashMap: public ValueObject { |
public: |
DirectChainedHashMap() : array_size_(0), |
@@ -22,16 +22,16 @@ class DirectChainedHashMap: public ValueObject { |
DirectChainedHashMap(const DirectChainedHashMap& other); |
- void Insert(T value); |
+ void Insert(typename KeyValueTrait::Pair kv); |
- T Lookup(T value) const; |
+ typename KeyValueTrait::Value Lookup(typename KeyValueTrait::Key key) const; |
bool IsEmpty() const { return count_ == 0; } |
private: |
// A linked list of T values. Stored in arrays. |
struct HashMapListElement { |
- T value; |
+ typename KeyValueTrait::Pair kv; |
intptr_t next; // Index in the array of the next list element. |
}; |
static const intptr_t kNil = -1; // The end of a linked list |
@@ -53,15 +53,22 @@ class DirectChainedHashMap: public ValueObject { |
}; |
-template <typename T> |
-T DirectChainedHashMap<T>::Lookup(T value) const { |
- uword hash = static_cast<uword>(value->Hashcode()); |
+template <typename KeyValueTrait> |
+typename KeyValueTrait::Value |
+ DirectChainedHashMap<KeyValueTrait>:: |
+ Lookup(typename KeyValueTrait::Key key) const { |
+ uword hash = static_cast<uword>(KeyValueTrait::Hashcode(key)); |
uword pos = Bound(hash); |
- if (array_[pos].value != NULL) { |
- if (array_[pos].value->Equals(value)) return array_[pos].value; |
+ if (KeyValueTrait::ValueOf(array_[pos].kv) != NULL) { |
+ if (KeyValueTrait::IsKeyEqual(array_[pos].kv, key)) { |
+ return KeyValueTrait::ValueOf(array_[pos].kv); |
+ } |
+ |
intptr_t next = array_[pos].next; |
while (next != kNil) { |
- if (lists_[next].value->Equals(value)) return lists_[next].value; |
+ if (KeyValueTrait::IsKeyEqual(lists_[next].kv, key)) { |
+ return KeyValueTrait::ValueOf(lists_[next].kv); |
+ } |
next = lists_[next].next; |
} |
} |
@@ -69,8 +76,9 @@ T DirectChainedHashMap<T>::Lookup(T value) const { |
} |
-template <typename T> |
-DirectChainedHashMap<T>::DirectChainedHashMap(const DirectChainedHashMap& other) |
+template <typename KeyValueTrait> |
+DirectChainedHashMap<KeyValueTrait>:: |
+ DirectChainedHashMap(const DirectChainedHashMap& other) |
: ValueObject(), |
array_size_(other.array_size_), |
lists_size_(other.lists_size_), |
@@ -85,8 +93,8 @@ DirectChainedHashMap<T>::DirectChainedHashMap(const DirectChainedHashMap& other) |
} |
-template <typename T> |
-void DirectChainedHashMap<T>::Resize(intptr_t new_size) { |
+template <typename KeyValueTrait> |
+void DirectChainedHashMap<KeyValueTrait>::Resize(intptr_t new_size) { |
ASSERT(new_size > count_); |
// Hashing the values into the new array has no more collisions than in the |
// old hash map, so we can use the existing lists_ array, if we are careful. |
@@ -111,17 +119,17 @@ void DirectChainedHashMap<T>::Resize(intptr_t new_size) { |
if (old_array != NULL) { |
// Iterate over all the elements in lists, rehashing them. |
for (intptr_t i = 0; i < old_size; ++i) { |
- if (old_array[i].value != NULL) { |
+ if (KeyValueTrait::ValueOf(old_array[i].kv) != NULL) { |
intptr_t current = old_array[i].next; |
while (current != kNil) { |
- Insert(lists_[current].value); |
+ Insert(lists_[current].kv); |
intptr_t next = lists_[current].next; |
lists_[current].next = free_list_head_; |
free_list_head_ = current; |
current = next; |
} |
// Rehash the directly stored value. |
- Insert(old_array[i].value); |
+ Insert(old_array[i].kv); |
} |
} |
} |
@@ -155,16 +163,18 @@ void DirectChainedHashMap<T>::ResizeLists(intptr_t new_size) { |
} |
-template <typename T> |
-void DirectChainedHashMap<T>::Insert(T value) { |
- ASSERT(value != NULL); |
+template <typename KeyValueTrait> |
+void DirectChainedHashMap<KeyValueTrait>:: |
+ Insert(typename KeyValueTrait::Pair kv) { |
+ ASSERT(KeyValueTrait::ValueOf(kv) != NULL); |
// Resizing when half of the hashtable is filled up. |
if (count_ >= array_size_ >> 1) Resize(array_size_ << 1); |
ASSERT(count_ < array_size_); |
count_++; |
- uword pos = Bound(static_cast<uword>(value->Hashcode())); |
- if (array_[pos].value == NULL) { |
- array_[pos].value = value; |
+ uword pos = Bound( |
+ static_cast<uword>(KeyValueTrait::Hashcode(KeyValueTrait::KeyOf(kv)))); |
+ if (KeyValueTrait::ValueOf(array_[pos].kv) == NULL) { |
+ array_[pos].kv = kv; |
array_[pos].next = kNil; |
} else { |
if (free_list_head_ == kNil) { |
@@ -173,13 +183,39 @@ void DirectChainedHashMap<T>::Insert(T value) { |
intptr_t new_element_pos = free_list_head_; |
ASSERT(new_element_pos != kNil); |
free_list_head_ = lists_[free_list_head_].next; |
- lists_[new_element_pos].value = value; |
+ lists_[new_element_pos].kv = kv; |
lists_[new_element_pos].next = array_[pos].next; |
- ASSERT(array_[pos].next == kNil || lists_[array_[pos].next].value != NULL); |
+ ASSERT(array_[pos].next == kNil || |
+ KeyValueTrait::ValueOf(lists_[array_[pos].next].kv) != NULL); |
array_[pos].next = new_element_pos; |
} |
} |
+ |
+template<typename T> |
+class PointerKeyValueTrait { |
+ public: |
+ typedef T* Value; |
+ typedef T* Key; |
+ typedef T* Pair; |
+ |
+ static Key KeyOf(Pair kv) { |
+ return kv; |
+ } |
+ |
+ static Value ValueOf(Pair kv) { |
+ return kv; |
+ } |
+ |
+ static inline intptr_t Hashcode(Key key) { |
+ return key->Hashcode(); |
+ } |
+ |
+ static inline bool IsKeyEqual(Pair kv, Key key) { |
+ return kv->Equals(key); |
+ } |
+}; |
+ |
} // namespace dart |
#endif // VM_HASH_MAP_H_ |