diff options
Diffstat (limited to 'chromium/third_party/blink/renderer/platform/wtf/hash_table.h')
-rw-r--r-- | chromium/third_party/blink/renderer/platform/wtf/hash_table.h | 55 |
1 files changed, 48 insertions, 7 deletions
diff --git a/chromium/third_party/blink/renderer/platform/wtf/hash_table.h b/chromium/third_party/blink/renderer/platform/wtf/hash_table.h index 9289763b271..46568c25b84 100644 --- a/chromium/third_party/blink/renderer/platform/wtf/hash_table.h +++ b/chromium/third_party/blink/renderer/platform/wtf/hash_table.h @@ -922,6 +922,7 @@ class HashTable final ValueType* Reinsert(ValueType&&); static void InitializeBucket(ValueType& bucket); + static void ReinitializeBucket(ValueType& bucket); static void DeleteBucket(const ValueType& bucket) { bucket.~ValueType(); Traits::ConstructDeletedValue(const_cast<ValueType&>(bucket), @@ -1283,6 +1284,15 @@ struct HashTableBucketInitializer<false> { ConstructTraits<Value, Traits, Allocator>::ConstructAndNotifyElement( &bucket, Traits::EmptyValue()); } + + template <typename Traits, typename Allocator, typename Value> + static void Reinitialize(Value& bucket) { + // Reinitialize is used when recycling a deleted bucket. For buckets for + // which empty value is non-zero, this is forbidden during marking. Thus if + // we get here, marking is not active and we can reuse Initialize. + DCHECK(Allocator::template CanReuseHashTableDeletedBucket<Traits>()); + Initialize<Traits, Allocator, Value>(bucket); + } }; template <> @@ -1296,6 +1306,19 @@ struct HashTableBucketInitializer<true> { // compilers. memset(&bucket, 0, sizeof(bucket)); } + + template <typename Traits, typename Allocator, typename Value> + static void Reinitialize(Value& bucket) { + // This initializes the bucket without copying the empty value. That + // makes it possible to use this with types that don't support copying. + // The memset to 0 looks like a slow operation but is optimized by the + // compilers. + if (!Allocator::kIsGarbageCollected) { + memset(&bucket, 0, sizeof(bucket)); + return; + } + AtomicMemzero(&bucket, sizeof(bucket)); + } }; template <typename Key, @@ -1319,6 +1342,20 @@ template <typename Key, typename Traits, typename KeyTraits, typename Allocator> +inline void +HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>:: + ReinitializeBucket(ValueType& bucket) { + HashTableBucketInitializer<Traits::kEmptyValueIsZero>::template Reinitialize< + Traits, Allocator>(bucket); +} + +template <typename Key, + typename Value, + typename Extractor, + typename HashFunctions, + typename Traits, + typename KeyTraits, + typename Allocator> template <typename HashTranslator, typename T, typename Extra> typename HashTable<Key, Value, @@ -1344,6 +1381,9 @@ HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>:: UPDATE_ACCESS_COUNTS(); + bool can_reuse_deleted_entry = + Allocator::template CanReuseHashTableDeletedBucket<Traits>(); + ValueType* deleted_entry = nullptr; ValueType* entry; while (1) { @@ -1356,10 +1396,10 @@ HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>:: if (HashTranslator::Equal(Extractor::Extract(*entry), key)) return AddResult(this, entry, false); - if (IsDeletedBucket(*entry)) + if (IsDeletedBucket(*entry) && can_reuse_deleted_entry) deleted_entry = entry; } else { - if (IsDeletedBucket(*entry)) + if (IsDeletedBucket(*entry) && can_reuse_deleted_entry) deleted_entry = entry; else if (HashTranslator::Equal(Extractor::Extract(*entry), key)) return AddResult(this, entry, false); @@ -1373,9 +1413,10 @@ HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>:: RegisterModification(); if (deleted_entry) { + DCHECK(can_reuse_deleted_entry); // Overwrite any data left over from last use, using placement new or // memset. - InitializeBucket(*deleted_entry); + ReinitializeBucket(*deleted_entry); entry = deleted_entry; --deleted_count_; } @@ -1444,7 +1485,7 @@ HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>:: RegisterModification(); if (IsDeletedBucket(*entry)) { - InitializeBucket(*entry); + ReinitializeBucket(*entry); --deleted_count_; } @@ -1836,7 +1877,7 @@ HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>:: } } - Allocator::TraceBackingStoreIfMarked(new_hash_table.table_); + Allocator::TraceBackingStoreIfMarked(&new_hash_table.table_); ValueType* old_table = table_; unsigned old_table_size = table_size_; @@ -2018,9 +2059,9 @@ void HashTable<Key, // Weak processing is omitted when no backing store is present. In case such // an empty table is later on used it needs to be strongified. if (table_) - Allocator::TraceBackingStoreIfMarked(table_); + Allocator::TraceBackingStoreIfMarked(&table_); if (other.table_) - Allocator::TraceBackingStoreIfMarked(other.table_); + Allocator::TraceBackingStoreIfMarked(&other.table_); } std::swap(table_size_, other.table_size_); std::swap(key_count_, other.key_count_); |