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

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

Issue 1892533003: Catch illegal hash table modifications when they happen. Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: add reqd copy ctor Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | third_party/WebKit/Source/wtf/LinkedHashSet.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2005, 2006, 2007, 2008, 2011, 2012 Apple Inc. All rights reserv ed. 2 * Copyright (C) 2005, 2006, 2007, 2008, 2011, 2012 Apple Inc. All rights reserv ed.
3 * Copyright (C) 2008 David Levin <levin@chromium.org> 3 * Copyright (C) 2008 David Levin <levin@chromium.org>
4 * 4 *
5 * This library is free software; you can redistribute it and/or 5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public 6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either 7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version. 8 * version 2 of the License, or (at your option) any later version.
9 * 9 *
10 * This library is distributed in the hope that it will be useful, 10 * This library is distributed in the hope that it will be useful,
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
96 class HashTable; 96 class HashTable;
97 template <typename Key, typename Value, typename Extractor, typename HashFunctio ns, typename Traits, typename KeyTraits, typename Allocator> 97 template <typename Key, typename Value, typename Extractor, typename HashFunctio ns, typename Traits, typename KeyTraits, typename Allocator>
98 class HashTableIterator; 98 class HashTableIterator;
99 template <typename Key, typename Value, typename Extractor, typename HashFunctio ns, typename Traits, typename KeyTraits, typename Allocator> 99 template <typename Key, typename Value, typename Extractor, typename HashFunctio ns, typename Traits, typename KeyTraits, typename Allocator>
100 class HashTableConstIterator; 100 class HashTableConstIterator;
101 template <typename Value, typename HashFunctions, typename HashTraits, typename Allocator> 101 template <typename Value, typename HashFunctions, typename HashTraits, typename Allocator>
102 class LinkedHashSet; 102 class LinkedHashSet;
103 template <WeakHandlingFlag x, typename T, typename U, typename V, typename W, ty pename X, typename Y, typename Z> 103 template <WeakHandlingFlag x, typename T, typename U, typename V, typename W, ty pename X, typename Y, typename Z>
104 struct WeakProcessingHashTableHelper; 104 struct WeakProcessingHashTableHelper;
105 105
106 #if ENABLE(ASSERT)
107 // HashTable and collections that build on it do not support modifications
108 // while there is an iterator or HashTableAddResult on the stack.
109 // The exception is ListHashSet, which has its own iterators that tolerate modif ication
110 // of the underlying set.
111 //
112 // Constraint enforced by this scope object.
113 template <typename HashTableType>
114 class HashTableModificationForbiddenScope {
115 public:
116 HashTableModificationForbiddenScope();
117 explicit HashTableModificationForbiddenScope(const HashTableType*);
118 HashTableModificationForbiddenScope(const HashTableModificationForbiddenScop e&);
119
120 ~HashTableModificationForbiddenScope();
121
122 void leaveScope();
123
124 private:
125 HashTableType* m_container;
126 };
127 #endif
128
106 typedef enum { HashItemKnownGood } HashItemKnownGoodTag; 129 typedef enum { HashItemKnownGood } HashItemKnownGoodTag;
107 130
108 template <typename Key, typename Value, typename Extractor, typename HashFunctio ns, typename Traits, typename KeyTraits, typename Allocator> 131 template <typename Key, typename Value, typename Extractor, typename HashFunctio ns, typename Traits, typename KeyTraits, typename Allocator>
109 class HashTableConstIterator final { 132 class HashTableConstIterator final {
110 DISALLOW_NEW(); 133 DISALLOW_NEW();
111 private: 134 private:
112 typedef HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, A llocator> HashTableType; 135 typedef HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, A llocator> HashTableType;
113 typedef HashTableIterator<Key, Value, Extractor, HashFunctions, Traits, KeyT raits, Allocator> iterator; 136 typedef HashTableIterator<Key, Value, Extractor, HashFunctions, Traits, KeyT raits, Allocator> iterator;
114 typedef HashTableConstIterator<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator> const_iterator; 137 typedef HashTableConstIterator<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator> const_iterator;
115 typedef Value ValueType; 138 typedef Value ValueType;
116 typedef typename Traits::IteratorConstGetType GetType; 139 typedef typename Traits::IteratorConstGetType GetType;
117 typedef const ValueType* PointerType; 140 typedef const ValueType* PointerType;
118 141
119 friend class HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTrai ts, Allocator>; 142 friend class HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTrai ts, Allocator>;
120 friend class HashTableIterator<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>; 143 friend class HashTableIterator<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>;
121 144
122 void skipEmptyBuckets() 145 void skipEmptyBuckets()
123 { 146 {
124 while (m_position != m_endPosition && HashTableType::isEmptyOrDeletedBuc ket(*m_position)) 147 while (m_position != m_endPosition && HashTableType::isEmptyOrDeletedBuc ket(*m_position))
125 ++m_position; 148 ++m_position;
126 } 149 }
127 150
128 HashTableConstIterator(PointerType position, PointerType endPosition, const HashTableType* container) 151 HashTableConstIterator(PointerType position, PointerType endPosition, const HashTableType* container)
129 : m_position(position) 152 : m_position(position)
130 , m_endPosition(endPosition) 153 , m_endPosition(endPosition)
131 #if ENABLE(ASSERT) 154 #if ENABLE(ASSERT)
132 , m_container(container) 155 , m_modificationForbiddenScope(position != endPosition ? container : nul lptr)
133 , m_containerModifications(container->modifications())
134 #endif 156 #endif
135 { 157 {
136 skipEmptyBuckets(); 158 skipEmptyBuckets();
137 } 159 }
138 160
139 HashTableConstIterator(PointerType position, PointerType endPosition, const HashTableType* container, HashItemKnownGoodTag) 161 HashTableConstIterator(PointerType position, PointerType endPosition, const HashTableType* container, HashItemKnownGoodTag)
140 : m_position(position) 162 : m_position(position)
141 , m_endPosition(endPosition) 163 , m_endPosition(endPosition)
142 #if ENABLE(ASSERT) 164 #if ENABLE(ASSERT)
143 , m_container(container) 165 , m_modificationForbiddenScope(position != endPosition ? container : nul lptr)
144 , m_containerModifications(container->modifications())
145 #endif 166 #endif
146 { 167 {
147 ASSERT(m_containerModifications == m_container->modifications());
148 }
149
150 void checkModifications() const
151 {
152 // HashTable and collections that build on it do not support
153 // modifications while there is an iterator in use. The exception is
154 // ListHashSet, which has its own iterators that tolerate modification
155 // of the underlying set.
156 ASSERT(m_containerModifications == m_container->modifications());
157 ASSERT(!m_container->accessForbidden());
158 } 168 }
159 169
160 public: 170 public:
161 HashTableConstIterator() {} 171 HashTableConstIterator() {}
162 172
163 GetType get() const 173 GetType get() const
164 { 174 {
165 checkModifications();
166 return m_position; 175 return m_position;
167 } 176 }
168 typename Traits::IteratorConstReferenceType operator*() const { return Trait s::getToReferenceConstConversion(get()); } 177 typename Traits::IteratorConstReferenceType operator*() const { return Trait s::getToReferenceConstConversion(get()); }
169 GetType operator->() const { return get(); } 178 GetType operator->() const { return get(); }
170 179
171 const_iterator& operator++() 180 const_iterator& operator++()
172 { 181 {
173 ASSERT(m_position != m_endPosition); 182 ASSERT(m_position != m_endPosition);
174 checkModifications();
175 ++m_position; 183 ++m_position;
176 skipEmptyBuckets(); 184 skipEmptyBuckets();
185 #if ENABLE(ASSERT)
186 // If now at the end, leave the forbidden scope. Waiting until
187 // the iterator goes out of (stack) scope disallows perfectly valid
188 // code idioms.
189 if (m_position == m_endPosition)
190 m_modificationForbiddenScope.leaveScope();
191 #endif
177 return *this; 192 return *this;
178 } 193 }
179 194
180 // postfix ++ intentionally omitted 195 // postfix ++ intentionally omitted
181 196
182 // Comparison. 197 // Comparison.
183 bool operator==(const const_iterator& other) const 198 bool operator==(const const_iterator& other) const
184 { 199 {
185 return m_position == other.m_position; 200 return m_position == other.m_position;
186 } 201 }
187 bool operator!=(const const_iterator& other) const 202 bool operator!=(const const_iterator& other) const
188 { 203 {
189 return m_position != other.m_position; 204 return m_position != other.m_position;
190 } 205 }
191 bool operator==(const iterator& other) const 206 bool operator==(const iterator& other) const
192 { 207 {
193 return *this == static_cast<const_iterator>(other); 208 return *this == static_cast<const_iterator>(other);
194 } 209 }
195 bool operator!=(const iterator& other) const 210 bool operator!=(const iterator& other) const
196 { 211 {
197 return *this != static_cast<const_iterator>(other); 212 return *this != static_cast<const_iterator>(other);
198 } 213 }
199 214
200 private: 215 private:
201 PointerType m_position; 216 PointerType m_position;
202 PointerType m_endPosition; 217 PointerType m_endPosition;
203 #if ENABLE(ASSERT) 218 #if ENABLE(ASSERT)
204 const HashTableType* m_container; 219 HashTableModificationForbiddenScope<HashTableType> m_modificationForbiddenSc ope;
205 int64_t m_containerModifications;
206 #endif 220 #endif
207 }; 221 };
208 222
209 template <typename Key, typename Value, typename Extractor, typename HashFunctio ns, typename Traits, typename KeyTraits, typename Allocator> 223 template <typename Key, typename Value, typename Extractor, typename HashFunctio ns, typename Traits, typename KeyTraits, typename Allocator>
210 class HashTableIterator final { 224 class HashTableIterator final {
211 DISALLOW_NEW(); 225 DISALLOW_NEW();
212 private: 226 private:
213 typedef HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, A llocator> HashTableType; 227 typedef HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, A llocator> HashTableType;
214 typedef HashTableIterator<Key, Value, Extractor, HashFunctions, Traits, KeyT raits, Allocator> iterator; 228 typedef HashTableIterator<Key, Value, Extractor, HashFunctions, Traits, KeyT raits, Allocator> iterator;
215 typedef HashTableConstIterator<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator> const_iterator; 229 typedef HashTableConstIterator<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator> const_iterator;
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
270 }; 284 };
271 285
272 template <typename HashFunctions> class IdentityHashTranslator { 286 template <typename HashFunctions> class IdentityHashTranslator {
273 STATIC_ONLY(IdentityHashTranslator); 287 STATIC_ONLY(IdentityHashTranslator);
274 public: 288 public:
275 template <typename T> static unsigned hash(const T& key) { return HashFuncti ons::hash(key); } 289 template <typename T> static unsigned hash(const T& key) { return HashFuncti ons::hash(key); }
276 template <typename T, typename U> static bool equal(const T& a, const U& b) { return HashFunctions::equal(a, b); } 290 template <typename T, typename U> static bool equal(const T& a, const U& b) { return HashFunctions::equal(a, b); }
277 template <typename T, typename U, typename V> static void translate(T& locat ion, U&&, V&& value) { location = std::forward<V>(value); } 291 template <typename T, typename U, typename V> static void translate(T& locat ion, U&&, V&& value) { location = std::forward<V>(value); }
278 }; 292 };
279 293
280 template <typename HashTableType, typename ValueType> struct HashTableAddResult final { 294 template <typename HashTableType, typename ValueType>
295 struct HashTableAddResult final {
281 STACK_ALLOCATED(); 296 STACK_ALLOCATED();
282 HashTableAddResult(const HashTableType* container, ValueType* storedValue, b ool isNewEntry) 297 HashTableAddResult(const HashTableType* container, ValueType* storedValue, b ool isNewEntry)
283 : storedValue(storedValue) 298 : storedValue(storedValue)
284 , isNewEntry(isNewEntry) 299 , isNewEntry(isNewEntry)
285 #if ENABLE(SECURITY_ASSERT) 300 #if ENABLE(SECURITY_ASSERT)
286 , m_container(container) 301 , m_modificationForbiddenScope(container)
287 , m_containerModifications(container->modifications())
288 #endif 302 #endif
289 { 303 {
290 ALLOW_UNUSED_LOCAL(container); 304 ALLOW_UNUSED_LOCAL(container);
291 DCHECK(container); 305 DCHECK(container);
292 } 306 }
293 307
294 ValueType* storedValue; 308 ValueType* storedValue;
295 bool isNewEntry; 309 bool isNewEntry;
296 310
297 #if ENABLE(SECURITY_ASSERT) 311 #if ENABLE(SECURITY_ASSERT)
298 ~HashTableAddResult() 312 ~HashTableAddResult()
299 { 313 {
300 // If rehash happened before accessing storedValue, it's 314 // If rehash happened before accessing storedValue, it's
301 // use-after-free. Any modification may cause a rehash, so we check for 315 // use-after-free. Any modification may cause a rehash, so we enter
302 // modifications here. 316 // a modification forbidden scope for the lifetime of this value.
303
304 // Rehash after accessing storedValue is harmless but will assert if the
305 // AddResult destructor takes place after a modification. You may need
306 // to limit the scope of the AddResult.
307 ASSERT_WITH_SECURITY_IMPLICATION(m_containerModifications == m_container ->modifications());
308 } 317 }
309 318
310 private: 319 private:
311 const HashTableType* m_container; 320 HashTableModificationForbiddenScope<HashTableType> m_modificationForbiddenSc ope;
312 const int64_t m_containerModifications;
313 #endif 321 #endif
314 }; 322 };
315 323
316 template <typename Value, typename Extractor, typename KeyTraits> 324 template <typename Value, typename Extractor, typename KeyTraits>
317 struct HashTableHelper { 325 struct HashTableHelper {
318 STATIC_ONLY(HashTableHelper); 326 STATIC_ONLY(HashTableHelper);
319 static bool isEmptyBucket(const Value& value) { return isHashTraitsEmptyValu e<KeyTraits>(Extractor::extract(value)); } 327 static bool isEmptyBucket(const Value& value) { return isHashTraitsEmptyValu e<KeyTraits>(Extractor::extract(value)); }
320 static bool isDeletedBucket(const Value& value) { return KeyTraits::isDelete dValue(Extractor::extract(value)); } 328 static bool isDeletedBucket(const Value& value) { return KeyTraits::isDelete dValue(Extractor::extract(value)); }
321 static bool isEmptyOrDeletedBucket(const Value& value) { return isEmptyBucke t(value) || isDeletedBucket(value); } 329 static bool isEmptyOrDeletedBucket(const Value& value) { return isEmptyBucke t(value) || isDeletedBucket(value); }
322 }; 330 };
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
406 } 414 }
407 }; 415 };
408 #endif 416 #endif
409 417
410 HashTable(); 418 HashTable();
411 void finalize() 419 void finalize()
412 { 420 {
413 ASSERT(!Allocator::isGarbageCollected); 421 ASSERT(!Allocator::isGarbageCollected);
414 if (LIKELY(!m_table)) 422 if (LIKELY(!m_table))
415 return; 423 return;
416 ASSERT(!m_accessForbidden);
417 #if ENABLE(ASSERT)
418 m_accessForbidden = true;
419 #endif
420 deleteAllBucketsAndDeallocate(m_table, m_tableSize); 424 deleteAllBucketsAndDeallocate(m_table, m_tableSize);
421 #if ENABLE(ASSERT)
422 m_accessForbidden = false;
423 #endif
424 m_table = nullptr; 425 m_table = nullptr;
425 } 426 }
426 427
427 HashTable(const HashTable&); 428 HashTable(const HashTable&);
428 HashTable(HashTable&&); 429 HashTable(HashTable&&);
429 void swap(HashTable&); 430 void swap(HashTable&);
430 HashTable& operator=(const HashTable&); 431 HashTable& operator=(const HashTable&);
431 HashTable& operator=(HashTable&&); 432 HashTable& operator=(HashTable&&);
432 433
433 // When the hash table is empty, just return the same iterator for end as 434 // When the hash table is empty, just return the same iterator for end as
434 // for begin. This is more efficient because we don't have to skip all the 435 // for begin. This is more efficient because we don't have to skip all the
435 // empty and deleted buckets, and iterating an empty table is a common case 436 // empty and deleted buckets, and iterating an empty table is a common case
436 // that's worth optimizing. 437 // that's worth optimizing.
437 iterator begin() { return isEmpty() ? end() : makeIterator(m_table); } 438 iterator begin() { return isEmpty() ? end() : makeIterator(m_table); }
438 iterator end() { return makeKnownGoodIterator(m_table + m_tableSize); } 439 iterator end() { return makeKnownGoodIterator(m_table + m_tableSize); }
439 const_iterator begin() const { return isEmpty() ? end() : makeConstIterator( m_table); } 440 const_iterator begin() const { return isEmpty() ? end() : makeConstIterator( m_table); }
440 const_iterator end() const { return makeKnownGoodConstIterator(m_table + m_t ableSize); } 441 const_iterator end() const { return makeKnownGoodConstIterator(m_table + m_t ableSize); }
441 442
442 unsigned size() const 443 unsigned size() const
443 { 444 {
444 ASSERT(!m_accessForbidden);
445 return m_keyCount; 445 return m_keyCount;
446 } 446 }
447 unsigned capacity() const 447 unsigned capacity() const
448 { 448 {
449 ASSERT(!m_accessForbidden);
450 return m_tableSize; 449 return m_tableSize;
451 } 450 }
452 bool isEmpty() const 451 bool isEmpty() const
453 { 452 {
454 ASSERT(!m_accessForbidden);
455 return !m_keyCount; 453 return !m_keyCount;
456 } 454 }
457 455
458 void reserveCapacityForSize(unsigned size); 456 void reserveCapacityForSize(unsigned size);
459 457
460 template <typename IncomingValueType> 458 template <typename IncomingValueType>
461 AddResult add(IncomingValueType&& value) 459 AddResult add(IncomingValueType&& value)
462 { 460 {
463 return add<IdentityTranslatorType>(Extractor::extract(value), std::forwa rd<IncomingValueType>(value)); 461 return add<IdentityTranslatorType>(Extractor::extract(value), std::forwa rd<IncomingValueType>(value));
464 } 462 }
(...skipping 21 matching lines...) Expand all
486 static bool isDeletedBucket(const ValueType& value) { return KeyTraits::isDe letedValue(Extractor::extract(value)); } 484 static bool isDeletedBucket(const ValueType& value) { return KeyTraits::isDe letedValue(Extractor::extract(value)); }
487 static bool isEmptyOrDeletedBucket(const ValueType& value) { return HashTabl eHelper<ValueType, Extractor, KeyTraits>:: isEmptyOrDeletedBucket(value); } 485 static bool isEmptyOrDeletedBucket(const ValueType& value) { return HashTabl eHelper<ValueType, Extractor, KeyTraits>:: isEmptyOrDeletedBucket(value); }
488 486
489 ValueType* lookup(KeyPeekInType key) { return lookup<IdentityTranslatorType, KeyPeekInType>(key); } 487 ValueType* lookup(KeyPeekInType key) { return lookup<IdentityTranslatorType, KeyPeekInType>(key); }
490 template <typename HashTranslator, typename T> ValueType* lookup(const T&); 488 template <typename HashTranslator, typename T> ValueType* lookup(const T&);
491 template <typename HashTranslator, typename T> const ValueType* lookup(const T&) const; 489 template <typename HashTranslator, typename T> const ValueType* lookup(const T&) const;
492 490
493 template <typename VisitorDispatcher> void trace(VisitorDispatcher); 491 template <typename VisitorDispatcher> void trace(VisitorDispatcher);
494 492
495 #if ENABLE(ASSERT) 493 #if ENABLE(ASSERT)
496 bool accessForbidden() const { return m_accessForbidden; } 494 void enterModificationForbiddenScope() { m_modificationForbidden++; }
497 int64_t modifications() const { return m_modifications; } 495 void leaveModificationForbiddenScope()
498 void registerModification() { m_modifications++; } 496 {
499 // HashTable and collections that build on it do not support modifications 497 ASSERT(m_modificationForbidden > 0);
500 // while there is an iterator in use. The exception is ListHashSet, which 498 m_modificationForbidden--;
501 // has its own iterators that tolerate modification of the underlying set. 499 }
502 void checkModifications(int64_t mods) const { ASSERT(mods == m_modifications ); } 500
501 void registerModification()
502 {
503 ASSERT(!m_modificationForbidden);
504 }
503 #else 505 #else
504 int64_t modifications() const { return 0; } 506 void registerModification() { }
505 void registerModification() {}
506 void checkModifications(int64_t mods) const {}
507 #endif 507 #endif
508 508
509 private: 509 private:
510 static ValueType* allocateTable(unsigned size); 510 static ValueType* allocateTable(unsigned size);
511 static void deleteAllBucketsAndDeallocate(ValueType* table, unsigned size); 511 static void deleteAllBucketsAndDeallocate(ValueType* table, unsigned size);
512 512
513 typedef std::pair<ValueType*, bool> LookupType; 513 typedef std::pair<ValueType*, bool> LookupType;
514 typedef std::pair<LookupType, unsigned> FullLookupType; 514 typedef std::pair<LookupType, unsigned> FullLookupType;
515 515
516 LookupType lookupForWriting(const Key& key) { return lookupForWriting<Identi tyTranslatorType>(key); } 516 LookupType lookupForWriting(const Key& key) { return lookupForWriting<Identi tyTranslatorType>(key); }
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
562 return mask; 562 return mask;
563 } 563 }
564 564
565 void setEnqueued() { m_queueFlag = true; } 565 void setEnqueued() { m_queueFlag = true; }
566 void clearEnqueued() { m_queueFlag = false; } 566 void clearEnqueued() { m_queueFlag = false; }
567 bool enqueued() { return m_queueFlag; } 567 bool enqueued() { return m_queueFlag; }
568 568
569 ValueType* m_table; 569 ValueType* m_table;
570 unsigned m_tableSize; 570 unsigned m_tableSize;
571 unsigned m_keyCount; 571 unsigned m_keyCount;
572 #if ENABLE(ASSERT)
573 unsigned m_deletedCount:30;
574 unsigned m_queueFlag:1;
575 unsigned m_accessForbidden:1;
576 unsigned m_modifications;
577 #else
578 unsigned m_deletedCount:31; 572 unsigned m_deletedCount:31;
579 unsigned m_queueFlag:1; 573 unsigned m_queueFlag:1;
574 #if ENABLE(ASSERT)
575 unsigned m_modificationForbidden;
580 #endif 576 #endif
581 577
582 #if DUMP_HASHTABLE_STATS_PER_TABLE 578 #if DUMP_HASHTABLE_STATS_PER_TABLE
583 public: 579 public:
584 mutable OwnPtr<Stats> m_stats; 580 mutable OwnPtr<Stats> m_stats;
585 #endif 581 #endif
586 582
587 template <WeakHandlingFlag x, typename T, typename U, typename V, typename W , typename X, typename Y, typename Z> friend struct WeakProcessingHashTableHelpe r; 583 template <WeakHandlingFlag x, typename T, typename U, typename V, typename W , typename X, typename Y, typename Z> friend struct WeakProcessingHashTableHelpe r;
588 template <typename T, typename U, typename V, typename W> friend class Linke dHashSet; 584 template <typename T, typename U, typename V, typename W> friend class Linke dHashSet;
589 }; 585 };
590 586
591 template <typename Key, typename Value, typename Extractor, typename HashFunctio ns, typename Traits, typename KeyTraits, typename Allocator> 587 template <typename Key, typename Value, typename Extractor, typename HashFunctio ns, typename Traits, typename KeyTraits, typename Allocator>
592 inline HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Alloca tor>::HashTable() 588 inline HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Alloca tor>::HashTable()
593 : m_table(nullptr) 589 : m_table(nullptr)
594 , m_tableSize(0) 590 , m_tableSize(0)
595 , m_keyCount(0) 591 , m_keyCount(0)
596 , m_deletedCount(0) 592 , m_deletedCount(0)
597 , m_queueFlag(false) 593 , m_queueFlag(false)
598 #if ENABLE(ASSERT) 594 #if ENABLE(ASSERT)
599 , m_accessForbidden(false) 595 , m_modificationForbidden(0)
600 , m_modifications(0)
601 #endif 596 #endif
602 #if DUMP_HASHTABLE_STATS_PER_TABLE 597 #if DUMP_HASHTABLE_STATS_PER_TABLE
603 , m_stats(adoptPtr(new Stats)) 598 , m_stats(adoptPtr(new Stats))
604 #endif 599 #endif
605 { 600 {
606 static_assert(Allocator::isGarbageCollected || (!IsPointerToGarbageCollected Type<Key>::value && !IsPointerToGarbageCollectedType<Value>::value), "Cannot put raw pointers to garbage-collected classes into an off-heap collection."); 601 static_assert(Allocator::isGarbageCollected || (!IsPointerToGarbageCollected Type<Key>::value && !IsPointerToGarbageCollectedType<Value>::value), "Cannot put raw pointers to garbage-collected classes into an off-heap collection.");
607 } 602 }
608 603
609 inline unsigned doubleHash(unsigned key) 604 inline unsigned doubleHash(unsigned key)
610 { 605 {
(...skipping 29 matching lines...) Expand all
640 template <typename HashTranslator, typename T> 635 template <typename HashTranslator, typename T>
641 inline Value* HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::lookup(const T& key) 636 inline Value* HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::lookup(const T& key)
642 { 637 {
643 return const_cast<Value*>(const_cast<const HashTable*>(this)->lookup<HashTra nslator>(key)); 638 return const_cast<Value*>(const_cast<const HashTable*>(this)->lookup<HashTra nslator>(key));
644 } 639 }
645 640
646 template <typename Key, typename Value, typename Extractor, typename HashFunctio ns, typename Traits, typename KeyTraits, typename Allocator> 641 template <typename Key, typename Value, typename Extractor, typename HashFunctio ns, typename Traits, typename KeyTraits, typename Allocator>
647 template <typename HashTranslator, typename T> 642 template <typename HashTranslator, typename T>
648 inline const Value* HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyT raits, Allocator>::lookup(const T& key) const 643 inline const Value* HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyT raits, Allocator>::lookup(const T& key) const
649 { 644 {
650 ASSERT(!m_accessForbidden);
651 ASSERT((HashTableKeyChecker<HashTranslator, KeyTraits, HashFunctions::safeTo CompareToEmptyOrDeleted>::checkKey(key))); 645 ASSERT((HashTableKeyChecker<HashTranslator, KeyTraits, HashFunctions::safeTo CompareToEmptyOrDeleted>::checkKey(key)));
652 const ValueType* table = m_table; 646 const ValueType* table = m_table;
653 if (!table) 647 if (!table)
654 return nullptr; 648 return nullptr;
655 649
656 size_t k = 0; 650 size_t k = 0;
657 size_t sizeMask = tableSizeMask(); 651 size_t sizeMask = tableSizeMask();
658 unsigned h = HashTranslator::hash(key); 652 unsigned h = HashTranslator::hash(key);
659 size_t i = h & sizeMask; 653 size_t i = h & sizeMask;
660 654
(...skipping 19 matching lines...) Expand all
680 if (!k) 674 if (!k)
681 k = 1 | doubleHash(h); 675 k = 1 | doubleHash(h);
682 i = (i + k) & sizeMask; 676 i = (i + k) & sizeMask;
683 } 677 }
684 } 678 }
685 679
686 template <typename Key, typename Value, typename Extractor, typename HashFunctio ns, typename Traits, typename KeyTraits, typename Allocator> 680 template <typename Key, typename Value, typename Extractor, typename HashFunctio ns, typename Traits, typename KeyTraits, typename Allocator>
687 template <typename HashTranslator, typename T> 681 template <typename HashTranslator, typename T>
688 inline typename HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTrait s, Allocator>::LookupType HashTable<Key, Value, Extractor, HashFunctions, Traits , KeyTraits, Allocator>::lookupForWriting(const T& key) 682 inline typename HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTrait s, Allocator>::LookupType HashTable<Key, Value, Extractor, HashFunctions, Traits , KeyTraits, Allocator>::lookupForWriting(const T& key)
689 { 683 {
690 ASSERT(!m_accessForbidden);
691 ASSERT(m_table); 684 ASSERT(m_table);
692 registerModification(); 685 registerModification();
693 686
694 ValueType* table = m_table; 687 ValueType* table = m_table;
695 size_t k = 0; 688 size_t k = 0;
696 size_t sizeMask = tableSizeMask(); 689 size_t sizeMask = tableSizeMask();
697 unsigned h = HashTranslator::hash(key); 690 unsigned h = HashTranslator::hash(key);
698 size_t i = h & sizeMask; 691 size_t i = h & sizeMask;
699 692
700 UPDATE_ACCESS_COUNTS(); 693 UPDATE_ACCESS_COUNTS();
(...skipping 22 matching lines...) Expand all
723 if (!k) 716 if (!k)
724 k = 1 | doubleHash(h); 717 k = 1 | doubleHash(h);
725 i = (i + k) & sizeMask; 718 i = (i + k) & sizeMask;
726 } 719 }
727 } 720 }
728 721
729 template <typename Key, typename Value, typename Extractor, typename HashFunctio ns, typename Traits, typename KeyTraits, typename Allocator> 722 template <typename Key, typename Value, typename Extractor, typename HashFunctio ns, typename Traits, typename KeyTraits, typename Allocator>
730 template <typename HashTranslator, typename T> 723 template <typename HashTranslator, typename T>
731 inline typename HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTrait s, Allocator>::FullLookupType HashTable<Key, Value, Extractor, HashFunctions, Tr aits, KeyTraits, Allocator>::fullLookupForWriting(const T& key) 724 inline typename HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTrait s, Allocator>::FullLookupType HashTable<Key, Value, Extractor, HashFunctions, Tr aits, KeyTraits, Allocator>::fullLookupForWriting(const T& key)
732 { 725 {
733 ASSERT(!m_accessForbidden);
734 ASSERT(m_table); 726 ASSERT(m_table);
735 registerModification(); 727 registerModification();
736 728
737 ValueType* table = m_table; 729 ValueType* table = m_table;
738 size_t k = 0; 730 size_t k = 0;
739 size_t sizeMask = tableSizeMask(); 731 size_t sizeMask = tableSizeMask();
740 unsigned h = HashTranslator::hash(key); 732 unsigned h = HashTranslator::hash(key);
741 size_t i = h & sizeMask; 733 size_t i = h & sizeMask;
742 734
743 UPDATE_ACCESS_COUNTS(); 735 UPDATE_ACCESS_COUNTS();
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
794 template <typename Key, typename Value, typename Extractor, typename HashFunctio ns, typename Traits, typename KeyTraits, typename Allocator> 786 template <typename Key, typename Value, typename Extractor, typename HashFunctio ns, typename Traits, typename KeyTraits, typename Allocator>
795 inline void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, A llocator>::initializeBucket(ValueType& bucket) 787 inline void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, A llocator>::initializeBucket(ValueType& bucket)
796 { 788 {
797 HashTableBucketInitializer<Traits::emptyValueIsZero>::template initialize<Tr aits>(bucket); 789 HashTableBucketInitializer<Traits::emptyValueIsZero>::template initialize<Tr aits>(bucket);
798 } 790 }
799 791
800 template <typename Key, typename Value, typename Extractor, typename HashFunctio ns, typename Traits, typename KeyTraits, typename Allocator> 792 template <typename Key, typename Value, typename Extractor, typename HashFunctio ns, typename Traits, typename KeyTraits, typename Allocator>
801 template <typename HashTranslator, typename T, typename Extra> 793 template <typename HashTranslator, typename T, typename Extra>
802 typename HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allo cator>::AddResult HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTra its, Allocator>::add(T&& key, Extra&& extra) 794 typename HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allo cator>::AddResult HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTra its, Allocator>::add(T&& key, Extra&& extra)
803 { 795 {
804 ASSERT(!m_accessForbidden);
805 ASSERT(Allocator::isAllocationAllowed()); 796 ASSERT(Allocator::isAllocationAllowed());
806 if (!m_table) 797 if (!m_table)
807 expand(); 798 expand();
808 799
809 ASSERT(m_table); 800 ASSERT(m_table);
810 801
811 ValueType* table = m_table; 802 ValueType* table = m_table;
812 size_t k = 0; 803 size_t k = 0;
813 size_t sizeMask = tableSizeMask(); 804 size_t sizeMask = tableSizeMask();
814 unsigned h = HashTranslator::hash(key); 805 unsigned h = HashTranslator::hash(key);
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
860 if (shouldExpand()) 851 if (shouldExpand())
861 entry = expand(entry); 852 entry = expand(entry);
862 853
863 return AddResult(this, entry, true); 854 return AddResult(this, entry, true);
864 } 855 }
865 856
866 template <typename Key, typename Value, typename Extractor, typename HashFunctio ns, typename Traits, typename KeyTraits, typename Allocator> 857 template <typename Key, typename Value, typename Extractor, typename HashFunctio ns, typename Traits, typename KeyTraits, typename Allocator>
867 template <typename HashTranslator, typename T, typename Extra> 858 template <typename HashTranslator, typename T, typename Extra>
868 typename HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allo cator>::AddResult HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTra its, Allocator>::addPassingHashCode(T&& key, Extra&& extra) 859 typename HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allo cator>::AddResult HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTra its, Allocator>::addPassingHashCode(T&& key, Extra&& extra)
869 { 860 {
870 ASSERT(!m_accessForbidden);
871 ASSERT(Allocator::isAllocationAllowed()); 861 ASSERT(Allocator::isAllocationAllowed());
872 if (!m_table) 862 if (!m_table)
873 expand(); 863 expand();
874 864
875 FullLookupType lookupResult = fullLookupForWriting<HashTranslator>(key); 865 FullLookupType lookupResult = fullLookupForWriting<HashTranslator>(key);
876 866
877 ValueType* entry = lookupResult.first.first; 867 ValueType* entry = lookupResult.first.first;
878 bool found = lookupResult.first.second; 868 bool found = lookupResult.first.second;
879 unsigned h = lookupResult.second; 869 unsigned h = lookupResult.second;
880 870
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
950 void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocato r>::remove(ValueType* pos) 940 void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocato r>::remove(ValueType* pos)
951 { 941 {
952 registerModification(); 942 registerModification();
953 #if DUMP_HASHTABLE_STATS 943 #if DUMP_HASHTABLE_STATS
954 atomicIncrement(&HashTableStats::numRemoves); 944 atomicIncrement(&HashTableStats::numRemoves);
955 #endif 945 #endif
956 #if DUMP_HASHTABLE_STATS_PER_TABLE 946 #if DUMP_HASHTABLE_STATS_PER_TABLE
957 ++m_stats->numRemoves; 947 ++m_stats->numRemoves;
958 #endif 948 #endif
959 949
960 ASSERT(!m_accessForbidden);
961 #if ENABLE(ASSERT)
962 m_accessForbidden = true;
963 #endif
964 deleteBucket(*pos); 950 deleteBucket(*pos);
965 #if ENABLE(ASSERT)
966 m_accessForbidden = false;
967 #endif
968 ++m_deletedCount; 951 ++m_deletedCount;
969 --m_keyCount; 952 --m_keyCount;
970 953
971 if (shouldShrink()) 954 if (shouldShrink())
972 shrink(); 955 shrink();
973 } 956 }
974 957
975 template <typename Key, typename Value, typename Extractor, typename HashFunctio ns, typename Traits, typename KeyTraits, typename Allocator> 958 template <typename Key, typename Value, typename Extractor, typename HashFunctio ns, typename Traits, typename KeyTraits, typename Allocator>
976 inline void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, A llocator>::remove(iterator it) 959 inline void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, A llocator>::remove(iterator it)
977 { 960 {
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after
1093 m_table = temporaryTable; 1076 m_table = temporaryTable;
1094 1077
1095 if (Traits::emptyValueIsZero) { 1078 if (Traits::emptyValueIsZero) {
1096 memset(originalTable, 0, newTableSize * sizeof(ValueType)); 1079 memset(originalTable, 0, newTableSize * sizeof(ValueType));
1097 } else { 1080 } else {
1098 for (unsigned i = 0; i < newTableSize; i++) 1081 for (unsigned i = 0; i < newTableSize; i++)
1099 initializeBucket(originalTable[i]); 1082 initializeBucket(originalTable[i]);
1100 } 1083 }
1101 newEntry = rehashTo(originalTable, newTableSize, newEntry); 1084 newEntry = rehashTo(originalTable, newTableSize, newEntry);
1102 1085
1103 ASSERT(!m_accessForbidden);
1104 #if ENABLE(ASSERT)
1105 m_accessForbidden = true;
1106 #endif
1107 deleteAllBucketsAndDeallocate(temporaryTable, oldTableSize); 1086 deleteAllBucketsAndDeallocate(temporaryTable, oldTableSize);
1108 #if ENABLE(ASSERT)
1109 m_accessForbidden = false;
1110 #endif
1111
1112 return newEntry; 1087 return newEntry;
1113 } 1088 }
1114 1089
1115 template <typename Key, typename Value, typename Extractor, typename HashFunctio ns, typename Traits, typename KeyTraits, typename Allocator> 1090 template <typename Key, typename Value, typename Extractor, typename HashFunctio ns, typename Traits, typename KeyTraits, typename Allocator>
1116 Value* HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Alloca tor>::rehashTo(ValueType* newTable, unsigned newTableSize, Value* entry) 1091 Value* HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Alloca tor>::rehashTo(ValueType* newTable, unsigned newTableSize, Value* entry)
1117 { 1092 {
1118 unsigned oldTableSize = m_tableSize; 1093 unsigned oldTableSize = m_tableSize;
1119 ValueType* oldTable = m_table; 1094 ValueType* oldTable = m_table;
1120 1095
1121 #if DUMP_HASHTABLE_STATS 1096 #if DUMP_HASHTABLE_STATS
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
1171 if (Allocator::isGarbageCollected && newTableSize > oldTableSize) { 1146 if (Allocator::isGarbageCollected && newTableSize > oldTableSize) {
1172 bool success; 1147 bool success;
1173 Value* newEntry = expandBuffer(newTableSize, entry, success); 1148 Value* newEntry = expandBuffer(newTableSize, entry, success);
1174 if (success) 1149 if (success)
1175 return newEntry; 1150 return newEntry;
1176 } 1151 }
1177 1152
1178 ValueType* newTable = allocateTable(newTableSize); 1153 ValueType* newTable = allocateTable(newTableSize);
1179 Value* newEntry = rehashTo(newTable, newTableSize, entry); 1154 Value* newEntry = rehashTo(newTable, newTableSize, entry);
1180 1155
1181 ASSERT(!m_accessForbidden);
1182 #if ENABLE(ASSERT)
1183 m_accessForbidden = true;
1184 #endif
1185 deleteAllBucketsAndDeallocate(oldTable, oldTableSize); 1156 deleteAllBucketsAndDeallocate(oldTable, oldTableSize);
1186 #if ENABLE(ASSERT)
1187 m_accessForbidden = false;
1188 #endif
1189
1190 return newEntry; 1157 return newEntry;
1191 } 1158 }
1192 1159
1193 template <typename Key, typename Value, typename Extractor, typename HashFunctio ns, typename Traits, typename KeyTraits, typename Allocator> 1160 template <typename Key, typename Value, typename Extractor, typename HashFunctio ns, typename Traits, typename KeyTraits, typename Allocator>
1194 void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocato r>::clear() 1161 void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocato r>::clear()
1195 { 1162 {
1196 registerModification(); 1163 registerModification();
1197 if (!m_table) 1164 if (!m_table)
1198 return; 1165 return;
1199 1166
1200 ASSERT(!m_accessForbidden);
1201 #if ENABLE(ASSERT)
1202 m_accessForbidden = true;
1203 #endif
1204 deleteAllBucketsAndDeallocate(m_table, m_tableSize); 1167 deleteAllBucketsAndDeallocate(m_table, m_tableSize);
1205 #if ENABLE(ASSERT)
1206 m_accessForbidden = false;
1207 #endif
1208 m_table = nullptr; 1168 m_table = nullptr;
1209 m_tableSize = 0; 1169 m_tableSize = 0;
1210 m_keyCount = 0; 1170 m_keyCount = 0;
1211 } 1171 }
1212 1172
1213 template <typename Key, typename Value, typename Extractor, typename HashFunctio ns, typename Traits, typename KeyTraits, typename Allocator> 1173 template <typename Key, typename Value, typename Extractor, typename HashFunctio ns, typename Traits, typename KeyTraits, typename Allocator>
1214 HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::H ashTable(const HashTable& other) 1174 HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::H ashTable(const HashTable& other)
1215 : m_table(nullptr) 1175 : m_table(nullptr)
1216 , m_tableSize(0) 1176 , m_tableSize(0)
1217 , m_keyCount(0) 1177 , m_keyCount(0)
1218 , m_deletedCount(0) 1178 , m_deletedCount(0)
1219 , m_queueFlag(false) 1179 , m_queueFlag(false)
1220 #if ENABLE(ASSERT) 1180 #if ENABLE(ASSERT)
1221 , m_accessForbidden(false) 1181 , m_modificationForbidden(0)
1222 , m_modifications(0)
1223 #endif 1182 #endif
1224 #if DUMP_HASHTABLE_STATS_PER_TABLE 1183 #if DUMP_HASHTABLE_STATS_PER_TABLE
1225 , m_stats(adoptPtr(new Stats(*other.m_stats))) 1184 , m_stats(adoptPtr(new Stats(*other.m_stats)))
1226 #endif 1185 #endif
1227 { 1186 {
1228 // Copy the hash table the dumb way, by adding each element to the new 1187 // Copy the hash table the dumb way, by adding each element to the new
1229 // table. It might be more efficient to copy the table slots, but it's not 1188 // table. It might be more efficient to copy the table slots, but it's not
1230 // clear that efficiency is needed. 1189 // clear that efficiency is needed.
1231 const_iterator end = other.end(); 1190 const_iterator end = other.end();
1232 for (const_iterator it = other.begin(); it != end; ++it) 1191 for (const_iterator it = other.begin(); it != end; ++it)
1233 add(*it); 1192 add(*it);
1234 } 1193 }
1235 1194
1236 template <typename Key, typename Value, typename Extractor, typename HashFunctio ns, typename Traits, typename KeyTraits, typename Allocator> 1195 template <typename Key, typename Value, typename Extractor, typename HashFunctio ns, typename Traits, typename KeyTraits, typename Allocator>
1237 HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::H ashTable(HashTable&& other) 1196 HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::H ashTable(HashTable&& other)
1238 : m_table(nullptr) 1197 : m_table(nullptr)
1239 , m_tableSize(0) 1198 , m_tableSize(0)
1240 , m_keyCount(0) 1199 , m_keyCount(0)
1241 , m_deletedCount(0) 1200 , m_deletedCount(0)
1242 , m_queueFlag(false) 1201 , m_queueFlag(false)
1243 #if ENABLE(ASSERT) 1202 #if ENABLE(ASSERT)
1244 , m_accessForbidden(false) 1203 , m_modificationForbidden(0)
1245 , m_modifications(0)
1246 #endif 1204 #endif
1247 #if DUMP_HASHTABLE_STATS_PER_TABLE 1205 #if DUMP_HASHTABLE_STATS_PER_TABLE
1248 , m_stats(adoptPtr(new Stats(*other.m_stats))) 1206 , m_stats(adoptPtr(new Stats(*other.m_stats)))
1249 #endif 1207 #endif
1250 { 1208 {
1251 swap(other); 1209 swap(other);
1252 } 1210 }
1253 1211
1254 1212
1255 template <typename Key, typename Value, typename Extractor, typename HashFunctio ns, typename Traits, typename KeyTraits, typename Allocator> 1213 template <typename Key, typename Value, typename Extractor, typename HashFunctio ns, typename Traits, typename KeyTraits, typename Allocator>
1256 void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocato r>::swap(HashTable& other) 1214 void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocato r>::swap(HashTable& other)
1257 { 1215 {
1258 ASSERT(!m_accessForbidden); 1216 registerModification();
1259 std::swap(m_table, other.m_table); 1217 std::swap(m_table, other.m_table);
1260 std::swap(m_tableSize, other.m_tableSize); 1218 std::swap(m_tableSize, other.m_tableSize);
1261 std::swap(m_keyCount, other.m_keyCount); 1219 std::swap(m_keyCount, other.m_keyCount);
1262 // std::swap does not work for bit fields. 1220 // std::swap does not work for bit fields.
1263 unsigned deleted = m_deletedCount; 1221 unsigned deleted = m_deletedCount;
1264 m_deletedCount = other.m_deletedCount; 1222 m_deletedCount = other.m_deletedCount;
1265 other.m_deletedCount = deleted; 1223 other.m_deletedCount = deleted;
1266 ASSERT(!m_queueFlag); 1224 ASSERT(!m_queueFlag);
1267 ASSERT(!other.m_queueFlag); 1225 ASSERT(!other.m_queueFlag);
1268 1226
1269 #if ENABLE(ASSERT) 1227 #if ENABLE(ASSERT)
1270 std::swap(m_modifications, other.m_modifications); 1228 std::swap(m_modificationForbidden, other.m_modificationForbidden);
1271 #endif 1229 #endif
1272 1230
1273 #if DUMP_HASHTABLE_STATS_PER_TABLE 1231 #if DUMP_HASHTABLE_STATS_PER_TABLE
1274 m_stats.swap(other.m_stats); 1232 m_stats.swap(other.m_stats);
1275 #endif 1233 #endif
1276 } 1234 }
1277 1235
1278 template <typename Key, typename Value, typename Extractor, typename HashFunctio ns, typename Traits, typename KeyTraits, typename Allocator> 1236 template <typename Key, typename Value, typename Extractor, typename HashFunctio ns, typename Traits, typename KeyTraits, typename Allocator>
1279 HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>& H ashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::op erator=(const HashTable& other) 1237 HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>& H ashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::op erator=(const HashTable& other)
1280 { 1238 {
1281 HashTable tmp(other); 1239 HashTable tmp(other);
1282 swap(tmp); 1240 swap(tmp);
1283 return *this; 1241 return *this;
1284 } 1242 }
1285 1243
1286 template <typename Key, typename Value, typename Extractor, typename HashFunctio ns, typename Traits, typename KeyTraits, typename Allocator> 1244 template <typename Key, typename Value, typename Extractor, typename HashFunctio ns, typename Traits, typename KeyTraits, typename Allocator>
1287 HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>& H ashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::op erator=(HashTable&& other) 1245 HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>& H ashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::op erator=(HashTable&& other)
1288 { 1246 {
1289 swap(other); 1247 swap(other);
1290 return *this; 1248 return *this;
1291 } 1249 }
1292 1250
1251 #if ENABLE(ASSERT)
1252 template <typename HashTableType>
1253 HashTableModificationForbiddenScope<HashTableType>::HashTableModificationForbidd enScope()
1254 : m_container(nullptr)
1255 {
1256 }
1257
1258 template <typename HashTableType>
1259 HashTableModificationForbiddenScope<HashTableType>::HashTableModificationForbidd enScope(const HashTableType* container)
1260 : m_container(const_cast<HashTableType*>(container))
1261 {
1262 if (m_container)
1263 m_container->enterModificationForbiddenScope();
1264 }
1265
1266 template <typename HashTableType>
1267 HashTableModificationForbiddenScope<HashTableType>::HashTableModificationForbidd enScope(const HashTableModificationForbiddenScope& other)
1268 : m_container(other.m_container)
1269 {
1270 if (m_container)
1271 m_container->enterModificationForbiddenScope();
1272 }
1273
1274 template <typename HashTableType>
1275 HashTableModificationForbiddenScope<HashTableType>::~HashTableModificationForbid denScope()
1276 {
1277 leaveScope();
1278 }
1279
1280 template <typename HashTableType>
1281 void HashTableModificationForbiddenScope<HashTableType>::leaveScope()
1282 {
1283 if (!m_container)
1284 return;
1285 m_container->leaveModificationForbiddenScope();
1286 m_container = nullptr;
1287 }
1288 #endif
1289
1293 template <WeakHandlingFlag weakHandlingFlag, typename Key, typename Value, typen ame Extractor, typename HashFunctions, typename Traits, typename KeyTraits, type name Allocator> 1290 template <WeakHandlingFlag weakHandlingFlag, typename Key, typename Value, typen ame Extractor, typename HashFunctions, typename Traits, typename KeyTraits, type name Allocator>
1294 struct WeakProcessingHashTableHelper; 1291 struct WeakProcessingHashTableHelper;
1295 1292
1296 template <typename Key, typename Value, typename Extractor, typename HashFunctio ns, typename Traits, typename KeyTraits, typename Allocator> 1293 template <typename Key, typename Value, typename Extractor, typename HashFunctio ns, typename Traits, typename KeyTraits, typename Allocator>
1297 struct WeakProcessingHashTableHelper<NoWeakHandlingInCollections, Key, Value, Ex tractor, HashFunctions, Traits, KeyTraits, Allocator> { 1294 struct WeakProcessingHashTableHelper<NoWeakHandlingInCollections, Key, Value, Ex tractor, HashFunctions, Traits, KeyTraits, Allocator> {
1298 STATIC_ONLY(WeakProcessingHashTableHelper); 1295 STATIC_ONLY(WeakProcessingHashTableHelper);
1299 static void process(typename Allocator::Visitor* visitor, void* closure) {} 1296 static void process(typename Allocator::Visitor* visitor, void* closure) {}
1300 static void ephemeronIteration(typename Allocator::Visitor* visitor, void* c losure) {} 1297 static void ephemeronIteration(typename Allocator::Visitor* visitor, void* c losure) {}
1301 static void ephemeronIterationDone(typename Allocator::Visitor* visitor, voi d* closure) {} 1298 static void ephemeronIterationDone(typename Allocator::Visitor* visitor, voi d* closure) {}
1302 }; 1299 };
(...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after
1522 CollectionIterator end(toBeRemoved.end()); 1519 CollectionIterator end(toBeRemoved.end());
1523 for (CollectionIterator it(toBeRemoved.begin()); it != end; ++it) 1520 for (CollectionIterator it(toBeRemoved.begin()); it != end; ++it)
1524 collection.remove(*it); 1521 collection.remove(*it);
1525 } 1522 }
1526 1523
1527 } // namespace WTF 1524 } // namespace WTF
1528 1525
1529 #include "wtf/HashIterators.h" 1526 #include "wtf/HashIterators.h"
1530 1527
1531 #endif // WTF_HashTable_h 1528 #endif // WTF_HashTable_h
OLDNEW
« no previous file with comments | « no previous file | third_party/WebKit/Source/wtf/LinkedHashSet.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698