| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #ifndef VM_HASH_MAP_H_ | 5 #ifndef VM_HASH_MAP_H_ |
| 6 #define VM_HASH_MAP_H_ | 6 #define VM_HASH_MAP_H_ |
| 7 | 7 |
| 8 namespace dart { | 8 namespace dart { |
| 9 | 9 |
| 10 template <typename KeyValueTrait> | 10 template <typename KeyValueTrait> |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 50 // with a given hash. Colliding elements are stored in linked lists. | 50 // with a given hash. Colliding elements are stored in linked lists. |
| 51 HashMapListElement* lists_; // The linked lists containing hash collisions. | 51 HashMapListElement* lists_; // The linked lists containing hash collisions. |
| 52 intptr_t free_list_head_; // Unused elements in lists_ are on the free list. | 52 intptr_t free_list_head_; // Unused elements in lists_ are on the free list. |
| 53 }; | 53 }; |
| 54 | 54 |
| 55 | 55 |
| 56 template <typename KeyValueTrait> | 56 template <typename KeyValueTrait> |
| 57 typename KeyValueTrait::Value | 57 typename KeyValueTrait::Value |
| 58 DirectChainedHashMap<KeyValueTrait>:: | 58 DirectChainedHashMap<KeyValueTrait>:: |
| 59 Lookup(typename KeyValueTrait::Key key) const { | 59 Lookup(typename KeyValueTrait::Key key) const { |
| 60 const typename KeyValueTrait::Value kNoValue = |
| 61 static_cast<typename KeyValueTrait::Value>(0); |
| 62 |
| 60 uword hash = static_cast<uword>(KeyValueTrait::Hashcode(key)); | 63 uword hash = static_cast<uword>(KeyValueTrait::Hashcode(key)); |
| 61 uword pos = Bound(hash); | 64 uword pos = Bound(hash); |
| 62 if (KeyValueTrait::ValueOf(array_[pos].kv) != NULL) { | 65 if (KeyValueTrait::ValueOf(array_[pos].kv) != kNoValue) { |
| 63 if (KeyValueTrait::IsKeyEqual(array_[pos].kv, key)) { | 66 if (KeyValueTrait::IsKeyEqual(array_[pos].kv, key)) { |
| 64 return KeyValueTrait::ValueOf(array_[pos].kv); | 67 return KeyValueTrait::ValueOf(array_[pos].kv); |
| 65 } | 68 } |
| 66 | 69 |
| 67 intptr_t next = array_[pos].next; | 70 intptr_t next = array_[pos].next; |
| 68 while (next != kNil) { | 71 while (next != kNil) { |
| 69 if (KeyValueTrait::IsKeyEqual(lists_[next].kv, key)) { | 72 if (KeyValueTrait::IsKeyEqual(lists_[next].kv, key)) { |
| 70 return KeyValueTrait::ValueOf(lists_[next].kv); | 73 return KeyValueTrait::ValueOf(lists_[next].kv); |
| 71 } | 74 } |
| 72 next = lists_[next].next; | 75 next = lists_[next].next; |
| 73 } | 76 } |
| 74 } | 77 } |
| 75 return NULL; | 78 return kNoValue; |
| 76 } | 79 } |
| 77 | 80 |
| 78 | 81 |
| 79 template <typename KeyValueTrait> | 82 template <typename KeyValueTrait> |
| 80 DirectChainedHashMap<KeyValueTrait>:: | 83 DirectChainedHashMap<KeyValueTrait>:: |
| 81 DirectChainedHashMap(const DirectChainedHashMap& other) | 84 DirectChainedHashMap(const DirectChainedHashMap& other) |
| 82 : ValueObject(), | 85 : ValueObject(), |
| 83 array_size_(other.array_size_), | 86 array_size_(other.array_size_), |
| 84 lists_size_(other.lists_size_), | 87 lists_size_(other.lists_size_), |
| 85 count_(other.count_), | 88 count_(other.count_), |
| 86 array_(Isolate::Current()->current_zone()-> | 89 array_(Isolate::Current()->current_zone()-> |
| 87 Alloc<HashMapListElement>(other.array_size_)), | 90 Alloc<HashMapListElement>(other.array_size_)), |
| 88 lists_(Isolate::Current()->current_zone()-> | 91 lists_(Isolate::Current()->current_zone()-> |
| 89 Alloc<HashMapListElement>(other.lists_size_)), | 92 Alloc<HashMapListElement>(other.lists_size_)), |
| 90 free_list_head_(other.free_list_head_) { | 93 free_list_head_(other.free_list_head_) { |
| 91 memmove(array_, other.array_, array_size_ * sizeof(HashMapListElement)); | 94 memmove(array_, other.array_, array_size_ * sizeof(HashMapListElement)); |
| 92 memmove(lists_, other.lists_, lists_size_ * sizeof(HashMapListElement)); | 95 memmove(lists_, other.lists_, lists_size_ * sizeof(HashMapListElement)); |
| 93 } | 96 } |
| 94 | 97 |
| 95 | 98 |
| 96 template <typename KeyValueTrait> | 99 template <typename KeyValueTrait> |
| 97 void DirectChainedHashMap<KeyValueTrait>::Resize(intptr_t new_size) { | 100 void DirectChainedHashMap<KeyValueTrait>::Resize(intptr_t new_size) { |
| 101 const typename KeyValueTrait::Value kNoValue = |
| 102 static_cast<typename KeyValueTrait::Value>(0); |
| 103 |
| 98 ASSERT(new_size > count_); | 104 ASSERT(new_size > count_); |
| 99 // Hashing the values into the new array has no more collisions than in the | 105 // Hashing the values into the new array has no more collisions than in the |
| 100 // old hash map, so we can use the existing lists_ array, if we are careful. | 106 // old hash map, so we can use the existing lists_ array, if we are careful. |
| 101 | 107 |
| 102 // Make sure we have at least one free element. | 108 // Make sure we have at least one free element. |
| 103 if (free_list_head_ == kNil) { | 109 if (free_list_head_ == kNil) { |
| 104 ResizeLists(lists_size_ << 1); | 110 ResizeLists(lists_size_ << 1); |
| 105 } | 111 } |
| 106 | 112 |
| 107 HashMapListElement* new_array = | 113 HashMapListElement* new_array = |
| 108 Isolate::Current()->current_zone()->Alloc<HashMapListElement>(new_size); | 114 Isolate::Current()->current_zone()->Alloc<HashMapListElement>(new_size); |
| 109 memset(new_array, 0, sizeof(HashMapListElement) * new_size); | 115 memset(new_array, 0, sizeof(HashMapListElement) * new_size); |
| 110 | 116 |
| 111 HashMapListElement* old_array = array_; | 117 HashMapListElement* old_array = array_; |
| 112 intptr_t old_size = array_size_; | 118 intptr_t old_size = array_size_; |
| 113 | 119 |
| 114 intptr_t old_count = count_; | 120 intptr_t old_count = count_; |
| 115 count_ = 0; | 121 count_ = 0; |
| 116 array_size_ = new_size; | 122 array_size_ = new_size; |
| 117 array_ = new_array; | 123 array_ = new_array; |
| 118 | 124 |
| 119 if (old_array != NULL) { | 125 if (old_array != NULL) { |
| 120 // Iterate over all the elements in lists, rehashing them. | 126 // Iterate over all the elements in lists, rehashing them. |
| 121 for (intptr_t i = 0; i < old_size; ++i) { | 127 for (intptr_t i = 0; i < old_size; ++i) { |
| 122 if (KeyValueTrait::ValueOf(old_array[i].kv) != NULL) { | 128 if (KeyValueTrait::ValueOf(old_array[i].kv) != kNoValue) { |
| 123 intptr_t current = old_array[i].next; | 129 intptr_t current = old_array[i].next; |
| 124 while (current != kNil) { | 130 while (current != kNil) { |
| 125 Insert(lists_[current].kv); | 131 Insert(lists_[current].kv); |
| 126 intptr_t next = lists_[current].next; | 132 intptr_t next = lists_[current].next; |
| 127 lists_[current].next = free_list_head_; | 133 lists_[current].next = free_list_head_; |
| 128 free_list_head_ = current; | 134 free_list_head_ = current; |
| 129 current = next; | 135 current = next; |
| 130 } | 136 } |
| 131 // Rehash the directly stored value. | 137 // Rehash the directly stored value. |
| 132 Insert(old_array[i].kv); | 138 Insert(old_array[i].kv); |
| (...skipping 26 matching lines...) Expand all Loading... |
| 159 for (intptr_t i = old_size; i < lists_size_; ++i) { | 165 for (intptr_t i = old_size; i < lists_size_; ++i) { |
| 160 lists_[i].next = free_list_head_; | 166 lists_[i].next = free_list_head_; |
| 161 free_list_head_ = i; | 167 free_list_head_ = i; |
| 162 } | 168 } |
| 163 } | 169 } |
| 164 | 170 |
| 165 | 171 |
| 166 template <typename KeyValueTrait> | 172 template <typename KeyValueTrait> |
| 167 void DirectChainedHashMap<KeyValueTrait>:: | 173 void DirectChainedHashMap<KeyValueTrait>:: |
| 168 Insert(typename KeyValueTrait::Pair kv) { | 174 Insert(typename KeyValueTrait::Pair kv) { |
| 169 ASSERT(KeyValueTrait::ValueOf(kv) != NULL); | 175 const typename KeyValueTrait::Value kNoValue = |
| 176 static_cast<typename KeyValueTrait::Value>(0); |
| 177 |
| 178 ASSERT(KeyValueTrait::ValueOf(kv) != kNoValue); |
| 170 // Resizing when half of the hashtable is filled up. | 179 // Resizing when half of the hashtable is filled up. |
| 171 if (count_ >= array_size_ >> 1) Resize(array_size_ << 1); | 180 if (count_ >= array_size_ >> 1) Resize(array_size_ << 1); |
| 172 ASSERT(count_ < array_size_); | 181 ASSERT(count_ < array_size_); |
| 173 count_++; | 182 count_++; |
| 174 uword pos = Bound( | 183 uword pos = Bound( |
| 175 static_cast<uword>(KeyValueTrait::Hashcode(KeyValueTrait::KeyOf(kv)))); | 184 static_cast<uword>(KeyValueTrait::Hashcode(KeyValueTrait::KeyOf(kv)))); |
| 176 if (KeyValueTrait::ValueOf(array_[pos].kv) == NULL) { | 185 if (KeyValueTrait::ValueOf(array_[pos].kv) == kNoValue) { |
| 177 array_[pos].kv = kv; | 186 array_[pos].kv = kv; |
| 178 array_[pos].next = kNil; | 187 array_[pos].next = kNil; |
| 179 } else { | 188 } else { |
| 180 if (free_list_head_ == kNil) { | 189 if (free_list_head_ == kNil) { |
| 181 ResizeLists(lists_size_ << 1); | 190 ResizeLists(lists_size_ << 1); |
| 182 } | 191 } |
| 183 intptr_t new_element_pos = free_list_head_; | 192 intptr_t new_element_pos = free_list_head_; |
| 184 ASSERT(new_element_pos != kNil); | 193 ASSERT(new_element_pos != kNil); |
| 185 free_list_head_ = lists_[free_list_head_].next; | 194 free_list_head_ = lists_[free_list_head_].next; |
| 186 lists_[new_element_pos].kv = kv; | 195 lists_[new_element_pos].kv = kv; |
| 187 lists_[new_element_pos].next = array_[pos].next; | 196 lists_[new_element_pos].next = array_[pos].next; |
| 188 ASSERT(array_[pos].next == kNil || | 197 ASSERT(array_[pos].next == kNil || |
| 189 KeyValueTrait::ValueOf(lists_[array_[pos].next].kv) != NULL); | 198 KeyValueTrait::ValueOf(lists_[array_[pos].next].kv) != kNoValue); |
| 190 array_[pos].next = new_element_pos; | 199 array_[pos].next = new_element_pos; |
| 191 } | 200 } |
| 192 } | 201 } |
| 193 | 202 |
| 194 | 203 |
| 195 template<typename T> | 204 template<typename T> |
| 196 class PointerKeyValueTrait { | 205 class PointerKeyValueTrait { |
| 197 public: | 206 public: |
| 198 typedef T* Value; | 207 typedef T* Value; |
| 199 typedef T* Key; | 208 typedef T* Key; |
| (...skipping 12 matching lines...) Expand all Loading... |
| 212 } | 221 } |
| 213 | 222 |
| 214 static inline bool IsKeyEqual(Pair kv, Key key) { | 223 static inline bool IsKeyEqual(Pair kv, Key key) { |
| 215 return kv->Equals(key); | 224 return kv->Equals(key); |
| 216 } | 225 } |
| 217 }; | 226 }; |
| 218 | 227 |
| 219 } // namespace dart | 228 } // namespace dart |
| 220 | 229 |
| 221 #endif // VM_HASH_MAP_H_ | 230 #endif // VM_HASH_MAP_H_ |
| OLD | NEW |