Home | History | Annotate | Download | only in wtf
      1 /*
      2  * Copyright (C) 2005, 2006, 2007, 2008, 2011, 2012 Apple Inc. All rights reserved.
      3  * Copyright (C) 2008 David Levin <levin (at) chromium.org>
      4  *
      5  * This library is free software; you can redistribute it and/or
      6  * modify it under the terms of the GNU Library General Public
      7  * License as published by the Free Software Foundation; either
      8  * version 2 of the License, or (at your option) any later version.
      9  *
     10  * This library is distributed in the hope that it will be useful,
     11  * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU * Library General Public License for more details.
     12  *
     13  * You should have received a copy of the GNU Library General Public License
     14  * along with this library; see the file COPYING.LIB.  If not, write to
     15  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     16  * Boston, MA 02110-1301, USA.
     17  *
     18  */
     19 
     20 #ifndef WTF_HashTable_h
     21 #define WTF_HashTable_h
     22 
     23 #include "wtf/Alignment.h"
     24 #include "wtf/Assertions.h"
     25 #include "wtf/DefaultAllocator.h"
     26 #include "wtf/HashTraits.h"
     27 #include "wtf/WTF.h"
     28 
     29 #define DUMP_HASHTABLE_STATS 0
     30 #define DUMP_HASHTABLE_STATS_PER_TABLE 0
     31 
     32 #if DUMP_HASHTABLE_STATS_PER_TABLE
     33 #include "wtf/DataLog.h"
     34 #endif
     35 
     36 #if DUMP_HASHTABLE_STATS
     37 #if DUMP_HASHTABLE_STATS_PER_TABLE
     38 #define UPDATE_PROBE_COUNTS()                            \
     39     ++probeCount;                                        \
     40     HashTableStats::recordCollisionAtCount(probeCount);  \
     41     ++perTableProbeCount;                                \
     42     m_stats->recordCollisionAtCount(perTableProbeCount)
     43 #define UPDATE_ACCESS_COUNTS()                           \
     44     atomicIncrement(&HashTableStats::numAccesses);       \
     45     int probeCount = 0;                                  \
     46     ++m_stats->numAccesses;                              \
     47     int perTableProbeCount = 0
     48 #else
     49 #define UPDATE_PROBE_COUNTS()                            \
     50     ++probeCount;                                        \
     51     HashTableStats::recordCollisionAtCount(probeCount)
     52 #define UPDATE_ACCESS_COUNTS()                           \
     53     atomicIncrement(&HashTableStats::numAccesses);       \
     54     int probeCount = 0
     55 #endif
     56 #else
     57 #if DUMP_HASHTABLE_STATS_PER_TABLE
     58 #define UPDATE_PROBE_COUNTS()                            \
     59     ++perTableProbeCount;                                \
     60     m_stats->recordCollisionAtCount(perTableProbeCount)
     61 #define UPDATE_ACCESS_COUNTS()                           \
     62     ++m_stats->numAccesses;                              \
     63     int perTableProbeCount = 0
     64 #else
     65 #define UPDATE_PROBE_COUNTS() do { } while (0)
     66 #define UPDATE_ACCESS_COUNTS() do { } while (0)
     67 #endif
     68 #endif
     69 
     70 namespace WTF {
     71 
     72 #if DUMP_HASHTABLE_STATS
     73 
     74     struct HashTableStats {
     75         // The following variables are all atomically incremented when modified.
     76         static int numAccesses;
     77         static int numRehashes;
     78         static int numRemoves;
     79         static int numReinserts;
     80 
     81         // The following variables are only modified in the recordCollisionAtCount method within a mutex.
     82         static int maxCollisions;
     83         static int numCollisions;
     84         static int collisionGraph[4096];
     85 
     86         static void recordCollisionAtCount(int count);
     87         static void dumpStats();
     88     };
     89 
     90 #endif
     91 
     92     template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
     93     class HashTable;
     94     template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
     95     class HashTableIterator;
     96     template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
     97     class HashTableConstIterator;
     98     template<typename Value, typename HashFunctions, typename HashTraits, typename Allocator>
     99     class LinkedHashSet;
    100     template<WeakHandlingFlag x, typename T, typename U, typename V, typename W, typename X, typename Y, typename Z>
    101     struct WeakProcessingHashTableHelper;
    102 
    103     typedef enum { HashItemKnownGood } HashItemKnownGoodTag;
    104 
    105     template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
    106     class HashTableConstIterator {
    107     private:
    108         typedef HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator> HashTableType;
    109         typedef HashTableIterator<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator> iterator;
    110         typedef HashTableConstIterator<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator> const_iterator;
    111         typedef Value ValueType;
    112         typedef typename Traits::IteratorConstGetType GetType;
    113         typedef const ValueType* PointerType;
    114 
    115         friend class HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>;
    116         friend class HashTableIterator<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>;
    117 
    118         void skipEmptyBuckets()
    119         {
    120             while (m_position != m_endPosition && HashTableType::isEmptyOrDeletedBucket(*m_position))
    121                 ++m_position;
    122         }
    123 
    124         HashTableConstIterator(PointerType position, PointerType endPosition, const HashTableType* container)
    125             : m_position(position)
    126             , m_endPosition(endPosition)
    127 #if ENABLE(ASSERT)
    128             , m_container(container)
    129             , m_containerModifications(container->modifications())
    130 #endif
    131         {
    132             skipEmptyBuckets();
    133         }
    134 
    135         HashTableConstIterator(PointerType position, PointerType endPosition, const HashTableType* container, HashItemKnownGoodTag)
    136             : m_position(position)
    137             , m_endPosition(endPosition)
    138 #if ENABLE(ASSERT)
    139             , m_container(container)
    140             , m_containerModifications(container->modifications())
    141 #endif
    142         {
    143             ASSERT(m_containerModifications == m_container->modifications());
    144         }
    145 
    146         void checkModifications() const
    147         {
    148             // HashTable and collections that build on it do not support
    149             // modifications while there is an iterator in use. The exception
    150             // is ListHashSet, which has its own iterators that tolerate
    151             // modification of the underlying set.
    152             ASSERT(m_containerModifications == m_container->modifications());
    153         }
    154 
    155     public:
    156         HashTableConstIterator()
    157         {
    158         }
    159 
    160         GetType get() const
    161         {
    162             checkModifications();
    163             return m_position;
    164         }
    165         typename Traits::IteratorConstReferenceType operator*() const { return Traits::getToReferenceConstConversion(get()); }
    166         GetType operator->() const { return get(); }
    167 
    168         const_iterator& operator++()
    169         {
    170             ASSERT(m_position != m_endPosition);
    171             checkModifications();
    172             ++m_position;
    173             skipEmptyBuckets();
    174             return *this;
    175         }
    176 
    177         // postfix ++ intentionally omitted
    178 
    179         // Comparison.
    180         bool operator==(const const_iterator& other) const
    181         {
    182             return m_position == other.m_position;
    183         }
    184         bool operator!=(const const_iterator& other) const
    185         {
    186             return m_position != other.m_position;
    187         }
    188         bool operator==(const iterator& other) const
    189         {
    190             return *this == static_cast<const_iterator>(other);
    191         }
    192         bool operator!=(const iterator& other) const
    193         {
    194             return *this != static_cast<const_iterator>(other);
    195         }
    196 
    197     private:
    198         PointerType m_position;
    199         PointerType m_endPosition;
    200 #if ENABLE(ASSERT)
    201         const HashTableType* m_container;
    202         int64_t m_containerModifications;
    203 #endif
    204     };
    205 
    206     template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
    207     class HashTableIterator {
    208     private:
    209         typedef HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator> HashTableType;
    210         typedef HashTableIterator<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator> iterator;
    211         typedef HashTableConstIterator<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator> const_iterator;
    212         typedef Value ValueType;
    213         typedef typename Traits::IteratorGetType GetType;
    214         typedef ValueType* PointerType;
    215 
    216         friend class HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>;
    217 
    218         HashTableIterator(PointerType pos, PointerType end, const HashTableType* container) : m_iterator(pos, end, container) { }
    219         HashTableIterator(PointerType pos, PointerType end, const HashTableType* container, HashItemKnownGoodTag tag) : m_iterator(pos, end, container, tag) { }
    220 
    221     public:
    222         HashTableIterator() { }
    223 
    224         // default copy, assignment and destructor are OK
    225 
    226         GetType get() const { return const_cast<GetType>(m_iterator.get()); }
    227         typename Traits::IteratorReferenceType operator*() const { return Traits::getToReferenceConversion(get()); }
    228         GetType operator->() const { return get(); }
    229 
    230         iterator& operator++() { ++m_iterator; return *this; }
    231 
    232         // postfix ++ intentionally omitted
    233 
    234         // Comparison.
    235         bool operator==(const iterator& other) const { return m_iterator == other.m_iterator; }
    236         bool operator!=(const iterator& other) const { return m_iterator != other.m_iterator; }
    237         bool operator==(const const_iterator& other) const { return m_iterator == other; }
    238         bool operator!=(const const_iterator& other) const { return m_iterator != other; }
    239 
    240         operator const_iterator() const { return m_iterator; }
    241 
    242     private:
    243         const_iterator m_iterator;
    244     };
    245 
    246     using std::swap;
    247 
    248     // Work around MSVC's standard library, whose swap for pairs does not swap by component.
    249     template<typename T> inline void hashTableSwap(T& a, T& b)
    250     {
    251         swap(a, b);
    252     }
    253 
    254     template<typename T, typename U> inline void hashTableSwap(KeyValuePair<T, U>& a, KeyValuePair<T, U>& b)
    255     {
    256         swap(a.key, b.key);
    257         swap(a.value, b.value);
    258     }
    259 
    260     template<typename T, typename Allocator, bool useSwap> struct Mover;
    261     template<typename T, typename Allocator> struct Mover<T, Allocator, true> {
    262         static void move(T& from, T& to)
    263         {
    264             // A swap operation should not normally allocate, but it may do so
    265             // if it is falling back on some sort of triple assignment in the
    266             // style of t = a; a = b; b = t because there is no overloaded swap
    267             // operation. We can't allow allocation both because it is slower
    268             // than a true swap operation, but also because allocation implies
    269             // allowing GC: We cannot allow a GC after swapping only the key.
    270             // The value is only traced if the key is present and therefore the
    271             // GC will not see the value in the old backing if the key has been
    272             // moved to the new backing. Therefore, we cannot allow GC until
    273             // after both key and value have been moved.
    274             Allocator::enterNoAllocationScope();
    275             hashTableSwap(from, to);
    276             Allocator::leaveNoAllocationScope();
    277         }
    278     };
    279     template<typename T, typename Allocator> struct Mover<T, Allocator, false> {
    280         static void move(T& from, T& to) { to = from; }
    281     };
    282 
    283     template<typename HashFunctions> class IdentityHashTranslator {
    284     public:
    285         template<typename T> static unsigned hash(const T& key) { return HashFunctions::hash(key); }
    286         template<typename T, typename U> static bool equal(const T& a, const U& b) { return HashFunctions::equal(a, b); }
    287         template<typename T, typename U, typename V> static void translate(T& location, const U&, const V& value) { location = value; }
    288     };
    289 
    290     template<typename HashTableType, typename ValueType> struct HashTableAddResult {
    291         HashTableAddResult(const HashTableType* container, ValueType* storedValue, bool isNewEntry)
    292             : storedValue(storedValue)
    293             , isNewEntry(isNewEntry)
    294 #if ENABLE(SECURITY_ASSERT)
    295             , m_container(container)
    296             , m_containerModifications(container->modifications())
    297 #endif
    298         {
    299             ASSERT_UNUSED(container, container);
    300         }
    301 
    302         ~HashTableAddResult()
    303         {
    304             // If rehash happened before accessing storedValue, it's
    305             // use-after-free. Any modification may cause a rehash, so we check
    306             // for modifications here.
    307             // Rehash after accessing storedValue is harmless but will assert if
    308             // the AddResult destructor takes place after a modification. You
    309             // may need to limit the scope of the AddResult.
    310             ASSERT_WITH_SECURITY_IMPLICATION(m_containerModifications == m_container->modifications());
    311         }
    312 
    313         ValueType* storedValue;
    314         bool isNewEntry;
    315 
    316 #if ENABLE(SECURITY_ASSERT)
    317     private:
    318         const HashTableType* m_container;
    319         const int64_t m_containerModifications;
    320 #endif
    321     };
    322 
    323     template<typename Value, typename Extractor, typename KeyTraits>
    324     struct HashTableHelper {
    325         static bool isEmptyBucket(const Value& value) { return isHashTraitsEmptyValue<KeyTraits>(Extractor::extract(value)); }
    326         static bool isDeletedBucket(const Value& value) { return KeyTraits::isDeletedValue(Extractor::extract(value)); }
    327         static bool isEmptyOrDeletedBucket(const Value& value) { return isEmptyBucket(value) || isDeletedBucket(value); }
    328     };
    329 
    330     template<typename HashTranslator, typename KeyTraits, bool safeToCompareToEmptyOrDeleted>
    331     struct HashTableKeyChecker {
    332         // There's no simple generic way to make this check if safeToCompareToEmptyOrDeleted is false,
    333         // so the check always passes.
    334         template <typename T>
    335         static bool checkKey(const T&) { return true; }
    336     };
    337 
    338     template<typename HashTranslator, typename KeyTraits>
    339     struct HashTableKeyChecker<HashTranslator, KeyTraits, true> {
    340         template <typename T>
    341         static bool checkKey(const T& key)
    342         {
    343             // FIXME : Check also equality to the deleted value.
    344             return !HashTranslator::equal(KeyTraits::emptyValue(), key);
    345         }
    346     };
    347 
    348     // Don't declare a destructor for HeapAllocated hash tables.
    349     template<typename Derived, bool isGarbageCollected>
    350     class HashTableDestructorBase;
    351 
    352     template<typename Derived>
    353     class HashTableDestructorBase<Derived, true> { };
    354 
    355     template<typename Derived>
    356     class HashTableDestructorBase<Derived, false> {
    357     public:
    358         ~HashTableDestructorBase() { static_cast<Derived*>(this)->finalize(); }
    359     };
    360 
    361     // Note: empty or deleted key values are not allowed, using them may lead to undefined behavior.
    362     // For pointer keys this means that null pointers are not allowed unless you supply custom key traits.
    363     template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
    364     class HashTable : public HashTableDestructorBase<HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>, Allocator::isGarbageCollected> {
    365     public:
    366         typedef HashTableIterator<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator> iterator;
    367         typedef HashTableConstIterator<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator> const_iterator;
    368         typedef Traits ValueTraits;
    369         typedef Key KeyType;
    370         typedef typename KeyTraits::PeekInType KeyPeekInType;
    371         typedef typename KeyTraits::PassInType KeyPassInType;
    372         typedef Value ValueType;
    373         typedef Extractor ExtractorType;
    374         typedef KeyTraits KeyTraitsType;
    375         typedef typename Traits::PassInType ValuePassInType;
    376         typedef IdentityHashTranslator<HashFunctions> IdentityTranslatorType;
    377         typedef HashTableAddResult<HashTable, ValueType> AddResult;
    378 
    379 #if DUMP_HASHTABLE_STATS_PER_TABLE
    380         struct Stats {
    381             Stats()
    382                 : numAccesses(0)
    383                 , numRehashes(0)
    384                 , numRemoves(0)
    385                 , numReinserts(0)
    386                 , maxCollisions(0)
    387                 , numCollisions(0)
    388                 , collisionGraph()
    389             {
    390             }
    391 
    392             int numAccesses;
    393             int numRehashes;
    394             int numRemoves;
    395             int numReinserts;
    396 
    397             int maxCollisions;
    398             int numCollisions;
    399             int collisionGraph[4096];
    400 
    401             void recordCollisionAtCount(int count)
    402             {
    403                 if (count > maxCollisions)
    404                     maxCollisions = count;
    405                 numCollisions++;
    406                 collisionGraph[count]++;
    407             }
    408 
    409             void dumpStats()
    410             {
    411                 dataLogF("\nWTF::HashTable::Stats dump\n\n");
    412                 dataLogF("%d accesses\n", numAccesses);
    413                 dataLogF("%d total collisions, average %.2f probes per access\n", numCollisions, 1.0 * (numAccesses + numCollisions) / numAccesses);
    414                 dataLogF("longest collision chain: %d\n", maxCollisions);
    415                 for (int i = 1; i <= maxCollisions; i++) {
    416                     dataLogF("  %d lookups with exactly %d collisions (%.2f%% , %.2f%% with this many or more)\n", collisionGraph[i], i, 100.0 * (collisionGraph[i] - collisionGraph[i+1]) / numAccesses, 100.0 * collisionGraph[i] / numAccesses);
    417                 }
    418                 dataLogF("%d rehashes\n", numRehashes);
    419                 dataLogF("%d reinserts\n", numReinserts);
    420             }
    421         };
    422 #endif
    423 
    424         HashTable();
    425         void finalize()
    426         {
    427             ASSERT(!Allocator::isGarbageCollected);
    428             if (LIKELY(!m_table))
    429                 return;
    430             deleteAllBucketsAndDeallocate(m_table, m_tableSize);
    431             m_table = 0;
    432         }
    433 
    434         HashTable(const HashTable&);
    435         void swap(HashTable&);
    436         HashTable& operator=(const HashTable&);
    437 
    438         // When the hash table is empty, just return the same iterator for end as for begin.
    439         // This is more efficient because we don't have to skip all the empty and deleted
    440         // buckets, and iterating an empty table is a common case that's worth optimizing.
    441         iterator begin() { return isEmpty() ? end() : makeIterator(m_table); }
    442         iterator end() { return makeKnownGoodIterator(m_table + m_tableSize); }
    443         const_iterator begin() const { return isEmpty() ? end() : makeConstIterator(m_table); }
    444         const_iterator end() const { return makeKnownGoodConstIterator(m_table + m_tableSize); }
    445 
    446         unsigned size() const { return m_keyCount; }
    447         unsigned capacity() const { return m_tableSize; }
    448         bool isEmpty() const { return !m_keyCount; }
    449 
    450         AddResult add(ValuePassInType value)
    451         {
    452             return add<IdentityTranslatorType>(Extractor::extract(value), value);
    453         }
    454 
    455         // A special version of add() that finds the object by hashing and comparing
    456         // with some other type, to avoid the cost of type conversion if the object is already
    457         // in the table.
    458         template<typename HashTranslator, typename T, typename Extra> AddResult add(const T& key, const Extra&);
    459         template<typename HashTranslator, typename T, typename Extra> AddResult addPassingHashCode(const T& key, const Extra&);
    460 
    461         iterator find(KeyPeekInType key) { return find<IdentityTranslatorType>(key); }
    462         const_iterator find(KeyPeekInType key) const { return find<IdentityTranslatorType>(key); }
    463         bool contains(KeyPeekInType key) const { return contains<IdentityTranslatorType>(key); }
    464 
    465         template<typename HashTranslator, typename T> iterator find(const T&);
    466         template<typename HashTranslator, typename T> const_iterator find(const T&) const;
    467         template<typename HashTranslator, typename T> bool contains(const T&) const;
    468 
    469         void remove(KeyPeekInType);
    470         void remove(iterator);
    471         void remove(const_iterator);
    472         void clear();
    473 
    474         static bool isEmptyBucket(const ValueType& value) { return isHashTraitsEmptyValue<KeyTraits>(Extractor::extract(value)); }
    475         static bool isDeletedBucket(const ValueType& value) { return KeyTraits::isDeletedValue(Extractor::extract(value)); }
    476         static bool isEmptyOrDeletedBucket(const ValueType& value) { return HashTableHelper<ValueType, Extractor, KeyTraits>:: isEmptyOrDeletedBucket(value); }
    477 
    478         ValueType* lookup(KeyPeekInType key) { return lookup<IdentityTranslatorType, KeyPeekInType>(key); }
    479         template<typename HashTranslator, typename T> ValueType* lookup(T);
    480         template<typename HashTranslator, typename T> const ValueType* lookup(T) const;
    481 
    482         void trace(typename Allocator::Visitor*);
    483 
    484 #if ENABLE(ASSERT)
    485         int64_t modifications() const { return m_modifications; }
    486         void registerModification() { m_modifications++; }
    487         // HashTable and collections that build on it do not support
    488         // modifications while there is an iterator in use. The exception is
    489         // ListHashSet, which has its own iterators that tolerate modification
    490         // of the underlying set.
    491         void checkModifications(int64_t mods) const { ASSERT(mods == m_modifications); }
    492 #else
    493         int64_t modifications() const { return 0; }
    494         void registerModification() { }
    495         void checkModifications(int64_t mods) const { }
    496 #endif
    497 
    498     private:
    499         static ValueType* allocateTable(unsigned size);
    500         static void deleteAllBucketsAndDeallocate(ValueType* table, unsigned size);
    501 
    502         typedef std::pair<ValueType*, bool> LookupType;
    503         typedef std::pair<LookupType, unsigned> FullLookupType;
    504 
    505         LookupType lookupForWriting(const Key& key) { return lookupForWriting<IdentityTranslatorType>(key); };
    506         template<typename HashTranslator, typename T> FullLookupType fullLookupForWriting(const T&);
    507         template<typename HashTranslator, typename T> LookupType lookupForWriting(const T&);
    508 
    509         void remove(ValueType*);
    510 
    511         bool shouldExpand() const { return (m_keyCount + m_deletedCount) * m_maxLoad >= m_tableSize; }
    512         bool mustRehashInPlace() const { return m_keyCount * m_minLoad < m_tableSize * 2; }
    513         bool shouldShrink() const
    514         {
    515             // isAllocationAllowed check should be at the last because it's
    516             // expensive.
    517             return m_keyCount * m_minLoad < m_tableSize
    518                 && m_tableSize > KeyTraits::minimumTableSize
    519                 && Allocator::isAllocationAllowed();
    520         }
    521         ValueType* expand(ValueType* entry = 0);
    522         void shrink() { rehash(m_tableSize / 2, 0); }
    523 
    524         ValueType* rehash(unsigned newTableSize, ValueType* entry);
    525         ValueType* reinsert(ValueType&);
    526 
    527         static void initializeBucket(ValueType& bucket);
    528         static void deleteBucket(ValueType& bucket) { bucket.~ValueType(); Traits::constructDeletedValue(bucket, Allocator::isGarbageCollected); }
    529 
    530         FullLookupType makeLookupResult(ValueType* position, bool found, unsigned hash)
    531             { return FullLookupType(LookupType(position, found), hash); }
    532 
    533         iterator makeIterator(ValueType* pos) { return iterator(pos, m_table + m_tableSize, this); }
    534         const_iterator makeConstIterator(ValueType* pos) const { return const_iterator(pos, m_table + m_tableSize, this); }
    535         iterator makeKnownGoodIterator(ValueType* pos) { return iterator(pos, m_table + m_tableSize, this, HashItemKnownGood); }
    536         const_iterator makeKnownGoodConstIterator(ValueType* pos) const { return const_iterator(pos, m_table + m_tableSize, this, HashItemKnownGood); }
    537 
    538         static const unsigned m_maxLoad = 2;
    539         static const unsigned m_minLoad = 6;
    540 
    541         unsigned tableSizeMask() const
    542         {
    543             size_t mask = m_tableSize - 1;
    544             ASSERT((mask & m_tableSize) == 0);
    545             return mask;
    546         }
    547 
    548         void setEnqueued() { m_queueFlag = true; }
    549         void clearEnqueued() { m_queueFlag = false; }
    550         bool enqueued() { return m_queueFlag; }
    551 
    552         ValueType* m_table;
    553         unsigned m_tableSize;
    554         unsigned m_keyCount;
    555         unsigned m_deletedCount:31;
    556         bool m_queueFlag:1;
    557 #if ENABLE(ASSERT)
    558         unsigned m_modifications;
    559 #endif
    560 
    561 #if DUMP_HASHTABLE_STATS_PER_TABLE
    562     public:
    563         mutable OwnPtr<Stats> m_stats;
    564 #endif
    565 
    566         template<WeakHandlingFlag x, typename T, typename U, typename V, typename W, typename X, typename Y, typename Z> friend struct WeakProcessingHashTableHelper;
    567         template<typename T, typename U, typename V, typename W> friend class LinkedHashSet;
    568     };
    569 
    570     // Set all the bits to one after the most significant bit: 00110101010 -> 00111111111.
    571     template<unsigned size> struct OneifyLowBits;
    572     template<>
    573     struct OneifyLowBits<0> {
    574         static const unsigned value = 0;
    575     };
    576     template<unsigned number>
    577     struct OneifyLowBits {
    578         static const unsigned value = number | OneifyLowBits<(number >> 1)>::value;
    579     };
    580     // Compute the first power of two integer that is an upper bound of the parameter 'number'.
    581     template<unsigned number>
    582     struct UpperPowerOfTwoBound {
    583         static const unsigned value = (OneifyLowBits<number - 1>::value + 1) * 2;
    584     };
    585 
    586     // Because power of two numbers are the limit of maxLoad, their capacity is twice the
    587     // UpperPowerOfTwoBound, or 4 times their values.
    588     template<unsigned size, bool isPowerOfTwo> struct HashTableCapacityForSizeSplitter;
    589     template<unsigned size>
    590     struct HashTableCapacityForSizeSplitter<size, true> {
    591         static const unsigned value = size * 4;
    592     };
    593     template<unsigned size>
    594     struct HashTableCapacityForSizeSplitter<size, false> {
    595         static const unsigned value = UpperPowerOfTwoBound<size>::value;
    596     };
    597 
    598     // HashTableCapacityForSize computes the upper power of two capacity to hold the size parameter.
    599     // This is done at compile time to initialize the HashTraits.
    600     template<unsigned size>
    601     struct HashTableCapacityForSize {
    602         static const unsigned value = HashTableCapacityForSizeSplitter<size, !(size & (size - 1))>::value;
    603         COMPILE_ASSERT(size > 0, HashTableNonZeroMinimumCapacity);
    604         COMPILE_ASSERT(!static_cast<int>(value >> 31), HashTableNoCapacityOverflow);
    605         COMPILE_ASSERT(value > (2 * size), HashTableCapacityHoldsContentSize);
    606     };
    607 
    608     template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
    609     inline HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::HashTable()
    610         : m_table(0)
    611         , m_tableSize(0)
    612         , m_keyCount(0)
    613         , m_deletedCount(0)
    614         , m_queueFlag(false)
    615 #if ENABLE(ASSERT)
    616         , m_modifications(0)
    617 #endif
    618 #if DUMP_HASHTABLE_STATS_PER_TABLE
    619         , m_stats(adoptPtr(new Stats))
    620 #endif
    621     {
    622     }
    623 
    624     inline unsigned doubleHash(unsigned key)
    625     {
    626         key = ~key + (key >> 23);
    627         key ^= (key << 12);
    628         key ^= (key >> 7);
    629         key ^= (key << 2);
    630         key ^= (key >> 20);
    631         return key;
    632     }
    633 
    634     template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
    635     template<typename HashTranslator, typename T>
    636     inline Value* HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::lookup(T key)
    637     {
    638         return const_cast<Value*>(const_cast<const HashTable*>(this)->lookup<HashTranslator, T>(key));
    639     }
    640 
    641     template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
    642     template<typename HashTranslator, typename T>
    643     inline const Value* HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::lookup(T key) const
    644     {
    645         ASSERT((HashTableKeyChecker<HashTranslator, KeyTraits, HashFunctions::safeToCompareToEmptyOrDeleted>::checkKey(key)));
    646         const ValueType* table = m_table;
    647         if (!table)
    648             return 0;
    649 
    650         size_t k = 0;
    651         size_t sizeMask = tableSizeMask();
    652         unsigned h = HashTranslator::hash(key);
    653         size_t i = h & sizeMask;
    654 
    655         UPDATE_ACCESS_COUNTS();
    656 
    657         while (1) {
    658             const ValueType* entry = table + i;
    659 
    660             if (HashFunctions::safeToCompareToEmptyOrDeleted) {
    661                 if (HashTranslator::equal(Extractor::extract(*entry), key))
    662                     return entry;
    663 
    664                 if (isEmptyBucket(*entry))
    665                     return 0;
    666             } else {
    667                 if (isEmptyBucket(*entry))
    668                     return 0;
    669 
    670                 if (!isDeletedBucket(*entry) && HashTranslator::equal(Extractor::extract(*entry), key))
    671                     return entry;
    672             }
    673             UPDATE_PROBE_COUNTS();
    674             if (!k)
    675                 k = 1 | doubleHash(h);
    676             i = (i + k) & sizeMask;
    677         }
    678     }
    679 
    680     template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
    681     template<typename HashTranslator, typename T>
    682     inline typename HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::LookupType HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::lookupForWriting(const T& key)
    683     {
    684         ASSERT(m_table);
    685         registerModification();
    686 
    687         ValueType* table = m_table;
    688         size_t k = 0;
    689         size_t sizeMask = tableSizeMask();
    690         unsigned h = HashTranslator::hash(key);
    691         size_t i = h & sizeMask;
    692 
    693         UPDATE_ACCESS_COUNTS();
    694 
    695         ValueType* deletedEntry = 0;
    696 
    697         while (1) {
    698             ValueType* entry = table + i;
    699 
    700             if (isEmptyBucket(*entry))
    701                 return LookupType(deletedEntry ? deletedEntry : entry, false);
    702 
    703             if (HashFunctions::safeToCompareToEmptyOrDeleted) {
    704                 if (HashTranslator::equal(Extractor::extract(*entry), key))
    705                     return LookupType(entry, true);
    706 
    707                 if (isDeletedBucket(*entry))
    708                     deletedEntry = entry;
    709             } else {
    710                 if (isDeletedBucket(*entry))
    711                     deletedEntry = entry;
    712                 else if (HashTranslator::equal(Extractor::extract(*entry), key))
    713                     return LookupType(entry, true);
    714             }
    715             UPDATE_PROBE_COUNTS();
    716             if (!k)
    717                 k = 1 | doubleHash(h);
    718             i = (i + k) & sizeMask;
    719         }
    720     }
    721 
    722     template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
    723     template<typename HashTranslator, typename T>
    724     inline typename HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::FullLookupType HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::fullLookupForWriting(const T& key)
    725     {
    726         ASSERT(m_table);
    727         registerModification();
    728 
    729         ValueType* table = m_table;
    730         size_t k = 0;
    731         size_t sizeMask = tableSizeMask();
    732         unsigned h = HashTranslator::hash(key);
    733         size_t i = h & sizeMask;
    734 
    735         UPDATE_ACCESS_COUNTS();
    736 
    737         ValueType* deletedEntry = 0;
    738 
    739         while (1) {
    740             ValueType* entry = table + i;
    741 
    742             if (isEmptyBucket(*entry))
    743                 return makeLookupResult(deletedEntry ? deletedEntry : entry, false, h);
    744 
    745             if (HashFunctions::safeToCompareToEmptyOrDeleted) {
    746                 if (HashTranslator::equal(Extractor::extract(*entry), key))
    747                     return makeLookupResult(entry, true, h);
    748 
    749                 if (isDeletedBucket(*entry))
    750                     deletedEntry = entry;
    751             } else {
    752                 if (isDeletedBucket(*entry))
    753                     deletedEntry = entry;
    754                 else if (HashTranslator::equal(Extractor::extract(*entry), key))
    755                     return makeLookupResult(entry, true, h);
    756             }
    757             UPDATE_PROBE_COUNTS();
    758             if (!k)
    759                 k = 1 | doubleHash(h);
    760             i = (i + k) & sizeMask;
    761         }
    762     }
    763 
    764     template<bool emptyValueIsZero> struct HashTableBucketInitializer;
    765 
    766     template<> struct HashTableBucketInitializer<false> {
    767         template<typename Traits, typename Value> static void initialize(Value& bucket)
    768         {
    769             new (NotNull, &bucket) Value(Traits::emptyValue());
    770         }
    771     };
    772 
    773     template<> struct HashTableBucketInitializer<true> {
    774         template<typename Traits, typename Value> static void initialize(Value& bucket)
    775         {
    776             // This initializes the bucket without copying the empty value.
    777             // That makes it possible to use this with types that don't support copying.
    778             // The memset to 0 looks like a slow operation but is optimized by the compilers.
    779             memset(&bucket, 0, sizeof(bucket));
    780         }
    781     };
    782 
    783     template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
    784     inline void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::initializeBucket(ValueType& bucket)
    785     {
    786         // For hash maps the key and value cannot be initialied simultaneously,
    787         // and it would be wrong to have a GC when only one was initialized and
    788         // the other still contained garbage (eg. from a previous use of the
    789         // same slot). Therefore we forbid allocation (and thus GC) while the
    790         // slot is initalized to an empty value.
    791         Allocator::enterNoAllocationScope();
    792         HashTableBucketInitializer<Traits::emptyValueIsZero>::template initialize<Traits>(bucket);
    793         Allocator::leaveNoAllocationScope();
    794     }
    795 
    796     template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
    797     template<typename HashTranslator, typename T, typename Extra>
    798     typename HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::AddResult HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::add(const T& key, const Extra& extra)
    799     {
    800         ASSERT(Allocator::isAllocationAllowed());
    801         if (!m_table)
    802             expand();
    803 
    804         ASSERT(m_table);
    805 
    806         ValueType* table = m_table;
    807         size_t k = 0;
    808         size_t sizeMask = tableSizeMask();
    809         unsigned h = HashTranslator::hash(key);
    810         size_t i = h & sizeMask;
    811 
    812         UPDATE_ACCESS_COUNTS();
    813 
    814         ValueType* deletedEntry = 0;
    815         ValueType* entry;
    816         while (1) {
    817             entry = table + i;
    818 
    819             if (isEmptyBucket(*entry))
    820                 break;
    821 
    822             if (HashFunctions::safeToCompareToEmptyOrDeleted) {
    823                 if (HashTranslator::equal(Extractor::extract(*entry), key))
    824                     return AddResult(this, entry, false);
    825 
    826                 if (isDeletedBucket(*entry))
    827                     deletedEntry = entry;
    828             } else {
    829                 if (isDeletedBucket(*entry))
    830                     deletedEntry = entry;
    831                 else if (HashTranslator::equal(Extractor::extract(*entry), key))
    832                     return AddResult(this, entry, false);
    833             }
    834             UPDATE_PROBE_COUNTS();
    835             if (!k)
    836                 k = 1 | doubleHash(h);
    837             i = (i + k) & sizeMask;
    838         }
    839 
    840         registerModification();
    841 
    842         if (deletedEntry) {
    843             // Overwrite any data left over from last use, using placement new
    844             // or memset.
    845             initializeBucket(*deletedEntry);
    846             entry = deletedEntry;
    847             --m_deletedCount;
    848         }
    849 
    850         HashTranslator::translate(*entry, key, extra);
    851         ASSERT(!isEmptyOrDeletedBucket(*entry));
    852 
    853         ++m_keyCount;
    854 
    855         if (shouldExpand())
    856             entry = expand(entry);
    857 
    858         return AddResult(this, entry, true);
    859     }
    860 
    861     template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
    862     template<typename HashTranslator, typename T, typename Extra>
    863     typename HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::AddResult HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::addPassingHashCode(const T& key, const Extra& extra)
    864     {
    865         ASSERT(Allocator::isAllocationAllowed());
    866         if (!m_table)
    867             expand();
    868 
    869         FullLookupType lookupResult = fullLookupForWriting<HashTranslator>(key);
    870 
    871         ValueType* entry = lookupResult.first.first;
    872         bool found = lookupResult.first.second;
    873         unsigned h = lookupResult.second;
    874 
    875         if (found)
    876             return AddResult(this, entry, false);
    877 
    878         registerModification();
    879 
    880         if (isDeletedBucket(*entry)) {
    881             initializeBucket(*entry);
    882             --m_deletedCount;
    883         }
    884 
    885         HashTranslator::translate(*entry, key, extra, h);
    886         ASSERT(!isEmptyOrDeletedBucket(*entry));
    887 
    888         ++m_keyCount;
    889         if (shouldExpand())
    890             entry = expand(entry);
    891 
    892         return AddResult(this, entry, true);
    893     }
    894 
    895     template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
    896     Value* HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::reinsert(ValueType& entry)
    897     {
    898         ASSERT(m_table);
    899         registerModification();
    900         ASSERT(!lookupForWriting(Extractor::extract(entry)).second);
    901         ASSERT(!isDeletedBucket(*(lookupForWriting(Extractor::extract(entry)).first)));
    902 #if DUMP_HASHTABLE_STATS
    903         atomicIncrement(&HashTableStats::numReinserts);
    904 #endif
    905 #if DUMP_HASHTABLE_STATS_PER_TABLE
    906         ++m_stats->numReinserts;
    907 #endif
    908         Value* newEntry = lookupForWriting(Extractor::extract(entry)).first;
    909         Mover<ValueType, Allocator, Traits::needsDestruction>::move(entry, *newEntry);
    910 
    911         return newEntry;
    912     }
    913 
    914     template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
    915     template <typename HashTranslator, typename T>
    916     inline typename HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::iterator HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::find(const T& key)
    917     {
    918         ValueType* entry = lookup<HashTranslator>(key);
    919         if (!entry)
    920             return end();
    921 
    922         return makeKnownGoodIterator(entry);
    923     }
    924 
    925     template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
    926     template <typename HashTranslator, typename T>
    927     inline typename HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::const_iterator HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::find(const T& key) const
    928     {
    929         ValueType* entry = const_cast<HashTable*>(this)->lookup<HashTranslator>(key);
    930         if (!entry)
    931             return end();
    932 
    933         return makeKnownGoodConstIterator(entry);
    934     }
    935 
    936     template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
    937     template <typename HashTranslator, typename T>
    938     bool HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::contains(const T& key) const
    939     {
    940         return const_cast<HashTable*>(this)->lookup<HashTranslator>(key);
    941     }
    942 
    943     template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
    944     void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::remove(ValueType* pos)
    945     {
    946         registerModification();
    947 #if DUMP_HASHTABLE_STATS
    948         atomicIncrement(&HashTableStats::numRemoves);
    949 #endif
    950 #if DUMP_HASHTABLE_STATS_PER_TABLE
    951         ++m_stats->numRemoves;
    952 #endif
    953 
    954         deleteBucket(*pos);
    955         ++m_deletedCount;
    956         --m_keyCount;
    957 
    958         if (shouldShrink())
    959             shrink();
    960     }
    961 
    962     template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
    963     inline void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::remove(iterator it)
    964     {
    965         if (it == end())
    966             return;
    967 
    968         remove(const_cast<ValueType*>(it.m_iterator.m_position));
    969     }
    970 
    971     template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
    972     inline void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::remove(const_iterator it)
    973     {
    974         if (it == end())
    975             return;
    976 
    977         remove(const_cast<ValueType*>(it.m_position));
    978     }
    979 
    980     template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
    981     inline void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::remove(KeyPeekInType key)
    982     {
    983         remove(find(key));
    984     }
    985 
    986     template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
    987     Value* HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::allocateTable(unsigned size)
    988     {
    989         typedef typename Allocator::template HashTableBackingHelper<HashTable>::Type HashTableBacking;
    990 
    991         size_t allocSize = size * sizeof(ValueType);
    992         ValueType* result;
    993         // Assert that we will not use memset on things with a vtable entry.
    994         // The compiler will also check this on some platforms. We would
    995         // like to check this on the whole value (key-value pair), but
    996         // IsPolymorphic will return false for a pair of two types, even if
    997         // one of the components is polymorphic.
    998         COMPILE_ASSERT(!Traits::emptyValueIsZero || !IsPolymorphic<KeyType>::value, EmptyValueCannotBeZeroForThingsWithAVtable);
    999         if (Traits::emptyValueIsZero) {
   1000             result = Allocator::template zeroedBackingMalloc<ValueType*, HashTableBacking>(allocSize);
   1001         } else {
   1002             result = Allocator::template backingMalloc<ValueType*, HashTableBacking>(allocSize);
   1003             for (unsigned i = 0; i < size; i++)
   1004                 initializeBucket(result[i]);
   1005         }
   1006         return result;
   1007     }
   1008 
   1009     template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
   1010     void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::deleteAllBucketsAndDeallocate(ValueType* table, unsigned size)
   1011     {
   1012         if (Traits::needsDestruction) {
   1013             for (unsigned i = 0; i < size; ++i) {
   1014                 // This code is called when the hash table is cleared or
   1015                 // resized. We have allocated a new backing store and we need
   1016                 // to run the destructors on the old backing store, as it is
   1017                 // being freed. If we are GCing we need to both call the
   1018                 // destructor and mark the bucket as deleted, otherwise the
   1019                 // destructor gets called again when the GC finds the backing
   1020                 // store. With the default allocator it's enough to call the
   1021                 // destructor, since we will free the memory explicitly and
   1022                 // we won't see the memory with the bucket again.
   1023                 if (!isEmptyOrDeletedBucket(table[i])) {
   1024                     if (Allocator::isGarbageCollected)
   1025                         deleteBucket(table[i]);
   1026                     else
   1027                         table[i].~ValueType();
   1028                 }
   1029             }
   1030         }
   1031         Allocator::backingFree(table);
   1032     }
   1033 
   1034     template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
   1035     Value* HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::expand(Value* entry)
   1036     {
   1037         unsigned newSize;
   1038         if (!m_tableSize) {
   1039             newSize = KeyTraits::minimumTableSize;
   1040         } else if (mustRehashInPlace()) {
   1041             newSize = m_tableSize;
   1042         } else {
   1043             newSize = m_tableSize * 2;
   1044             RELEASE_ASSERT(newSize > m_tableSize);
   1045         }
   1046 
   1047         return rehash(newSize, entry);
   1048     }
   1049 
   1050     template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
   1051     Value* HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::rehash(unsigned newTableSize, Value* entry)
   1052     {
   1053         unsigned oldTableSize = m_tableSize;
   1054         ValueType* oldTable = m_table;
   1055 
   1056 #if DUMP_HASHTABLE_STATS
   1057         if (oldTableSize != 0)
   1058             atomicIncrement(&HashTableStats::numRehashes);
   1059 #endif
   1060 
   1061 #if DUMP_HASHTABLE_STATS_PER_TABLE
   1062         if (oldTableSize != 0)
   1063             ++m_stats->numRehashes;
   1064 #endif
   1065 
   1066         m_table = allocateTable(newTableSize);
   1067         m_tableSize = newTableSize;
   1068 
   1069         Value* newEntry = 0;
   1070         for (unsigned i = 0; i != oldTableSize; ++i) {
   1071             if (isEmptyOrDeletedBucket(oldTable[i])) {
   1072                 ASSERT(&oldTable[i] != entry);
   1073                 continue;
   1074             }
   1075 
   1076             Value* reinsertedEntry = reinsert(oldTable[i]);
   1077             if (&oldTable[i] == entry) {
   1078                 ASSERT(!newEntry);
   1079                 newEntry = reinsertedEntry;
   1080             }
   1081         }
   1082 
   1083         m_deletedCount = 0;
   1084 
   1085         deleteAllBucketsAndDeallocate(oldTable, oldTableSize);
   1086 
   1087         return newEntry;
   1088     }
   1089 
   1090     template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
   1091     void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::clear()
   1092     {
   1093         registerModification();
   1094         if (!m_table)
   1095             return;
   1096 
   1097         deleteAllBucketsAndDeallocate(m_table, m_tableSize);
   1098         m_table = 0;
   1099         m_tableSize = 0;
   1100         m_keyCount = 0;
   1101     }
   1102 
   1103     template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
   1104     HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::HashTable(const HashTable& other)
   1105         : m_table(0)
   1106         , m_tableSize(0)
   1107         , m_keyCount(0)
   1108         , m_deletedCount(0)
   1109         , m_queueFlag(false)
   1110 #if ENABLE(ASSERT)
   1111         , m_modifications(0)
   1112 #endif
   1113 #if DUMP_HASHTABLE_STATS_PER_TABLE
   1114         , m_stats(adoptPtr(new Stats(*other.m_stats)))
   1115 #endif
   1116     {
   1117         // Copy the hash table the dumb way, by adding each element to the new table.
   1118         // It might be more efficient to copy the table slots, but it's not clear that efficiency is needed.
   1119         const_iterator end = other.end();
   1120         for (const_iterator it = other.begin(); it != end; ++it)
   1121             add(*it);
   1122     }
   1123 
   1124     template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
   1125     void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::swap(HashTable& other)
   1126     {
   1127         std::swap(m_table, other.m_table);
   1128         std::swap(m_tableSize, other.m_tableSize);
   1129         std::swap(m_keyCount, other.m_keyCount);
   1130         // std::swap does not work for bit fields.
   1131         unsigned deleted = m_deletedCount;
   1132         m_deletedCount = other.m_deletedCount;
   1133         other.m_deletedCount = deleted;
   1134         ASSERT(!m_queueFlag);
   1135         ASSERT(!other.m_queueFlag);
   1136 
   1137 #if ENABLE(ASSERT)
   1138         std::swap(m_modifications, other.m_modifications);
   1139 #endif
   1140 
   1141 #if DUMP_HASHTABLE_STATS_PER_TABLE
   1142         m_stats.swap(other.m_stats);
   1143 #endif
   1144     }
   1145 
   1146     template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
   1147     HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>& HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::operator=(const HashTable& other)
   1148     {
   1149         HashTable tmp(other);
   1150         swap(tmp);
   1151         return *this;
   1152     }
   1153 
   1154     template<WeakHandlingFlag weakHandlingFlag, typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
   1155     struct WeakProcessingHashTableHelper;
   1156 
   1157     template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
   1158     struct WeakProcessingHashTableHelper<NoWeakHandlingInCollections, Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator> {
   1159         static void process(typename Allocator::Visitor* visitor, void* closure) { }
   1160         static void ephemeronIteration(typename Allocator::Visitor* visitor, void* closure) { }
   1161         static void ephemeronIterationDone(typename Allocator::Visitor* visitor, void* closure) { }
   1162     };
   1163 
   1164     template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
   1165     struct WeakProcessingHashTableHelper<WeakHandlingInCollections, Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator> {
   1166         // Used for purely weak and for weak-and-strong tables (ephemerons).
   1167         static void process(typename Allocator::Visitor* visitor, void* closure)
   1168         {
   1169             typedef HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator> HashTableType;
   1170             HashTableType* table = reinterpret_cast<HashTableType*>(closure);
   1171             if (table->m_table) {
   1172                 // This is run as part of weak processing after full
   1173                 // marking. The backing store is therefore marked if
   1174                 // we get here.
   1175                 ASSERT(visitor->isAlive(table->m_table));
   1176                 // Now perform weak processing (this is a no-op if the backing
   1177                 // was accessible through an iterator and was already marked
   1178                 // strongly).
   1179                 typedef typename HashTableType::ValueType ValueType;
   1180                 for (ValueType* element = table->m_table + table->m_tableSize - 1; element >= table->m_table; element--) {
   1181                     if (!HashTableType::isEmptyOrDeletedBucket(*element)) {
   1182                         // At this stage calling trace can make no difference
   1183                         // (everything is already traced), but we use the
   1184                         // return value to remove things from the collection.
   1185                         if (TraceInCollectionTrait<WeakHandlingInCollections, WeakPointersActWeak, ValueType, Traits>::trace(visitor, *element)) {
   1186                             table->registerModification();
   1187                             HashTableType::deleteBucket(*element); // Also calls the destructor.
   1188                             table->m_deletedCount++;
   1189                             table->m_keyCount--;
   1190                             // We don't rehash the backing until the next add
   1191                             // or delete, because that would cause allocation
   1192                             // during GC.
   1193                         }
   1194                     }
   1195                 }
   1196             }
   1197         }
   1198 
   1199         // Called repeatedly for tables that have both weak and strong pointers.
   1200         static void ephemeronIteration(typename Allocator::Visitor* visitor, void* closure)
   1201         {
   1202             typedef HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator> HashTableType;
   1203             HashTableType* table = reinterpret_cast<HashTableType*>(closure);
   1204             if (table->m_table) {
   1205                 // Check the hash table for elements that we now know will not
   1206                 // be removed by weak processing. Those elements need to have
   1207                 // their strong pointers traced.
   1208                 typedef typename HashTableType::ValueType ValueType;
   1209                 for (ValueType* element = table->m_table + table->m_tableSize - 1; element >= table->m_table; element--) {
   1210                     if (!HashTableType::isEmptyOrDeletedBucket(*element))
   1211                         TraceInCollectionTrait<WeakHandlingInCollections, WeakPointersActWeak, ValueType, Traits>::trace(visitor, *element);
   1212                 }
   1213             }
   1214         }
   1215 
   1216         // Called when the ephemeron iteration is done and before running the per thread
   1217         // weak processing. It is guaranteed to be called before any thread is resumed.
   1218         static void ephemeronIterationDone(typename Allocator::Visitor* visitor, void* closure)
   1219         {
   1220             typedef HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator> HashTableType;
   1221             HashTableType* table = reinterpret_cast<HashTableType*>(closure);
   1222             ASSERT(Allocator::weakTableRegistered(visitor, table));
   1223             table->clearEnqueued();
   1224         }
   1225     };
   1226 
   1227     template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
   1228     void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::trace(typename Allocator::Visitor* visitor)
   1229     {
   1230         // If someone else already marked the backing and queued up the trace
   1231         // and/or weak callback then we are done. This optimization does not
   1232         // happen for ListHashSet since its iterator does not point at the
   1233         // backing.
   1234         if (!m_table || visitor->isAlive(m_table))
   1235             return;
   1236         // Normally, we mark the backing store without performing trace. This
   1237         // means it is marked live, but the pointers inside it are not marked.
   1238         // Instead we will mark the pointers below. However, for backing
   1239         // stores that contain weak pointers the handling is rather different.
   1240         // We don't mark the backing store here, so the marking GC will leave
   1241         // the backing unmarked. If the backing is found in any other way than
   1242         // through its HashTable (ie from an iterator) then the mark bit will
   1243         // be set and the pointers will be marked strongly, avoiding problems
   1244         // with iterating over things that disappear due to weak processing
   1245         // while we are iterating over them. We register the backing store
   1246         // pointer for delayed marking which will take place after we know if
   1247         // the backing is reachable from elsewhere. We also register a
   1248         // weakProcessing callback which will perform weak processing if needed.
   1249         if (Traits::weakHandlingFlag == NoWeakHandlingInCollections) {
   1250             Allocator::markNoTracing(visitor, m_table);
   1251         } else {
   1252             Allocator::registerDelayedMarkNoTracing(visitor, m_table);
   1253             Allocator::registerWeakMembers(visitor, this, m_table, WeakProcessingHashTableHelper<Traits::weakHandlingFlag, Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::process);
   1254         }
   1255         if (ShouldBeTraced<Traits>::value) {
   1256             if (Traits::weakHandlingFlag == WeakHandlingInCollections) {
   1257                 // If we have both strong and weak pointers in the collection
   1258                 // then we queue up the collection for fixed point iteration a
   1259                 // la Ephemerons:
   1260                 // http://dl.acm.org/citation.cfm?doid=263698.263733 - see also
   1261                 // http://www.jucs.org/jucs_14_21/eliminating_cycles_in_weak
   1262                 ASSERT(!enqueued() || Allocator::weakTableRegistered(visitor, this));
   1263                 if (!enqueued()) {
   1264                     Allocator::registerWeakTable(visitor, this,
   1265                         WeakProcessingHashTableHelper<Traits::weakHandlingFlag, Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::ephemeronIteration,
   1266                         WeakProcessingHashTableHelper<Traits::weakHandlingFlag, Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::ephemeronIterationDone);
   1267                     setEnqueued();
   1268                 }
   1269                 // We don't need to trace the elements here, since registering
   1270                 // as a weak table above will cause them to be traced (perhaps
   1271                 // several times). It's better to wait until everything else is
   1272                 // traced before tracing the elements for the first time; this
   1273                 // may reduce (by one) the number of iterations needed to get
   1274                 // to a fixed point.
   1275                 return;
   1276             }
   1277             for (ValueType* element = m_table + m_tableSize - 1; element >= m_table; element--) {
   1278                 if (!isEmptyOrDeletedBucket(*element))
   1279                     Allocator::template trace<ValueType, Traits>(visitor, *element);
   1280             }
   1281         }
   1282     }
   1283 
   1284     // iterator adapters
   1285 
   1286     template<typename HashTableType, typename Traits> struct HashTableConstIteratorAdapter {
   1287         HashTableConstIteratorAdapter() {}
   1288         HashTableConstIteratorAdapter(const typename HashTableType::const_iterator& impl) : m_impl(impl) {}
   1289         typedef typename Traits::IteratorConstGetType GetType;
   1290         typedef typename HashTableType::ValueTraits::IteratorConstGetType SourceGetType;
   1291 
   1292         GetType get() const { return const_cast<GetType>(SourceGetType(m_impl.get())); }
   1293         typename Traits::IteratorConstReferenceType operator*() const { return Traits::getToReferenceConstConversion(get()); }
   1294         GetType operator->() const { return get(); }
   1295 
   1296         HashTableConstIteratorAdapter& operator++() { ++m_impl; return *this; }
   1297         // postfix ++ intentionally omitted
   1298 
   1299         typename HashTableType::const_iterator m_impl;
   1300     };
   1301 
   1302     template<typename HashTableType, typename Traits> struct HashTableIteratorAdapter {
   1303         typedef typename Traits::IteratorGetType GetType;
   1304         typedef typename HashTableType::ValueTraits::IteratorGetType SourceGetType;
   1305 
   1306         HashTableIteratorAdapter() {}
   1307         HashTableIteratorAdapter(const typename HashTableType::iterator& impl) : m_impl(impl) {}
   1308 
   1309         GetType get() const { return const_cast<GetType>(SourceGetType(m_impl.get())); }
   1310         typename Traits::IteratorReferenceType operator*() const { return Traits::getToReferenceConversion(get()); }
   1311         GetType operator->() const { return get(); }
   1312 
   1313         HashTableIteratorAdapter& operator++() { ++m_impl; return *this; }
   1314         // postfix ++ intentionally omitted
   1315 
   1316         operator HashTableConstIteratorAdapter<HashTableType, Traits>()
   1317         {
   1318             typename HashTableType::const_iterator i = m_impl;
   1319             return i;
   1320         }
   1321 
   1322         typename HashTableType::iterator m_impl;
   1323     };
   1324 
   1325     template<typename T, typename U>
   1326     inline bool operator==(const HashTableConstIteratorAdapter<T, U>& a, const HashTableConstIteratorAdapter<T, U>& b)
   1327     {
   1328         return a.m_impl == b.m_impl;
   1329     }
   1330 
   1331     template<typename T, typename U>
   1332     inline bool operator!=(const HashTableConstIteratorAdapter<T, U>& a, const HashTableConstIteratorAdapter<T, U>& b)
   1333     {
   1334         return a.m_impl != b.m_impl;
   1335     }
   1336 
   1337     template<typename T, typename U>
   1338     inline bool operator==(const HashTableIteratorAdapter<T, U>& a, const HashTableIteratorAdapter<T, U>& b)
   1339     {
   1340         return a.m_impl == b.m_impl;
   1341     }
   1342 
   1343     template<typename T, typename U>
   1344     inline bool operator!=(const HashTableIteratorAdapter<T, U>& a, const HashTableIteratorAdapter<T, U>& b)
   1345     {
   1346         return a.m_impl != b.m_impl;
   1347     }
   1348 
   1349     // All 4 combinations of ==, != and Const,non const.
   1350     template<typename T, typename U>
   1351     inline bool operator==(const HashTableConstIteratorAdapter<T, U>& a, const HashTableIteratorAdapter<T, U>& b)
   1352     {
   1353         return a.m_impl == b.m_impl;
   1354     }
   1355 
   1356     template<typename T, typename U>
   1357     inline bool operator!=(const HashTableConstIteratorAdapter<T, U>& a, const HashTableIteratorAdapter<T, U>& b)
   1358     {
   1359         return a.m_impl != b.m_impl;
   1360     }
   1361 
   1362     template<typename T, typename U>
   1363     inline bool operator==(const HashTableIteratorAdapter<T, U>& a, const HashTableConstIteratorAdapter<T, U>& b)
   1364     {
   1365         return a.m_impl == b.m_impl;
   1366     }
   1367 
   1368     template<typename T, typename U>
   1369     inline bool operator!=(const HashTableIteratorAdapter<T, U>& a, const HashTableConstIteratorAdapter<T, U>& b)
   1370     {
   1371         return a.m_impl != b.m_impl;
   1372     }
   1373 
   1374     template<typename Collection1, typename Collection2>
   1375     inline void removeAll(Collection1& collection, const Collection2& toBeRemoved)
   1376     {
   1377         if (collection.isEmpty() || toBeRemoved.isEmpty())
   1378             return;
   1379         typedef typename Collection2::const_iterator CollectionIterator;
   1380         CollectionIterator end(toBeRemoved.end());
   1381         for (CollectionIterator it(toBeRemoved.begin()); it != end; ++it)
   1382             collection.remove(*it);
   1383     }
   1384 
   1385 } // namespace WTF
   1386 
   1387 #include "wtf/HashIterators.h"
   1388 
   1389 #endif // WTF_HashTable_h
   1390