Commit 306f8311 authored by leszeks's avatar leszeks Committed by Commit bot

[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}
parent 270db790
...@@ -269,7 +269,7 @@ TemplateHashMapImpl<Key, Value, MatchFun, AllocationPolicy>::Probe( ...@@ -269,7 +269,7 @@ TemplateHashMapImpl<Key, Value, MatchFun, AllocationPolicy>::Probe(
DCHECK(map_ <= entry && entry < end); DCHECK(map_ <= entry && entry < end);
DCHECK(occupancy_ < capacity_); // Guarantees loop termination. 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++; entry++;
if (entry >= end) { if (entry >= end) {
entry = map_; entry = map_;
...@@ -337,11 +337,30 @@ void TemplateHashMapImpl<Key, Value, MatchFun, AllocationPolicy>::Resize( ...@@ -337,11 +337,30 @@ void TemplateHashMapImpl<Key, Value, MatchFun, AllocationPolicy>::Resize(
AllocationPolicy::Delete(map); AllocationPolicy::Delete(map);
} }
// Match function which compares hashes before executing a (potentially
// expensive) key comparison.
template <typename Key, typename MatchFun>
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<void*, void*> which takes a custom key comparison function pointer.
template <typename AllocationPolicy> template <typename AllocationPolicy>
class CustomMatcherTemplateHashMapImpl class CustomMatcherTemplateHashMapImpl
: public TemplateHashMapImpl<void*, void*, bool (*)(void*, void*), : public TemplateHashMapImpl<
void*, void*,
HashEqualityThenKeyMatcher<void*, bool (*)(void*, void*)>,
AllocationPolicy> { AllocationPolicy> {
typedef TemplateHashMapImpl<void*, void*, bool (*)(void*, void*), typedef TemplateHashMapImpl<
void*, void*, HashEqualityThenKeyMatcher<void*, bool (*)(void*, void*)>,
AllocationPolicy> AllocationPolicy>
Base; Base;
...@@ -351,24 +370,35 @@ class CustomMatcherTemplateHashMapImpl ...@@ -351,24 +370,35 @@ class CustomMatcherTemplateHashMapImpl
CustomMatcherTemplateHashMapImpl( CustomMatcherTemplateHashMapImpl(
MatchFun match, uint32_t capacity = Base::kDefaultHashMapCapacity, MatchFun match, uint32_t capacity = Base::kDefaultHashMapCapacity,
AllocationPolicy allocator = AllocationPolicy()) AllocationPolicy allocator = AllocationPolicy())
: Base(capacity, match, allocator) {} : Base(capacity, HashEqualityThenKeyMatcher<void*, MatchFun>(match),
allocator) {}
}; };
typedef CustomMatcherTemplateHashMapImpl<DefaultAllocationPolicy> typedef CustomMatcherTemplateHashMapImpl<DefaultAllocationPolicy>
CustomMatcherHashMap; CustomMatcherHashMap;
// Match function which compares keys directly by equality.
template <typename Key>
struct KeyEqualityMatcher {
bool operator()(uint32_t hash1, uint32_t hash2, const Key& key1,
const Key& key2) const {
return key1 == key2;
}
};
// Hashmap<void*, void*> which compares the key pointers directly.
template <typename AllocationPolicy> template <typename AllocationPolicy>
class PointerTemplateHashMapImpl class PointerTemplateHashMapImpl
: public TemplateHashMapImpl<void*, void*, std::equal_to<void*>, : public TemplateHashMapImpl<void*, void*, KeyEqualityMatcher<void*>,
AllocationPolicy> { AllocationPolicy> {
typedef TemplateHashMapImpl<void*, void*, std::equal_to<void*>, typedef TemplateHashMapImpl<void*, void*, KeyEqualityMatcher<void*>,
AllocationPolicy> AllocationPolicy>
Base; Base;
public: public:
PointerTemplateHashMapImpl(uint32_t capacity = Base::kDefaultHashMapCapacity, PointerTemplateHashMapImpl(uint32_t capacity = Base::kDefaultHashMapCapacity,
AllocationPolicy allocator = AllocationPolicy()) AllocationPolicy allocator = AllocationPolicy())
: Base(capacity, std::equal_to<void*>(), allocator) {} : Base(capacity, KeyEqualityMatcher<void*>(), allocator) {}
}; };
typedef PointerTemplateHashMapImpl<DefaultAllocationPolicy> HashMap; typedef PointerTemplateHashMapImpl<DefaultAllocationPolicy> HashMap;
...@@ -376,8 +406,13 @@ typedef PointerTemplateHashMapImpl<DefaultAllocationPolicy> HashMap; ...@@ -376,8 +406,13 @@ typedef PointerTemplateHashMapImpl<DefaultAllocationPolicy> HashMap;
// A hash map for pointer keys and values with an STL-like interface. // A hash map for pointer keys and values with an STL-like interface.
template <class Key, class Value, class MatchFun, class AllocationPolicy> template <class Key, class Value, class MatchFun, class AllocationPolicy>
class TemplateHashMap class TemplateHashMap
: private TemplateHashMapImpl<void*, void*, MatchFun, AllocationPolicy> { : private TemplateHashMapImpl<void*, void*,
typedef TemplateHashMapImpl<void*, void*, MatchFun, AllocationPolicy> Base; HashEqualityThenKeyMatcher<void*, MatchFun>,
AllocationPolicy> {
typedef TemplateHashMapImpl<void*, void*,
HashEqualityThenKeyMatcher<void*, MatchFun>,
AllocationPolicy>
Base;
public: public:
STATIC_ASSERT(sizeof(Key*) == sizeof(void*)); // NOLINT STATIC_ASSERT(sizeof(Key*) == sizeof(void*)); // NOLINT
...@@ -409,7 +444,8 @@ class TemplateHashMap ...@@ -409,7 +444,8 @@ class TemplateHashMap
TemplateHashMap(MatchFun match, TemplateHashMap(MatchFun match,
AllocationPolicy allocator = AllocationPolicy()) AllocationPolicy allocator = AllocationPolicy())
: Base(Base::kDefaultHashMapCapacity, match, allocator) {} : Base(Base::kDefaultHashMapCapacity,
HashEqualityThenKeyMatcher<void*, MatchFun>(match), allocator) {}
Iterator begin() const { return Iterator(this, this->Start()); } Iterator begin() const { return Iterator(this, this->Start()); }
Iterator end() const { return Iterator(this, nullptr); } Iterator end() const { return Iterator(this, nullptr); }
......
...@@ -73,7 +73,8 @@ STATIC_CONST_MEMBER_DEFINITION const size_t ...@@ -73,7 +73,8 @@ STATIC_CONST_MEMBER_DEFINITION const size_t
ConstantArrayBuilder::ConstantArrayBuilder(Zone* zone, ConstantArrayBuilder::ConstantArrayBuilder(Zone* zone,
Handle<Object> the_hole_value) Handle<Object> the_hole_value)
: constants_map_(16, std::equal_to<Address>(), ZoneAllocationPolicy(zone)), : constants_map_(16, base::KeyEqualityMatcher<Address>(),
ZoneAllocationPolicy(zone)),
smi_map_(zone), smi_map_(zone),
smi_pairs_(zone), smi_pairs_(zone),
zone_(zone), zone_(zone),
......
...@@ -107,7 +107,7 @@ class ConstantArrayBuilder final BASE_EMBEDDED { ...@@ -107,7 +107,7 @@ class ConstantArrayBuilder final BASE_EMBEDDED {
Handle<Object> the_hole_value() const { return the_hole_value_; } Handle<Object> the_hole_value() const { return the_hole_value_; }
ConstantArraySlice* idx_slice_[3]; ConstantArraySlice* idx_slice_[3];
base::TemplateHashMapImpl<Address, index_t, std::equal_to<Address>, base::TemplateHashMapImpl<Address, index_t, base::KeyEqualityMatcher<Address>,
ZoneAllocationPolicy> ZoneAllocationPolicy>
constants_map_; constants_map_;
ZoneMap<Smi*, index_t> smi_map_; ZoneMap<Smi*, index_t> smi_map_;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment