Chromium Code Reviews| Index: src/base/hashmap.h |
| diff --git a/src/base/hashmap.h b/src/base/hashmap.h |
| index bca35d41b1167678e5b9b025ffc2ddf912a22aad..2dcf8429261711d53c2a0d5e59271f00a2df710c 100644 |
| --- a/src/base/hashmap.h |
| +++ b/src/base/hashmap.h |
| @@ -55,11 +55,9 @@ class TemplateHashMapImpl { |
| // If an entry with matching key is found, returns that entry. |
| // If no matching entry is found, a new entry is inserted with |
| // corresponding key, key hash, and default initialized value. |
| - Entry* LookupOrInsert(const Key& key, uint32_t hash, |
| - AllocationPolicy allocator = AllocationPolicy()); |
| + Entry* LookupOrInsert(const Key& key, uint32_t hash); |
| - Entry* InsertNew(const Key& key, uint32_t hash, |
| - AllocationPolicy allocator = AllocationPolicy()); |
| + Entry* InsertNew(const Key& key, uint32_t hash); |
| // Removes the entry with matching key. |
| // It returns the value of the deleted entry |
| @@ -95,15 +93,25 @@ class TemplateHashMapImpl { |
| } |
| private: |
| + // Helper which holds the entry array as well as the allocation policy. |
| + // AllocationPolicy is a base class rather than a field to take advantage of |
| + // the empty base optimisation for state-free allocators, such as the |
| + // DefaultAllocationPolicy above. |
|
rmcilroy
2016/09/19 10:55:11
Let's make this a field instead of using the empty
Leszek Swirski
2016/09/19 12:20:56
Fair enough, done.
|
| + struct AllocatedEntryHolder : public AllocationPolicy { |
| + Entry* values; |
| + explicit AllocatedEntryHolder(AllocationPolicy allocator) |
| + : AllocationPolicy(allocator) {} |
| + }; |
| + |
| MatchFun match_; |
| - Entry* map_; |
| + AllocatedEntryHolder map_; |
| uint32_t capacity_; |
| uint32_t occupancy_; |
| - Entry* map_end() const { return map_ + capacity_; } |
| + Entry* map_end() const { return map_.values + capacity_; } |
| Entry* Probe(const Key& key, uint32_t hash) const; |
| - void Initialize(uint32_t capacity, AllocationPolicy allocator); |
| - void Resize(AllocationPolicy allocator); |
| + void Initialize(uint32_t capacity); |
| + void Resize(); |
| }; |
| template <typename Key> |
| @@ -122,14 +130,15 @@ typedef TemplateHashMapImpl<void*, void*, DefaultAllocationPolicy> HashMap; |
| template <typename Key, typename Value, class AllocationPolicy> |
| TemplateHashMapImpl<Key, Value, AllocationPolicy>::TemplateHashMapImpl( |
| - MatchFun match, uint32_t initial_capacity, AllocationPolicy allocator) { |
| + MatchFun match, uint32_t initial_capacity, AllocationPolicy allocator) |
| + : map_(allocator) { |
| match_ = match; |
| - Initialize(initial_capacity, allocator); |
| + Initialize(initial_capacity); |
| } |
| template <typename Key, typename Value, class AllocationPolicy> |
| TemplateHashMapImpl<Key, Value, AllocationPolicy>::~TemplateHashMapImpl() { |
| - AllocationPolicy::Delete(map_); |
| + map_.AllocationPolicy::Delete(map_.values); |
| } |
| template <typename Key, typename Value, class AllocationPolicy> |
| @@ -143,20 +152,20 @@ TemplateHashMapImpl<Key, Value, AllocationPolicy>::Lookup(const Key& key, |
| template <typename Key, typename Value, class AllocationPolicy> |
| typename TemplateHashMapImpl<Key, Value, AllocationPolicy>::Entry* |
| TemplateHashMapImpl<Key, Value, AllocationPolicy>::LookupOrInsert( |
| - const Key& key, uint32_t hash, AllocationPolicy allocator) { |
| + const Key& key, uint32_t hash) { |
| // Find a matching entry. |
| Entry* p = Probe(key, hash); |
| if (p->exists()) { |
| return p; |
| } |
| - return InsertNew(key, hash, allocator); |
| + return InsertNew(key, hash); |
| } |
| template <typename Key, typename Value, class AllocationPolicy> |
| typename TemplateHashMapImpl<Key, Value, AllocationPolicy>::Entry* |
| -TemplateHashMapImpl<Key, Value, AllocationPolicy>::InsertNew( |
| - const Key& key, uint32_t hash, AllocationPolicy allocator) { |
| +TemplateHashMapImpl<Key, Value, AllocationPolicy>::InsertNew(const Key& key, |
| + uint32_t hash) { |
| // Find a matching entry. |
| Entry* p = Probe(key, hash); |
| DCHECK(!p->exists()); |
| @@ -167,7 +176,7 @@ TemplateHashMapImpl<Key, Value, AllocationPolicy>::InsertNew( |
| // Grow the map if we reached >= 80% occupancy. |
| if (occupancy_ + occupancy_ / 4 >= capacity_) { |
| - Resize(allocator); |
| + Resize(); |
| p = Probe(key, hash); |
| } |
| @@ -207,7 +216,7 @@ Value TemplateHashMapImpl<Key, Value, AllocationPolicy>::Remove(const Key& key, |
| // Move q to the next entry. |
| q = q + 1; |
| if (q == map_end()) { |
| - q = map_; |
| + q = map_.values; |
| } |
| // All entries between p and q have their initial position between p and q |
| @@ -218,7 +227,7 @@ Value TemplateHashMapImpl<Key, Value, AllocationPolicy>::Remove(const Key& key, |
| } |
| // Find the initial position for the entry at position q. |
| - Entry* r = map_ + (q->hash & (capacity_ - 1)); |
| + Entry* r = map_.values + (q->hash & (capacity_ - 1)); |
| // If the entry at position q has its initial position outside the range |
| // between p and q it can be moved forward to position p and will still be |
| @@ -239,7 +248,7 @@ template <typename Key, typename Value, class AllocationPolicy> |
| void TemplateHashMapImpl<Key, Value, AllocationPolicy>::Clear() { |
| // Mark all entries as empty. |
| const Entry* end = map_end(); |
| - for (Entry* p = map_; p < end; p++) { |
| + for (Entry* p = map_.values; p < end; p++) { |
| p->clear(); |
| } |
| occupancy_ = 0; |
| @@ -248,14 +257,14 @@ void TemplateHashMapImpl<Key, Value, AllocationPolicy>::Clear() { |
| template <typename Key, typename Value, class AllocationPolicy> |
| typename TemplateHashMapImpl<Key, Value, AllocationPolicy>::Entry* |
| TemplateHashMapImpl<Key, Value, AllocationPolicy>::Start() const { |
| - return Next(map_ - 1); |
| + return Next(map_.values - 1); |
| } |
| template <typename Key, typename Value, class AllocationPolicy> |
| typename TemplateHashMapImpl<Key, Value, AllocationPolicy>::Entry* |
| TemplateHashMapImpl<Key, Value, AllocationPolicy>::Next(Entry* p) const { |
| const Entry* end = map_end(); |
| - DCHECK(map_ - 1 <= p && p < end); |
| + DCHECK(map_.values - 1 <= p && p < end); |
| for (p++; p < end; p++) { |
| if (p->exists()) { |
| return p; |
| @@ -269,15 +278,15 @@ typename TemplateHashMapImpl<Key, Value, AllocationPolicy>::Entry* |
| TemplateHashMapImpl<Key, Value, AllocationPolicy>::Probe(const Key& key, |
| uint32_t hash) const { |
| DCHECK(base::bits::IsPowerOfTwo32(capacity_)); |
| - Entry* p = map_ + (hash & (capacity_ - 1)); |
| + Entry* p = map_.values + (hash & (capacity_ - 1)); |
| const Entry* end = map_end(); |
| - DCHECK(map_ <= p && p < end); |
| + DCHECK(map_.values <= p && p < end); |
| DCHECK(occupancy_ < capacity_); // Guarantees loop termination. |
| while (p->exists() && (hash != p->hash || !match_(key, p->key))) { |
| p++; |
| if (p >= end) { |
| - p = map_; |
| + p = map_.values; |
| } |
| } |
| @@ -286,10 +295,11 @@ TemplateHashMapImpl<Key, Value, AllocationPolicy>::Probe(const Key& key, |
| template <typename Key, typename Value, class AllocationPolicy> |
| void TemplateHashMapImpl<Key, Value, AllocationPolicy>::Initialize( |
| - uint32_t capacity, AllocationPolicy allocator) { |
| + uint32_t capacity) { |
| DCHECK(base::bits::IsPowerOfTwo32(capacity)); |
| - map_ = reinterpret_cast<Entry*>(allocator.New(capacity * sizeof(Entry))); |
| - if (map_ == nullptr) { |
| + map_.values = reinterpret_cast<Entry*>( |
| + map_.AllocationPolicy::New(capacity * sizeof(Entry))); |
| + if (map_.values == nullptr) { |
| FATAL("Out of memory: HashMap::Initialize"); |
| return; |
| } |
| @@ -298,18 +308,17 @@ void TemplateHashMapImpl<Key, Value, AllocationPolicy>::Initialize( |
| } |
| template <typename Key, typename Value, class AllocationPolicy> |
| -void TemplateHashMapImpl<Key, Value, AllocationPolicy>::Resize( |
| - AllocationPolicy allocator) { |
| - Entry* map = map_; |
| +void TemplateHashMapImpl<Key, Value, AllocationPolicy>::Resize() { |
| + Entry* map = map_.values; |
| uint32_t n = occupancy_; |
| // Allocate larger map. |
| - Initialize(capacity_ * 2, allocator); |
| + Initialize(capacity_ * 2); |
| // Rehash all current entries. |
| for (Entry* p = map; n > 0; p++) { |
| if (p->exists()) { |
| - Entry* entry = LookupOrInsert(p->key, p->hash, allocator); |
| + Entry* entry = LookupOrInsert(p->key, p->hash); |
| entry->value = p->value; |
| n--; |
| } |
| @@ -364,10 +373,9 @@ class TemplateHashMap |
| Iterator begin() const { return Iterator(this, this->Start()); } |
| Iterator end() const { return Iterator(this, nullptr); } |
| - Iterator find(Key* key, bool insert = false, |
| - AllocationPolicy allocator = AllocationPolicy()) { |
| + Iterator find(Key* key, bool insert = false) { |
| if (insert) { |
| - return Iterator(this, this->LookupOrInsert(key, key->Hash(), allocator)); |
| + return Iterator(this, this->LookupOrInsert(key, key->Hash())); |
| } |
| return Iterator(this, this->Lookup(key, key->Hash())); |
| } |