Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #ifndef V8_HASHMAP_H_ | 5 #ifndef V8_HASHMAP_H_ |
| 6 #define V8_HASHMAP_H_ | 6 #define V8_HASHMAP_H_ |
| 7 | 7 |
| 8 #include "src/allocation.h" | 8 #include "src/allocation.h" |
| 9 #include "src/base/bits.h" | 9 #include "src/base/bits.h" |
| 10 #include "src/base/logging.h" | 10 #include "src/base/logging.h" |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 34 // HashMap entries are (key, value, hash) triplets. | 34 // HashMap entries are (key, value, hash) triplets. |
| 35 // Some clients may not need to use the value slot | 35 // Some clients may not need to use the value slot |
| 36 // (e.g. implementers of sets, where the key is the value). | 36 // (e.g. implementers of sets, where the key is the value). |
| 37 struct Entry { | 37 struct Entry { |
| 38 void* key; | 38 void* key; |
| 39 void* value; | 39 void* value; |
| 40 uint32_t hash; // The full hash value for key | 40 uint32_t hash; // The full hash value for key |
| 41 int order; // If you never remove entries this is the insertion order. | 41 int order; // If you never remove entries this is the insertion order. |
| 42 }; | 42 }; |
| 43 | 43 |
| 44 // If an entry with matching key is found, Lookup() | 44 // If an entry with matching key is found, returns that entry. |
| 45 // returns that entry. If no matching entry is found, | 45 // Otherwise, NULL is returned. |
| 46 // but insert is set, a new entry is inserted with | 46 Entry* Lookup(void* key, uint32_t hash); |
| 47 | |
| 48 // If an entry with matching key is found, returns that entry. | |
| 49 // If no matching entry is found, a new entry is inserted with | |
| 47 // corresponding key, key hash, and NULL value. | 50 // corresponding key, key hash, and NULL value. |
| 48 // Otherwise, NULL is returned. | 51 Entry* LookupOrInsert(void* key, uint32_t hash, |
| 49 Entry* Lookup(void* key, uint32_t hash, bool insert, | 52 AllocationPolicy allocator = AllocationPolicy()); |
| 50 AllocationPolicy allocator = AllocationPolicy()); | |
| 51 | 53 |
| 52 // Removes the entry with matching key. | 54 // Removes the entry with matching key. |
| 53 // It returns the value of the deleted entry | 55 // It returns the value of the deleted entry |
| 54 // or null if there is no value for such key. | 56 // or null if there is no value for such key. |
| 55 void* Remove(void* key, uint32_t hash); | 57 void* Remove(void* key, uint32_t hash); |
| 56 | 58 |
| 57 // Empties the hash map (occupancy() == 0). | 59 // Empties the hash map (occupancy() == 0). |
| 58 void Clear(); | 60 void Clear(); |
| 59 | 61 |
| 60 // The number of (non-empty) entries in the table. | 62 // The number of (non-empty) entries in the table. |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 102 Initialize(initial_capacity, allocator); | 104 Initialize(initial_capacity, allocator); |
| 103 } | 105 } |
| 104 | 106 |
| 105 | 107 |
| 106 template<class AllocationPolicy> | 108 template<class AllocationPolicy> |
| 107 TemplateHashMapImpl<AllocationPolicy>::~TemplateHashMapImpl() { | 109 TemplateHashMapImpl<AllocationPolicy>::~TemplateHashMapImpl() { |
| 108 AllocationPolicy::Delete(map_); | 110 AllocationPolicy::Delete(map_); |
| 109 } | 111 } |
| 110 | 112 |
| 111 | 113 |
| 112 template<class AllocationPolicy> | 114 template <class AllocationPolicy> |
| 113 typename TemplateHashMapImpl<AllocationPolicy>::Entry* | 115 typename TemplateHashMapImpl<AllocationPolicy>::Entry* |
| 114 TemplateHashMapImpl<AllocationPolicy>::Lookup( | 116 TemplateHashMapImpl<AllocationPolicy>::Lookup(void* key, uint32_t hash) { |
| 115 void* key, uint32_t hash, bool insert, AllocationPolicy allocator) { | 117 Entry* p = Probe(key, hash); |
| 118 return p->key != NULL ? p : NULL; | |
|
marja
2015/04/10 07:59:58
We seem to be migrating to use nullptr instead of
adamk
2015/04/13 18:34:41
I'd favor consistency here, if that's ok with you;
| |
| 119 } | |
| 120 | |
| 121 | |
| 122 template <class AllocationPolicy> | |
| 123 typename TemplateHashMapImpl<AllocationPolicy>::Entry* | |
| 124 TemplateHashMapImpl<AllocationPolicy>::LookupOrInsert( | |
| 125 void* key, uint32_t hash, AllocationPolicy allocator) { | |
| 116 // Find a matching entry. | 126 // Find a matching entry. |
| 117 Entry* p = Probe(key, hash); | 127 Entry* p = Probe(key, hash); |
| 118 if (p->key != NULL) { | 128 if (p->key != NULL) { |
| 119 return p; | 129 return p; |
| 120 } | 130 } |
| 121 | 131 |
| 122 // No entry found; insert one if necessary. | 132 // No entry found; insert one. |
| 123 if (insert) { | 133 p->key = key; |
| 124 p->key = key; | 134 p->value = NULL; |
| 125 p->value = NULL; | 135 p->hash = hash; |
| 126 p->hash = hash; | 136 p->order = occupancy_; |
| 127 p->order = occupancy_; | 137 occupancy_++; |
| 128 occupancy_++; | |
| 129 | 138 |
| 130 // Grow the map if we reached >= 80% occupancy. | 139 // Grow the map if we reached >= 80% occupancy. |
| 131 if (occupancy_ + occupancy_/4 >= capacity_) { | 140 if (occupancy_ + occupancy_ / 4 >= capacity_) { |
| 132 Resize(allocator); | 141 Resize(allocator); |
| 133 p = Probe(key, hash); | 142 p = Probe(key, hash); |
| 134 } | |
| 135 | |
| 136 return p; | |
| 137 } | 143 } |
| 138 | 144 |
| 139 // No entry found and none inserted. | 145 return p; |
| 140 return NULL; | |
| 141 } | 146 } |
| 142 | 147 |
| 143 | 148 |
| 144 template<class AllocationPolicy> | 149 template<class AllocationPolicy> |
| 145 void* TemplateHashMapImpl<AllocationPolicy>::Remove(void* key, uint32_t hash) { | 150 void* TemplateHashMapImpl<AllocationPolicy>::Remove(void* key, uint32_t hash) { |
| 146 // Lookup the entry for the key to remove. | 151 // Lookup the entry for the key to remove. |
| 147 Entry* p = Probe(key, hash); | 152 Entry* p = Probe(key, hash); |
| 148 if (p->key == NULL) { | 153 if (p->key == NULL) { |
| 149 // Key not found nothing to remove. | 154 // Key not found nothing to remove. |
| 150 return NULL; | 155 return NULL; |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 228 DCHECK(map_ - 1 <= p && p < end); | 233 DCHECK(map_ - 1 <= p && p < end); |
| 229 for (p++; p < end; p++) { | 234 for (p++; p < end; p++) { |
| 230 if (p->key != NULL) { | 235 if (p->key != NULL) { |
| 231 return p; | 236 return p; |
| 232 } | 237 } |
| 233 } | 238 } |
| 234 return NULL; | 239 return NULL; |
| 235 } | 240 } |
| 236 | 241 |
| 237 | 242 |
| 238 template<class AllocationPolicy> | 243 template <class AllocationPolicy> |
| 239 typename TemplateHashMapImpl<AllocationPolicy>::Entry* | 244 typename TemplateHashMapImpl<AllocationPolicy>::Entry* |
| 240 TemplateHashMapImpl<AllocationPolicy>::Probe(void* key, uint32_t hash) { | 245 TemplateHashMapImpl<AllocationPolicy>::Probe(void* key, uint32_t hash) { |
| 241 DCHECK(key != NULL); | 246 DCHECK(key != NULL); |
| 242 | 247 |
| 243 DCHECK(base::bits::IsPowerOfTwo32(capacity_)); | 248 DCHECK(base::bits::IsPowerOfTwo32(capacity_)); |
| 244 Entry* p = map_ + (hash & (capacity_ - 1)); | 249 Entry* p = map_ + (hash & (capacity_ - 1)); |
| 245 const Entry* end = map_end(); | 250 const Entry* end = map_end(); |
| 246 DCHECK(map_ <= p && p < end); | 251 DCHECK(map_ <= p && p < end); |
| 247 | 252 |
| 248 DCHECK(occupancy_ < capacity_); // Guarantees loop termination. | 253 DCHECK(occupancy_ < capacity_); // Guarantees loop termination. |
| 249 while (p->key != NULL && (hash != p->hash || !match_(key, p->key))) { | 254 while (p->key != NULL && (hash != p->hash || !match_(key, p->key))) { |
| 250 p++; | 255 p++; |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 275 void TemplateHashMapImpl<AllocationPolicy>::Resize(AllocationPolicy allocator) { | 280 void TemplateHashMapImpl<AllocationPolicy>::Resize(AllocationPolicy allocator) { |
| 276 Entry* map = map_; | 281 Entry* map = map_; |
| 277 uint32_t n = occupancy_; | 282 uint32_t n = occupancy_; |
| 278 | 283 |
| 279 // Allocate larger map. | 284 // Allocate larger map. |
| 280 Initialize(capacity_ * 2, allocator); | 285 Initialize(capacity_ * 2, allocator); |
| 281 | 286 |
| 282 // Rehash all current entries. | 287 // Rehash all current entries. |
| 283 for (Entry* p = map; n > 0; p++) { | 288 for (Entry* p = map; n > 0; p++) { |
| 284 if (p->key != NULL) { | 289 if (p->key != NULL) { |
| 285 Entry* entry = Lookup(p->key, p->hash, true, allocator); | 290 Entry* entry = LookupOrInsert(p->key, p->hash, allocator); |
| 286 entry->value = p->value; | 291 entry->value = p->value; |
| 287 entry->order = p->order; | 292 entry->order = p->order; |
| 288 n--; | 293 n--; |
| 289 } | 294 } |
| 290 } | 295 } |
| 291 | 296 |
| 292 // Delete old map. | 297 // Delete old map. |
| 293 AllocationPolicy::Delete(map); | 298 AllocationPolicy::Delete(map); |
| 294 } | 299 } |
| 295 | 300 |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 331 AllocationPolicy allocator = AllocationPolicy()) | 336 AllocationPolicy allocator = AllocationPolicy()) |
| 332 : TemplateHashMapImpl<AllocationPolicy>( | 337 : TemplateHashMapImpl<AllocationPolicy>( |
| 333 match, | 338 match, |
| 334 TemplateHashMapImpl<AllocationPolicy>::kDefaultHashMapCapacity, | 339 TemplateHashMapImpl<AllocationPolicy>::kDefaultHashMapCapacity, |
| 335 allocator) { } | 340 allocator) { } |
| 336 | 341 |
| 337 Iterator begin() const { return Iterator(this, this->Start()); } | 342 Iterator begin() const { return Iterator(this, this->Start()); } |
| 338 Iterator end() const { return Iterator(this, NULL); } | 343 Iterator end() const { return Iterator(this, NULL); } |
| 339 Iterator find(Key* key, bool insert = false, | 344 Iterator find(Key* key, bool insert = false, |
| 340 AllocationPolicy allocator = AllocationPolicy()) { | 345 AllocationPolicy allocator = AllocationPolicy()) { |
| 341 return Iterator(this, this->Lookup(key, key->Hash(), insert, allocator)); | 346 if (insert) { |
| 347 return Iterator(this, this->LookupOrInsert(key, key->Hash(), allocator)); | |
| 348 } | |
| 349 return Iterator(this, this->Lookup(key, key->Hash())); | |
| 342 } | 350 } |
| 343 }; | 351 }; |
| 344 | 352 |
| 345 } } // namespace v8::internal | 353 } } // namespace v8::internal |
| 346 | 354 |
| 347 #endif // V8_HASHMAP_H_ | 355 #endif // V8_HASHMAP_H_ |
| OLD | NEW |