Index: Source/wtf/HashTable.h |
diff --git a/Source/wtf/HashTable.h b/Source/wtf/HashTable.h |
index 566fda8164554a8c67cf060641d6f9965f5e03b9..c2296a97b6a7da97a903d47dff92e876ca7b1f10 100644 |
--- a/Source/wtf/HashTable.h |
+++ b/Source/wtf/HashTable.h |
@@ -241,6 +241,8 @@ namespace WTF { |
typedef typename KeyTraits::PeekInType KeyPeekInType; |
typedef typename KeyTraits::PassInType KeyPassInType; |
typedef Value ValueType; |
+ typedef Extractor ExtractorType; |
+ typedef KeyTraits KeyTraitsType; |
typedef typename Traits::PeekInType ValuePeekInType; |
typedef IdentityHashTranslator<HashFunctions> IdentityTranslatorType; |
typedef HashTableAddResult<ValueType> AddResult; |
@@ -296,7 +298,7 @@ namespace WTF { |
ASSERT(!Allocator::isGarbageCollected); |
if (LIKELY(!m_table)) |
return; |
- deallocateTable(m_table, m_tableSize); |
+ deleteAllBucketsAndDeallocate(m_table, m_tableSize); |
m_table = 0; |
} |
@@ -351,7 +353,7 @@ namespace WTF { |
private: |
static ValueType* allocateTable(unsigned size); |
- static void deallocateTable(ValueType* table, unsigned size); |
+ static void deleteAllBucketsAndDeallocate(ValueType* table, unsigned size); |
typedef std::pair<ValueType*, bool> LookupType; |
typedef std::pair<LookupType, unsigned> FullLookupType; |
@@ -884,7 +886,7 @@ namespace WTF { |
template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator> |
Value* HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::allocateTable(unsigned size) |
{ |
- typedef typename Allocator::template HashTableBackingHelper<Key, Value, Extractor, Traits, KeyTraits>::Type HashTableBacking; |
+ typedef typename Allocator::template HashTableBackingHelper<HashTable>::Type HashTableBacking; |
size_t allocSize = size * sizeof(ValueType); |
ValueType* result; |
@@ -899,14 +901,25 @@ namespace WTF { |
} |
template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator> |
- void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::deallocateTable(ValueType* table, unsigned size) |
+ void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::deleteAllBucketsAndDeallocate(ValueType* table, unsigned size) |
{ |
- if (Allocator::isGarbageCollected) |
- return; |
if (Traits::needsDestruction) { |
for (unsigned i = 0; i < size; ++i) { |
- if (!isDeletedBucket(table[i])) |
- table[i].~ValueType(); |
+ // This code is called when the hash table is cleared or |
+ // resized. We have allocated a new backing store and we need |
+ // to run the destructors on the old backing store, as it is |
+ // being freed. If we are GCing we need to both call the |
+ // destructor and mark the bucket as deleted, otherwise the |
+ // destructor gets called again when the GC finds the backing |
+ // store. With the default allocator it's enough to call the |
+ // destructor, since we will free the memory explicitly and |
+ // we won't see the memory with the bucket again. |
+ if (!isEmptyOrDeletedBucket(table[i])) { |
+ if (Allocator::isGarbageCollected) |
+ deleteBucket(table[i]); |
+ else |
+ table[i].~ValueType(); |
+ } |
} |
} |
Allocator::backingFree(table); |
@@ -954,7 +967,7 @@ namespace WTF { |
m_deletedCount = 0; |
- deallocateTable(oldTable, oldTableSize); |
+ deleteAllBucketsAndDeallocate(oldTable, oldTableSize); |
} |
template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator> |
@@ -963,7 +976,7 @@ namespace WTF { |
if (!m_table) |
return; |
- deallocateTable(m_table, m_tableSize); |
+ deleteAllBucketsAndDeallocate(m_table, m_tableSize); |
m_table = 0; |
m_tableSize = 0; |
m_tableSizeMask = 0; |