 Chromium Code Reviews
 Chromium Code Reviews Issue 2354593002:
  [base] Template MatchFun in TemplateHashMapImpl  (Closed)
    
  
    Issue 2354593002:
  [base] Template MatchFun in TemplateHashMapImpl  (Closed) 
  | 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/hashmap-entry.h" | 
| 16 #include "src/base/logging.h" | 16 #include "src/base/logging.h" | 
| 17 | 17 | 
| 18 namespace v8 { | 18 namespace v8 { | 
| 19 namespace base { | 19 namespace base { | 
| 20 | 20 | 
| 21 class DefaultAllocationPolicy { | 21 class DefaultAllocationPolicy { | 
| 22 public: | 22 public: | 
| 23 V8_INLINE void* New(size_t size) { return malloc(size); } | 23 V8_INLINE void* New(size_t size) { return malloc(size); } | 
| 24 V8_INLINE static void Delete(void* p) { free(p); } | 24 V8_INLINE static void Delete(void* p) { free(p); } | 
| 25 }; | 25 }; | 
| 26 | 26 | 
| 27 // Metaprogramming helper to allow pointer keys to be passed by value and | 27 template <typename Key, typename Value, class MatchFun, class AllocationPolicy> | 
| 28 // non-pointer keys by const reference. | |
| 29 template <typename Key> | |
| 30 struct MatchFunHelper; | |
| 31 | |
| 32 template <typename Key, typename Value, class AllocationPolicy> | |
| 33 class TemplateHashMapImpl { | 28 class TemplateHashMapImpl { | 
| 34 public: | 29 public: | 
| 35 typedef typename MatchFunHelper<Key>::Fun MatchFun; | |
| 36 typedef TemplateHashMapEntry<Key, Value> Entry; | 30 typedef TemplateHashMapEntry<Key, Value> Entry; | 
| 37 | 31 | 
| 38 // 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 | 
| 39 // 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 | 
| 40 // default value of capacity specified by the implementation. | 34 // default value of capacity specified by the implementation. | 
| 41 static const uint32_t kDefaultHashMapCapacity = 8; | 35 static const uint32_t kDefaultHashMapCapacity = 8; | 
| 42 | 36 | 
| 43 // initial_capacity is the size of the initial hash map; | 37 // initial_capacity is the size of the initial hash map; | 
| 44 // 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). | 
| 45 TemplateHashMapImpl(MatchFun match, | 39 TemplateHashMapImpl(MatchFun match = MatchFun(), | 
| 
rmcilroy
2016/09/19 17:21:35
Does this need to be passed as a argument (and sto
 
Leszek Swirski
2016/09/20 11:14:30
Yes, because it could be stateful (not least, the
 
rmcilroy
2016/09/20 12:57:57
Ok sounds good. No need to specialize for space, t
 
Leszek Swirski
2016/09/20 15:04:20
Acknowledged.
 | |
| 46 uint32_t capacity = kDefaultHashMapCapacity, | 40 uint32_t capacity = kDefaultHashMapCapacity, | 
| 47 AllocationPolicy allocator = AllocationPolicy()); | 41 AllocationPolicy allocator = AllocationPolicy()); | 
| 48 | 42 | 
| 49 ~TemplateHashMapImpl(); | 43 ~TemplateHashMapImpl(); | 
| 50 | 44 | 
| 51 // If an entry with matching key is found, returns that entry. | 45 // If an entry with matching key is found, returns that entry. | 
| 52 // Otherwise, nullptr is returned. | 46 // Otherwise, nullptr is returned. | 
| 53 Entry* Lookup(const Key& key, uint32_t hash) const; | 47 Entry* Lookup(const Key& key, uint32_t hash) const; | 
| 54 | 48 | 
| 55 // If an entry with matching key is found, returns that entry. | 49 // If an entry with matching key is found, returns that entry. | 
| (...skipping 23 matching lines...) Expand all Loading... | |
| 79 // | 73 // | 
| 80 // for (Entry* p = map.Start(); p != nullptr; p = map.Next(p)) { | 74 // for (Entry* p = map.Start(); p != nullptr; p = map.Next(p)) { | 
| 81 // ... | 75 // ... | 
| 82 // } | 76 // } | 
| 83 // | 77 // | 
| 84 // If entries are inserted during iteration, the effect of | 78 // If entries are inserted during iteration, the effect of | 
| 85 // calling Next() is undefined. | 79 // calling Next() is undefined. | 
| 86 Entry* Start() const; | 80 Entry* Start() const; | 
| 87 Entry* Next(Entry* entry) const; | 81 Entry* Next(Entry* entry) const; | 
| 88 | 82 | 
| 89 // Some match functions defined for convenience. | |
| 90 // TODO(leszeks): This isn't really matching pointers, so the name doesn't | |
| 91 // really make sense, but we should remove this entirely and template the map | |
| 92 // on the matching function. | |
| 93 static bool PointersMatch(typename MatchFunHelper<Key>::KeyRef key1, | |
| 94 typename MatchFunHelper<Key>::KeyRef key2) { | |
| 95 return key1 == key2; | |
| 96 } | |
| 97 | |
| 98 private: | 83 private: | 
| 99 MatchFun match_; | |
| 100 Entry* map_; | 84 Entry* map_; | 
| 101 uint32_t capacity_; | 85 uint32_t capacity_; | 
| 102 uint32_t occupancy_; | 86 uint32_t occupancy_; | 
| 87 MatchFun match_; | |
| 103 AllocationPolicy allocator_; | 88 AllocationPolicy allocator_; | 
| 104 | 89 | 
| 105 Entry* map_end() const { return map_ + capacity_; } | 90 Entry* map_end() const { return map_ + capacity_; } | 
| 106 Entry* Probe(const Key& key, uint32_t hash) const; | 91 Entry* Probe(const Key& key, uint32_t hash) const; | 
| 107 Entry* FillEmptyEntry(Entry* entry, const Key& key, const Value& value, | 92 Entry* FillEmptyEntry(Entry* entry, const Key& key, const Value& value, | 
| 108 uint32_t hash); | 93 uint32_t hash); | 
| 109 void Initialize(uint32_t capacity); | 94 void Initialize(uint32_t capacity); | 
| 110 void Resize(); | 95 void Resize(); | 
| 111 }; | 96 }; | 
| 112 | 97 | 
| 113 template <typename Key> | 98 template <typename Key, typename Value, typename MatchFun, | 
| 114 struct MatchFunHelper { | 99 class AllocationPolicy> | 
| 115 typedef const Key& KeyRef; | 100 TemplateHashMapImpl<Key, Value, MatchFun, AllocationPolicy>:: | 
| 116 typedef bool (*Fun)(KeyRef key1, KeyRef key2); | 101 TemplateHashMapImpl(MatchFun match, uint32_t initial_capacity, | 
| 117 }; | 102 AllocationPolicy allocator) | 
| 118 | 103 : match_(match), allocator_(allocator) { | 
| 119 template <typename Key> | |
| 120 struct MatchFunHelper<Key*> { | |
| 121 typedef Key* KeyRef; | |
| 122 typedef bool (*Fun)(KeyRef key1, KeyRef key2); | |
| 123 }; | |
| 124 | |
| 125 typedef TemplateHashMapImpl<void*, void*, DefaultAllocationPolicy> HashMap; | |
| 126 | |
| 127 template <typename Key, typename Value, class AllocationPolicy> | |
| 128 TemplateHashMapImpl<Key, Value, AllocationPolicy>::TemplateHashMapImpl( | |
| 129 MatchFun match, uint32_t initial_capacity, AllocationPolicy allocator) | |
| 130 : allocator_(allocator) { | |
| 131 match_ = match; | |
| 132 Initialize(initial_capacity); | 104 Initialize(initial_capacity); | 
| 133 } | 105 } | 
| 134 | 106 | 
| 135 template <typename Key, typename Value, class AllocationPolicy> | 107 template <typename Key, typename Value, typename MatchFun, | 
| 136 TemplateHashMapImpl<Key, Value, AllocationPolicy>::~TemplateHashMapImpl() { | 108 class AllocationPolicy> | 
| 109 TemplateHashMapImpl<Key, Value, MatchFun, | |
| 110 AllocationPolicy>::~TemplateHashMapImpl() { | |
| 137 allocator_.Delete(map_); | 111 allocator_.Delete(map_); | 
| 138 } | 112 } | 
| 139 | 113 | 
| 140 template <typename Key, typename Value, class AllocationPolicy> | 114 template <typename Key, typename Value, typename MatchFun, | 
| 141 typename TemplateHashMapImpl<Key, Value, AllocationPolicy>::Entry* | 115 class AllocationPolicy> | 
| 142 TemplateHashMapImpl<Key, Value, AllocationPolicy>::Lookup(const Key& key, | 116 typename TemplateHashMapImpl<Key, Value, MatchFun, AllocationPolicy>::Entry* | 
| 143 uint32_t hash) const { | 117 TemplateHashMapImpl<Key, Value, MatchFun, AllocationPolicy>::Lookup( | 
| 118 const Key& key, uint32_t hash) const { | |
| 144 Entry* entry = Probe(key, hash); | 119 Entry* entry = Probe(key, hash); | 
| 145 return entry->exists() ? entry : nullptr; | 120 return entry->exists() ? entry : nullptr; | 
| 146 } | 121 } | 
| 147 | 122 | 
| 148 template <typename Key, typename Value, class AllocationPolicy> | 123 template <typename Key, typename Value, typename MatchFun, | 
| 149 typename TemplateHashMapImpl<Key, Value, AllocationPolicy>::Entry* | 124 class AllocationPolicy> | 
| 150 TemplateHashMapImpl<Key, Value, AllocationPolicy>::LookupOrInsert( | 125 typename TemplateHashMapImpl<Key, Value, MatchFun, AllocationPolicy>::Entry* | 
| 126 TemplateHashMapImpl<Key, Value, MatchFun, AllocationPolicy>::LookupOrInsert( | |
| 151 const Key& key, uint32_t hash) { | 127 const Key& key, uint32_t hash) { | 
| 152 // Find a matching entry. | 128 // Find a matching entry. | 
| 153 Entry* entry = Probe(key, hash); | 129 Entry* entry = Probe(key, hash); | 
| 154 if (entry->exists()) { | 130 if (entry->exists()) { | 
| 155 return entry; | 131 return entry; | 
| 156 } | 132 } | 
| 157 | 133 | 
| 158 return FillEmptyEntry(entry, key, Value(), hash); | 134 return FillEmptyEntry(entry, key, Value(), hash); | 
| 159 } | 135 } | 
| 160 | 136 | 
| 161 template <typename Key, typename Value, class AllocationPolicy> | 137 template <typename Key, typename Value, typename MatchFun, | 
| 162 typename TemplateHashMapImpl<Key, Value, AllocationPolicy>::Entry* | 138 class AllocationPolicy> | 
| 163 TemplateHashMapImpl<Key, Value, AllocationPolicy>::InsertNew(const Key& key, | 139 typename TemplateHashMapImpl<Key, Value, MatchFun, AllocationPolicy>::Entry* | 
| 164 uint32_t hash) { | 140 TemplateHashMapImpl<Key, Value, MatchFun, AllocationPolicy>::InsertNew( | 
| 141 const Key& key, uint32_t hash) { | |
| 165 Entry* entry = Probe(key, hash); | 142 Entry* entry = Probe(key, hash); | 
| 166 return FillEmptyEntry(entry, key, Value(), hash); | 143 return FillEmptyEntry(entry, key, Value(), hash); | 
| 167 } | 144 } | 
| 168 | 145 | 
| 169 template <typename Key, typename Value, class AllocationPolicy> | 146 template <typename Key, typename Value, typename MatchFun, | 
| 170 Value TemplateHashMapImpl<Key, Value, AllocationPolicy>::Remove(const Key& key, | 147 class AllocationPolicy> | 
| 171 uint32_t hash) { | 148 Value TemplateHashMapImpl<Key, Value, MatchFun, AllocationPolicy>::Remove( | 
| 149 const Key& key, uint32_t hash) { | |
| 172 // Lookup the entry for the key to remove. | 150 // Lookup the entry for the key to remove. | 
| 173 Entry* p = Probe(key, hash); | 151 Entry* p = Probe(key, hash); | 
| 174 if (!p->exists()) { | 152 if (!p->exists()) { | 
| 175 // Key not found nothing to remove. | 153 // Key not found nothing to remove. | 
| 176 return nullptr; | 154 return nullptr; | 
| 177 } | 155 } | 
| 178 | 156 | 
| 179 Value value = p->value; | 157 Value value = p->value; | 
| 180 // To remove an entry we need to ensure that it does not create an empty | 158 // To remove an entry we need to ensure that it does not create an empty | 
| 181 // entry that will cause the search for another entry to stop too soon. If all | 159 // entry that will cause the search for another entry to stop too soon. If all | 
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 220 p = q; | 198 p = q; | 
| 221 } | 199 } | 
| 222 } | 200 } | 
| 223 | 201 | 
| 224 // Clear the entry which is allowed to en emptied. | 202 // Clear the entry which is allowed to en emptied. | 
| 225 p->clear(); | 203 p->clear(); | 
| 226 occupancy_--; | 204 occupancy_--; | 
| 227 return value; | 205 return value; | 
| 228 } | 206 } | 
| 229 | 207 | 
| 230 template <typename Key, typename Value, class AllocationPolicy> | 208 template <typename Key, typename Value, typename MatchFun, | 
| 231 void TemplateHashMapImpl<Key, Value, AllocationPolicy>::Clear() { | 209 class AllocationPolicy> | 
| 210 void TemplateHashMapImpl<Key, Value, MatchFun, AllocationPolicy>::Clear() { | |
| 232 // Mark all entries as empty. | 211 // Mark all entries as empty. | 
| 233 const Entry* end = map_end(); | 212 const Entry* end = map_end(); | 
| 234 for (Entry* entry = map_; entry < end; entry++) { | 213 for (Entry* entry = map_; entry < end; entry++) { | 
| 235 entry->clear(); | 214 entry->clear(); | 
| 236 } | 215 } | 
| 237 occupancy_ = 0; | 216 occupancy_ = 0; | 
| 238 } | 217 } | 
| 239 | 218 | 
| 240 template <typename Key, typename Value, class AllocationPolicy> | 219 template <typename Key, typename Value, typename MatchFun, | 
| 241 typename TemplateHashMapImpl<Key, Value, AllocationPolicy>::Entry* | 220 class AllocationPolicy> | 
| 242 TemplateHashMapImpl<Key, Value, AllocationPolicy>::Start() const { | 221 typename TemplateHashMapImpl<Key, Value, MatchFun, AllocationPolicy>::Entry* | 
| 222 TemplateHashMapImpl<Key, Value, MatchFun, AllocationPolicy>::Start() const { | |
| 243 return Next(map_ - 1); | 223 return Next(map_ - 1); | 
| 244 } | 224 } | 
| 245 | 225 | 
| 246 template <typename Key, typename Value, class AllocationPolicy> | 226 template <typename Key, typename Value, typename MatchFun, | 
| 247 typename TemplateHashMapImpl<Key, Value, AllocationPolicy>::Entry* | 227 class AllocationPolicy> | 
| 248 TemplateHashMapImpl<Key, Value, AllocationPolicy>::Next(Entry* entry) const { | 228 typename TemplateHashMapImpl<Key, Value, MatchFun, AllocationPolicy>::Entry* | 
| 229 TemplateHashMapImpl<Key, Value, MatchFun, AllocationPolicy>::Next( | |
| 230 Entry* entry) const { | |
| 249 const Entry* end = map_end(); | 231 const Entry* end = map_end(); | 
| 250 DCHECK(map_ - 1 <= entry && entry < end); | 232 DCHECK(map_ - 1 <= entry && entry < end); | 
| 251 for (entry++; entry < end; entry++) { | 233 for (entry++; entry < end; entry++) { | 
| 252 if (entry->exists()) { | 234 if (entry->exists()) { | 
| 253 return entry; | 235 return entry; | 
| 254 } | 236 } | 
| 255 } | 237 } | 
| 256 return nullptr; | 238 return nullptr; | 
| 257 } | 239 } | 
| 258 | 240 | 
| 259 template <typename Key, typename Value, class AllocationPolicy> | 241 template <typename Key, typename Value, typename MatchFun, | 
| 260 typename TemplateHashMapImpl<Key, Value, AllocationPolicy>::Entry* | 242 class AllocationPolicy> | 
| 261 TemplateHashMapImpl<Key, Value, AllocationPolicy>::Probe(const Key& key, | 243 typename TemplateHashMapImpl<Key, Value, MatchFun, AllocationPolicy>::Entry* | 
| 262 uint32_t hash) const { | 244 TemplateHashMapImpl<Key, Value, MatchFun, AllocationPolicy>::Probe( | 
| 245 const Key& key, uint32_t hash) const { | |
| 263 DCHECK(base::bits::IsPowerOfTwo32(capacity_)); | 246 DCHECK(base::bits::IsPowerOfTwo32(capacity_)); | 
| 264 Entry* entry = map_ + (hash & (capacity_ - 1)); | 247 Entry* entry = map_ + (hash & (capacity_ - 1)); | 
| 265 const Entry* end = map_end(); | 248 const Entry* end = map_end(); | 
| 266 DCHECK(map_ <= entry && entry < end); | 249 DCHECK(map_ <= entry && entry < end); | 
| 267 | 250 | 
| 268 DCHECK(occupancy_ < capacity_); // Guarantees loop termination. | 251 DCHECK(occupancy_ < capacity_); // Guarantees loop termination. | 
| 269 while (entry->exists() && (hash != entry->hash || !match_(key, entry->key))) { | 252 while (entry->exists() && (hash != entry->hash || !match_(key, entry->key))) { | 
| 270 entry++; | 253 entry++; | 
| 271 if (entry >= end) { | 254 if (entry >= end) { | 
| 272 entry = map_; | 255 entry = map_; | 
| 273 } | 256 } | 
| 274 } | 257 } | 
| 275 | 258 | 
| 276 return entry; | 259 return entry; | 
| 277 } | 260 } | 
| 278 | 261 | 
| 279 template <typename Key, typename Value, class AllocationPolicy> | 262 template <typename Key, typename Value, typename MatchFun, | 
| 280 typename TemplateHashMapImpl<Key, Value, AllocationPolicy>::Entry* | 263 class AllocationPolicy> | 
| 281 TemplateHashMapImpl<Key, Value, AllocationPolicy>::FillEmptyEntry( | 264 typename TemplateHashMapImpl<Key, Value, MatchFun, AllocationPolicy>::Entry* | 
| 265 TemplateHashMapImpl<Key, Value, MatchFun, AllocationPolicy>::FillEmptyEntry( | |
| 282 Entry* entry, const Key& key, const Value& value, uint32_t hash) { | 266 Entry* entry, const Key& key, const Value& value, uint32_t hash) { | 
| 283 DCHECK(!entry->exists()); | 267 DCHECK(!entry->exists()); | 
| 284 | 268 | 
| 285 new (entry) Entry(key, value, hash); | 269 new (entry) Entry(key, value, hash); | 
| 286 occupancy_++; | 270 occupancy_++; | 
| 287 | 271 | 
| 288 // Grow the map if we reached >= 80% occupancy. | 272 // Grow the map if we reached >= 80% occupancy. | 
| 289 if (occupancy_ + occupancy_ / 4 >= capacity_) { | 273 if (occupancy_ + occupancy_ / 4 >= capacity_) { | 
| 290 Resize(); | 274 Resize(); | 
| 291 entry = Probe(key, hash); | 275 entry = Probe(key, hash); | 
| 292 } | 276 } | 
| 293 | 277 | 
| 294 return entry; | 278 return entry; | 
| 295 } | 279 } | 
| 296 | 280 | 
| 297 template <typename Key, typename Value, class AllocationPolicy> | 281 template <typename Key, typename Value, typename MatchFun, | 
| 298 void TemplateHashMapImpl<Key, Value, AllocationPolicy>::Initialize( | 282 class AllocationPolicy> | 
| 283 void TemplateHashMapImpl<Key, Value, MatchFun, AllocationPolicy>::Initialize( | |
| 299 uint32_t capacity) { | 284 uint32_t capacity) { | 
| 300 DCHECK(base::bits::IsPowerOfTwo32(capacity)); | 285 DCHECK(base::bits::IsPowerOfTwo32(capacity)); | 
| 301 map_ = reinterpret_cast<Entry*>(allocator_.New(capacity * sizeof(Entry))); | 286 map_ = reinterpret_cast<Entry*>(allocator_.New(capacity * sizeof(Entry))); | 
| 302 if (map_ == nullptr) { | 287 if (map_ == nullptr) { | 
| 303 FATAL("Out of memory: HashMap::Initialize"); | 288 FATAL("Out of memory: HashMap::Initialize"); | 
| 304 return; | 289 return; | 
| 305 } | 290 } | 
| 306 capacity_ = capacity; | 291 capacity_ = capacity; | 
| 307 Clear(); | 292 Clear(); | 
| 308 } | 293 } | 
| 309 | 294 | 
| 310 template <typename Key, typename Value, class AllocationPolicy> | 295 template <typename Key, typename Value, typename MatchFun, | 
| 311 void TemplateHashMapImpl<Key, Value, AllocationPolicy>::Resize() { | 296 class AllocationPolicy> | 
| 297 void TemplateHashMapImpl<Key, Value, MatchFun, AllocationPolicy>::Resize() { | |
| 312 Entry* map = map_; | 298 Entry* map = map_; | 
| 313 uint32_t n = occupancy_; | 299 uint32_t n = occupancy_; | 
| 314 | 300 | 
| 315 // Allocate larger map. | 301 // Allocate larger map. | 
| 316 Initialize(capacity_ * 2); | 302 Initialize(capacity_ * 2); | 
| 317 | 303 | 
| 318 // Rehash all current entries. | 304 // Rehash all current entries. | 
| 319 for (Entry* entry = map; n > 0; entry++) { | 305 for (Entry* entry = map; n > 0; entry++) { | 
| 320 if (entry->exists()) { | 306 if (entry->exists()) { | 
| 321 Entry* new_entry = Probe(entry->key, entry->hash); | 307 Entry* new_entry = Probe(entry->key, entry->hash); | 
| 322 new_entry = | 308 new_entry = | 
| 323 FillEmptyEntry(new_entry, entry->key, entry->value, entry->hash); | 309 FillEmptyEntry(new_entry, entry->key, entry->value, entry->hash); | 
| 324 n--; | 310 n--; | 
| 325 } | 311 } | 
| 326 } | 312 } | 
| 327 | 313 | 
| 328 // Delete old map. | 314 // Delete old map. | 
| 329 allocator_.Delete(map); | 315 allocator_.Delete(map); | 
| 330 } | 316 } | 
| 331 | 317 | 
| 318 template <typename AllocationPolicy> | |
| 
rmcilroy
2016/09/19 17:21:35
Any reason we need both this class and TemplateHas
 
Leszek Swirski
2016/09/20 11:14:30
It's to have
a) a static PointersMatch method, an
 
rmcilroy
2016/09/20 12:57:57
Ok makes sense. A couple of points though: 
 - Thi
 
Leszek Swirski
2016/09/20 15:04:20
I was actually considering re-ordering the paramet
 
rmcilroy
2016/09/20 16:06:03
Yeah this probably makes sense - it does seem to b
 | |
| 319 class PointerHashMap | |
| 320 : public TemplateHashMapImpl<void*, void*, bool (*)(void*, void*), | |
| 321 AllocationPolicy> { | |
| 322 typedef TemplateHashMapImpl<void*, void*, bool (*)(void*, void*), | |
| 323 AllocationPolicy> | |
| 324 Base; | |
| 325 | |
| 326 public: | |
| 327 typedef bool (*MatchFun)(void*, void*); | |
| 328 | |
| 329 PointerHashMap(MatchFun match, | |
| 330 uint32_t capacity = Base::kDefaultHashMapCapacity, | |
| 331 AllocationPolicy allocator = AllocationPolicy()) | |
| 332 : Base(match, capacity, allocator) {} | |
| 333 | |
| 334 static bool PointersMatch(void* key1, void* key2) { return key1 == key2; } | |
| 335 }; | |
| 336 | |
| 337 typedef PointerHashMap<DefaultAllocationPolicy> HashMap; | |
| 338 | |
| 332 // A hash map for pointer keys and values with an STL-like interface. | 339 // A hash map for pointer keys and values with an STL-like interface. | 
| 333 template <class Key, class Value, class AllocationPolicy> | 340 template <class Key, class Value, class AllocationPolicy> | 
| 334 class TemplateHashMap | 341 class TemplateHashMap : private PointerHashMap<AllocationPolicy> { | 
| 335 : private TemplateHashMapImpl<void*, void*, AllocationPolicy> { | 342 typedef PointerHashMap<AllocationPolicy> Base; | 
| 343 | |
| 336 public: | 344 public: | 
| 345 typedef bool (*MatchFun)(void*, void*); | |
| 346 | |
| 337 STATIC_ASSERT(sizeof(Key*) == sizeof(void*)); // NOLINT | 347 STATIC_ASSERT(sizeof(Key*) == sizeof(void*)); // NOLINT | 
| 338 STATIC_ASSERT(sizeof(Value*) == sizeof(void*)); // NOLINT | 348 STATIC_ASSERT(sizeof(Value*) == sizeof(void*)); // NOLINT | 
| 339 struct value_type { | 349 struct value_type { | 
| 340 Key* first; | 350 Key* first; | 
| 341 Value* second; | 351 Value* second; | 
| 342 }; | 352 }; | 
| 343 | 353 | 
| 344 class Iterator { | 354 class Iterator { | 
| 345 public: | 355 public: | 
| 346 Iterator& operator++() { | 356 Iterator& operator++() { | 
| 347 entry_ = map_->Next(entry_); | 357 entry_ = map_->Next(entry_); | 
| 348 return *this; | 358 return *this; | 
| 349 } | 359 } | 
| 350 | 360 | 
| 351 value_type* operator->() { return reinterpret_cast<value_type*>(entry_); } | 361 value_type* operator->() { return reinterpret_cast<value_type*>(entry_); } | 
| 352 bool operator!=(const Iterator& other) { return entry_ != other.entry_; } | 362 bool operator!=(const Iterator& other) { return entry_ != other.entry_; } | 
| 353 | 363 | 
| 354 private: | 364 private: | 
| 355 Iterator(const TemplateHashMapImpl<void*, void*, AllocationPolicy>* map, | 365 Iterator(const Base* map, typename Base::Entry* entry) | 
| 356 typename TemplateHashMapImpl<void*, void*, | |
| 357 AllocationPolicy>::Entry* entry) | |
| 358 : map_(map), entry_(entry) {} | 366 : map_(map), entry_(entry) {} | 
| 359 | 367 | 
| 360 const TemplateHashMapImpl<void*, void*, AllocationPolicy>* map_; | 368 const Base* map_; | 
| 361 typename TemplateHashMapImpl<void*, void*, AllocationPolicy>::Entry* entry_; | 369 typename Base::Entry* entry_; | 
| 362 | 370 | 
| 363 friend class TemplateHashMap; | 371 friend class TemplateHashMap; | 
| 364 }; | 372 }; | 
| 365 | 373 | 
| 366 TemplateHashMap(typename TemplateHashMapImpl< | 374 TemplateHashMap(MatchFun match, | 
| 367 void*, void*, AllocationPolicy>::MatchFun match, | |
| 368 AllocationPolicy allocator = AllocationPolicy()) | 375 AllocationPolicy allocator = AllocationPolicy()) | 
| 369 : TemplateHashMapImpl<void*, void*, AllocationPolicy>( | 376 : Base(match, Base::kDefaultHashMapCapacity, allocator) {} | 
| 370 match, | |
| 371 TemplateHashMapImpl<void*, void*, | |
| 372 AllocationPolicy>::kDefaultHashMapCapacity, | |
| 373 allocator) {} | |
| 374 | 377 | 
| 375 Iterator begin() const { return Iterator(this, this->Start()); } | 378 Iterator begin() const { return Iterator(this, this->Start()); } | 
| 376 Iterator end() const { return Iterator(this, nullptr); } | 379 Iterator end() const { return Iterator(this, nullptr); } | 
| 377 Iterator find(Key* key, bool insert = false) { | 380 Iterator find(Key* key, bool insert = false) { | 
| 378 if (insert) { | 381 if (insert) { | 
| 379 return Iterator(this, this->LookupOrInsert(key, key->Hash())); | 382 return Iterator(this, this->LookupOrInsert(key, key->Hash())); | 
| 380 } | 383 } | 
| 381 return Iterator(this, this->Lookup(key, key->Hash())); | 384 return Iterator(this, this->Lookup(key, key->Hash())); | 
| 382 } | 385 } | 
| 383 }; | 386 }; | 
| 384 | 387 | 
| 385 } // namespace base | 388 } // namespace base | 
| 386 } // namespace v8 | 389 } // namespace v8 | 
| 387 | 390 | 
| 388 #endif // V8_BASE_HASHMAP_H_ | 391 #endif // V8_BASE_HASHMAP_H_ | 
| OLD | NEW |