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 // The reason we write our own hash map instead of using unordered_map in STL, | 5 // The reason we write our own hash map instead of using unordered_map in STL, |
6 // is that STL containers use a mutex pool on debug build, which will lead to | 6 // is that STL containers use a mutex pool on debug build, which will lead to |
7 // deadlock when we are using async signal handler. | 7 // deadlock when we are using async signal handler. |
8 | 8 |
9 #ifndef V8_BASE_HASHMAP_H_ | 9 #ifndef V8_BASE_HASHMAP_H_ |
10 #define V8_BASE_HASHMAP_H_ | 10 #define V8_BASE_HASHMAP_H_ |
11 | 11 |
12 #include <stdlib.h> | 12 #include <stdlib.h> |
13 | 13 |
14 #include "src/base/bits.h" | 14 #include "src/base/bits.h" |
15 #include "src/base/hashmap-entry.h" | |
15 #include "src/base/logging.h" | 16 #include "src/base/logging.h" |
16 | 17 |
17 namespace v8 { | 18 namespace v8 { |
18 namespace base { | 19 namespace base { |
19 | 20 |
20 class DefaultAllocationPolicy { | 21 class DefaultAllocationPolicy { |
21 public: | 22 public: |
22 V8_INLINE void* New(size_t size) { return malloc(size); } | 23 V8_INLINE void* New(size_t size) { return malloc(size); } |
23 V8_INLINE static void Delete(void* p) { free(p); } | 24 V8_INLINE static void Delete(void* p) { free(p); } |
24 }; | 25 }; |
25 | 26 |
26 template <class AllocationPolicy> | 27 // Metaprogramming helper to allow pointer keys to be passed by value and |
28 // non-pointer keys by const reference. | |
29 template <typename Key> | |
30 struct MatchFunHelper; | |
31 | |
32 template <typename Key, typename Value, class AllocationPolicy> | |
27 class TemplateHashMapImpl { | 33 class TemplateHashMapImpl { |
28 public: | 34 public: |
29 typedef bool (*MatchFun)(void* key1, void* key2); | 35 typedef typename MatchFunHelper<Key>::Fun MatchFun; |
36 typedef TemplateHashMapEntry<Key, Value> Entry; | |
30 | 37 |
31 // The default capacity. This is used by the call sites which want | 38 // The default capacity. This is used by the call sites which want |
32 // to pass in a non-default AllocationPolicy but want to use the | 39 // to pass in a non-default AllocationPolicy but want to use the |
33 // default value of capacity specified by the implementation. | 40 // default value of capacity specified by the implementation. |
34 static const uint32_t kDefaultHashMapCapacity = 8; | 41 static const uint32_t kDefaultHashMapCapacity = 8; |
35 | 42 |
36 // initial_capacity is the size of the initial hash map; | 43 // initial_capacity is the size of the initial hash map; |
37 // it must be a power of 2 (and thus must not be 0). | 44 // it must be a power of 2 (and thus must not be 0). |
38 TemplateHashMapImpl(MatchFun match, | 45 TemplateHashMapImpl(MatchFun match, |
39 uint32_t capacity = kDefaultHashMapCapacity, | 46 uint32_t capacity = kDefaultHashMapCapacity, |
40 AllocationPolicy allocator = AllocationPolicy()); | 47 AllocationPolicy allocator = AllocationPolicy()); |
41 | 48 |
42 ~TemplateHashMapImpl(); | 49 ~TemplateHashMapImpl(); |
43 | 50 |
44 // HashMap entries are (key, value, hash) triplets. | |
45 // Some clients may not need to use the value slot | |
46 // (e.g. implementers of sets, where the key is the value). | |
47 struct Entry { | |
48 void* key; | |
49 void* value; | |
50 uint32_t hash; // The full hash value for key | |
51 }; | |
52 | |
53 // If an entry with matching key is found, returns that entry. | 51 // If an entry with matching key is found, returns that entry. |
54 // Otherwise, NULL is returned. | 52 // Otherwise, nullptr is returned. |
55 Entry* Lookup(void* key, uint32_t hash) const; | 53 Entry* Lookup(const Key& key, uint32_t hash) const; |
56 | 54 |
57 // If an entry with matching key is found, returns that entry. | 55 // If an entry with matching key is found, returns that entry. |
58 // If no matching entry is found, a new entry is inserted with | 56 // If no matching entry is found, a new entry is inserted with |
59 // corresponding key, key hash, and NULL value. | 57 // corresponding key, key hash, and default initialized value. |
60 Entry* LookupOrInsert(void* key, uint32_t hash, | 58 Entry* LookupOrInsert(const Key& key, uint32_t hash, |
61 AllocationPolicy allocator = AllocationPolicy()); | 59 AllocationPolicy allocator = AllocationPolicy()); |
62 | 60 |
63 Entry* InsertNew(void* key, uint32_t hash, | 61 Entry* InsertNew(const Key& key, uint32_t hash, |
64 AllocationPolicy allocator = AllocationPolicy()); | 62 AllocationPolicy allocator = AllocationPolicy()); |
65 | 63 |
66 // Removes the entry with matching key. | 64 // Removes the entry with matching key. |
67 // It returns the value of the deleted entry | 65 // It returns the value of the deleted entry |
68 // or null if there is no value for such key. | 66 // or null if there is no value for such key. |
69 void* Remove(void* key, uint32_t hash); | 67 Value Remove(const Key& key, uint32_t hash); |
70 | 68 |
71 // Empties the hash map (occupancy() == 0). | 69 // Empties the hash map (occupancy() == 0). |
72 void Clear(); | 70 void Clear(); |
73 | 71 |
74 // The number of (non-empty) entries in the table. | 72 // The number of (non-empty) entries in the table. |
75 uint32_t occupancy() const { return occupancy_; } | 73 uint32_t occupancy() const { return occupancy_; } |
76 | 74 |
77 // The capacity of the table. The implementation | 75 // The capacity of the table. The implementation |
78 // makes sure that occupancy is at most 80% of | 76 // makes sure that occupancy is at most 80% of |
79 // the table capacity. | 77 // the table capacity. |
80 uint32_t capacity() const { return capacity_; } | 78 uint32_t capacity() const { return capacity_; } |
81 | 79 |
82 // Iteration | 80 // Iteration |
83 // | 81 // |
84 // for (Entry* p = map.Start(); p != NULL; p = map.Next(p)) { | 82 // for (Entry* p = map.Start(); p != nullptr; p = map.Next(p)) { |
85 // ... | 83 // ... |
86 // } | 84 // } |
87 // | 85 // |
88 // If entries are inserted during iteration, the effect of | 86 // If entries are inserted during iteration, the effect of |
89 // calling Next() is undefined. | 87 // calling Next() is undefined. |
90 Entry* Start() const; | 88 Entry* Start() const; |
91 Entry* Next(Entry* p) const; | 89 Entry* Next(Entry* p) const; |
92 | 90 |
93 // Some match functions defined for convenience. | 91 // Some match functions defined for convenience. |
94 static bool PointersMatch(void* key1, void* key2) { return key1 == key2; } | 92 static bool PointersMatch(typename MatchFunHelper<Key>::KeyRef key1, |
rmcilroy
2016/09/19 10:32:07
Hmm, this isn't really PointersMatch unless Key is
Leszek Swirski
2016/09/19 10:45:33
Added a TODO because I want to move the matcher fu
| |
93 typename MatchFunHelper<Key>::KeyRef key2) { | |
94 return key1 == key2; | |
95 } | |
95 | 96 |
96 private: | 97 private: |
97 MatchFun match_; | 98 MatchFun match_; |
98 Entry* map_; | 99 Entry* map_; |
99 uint32_t capacity_; | 100 uint32_t capacity_; |
100 uint32_t occupancy_; | 101 uint32_t occupancy_; |
101 | 102 |
102 Entry* map_end() const { return map_ + capacity_; } | 103 Entry* map_end() const { return map_ + capacity_; } |
103 Entry* Probe(void* key, uint32_t hash) const; | 104 Entry* Probe(const Key& key, uint32_t hash) const; |
104 void Initialize(uint32_t capacity, AllocationPolicy allocator); | 105 void Initialize(uint32_t capacity, AllocationPolicy allocator); |
105 void Resize(AllocationPolicy allocator); | 106 void Resize(AllocationPolicy allocator); |
106 }; | 107 }; |
107 | 108 |
108 typedef TemplateHashMapImpl<DefaultAllocationPolicy> HashMap; | 109 template <typename Key> |
110 struct MatchFunHelper { | |
111 typedef const Key& KeyRef; | |
112 typedef bool (*Fun)(KeyRef key1, KeyRef key2); | |
113 }; | |
109 | 114 |
110 template <class AllocationPolicy> | 115 template <typename Key> |
111 TemplateHashMapImpl<AllocationPolicy>::TemplateHashMapImpl( | 116 struct MatchFunHelper<Key*> { |
117 typedef Key* KeyRef; | |
118 typedef bool (*Fun)(KeyRef key1, KeyRef key2); | |
119 }; | |
120 | |
121 typedef TemplateHashMapImpl<void*, void*, DefaultAllocationPolicy> HashMap; | |
122 | |
123 template <typename Key, typename Value, class AllocationPolicy> | |
124 TemplateHashMapImpl<Key, Value, AllocationPolicy>::TemplateHashMapImpl( | |
112 MatchFun match, uint32_t initial_capacity, AllocationPolicy allocator) { | 125 MatchFun match, uint32_t initial_capacity, AllocationPolicy allocator) { |
113 match_ = match; | 126 match_ = match; |
114 Initialize(initial_capacity, allocator); | 127 Initialize(initial_capacity, allocator); |
115 } | 128 } |
116 | 129 |
117 template <class AllocationPolicy> | 130 template <typename Key, typename Value, class AllocationPolicy> |
118 TemplateHashMapImpl<AllocationPolicy>::~TemplateHashMapImpl() { | 131 TemplateHashMapImpl<Key, Value, AllocationPolicy>::~TemplateHashMapImpl() { |
119 AllocationPolicy::Delete(map_); | 132 AllocationPolicy::Delete(map_); |
120 } | 133 } |
121 | 134 |
122 template <class AllocationPolicy> | 135 template <typename Key, typename Value, class AllocationPolicy> |
123 typename TemplateHashMapImpl<AllocationPolicy>::Entry* | 136 typename TemplateHashMapImpl<Key, Value, AllocationPolicy>::Entry* |
124 TemplateHashMapImpl<AllocationPolicy>::Lookup(void* key, uint32_t hash) const { | 137 TemplateHashMapImpl<Key, Value, AllocationPolicy>::Lookup(const Key& key, |
138 uint32_t hash) const { | |
125 Entry* p = Probe(key, hash); | 139 Entry* p = Probe(key, hash); |
126 return p->key != NULL ? p : NULL; | 140 return p->exists() ? p : nullptr; |
127 } | 141 } |
128 | 142 |
129 template <class AllocationPolicy> | 143 template <typename Key, typename Value, class AllocationPolicy> |
130 typename TemplateHashMapImpl<AllocationPolicy>::Entry* | 144 typename TemplateHashMapImpl<Key, Value, AllocationPolicy>::Entry* |
131 TemplateHashMapImpl<AllocationPolicy>::LookupOrInsert( | 145 TemplateHashMapImpl<Key, Value, AllocationPolicy>::LookupOrInsert( |
132 void* key, uint32_t hash, AllocationPolicy allocator) { | 146 const Key& key, uint32_t hash, AllocationPolicy allocator) { |
133 // Find a matching entry. | 147 // Find a matching entry. |
134 Entry* p = Probe(key, hash); | 148 Entry* p = Probe(key, hash); |
135 if (p->key != NULL) { | 149 if (p->exists()) { |
136 return p; | 150 return p; |
137 } | 151 } |
138 | 152 |
139 return InsertNew(key, hash, allocator); | 153 return InsertNew(key, hash, allocator); |
140 } | 154 } |
141 | 155 |
142 template <class AllocationPolicy> | 156 template <typename Key, typename Value, class AllocationPolicy> |
143 typename TemplateHashMapImpl<AllocationPolicy>::Entry* | 157 typename TemplateHashMapImpl<Key, Value, AllocationPolicy>::Entry* |
144 TemplateHashMapImpl<AllocationPolicy>::InsertNew(void* key, uint32_t hash, | 158 TemplateHashMapImpl<Key, Value, AllocationPolicy>::InsertNew( |
145 AllocationPolicy allocator) { | 159 const Key& key, uint32_t hash, AllocationPolicy allocator) { |
146 // Find a matching entry. | 160 // Find a matching entry. |
147 Entry* p = Probe(key, hash); | 161 Entry* p = Probe(key, hash); |
148 DCHECK(p->key == NULL); | 162 DCHECK(!p->exists()); |
149 | 163 |
150 // No entry found; insert one. | 164 // No entry found; insert one. |
151 p->key = key; | 165 new (p) Entry(key, Value(), hash); |
rmcilroy
2016/09/19 10:32:07
Could you add a comment that this is in-placement
Leszek Swirski
2016/09/19 10:45:33
Done.
| |
152 p->value = NULL; | |
153 p->hash = hash; | |
154 occupancy_++; | 166 occupancy_++; |
155 | 167 |
156 // Grow the map if we reached >= 80% occupancy. | 168 // Grow the map if we reached >= 80% occupancy. |
157 if (occupancy_ + occupancy_ / 4 >= capacity_) { | 169 if (occupancy_ + occupancy_ / 4 >= capacity_) { |
158 Resize(allocator); | 170 Resize(allocator); |
159 p = Probe(key, hash); | 171 p = Probe(key, hash); |
160 } | 172 } |
161 | 173 |
162 return p; | 174 return p; |
163 } | 175 } |
164 | 176 |
165 template <class AllocationPolicy> | 177 template <typename Key, typename Value, class AllocationPolicy> |
166 void* TemplateHashMapImpl<AllocationPolicy>::Remove(void* key, uint32_t hash) { | 178 Value TemplateHashMapImpl<Key, Value, AllocationPolicy>::Remove(const Key& key, |
179 uint32_t hash) { | |
167 // Lookup the entry for the key to remove. | 180 // Lookup the entry for the key to remove. |
168 Entry* p = Probe(key, hash); | 181 Entry* p = Probe(key, hash); |
169 if (p->key == NULL) { | 182 if (!p->exists()) { |
170 // Key not found nothing to remove. | 183 // Key not found nothing to remove. |
171 return NULL; | 184 return nullptr; |
172 } | 185 } |
173 | 186 |
174 void* value = p->value; | 187 Value value = p->value; |
175 // To remove an entry we need to ensure that it does not create an empty | 188 // To remove an entry we need to ensure that it does not create an empty |
176 // entry that will cause the search for another entry to stop too soon. If all | 189 // entry that will cause the search for another entry to stop too soon. If all |
177 // the entries between the entry to remove and the next empty slot have their | 190 // the entries between the entry to remove and the next empty slot have their |
178 // initial position inside this interval, clearing the entry to remove will | 191 // initial position inside this interval, clearing the entry to remove will |
179 // not break the search. If, while searching for the next empty entry, an | 192 // not break the search. If, while searching for the next empty entry, an |
180 // entry is encountered which does not have its initial position between the | 193 // entry is encountered which does not have its initial position between the |
181 // entry to remove and the position looked at, then this entry can be moved to | 194 // entry to remove and the position looked at, then this entry can be moved to |
182 // the place of the entry to remove without breaking the search for it. The | 195 // the place of the entry to remove without breaking the search for it. The |
183 // entry made vacant by this move is now the entry to remove and the process | 196 // entry made vacant by this move is now the entry to remove and the process |
184 // starts over. | 197 // starts over. |
185 // Algorithm from http://en.wikipedia.org/wiki/Open_addressing. | 198 // Algorithm from http://en.wikipedia.org/wiki/Open_addressing. |
186 | 199 |
187 // This guarantees loop termination as there is at least one empty entry so | 200 // This guarantees loop termination as there is at least one empty entry so |
188 // eventually the removed entry will have an empty entry after it. | 201 // eventually the removed entry will have an empty entry after it. |
189 DCHECK(occupancy_ < capacity_); | 202 DCHECK(occupancy_ < capacity_); |
190 | 203 |
191 // p is the candidate entry to clear. q is used to scan forwards. | 204 // p is the candidate entry to clear. q is used to scan forwards. |
192 Entry* q = p; // Start at the entry to remove. | 205 Entry* q = p; // Start at the entry to remove. |
193 while (true) { | 206 while (true) { |
194 // Move q to the next entry. | 207 // Move q to the next entry. |
195 q = q + 1; | 208 q = q + 1; |
196 if (q == map_end()) { | 209 if (q == map_end()) { |
197 q = map_; | 210 q = map_; |
198 } | 211 } |
199 | 212 |
200 // All entries between p and q have their initial position between p and q | 213 // All entries between p and q have their initial position between p and q |
201 // and the entry p can be cleared without breaking the search for these | 214 // and the entry p can be cleared without breaking the search for these |
202 // entries. | 215 // entries. |
203 if (q->key == NULL) { | 216 if (!q->exists()) { |
204 break; | 217 break; |
205 } | 218 } |
206 | 219 |
207 // Find the initial position for the entry at position q. | 220 // Find the initial position for the entry at position q. |
208 Entry* r = map_ + (q->hash & (capacity_ - 1)); | 221 Entry* r = map_ + (q->hash & (capacity_ - 1)); |
209 | 222 |
210 // If the entry at position q has its initial position outside the range | 223 // If the entry at position q has its initial position outside the range |
211 // between p and q it can be moved forward to position p and will still be | 224 // between p and q it can be moved forward to position p and will still be |
212 // found. There is now a new candidate entry for clearing. | 225 // found. There is now a new candidate entry for clearing. |
213 if ((q > p && (r <= p || r > q)) || (q < p && (r <= p && r > q))) { | 226 if ((q > p && (r <= p || r > q)) || (q < p && (r <= p && r > q))) { |
214 *p = *q; | 227 *p = *q; |
215 p = q; | 228 p = q; |
216 } | 229 } |
217 } | 230 } |
218 | 231 |
219 // Clear the entry which is allowed to en emptied. | 232 // Clear the entry which is allowed to en emptied. |
220 p->key = NULL; | 233 p->clear(); |
221 occupancy_--; | 234 occupancy_--; |
222 return value; | 235 return value; |
223 } | 236 } |
224 | 237 |
225 template <class AllocationPolicy> | 238 template <typename Key, typename Value, class AllocationPolicy> |
226 void TemplateHashMapImpl<AllocationPolicy>::Clear() { | 239 void TemplateHashMapImpl<Key, Value, AllocationPolicy>::Clear() { |
227 // Mark all entries as empty. | 240 // Mark all entries as empty. |
228 const Entry* end = map_end(); | 241 const Entry* end = map_end(); |
229 for (Entry* p = map_; p < end; p++) { | 242 for (Entry* p = map_; p < end; p++) { |
230 p->key = NULL; | 243 p->clear(); |
231 } | 244 } |
232 occupancy_ = 0; | 245 occupancy_ = 0; |
233 } | 246 } |
234 | 247 |
235 template <class AllocationPolicy> | 248 template <typename Key, typename Value, class AllocationPolicy> |
236 typename TemplateHashMapImpl<AllocationPolicy>::Entry* | 249 typename TemplateHashMapImpl<Key, Value, AllocationPolicy>::Entry* |
237 TemplateHashMapImpl<AllocationPolicy>::Start() const { | 250 TemplateHashMapImpl<Key, Value, AllocationPolicy>::Start() const { |
238 return Next(map_ - 1); | 251 return Next(map_ - 1); |
239 } | 252 } |
240 | 253 |
241 template <class AllocationPolicy> | 254 template <typename Key, typename Value, class AllocationPolicy> |
242 typename TemplateHashMapImpl<AllocationPolicy>::Entry* | 255 typename TemplateHashMapImpl<Key, Value, AllocationPolicy>::Entry* |
243 TemplateHashMapImpl<AllocationPolicy>::Next(Entry* p) const { | 256 TemplateHashMapImpl<Key, Value, AllocationPolicy>::Next(Entry* p) const { |
244 const Entry* end = map_end(); | 257 const Entry* end = map_end(); |
245 DCHECK(map_ - 1 <= p && p < end); | 258 DCHECK(map_ - 1 <= p && p < end); |
246 for (p++; p < end; p++) { | 259 for (p++; p < end; p++) { |
247 if (p->key != NULL) { | 260 if (p->exists()) { |
248 return p; | 261 return p; |
249 } | 262 } |
250 } | 263 } |
251 return NULL; | 264 return nullptr; |
252 } | 265 } |
253 | 266 |
254 template <class AllocationPolicy> | 267 template <typename Key, typename Value, class AllocationPolicy> |
255 typename TemplateHashMapImpl<AllocationPolicy>::Entry* | 268 typename TemplateHashMapImpl<Key, Value, AllocationPolicy>::Entry* |
256 TemplateHashMapImpl<AllocationPolicy>::Probe(void* key, uint32_t hash) const { | 269 TemplateHashMapImpl<Key, Value, AllocationPolicy>::Probe(const Key& key, |
257 DCHECK(key != NULL); | 270 uint32_t hash) const { |
258 | |
259 DCHECK(base::bits::IsPowerOfTwo32(capacity_)); | 271 DCHECK(base::bits::IsPowerOfTwo32(capacity_)); |
260 Entry* p = map_ + (hash & (capacity_ - 1)); | 272 Entry* p = map_ + (hash & (capacity_ - 1)); |
261 const Entry* end = map_end(); | 273 const Entry* end = map_end(); |
262 DCHECK(map_ <= p && p < end); | 274 DCHECK(map_ <= p && p < end); |
263 | 275 |
264 DCHECK(occupancy_ < capacity_); // Guarantees loop termination. | 276 DCHECK(occupancy_ < capacity_); // Guarantees loop termination. |
265 while (p->key != NULL && (hash != p->hash || !match_(key, p->key))) { | 277 while (p->exists() && (hash != p->hash || !match_(key, p->key))) { |
266 p++; | 278 p++; |
267 if (p >= end) { | 279 if (p >= end) { |
268 p = map_; | 280 p = map_; |
269 } | 281 } |
270 } | 282 } |
271 | 283 |
272 return p; | 284 return p; |
273 } | 285 } |
274 | 286 |
275 template <class AllocationPolicy> | 287 template <typename Key, typename Value, class AllocationPolicy> |
276 void TemplateHashMapImpl<AllocationPolicy>::Initialize( | 288 void TemplateHashMapImpl<Key, Value, AllocationPolicy>::Initialize( |
277 uint32_t capacity, AllocationPolicy allocator) { | 289 uint32_t capacity, AllocationPolicy allocator) { |
278 DCHECK(base::bits::IsPowerOfTwo32(capacity)); | 290 DCHECK(base::bits::IsPowerOfTwo32(capacity)); |
279 map_ = reinterpret_cast<Entry*>(allocator.New(capacity * sizeof(Entry))); | 291 map_ = reinterpret_cast<Entry*>(allocator.New(capacity * sizeof(Entry))); |
280 if (map_ == NULL) { | 292 if (map_ == nullptr) { |
281 FATAL("Out of memory: HashMap::Initialize"); | 293 FATAL("Out of memory: HashMap::Initialize"); |
282 return; | 294 return; |
283 } | 295 } |
284 capacity_ = capacity; | 296 capacity_ = capacity; |
285 Clear(); | 297 Clear(); |
286 } | 298 } |
287 | 299 |
288 template <class AllocationPolicy> | 300 template <typename Key, typename Value, class AllocationPolicy> |
289 void TemplateHashMapImpl<AllocationPolicy>::Resize(AllocationPolicy allocator) { | 301 void TemplateHashMapImpl<Key, Value, AllocationPolicy>::Resize( |
302 AllocationPolicy allocator) { | |
290 Entry* map = map_; | 303 Entry* map = map_; |
291 uint32_t n = occupancy_; | 304 uint32_t n = occupancy_; |
292 | 305 |
293 // Allocate larger map. | 306 // Allocate larger map. |
294 Initialize(capacity_ * 2, allocator); | 307 Initialize(capacity_ * 2, allocator); |
295 | 308 |
296 // Rehash all current entries. | 309 // Rehash all current entries. |
297 for (Entry* p = map; n > 0; p++) { | 310 for (Entry* p = map; n > 0; p++) { |
298 if (p->key != NULL) { | 311 if (p->exists()) { |
299 Entry* entry = LookupOrInsert(p->key, p->hash, allocator); | 312 Entry* entry = LookupOrInsert(p->key, p->hash, allocator); |
300 entry->value = p->value; | 313 entry->value = p->value; |
301 n--; | 314 n--; |
302 } | 315 } |
303 } | 316 } |
304 | 317 |
305 // Delete old map. | 318 // Delete old map. |
306 AllocationPolicy::Delete(map); | 319 AllocationPolicy::Delete(map); |
307 } | 320 } |
308 | 321 |
309 // A hash map for pointer keys and values with an STL-like interface. | 322 // A hash map for pointer keys and values with an STL-like interface. |
310 template <class Key, class Value, class AllocationPolicy> | 323 template <class Key, class Value, class AllocationPolicy> |
311 class TemplateHashMap : private TemplateHashMapImpl<AllocationPolicy> { | 324 class TemplateHashMap |
325 : private TemplateHashMapImpl<void*, void*, AllocationPolicy> { | |
312 public: | 326 public: |
313 STATIC_ASSERT(sizeof(Key*) == sizeof(void*)); // NOLINT | 327 STATIC_ASSERT(sizeof(Key*) == sizeof(void*)); // NOLINT |
314 STATIC_ASSERT(sizeof(Value*) == sizeof(void*)); // NOLINT | 328 STATIC_ASSERT(sizeof(Value*) == sizeof(void*)); // NOLINT |
315 struct value_type { | 329 struct value_type { |
316 Key* first; | 330 Key* first; |
317 Value* second; | 331 Value* second; |
318 }; | 332 }; |
319 | 333 |
320 class Iterator { | 334 class Iterator { |
321 public: | 335 public: |
322 Iterator& operator++() { | 336 Iterator& operator++() { |
323 entry_ = map_->Next(entry_); | 337 entry_ = map_->Next(entry_); |
324 return *this; | 338 return *this; |
325 } | 339 } |
326 | 340 |
327 value_type* operator->() { return reinterpret_cast<value_type*>(entry_); } | 341 value_type* operator->() { return reinterpret_cast<value_type*>(entry_); } |
328 bool operator!=(const Iterator& other) { return entry_ != other.entry_; } | 342 bool operator!=(const Iterator& other) { return entry_ != other.entry_; } |
329 | 343 |
330 private: | 344 private: |
331 Iterator(const TemplateHashMapImpl<AllocationPolicy>* map, | 345 Iterator(const TemplateHashMapImpl<void*, void*, AllocationPolicy>* map, |
332 typename TemplateHashMapImpl<AllocationPolicy>::Entry* entry) | 346 typename TemplateHashMapImpl<void*, void*, |
347 AllocationPolicy>::Entry* entry) | |
333 : map_(map), entry_(entry) {} | 348 : map_(map), entry_(entry) {} |
334 | 349 |
335 const TemplateHashMapImpl<AllocationPolicy>* map_; | 350 const TemplateHashMapImpl<void*, void*, AllocationPolicy>* map_; |
336 typename TemplateHashMapImpl<AllocationPolicy>::Entry* entry_; | 351 typename TemplateHashMapImpl<void*, void*, AllocationPolicy>::Entry* entry_; |
337 | 352 |
338 friend class TemplateHashMap; | 353 friend class TemplateHashMap; |
339 }; | 354 }; |
340 | 355 |
341 TemplateHashMap( | 356 TemplateHashMap(typename TemplateHashMapImpl< |
342 typename TemplateHashMapImpl<AllocationPolicy>::MatchFun match, | 357 void*, void*, AllocationPolicy>::MatchFun match, |
343 AllocationPolicy allocator = AllocationPolicy()) | 358 AllocationPolicy allocator = AllocationPolicy()) |
344 : TemplateHashMapImpl<AllocationPolicy>( | 359 : TemplateHashMapImpl<void*, void*, AllocationPolicy>( |
345 match, | 360 match, |
346 TemplateHashMapImpl<AllocationPolicy>::kDefaultHashMapCapacity, | 361 TemplateHashMapImpl<void*, void*, |
362 AllocationPolicy>::kDefaultHashMapCapacity, | |
347 allocator) {} | 363 allocator) {} |
348 | 364 |
349 Iterator begin() const { return Iterator(this, this->Start()); } | 365 Iterator begin() const { return Iterator(this, this->Start()); } |
350 Iterator end() const { return Iterator(this, NULL); } | 366 Iterator end() const { return Iterator(this, nullptr); } |
351 Iterator find(Key* key, bool insert = false, | 367 Iterator find(Key* key, bool insert = false, |
352 AllocationPolicy allocator = AllocationPolicy()) { | 368 AllocationPolicy allocator = AllocationPolicy()) { |
353 if (insert) { | 369 if (insert) { |
354 return Iterator(this, this->LookupOrInsert(key, key->Hash(), allocator)); | 370 return Iterator(this, this->LookupOrInsert(key, key->Hash(), allocator)); |
355 } | 371 } |
356 return Iterator(this, this->Lookup(key, key->Hash())); | 372 return Iterator(this, this->Lookup(key, key->Hash())); |
357 } | 373 } |
358 }; | 374 }; |
359 | 375 |
360 } // namespace base | 376 } // namespace base |
361 } // namespace v8 | 377 } // namespace v8 |
362 | 378 |
363 #endif // V8_BASE_HASHMAP_H_ | 379 #endif // V8_BASE_HASHMAP_H_ |
OLD | NEW |