| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2005, 2006, 2007, 2008, 2011, 2012 Apple Inc. All rights reserv
ed. | 2 * Copyright (C) 2005, 2006, 2007, 2008, 2011, 2012 Apple Inc. All rights reserv
ed. |
| 3 * Copyright (C) 2008 David Levin <levin@chromium.org> | 3 * Copyright (C) 2008 David Levin <levin@chromium.org> |
| 4 * | 4 * |
| 5 * This library is free software; you can redistribute it and/or | 5 * This library is free software; you can redistribute it and/or |
| 6 * modify it under the terms of the GNU Library General Public | 6 * modify it under the terms of the GNU Library General Public |
| 7 * License as published by the Free Software Foundation; either | 7 * License as published by the Free Software Foundation; either |
| 8 * version 2 of the License, or (at your option) any later version. | 8 * version 2 of the License, or (at your option) any later version. |
| 9 * | 9 * |
| 10 * This library is distributed in the hope that it will be useful, | 10 * This library is distributed in the hope that it will be useful, |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |