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_ |
(...skipping 18 matching lines...) Expand all Loading... |
29 public: | 29 public: |
30 typedef TemplateHashMapEntry<Key, Value> Entry; | 30 typedef TemplateHashMapEntry<Key, Value> Entry; |
31 | 31 |
32 // The default capacity. This is used by the call sites which want | 32 // The default capacity. This is used by the call sites which want |
33 // to pass in a non-default AllocationPolicy but want to use the | 33 // to pass in a non-default AllocationPolicy but want to use the |
34 // default value of capacity specified by the implementation. | 34 // default value of capacity specified by the implementation. |
35 static const uint32_t kDefaultHashMapCapacity = 8; | 35 static const uint32_t kDefaultHashMapCapacity = 8; |
36 | 36 |
37 // initial_capacity is the size of the initial hash map; | 37 // initial_capacity is the size of the initial hash map; |
38 // it must be a power of 2 (and thus must not be 0). | 38 // it must be a power of 2 (and thus must not be 0). |
39 TemplateHashMapImpl(MatchFun match = MatchFun(), | 39 TemplateHashMapImpl(uint32_t capacity = kDefaultHashMapCapacity, |
40 uint32_t capacity = kDefaultHashMapCapacity, | 40 MatchFun match = MatchFun(), |
41 AllocationPolicy allocator = AllocationPolicy()); | 41 AllocationPolicy allocator = AllocationPolicy()); |
42 | 42 |
43 ~TemplateHashMapImpl(); | 43 ~TemplateHashMapImpl(); |
44 | 44 |
45 // If an entry with matching key is found, returns that entry. | 45 // If an entry with matching key is found, returns that entry. |
46 // Otherwise, nullptr is returned. | 46 // Otherwise, nullptr is returned. |
47 Entry* Lookup(const Key& key, uint32_t hash) const; | 47 Entry* Lookup(const Key& key, uint32_t hash) const; |
48 | 48 |
49 // If an entry with matching key is found, returns that entry. | 49 // If an entry with matching key is found, returns that entry. |
50 // If no matching entry is found, a new entry is inserted with | 50 // If no matching entry is found, a new entry is inserted with |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
86 // | 86 // |
87 // If entries are inserted during iteration, the effect of | 87 // If entries are inserted during iteration, the effect of |
88 // calling Next() is undefined. | 88 // calling Next() is undefined. |
89 Entry* Start() const; | 89 Entry* Start() const; |
90 Entry* Next(Entry* entry) const; | 90 Entry* Next(Entry* entry) const; |
91 | 91 |
92 private: | 92 private: |
93 Entry* map_; | 93 Entry* map_; |
94 uint32_t capacity_; | 94 uint32_t capacity_; |
95 uint32_t occupancy_; | 95 uint32_t occupancy_; |
| 96 // TODO(leszeks): This takes up space even if it has no state, maybe replace |
| 97 // with something that does the empty base optimisation e.g. std::tuple |
96 MatchFun match_; | 98 MatchFun match_; |
97 | 99 |
98 Entry* map_end() const { return map_ + capacity_; } | 100 Entry* map_end() const { return map_ + capacity_; } |
99 Entry* Probe(const Key& key, uint32_t hash) const; | 101 Entry* Probe(const Key& key, uint32_t hash) const; |
100 Entry* FillEmptyEntry(Entry* entry, const Key& key, const Value& value, | 102 Entry* FillEmptyEntry(Entry* entry, const Key& key, const Value& value, |
101 uint32_t hash, | 103 uint32_t hash, |
102 AllocationPolicy allocator = AllocationPolicy()); | 104 AllocationPolicy allocator = AllocationPolicy()); |
103 void Initialize(uint32_t capacity, AllocationPolicy allocator); | 105 void Initialize(uint32_t capacity, AllocationPolicy allocator); |
104 void Resize(AllocationPolicy allocator); | 106 void Resize(AllocationPolicy allocator); |
105 }; | 107 }; |
106 template <typename Key, typename Value, typename MatchFun, | 108 template <typename Key, typename Value, typename MatchFun, |
107 class AllocationPolicy> | 109 class AllocationPolicy> |
108 TemplateHashMapImpl<Key, Value, MatchFun, AllocationPolicy>:: | 110 TemplateHashMapImpl<Key, Value, MatchFun, AllocationPolicy>:: |
109 TemplateHashMapImpl(MatchFun match, uint32_t initial_capacity, | 111 TemplateHashMapImpl(uint32_t initial_capacity, MatchFun match, |
110 AllocationPolicy allocator) | 112 AllocationPolicy allocator) |
111 : match_(match) { | 113 : match_(match) { |
112 Initialize(initial_capacity, allocator); | 114 Initialize(initial_capacity, allocator); |
113 } | 115 } |
114 | 116 |
115 template <typename Key, typename Value, typename MatchFun, | 117 template <typename Key, typename Value, typename MatchFun, |
116 class AllocationPolicy> | 118 class AllocationPolicy> |
117 TemplateHashMapImpl<Key, Value, MatchFun, | 119 TemplateHashMapImpl<Key, Value, MatchFun, |
118 AllocationPolicy>::~TemplateHashMapImpl() { | 120 AllocationPolicy>::~TemplateHashMapImpl() { |
119 AllocationPolicy::Delete(map_); | 121 AllocationPolicy::Delete(map_); |
(...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
329 entry->hash, allocator); | 331 entry->hash, allocator); |
330 n--; | 332 n--; |
331 } | 333 } |
332 } | 334 } |
333 | 335 |
334 // Delete old map. | 336 // Delete old map. |
335 AllocationPolicy::Delete(map); | 337 AllocationPolicy::Delete(map); |
336 } | 338 } |
337 | 339 |
338 template <typename AllocationPolicy> | 340 template <typename AllocationPolicy> |
339 class PointerTemplateHashMapImpl | 341 class CustomMatcherTemplateHashMapImpl |
340 : public TemplateHashMapImpl<void*, void*, bool (*)(void*, void*), | 342 : public TemplateHashMapImpl<void*, void*, bool (*)(void*, void*), |
341 AllocationPolicy> { | 343 AllocationPolicy> { |
342 typedef TemplateHashMapImpl<void*, void*, bool (*)(void*, void*), | 344 typedef TemplateHashMapImpl<void*, void*, bool (*)(void*, void*), |
343 AllocationPolicy> | 345 AllocationPolicy> |
344 Base; | 346 Base; |
345 | 347 |
346 public: | 348 public: |
347 typedef bool (*MatchFun)(void*, void*); | 349 typedef bool (*MatchFun)(void*, void*); |
348 | 350 |
349 PointerTemplateHashMapImpl(MatchFun match = PointersMatch, | 351 CustomMatcherTemplateHashMapImpl( |
350 uint32_t capacity = Base::kDefaultHashMapCapacity, | 352 MatchFun match, uint32_t capacity = Base::kDefaultHashMapCapacity, |
| 353 AllocationPolicy allocator = AllocationPolicy()) |
| 354 : Base(capacity, match, allocator) {} |
| 355 }; |
| 356 |
| 357 typedef CustomMatcherTemplateHashMapImpl<DefaultAllocationPolicy> |
| 358 CustomMatcherHashMap; |
| 359 |
| 360 template <typename AllocationPolicy> |
| 361 class PointerTemplateHashMapImpl |
| 362 : public TemplateHashMapImpl<void*, void*, std::equal_to<void*>, |
| 363 AllocationPolicy> { |
| 364 typedef TemplateHashMapImpl<void*, void*, std::equal_to<void*>, |
| 365 AllocationPolicy> |
| 366 Base; |
| 367 |
| 368 public: |
| 369 PointerTemplateHashMapImpl(uint32_t capacity = Base::kDefaultHashMapCapacity, |
351 AllocationPolicy allocator = AllocationPolicy()) | 370 AllocationPolicy allocator = AllocationPolicy()) |
352 : Base(match, capacity, allocator) {} | 371 : Base(capacity, std::equal_to<void*>(), allocator) {} |
353 | |
354 static bool PointersMatch(void* key1, void* key2) { return key1 == key2; } | |
355 }; | 372 }; |
356 | 373 |
357 typedef PointerTemplateHashMapImpl<DefaultAllocationPolicy> HashMap; | 374 typedef PointerTemplateHashMapImpl<DefaultAllocationPolicy> HashMap; |
358 | 375 |
359 // A hash map for pointer keys and values with an STL-like interface. | 376 // A hash map for pointer keys and values with an STL-like interface. |
360 template <class Key, class Value, class AllocationPolicy> | 377 template <class Key, class Value, class MatchFun, class AllocationPolicy> |
361 class TemplateHashMap : private PointerTemplateHashMapImpl<AllocationPolicy> { | 378 class TemplateHashMap |
362 typedef PointerTemplateHashMapImpl<AllocationPolicy> Base; | 379 : private TemplateHashMapImpl<void*, void*, MatchFun, AllocationPolicy> { |
| 380 typedef TemplateHashMapImpl<void*, void*, MatchFun, AllocationPolicy> Base; |
363 | 381 |
364 public: | 382 public: |
365 typedef bool (*MatchFun)(void*, void*); | |
366 | |
367 STATIC_ASSERT(sizeof(Key*) == sizeof(void*)); // NOLINT | 383 STATIC_ASSERT(sizeof(Key*) == sizeof(void*)); // NOLINT |
368 STATIC_ASSERT(sizeof(Value*) == sizeof(void*)); // NOLINT | 384 STATIC_ASSERT(sizeof(Value*) == sizeof(void*)); // NOLINT |
369 struct value_type { | 385 struct value_type { |
370 Key* first; | 386 Key* first; |
371 Value* second; | 387 Value* second; |
372 }; | 388 }; |
373 | 389 |
374 class Iterator { | 390 class Iterator { |
375 public: | 391 public: |
376 Iterator& operator++() { | 392 Iterator& operator++() { |
377 entry_ = map_->Next(entry_); | 393 entry_ = map_->Next(entry_); |
378 return *this; | 394 return *this; |
379 } | 395 } |
380 | 396 |
381 value_type* operator->() { return reinterpret_cast<value_type*>(entry_); } | 397 value_type* operator->() { return reinterpret_cast<value_type*>(entry_); } |
382 bool operator!=(const Iterator& other) { return entry_ != other.entry_; } | 398 bool operator!=(const Iterator& other) { return entry_ != other.entry_; } |
383 | 399 |
384 private: | 400 private: |
385 Iterator(const Base* map, typename Base::Entry* entry) | 401 Iterator(const Base* map, typename Base::Entry* entry) |
386 : map_(map), entry_(entry) {} | 402 : map_(map), entry_(entry) {} |
387 | 403 |
388 const Base* map_; | 404 const Base* map_; |
389 typename Base::Entry* entry_; | 405 typename Base::Entry* entry_; |
390 | 406 |
391 friend class TemplateHashMap; | 407 friend class TemplateHashMap; |
392 }; | 408 }; |
393 | 409 |
394 TemplateHashMap(MatchFun match, | 410 TemplateHashMap(MatchFun match, |
395 AllocationPolicy allocator = AllocationPolicy()) | 411 AllocationPolicy allocator = AllocationPolicy()) |
396 : Base(match, Base::kDefaultHashMapCapacity, allocator) {} | 412 : Base(Base::kDefaultHashMapCapacity, match, allocator) {} |
397 | 413 |
398 Iterator begin() const { return Iterator(this, this->Start()); } | 414 Iterator begin() const { return Iterator(this, this->Start()); } |
399 Iterator end() const { return Iterator(this, nullptr); } | 415 Iterator end() const { return Iterator(this, nullptr); } |
400 Iterator find(Key* key, bool insert = false, | 416 Iterator find(Key* key, bool insert = false, |
401 AllocationPolicy allocator = AllocationPolicy()) { | 417 AllocationPolicy allocator = AllocationPolicy()) { |
402 if (insert) { | 418 if (insert) { |
403 return Iterator(this, this->LookupOrInsert(key, key->Hash(), allocator)); | 419 return Iterator(this, this->LookupOrInsert(key, key->Hash(), allocator)); |
404 } | 420 } |
405 return Iterator(this, this->Lookup(key, key->Hash())); | 421 return Iterator(this, this->Lookup(key, key->Hash())); |
406 } | 422 } |
407 }; | 423 }; |
408 | 424 |
409 } // namespace base | 425 } // namespace base |
410 } // namespace v8 | 426 } // namespace v8 |
411 | 427 |
412 #endif // V8_BASE_HASHMAP_H_ | 428 #endif // V8_BASE_HASHMAP_H_ |
OLD | NEW |