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 256 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 267 new (NotNull, &to) T(std::move(from)); | 267 new (NotNull, &to) T(std::move(from)); |
| 268 Allocator::leaveGCForbiddenScope(); | 268 Allocator::leaveGCForbiddenScope(); |
| 269 } | 269 } |
| 270 }; | 270 }; |
| 271 | 271 |
| 272 template <typename HashFunctions> class IdentityHashTranslator { | 272 template <typename HashFunctions> class IdentityHashTranslator { |
| 273 STATIC_ONLY(IdentityHashTranslator); | 273 STATIC_ONLY(IdentityHashTranslator); |
| 274 public: | 274 public: |
| 275 template <typename T> static unsigned hash(const T& key) { return HashFuncti ons::hash(key); } | 275 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); } | 276 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, const U&, const V& value) { location = value; } | 277 template <typename T, typename U, typename V> static void translate(T& locat ion, U&&, V&& value) { location = std::forward<V>(value); } |
| 278 }; | 278 }; |
| 279 | 279 |
| 280 template <typename HashTableType, typename ValueType> struct HashTableAddResult final { | 280 template <typename HashTableType, typename ValueType> struct HashTableAddResult final { |
| 281 STACK_ALLOCATED(); | 281 STACK_ALLOCATED(); |
| 282 HashTableAddResult(const HashTableType* container, ValueType* storedValue, b ool isNewEntry) | 282 HashTableAddResult(const HashTableType* container, ValueType* storedValue, b ool isNewEntry) |
| 283 : storedValue(storedValue) | 283 : storedValue(storedValue) |
| 284 , isNewEntry(isNewEntry) | 284 , isNewEntry(isNewEntry) |
| 285 #if ENABLE(SECURITY_ASSERT) | 285 #if ENABLE(SECURITY_ASSERT) |
| 286 , m_container(container) | 286 , m_container(container) |
| 287 , m_containerModifications(container->modifications()) | 287 , m_containerModifications(container->modifications()) |
| (...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 455 void reserveCapacityForSize(unsigned size); | 455 void reserveCapacityForSize(unsigned size); |
| 456 | 456 |
| 457 AddResult add(ValuePassInType value) | 457 AddResult add(ValuePassInType value) |
| 458 { | 458 { |
| 459 return add<IdentityTranslatorType>(Extractor::extract(value), value); | 459 return add<IdentityTranslatorType>(Extractor::extract(value), value); |
| 460 } | 460 } |
| 461 | 461 |
| 462 // A special version of add() that finds the object by hashing and comparing | 462 // A special version of add() that finds the object by hashing and comparing |
| 463 // with some other type, to avoid the cost of type conversion if the object | 463 // with some other type, to avoid the cost of type conversion if the object |
| 464 // is already in the table. | 464 // is already in the table. |
| 465 template <typename HashTranslator, typename T, typename Extra> AddResult add (const T& key, const Extra&); | 465 template <typename HashTranslator, typename T, typename Extra> AddResult add (T&& key, Extra&&); |
| 466 template <typename HashTranslator, typename T, typename Extra> AddResult add PassingHashCode(const T& key, const Extra&); | 466 template <typename HashTranslator, typename T, typename Extra> AddResult add PassingHashCode(const T& key, const Extra&); |
| 467 | 467 |
| 468 iterator find(KeyPeekInType key) { return find<IdentityTranslatorType>(key); } | 468 iterator find(KeyPeekInType key) { return find<IdentityTranslatorType>(key); } |
| 469 const_iterator find(KeyPeekInType key) const { return find<IdentityTranslato rType>(key); } | 469 const_iterator find(KeyPeekInType key) const { return find<IdentityTranslato rType>(key); } |
| 470 bool contains(KeyPeekInType key) const { return contains<IdentityTranslatorT ype>(key); } | 470 bool contains(KeyPeekInType key) const { return contains<IdentityTranslatorT ype>(key); } |
| 471 | 471 |
| 472 template <typename HashTranslator, typename T> iterator find(const T&); | 472 template <typename HashTranslator, typename T> iterator find(const T&); |
| 473 template <typename HashTranslator, typename T> const_iterator find(const T&) const; | 473 template <typename HashTranslator, typename T> const_iterator find(const T&) const; |
| 474 template <typename HashTranslator, typename T> bool contains(const T&) const ; | 474 template <typename HashTranslator, typename T> bool contains(const T&) const ; |
| 475 | 475 |
| 476 void remove(KeyPeekInType); | 476 void remove(KeyPeekInType); |
| 477 void remove(iterator); | 477 void remove(iterator); |
| 478 void remove(const_iterator); | 478 void remove(const_iterator); |
| 479 void clear(); | 479 void clear(); |
| 480 | 480 |
| 481 static bool isEmptyBucket(const ValueType& value) { return isHashTraitsEmpty Value<KeyTraits>(Extractor::extract(value)); } | 481 static bool isEmptyBucket(const ValueType& value) { return isHashTraitsEmpty Value<KeyTraits>(Extractor::extract(value)); } |
| 482 static bool isDeletedBucket(const ValueType& value) { return KeyTraits::isDe letedValue(Extractor::extract(value)); } | 482 static bool isDeletedBucket(const ValueType& value) { return KeyTraits::isDe letedValue(Extractor::extract(value)); } |
| 483 static bool isEmptyOrDeletedBucket(const ValueType& value) { return HashTabl eHelper<ValueType, Extractor, KeyTraits>:: isEmptyOrDeletedBucket(value); } | 483 static bool isEmptyOrDeletedBucket(const ValueType& value) { return HashTabl eHelper<ValueType, Extractor, KeyTraits>:: isEmptyOrDeletedBucket(value); } |
| 484 | 484 |
| 485 ValueType* lookup(KeyPeekInType key) { return lookup<IdentityTranslatorType, KeyPeekInType>(key); } | 485 ValueType* lookup(KeyPeekInType key) { return lookup<IdentityTranslatorType, KeyPeekInType>(key); } |
| 486 template <typename HashTranslator, typename T> ValueType* lookup(T); | 486 template <typename HashTranslator, typename T> ValueType* lookup(const T&); |
|
Mikhail
2016/03/04 12:58:02
why not T&& ?
Yuta Kitamura
2016/03/04 13:55:37
This is used to calculate the hash value of T, so
| |
| 487 template <typename HashTranslator, typename T> const ValueType* lookup(T) co nst; | 487 template <typename HashTranslator, typename T> const ValueType* lookup(const T&) const; |
| 488 | 488 |
| 489 template <typename VisitorDispatcher> void trace(VisitorDispatcher); | 489 template <typename VisitorDispatcher> void trace(VisitorDispatcher); |
| 490 | 490 |
| 491 #if ENABLE(ASSERT) | 491 #if ENABLE(ASSERT) |
| 492 bool accessForbidden() const { return m_accessForbidden; } | 492 bool accessForbidden() const { return m_accessForbidden; } |
| 493 int64_t modifications() const { return m_modifications; } | 493 int64_t modifications() const { return m_modifications; } |
| 494 void registerModification() { m_modifications++; } | 494 void registerModification() { m_modifications++; } |
| 495 // HashTable and collections that build on it do not support modifications | 495 // HashTable and collections that build on it do not support modifications |
| 496 // while there is an iterator in use. The exception is ListHashSet, which | 496 // while there is an iterator in use. The exception is ListHashSet, which |
| 497 // has its own iterators that tolerate modification of the underlying set. | 497 // has its own iterators that tolerate modification of the underlying set. |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 627 newCapacity = KeyTraits::minimumTableSize; | 627 newCapacity = KeyTraits::minimumTableSize; |
| 628 | 628 |
| 629 if (newCapacity > capacity()) { | 629 if (newCapacity > capacity()) { |
| 630 RELEASE_ASSERT(!static_cast<int>(newCapacity >> 31)); // HashTable capac ity should not overflow 32bit int. | 630 RELEASE_ASSERT(!static_cast<int>(newCapacity >> 31)); // HashTable capac ity should not overflow 32bit int. |
| 631 rehash(newCapacity, 0); | 631 rehash(newCapacity, 0); |
| 632 } | 632 } |
| 633 } | 633 } |
| 634 | 634 |
| 635 template <typename Key, typename Value, typename Extractor, typename HashFunctio ns, typename Traits, typename KeyTraits, typename Allocator> | 635 template <typename Key, typename Value, typename Extractor, typename HashFunctio ns, typename Traits, typename KeyTraits, typename Allocator> |
| 636 template <typename HashTranslator, typename T> | 636 template <typename HashTranslator, typename T> |
| 637 inline Value* HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::lookup(T key) | 637 inline Value* HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::lookup(const T& key) |
| 638 { | 638 { |
| 639 return const_cast<Value*>(const_cast<const HashTable*>(this)->lookup<HashTra nslator, T>(key)); | 639 return const_cast<Value*>(const_cast<const HashTable*>(this)->lookup<HashTra nslator>(key)); |
| 640 } | 640 } |
| 641 | 641 |
| 642 template <typename Key, typename Value, typename Extractor, typename HashFunctio ns, typename Traits, typename KeyTraits, typename Allocator> | 642 template <typename Key, typename Value, typename Extractor, typename HashFunctio ns, typename Traits, typename KeyTraits, typename Allocator> |
| 643 template <typename HashTranslator, typename T> | 643 template <typename HashTranslator, typename T> |
| 644 inline const Value* HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyT raits, Allocator>::lookup(T key) const | 644 inline const Value* HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyT raits, Allocator>::lookup(const T& key) const |
| 645 { | 645 { |
| 646 ASSERT(!m_accessForbidden); | 646 ASSERT(!m_accessForbidden); |
| 647 ASSERT((HashTableKeyChecker<HashTranslator, KeyTraits, HashFunctions::safeTo CompareToEmptyOrDeleted>::checkKey(key))); | 647 ASSERT((HashTableKeyChecker<HashTranslator, KeyTraits, HashFunctions::safeTo CompareToEmptyOrDeleted>::checkKey(key))); |
| 648 const ValueType* table = m_table; | 648 const ValueType* table = m_table; |
| 649 if (!table) | 649 if (!table) |
| 650 return nullptr; | 650 return nullptr; |
| 651 | 651 |
| 652 size_t k = 0; | 652 size_t k = 0; |
| 653 size_t sizeMask = tableSizeMask(); | 653 size_t sizeMask = tableSizeMask(); |
| 654 unsigned h = HashTranslator::hash(key); | 654 unsigned h = HashTranslator::hash(key); |
| (...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 788 }; | 788 }; |
| 789 | 789 |
| 790 template <typename Key, typename Value, typename Extractor, typename HashFunctio ns, typename Traits, typename KeyTraits, typename Allocator> | 790 template <typename Key, typename Value, typename Extractor, typename HashFunctio ns, typename Traits, typename KeyTraits, typename Allocator> |
| 791 inline void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, A llocator>::initializeBucket(ValueType& bucket) | 791 inline void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, A llocator>::initializeBucket(ValueType& bucket) |
| 792 { | 792 { |
| 793 HashTableBucketInitializer<Traits::emptyValueIsZero>::template initialize<Tr aits>(bucket); | 793 HashTableBucketInitializer<Traits::emptyValueIsZero>::template initialize<Tr aits>(bucket); |
| 794 } | 794 } |
| 795 | 795 |
| 796 template <typename Key, typename Value, typename Extractor, typename HashFunctio ns, typename Traits, typename KeyTraits, typename Allocator> | 796 template <typename Key, typename Value, typename Extractor, typename HashFunctio ns, typename Traits, typename KeyTraits, typename Allocator> |
| 797 template <typename HashTranslator, typename T, typename Extra> | 797 template <typename HashTranslator, typename T, typename Extra> |
| 798 typename HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allo cator>::AddResult HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTra its, Allocator>::add(const T& key, const Extra& extra) | 798 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) |
| 799 { | 799 { |
| 800 ASSERT(!m_accessForbidden); | 800 ASSERT(!m_accessForbidden); |
| 801 ASSERT(Allocator::isAllocationAllowed()); | 801 ASSERT(Allocator::isAllocationAllowed()); |
| 802 if (!m_table) | 802 if (!m_table) |
| 803 expand(); | 803 expand(); |
| 804 | 804 |
| 805 ASSERT(m_table); | 805 ASSERT(m_table); |
| 806 | 806 |
| 807 ValueType* table = m_table; | 807 ValueType* table = m_table; |
| 808 size_t k = 0; | 808 size_t k = 0; |
| 809 size_t sizeMask = tableSizeMask(); | 809 size_t sizeMask = tableSizeMask(); |
| 810 unsigned h = HashTranslator::hash(key); | 810 unsigned h = HashTranslator::hash(key); |
|
tzik
2016/03/04 15:29:59
This is not directly related to this CL, but it ma
Yuta Kitamura
2016/03/07 04:36:27
I don't plan to do that in this patch, but sounds
| |
| 811 size_t i = h & sizeMask; | 811 size_t i = h & sizeMask; |
| 812 | 812 |
| 813 UPDATE_ACCESS_COUNTS(); | 813 UPDATE_ACCESS_COUNTS(); |
| 814 | 814 |
| 815 ValueType* deletedEntry = nullptr; | 815 ValueType* deletedEntry = nullptr; |
| 816 ValueType* entry; | 816 ValueType* entry; |
| 817 while (1) { | 817 while (1) { |
| 818 entry = table + i; | 818 entry = table + i; |
| 819 | 819 |
| 820 if (isEmptyBucket(*entry)) | 820 if (isEmptyBucket(*entry)) |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 841 registerModification(); | 841 registerModification(); |
| 842 | 842 |
| 843 if (deletedEntry) { | 843 if (deletedEntry) { |
| 844 // Overwrite any data left over from last use, using placement new or | 844 // Overwrite any data left over from last use, using placement new or |
| 845 // memset. | 845 // memset. |
| 846 initializeBucket(*deletedEntry); | 846 initializeBucket(*deletedEntry); |
| 847 entry = deletedEntry; | 847 entry = deletedEntry; |
| 848 --m_deletedCount; | 848 --m_deletedCount; |
| 849 } | 849 } |
| 850 | 850 |
| 851 HashTranslator::translate(*entry, key, extra); | 851 HashTranslator::translate(*entry, std::forward<T>(key), std::forward<Extra>( extra)); |
| 852 ASSERT(!isEmptyOrDeletedBucket(*entry)); | 852 ASSERT(!isEmptyOrDeletedBucket(*entry)); |
| 853 | 853 |
| 854 ++m_keyCount; | 854 ++m_keyCount; |
| 855 | 855 |
| 856 if (shouldExpand()) | 856 if (shouldExpand()) |
| 857 entry = expand(entry); | 857 entry = expand(entry); |
| 858 | 858 |
| 859 return AddResult(this, entry, true); | 859 return AddResult(this, entry, true); |
| 860 } | 860 } |
| 861 | 861 |
| (...skipping 633 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1495 CollectionIterator end(toBeRemoved.end()); | 1495 CollectionIterator end(toBeRemoved.end()); |
| 1496 for (CollectionIterator it(toBeRemoved.begin()); it != end; ++it) | 1496 for (CollectionIterator it(toBeRemoved.begin()); it != end; ++it) |
| 1497 collection.remove(*it); | 1497 collection.remove(*it); |
| 1498 } | 1498 } |
| 1499 | 1499 |
| 1500 } // namespace WTF | 1500 } // namespace WTF |
| 1501 | 1501 |
| 1502 #include "wtf/HashIterators.h" | 1502 #include "wtf/HashIterators.h" |
| 1503 | 1503 |
| 1504 #endif // WTF_HashTable_h | 1504 #endif // WTF_HashTable_h |
| OLD | NEW |