Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / wtf / HashTable.h
1 /*
2  * Copyright (C) 2005, 2006, 2007, 2008, 2011, 2012 Apple Inc. All rights reserved.
3  * Copyright (C) 2008 David Levin <levin@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