| 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 // This file is ported from src/hashmap.h | 
| 6 #define V8_HASHMAP_H_ |  | 
| 7 | 6 | 
| 8 #include "src/allocation.h" | 7 #ifndef V8_LIBSAMPLER_HASHMAP_H_ | 
|  | 8 #define V8_LIBSAMPLER_HASHMAP_H_ | 
|  | 9 | 
| 9 #include "src/base/bits.h" | 10 #include "src/base/bits.h" | 
| 10 #include "src/base/logging.h" | 11 #include "src/base/logging.h" | 
| 11 #include "src/utils.h" | 12 #include "src/libsampler/utils.h" | 
| 12 | 13 | 
| 13 namespace v8 { | 14 namespace v8 { | 
| 14 namespace internal { | 15 namespace sampler { | 
| 15 | 16 | 
| 16 template<class AllocationPolicy> | 17 class HashMapImpl { | 
| 17 class TemplateHashMapImpl { |  | 
| 18  public: | 18  public: | 
| 19   typedef bool (*MatchFun) (void* key1, void* key2); | 19   typedef bool (*MatchFun) (void* key1, void* key2); | 
| 20 | 20 | 
| 21   // The default capacity.  This is used by the call sites which want | 21   // The default capacity. | 
| 22   // to pass in a non-default AllocationPolicy but want to use the |  | 
| 23   // default value of capacity specified by the implementation. |  | 
| 24   static const uint32_t kDefaultHashMapCapacity = 8; | 22   static const uint32_t kDefaultHashMapCapacity = 8; | 
| 25 | 23 | 
| 26   // initial_capacity is the size of the initial hash map; | 24   // initial_capacity is the size of the initial hash map; | 
| 27   // it must be a power of 2 (and thus must not be 0). | 25   // it must be a power of 2 (and thus must not be 0). | 
| 28   TemplateHashMapImpl(MatchFun match, | 26   HashMapImpl(MatchFun match, | 
| 29                       uint32_t capacity = kDefaultHashMapCapacity, | 27               uint32_t capacity = kDefaultHashMapCapacity); | 
| 30                       AllocationPolicy allocator = AllocationPolicy()); |  | 
| 31 | 28 | 
| 32   ~TemplateHashMapImpl(); | 29   ~HashMapImpl(); | 
| 33 | 30 | 
| 34   // HashMap entries are (key, value, hash) triplets. | 31   // HashMap entries are (key, value, hash) triplets. | 
| 35   // Some clients may not need to use the value slot | 32   // Some clients may not need to use the value slot | 
| 36   // (e.g. implementers of sets, where the key is the value). | 33   // (e.g. implementers of sets, where the key is the value). | 
| 37   struct Entry { | 34   struct Entry { | 
| 38     void* key; | 35     void* key; | 
| 39     void* value; | 36     void* value; | 
| 40     uint32_t hash;  // The full hash value for key | 37     uint32_t hash;  // The full hash value for key | 
| 41     int order;  // If you never remove entries this is the insertion order. | 38     int order;  // If you never remove entries this is the insertion order. | 
| 42   }; | 39   }; | 
| 43 | 40 | 
| 44   // If an entry with matching key is found, returns that entry. | 41   // If an entry with matching key is found, returns that entry. | 
| 45   // Otherwise, NULL is returned. | 42   // Otherwise, NULL is returned. | 
| 46   Entry* Lookup(void* key, uint32_t hash) const; | 43   Entry* Lookup(void* key, uint32_t hash) const; | 
| 47 | 44 | 
| 48   // If an entry with matching key is found, returns that entry. | 45   // If an entry with matching key is found, returns that entry. | 
| 49   // If no matching entry is found, a new entry is inserted with | 46   // If no matching entry is found, a new entry is inserted with | 
| 50   // corresponding key, key hash, and NULL value. | 47   // corresponding key, key hash, and NULL value. | 
| 51   Entry* LookupOrInsert(void* key, uint32_t hash, | 48   Entry* LookupOrInsert(void* key, uint32_t hash); | 
| 52                         AllocationPolicy allocator = AllocationPolicy()); |  | 
| 53 | 49 | 
| 54   // Removes the entry with matching key. | 50   // Removes the entry with matching key. | 
| 55   // It returns the value of the deleted entry | 51   // It returns the value of the deleted entry | 
| 56   // or null if there is no value for such key. | 52   // or null if there is no value for such key. | 
| 57   void* Remove(void* key, uint32_t hash); | 53   void* Remove(void* key, uint32_t hash); | 
| 58 | 54 | 
| 59   // Empties the hash map (occupancy() == 0). | 55   // Empties the hash map (occupancy() == 0). | 
| 60   void Clear(); | 56   void Clear(); | 
| 61 | 57 | 
| 62   // The number of (non-empty) entries in the table. | 58   // The number of (non-empty) entries in the table. | 
| (...skipping 21 matching lines...) Expand all  Loading... | 
| 84   } | 80   } | 
| 85 | 81 | 
| 86  private: | 82  private: | 
| 87   MatchFun match_; | 83   MatchFun match_; | 
| 88   Entry* map_; | 84   Entry* map_; | 
| 89   uint32_t capacity_; | 85   uint32_t capacity_; | 
| 90   uint32_t occupancy_; | 86   uint32_t occupancy_; | 
| 91 | 87 | 
| 92   Entry* map_end() const { return map_ + capacity_; } | 88   Entry* map_end() const { return map_ + capacity_; } | 
| 93   Entry* Probe(void* key, uint32_t hash) const; | 89   Entry* Probe(void* key, uint32_t hash) const; | 
| 94   void Initialize(uint32_t capacity, AllocationPolicy allocator); | 90   void Initialize(uint32_t capacity); | 
| 95   void Resize(AllocationPolicy allocator); | 91   void Resize(); | 
| 96 }; | 92 }; | 
| 97 | 93 | 
| 98 typedef TemplateHashMapImpl<FreeStoreAllocationPolicy> HashMap; | 94 typedef HashMapImpl HashMap; | 
| 99 | 95 | 
| 100 template<class AllocationPolicy> | 96 HashMapImpl::HashMapImpl(MatchFun match, uint32_t initial_capacity) { | 
| 101 TemplateHashMapImpl<AllocationPolicy>::TemplateHashMapImpl( |  | 
| 102     MatchFun match, uint32_t initial_capacity, AllocationPolicy allocator) { |  | 
| 103   match_ = match; | 97   match_ = match; | 
| 104   Initialize(initial_capacity, allocator); | 98   Initialize(initial_capacity); | 
| 105 } | 99 } | 
| 106 | 100 | 
| 107 | 101 | 
| 108 template<class AllocationPolicy> | 102 HashMapImpl::~HashMapImpl() { | 
| 109 TemplateHashMapImpl<AllocationPolicy>::~TemplateHashMapImpl() { | 103   Malloced::Delete(map_); | 
| 110   AllocationPolicy::Delete(map_); |  | 
| 111 } | 104 } | 
| 112 | 105 | 
| 113 | 106 | 
| 114 template <class AllocationPolicy> | 107 HashMapImpl::Entry* HashMapImpl::Lookup(void* key, uint32_t hash) const { | 
| 115 typename TemplateHashMapImpl<AllocationPolicy>::Entry* |  | 
| 116 TemplateHashMapImpl<AllocationPolicy>::Lookup(void* key, uint32_t hash) const { |  | 
| 117   Entry* p = Probe(key, hash); | 108   Entry* p = Probe(key, hash); | 
| 118   return p->key != NULL ? p : NULL; | 109   return p->key != NULL ? p : NULL; | 
| 119 } | 110 } | 
| 120 | 111 | 
| 121 | 112 | 
| 122 template <class AllocationPolicy> | 113 HashMapImpl::Entry* HashMapImpl::LookupOrInsert(void* key, uint32_t hash) { | 
| 123 typename TemplateHashMapImpl<AllocationPolicy>::Entry* |  | 
| 124 TemplateHashMapImpl<AllocationPolicy>::LookupOrInsert( |  | 
| 125     void* key, uint32_t hash, AllocationPolicy allocator) { |  | 
| 126   // Find a matching entry. | 114   // Find a matching entry. | 
| 127   Entry* p = Probe(key, hash); | 115   Entry* p = Probe(key, hash); | 
| 128   if (p->key != NULL) { | 116   if (p->key != NULL) { | 
| 129     return p; | 117     return p; | 
| 130   } | 118   } | 
| 131 | 119 | 
| 132   // No entry found; insert one. | 120   // No entry found; insert one. | 
| 133   p->key = key; | 121   p->key = key; | 
| 134   p->value = NULL; | 122   p->value = NULL; | 
| 135   p->hash = hash; | 123   p->hash = hash; | 
| 136   p->order = occupancy_; | 124   p->order = occupancy_; | 
| 137   occupancy_++; | 125   occupancy_++; | 
| 138 | 126 | 
| 139   // Grow the map if we reached >= 80% occupancy. | 127   // Grow the map if we reached >= 80% occupancy. | 
| 140   if (occupancy_ + occupancy_ / 4 >= capacity_) { | 128   if (occupancy_ + occupancy_ / 4 >= capacity_) { | 
| 141     Resize(allocator); | 129     Resize(); | 
| 142     p = Probe(key, hash); | 130     p = Probe(key, hash); | 
| 143   } | 131   } | 
| 144 | 132 | 
| 145   return p; | 133   return p; | 
| 146 } | 134 } | 
| 147 | 135 | 
| 148 | 136 | 
| 149 template<class AllocationPolicy> | 137 void* HashMapImpl::Remove(void* key, uint32_t hash) { | 
| 150 void* TemplateHashMapImpl<AllocationPolicy>::Remove(void* key, uint32_t hash) { |  | 
| 151   // Lookup the entry for the key to remove. | 138   // Lookup the entry for the key to remove. | 
| 152   Entry* p = Probe(key, hash); | 139   Entry* p = Probe(key, hash); | 
| 153   if (p->key == NULL) { | 140   if (p->key == NULL) { | 
| 154     // Key not found nothing to remove. | 141     // Key not found nothing to remove. | 
| 155     return NULL; | 142     return NULL; | 
| 156   } | 143   } | 
| 157 | 144 | 
| 158   void* value = p->value; | 145   void* value = p->value; | 
| 159   // To remove an entry we need to ensure that it does not create an empty | 146   // To remove an entry we need to ensure that it does not create an empty | 
| 160   // entry that will cause the search for another entry to stop too soon. If all | 147   // entry that will cause the search for another entry to stop too soon. If all | 
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 201     } | 188     } | 
| 202   } | 189   } | 
| 203 | 190 | 
| 204   // Clear the entry which is allowed to en emptied. | 191   // Clear the entry which is allowed to en emptied. | 
| 205   p->key = NULL; | 192   p->key = NULL; | 
| 206   occupancy_--; | 193   occupancy_--; | 
| 207   return value; | 194   return value; | 
| 208 } | 195 } | 
| 209 | 196 | 
| 210 | 197 | 
| 211 template<class AllocationPolicy> | 198 void HashMapImpl::Clear() { | 
| 212 void TemplateHashMapImpl<AllocationPolicy>::Clear() { |  | 
| 213   // Mark all entries as empty. | 199   // Mark all entries as empty. | 
| 214   const Entry* end = map_end(); | 200   const Entry* end = map_end(); | 
| 215   for (Entry* p = map_; p < end; p++) { | 201   for (Entry* p = map_; p < end; p++) { | 
| 216     p->key = NULL; | 202     p->key = NULL; | 
| 217   } | 203   } | 
| 218   occupancy_ = 0; | 204   occupancy_ = 0; | 
| 219 } | 205 } | 
| 220 | 206 | 
| 221 | 207 | 
| 222 template<class AllocationPolicy> | 208 HashMapImpl::Entry* HashMapImpl::Start() const { | 
| 223 typename TemplateHashMapImpl<AllocationPolicy>::Entry* |  | 
| 224     TemplateHashMapImpl<AllocationPolicy>::Start() const { |  | 
| 225   return Next(map_ - 1); | 209   return Next(map_ - 1); | 
| 226 } | 210 } | 
| 227 | 211 | 
| 228 | 212 | 
| 229 template<class AllocationPolicy> | 213 HashMapImpl::Entry* HashMapImpl::Next(Entry* p) const { | 
| 230 typename TemplateHashMapImpl<AllocationPolicy>::Entry* |  | 
| 231     TemplateHashMapImpl<AllocationPolicy>::Next(Entry* p) const { |  | 
| 232   const Entry* end = map_end(); | 214   const Entry* end = map_end(); | 
| 233   DCHECK(map_ - 1 <= p && p < end); | 215   DCHECK(map_ - 1 <= p && p < end); | 
| 234   for (p++; p < end; p++) { | 216   for (p++; p < end; p++) { | 
| 235     if (p->key != NULL) { | 217     if (p->key != NULL) { | 
| 236       return p; | 218       return p; | 
| 237     } | 219     } | 
| 238   } | 220   } | 
| 239   return NULL; | 221   return NULL; | 
| 240 } | 222 } | 
| 241 | 223 | 
| 242 | 224 | 
| 243 template <class AllocationPolicy> | 225 HashMapImpl::Entry* HashMapImpl::Probe(void* key, uint32_t hash) const { | 
| 244 typename TemplateHashMapImpl<AllocationPolicy>::Entry* |  | 
| 245 TemplateHashMapImpl<AllocationPolicy>::Probe(void* key, uint32_t hash) const { |  | 
| 246   DCHECK(key != NULL); | 226   DCHECK(key != NULL); | 
| 247 | 227 | 
| 248   DCHECK(base::bits::IsPowerOfTwo32(capacity_)); | 228   DCHECK(base::bits::IsPowerOfTwo32(capacity_)); | 
| 249   Entry* p = map_ + (hash & (capacity_ - 1)); | 229   Entry* p = map_ + (hash & (capacity_ - 1)); | 
| 250   const Entry* end = map_end(); | 230   const Entry* end = map_end(); | 
| 251   DCHECK(map_ <= p && p < end); | 231   DCHECK(map_ <= p && p < end); | 
| 252 | 232 | 
| 253   DCHECK(occupancy_ < capacity_);  // Guarantees loop termination. | 233   DCHECK(occupancy_ < capacity_);  // Guarantees loop termination. | 
| 254   while (p->key != NULL && (hash != p->hash || !match_(key, p->key))) { | 234   while (p->key != NULL && (hash != p->hash || !match_(key, p->key))) { | 
| 255     p++; | 235     p++; | 
| 256     if (p >= end) { | 236     if (p >= end) { | 
| 257       p = map_; | 237       p = map_; | 
| 258     } | 238     } | 
| 259   } | 239   } | 
| 260 | 240 | 
| 261   return p; | 241   return p; | 
| 262 } | 242 } | 
| 263 | 243 | 
| 264 | 244 | 
| 265 template<class AllocationPolicy> | 245 void HashMapImpl::Initialize(uint32_t capacity) { | 
| 266 void TemplateHashMapImpl<AllocationPolicy>::Initialize( |  | 
| 267     uint32_t capacity, AllocationPolicy allocator) { |  | 
| 268   DCHECK(base::bits::IsPowerOfTwo32(capacity)); | 246   DCHECK(base::bits::IsPowerOfTwo32(capacity)); | 
| 269   map_ = reinterpret_cast<Entry*>(allocator.New(capacity * sizeof(Entry))); | 247   map_ = reinterpret_cast<Entry*>(Malloced::New(capacity * sizeof(Entry))); | 
| 270   if (map_ == NULL) { | 248   CHECK(map_ != NULL); | 
| 271     v8::internal::FatalProcessOutOfMemory("HashMap::Initialize"); |  | 
| 272     return; |  | 
| 273   } |  | 
| 274   capacity_ = capacity; | 249   capacity_ = capacity; | 
| 275   Clear(); | 250   Clear(); | 
| 276 } | 251 } | 
| 277 | 252 | 
| 278 | 253 | 
| 279 template<class AllocationPolicy> | 254 void HashMapImpl::Resize() { | 
| 280 void TemplateHashMapImpl<AllocationPolicy>::Resize(AllocationPolicy allocator) { |  | 
| 281   Entry* map = map_; | 255   Entry* map = map_; | 
| 282   uint32_t n = occupancy_; | 256   uint32_t n = occupancy_; | 
| 283 | 257 | 
| 284   // Allocate larger map. | 258   // Allocate larger map. | 
| 285   Initialize(capacity_ * 2, allocator); | 259   Initialize(capacity_ * 2); | 
| 286 | 260 | 
| 287   // Rehash all current entries. | 261   // Rehash all current entries. | 
| 288   for (Entry* p = map; n > 0; p++) { | 262   for (Entry* p = map; n > 0; p++) { | 
| 289     if (p->key != NULL) { | 263     if (p->key != NULL) { | 
| 290       Entry* entry = LookupOrInsert(p->key, p->hash, allocator); | 264       Entry* entry = LookupOrInsert(p->key, p->hash); | 
| 291       entry->value = p->value; | 265       entry->value = p->value; | 
| 292       entry->order = p->order; | 266       entry->order = p->order; | 
| 293       n--; | 267       n--; | 
| 294     } | 268     } | 
| 295   } | 269   } | 
| 296 | 270 | 
| 297   // Delete old map. | 271   // Delete old map. | 
| 298   AllocationPolicy::Delete(map); | 272   Malloced::Delete(map); | 
| 299 } | 273 } | 
| 300 | 274 | 
| 301 | 275 }  // namespace sampler | 
| 302 // A hash map for pointer keys and values with an STL-like interface. |  | 
| 303 template<class Key, class Value, class AllocationPolicy> |  | 
| 304 class TemplateHashMap: private TemplateHashMapImpl<AllocationPolicy> { |  | 
| 305  public: |  | 
| 306   STATIC_ASSERT(sizeof(Key*) == sizeof(void*));  // NOLINT |  | 
| 307   STATIC_ASSERT(sizeof(Value*) == sizeof(void*));  // NOLINT |  | 
| 308   struct value_type { |  | 
| 309     Key* first; |  | 
| 310     Value* second; |  | 
| 311   }; |  | 
| 312 |  | 
| 313   class Iterator { |  | 
| 314    public: |  | 
| 315     Iterator& operator++() { |  | 
| 316       entry_ = map_->Next(entry_); |  | 
| 317       return *this; |  | 
| 318     } |  | 
| 319 |  | 
| 320     value_type* operator->() { return reinterpret_cast<value_type*>(entry_); } |  | 
| 321     bool operator!=(const Iterator& other) { return  entry_ != other.entry_; } |  | 
| 322 |  | 
| 323    private: |  | 
| 324     Iterator(const TemplateHashMapImpl<AllocationPolicy>* map, |  | 
| 325              typename TemplateHashMapImpl<AllocationPolicy>::Entry* entry) : |  | 
| 326         map_(map), entry_(entry) { } |  | 
| 327 |  | 
| 328     const TemplateHashMapImpl<AllocationPolicy>* map_; |  | 
| 329     typename TemplateHashMapImpl<AllocationPolicy>::Entry* entry_; |  | 
| 330 |  | 
| 331     friend class TemplateHashMap; |  | 
| 332   }; |  | 
| 333 |  | 
| 334   TemplateHashMap( |  | 
| 335       typename TemplateHashMapImpl<AllocationPolicy>::MatchFun match, |  | 
| 336       AllocationPolicy allocator = AllocationPolicy()) |  | 
| 337         : TemplateHashMapImpl<AllocationPolicy>( |  | 
| 338             match, |  | 
| 339             TemplateHashMapImpl<AllocationPolicy>::kDefaultHashMapCapacity, |  | 
| 340             allocator) { } |  | 
| 341 |  | 
| 342   Iterator begin() const { return Iterator(this, this->Start()); } |  | 
| 343   Iterator end() const { return Iterator(this, NULL); } |  | 
| 344   Iterator find(Key* key, bool insert = false, |  | 
| 345                 AllocationPolicy allocator = AllocationPolicy()) { |  | 
| 346     if (insert) { |  | 
| 347       return Iterator(this, this->LookupOrInsert(key, key->Hash(), allocator)); |  | 
| 348     } |  | 
| 349     return Iterator(this, this->Lookup(key, key->Hash())); |  | 
| 350   } |  | 
| 351 }; |  | 
| 352 |  | 
| 353 }  // namespace internal |  | 
| 354 }  // namespace v8 | 276 }  // namespace v8 | 
| 355 | 277 | 
| 356 #endif  // V8_HASHMAP_H_ | 278 #endif  // V8_LIBSAMPLER_HASHMAP_H_ | 
| OLD | NEW | 
|---|