Chromium Code Reviews| 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 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 78 | 78 |
| 79 friend class HashTable<Key, Value, Extractor, HashFunctions, Traits, Key Traits, Allocator>; | 79 friend class HashTable<Key, Value, Extractor, HashFunctions, Traits, Key Traits, Allocator>; |
| 80 friend class HashTableIterator<Key, Value, Extractor, HashFunctions, Tra its, KeyTraits, Allocator>; | 80 friend class HashTableIterator<Key, Value, Extractor, HashFunctions, Tra its, KeyTraits, Allocator>; |
| 81 | 81 |
| 82 void skipEmptyBuckets() | 82 void skipEmptyBuckets() |
| 83 { | 83 { |
| 84 while (m_position != m_endPosition && HashTableType::isEmptyOrDelete dBucket(*m_position)) | 84 while (m_position != m_endPosition && HashTableType::isEmptyOrDelete dBucket(*m_position)) |
| 85 ++m_position; | 85 ++m_position; |
| 86 } | 86 } |
| 87 | 87 |
| 88 HashTableConstIterator(PointerType position, PointerType endPosition) | 88 HashTableConstIterator(PointerType position, PointerType endPosition, co nst HashTableType* container) |
| 89 : m_position(position), m_endPosition(endPosition) | 89 : m_position(position) |
| 90 , m_endPosition(endPosition) | |
| 91 #ifndef NDEBUG | |
| 92 , m_container(container) | |
| 93 , m_containerModifications(container->modifications()) | |
| 94 #endif | |
| 90 { | 95 { |
| 91 skipEmptyBuckets(); | 96 skipEmptyBuckets(); |
| 92 } | 97 } |
| 93 | 98 |
| 94 HashTableConstIterator(PointerType position, PointerType endPosition, Ha shItemKnownGoodTag) | 99 HashTableConstIterator(PointerType position, PointerType endPosition, co nst HashTableType* container, HashItemKnownGoodTag) |
| 95 : m_position(position), m_endPosition(endPosition) | 100 : m_position(position) |
| 101 , m_endPosition(endPosition) | |
| 102 #ifndef NDEBUG | |
|
Mikhail
2014/03/31 14:08:09
Since the actual check is assertion, maybe it's be
Erik Corry
2014/03/31 19:45:38
Done.
| |
| 103 , m_container(container) | |
| 104 , m_containerModifications(container->modifications()) | |
| 105 #endif | |
| 96 { | 106 { |
| 97 } | 107 } |
| 98 | 108 |
| 109 void checkModifications() const | |
| 110 { | |
| 111 ASSERT(m_containerModifications == m_container->modifications()); | |
| 112 } | |
| 113 | |
| 99 public: | 114 public: |
| 100 HashTableConstIterator() | 115 HashTableConstIterator() |
| 101 { | 116 { |
| 102 } | 117 } |
| 103 | 118 |
| 104 GetType get() const | 119 GetType get() const |
| 105 { | 120 { |
| 121 checkModifications(); | |
| 106 return m_position; | 122 return m_position; |
| 107 } | 123 } |
| 108 typename Traits::IteratorConstReferenceType operator*() const { return T raits::getToReferenceConstConversion(get()); } | 124 typename Traits::IteratorConstReferenceType operator*() const { return T raits::getToReferenceConstConversion(get()); } |
| 109 GetType operator->() const { return get(); } | 125 GetType operator->() const { return get(); } |
| 110 | 126 |
| 111 const_iterator& operator++() | 127 const_iterator& operator++() |
| 112 { | 128 { |
| 113 ASSERT(m_position != m_endPosition); | 129 ASSERT(m_position != m_endPosition); |
| 130 checkModifications(); | |
| 114 ++m_position; | 131 ++m_position; |
| 115 skipEmptyBuckets(); | 132 skipEmptyBuckets(); |
| 116 return *this; | 133 return *this; |
| 117 } | 134 } |
| 118 | 135 |
| 119 // postfix ++ intentionally omitted | 136 // postfix ++ intentionally omitted |
| 120 | 137 |
| 121 // Comparison. | 138 // Comparison. |
| 122 bool operator==(const const_iterator& other) const | 139 bool operator==(const const_iterator& other) const |
| 123 { | 140 { |
| 124 return m_position == other.m_position; | 141 return m_position == other.m_position; |
| 125 } | 142 } |
| 126 bool operator!=(const const_iterator& other) const | 143 bool operator!=(const const_iterator& other) const |
| 127 { | 144 { |
| 128 return m_position != other.m_position; | 145 return m_position != other.m_position; |
| 129 } | 146 } |
| 130 bool operator==(const iterator& other) const | 147 bool operator==(const iterator& other) const |
| 131 { | 148 { |
| 132 return *this == static_cast<const_iterator>(other); | 149 return *this == static_cast<const_iterator>(other); |
| 133 } | 150 } |
| 134 bool operator!=(const iterator& other) const | 151 bool operator!=(const iterator& other) const |
| 135 { | 152 { |
| 136 return *this != static_cast<const_iterator>(other); | 153 return *this != static_cast<const_iterator>(other); |
| 137 } | 154 } |
| 138 | 155 |
| 139 private: | 156 private: |
| 140 PointerType m_position; | 157 PointerType m_position; |
| 141 PointerType m_endPosition; | 158 PointerType m_endPosition; |
| 159 #ifndef NDEBUG | |
| 160 const HashTableType* m_container; | |
| 161 int64_t m_containerModifications; | |
| 162 #endif | |
| 142 }; | 163 }; |
| 143 | 164 |
| 144 template<typename Key, typename Value, typename Extractor, typename HashFunc tions, typename Traits, typename KeyTraits, typename Allocator> | 165 template<typename Key, typename Value, typename Extractor, typename HashFunc tions, typename Traits, typename KeyTraits, typename Allocator> |
| 145 class HashTableIterator { | 166 class HashTableIterator { |
| 146 private: | 167 private: |
| 168 typedef HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTrait s, Allocator> HashTableType; | |
| 147 typedef HashTableIterator<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator> iterator; | 169 typedef HashTableIterator<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator> iterator; |
| 148 typedef HashTableConstIterator<Key, Value, Extractor, HashFunctions, Tra its, KeyTraits, Allocator> const_iterator; | 170 typedef HashTableConstIterator<Key, Value, Extractor, HashFunctions, Tra its, KeyTraits, Allocator> const_iterator; |
| 149 typedef Value ValueType; | 171 typedef Value ValueType; |
| 150 typedef typename Traits::IteratorGetType GetType; | 172 typedef typename Traits::IteratorGetType GetType; |
| 151 typedef ValueType* PointerType; | 173 typedef ValueType* PointerType; |
| 152 | 174 |
| 153 friend class HashTable<Key, Value, Extractor, HashFunctions, Traits, Key Traits, Allocator>; | 175 friend class HashTable<Key, Value, Extractor, HashFunctions, Traits, Key Traits, Allocator>; |
| 154 | 176 |
| 155 HashTableIterator(PointerType pos, PointerType end) : m_iterator(pos, en d) { } | 177 HashTableIterator(PointerType pos, PointerType end, const HashTableType* container) : m_iterator(pos, end, container) { } |
| 156 HashTableIterator(PointerType pos, PointerType end, HashItemKnownGoodTag tag) : m_iterator(pos, end, tag) { } | 178 HashTableIterator(PointerType pos, PointerType end, const HashTableType* container, HashItemKnownGoodTag tag) : m_iterator(pos, end, container, tag) { } |
| 157 | 179 |
| 158 public: | 180 public: |
| 159 HashTableIterator() { } | 181 HashTableIterator() { } |
| 160 | 182 |
| 161 // default copy, assignment and destructor are OK | 183 // default copy, assignment and destructor are OK |
| 162 | 184 |
| 163 GetType get() const { return const_cast<GetType>(m_iterator.get()); } | 185 GetType get() const { return const_cast<GetType>(m_iterator.get()); } |
| 164 typename Traits::IteratorReferenceType operator*() const { return Traits ::getToReferenceConversion(get()); } | 186 typename Traits::IteratorReferenceType operator*() const { return Traits ::getToReferenceConversion(get()); } |
| 165 GetType operator->() const { return get(); } | 187 GetType operator->() const { return get(); } |
| 166 | 188 |
| (...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 342 | 364 |
| 343 static bool isEmptyBucket(const ValueType& value) { return isHashTraitsE mptyValue<KeyTraits>(Extractor::extract(value)); } | 365 static bool isEmptyBucket(const ValueType& value) { return isHashTraitsE mptyValue<KeyTraits>(Extractor::extract(value)); } |
| 344 static bool isDeletedBucket(const ValueType& value) { return KeyTraits:: isDeletedValue(Extractor::extract(value)); } | 366 static bool isDeletedBucket(const ValueType& value) { return KeyTraits:: isDeletedValue(Extractor::extract(value)); } |
| 345 static bool isEmptyOrDeletedBucket(const ValueType& value) { return Hash TableHelper<ValueType, Extractor, KeyTraits>:: isEmptyOrDeletedBucket(value); } | 367 static bool isEmptyOrDeletedBucket(const ValueType& value) { return Hash TableHelper<ValueType, Extractor, KeyTraits>:: isEmptyOrDeletedBucket(value); } |
| 346 | 368 |
| 347 ValueType* lookup(KeyPeekInType key) { return lookup<IdentityTranslatorT ype>(key); } | 369 ValueType* lookup(KeyPeekInType key) { return lookup<IdentityTranslatorT ype>(key); } |
| 348 template<typename HashTranslator, typename T> ValueType* lookup(const T& ); | 370 template<typename HashTranslator, typename T> ValueType* lookup(const T& ); |
| 349 | 371 |
| 350 void trace(typename Allocator::Visitor*); | 372 void trace(typename Allocator::Visitor*); |
| 351 | 373 |
| 374 #ifdef NDEBUG | |
| 375 int64_t modifications() const { return 0; } | |
| 376 void registerModification() { } | |
| 377 void checkModifications(int64_t mods) const { } | |
|
Mads Ager (chromium)
2014/03/31 14:18:47
mods -> modifications (or better, remove the name)
Erik Corry
2014/03/31 19:45:38
gone
| |
| 378 #else | |
| 379 int64_t modifications() const { return m_modifications; } | |
| 380 void registerModification() { m_modifications++; } | |
|
Mikhail
2014/03/31 14:08:09
modified() ?
Erik Corry
2014/03/31 19:45:38
That looks more like a question than an action to
| |
| 381 // HashTable and collections that build on it do not support | |
| 382 // modifications while there is an iterator in use. The exception is | |
| 383 // ListHashSet, which has its own iterators that tolerate modification | |
| 384 // of the underlying set. | |
| 385 void checkModifications(int64_t mods) const { ASSERT(mods == m_modificat ions); } | |
|
Mikhail
2014/03/31 14:08:09
is this method used?
Mads Ager (chromium)
2014/03/31 14:18:47
mods -> modifications (but as Mikhail writes, it l
Erik Corry
2014/03/31 19:45:38
It's not used yet, so I removed it for now.
| |
| 386 #endif | |
| 387 | |
| 352 private: | 388 private: |
| 353 static ValueType* allocateTable(unsigned size); | 389 static ValueType* allocateTable(unsigned size); |
| 354 static void deallocateTable(ValueType* table, unsigned size); | 390 static void deallocateTable(ValueType* table, unsigned size); |
| 355 | 391 |
| 356 typedef std::pair<ValueType*, bool> LookupType; | 392 typedef std::pair<ValueType*, bool> LookupType; |
| 357 typedef std::pair<LookupType, unsigned> FullLookupType; | 393 typedef std::pair<LookupType, unsigned> FullLookupType; |
| 358 | 394 |
| 359 LookupType lookupForWriting(const Key& key) { return lookupForWriting<Id entityTranslatorType>(key); }; | 395 LookupType lookupForWriting(const Key& key) { return lookupForWriting<Id entityTranslatorType>(key); }; |
| 360 template<typename HashTranslator, typename T> FullLookupType fullLookupF orWriting(const T&); | 396 template<typename HashTranslator, typename T> FullLookupType fullLookupF orWriting(const T&); |
| 361 template<typename HashTranslator, typename T> LookupType lookupForWritin g(const T&); | 397 template<typename HashTranslator, typename T> LookupType lookupForWritin g(const T&); |
| 362 | 398 |
| 363 void remove(ValueType*); | 399 void remove(ValueType*); |
| 364 | 400 |
| 365 bool shouldExpand() const { return (m_keyCount + m_deletedCount) * m_max Load >= m_tableSize; } | 401 bool shouldExpand() const { return (m_keyCount + m_deletedCount) * m_max Load >= m_tableSize; } |
| 366 bool mustRehashInPlace() const { return m_keyCount * m_minLoad < m_table Size * 2; } | 402 bool mustRehashInPlace() const { return m_keyCount * m_minLoad < m_table Size * 2; } |
| 367 bool shouldShrink() const { return m_keyCount * m_minLoad < m_tableSize && m_tableSize > KeyTraits::minimumTableSize; } | 403 bool shouldShrink() const { return m_keyCount * m_minLoad < m_tableSize && m_tableSize > KeyTraits::minimumTableSize; } |
| 368 void expand(); | 404 void expand(); |
| 369 void shrink() { rehash(m_tableSize / 2); } | 405 void shrink() { rehash(m_tableSize / 2); } |
| 370 | 406 |
| 371 void rehash(unsigned newTableSize); | 407 void rehash(unsigned newTableSize); |
| 372 void reinsert(ValueType&); | 408 void reinsert(ValueType&); |
| 373 | 409 |
| 374 static void initializeBucket(ValueType& bucket); | 410 static void initializeBucket(ValueType& bucket); |
| 375 static void deleteBucket(ValueType& bucket) { bucket.~ValueType(); Trait s::constructDeletedValue(bucket); } | 411 static void deleteBucket(ValueType& bucket) { bucket.~ValueType(); Trait s::constructDeletedValue(bucket); } |
| 376 | 412 |
| 377 FullLookupType makeLookupResult(ValueType* position, bool found, unsigne d hash) | 413 FullLookupType makeLookupResult(ValueType* position, bool found, unsigne d hash) |
| 378 { return FullLookupType(LookupType(position, found), hash); } | 414 { return FullLookupType(LookupType(position, found), hash); } |
| 379 | 415 |
| 380 iterator makeIterator(ValueType* pos) { return iterator(pos, m_table + m _tableSize); } | 416 iterator makeIterator(ValueType* pos) { return iterator(pos, m_table + m _tableSize, this); } |
| 381 const_iterator makeConstIterator(ValueType* pos) const { return const_it erator(pos, m_table + m_tableSize); } | 417 const_iterator makeConstIterator(ValueType* pos) const { return const_it erator(pos, m_table + m_tableSize, this); } |
| 382 iterator makeKnownGoodIterator(ValueType* pos) { return iterator(pos, m_ table + m_tableSize, HashItemKnownGood); } | 418 iterator makeKnownGoodIterator(ValueType* pos) { return iterator(pos, m_ table + m_tableSize, this, HashItemKnownGood); } |
| 383 const_iterator makeKnownGoodConstIterator(ValueType* pos) const { return const_iterator(pos, m_table + m_tableSize, HashItemKnownGood); } | 419 const_iterator makeKnownGoodConstIterator(ValueType* pos) const { return const_iterator(pos, m_table + m_tableSize, this, HashItemKnownGood); } |
| 384 | 420 |
| 385 static const unsigned m_maxLoad = 2; | 421 static const unsigned m_maxLoad = 2; |
| 386 static const unsigned m_minLoad = 6; | 422 static const unsigned m_minLoad = 6; |
| 387 | 423 |
| 388 ValueType* m_table; | 424 ValueType* m_table; |
| 389 unsigned m_tableSize; | 425 unsigned m_tableSize; |
| 390 unsigned m_tableSizeMask; | 426 unsigned m_tableSizeMask; |
| 391 unsigned m_keyCount; | 427 unsigned m_keyCount; |
| 392 unsigned m_deletedCount; | 428 unsigned m_deletedCount; |
| 429 #ifndef NDEBUG | |
| 430 unsigned m_modifications; | |
| 431 #endif | |
| 393 | 432 |
| 394 #if DUMP_HASHTABLE_STATS_PER_TABLE | 433 #if DUMP_HASHTABLE_STATS_PER_TABLE |
| 395 public: | 434 public: |
| 396 mutable OwnPtr<Stats> m_stats; | 435 mutable OwnPtr<Stats> m_stats; |
| 397 #endif | 436 #endif |
| 398 | 437 |
| 399 template<bool x, typename T, typename U, typename V, typename W, typenam e X, typename Y, typename Z> friend struct WeakProcessingHashTableHelper; | 438 template<bool x, typename T, typename U, typename V, typename W, typenam e X, typename Y, typename Z> friend struct WeakProcessingHashTableHelper; |
| 400 }; | 439 }; |
| 401 | 440 |
| 402 // Set all the bits to one after the most significant bit: 00110101010 -> 00 111111111. | 441 // Set all the bits to one after the most significant bit: 00110101010 -> 00 111111111. |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 437 COMPILE_ASSERT(value > (2 * size), HashTableCapacityHoldsContentSize); | 476 COMPILE_ASSERT(value > (2 * size), HashTableCapacityHoldsContentSize); |
| 438 }; | 477 }; |
| 439 | 478 |
| 440 template<typename Key, typename Value, typename Extractor, typename HashFunc tions, typename Traits, typename KeyTraits, typename Allocator> | 479 template<typename Key, typename Value, typename Extractor, typename HashFunc tions, typename Traits, typename KeyTraits, typename Allocator> |
| 441 inline HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Al locator>::HashTable() | 480 inline HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Al locator>::HashTable() |
| 442 : m_table(0) | 481 : m_table(0) |
| 443 , m_tableSize(0) | 482 , m_tableSize(0) |
| 444 , m_tableSizeMask(0) | 483 , m_tableSizeMask(0) |
| 445 , m_keyCount(0) | 484 , m_keyCount(0) |
| 446 , m_deletedCount(0) | 485 , m_deletedCount(0) |
| 486 #ifndef NDEBUG | |
| 487 , m_modifications(0) | |
| 488 #endif | |
| 447 #if DUMP_HASHTABLE_STATS_PER_TABLE | 489 #if DUMP_HASHTABLE_STATS_PER_TABLE |
| 448 , m_stats(adoptPtr(new Stats)) | 490 , m_stats(adoptPtr(new Stats)) |
| 449 #endif | 491 #endif |
| 450 { | 492 { |
| 451 } | 493 } |
| 452 | 494 |
| 453 inline unsigned doubleHash(unsigned key) | 495 inline unsigned doubleHash(unsigned key) |
| 454 { | 496 { |
| 455 key = ~key + (key >> 23); | 497 key = ~key + (key >> 23); |
| 456 key ^= (key << 12); | 498 key ^= (key << 12); |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 514 k = 1 | doubleHash(h); | 556 k = 1 | doubleHash(h); |
| 515 i = (i + k) & sizeMask; | 557 i = (i + k) & sizeMask; |
| 516 } | 558 } |
| 517 } | 559 } |
| 518 | 560 |
| 519 template<typename Key, typename Value, typename Extractor, typename HashFunc tions, typename Traits, typename KeyTraits, typename Allocator> | 561 template<typename Key, typename Value, typename Extractor, typename HashFunc tions, typename Traits, typename KeyTraits, typename Allocator> |
| 520 template<typename HashTranslator, typename T> | 562 template<typename HashTranslator, typename T> |
| 521 inline typename HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyT raits, Allocator>::LookupType HashTable<Key, Value, Extractor, HashFunctions, Tr aits, KeyTraits, Allocator>::lookupForWriting(const T& key) | 563 inline typename HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyT raits, Allocator>::LookupType HashTable<Key, Value, Extractor, HashFunctions, Tr aits, KeyTraits, Allocator>::lookupForWriting(const T& key) |
| 522 { | 564 { |
| 523 ASSERT(m_table); | 565 ASSERT(m_table); |
| 566 registerModification(); | |
| 524 | 567 |
| 525 size_t k = 0; | 568 size_t k = 0; |
| 526 ValueType* table = m_table; | 569 ValueType* table = m_table; |
| 527 size_t sizeMask = m_tableSizeMask; | 570 size_t sizeMask = m_tableSizeMask; |
| 528 unsigned h = HashTranslator::hash(key); | 571 unsigned h = HashTranslator::hash(key); |
| 529 size_t i = h & sizeMask; | 572 size_t i = h & sizeMask; |
| 530 | 573 |
| 531 #if DUMP_HASHTABLE_STATS | 574 #if DUMP_HASHTABLE_STATS |
| 532 atomicIncrement(&HashTableStats::numAccesses); | 575 atomicIncrement(&HashTableStats::numAccesses); |
| 533 int probeCount = 0; | 576 int probeCount = 0; |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 576 k = 1 | doubleHash(h); | 619 k = 1 | doubleHash(h); |
| 577 i = (i + k) & sizeMask; | 620 i = (i + k) & sizeMask; |
| 578 } | 621 } |
| 579 } | 622 } |
| 580 | 623 |
| 581 template<typename Key, typename Value, typename Extractor, typename HashFunc tions, typename Traits, typename KeyTraits, typename Allocator> | 624 template<typename Key, typename Value, typename Extractor, typename HashFunc tions, typename Traits, typename KeyTraits, typename Allocator> |
| 582 template<typename HashTranslator, typename T> | 625 template<typename HashTranslator, typename T> |
| 583 inline typename HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyT raits, Allocator>::FullLookupType HashTable<Key, Value, Extractor, HashFunctions , Traits, KeyTraits, Allocator>::fullLookupForWriting(const T& key) | 626 inline typename HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyT raits, Allocator>::FullLookupType HashTable<Key, Value, Extractor, HashFunctions , Traits, KeyTraits, Allocator>::fullLookupForWriting(const T& key) |
| 584 { | 627 { |
| 585 ASSERT(m_table); | 628 ASSERT(m_table); |
| 629 registerModification(); | |
| 586 | 630 |
| 587 size_t k = 0; | 631 size_t k = 0; |
| 588 ValueType* table = m_table; | 632 ValueType* table = m_table; |
| 589 size_t sizeMask = m_tableSizeMask; | 633 size_t sizeMask = m_tableSizeMask; |
| 590 unsigned h = HashTranslator::hash(key); | 634 unsigned h = HashTranslator::hash(key); |
| 591 size_t i = h & sizeMask; | 635 size_t i = h & sizeMask; |
| 592 | 636 |
| 593 #if DUMP_HASHTABLE_STATS | 637 #if DUMP_HASHTABLE_STATS |
| 594 atomicIncrement(&HashTableStats::numAccesses); | 638 atomicIncrement(&HashTableStats::numAccesses); |
| 595 int probeCount = 0; | 639 int probeCount = 0; |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 662 template<typename Key, typename Value, typename Extractor, typename HashFunc tions, typename Traits, typename KeyTraits, typename Allocator> | 706 template<typename Key, typename Value, typename Extractor, typename HashFunc tions, typename Traits, typename KeyTraits, typename Allocator> |
| 663 inline void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTrait s, Allocator>::initializeBucket(ValueType& bucket) | 707 inline void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTrait s, Allocator>::initializeBucket(ValueType& bucket) |
| 664 { | 708 { |
| 665 HashTableBucketInitializer<Traits::emptyValueIsZero>::template initializ e<Traits>(bucket); | 709 HashTableBucketInitializer<Traits::emptyValueIsZero>::template initializ e<Traits>(bucket); |
| 666 } | 710 } |
| 667 | 711 |
| 668 template<typename Key, typename Value, typename Extractor, typename HashFunc tions, typename Traits, typename KeyTraits, typename Allocator> | 712 template<typename Key, typename Value, typename Extractor, typename HashFunc tions, typename Traits, typename KeyTraits, typename Allocator> |
| 669 template<typename HashTranslator, typename T, typename Extra> | 713 template<typename HashTranslator, typename T, typename Extra> |
| 670 typename HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::AddResult HashTable<Key, Value, Extractor, HashFunctions, Traits, Ke yTraits, Allocator>::add(const T& key, const Extra& extra) | 714 typename HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::AddResult HashTable<Key, Value, Extractor, HashFunctions, Traits, Ke yTraits, Allocator>::add(const T& key, const Extra& extra) |
| 671 { | 715 { |
| 716 registerModification(); | |
| 672 if (!m_table) | 717 if (!m_table) |
| 673 expand(); | 718 expand(); |
| 674 | 719 |
| 675 ASSERT(m_table); | 720 ASSERT(m_table); |
| 676 | 721 |
| 677 size_t k = 0; | 722 size_t k = 0; |
| 678 ValueType* table = m_table; | 723 ValueType* table = m_table; |
| 679 size_t sizeMask = m_tableSizeMask; | 724 size_t sizeMask = m_tableSizeMask; |
| 680 unsigned h = HashTranslator::hash(key); | 725 unsigned h = HashTranslator::hash(key); |
| 681 size_t i = h & sizeMask; | 726 size_t i = h & sizeMask; |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 752 return result; | 797 return result; |
| 753 } | 798 } |
| 754 | 799 |
| 755 return AddResult(entry, true); | 800 return AddResult(entry, true); |
| 756 } | 801 } |
| 757 | 802 |
| 758 template<typename Key, typename Value, typename Extractor, typename HashFunc tions, typename Traits, typename KeyTraits, typename Allocator> | 803 template<typename Key, typename Value, typename Extractor, typename HashFunc tions, typename Traits, typename KeyTraits, typename Allocator> |
| 759 template<typename HashTranslator, typename T, typename Extra> | 804 template<typename HashTranslator, typename T, typename Extra> |
| 760 typename HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::AddResult HashTable<Key, Value, Extractor, HashFunctions, Traits, Ke yTraits, Allocator>::addPassingHashCode(const T& key, const Extra& extra) | 805 typename HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::AddResult HashTable<Key, Value, Extractor, HashFunctions, Traits, Ke yTraits, Allocator>::addPassingHashCode(const T& key, const Extra& extra) |
| 761 { | 806 { |
| 807 registerModification(); | |
| 762 if (!m_table) | 808 if (!m_table) |
| 763 expand(); | 809 expand(); |
| 764 | 810 |
| 765 FullLookupType lookupResult = fullLookupForWriting<HashTranslator>(key); | 811 FullLookupType lookupResult = fullLookupForWriting<HashTranslator>(key); |
| 766 | 812 |
| 767 ValueType* entry = lookupResult.first.first; | 813 ValueType* entry = lookupResult.first.first; |
| 768 bool found = lookupResult.first.second; | 814 bool found = lookupResult.first.second; |
| 769 unsigned h = lookupResult.second; | 815 unsigned h = lookupResult.second; |
| 770 | 816 |
| 771 if (found) | 817 if (found) |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 791 return result; | 837 return result; |
| 792 } | 838 } |
| 793 | 839 |
| 794 return AddResult(entry, true); | 840 return AddResult(entry, true); |
| 795 } | 841 } |
| 796 | 842 |
| 797 template<typename Key, typename Value, typename Extractor, typename HashFunc tions, typename Traits, typename KeyTraits, typename Allocator> | 843 template<typename Key, typename Value, typename Extractor, typename HashFunc tions, typename Traits, typename KeyTraits, typename Allocator> |
| 798 inline void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTrait s, Allocator>::reinsert(ValueType& entry) | 844 inline void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTrait s, Allocator>::reinsert(ValueType& entry) |
| 799 { | 845 { |
| 800 ASSERT(m_table); | 846 ASSERT(m_table); |
| 847 registerModification(); | |
| 801 ASSERT(!lookupForWriting(Extractor::extract(entry)).second); | 848 ASSERT(!lookupForWriting(Extractor::extract(entry)).second); |
| 802 ASSERT(!isDeletedBucket(*(lookupForWriting(Extractor::extract(entry)).fi rst))); | 849 ASSERT(!isDeletedBucket(*(lookupForWriting(Extractor::extract(entry)).fi rst))); |
| 803 #if DUMP_HASHTABLE_STATS | 850 #if DUMP_HASHTABLE_STATS |
| 804 atomicIncrement(&HashTableStats::numReinserts); | 851 atomicIncrement(&HashTableStats::numReinserts); |
| 805 #endif | 852 #endif |
| 806 #if DUMP_HASHTABLE_STATS_PER_TABLE | 853 #if DUMP_HASHTABLE_STATS_PER_TABLE |
| 807 ++m_stats->numReinserts; | 854 ++m_stats->numReinserts; |
| 808 #endif | 855 #endif |
| 809 | 856 |
| 810 Mover<ValueType, Traits::needsDestruction>::move(entry, *lookupForWritin g(Extractor::extract(entry)).first); | 857 Mover<ValueType, Traits::needsDestruction>::move(entry, *lookupForWritin g(Extractor::extract(entry)).first); |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 835 template<typename Key, typename Value, typename Extractor, typename HashFunc tions, typename Traits, typename KeyTraits, typename Allocator> | 882 template<typename Key, typename Value, typename Extractor, typename HashFunc tions, typename Traits, typename KeyTraits, typename Allocator> |
| 836 template <typename HashTranslator, typename T> | 883 template <typename HashTranslator, typename T> |
| 837 bool HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allo cator>::contains(const T& key) const | 884 bool HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allo cator>::contains(const T& key) const |
| 838 { | 885 { |
| 839 return const_cast<HashTable*>(this)->lookup<HashTranslator>(key); | 886 return const_cast<HashTable*>(this)->lookup<HashTranslator>(key); |
| 840 } | 887 } |
| 841 | 888 |
| 842 template<typename Key, typename Value, typename Extractor, typename HashFunc tions, typename Traits, typename KeyTraits, typename Allocator> | 889 template<typename Key, typename Value, typename Extractor, typename HashFunc tions, typename Traits, typename KeyTraits, typename Allocator> |
| 843 void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allo cator>::remove(ValueType* pos) | 890 void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allo cator>::remove(ValueType* pos) |
| 844 { | 891 { |
| 892 registerModification(); | |
| 845 #if DUMP_HASHTABLE_STATS | 893 #if DUMP_HASHTABLE_STATS |
| 846 atomicIncrement(&HashTableStats::numRemoves); | 894 atomicIncrement(&HashTableStats::numRemoves); |
| 847 #endif | 895 #endif |
| 848 #if DUMP_HASHTABLE_STATS_PER_TABLE | 896 #if DUMP_HASHTABLE_STATS_PER_TABLE |
| 849 ++m_stats->numRemoves; | 897 ++m_stats->numRemoves; |
| 850 #endif | 898 #endif |
| 851 | 899 |
| 852 deleteBucket(*pos); | 900 deleteBucket(*pos); |
| 853 ++m_deletedCount; | 901 ++m_deletedCount; |
| 854 --m_keyCount; | 902 --m_keyCount; |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 953 reinsert(oldTable[i]); | 1001 reinsert(oldTable[i]); |
| 954 | 1002 |
| 955 m_deletedCount = 0; | 1003 m_deletedCount = 0; |
| 956 | 1004 |
| 957 deallocateTable(oldTable, oldTableSize); | 1005 deallocateTable(oldTable, oldTableSize); |
| 958 } | 1006 } |
| 959 | 1007 |
| 960 template<typename Key, typename Value, typename Extractor, typename HashFunc tions, typename Traits, typename KeyTraits, typename Allocator> | 1008 template<typename Key, typename Value, typename Extractor, typename HashFunc tions, typename Traits, typename KeyTraits, typename Allocator> |
| 961 void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allo cator>::clear() | 1009 void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allo cator>::clear() |
| 962 { | 1010 { |
| 1011 registerModification(); | |
| 963 if (!m_table) | 1012 if (!m_table) |
| 964 return; | 1013 return; |
| 965 | 1014 |
| 966 deallocateTable(m_table, m_tableSize); | 1015 deallocateTable(m_table, m_tableSize); |
| 967 m_table = 0; | 1016 m_table = 0; |
| 968 m_tableSize = 0; | 1017 m_tableSize = 0; |
| 969 m_tableSizeMask = 0; | 1018 m_tableSizeMask = 0; |
| 970 m_keyCount = 0; | 1019 m_keyCount = 0; |
| 971 } | 1020 } |
| 972 | 1021 |
| 973 template<typename Key, typename Value, typename Extractor, typename HashFunc tions, typename Traits, typename KeyTraits, typename Allocator> | 1022 template<typename Key, typename Value, typename Extractor, typename HashFunc tions, typename Traits, typename KeyTraits, typename Allocator> |
| 974 HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator >::HashTable(const HashTable& other) | 1023 HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator >::HashTable(const HashTable& other) |
| 975 : m_table(0) | 1024 : m_table(0) |
| 976 , m_tableSize(0) | 1025 , m_tableSize(0) |
| 977 , m_tableSizeMask(0) | 1026 , m_tableSizeMask(0) |
| 978 , m_keyCount(0) | 1027 , m_keyCount(0) |
| 979 , m_deletedCount(0) | 1028 , m_deletedCount(0) |
| 1029 #ifndef NDEBUG | |
| 1030 , m_modifications(0) | |
| 1031 #endif | |
| 980 #if DUMP_HASHTABLE_STATS_PER_TABLE | 1032 #if DUMP_HASHTABLE_STATS_PER_TABLE |
| 981 , m_stats(adoptPtr(new Stats(*other.m_stats))) | 1033 , m_stats(adoptPtr(new Stats(*other.m_stats))) |
| 982 #endif | 1034 #endif |
| 983 { | 1035 { |
| 984 // Copy the hash table the dumb way, by adding each element to the new t able. | 1036 // Copy the hash table the dumb way, by adding each element to the new t able. |
| 985 // It might be more efficient to copy the table slots, but it's not clea r that efficiency is needed. | 1037 // It might be more efficient to copy the table slots, but it's not clea r that efficiency is needed. |
| 986 const_iterator end = other.end(); | 1038 const_iterator end = other.end(); |
| 987 for (const_iterator it = other.begin(); it != end; ++it) | 1039 for (const_iterator it = other.begin(); it != end; ++it) |
| 988 add(*it); | 1040 add(*it); |
| 989 } | 1041 } |
| 990 | 1042 |
| 991 template<typename Key, typename Value, typename Extractor, typename HashFunc tions, typename Traits, typename KeyTraits, typename Allocator> | 1043 template<typename Key, typename Value, typename Extractor, typename HashFunc tions, typename Traits, typename KeyTraits, typename Allocator> |
| 992 void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allo cator>::swap(HashTable& other) | 1044 void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allo cator>::swap(HashTable& other) |
| 993 { | 1045 { |
| 994 std::swap(m_table, other.m_table); | 1046 std::swap(m_table, other.m_table); |
| 995 std::swap(m_tableSize, other.m_tableSize); | 1047 std::swap(m_tableSize, other.m_tableSize); |
| 996 std::swap(m_tableSizeMask, other.m_tableSizeMask); | 1048 std::swap(m_tableSizeMask, other.m_tableSizeMask); |
| 997 std::swap(m_keyCount, other.m_keyCount); | 1049 std::swap(m_keyCount, other.m_keyCount); |
| 998 std::swap(m_deletedCount, other.m_deletedCount); | 1050 std::swap(m_deletedCount, other.m_deletedCount); |
| 999 | 1051 |
| 1052 #ifndef NDEBUG | |
| 1053 int64_t tmpModifications = m_modifications; | |
| 1054 m_modifications = other.m_modifications; | |
| 1055 other.m_modifications = tmpModifications; | |
|
Mikhail
2014/03/31 14:08:09
why not 'swap' ?
Erik Corry
2014/03/31 19:45:38
Done.
| |
| 1056 #endif | |
| 1057 | |
| 1000 #if DUMP_HASHTABLE_STATS_PER_TABLE | 1058 #if DUMP_HASHTABLE_STATS_PER_TABLE |
| 1001 m_stats.swap(other.m_stats); | 1059 m_stats.swap(other.m_stats); |
| 1002 #endif | 1060 #endif |
| 1003 } | 1061 } |
| 1004 | 1062 |
| 1005 template<typename Key, typename Value, typename Extractor, typename HashFunc tions, typename Traits, typename KeyTraits, typename Allocator> | 1063 template<typename Key, typename Value, typename Extractor, typename HashFunc tions, typename Traits, typename KeyTraits, typename Allocator> |
| 1006 HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator >& HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator> ::operator=(const HashTable& other) | 1064 HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator >& HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator> ::operator=(const HashTable& other) |
| 1007 { | 1065 { |
| 1008 HashTable tmp(other); | 1066 HashTable tmp(other); |
| 1009 swap(tmp); | 1067 swap(tmp); |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 1027 if (table->m_table) { | 1085 if (table->m_table) { |
| 1028 // This just marks it live and does not push anything onto the | 1086 // This just marks it live and does not push anything onto the |
| 1029 // marking stack. | 1087 // marking stack. |
| 1030 Allocator::markNoTracing(visitor, table->m_table); | 1088 Allocator::markNoTracing(visitor, table->m_table); |
| 1031 // Now perform weak processing (this is a no-op if the backing | 1089 // Now perform weak processing (this is a no-op if the backing |
| 1032 // was accessible through an iterator and was already marked | 1090 // was accessible through an iterator and was already marked |
| 1033 // strongly). | 1091 // strongly). |
| 1034 for (typename HashTableType::ValueType* element = table->m_table + table->m_tableSize - 1; element >= table->m_table; element--) { | 1092 for (typename HashTableType::ValueType* element = table->m_table + table->m_tableSize - 1; element >= table->m_table; element--) { |
| 1035 if (!HashTableType::isEmptyOrDeletedBucket(*element)) { | 1093 if (!HashTableType::isEmptyOrDeletedBucket(*element)) { |
| 1036 if (Allocator::hasDeadMember(visitor, *element)) { | 1094 if (Allocator::hasDeadMember(visitor, *element)) { |
| 1095 table->registerModification(); | |
| 1037 HashTableType::deleteBucket(*element); // Also calls the destructor. | 1096 HashTableType::deleteBucket(*element); // Also calls the destructor. |
| 1038 table->m_deletedCount++; | 1097 table->m_deletedCount++; |
| 1039 table->m_keyCount--; | 1098 table->m_keyCount--; |
| 1040 // We don't rehash the backing until the next add | 1099 // We don't rehash the backing until the next add |
| 1041 // or delete, because that would cause allocation | 1100 // or delete, because that would cause allocation |
| 1042 // during GC. | 1101 // during GC. |
| 1043 } | 1102 } |
| 1044 } | 1103 } |
| 1045 } | 1104 } |
| 1046 } | 1105 } |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1166 inline bool operator!=(const HashTableIteratorAdapter<T, U>& a, const HashTa bleConstIteratorAdapter<T, U>& b) | 1225 inline bool operator!=(const HashTableIteratorAdapter<T, U>& a, const HashTa bleConstIteratorAdapter<T, U>& b) |
| 1167 { | 1226 { |
| 1168 return a.m_impl != b.m_impl; | 1227 return a.m_impl != b.m_impl; |
| 1169 } | 1228 } |
| 1170 | 1229 |
| 1171 } // namespace WTF | 1230 } // namespace WTF |
| 1172 | 1231 |
| 1173 #include "wtf/HashIterators.h" | 1232 #include "wtf/HashIterators.h" |
| 1174 | 1233 |
| 1175 #endif // WTF_HashTable_h | 1234 #endif // WTF_HashTable_h |
| OLD | NEW |