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 #ifdef ASSERT_ENABLED
    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 #ifdef ASSERT_ENABLED
    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 #ifdef ASSERT_ENABLED
    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, bool useSwap> struct Mover;
    261     template<typename T> struct Mover<T, true> { static void move(T& from, T& to) { hashTableSwap(from, to); } };
    262     template<typename T> struct Mover<T, false> { static void move(T& from, T& to) { to = from; } };
    263 
    264     template<typename HashFunctions> class IdentityHashTranslator {
    265     public:
    266         template<typename T> static unsigned hash(const T& key) { return HashFunctions::hash(key); }
    267         template<typename T, typename U> static bool equal(const T& a, const U& b) { return HashFunctions::equal(a, b); }
    268         template<typename T, typename U, typename V> static void translate(T& location, const U&, const V& value) { location = value; }
    269     };
    270 
    271     template<typename HashTableType, typename ValueType> struct HashTableAddResult {
    272         HashTableAddResult(const HashTableType* container, ValueType* storedValue, bool isNewEntry)
    273             : storedValue(storedValue)
    274             , isNewEntry(isNewEntry)
    275 #if SECURITY_ASSERT_ENABLED
    276             , m_container(container)
    277             , m_containerModifications(container->modifications())
    278 #endif
    279         {
    280             ASSERT_UNUSED(container, container);
    281         }
    282 
    283         ~HashTableAddResult()
    284         {
    285             // If rehash happened before accessing storedValue, it's
    286             // use-after-free. Any modification may cause a rehash, so we check
    287             // for modifications here.
    288             // Rehash after accessing storedValue is harmless but will assert if
    289             // the AddResult destructor takes place after a modification. You
    290             // may need to limit the scope of the AddResult.
    291             ASSERT_WITH_SECURITY_IMPLICATION(m_containerModifications == m_container->modifications());
    292         }
    293 
    294         ValueType* storedValue;
    295         bool isNewEntry;
    296 
    297 #if SECURITY_ASSERT_ENABLED
    298     private:
    299         const HashTableType* m_container;
    300         const int64_t m_containerModifications;
    301 #endif
    302     };
    303 
    304     template<typename Value, typename Extractor, typename KeyTraits>
    305     struct HashTableHelper {
    306         static bool isEmptyBucket(const Value& value) { return isHashTraitsEmptyValue<KeyTraits>(Extractor::extract(value)); }
    307         static bool isDeletedBucket(const Value& value) { return KeyTraits::isDeletedValue(Extractor::extract(value)); }
    308         static bool isEmptyOrDeletedBucket(const Value& value) { return isEmptyBucket(value) || isDeletedBucket(value); }
    309     };
    310 
    311     template<typename HashTranslator, typename KeyTraits, bool safeToCompareToEmptyOrDeleted>
    312     struct HashTableKeyChecker {
    313         // There's no simple generic way to make this check if safeToCompareToEmptyOrDeleted is false,
    314         // so the check always passes.
    315         template <typename T>
    316         static bool checkKey(const T&) { return true; }
    317     };
    318 
    319     template<typename HashTranslator, typename KeyTraits>
    320     struct HashTableKeyChecker<HashTranslator, KeyTraits, true> {
    321         template <typename T>
    322         static bool checkKey(const T& key)
    323         {
    324             // FIXME : Check also equality to the deleted value.
    325             return !HashTranslator::equal(KeyTraits::emptyValue(), key);
    326         }
    327     };
    328 
    329     // Don't declare a destructor for HeapAllocated hash tables.
    330     template<typename Derived, bool isGarbageCollected>
    331     class HashTableDestructorBase;
    332 
    333     template<typename Derived>
    334     class HashTableDestructorBase<Derived, true> { };
    335 
    336     template<typename Derived>
    337     class HashTableDestructorBase<Derived, false> {
    338     public:
    339         ~HashTableDestructorBase() { static_cast<Derived*>(this)->finalize(); }
    340     };
    341 
    342     // Note: empty or deleted key values are not allowed, using them may lead to undefined behavior.
    343     // For pointer keys this means that null pointers are not allowed unless you supply custom key traits.
    344     template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
    345     class HashTable : public HashTableDestructorBase<HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>, Allocator::isGarbageCollected> {
    346     public:
    347         typedef HashTableIterator<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator> iterator;
    348         typedef HashTableConstIterator<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator> const_iterator;
    349         typedef Traits ValueTraits;
    350         typedef Key KeyType;
    351         typedef typename KeyTraits::PeekInType KeyPeekInType;
    352         typedef typename KeyTraits::PassInType KeyPassInType;
    353         typedef Value ValueType;
    354         typedef Extractor ExtractorType;
    355         typedef KeyTraits KeyTraitsType;
    356         typedef typename Traits::PassInType ValuePassInType;
    357         typedef IdentityHashTranslator<HashFunctions> IdentityTranslatorType;
    358         typedef HashTableAddResult<HashTable, ValueType> AddResult;
    359 
    360 #if DUMP_HASHTABLE_STATS_PER_TABLE
    361         struct Stats {
    362             Stats()
    363                 : numAccesses(0)
    364                 , numRehashes(0)
    365                 , numRemoves(0)
    366                 , numReinserts(0)
    367                 , maxCollisions(0)
    368                 , numCollisions(0)
    369                 , collisionGraph()
    370             {
    371             }
    372 
    373             int numAccesses;
    374             int numRehashes;
    375             int numRemoves;
    376             int numReinserts;
    377 
    378             int maxCollisions;
    379             int numCollisions;
    380             int collisionGraph[4096];
    381 
    382             void recordCollisionAtCount(int count)
    383             {
    384                 if (count > maxCollisions)
    385                     maxCollisions = count;
    386                 numCollisions++;
    387                 collisionGraph[count]++;
    388             }
    389 
    390             void dumpStats()
    391             {
    392                 dataLogF("\nWTF::HashTable::Stats dump\n\n");
    393                 dataLogF("%d accesses\n", numAccesses);
    394                 dataLogF("%d total collisions, average %.2f probes per access\n", numCollisions, 1.0 * (numAccesses + numCollisions) / numAccesses);
    395                 dataLogF("longest collision chain: %d\n", maxCollisions);
    396                 for (int i = 1; i <= maxCollisions; i++) {
    397                     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);
    398                 }
    399                 dataLogF("%d rehashes\n", numRehashes);
    400                 dataLogF("%d reinserts\n", numReinserts);
    401             }
    402         };
    403 #endif
    404 
    405         HashTable();
    406         void finalize()
    407         {
    408             ASSERT(!Allocator::isGarbageCollected);
    409             if (LIKELY(!m_table))
    410                 return;
    411             deleteAllBucketsAndDeallocate(m_table, m_tableSize);
    412             m_table = 0;
    413         }
    414 
    415         HashTable(const HashTable&);
    416         void swap(HashTable&);
    417         HashTable& operator=(const HashTable&);
    418 
    419         // When the hash table is empty, just return the same iterator for end as for begin.
    420         // This is more efficient because we don't have to skip all the empty and deleted
    421         // buckets, and iterating an empty table is a common case that's worth optimizing.
    422         iterator begin() { return isEmpty() ? end() : makeIterator(m_table); }
    423         iterator end() { return makeKnownGoodIterator(m_table + m_tableSize); }
    424         const_iterator begin() const { return isEmpty() ? end() : makeConstIterator(m_table); }
    425         const_iterator end() const { return makeKnownGoodConstIterator(m_table + m_tableSize); }
    426 
    427         unsigned size() const { return m_keyCount; }
    428         unsigned capacity() const { return m_tableSize; }
    429         bool isEmpty() const { return !m_keyCount; }
    430 
    431         AddResult add(ValuePassInType value)
    432         {
    433             return add<IdentityTranslatorType>(Extractor::extract(value), value);
    434         }
    435 
    436         // A special version of add() that finds the object by hashing and comparing
    437         // with some other type, to avoid the cost of type conversion if the object is already
    438         // in the table.
    439         template<typename HashTranslator, typename T, typename Extra> AddResult add(const T& key, const Extra&);
    440         template<typename HashTranslator, typename T, typename Extra> AddResult addPassingHashCode(const T& key, const Extra&);
    441 
    442         iterator find(KeyPeekInType key) { return find<IdentityTranslatorType>(key); }
    443         const_iterator find(KeyPeekInType key) const { return find<IdentityTranslatorType>(key); }
    444         bool contains(KeyPeekInType key) const { return contains<IdentityTranslatorType>(key); }
    445 
    446         template<typename HashTranslator, typename T> iterator find(const T&);
    447         template<typename HashTranslator, typename T> const_iterator find(const T&) const;
    448         template<typename HashTranslator, typename T> bool contains(const T&) const;
    449 
    450         void remove(KeyPeekInType);
    451         void remove(iterator);
    452         void remove(const_iterator);
    453         void clear();
    454 
    455         static bool isEmptyBucket(const ValueType& value) { return isHashTraitsEmptyValue<KeyTraits>(Extractor::extract(value)); }
    456         static bool isDeletedBucket(const ValueType& value) { return KeyTraits::isDeletedValue(Extractor::extract(value)); }
    457         static bool isEmptyOrDeletedBucket(const ValueType& value) { return HashTableHelper<ValueType, Extractor, KeyTraits>:: isEmptyOrDeletedBucket(value); }
    458 
    459         ValueType* lookup(KeyPeekInType key) { return lookup<IdentityTranslatorType, KeyPeekInType>(key); }
    460         template<typename HashTranslator, typename T> ValueType* lookup(T);
    461         template<typename HashTranslator, typename T> const ValueType* lookup(T) const;
    462 
    463         void trace(typename Allocator::Visitor*);
    464 
    465 #ifdef ASSERT_ENABLED
    466         int64_t modifications() const { return m_modifications; }
    467         void registerModification() { m_modifications++; }
    468         // HashTable and collections that build on it do not support
    469         // modifications while there is an iterator in use. The exception is
    470         // ListHashSet, which has its own iterators that tolerate modification
    471         // of the underlying set.
    472         void checkModifications(int64_t mods) const { ASSERT(mods == m_modifications); }
    473 #else
    474         int64_t modifications() const { return 0; }
    475         void registerModification() { }
    476         void checkModifications(int64_t mods) const { }
    477 #endif
    478 
    479     private:
    480         static ValueType* allocateTable(unsigned size);
    481         static void deleteAllBucketsAndDeallocate(ValueType* table, unsigned size);
    482 
    483         typedef std::pair<ValueType*, bool> LookupType;
    484         typedef std::pair<LookupType, unsigned> FullLookupType;
    485 
    486         LookupType lookupForWriting(const Key& key) { return lookupForWriting<IdentityTranslatorType>(key); };
    487         template<typename HashTranslator, typename T> FullLookupType fullLookupForWriting(const T&);
    488         template<typename HashTranslator, typename T> LookupType lookupForWriting(const T&);
    489 
    490         void remove(ValueType*);
    491 
    492         bool shouldExpand() const { return (m_keyCount + m_deletedCount) * m_maxLoad >= m_tableSize; }
    493         bool mustRehashInPlace() const { return m_keyCount * m_minLoad < m_tableSize * 2; }
    494         bool shouldShrink() const { return m_keyCount * m_minLoad < m_tableSize && m_tableSize > KeyTraits::minimumTableSize; }
    495         ValueType* expand(ValueType* entry = 0);
    496         void shrink() { rehash(m_tableSize / 2, 0); }
    497 
    498         ValueType* rehash(unsigned newTableSize, ValueType* entry);
    499         ValueType* reinsert(ValueType&);
    500 
    501         static void initializeBucket(ValueType& bucket);
    502         static void deleteBucket(ValueType& bucket) { bucket.~ValueType(); Traits::constructDeletedValue(bucket); }
    503 
    504         FullLookupType makeLookupResult(ValueType* position, bool found, unsigned hash)
    505             { return FullLookupType(LookupType(position, found), hash); }
    506 
    507         iterator makeIterator(ValueType* pos) { return iterator(pos, m_table + m_tableSize, this); }
    508         const_iterator makeConstIterator(ValueType* pos) const { return const_iterator(pos, m_table + m_tableSize, this); }
    509         iterator makeKnownGoodIterator(ValueType* pos) { return iterator(pos, m_table + m_tableSize, this, HashItemKnownGood); }
    510         const_iterator makeKnownGoodConstIterator(ValueType* pos) const { return const_iterator(pos, m_table + m_tableSize, this, HashItemKnownGood); }
    511 
    512         static const unsigned m_maxLoad = 2;
    513         static const unsigned m_minLoad = 6;
    514 
    515         unsigned tableSizeMask() const
    516         {
    517             size_t mask = m_tableSize - 1;
    518             ASSERT((mask & m_tableSize) == 0);
    519             return mask;
    520         }
    521 
    522         ValueType* m_table;
    523         unsigned m_tableSize;
    524         unsigned m_keyCount;
    525         unsigned m_deletedCount;
    526 #ifdef ASSERT_ENABLED
    527         unsigned m_modifications;
    528 #endif
    529 
    530 #if DUMP_HASHTABLE_STATS_PER_TABLE
    531     public:
    532         mutable OwnPtr<Stats> m_stats;
    533 #endif
    534 
    535         template<WeakHandlingFlag x, typename T, typename U, typename V, typename W, typename X, typename Y, typename Z> friend struct WeakProcessingHashTableHelper;
    536         template<typename T, typename U, typename V, typename W> friend class LinkedHashSet;
    537     };
    538 
    539     // Set all the bits to one after the most significant bit: 00110101010 -> 00111111111.
    540     template<unsigned size> struct OneifyLowBits;
    541     template<>
    542     struct OneifyLowBits<0> {
    543         static const unsigned value = 0;
    544     };
    545     template<unsigned number>
    546     struct OneifyLowBits {
    547         static const unsigned value = number | OneifyLowBits<(number >> 1)>::value;
    548     };
    549     // Compute the first power of two integer that is an upper bound of the parameter 'number'.
    550     template<unsigned number>
    551     struct UpperPowerOfTwoBound {
    552         static const unsigned value = (OneifyLowBits<number - 1>::value + 1) * 2;
    553     };
    554 
    555     // Because power of two numbers are the limit of maxLoad, their capacity is twice the
    556     // UpperPowerOfTwoBound, or 4 times their values.
    557     template<unsigned size, bool isPowerOfTwo> struct HashTableCapacityForSizeSplitter;
    558     template<unsigned size>
    559     struct HashTableCapacityForSizeSplitter<size, true> {
    560         static const unsigned value = size * 4;
    561     };
    562     template<unsigned size>
    563     struct HashTableCapacityForSizeSplitter<size, false> {
    564         static const unsigned value = UpperPowerOfTwoBound<size>::value;
    565     };
    566 
    567     // HashTableCapacityForSize computes the upper power of two capacity to hold the size parameter.
    568     // This is done at compile time to initialize the HashTraits.
    569     template<unsigned size>
    570     struct HashTableCapacityForSize {
    571         static const unsigned value = HashTableCapacityForSizeSplitter<size, !(size & (size - 1))>::value;
    572         COMPILE_ASSERT(size > 0, HashTableNonZeroMinimumCapacity);
    573         COMPILE_ASSERT(!static_cast<int>(value >> 31), HashTableNoCapacityOverflow);
    574         COMPILE_ASSERT(value > (2 * size), HashTableCapacityHoldsContentSize);
    575     };
    576 
    577     template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
    578     inline HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::HashTable()
    579         : m_table(0)
    580         , m_tableSize(0)
    581         , m_keyCount(0)
    582         , m_deletedCount(0)
    583 #ifdef ASSERT_ENABLED
    584         , m_modifications(0)
    585 #endif
    586 #if DUMP_HASHTABLE_STATS_PER_TABLE
    587         , m_stats(adoptPtr(new Stats))
    588 #endif
    589     {
    590     }
    591 
    592     inline unsigned doubleHash(unsigned key)
    593     {
    594         key = ~key + (key >> 23);
    595         key ^= (key << 12);
    596         key ^= (key >> 7);
    597         key ^= (key << 2);
    598         key ^= (key >> 20);
    599         return key;
    600     }
    601 
    602     template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
    603     template<typename HashTranslator, typename T>
    604     inline Value* HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::lookup(T key)
    605     {
    606         return const_cast<Value*>(const_cast<const HashTable*>(this)->lookup<HashTranslator, T>(key));
    607     }
    608 
    609     template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
    610     template<typename HashTranslator, typename T>
    611     inline const Value* HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::lookup(T key) const
    612     {
    613         ASSERT((HashTableKeyChecker<HashTranslator, KeyTraits, HashFunctions::safeToCompareToEmptyOrDeleted>::checkKey(key)));
    614         const ValueType* table = m_table;
    615         if (!table)
    616             return 0;
    617 
    618         size_t k = 0;
    619         size_t sizeMask = tableSizeMask();
    620         unsigned h = HashTranslator::hash(key);
    621         size_t i = h & sizeMask;
    622 
    623         UPDATE_ACCESS_COUNTS();
    624 
    625         while (1) {
    626             const ValueType* entry = table + i;
    627 
    628             if (HashFunctions::safeToCompareToEmptyOrDeleted) {
    629                 if (HashTranslator::equal(Extractor::extract(*entry), key))
    630                     return entry;
    631 
    632                 if (isEmptyBucket(*entry))
    633                     return 0;
    634             } else {
    635                 if (isEmptyBucket(*entry))
    636                     return 0;
    637 
    638                 if (!isDeletedBucket(*entry) && HashTranslator::equal(Extractor::extract(*entry), key))
    639                     return entry;
    640             }
    641             UPDATE_PROBE_COUNTS();
    642             if (!k)
    643                 k = 1 | doubleHash(h);
    644             i = (i + k) & sizeMask;
    645         }
    646     }
    647 
    648     template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
    649     template<typename HashTranslator, typename T>
    650     inline typename HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::LookupType HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::lookupForWriting(const T& key)
    651     {
    652         ASSERT(m_table);
    653         registerModification();
    654 
    655         ValueType* table = m_table;
    656         size_t k = 0;
    657         size_t sizeMask = tableSizeMask();
    658         unsigned h = HashTranslator::hash(key);
    659         size_t i = h & sizeMask;
    660 
    661         UPDATE_ACCESS_COUNTS();
    662 
    663         ValueType* deletedEntry = 0;
    664 
    665         while (1) {
    666             ValueType* entry = table + i;
    667 
    668             if (isEmptyBucket(*entry))
    669                 return LookupType(deletedEntry ? deletedEntry : entry, false);
    670 
    671             if (HashFunctions::safeToCompareToEmptyOrDeleted) {
    672                 if (HashTranslator::equal(Extractor::extract(*entry), key))
    673                     return LookupType(entry, true);
    674 
    675                 if (isDeletedBucket(*entry))
    676                     deletedEntry = entry;
    677             } else {
    678                 if (isDeletedBucket(*entry))
    679                     deletedEntry = entry;
    680                 else if (HashTranslator::equal(Extractor::extract(*entry), key))
    681                     return LookupType(entry, true);
    682             }
    683             UPDATE_PROBE_COUNTS();
    684             if (!k)
    685                 k = 1 | doubleHash(h);
    686             i = (i + k) & sizeMask;
    687         }
    688     }
    689 
    690     template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
    691     template<typename HashTranslator, typename T>
    692     inline typename HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::FullLookupType HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::fullLookupForWriting(const T& key)
    693     {
    694         ASSERT(m_table);
    695         registerModification();
    696 
    697         ValueType* table = m_table;
    698         size_t k = 0;
    699         size_t sizeMask = tableSizeMask();
    700         unsigned h = HashTranslator::hash(key);
    701         size_t i = h & sizeMask;
    702 
    703         UPDATE_ACCESS_COUNTS();
    704 
    705         ValueType* deletedEntry = 0;
    706 
    707         while (1) {
    708             ValueType* entry = table + i;
    709 
    710             if (isEmptyBucket(*entry))
    711                 return makeLookupResult(deletedEntry ? deletedEntry : entry, false, h);
    712 
    713             if (HashFunctions::safeToCompareToEmptyOrDeleted) {
    714                 if (HashTranslator::equal(Extractor::extract(*entry), key))
    715                     return makeLookupResult(entry, true, h);
    716 
    717                 if (isDeletedBucket(*entry))
    718                     deletedEntry = entry;
    719             } else {
    720                 if (isDeletedBucket(*entry))
    721                     deletedEntry = entry;
    722                 else if (HashTranslator::equal(Extractor::extract(*entry), key))
    723                     return makeLookupResult(entry, true, h);
    724             }
    725             UPDATE_PROBE_COUNTS();
    726             if (!k)
    727                 k = 1 | doubleHash(h);
    728             i = (i + k) & sizeMask;
    729         }
    730     }
    731 
    732     template<bool emptyValueIsZero> struct HashTableBucketInitializer;
    733 
    734     template<> struct HashTableBucketInitializer<false> {
    735         template<typename Traits, typename Value> static void initialize(Value& bucket)
    736         {
    737             new (NotNull, &bucket) Value(Traits::emptyValue());
    738         }
    739     };
    740 
    741     template<> struct HashTableBucketInitializer<true> {
    742         template<typename Traits, typename Value> static void initialize(Value& bucket)
    743         {
    744             // This initializes the bucket without copying the empty value.
    745             // That makes it possible to use this with types that don't support copying.
    746             // The memset to 0 looks like a slow operation but is optimized by the compilers.
    747             memset(&bucket, 0, sizeof(bucket));
    748         }
    749     };
    750 
    751     template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
    752     inline void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::initializeBucket(ValueType& bucket)
    753     {
    754         HashTableBucketInitializer<Traits::emptyValueIsZero>::template initialize<Traits>(bucket);
    755     }
    756 
    757     template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
    758     template<typename HashTranslator, typename T, typename Extra>
    759     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)
    760     {
    761         if (!m_table)
    762             expand();
    763 
    764         ASSERT(m_table);
    765 
    766         ValueType* table = m_table;
    767         size_t k = 0;
    768         size_t sizeMask = tableSizeMask();
    769         unsigned h = HashTranslator::hash(key);
    770         size_t i = h & sizeMask;
    771 
    772         UPDATE_ACCESS_COUNTS();
    773 
    774         ValueType* deletedEntry = 0;
    775         ValueType* entry;
    776         while (1) {
    777             entry = table + i;
    778 
    779             if (isEmptyBucket(*entry))
    780                 break;
    781 
    782             if (HashFunctions::safeToCompareToEmptyOrDeleted) {
    783                 if (HashTranslator::equal(Extractor::extract(*entry), key))
    784                     return AddResult(this, entry, false);
    785 
    786                 if (isDeletedBucket(*entry))
    787                     deletedEntry = entry;
    788             } else {
    789                 if (isDeletedBucket(*entry))
    790                     deletedEntry = entry;
    791                 else if (HashTranslator::equal(Extractor::extract(*entry), key))
    792                     return AddResult(this, entry, false);
    793             }
    794             UPDATE_PROBE_COUNTS();
    795             if (!k)
    796                 k = 1 | doubleHash(h);
    797             i = (i + k) & sizeMask;
    798         }
    799 
    800         registerModification();
    801 
    802         if (deletedEntry) {
    803             initializeBucket(*deletedEntry);
    804             entry = deletedEntry;
    805             --m_deletedCount;
    806         }
    807 
    808         HashTranslator::translate(*entry, key, extra);
    809         ASSERT(!isEmptyOrDeletedBucket(*entry));
    810 
    811         ++m_keyCount;
    812 
    813         if (shouldExpand())
    814             entry = expand(entry);
    815 
    816         return AddResult(this, entry, true);
    817     }
    818 
    819     template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
    820     template<typename HashTranslator, typename T, typename Extra>
    821     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)
    822     {
    823         if (!m_table)
    824             expand();
    825 
    826         FullLookupType lookupResult = fullLookupForWriting<HashTranslator>(key);
    827 
    828         ValueType* entry = lookupResult.first.first;
    829         bool found = lookupResult.first.second;
    830         unsigned h = lookupResult.second;
    831 
    832         if (found)
    833             return AddResult(this, entry, false);
    834 
    835         registerModification();
    836 
    837         if (isDeletedBucket(*entry)) {
    838             initializeBucket(*entry);
    839             --m_deletedCount;
    840         }
    841 
    842         HashTranslator::translate(*entry, key, extra, h);
    843         ASSERT(!isEmptyOrDeletedBucket(*entry));
    844 
    845         ++m_keyCount;
    846         if (shouldExpand())
    847             entry = expand(entry);
    848 
    849         return AddResult(this, entry, true);
    850     }
    851 
    852     template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
    853     Value* HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::reinsert(ValueType& entry)
    854     {
    855         ASSERT(m_table);
    856         registerModification();
    857         ASSERT(!lookupForWriting(Extractor::extract(entry)).second);
    858         ASSERT(!isDeletedBucket(*(lookupForWriting(Extractor::extract(entry)).first)));
    859 #if DUMP_HASHTABLE_STATS
    860         atomicIncrement(&HashTableStats::numReinserts);
    861 #endif
    862 #if DUMP_HASHTABLE_STATS_PER_TABLE
    863         ++m_stats->numReinserts;
    864 #endif
    865         Value* newEntry = lookupForWriting(Extractor::extract(entry)).first;
    866         Mover<ValueType, Traits::needsDestruction>::move(entry, *newEntry);
    867 
    868         return newEntry;
    869     }
    870 
    871     template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
    872     template <typename HashTranslator, typename T>
    873     inline typename HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::iterator HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::find(const T& key)
    874     {
    875         ValueType* entry = lookup<HashTranslator>(key);
    876         if (!entry)
    877             return end();
    878 
    879         return makeKnownGoodIterator(entry);
    880     }
    881 
    882     template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
    883     template <typename HashTranslator, typename T>
    884     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
    885     {
    886         ValueType* entry = const_cast<HashTable*>(this)->lookup<HashTranslator>(key);
    887         if (!entry)
    888             return end();
    889 
    890         return makeKnownGoodConstIterator(entry);
    891     }
    892 
    893     template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
    894     template <typename HashTranslator, typename T>
    895     bool HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::contains(const T& key) const
    896     {
    897         return const_cast<HashTable*>(this)->lookup<HashTranslator>(key);
    898     }
    899 
    900     template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
    901     void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::remove(ValueType* pos)
    902     {
    903         registerModification();
    904 #if DUMP_HASHTABLE_STATS
    905         atomicIncrement(&HashTableStats::numRemoves);
    906 #endif
    907 #if DUMP_HASHTABLE_STATS_PER_TABLE
    908         ++m_stats->numRemoves;
    909 #endif
    910 
    911         deleteBucket(*pos);
    912         ++m_deletedCount;
    913         --m_keyCount;
    914 
    915         if (shouldShrink())
    916             shrink();
    917     }
    918 
    919     template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
    920     inline void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::remove(iterator it)
    921     {
    922         if (it == end())
    923             return;
    924 
    925         remove(const_cast<ValueType*>(it.m_iterator.m_position));
    926     }
    927 
    928     template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
    929     inline void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::remove(const_iterator it)
    930     {
    931         if (it == end())
    932             return;
    933 
    934         remove(const_cast<ValueType*>(it.m_position));
    935     }
    936 
    937     template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
    938     inline void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::remove(KeyPeekInType key)
    939     {
    940         remove(find(key));
    941     }
    942 
    943     template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
    944     Value* HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::allocateTable(unsigned size)
    945     {
    946         typedef typename Allocator::template HashTableBackingHelper<HashTable>::Type HashTableBacking;
    947 
    948         size_t allocSize = size * sizeof(ValueType);
    949         ValueType* result;
    950         COMPILE_ASSERT(!Traits::emptyValueIsZero || !IsPolymorphic<ValueType>::value, EmptyValueCannotBeZeroForThingsWithAVtable);
    951         if (Traits::emptyValueIsZero) {
    952             result = Allocator::template zeroedBackingMalloc<ValueType*, HashTableBacking>(allocSize);
    953         } else {
    954             result = Allocator::template backingMalloc<ValueType*, HashTableBacking>(allocSize);
    955             for (unsigned i = 0; i < size; i++)
    956                 initializeBucket(result[i]);
    957         }
    958         return result;
    959     }
    960 
    961     template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
    962     void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::deleteAllBucketsAndDeallocate(ValueType* table, unsigned size)
    963     {
    964         if (Traits::needsDestruction) {
    965             for (unsigned i = 0; i < size; ++i) {
    966                 // This code is called when the hash table is cleared or
    967                 // resized. We have allocated a new backing store and we need
    968                 // to run the destructors on the old backing store, as it is
    969                 // being freed. If we are GCing we need to both call the
    970                 // destructor and mark the bucket as deleted, otherwise the
    971                 // destructor gets called again when the GC finds the backing
    972                 // store. With the default allocator it's enough to call the
    973                 // destructor, since we will free the memory explicitly and
    974                 // we won't see the memory with the bucket again.
    975                 if (!isEmptyOrDeletedBucket(table[i])) {
    976                     if (Allocator::isGarbageCollected)
    977                         deleteBucket(table[i]);
    978                     else
    979                         table[i].~ValueType();
    980                 }
    981             }
    982         }
    983         Allocator::backingFree(table);
    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>::expand(Value* entry)
    988     {
    989         unsigned newSize;
    990         if (!m_tableSize) {
    991             newSize = KeyTraits::minimumTableSize;
    992         } else if (mustRehashInPlace()) {
    993             newSize = m_tableSize;
    994         } else {
    995             newSize = m_tableSize * 2;
    996             RELEASE_ASSERT(newSize > m_tableSize);
    997         }
    998 
    999         return rehash(newSize, entry);
   1000     }
   1001 
   1002     template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
   1003     Value* HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::rehash(unsigned newTableSize, Value* entry)
   1004     {
   1005         unsigned oldTableSize = m_tableSize;
   1006         ValueType* oldTable = m_table;
   1007 
   1008 #if DUMP_HASHTABLE_STATS
   1009         if (oldTableSize != 0)
   1010             atomicIncrement(&HashTableStats::numRehashes);
   1011 #endif
   1012 
   1013 #if DUMP_HASHTABLE_STATS_PER_TABLE
   1014         if (oldTableSize != 0)
   1015             ++m_stats->numRehashes;
   1016 #endif
   1017 
   1018         m_table = allocateTable(newTableSize);
   1019         m_tableSize = newTableSize;
   1020 
   1021         Value* newEntry = 0;
   1022         for (unsigned i = 0; i != oldTableSize; ++i) {
   1023             if (isEmptyOrDeletedBucket(oldTable[i])) {
   1024                 ASSERT(&oldTable[i] != entry);
   1025                 continue;
   1026             }
   1027 
   1028             Value* reinsertedEntry = reinsert(oldTable[i]);
   1029             if (&oldTable[i] == entry) {
   1030                 ASSERT(!newEntry);
   1031                 newEntry = reinsertedEntry;
   1032             }
   1033         }
   1034 
   1035         m_deletedCount = 0;
   1036 
   1037         deleteAllBucketsAndDeallocate(oldTable, oldTableSize);
   1038 
   1039         return newEntry;
   1040     }
   1041 
   1042     template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
   1043     void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::clear()
   1044     {
   1045         registerModification();
   1046         if (!m_table)
   1047             return;
   1048 
   1049         deleteAllBucketsAndDeallocate(m_table, m_tableSize);
   1050         m_table = 0;
   1051         m_tableSize = 0;
   1052         m_keyCount = 0;
   1053     }
   1054 
   1055     template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
   1056     HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::HashTable(const HashTable& other)
   1057         : m_table(0)
   1058         , m_tableSize(0)
   1059         , m_keyCount(0)
   1060         , m_deletedCount(0)
   1061 #ifdef ASSERT_ENABLED
   1062         , m_modifications(0)
   1063 #endif
   1064 #if DUMP_HASHTABLE_STATS_PER_TABLE
   1065         , m_stats(adoptPtr(new Stats(*other.m_stats)))
   1066 #endif
   1067     {
   1068         // Copy the hash table the dumb way, by adding each element to the new table.
   1069         // It might be more efficient to copy the table slots, but it's not clear that efficiency is needed.
   1070         const_iterator end = other.end();
   1071         for (const_iterator it = other.begin(); it != end; ++it)
   1072             add(*it);
   1073     }
   1074 
   1075     template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
   1076     void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::swap(HashTable& other)
   1077     {
   1078         std::swap(m_table, other.m_table);
   1079         std::swap(m_tableSize, other.m_tableSize);
   1080         std::swap(m_keyCount, other.m_keyCount);
   1081         std::swap(m_deletedCount, other.m_deletedCount);
   1082 
   1083 #ifdef ASSERT_ENABLED
   1084         std::swap(m_modifications, other.m_modifications);
   1085 #endif
   1086 
   1087 #if DUMP_HASHTABLE_STATS_PER_TABLE
   1088         m_stats.swap(other.m_stats);
   1089 #endif
   1090     }
   1091 
   1092     template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
   1093     HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>& HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::operator=(const HashTable& other)
   1094     {
   1095         HashTable tmp(other);
   1096         swap(tmp);
   1097         return *this;
   1098     }
   1099 
   1100     template<WeakHandlingFlag weakHandlingFlag, typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
   1101     struct WeakProcessingHashTableHelper;
   1102 
   1103     template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
   1104     struct WeakProcessingHashTableHelper<NoWeakHandlingInCollections, Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator> {
   1105         static void process(typename Allocator::Visitor* visitor, void* closure) { }
   1106     };
   1107 
   1108     template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
   1109     struct WeakProcessingHashTableHelper<WeakHandlingInCollections, Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator> {
   1110         static void process(typename Allocator::Visitor* visitor, void* closure)
   1111         {
   1112             typedef HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator> HashTableType;
   1113             HashTableType* table = reinterpret_cast<HashTableType*>(closure);
   1114             if (table->m_table) {
   1115                 // This just marks it live and does not push anything onto the
   1116                 // marking stack.
   1117                 Allocator::markNoTracing(visitor, table->m_table);
   1118                 // Now perform weak processing (this is a no-op if the backing
   1119                 // was accessible through an iterator and was already marked
   1120                 // strongly).
   1121                 for (typename HashTableType::ValueType* element = table->m_table + table->m_tableSize - 1; element >= table->m_table; element--) {
   1122                     if (!HashTableType::isEmptyOrDeletedBucket(*element)) {
   1123                         if (Traits::shouldRemoveFromCollection(visitor, *element)) {
   1124                             table->registerModification();
   1125                             HashTableType::deleteBucket(*element); // Also calls the destructor.
   1126                             table->m_deletedCount++;
   1127                             table->m_keyCount--;
   1128                             // We don't rehash the backing until the next add
   1129                             // or delete, because that would cause allocation
   1130                             // during GC.
   1131                         }
   1132                     }
   1133                 }
   1134             }
   1135         }
   1136     };
   1137 
   1138     template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
   1139     void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::trace(typename Allocator::Visitor* visitor)
   1140     {
   1141         // If someone else already marked the backing and queued up the trace
   1142         // and/or weak callback then we are done. This optimization does not
   1143         // happen for ListHashSet since its iterator does not point at the
   1144         // backing.
   1145         if (!m_table || visitor->isAlive(m_table))
   1146             return;
   1147         // Normally, we mark the backing store without performing trace. This
   1148         // means it is marked live, but the pointers inside it are not marked.
   1149         // Instead we will mark the pointers below. However, for backing
   1150         // stores that contain weak pointers the handling is rather different.
   1151         // We don't mark the backing store here, so the marking GC will leave
   1152         // the backing unmarked. If the backing is found in any other way than
   1153         // through its HashTable (ie from an iterator) then the mark bit will
   1154         // be set and the pointers will be marked strongly, avoiding problems
   1155         // with iterating over things that disappear due to weak processing
   1156         // while we are iterating over them. The weakProcessing callback will
   1157         // mark the backing as a void pointer, and will perform weak processing
   1158         // if needed.
   1159         if (Traits::weakHandlingFlag == NoWeakHandlingInCollections)
   1160             Allocator::markNoTracing(visitor, m_table);
   1161         else
   1162             Allocator::registerWeakMembers(visitor, this, m_table, WeakProcessingHashTableHelper<Traits::weakHandlingFlag, Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::process);
   1163         if (ShouldBeTraced<Traits>::value) {
   1164             for (ValueType* element = m_table + m_tableSize - 1; element >= m_table; element--) {
   1165                 if (!isEmptyOrDeletedBucket(*element))
   1166                     Allocator::template trace<ValueType, Traits>(visitor, *element);
   1167             }
   1168         }
   1169     }
   1170 
   1171     // iterator adapters
   1172 
   1173     template<typename HashTableType, typename Traits> struct HashTableConstIteratorAdapter {
   1174         HashTableConstIteratorAdapter() {}
   1175         HashTableConstIteratorAdapter(const typename HashTableType::const_iterator& impl) : m_impl(impl) {}
   1176         typedef typename Traits::IteratorConstGetType GetType;
   1177         typedef typename HashTableType::ValueTraits::IteratorConstGetType SourceGetType;
   1178 
   1179         GetType get() const { return const_cast<GetType>(SourceGetType(m_impl.get())); }
   1180         typename Traits::IteratorConstReferenceType operator*() const { return Traits::getToReferenceConstConversion(get()); }
   1181         GetType operator->() const { return get(); }
   1182 
   1183         HashTableConstIteratorAdapter& operator++() { ++m_impl; return *this; }
   1184         // postfix ++ intentionally omitted
   1185 
   1186         typename HashTableType::const_iterator m_impl;
   1187     };
   1188 
   1189     template<typename HashTableType, typename Traits> struct HashTableIteratorAdapter {
   1190         typedef typename Traits::IteratorGetType GetType;
   1191         typedef typename HashTableType::ValueTraits::IteratorGetType SourceGetType;
   1192 
   1193         HashTableIteratorAdapter() {}
   1194         HashTableIteratorAdapter(const typename HashTableType::iterator& impl) : m_impl(impl) {}
   1195 
   1196         GetType get() const { return const_cast<GetType>(SourceGetType(m_impl.get())); }
   1197         typename Traits::IteratorReferenceType operator*() const { return Traits::getToReferenceConversion(get()); }
   1198         GetType operator->() const { return get(); }
   1199 
   1200         HashTableIteratorAdapter& operator++() { ++m_impl; return *this; }
   1201         // postfix ++ intentionally omitted
   1202 
   1203         operator HashTableConstIteratorAdapter<HashTableType, Traits>()
   1204         {
   1205             typename HashTableType::const_iterator i = m_impl;
   1206             return i;
   1207         }
   1208 
   1209         typename HashTableType::iterator m_impl;
   1210     };
   1211 
   1212     template<typename T, typename U>
   1213     inline bool operator==(const HashTableConstIteratorAdapter<T, U>& a, const HashTableConstIteratorAdapter<T, U>& b)
   1214     {
   1215         return a.m_impl == b.m_impl;
   1216     }
   1217 
   1218     template<typename T, typename U>
   1219     inline bool operator!=(const HashTableConstIteratorAdapter<T, U>& a, const HashTableConstIteratorAdapter<T, U>& b)
   1220     {
   1221         return a.m_impl != b.m_impl;
   1222     }
   1223 
   1224     template<typename T, typename U>
   1225     inline bool operator==(const HashTableIteratorAdapter<T, U>& a, const HashTableIteratorAdapter<T, U>& b)
   1226     {
   1227         return a.m_impl == b.m_impl;
   1228     }
   1229 
   1230     template<typename T, typename U>
   1231     inline bool operator!=(const HashTableIteratorAdapter<T, U>& a, const HashTableIteratorAdapter<T, U>& b)
   1232     {
   1233         return a.m_impl != b.m_impl;
   1234     }
   1235 
   1236     // All 4 combinations of ==, != and Const,non const.
   1237     template<typename T, typename U>
   1238     inline bool operator==(const HashTableConstIteratorAdapter<T, U>& a, const HashTableIteratorAdapter<T, U>& b)
   1239     {
   1240         return a.m_impl == b.m_impl;
   1241     }
   1242 
   1243     template<typename T, typename U>
   1244     inline bool operator!=(const HashTableConstIteratorAdapter<T, U>& a, const HashTableIteratorAdapter<T, U>& b)
   1245     {
   1246         return a.m_impl != b.m_impl;
   1247     }
   1248 
   1249     template<typename T, typename U>
   1250     inline bool operator==(const HashTableIteratorAdapter<T, U>& a, const HashTableConstIteratorAdapter<T, U>& b)
   1251     {
   1252         return a.m_impl == b.m_impl;
   1253     }
   1254 
   1255     template<typename T, typename U>
   1256     inline bool operator!=(const HashTableIteratorAdapter<T, U>& a, const HashTableConstIteratorAdapter<T, U>& b)
   1257     {
   1258         return a.m_impl != b.m_impl;
   1259     }
   1260 
   1261     template<typename Collection1, typename Collection2>
   1262     inline void removeAll(Collection1& collection, const Collection2& toBeRemoved)
   1263     {
   1264         if (collection.isEmpty() || toBeRemoved.isEmpty())
   1265             return;
   1266         typedef typename Collection2::const_iterator CollectionIterator;
   1267         CollectionIterator end(toBeRemoved.end());
   1268         for (CollectionIterator it(toBeRemoved.begin()); it != end; ++it)
   1269             collection.remove(*it);
   1270     }
   1271 
   1272 } // namespace WTF
   1273 
   1274 #include "wtf/HashIterators.h"
   1275 
   1276 #endif // WTF_HashTable_h
   1277