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

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

Issue 219413002: Hash iterators: Check for concurrent modification and fix 1 place where it happened (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Created 6 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 | Annotate | Revision Log
« no previous file with comments | « Source/core/animation/DocumentTimeline.cpp ('k') | no next file » | 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 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « Source/core/animation/DocumentTimeline.cpp ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698