From 306f83119b404eecaf28697e81fa8360a5237e5f Mon Sep 17 00:00:00 2001 From: leszeks Date: Mon, 3 Oct 2016 08:07:13 -0700 Subject: [PATCH] [base] Optimise hashmaps with simple key equality Hashmaps with a simple key equality method (comparing pointers) don't need to waste cycles (and branches) comparing hash values, as the key comparison is cheap. This patch modifies the hashmap's MatchFun to take the hashes as well as the keys, thus allowing the MatchFun to ignore the hashes. This allows slightly cleaner generated code, especially when the MatchFun is inlined. BUG= Review-Url: https://codereview.chromium.org/2381303002 Cr-Commit-Position: refs/heads/master@{#39932} --- src/base/hashmap.h | 60 ++++++++++++++++++----- src/interpreter/constant-array-builder.cc | 3 +- src/interpreter/constant-array-builder.h | 2 +- 3 files changed, 51 insertions(+), 14 deletions(-) diff --git a/src/base/hashmap.h b/src/base/hashmap.h index d8151861cb..54038c5ef3 100644 --- a/src/base/hashmap.h +++ b/src/base/hashmap.h @@ -269,7 +269,7 @@ TemplateHashMapImpl::Probe( DCHECK(map_ <= entry && entry < end); DCHECK(occupancy_ < capacity_); // Guarantees loop termination. - while (entry->exists() && (hash != entry->hash || !match_(key, entry->key))) { + while (entry->exists() && !match_(hash, entry->hash, key, entry->key)) { entry++; if (entry >= end) { entry = map_; @@ -337,12 +337,31 @@ void TemplateHashMapImpl::Resize( AllocationPolicy::Delete(map); } +// Match function which compares hashes before executing a (potentially +// expensive) key comparison. +template +struct HashEqualityThenKeyMatcher { + explicit HashEqualityThenKeyMatcher(MatchFun match) : match_(match) {} + + bool operator()(uint32_t hash1, uint32_t hash2, const Key& key1, + const Key& key2) const { + return hash1 == hash2 && match_(key1, key2); + } + + private: + MatchFun match_; +}; + +// Hashmap which takes a custom key comparison function pointer. template class CustomMatcherTemplateHashMapImpl - : public TemplateHashMapImpl { - typedef TemplateHashMapImpl + : public TemplateHashMapImpl< + void*, void*, + HashEqualityThenKeyMatcher, + AllocationPolicy> { + typedef TemplateHashMapImpl< + void*, void*, HashEqualityThenKeyMatcher, + AllocationPolicy> Base; public: @@ -351,24 +370,35 @@ class CustomMatcherTemplateHashMapImpl CustomMatcherTemplateHashMapImpl( MatchFun match, uint32_t capacity = Base::kDefaultHashMapCapacity, AllocationPolicy allocator = AllocationPolicy()) - : Base(capacity, match, allocator) {} + : Base(capacity, HashEqualityThenKeyMatcher(match), + allocator) {} }; typedef CustomMatcherTemplateHashMapImpl CustomMatcherHashMap; +// Match function which compares keys directly by equality. +template +struct KeyEqualityMatcher { + bool operator()(uint32_t hash1, uint32_t hash2, const Key& key1, + const Key& key2) const { + return key1 == key2; + } +}; + +// Hashmap which compares the key pointers directly. template class PointerTemplateHashMapImpl - : public TemplateHashMapImpl, + : public TemplateHashMapImpl, AllocationPolicy> { - typedef TemplateHashMapImpl, + typedef TemplateHashMapImpl, AllocationPolicy> Base; public: PointerTemplateHashMapImpl(uint32_t capacity = Base::kDefaultHashMapCapacity, AllocationPolicy allocator = AllocationPolicy()) - : Base(capacity, std::equal_to(), allocator) {} + : Base(capacity, KeyEqualityMatcher(), allocator) {} }; typedef PointerTemplateHashMapImpl HashMap; @@ -376,8 +406,13 @@ typedef PointerTemplateHashMapImpl HashMap; // A hash map for pointer keys and values with an STL-like interface. template class TemplateHashMap - : private TemplateHashMapImpl { - typedef TemplateHashMapImpl Base; + : private TemplateHashMapImpl, + AllocationPolicy> { + typedef TemplateHashMapImpl, + AllocationPolicy> + Base; public: STATIC_ASSERT(sizeof(Key*) == sizeof(void*)); // NOLINT @@ -409,7 +444,8 @@ class TemplateHashMap TemplateHashMap(MatchFun match, AllocationPolicy allocator = AllocationPolicy()) - : Base(Base::kDefaultHashMapCapacity, match, allocator) {} + : Base(Base::kDefaultHashMapCapacity, + HashEqualityThenKeyMatcher(match), allocator) {} Iterator begin() const { return Iterator(this, this->Start()); } Iterator end() const { return Iterator(this, nullptr); } diff --git a/src/interpreter/constant-array-builder.cc b/src/interpreter/constant-array-builder.cc index 145d2d228c..d2b7995623 100644 --- a/src/interpreter/constant-array-builder.cc +++ b/src/interpreter/constant-array-builder.cc @@ -73,7 +73,8 @@ STATIC_CONST_MEMBER_DEFINITION const size_t ConstantArrayBuilder::ConstantArrayBuilder(Zone* zone, Handle the_hole_value) - : constants_map_(16, std::equal_to
(), ZoneAllocationPolicy(zone)), + : constants_map_(16, base::KeyEqualityMatcher
(), + ZoneAllocationPolicy(zone)), smi_map_(zone), smi_pairs_(zone), zone_(zone), diff --git a/src/interpreter/constant-array-builder.h b/src/interpreter/constant-array-builder.h index f0c4eae64d..78d36f5044 100644 --- a/src/interpreter/constant-array-builder.h +++ b/src/interpreter/constant-array-builder.h @@ -107,7 +107,7 @@ class ConstantArrayBuilder final BASE_EMBEDDED { Handle the_hole_value() const { return the_hole_value_; } ConstantArraySlice* idx_slice_[3]; - base::TemplateHashMapImpl, + base::TemplateHashMapImpl, ZoneAllocationPolicy> constants_map_; ZoneMap smi_map_;