diff --git a/common/raw_hashtable.h b/common/raw_hashtable.h index 8200117b2578b..9613f303c2b9f 100644 --- a/common/raw_hashtable.h +++ b/common/raw_hashtable.h @@ -570,16 +570,13 @@ class BaseImpl { auto CopySlotsFrom(const BaseImpl& arg) -> void; auto MoveFrom(BaseImpl&& arg, Storage* small_storage) -> void; - template - auto InsertIntoEmpty(LookupKeyT lookup_key, KeyContextT key_context) - -> EntryT*; + auto InsertIntoEmpty(HashCode hash) -> EntryT*; static auto ComputeNextAllocSize(ssize_t old_alloc_size) -> ssize_t; static auto GrowthThresholdForAllocSize(ssize_t alloc_size) -> ssize_t; auto GrowToNextAllocSize(KeyContextT key_context) -> void; - template - auto GrowAndInsert(LookupKeyT lookup_key, KeyContextT key_context) -> EntryT*; + auto GrowAndInsert(HashCode hash, KeyContextT key_context) -> EntryT*; ViewImplT view_impl_; int growth_budget_; @@ -974,7 +971,7 @@ auto BaseImpl::InsertImpl( // empty slot. Without the growth budget we'll have to completely rehash and // so we can just bail here. if (LLVM_UNLIKELY(growth_budget_ == 0)) { - return {GrowAndInsert(lookup_key, key_context), true}; + return {GrowAndInsert(hash, key_context), true}; } --growth_budget_; @@ -1029,8 +1026,9 @@ BaseImpl::GrowToAllocSizeImpl( for (ssize_t byte_index : present_matched_range) { ++count; ssize_t index = group_index + byte_index; - EntryT* new_entry = - InsertIntoEmpty(old_entries[index].key(), key_context); + HashCode hash = + key_context.HashKey(old_entries[index].key(), ComputeSeed()); + EntryT* new_entry = InsertIntoEmpty(hash); new_entry->MoveFrom(std::move(old_entries[index])); } } @@ -1291,11 +1289,8 @@ auto BaseImpl::MoveFrom( // these are true, typically just after growth, we can dramatically simplify the // insert position search. template -template -[[clang::noinline]] auto -BaseImpl::InsertIntoEmpty( - LookupKeyT lookup_key, KeyContextT key_context) -> EntryT* { - HashCode hash = key_context.HashKey(lookup_key, ComputeSeed()); +auto BaseImpl::InsertIntoEmpty( + HashCode hash) -> EntryT* { auto [hash_index, tag] = hash.ExtractIndexAndTag<7>(); uint8_t* local_metadata = metadata(); EntryT* local_entries = entries(); @@ -1375,7 +1370,7 @@ auto BaseImpl::GrowToNextAllocSize( // the group walk rather than after the group walk. In practice, between the // statistical rareness and using a large small size buffer here on the stack, // we can handle this most efficiently with temporary, additional storage. - llvm::SmallVector probed_indices; + llvm::SmallVector, 128> probed_indices; // Create locals for the old state of the table. ssize_t old_size = alloc_size(); @@ -1449,7 +1444,7 @@ auto BaseImpl::GrowToNextAllocSize( ssize_t old_hash_index = hash.ExtractIndexAndTag<7>().first & ComputeProbeMaskFromSize(old_size); if (LLVM_UNLIKELY(old_hash_index != group_index)) { - probed_indices.push_back(old_index); + probed_indices.push_back({old_index, hash}); if constexpr (MetadataGroup::FastByteClear) { low_g.ClearByte(byte_index); high_g.ClearByte(byte_index); @@ -1510,9 +1505,8 @@ auto BaseImpl::GrowToNextAllocSize( // We then need to do a normal insertion for anything that was probed before // growth, but we know we'll find an empty slot, so leverage that. - for (ssize_t old_index : probed_indices) { - EntryT* new_entry = - InsertIntoEmpty(old_entries[old_index].key(), key_context); + for (auto [old_index, hash] : probed_indices) { + EntryT* new_entry = InsertIntoEmpty(hash); new_entry->MoveFrom(std::move(old_entries[old_index])); } CARBON_DCHECK(count == @@ -1538,16 +1532,15 @@ auto BaseImpl::GrowToNextAllocSize( // that this function can be directly called and the result returned from // `InsertImpl`. template -template [[clang::noinline]] auto BaseImpl::GrowAndInsert( - LookupKeyT lookup_key, KeyContextT key_context) -> EntryT* { + HashCode hash, KeyContextT key_context) -> EntryT* { GrowToNextAllocSize(key_context); // And insert the lookup_key into an index in the newly grown map and return // that index for use. --growth_budget_; - return InsertIntoEmpty(lookup_key, key_context); + return InsertIntoEmpty(hash); } template