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 |