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 |