Commit 77cc96aa authored by Leszek Swirski's avatar Leszek Swirski Committed by Commit Bot

[identity-map] Cache the calculated Hash

In IdentityMap, explicitly pass the key's hash so that it can be cached
between Lookup and Insert.

Change-Id: Ib8a2d96cc399ae025f54c61c129dd4cd18d86c7e
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2448795
Auto-Submit: Leszek Swirski <leszeks@chromium.org>
Commit-Queue: Ross McIlroy <rmcilroy@chromium.org>
Reviewed-by: 's avatarRoss McIlroy <rmcilroy@chromium.org>
Cr-Commit-Position: refs/heads/master@{#70319}
parent 4d9d8518
...@@ -47,8 +47,8 @@ void IdentityMapBase::DisableIteration() { ...@@ -47,8 +47,8 @@ void IdentityMapBase::DisableIteration() {
is_iterable_ = false; is_iterable_ = false;
} }
int IdentityMapBase::ScanKeysFor(Address address) const { int IdentityMapBase::ScanKeysFor(Address address, uint32_t hash) const {
int start = Hash(address) & mask_; int start = hash & mask_;
Address not_mapped = ReadOnlyRoots(heap_).not_mapped_symbol().ptr(); Address not_mapped = ReadOnlyRoots(heap_).not_mapped_symbol().ptr();
for (int index = start; index < capacity_; index++) { for (int index = start; index < capacity_; index++) {
if (keys_[index] == address) return index; // Found. if (keys_[index] == address) return index; // Found.
...@@ -61,15 +61,17 @@ int IdentityMapBase::ScanKeysFor(Address address) const { ...@@ -61,15 +61,17 @@ int IdentityMapBase::ScanKeysFor(Address address) const {
return -1; return -1;
} }
std::pair<int, bool> IdentityMapBase::InsertKey(Address address) { std::pair<int, bool> IdentityMapBase::InsertKey(Address address,
uint32_t hash) {
DCHECK_EQ(gc_counter_, heap_->gc_count());
Address not_mapped = ReadOnlyRoots(heap_).not_mapped_symbol().ptr(); Address not_mapped = ReadOnlyRoots(heap_).not_mapped_symbol().ptr();
while (true) { while (true) {
int start = Hash(address) & mask_; int start = hash & mask_;
int limit = capacity_ / 2; int limit = capacity_ / 2;
// Search up to {limit} entries. // Search up to {limit} entries.
for (int index = start; --limit > 0; index = (index + 1) & mask_) { for (int index = start; --limit > 0; index = (index + 1) & mask_) {
if (keys_[index] == address) return {index, true}; // Found. if (keys_[index] == address) return {index, true}; // Found.
if (keys_[index] == not_mapped) { // Free entry. if (keys_[index] == not_mapped) { // Free entry.
size_++; size_++;
DCHECK_LE(size_, capacity_); DCHECK_LE(size_, capacity_);
keys_[index] = address; keys_[index] = address;
...@@ -123,23 +125,25 @@ bool IdentityMapBase::DeleteIndex(int index, uintptr_t* deleted_value) { ...@@ -123,23 +125,25 @@ bool IdentityMapBase::DeleteIndex(int index, uintptr_t* deleted_value) {
} }
int IdentityMapBase::Lookup(Address key) const { int IdentityMapBase::Lookup(Address key) const {
int index = ScanKeysFor(key); uint32_t hash = Hash(key);
int index = ScanKeysFor(key, hash);
if (index < 0 && gc_counter_ != heap_->gc_count()) { if (index < 0 && gc_counter_ != heap_->gc_count()) {
// Miss; rehash if there was a GC, then lookup again. // Miss; rehash if there was a GC, then lookup again.
const_cast<IdentityMapBase*>(this)->Rehash(); const_cast<IdentityMapBase*>(this)->Rehash();
index = ScanKeysFor(key); index = ScanKeysFor(key, hash);
} }
return index; return index;
} }
std::pair<int, bool> IdentityMapBase::LookupOrInsert(Address key) { std::pair<int, bool> IdentityMapBase::LookupOrInsert(Address key) {
uint32_t hash = Hash(key);
// Perform an optimistic lookup. // Perform an optimistic lookup.
int index = ScanKeysFor(key); int index = ScanKeysFor(key, hash);
bool already_exists; bool already_exists;
if (index < 0) { if (index < 0) {
// Miss; rehash if there was a GC, then insert. // Miss; rehash if there was a GC, then insert.
if (gc_counter_ != heap_->gc_count()) Rehash(); if (gc_counter_ != heap_->gc_count()) Rehash();
std::tie(index, already_exists) = InsertKey(key); std::tie(index, already_exists) = InsertKey(key, hash);
} else { } else {
already_exists = true; already_exists = true;
} }
...@@ -147,9 +151,9 @@ std::pair<int, bool> IdentityMapBase::LookupOrInsert(Address key) { ...@@ -147,9 +151,9 @@ std::pair<int, bool> IdentityMapBase::LookupOrInsert(Address key) {
return {index, already_exists}; return {index, already_exists};
} }
int IdentityMapBase::Hash(Address address) const { uint32_t IdentityMapBase::Hash(Address address) const {
CHECK_NE(address, ReadOnlyRoots(heap_).not_mapped_symbol().ptr()); CHECK_NE(address, ReadOnlyRoots(heap_).not_mapped_symbol().ptr());
return static_cast<int>(hasher_(address)); return static_cast<uint32_t>(hasher_(address));
} }
// Searches this map for the given key using the object's address // Searches this map for the given key using the object's address
...@@ -204,7 +208,7 @@ IdentityMapBase::RawEntry IdentityMapBase::InsertEntry(Address key) { ...@@ -204,7 +208,7 @@ IdentityMapBase::RawEntry IdentityMapBase::InsertEntry(Address key) {
int index; int index;
bool already_exists; bool already_exists;
std::tie(index, already_exists) = InsertKey(key); std::tie(index, already_exists) = InsertKey(key, Hash(key));
DCHECK(!already_exists); DCHECK(!already_exists);
return &values_[index]; return &values_[index];
} }
...@@ -276,7 +280,7 @@ void IdentityMapBase::Rehash() { ...@@ -276,7 +280,7 @@ void IdentityMapBase::Rehash() {
} }
// Reinsert all the key/value pairs that were in the wrong place. // Reinsert all the key/value pairs that were in the wrong place.
for (auto pair : reinsert) { for (auto pair : reinsert) {
int index = InsertKey(pair.first).first; int index = InsertKey(pair.first, Hash(pair.first)).first;
DCHECK_GE(index, 0); DCHECK_GE(index, 0);
values_[index] = pair.second; values_[index] = pair.second;
} }
...@@ -303,7 +307,7 @@ void IdentityMapBase::Resize(int new_capacity) { ...@@ -303,7 +307,7 @@ void IdentityMapBase::Resize(int new_capacity) {
for (int i = 0; i < old_capacity; i++) { for (int i = 0; i < old_capacity; i++) {
if (old_keys[i] == not_mapped) continue; if (old_keys[i] == not_mapped) continue;
int index = InsertKey(old_keys[i]).first; int index = InsertKey(old_keys[i], Hash(old_keys[i])).first;
DCHECK_GE(index, 0); DCHECK_GE(index, 0);
values_[index] = old_values[i]; values_[index] = old_values[i];
} }
......
...@@ -71,14 +71,14 @@ class V8_EXPORT_PRIVATE IdentityMapBase { ...@@ -71,14 +71,14 @@ class V8_EXPORT_PRIVATE IdentityMapBase {
private: private:
// Internal implementation should not be called directly by subclasses. // Internal implementation should not be called directly by subclasses.
int ScanKeysFor(Address address) const; int ScanKeysFor(Address address, uint32_t hash) const;
std::pair<int, bool> InsertKey(Address address); std::pair<int, bool> InsertKey(Address address, uint32_t hash);
int Lookup(Address key) const; int Lookup(Address key) const;
std::pair<int, bool> LookupOrInsert(Address key); std::pair<int, bool> LookupOrInsert(Address key);
bool DeleteIndex(int index, uintptr_t* deleted_value); bool DeleteIndex(int index, uintptr_t* deleted_value);
void Rehash(); void Rehash();
void Resize(int new_capacity); void Resize(int new_capacity);
int Hash(Address address) const; uint32_t Hash(Address address) const;
base::hash<uintptr_t> hasher_; base::hash<uintptr_t> hasher_;
Heap* heap_; Heap* heap_;
......
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