Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 // If we are GCing we need to both call the destructor and mark |
| 909 table[i].~ValueType(); | 909 // the bucket as deleted, otherwise the destructor gets called |
| 910 // again when the GC finds the backing store. With the default | |
|
haraken
2014/03/28 10:43:36
This comment was a bit confusing to me at first. M
Erik Corry
2014/03/30 20:11:36
This code is not related to weakness. It is calle
haraken
2014/03/31 00:34:54
Thanks, now I understand.
BTW, currently we don't
| |
| 911 // allocator it's enough to call the destructor, since we won't | |
| 912 // see the bucket again. | |
| 913 if (!isDeletedBucket(table[i])) { | |
| 914 if (Allocator::isGarbageCollected) | |
| 915 deleteBucket(table[i]); | |
| 916 else | |
| 917 table[i].~ValueType(); | |
| 918 } | |
| 910 } | 919 } |
| 911 } | 920 } |
| 912 Allocator::backingFree(table); | 921 Allocator::backingFree(table); |
| 913 } | 922 } |
| 914 | 923 |
| 915 template<typename Key, typename Value, typename Extractor, typename HashFunc tions, typename Traits, typename KeyTraits, typename Allocator> | 924 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() | 925 void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allo cator>::expand() |
| 917 { | 926 { |
| 918 unsigned newSize; | 927 unsigned newSize; |
| 919 if (!m_tableSize) { | 928 if (!m_tableSize) { |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 947 m_table = allocateTable(newTableSize); | 956 m_table = allocateTable(newTableSize); |
| 948 m_tableSize = newTableSize; | 957 m_tableSize = newTableSize; |
| 949 m_tableSizeMask = newTableSize - 1; | 958 m_tableSizeMask = newTableSize - 1; |
| 950 | 959 |
| 951 for (unsigned i = 0; i != oldTableSize; ++i) | 960 for (unsigned i = 0; i != oldTableSize; ++i) |
| 952 if (!isEmptyOrDeletedBucket(oldTable[i])) | 961 if (!isEmptyOrDeletedBucket(oldTable[i])) |
| 953 reinsert(oldTable[i]); | 962 reinsert(oldTable[i]); |
| 954 | 963 |
| 955 m_deletedCount = 0; | 964 m_deletedCount = 0; |
| 956 | 965 |
| 957 deallocateTable(oldTable, oldTableSize); | 966 deleteAllBucketsAndDeallocate(oldTable, oldTableSize); |
| 958 } | 967 } |
| 959 | 968 |
| 960 template<typename Key, typename Value, typename Extractor, typename HashFunc tions, typename Traits, typename KeyTraits, typename Allocator> | 969 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() | 970 void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allo cator>::clear() |
| 962 { | 971 { |
| 963 if (!m_table) | 972 if (!m_table) |
| 964 return; | 973 return; |
| 965 | 974 |
| 966 deallocateTable(m_table, m_tableSize); | 975 deleteAllBucketsAndDeallocate(m_table, m_tableSize); |
| 967 m_table = 0; | 976 m_table = 0; |
| 968 m_tableSize = 0; | 977 m_tableSize = 0; |
| 969 m_tableSizeMask = 0; | 978 m_tableSizeMask = 0; |
| 970 m_keyCount = 0; | 979 m_keyCount = 0; |
| 971 } | 980 } |
| 972 | 981 |
| 973 template<typename Key, typename Value, typename Extractor, typename HashFunc tions, typename Traits, typename KeyTraits, typename Allocator> | 982 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) | 983 HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator >::HashTable(const HashTable& other) |
| 975 : m_table(0) | 984 : m_table(0) |
| 976 , m_tableSize(0) | 985 , m_tableSize(0) |
| (...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1166 inline bool operator!=(const HashTableIteratorAdapter<T, U>& a, const HashTa bleConstIteratorAdapter<T, U>& b) | 1175 inline bool operator!=(const HashTableIteratorAdapter<T, U>& a, const HashTa bleConstIteratorAdapter<T, U>& b) |
| 1167 { | 1176 { |
| 1168 return a.m_impl != b.m_impl; | 1177 return a.m_impl != b.m_impl; |
| 1169 } | 1178 } |
| 1170 | 1179 |
| 1171 } // namespace WTF | 1180 } // namespace WTF |
| 1172 | 1181 |
| 1173 #include "wtf/HashIterators.h" | 1182 #include "wtf/HashIterators.h" |
| 1174 | 1183 |
| 1175 #endif // WTF_HashTable_h | 1184 #endif // WTF_HashTable_h |
| OLD | NEW |