Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(795)

Side by Side Diff: Source/wtf/HashTable.h

Issue 216723002: Make sure all destructors are called in HeapHashMap and HeapHashSet (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: CR feedback Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « Source/wtf/DefaultAllocator.h ('k') | Source/wtf/TypeTraits.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2005, 2006, 2007, 2008, 2011, 2012 Apple Inc. All rights reserv ed. 2 * Copyright (C) 2005, 2006, 2007, 2008, 2011, 2012 Apple Inc. All rights reserv ed.
3 * Copyright (C) 2008 David Levin <levin@chromium.org> 3 * Copyright (C) 2008 David Levin <levin@chromium.org>
4 * 4 *
5 * This library is free software; you can redistribute it and/or 5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public 6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either 7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version. 8 * version 2 of the License, or (at your option) any later version.
9 * 9 *
10 * This library is distributed in the hope that it will be useful, 10 * This library is distributed in the hope that it will be useful,
(...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after
234 template<typename Key, typename Value, typename Extractor, typename HashFunc tions, typename Traits, typename KeyTraits, typename Allocator> 234 template<typename Key, typename Value, typename Extractor, typename HashFunc tions, typename Traits, typename KeyTraits, typename Allocator>
235 class HashTable : public HashTableDestructorBase<HashTable<Key, Value, Extra ctor, HashFunctions, Traits, KeyTraits, Allocator>, Allocator::isGarbageCollecte d> { 235 class HashTable : public HashTableDestructorBase<HashTable<Key, Value, Extra ctor, HashFunctions, Traits, KeyTraits, Allocator>, Allocator::isGarbageCollecte d> {
236 public: 236 public:
237 typedef HashTableIterator<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator> iterator; 237 typedef HashTableIterator<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator> iterator;
238 typedef HashTableConstIterator<Key, Value, Extractor, HashFunctions, Tra its, KeyTraits, Allocator> const_iterator; 238 typedef HashTableConstIterator<Key, Value, Extractor, HashFunctions, Tra its, KeyTraits, Allocator> const_iterator;
239 typedef Traits ValueTraits; 239 typedef Traits ValueTraits;
240 typedef Key KeyType; 240 typedef Key KeyType;
241 typedef typename KeyTraits::PeekInType KeyPeekInType; 241 typedef typename KeyTraits::PeekInType KeyPeekInType;
242 typedef typename KeyTraits::PassInType KeyPassInType; 242 typedef typename KeyTraits::PassInType KeyPassInType;
243 typedef Value ValueType; 243 typedef Value ValueType;
244 typedef Extractor ExtractorType;
245 typedef KeyTraits KeyTraitsType;
244 typedef typename Traits::PeekInType ValuePeekInType; 246 typedef typename Traits::PeekInType ValuePeekInType;
245 typedef IdentityHashTranslator<HashFunctions> IdentityTranslatorType; 247 typedef IdentityHashTranslator<HashFunctions> IdentityTranslatorType;
246 typedef HashTableAddResult<ValueType> AddResult; 248 typedef HashTableAddResult<ValueType> AddResult;
247 249
248 #if DUMP_HASHTABLE_STATS_PER_TABLE 250 #if DUMP_HASHTABLE_STATS_PER_TABLE
249 struct Stats { 251 struct Stats {
250 Stats() 252 Stats()
251 : numAccesses(0) 253 : numAccesses(0)
252 , numRehashes(0) 254 , numRehashes(0)
253 , numRemoves(0) 255 , numRemoves(0)
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
289 } 291 }
290 }; 292 };
291 #endif 293 #endif
292 294
293 HashTable(); 295 HashTable();
294 void finalize() 296 void finalize()
295 { 297 {
296 ASSERT(!Allocator::isGarbageCollected); 298 ASSERT(!Allocator::isGarbageCollected);
297 if (LIKELY(!m_table)) 299 if (LIKELY(!m_table))
298 return; 300 return;
299 deallocateTable(m_table, m_tableSize); 301 deleteAllBucketsAndDeallocate(m_table, m_tableSize);
300 m_table = 0; 302 m_table = 0;
301 } 303 }
302 304
303 HashTable(const HashTable&); 305 HashTable(const HashTable&);
304 void swap(HashTable&); 306 void swap(HashTable&);
305 HashTable& operator=(const HashTable&); 307 HashTable& operator=(const HashTable&);
306 308
307 // When the hash table is empty, just return the same iterator for end a s for begin. 309 // When the hash table is empty, just return the same iterator for end a s for begin.
308 // This is more efficient because we don't have to skip all the empty an d deleted 310 // This is more efficient because we don't have to skip all the empty an d deleted
309 // buckets, and iterating an empty table is a common case that's worth o ptimizing. 311 // buckets, and iterating an empty table is a common case that's worth o ptimizing.
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
344 static bool isDeletedBucket(const ValueType& value) { return KeyTraits:: isDeletedValue(Extractor::extract(value)); } 346 static bool isDeletedBucket(const ValueType& value) { return KeyTraits:: isDeletedValue(Extractor::extract(value)); }
345 static bool isEmptyOrDeletedBucket(const ValueType& value) { return Hash TableHelper<ValueType, Extractor, KeyTraits>:: isEmptyOrDeletedBucket(value); } 347 static bool isEmptyOrDeletedBucket(const ValueType& value) { return Hash TableHelper<ValueType, Extractor, KeyTraits>:: isEmptyOrDeletedBucket(value); }
346 348
347 ValueType* lookup(KeyPeekInType key) { return lookup<IdentityTranslatorT ype>(key); } 349 ValueType* lookup(KeyPeekInType key) { return lookup<IdentityTranslatorT ype>(key); }
348 template<typename HashTranslator, typename T> ValueType* lookup(const T& ); 350 template<typename HashTranslator, typename T> ValueType* lookup(const T& );
349 351
350 void trace(typename Allocator::Visitor*); 352 void trace(typename Allocator::Visitor*);
351 353
352 private: 354 private:
353 static ValueType* allocateTable(unsigned size); 355 static ValueType* allocateTable(unsigned size);
354 static void deallocateTable(ValueType* table, unsigned size); 356 static void deleteAllBucketsAndDeallocate(ValueType* table, unsigned siz e);
355 357
356 typedef std::pair<ValueType*, bool> LookupType; 358 typedef std::pair<ValueType*, bool> LookupType;
357 typedef std::pair<LookupType, unsigned> FullLookupType; 359 typedef std::pair<LookupType, unsigned> FullLookupType;
358 360
359 LookupType lookupForWriting(const Key& key) { return lookupForWriting<Id entityTranslatorType>(key); }; 361 LookupType lookupForWriting(const Key& key) { return lookupForWriting<Id entityTranslatorType>(key); };
360 template<typename HashTranslator, typename T> FullLookupType fullLookupF orWriting(const T&); 362 template<typename HashTranslator, typename T> FullLookupType fullLookupF orWriting(const T&);
361 template<typename HashTranslator, typename T> LookupType lookupForWritin g(const T&); 363 template<typename HashTranslator, typename T> LookupType lookupForWritin g(const T&);
362 364
363 void remove(ValueType*); 365 void remove(ValueType*);
364 366
(...skipping 512 matching lines...) Expand 10 before | Expand all | Expand 10 after
877 879
878 template<typename Key, typename Value, typename Extractor, typename HashFunc tions, typename Traits, typename KeyTraits, typename Allocator> 880 template<typename Key, typename Value, typename Extractor, typename HashFunc tions, typename Traits, typename KeyTraits, typename Allocator>
879 inline void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTrait s, Allocator>::remove(KeyPeekInType key) 881 inline void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTrait s, Allocator>::remove(KeyPeekInType key)
880 { 882 {
881 remove(find(key)); 883 remove(find(key));
882 } 884 }
883 885
884 template<typename Key, typename Value, typename Extractor, typename HashFunc tions, typename Traits, typename KeyTraits, typename Allocator> 886 template<typename Key, typename Value, typename Extractor, typename HashFunc tions, typename Traits, typename KeyTraits, typename Allocator>
885 Value* HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Al locator>::allocateTable(unsigned size) 887 Value* HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Al locator>::allocateTable(unsigned size)
886 { 888 {
887 typedef typename Allocator::template HashTableBackingHelper<Key, Value, Extractor, Traits, KeyTraits>::Type HashTableBacking; 889 typedef typename Allocator::template HashTableBackingHelper<HashTable>:: Type HashTableBacking;
888 890
889 size_t allocSize = size * sizeof(ValueType); 891 size_t allocSize = size * sizeof(ValueType);
890 ValueType* result; 892 ValueType* result;
891 if (Traits::emptyValueIsZero) { 893 if (Traits::emptyValueIsZero) {
892 result = Allocator::template zeroedBackingMalloc<ValueType*, HashTab leBacking>(allocSize); 894 result = Allocator::template zeroedBackingMalloc<ValueType*, HashTab leBacking>(allocSize);
893 } else { 895 } else {
894 result = Allocator::template backingMalloc<ValueType*, HashTableBack ing>(allocSize); 896 result = Allocator::template backingMalloc<ValueType*, HashTableBack ing>(allocSize);
895 for (unsigned i = 0; i < size; i++) 897 for (unsigned i = 0; i < size; i++)
896 initializeBucket(result[i]); 898 initializeBucket(result[i]);
897 } 899 }
898 return result; 900 return result;
899 } 901 }
900 902
901 template<typename Key, typename Value, typename Extractor, typename HashFunc tions, typename Traits, typename KeyTraits, typename Allocator> 903 template<typename Key, typename Value, typename Extractor, typename HashFunc tions, typename Traits, typename KeyTraits, typename Allocator>
902 void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allo cator>::deallocateTable(ValueType* table, unsigned size) 904 void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allo cator>::deleteAllBucketsAndDeallocate(ValueType* table, unsigned size)
903 { 905 {
904 if (Allocator::isGarbageCollected)
905 return;
906 if (Traits::needsDestruction) { 906 if (Traits::needsDestruction) {
907 for (unsigned i = 0; i < size; ++i) { 907 for (unsigned i = 0; i < size; ++i) {
908 if (!isDeletedBucket(table[i])) 908 // This code is called when the hash table is cleared or
909 table[i].~ValueType(); 909 // resized. We have allocated a new backing store and we need
910 // to run the destructors on the old backing store, as it is
911 // being freed. If we are GCing we need to both call the
912 // destructor and mark the bucket as deleted, otherwise the
913 // destructor gets called again when the GC finds the backing
914 // store. With the default allocator it's enough to call the
915 // destructor, since we will free the memory explicitly and
916 // we won't see the memory with the bucket again.
917 if (!isEmptyOrDeletedBucket(table[i])) {
918 if (Allocator::isGarbageCollected)
919 deleteBucket(table[i]);
920 else
921 table[i].~ValueType();
922 }
910 } 923 }
911 } 924 }
912 Allocator::backingFree(table); 925 Allocator::backingFree(table);
913 } 926 }
914 927
915 template<typename Key, typename Value, typename Extractor, typename HashFunc tions, typename Traits, typename KeyTraits, typename Allocator> 928 template<typename Key, typename Value, typename Extractor, typename HashFunc tions, typename Traits, typename KeyTraits, typename Allocator>
916 void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allo cator>::expand() 929 void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allo cator>::expand()
917 { 930 {
918 unsigned newSize; 931 unsigned newSize;
919 if (!m_tableSize) { 932 if (!m_tableSize) {
(...skipping 27 matching lines...) Expand all
947 m_table = allocateTable(newTableSize); 960 m_table = allocateTable(newTableSize);
948 m_tableSize = newTableSize; 961 m_tableSize = newTableSize;
949 m_tableSizeMask = newTableSize - 1; 962 m_tableSizeMask = newTableSize - 1;
950 963
951 for (unsigned i = 0; i != oldTableSize; ++i) 964 for (unsigned i = 0; i != oldTableSize; ++i)
952 if (!isEmptyOrDeletedBucket(oldTable[i])) 965 if (!isEmptyOrDeletedBucket(oldTable[i]))
953 reinsert(oldTable[i]); 966 reinsert(oldTable[i]);
954 967
955 m_deletedCount = 0; 968 m_deletedCount = 0;
956 969
957 deallocateTable(oldTable, oldTableSize); 970 deleteAllBucketsAndDeallocate(oldTable, oldTableSize);
958 } 971 }
959 972
960 template<typename Key, typename Value, typename Extractor, typename HashFunc tions, typename Traits, typename KeyTraits, typename Allocator> 973 template<typename Key, typename Value, typename Extractor, typename HashFunc tions, typename Traits, typename KeyTraits, typename Allocator>
961 void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allo cator>::clear() 974 void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allo cator>::clear()
962 { 975 {
963 if (!m_table) 976 if (!m_table)
964 return; 977 return;
965 978
966 deallocateTable(m_table, m_tableSize); 979 deleteAllBucketsAndDeallocate(m_table, m_tableSize);
967 m_table = 0; 980 m_table = 0;
968 m_tableSize = 0; 981 m_tableSize = 0;
969 m_tableSizeMask = 0; 982 m_tableSizeMask = 0;
970 m_keyCount = 0; 983 m_keyCount = 0;
971 } 984 }
972 985
973 template<typename Key, typename Value, typename Extractor, typename HashFunc tions, typename Traits, typename KeyTraits, typename Allocator> 986 template<typename Key, typename Value, typename Extractor, typename HashFunc tions, typename Traits, typename KeyTraits, typename Allocator>
974 HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator >::HashTable(const HashTable& other) 987 HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator >::HashTable(const HashTable& other)
975 : m_table(0) 988 : m_table(0)
976 , m_tableSize(0) 989 , m_tableSize(0)
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after
1166 inline bool operator!=(const HashTableIteratorAdapter<T, U>& a, const HashTa bleConstIteratorAdapter<T, U>& b) 1179 inline bool operator!=(const HashTableIteratorAdapter<T, U>& a, const HashTa bleConstIteratorAdapter<T, U>& b)
1167 { 1180 {
1168 return a.m_impl != b.m_impl; 1181 return a.m_impl != b.m_impl;
1169 } 1182 }
1170 1183
1171 } // namespace WTF 1184 } // namespace WTF
1172 1185
1173 #include "wtf/HashIterators.h" 1186 #include "wtf/HashIterators.h"
1174 1187
1175 #endif // WTF_HashTable_h 1188 #endif // WTF_HashTable_h
OLDNEW
« no previous file with comments | « Source/wtf/DefaultAllocator.h ('k') | Source/wtf/TypeTraits.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698