| 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_
|
|
|