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 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
199 template<typename T> struct Mover<T, true> { static void move(T& from, T& to ) { hashTableSwap(from, to); } }; | 199 template<typename T> struct Mover<T, true> { static void move(T& from, T& to ) { hashTableSwap(from, to); } }; |
200 template<typename T> struct Mover<T, false> { static void move(T& from, T& t o) { to = from; } }; | 200 template<typename T> struct Mover<T, false> { static void move(T& from, T& t o) { to = from; } }; |
201 | 201 |
202 template<typename HashFunctions> class IdentityHashTranslator { | 202 template<typename HashFunctions> class IdentityHashTranslator { |
203 public: | 203 public: |
204 template<typename T> static unsigned hash(const T& key) { return HashFun ctions::hash(key); } | 204 template<typename T> static unsigned hash(const T& key) { return HashFun ctions::hash(key); } |
205 template<typename T, typename U> static bool equal(const T& a, const U& b) { return HashFunctions::equal(a, b); } | 205 template<typename T, typename U> static bool equal(const T& a, const U& b) { return HashFunctions::equal(a, b); } |
206 template<typename T, typename U> static void translate(T& location, cons t U&, const T& value) { location = value; } | 206 template<typename T, typename U> static void translate(T& location, cons t U&, const T& value) { location = value; } |
207 }; | 207 }; |
208 | 208 |
209 template<typename IteratorType> struct HashTableAddResult { | 209 template<typename ValueType> struct HashTableAddResult { |
210 HashTableAddResult(IteratorType iter, bool isNewEntry) : iterator(iter), isNewEntry(isNewEntry) { } | 210 HashTableAddResult(ValueType* iterator, bool isNewEntry) : iterator(iter ator), isNewEntry(isNewEntry) { } |
Erik Corry
2014/02/04 14:27:15
If this is no longer an iterator, should it be cal
eseidel
2014/02/05 22:17:20
No. :) But presumably Daniel did this to minimize
| |
211 IteratorType iterator; | 211 ValueType* iterator; |
212 bool isNewEntry; | 212 bool isNewEntry; |
213 }; | 213 }; |
214 | 214 |
215 template<typename Value, typename Extractor, typename KeyTraits> | 215 template<typename Value, typename Extractor, typename KeyTraits> |
216 struct HashTableHelper { | 216 struct HashTableHelper { |
217 static bool isEmptyBucket(const Value& value) { return isHashTraitsEmpty Value<KeyTraits>(Extractor::extract(value)); } | 217 static bool isEmptyBucket(const Value& value) { return isHashTraitsEmpty Value<KeyTraits>(Extractor::extract(value)); } |
218 static bool isDeletedBucket(const Value& value) { return KeyTraits::isDe letedValue(Extractor::extract(value)); } | 218 static bool isDeletedBucket(const Value& value) { return KeyTraits::isDe letedValue(Extractor::extract(value)); } |
219 static bool isEmptyOrDeletedBucket(const Value& value) { return isEmptyB ucket(value) || isDeletedBucket(value); } | 219 static bool isEmptyOrDeletedBucket(const Value& value) { return isEmptyB ucket(value) || isDeletedBucket(value); } |
220 }; | 220 }; |
221 | 221 |
222 template<typename Key, typename Value, typename Extractor, typename HashFunc tions, typename Traits, typename KeyTraits, typename Allocator> | 222 template<typename Key, typename Value, typename Extractor, typename HashFunc tions, typename Traits, typename KeyTraits, typename Allocator> |
223 class HashTable { | 223 class HashTable { |
224 public: | 224 public: |
225 typedef HashTableIterator<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator> iterator; | 225 typedef HashTableIterator<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator> iterator; |
226 typedef HashTableConstIterator<Key, Value, Extractor, HashFunctions, Tra its, KeyTraits, Allocator> const_iterator; | 226 typedef HashTableConstIterator<Key, Value, Extractor, HashFunctions, Tra its, KeyTraits, Allocator> const_iterator; |
227 typedef Traits ValueTraits; | 227 typedef Traits ValueTraits; |
228 typedef Key KeyType; | 228 typedef Key KeyType; |
229 typedef typename KeyTraits::PeekInType KeyPeekInType; | 229 typedef typename KeyTraits::PeekInType KeyPeekInType; |
230 typedef typename KeyTraits::PassInType KeyPassInType; | 230 typedef typename KeyTraits::PassInType KeyPassInType; |
231 typedef Value ValueType; | 231 typedef Value ValueType; |
232 typedef typename Traits::PeekInType ValuePeekInType; | 232 typedef typename Traits::PeekInType ValuePeekInType; |
233 typedef IdentityHashTranslator<HashFunctions> IdentityTranslatorType; | 233 typedef IdentityHashTranslator<HashFunctions> IdentityTranslatorType; |
234 typedef HashTableAddResult<iterator> AddResult; | 234 typedef HashTableAddResult<ValueType> AddResult; |
235 | 235 |
236 #if DUMP_HASHTABLE_STATS_PER_TABLE | 236 #if DUMP_HASHTABLE_STATS_PER_TABLE |
237 struct Stats { | 237 struct Stats { |
238 Stats() | 238 Stats() |
239 : numAccesses(0) | 239 : numAccesses(0) |
240 , numRehashes(0) | 240 , numRehashes(0) |
241 , numRemoves(0) | 241 , numRemoves(0) |
242 , numReinserts(0) | 242 , numReinserts(0) |
243 , maxCollisions(0) | 243 , maxCollisions(0) |
244 , numCollisions(0) | 244 , numCollisions(0) |
(...skipping 436 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
681 ValueType* entry; | 681 ValueType* entry; |
682 while (1) { | 682 while (1) { |
683 entry = table + i; | 683 entry = table + i; |
684 | 684 |
685 // we count on the compiler to optimize out this branch | 685 // we count on the compiler to optimize out this branch |
686 if (HashFunctions::safeToCompareToEmptyOrDeleted) { | 686 if (HashFunctions::safeToCompareToEmptyOrDeleted) { |
687 if (isEmptyBucket(*entry)) | 687 if (isEmptyBucket(*entry)) |
688 break; | 688 break; |
689 | 689 |
690 if (HashTranslator::equal(Extractor::extract(*entry), key)) | 690 if (HashTranslator::equal(Extractor::extract(*entry), key)) |
691 return AddResult(makeKnownGoodIterator(entry), false); | 691 return AddResult(entry, false); |
692 | 692 |
693 if (isDeletedBucket(*entry)) | 693 if (isDeletedBucket(*entry)) |
694 deletedEntry = entry; | 694 deletedEntry = entry; |
695 } else { | 695 } else { |
696 if (isEmptyBucket(*entry)) | 696 if (isEmptyBucket(*entry)) |
697 break; | 697 break; |
698 | 698 |
699 if (isDeletedBucket(*entry)) | 699 if (isDeletedBucket(*entry)) |
700 deletedEntry = entry; | 700 deletedEntry = entry; |
701 else if (HashTranslator::equal(Extractor::extract(*entry), key)) | 701 else if (HashTranslator::equal(Extractor::extract(*entry), key)) |
702 return AddResult(makeKnownGoodIterator(entry), false); | 702 return AddResult(entry, false); |
703 } | 703 } |
704 #if DUMP_HASHTABLE_STATS | 704 #if DUMP_HASHTABLE_STATS |
705 ++probeCount; | 705 ++probeCount; |
706 HashTableStats::recordCollisionAtCount(probeCount); | 706 HashTableStats::recordCollisionAtCount(probeCount); |
707 #endif | 707 #endif |
708 | 708 |
709 #if DUMP_HASHTABLE_STATS_PER_TABLE | 709 #if DUMP_HASHTABLE_STATS_PER_TABLE |
710 ++perTableProbeCount; | 710 ++perTableProbeCount; |
711 m_stats->recordCollisionAtCount(perTableProbeCount); | 711 m_stats->recordCollisionAtCount(perTableProbeCount); |
712 #endif | 712 #endif |
(...skipping 12 matching lines...) Expand all Loading... | |
725 HashTranslator::translate(*entry, key, extra); | 725 HashTranslator::translate(*entry, key, extra); |
726 | 726 |
727 ++m_keyCount; | 727 ++m_keyCount; |
728 | 728 |
729 if (shouldExpand()) { | 729 if (shouldExpand()) { |
730 // FIXME: This makes an extra copy on expand. Probably not that bad since | 730 // FIXME: This makes an extra copy on expand. Probably not that bad since |
731 // expand is rare, but would be better to have a version of expand t hat can | 731 // expand is rare, but would be better to have a version of expand t hat can |
732 // follow a pivot entry and return the new position. | 732 // follow a pivot entry and return the new position. |
733 typename WTF::RemoveReference<KeyPassInType>::Type enteredKey = Extr actor::extract(*entry); | 733 typename WTF::RemoveReference<KeyPassInType>::Type enteredKey = Extr actor::extract(*entry); |
734 expand(); | 734 expand(); |
735 AddResult result(find(enteredKey), true); | 735 iterator findResult = find(enteredKey); |
736 ASSERT(result.iterator != end()); | 736 ASSERT(findResult != end()); |
737 ValueType* resultValue = findResult.get(); | |
738 AddResult result(resultValue, true); | |
737 return result; | 739 return result; |
738 } | 740 } |
739 | 741 |
740 return AddResult(makeKnownGoodIterator(entry), true); | 742 return AddResult(entry, true); |
741 } | 743 } |
742 | 744 |
743 template<typename Key, typename Value, typename Extractor, typename HashFunc tions, typename Traits, typename KeyTraits, typename Allocator> | 745 template<typename Key, typename Value, typename Extractor, typename HashFunc tions, typename Traits, typename KeyTraits, typename Allocator> |
744 template<typename HashTranslator, typename T, typename Extra> | 746 template<typename HashTranslator, typename T, typename Extra> |
745 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) | 747 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) |
746 { | 748 { |
747 if (!m_table) | 749 if (!m_table) |
748 expand(); | 750 expand(); |
749 | 751 |
750 FullLookupType lookupResult = fullLookupForWriting<HashTranslator>(key); | 752 FullLookupType lookupResult = fullLookupForWriting<HashTranslator>(key); |
751 | 753 |
752 ValueType* entry = lookupResult.first.first; | 754 ValueType* entry = lookupResult.first.first; |
753 bool found = lookupResult.first.second; | 755 bool found = lookupResult.first.second; |
754 unsigned h = lookupResult.second; | 756 unsigned h = lookupResult.second; |
755 | 757 |
756 if (found) | 758 if (found) |
757 return AddResult(makeKnownGoodIterator(entry), false); | 759 return AddResult(entry, false); |
758 | 760 |
759 if (isDeletedBucket(*entry)) { | 761 if (isDeletedBucket(*entry)) { |
760 initializeBucket(*entry); | 762 initializeBucket(*entry); |
761 --m_deletedCount; | 763 --m_deletedCount; |
762 } | 764 } |
763 | 765 |
764 HashTranslator::translate(*entry, key, extra, h); | 766 HashTranslator::translate(*entry, key, extra, h); |
765 ++m_keyCount; | 767 ++m_keyCount; |
766 if (shouldExpand()) { | 768 if (shouldExpand()) { |
767 // FIXME: This makes an extra copy on expand. Probably not that bad since | 769 // FIXME: This makes an extra copy on expand. Probably not that bad since |
768 // expand is rare, but would be better to have a version of expand t hat can | 770 // expand is rare, but would be better to have a version of expand t hat can |
769 // follow a pivot entry and return the new position. | 771 // follow a pivot entry and return the new position. |
770 typename WTF::RemoveReference<KeyPassInType>::Type enteredKey = Extr actor::extract(*entry); | 772 typename WTF::RemoveReference<KeyPassInType>::Type enteredKey = Extr actor::extract(*entry); |
771 expand(); | 773 expand(); |
772 AddResult result(find(enteredKey), true); | 774 iterator findResult = find(enteredKey); |
773 ASSERT(result.iterator != end()); | 775 ASSERT(findResult != end()); |
776 ValueType* resultValue = findResult.get(); | |
777 AddResult result(resultValue, true); | |
774 return result; | 778 return result; |
775 } | 779 } |
776 | 780 |
777 return AddResult(makeKnownGoodIterator(entry), true); | 781 return AddResult(entry, true); |
778 } | 782 } |
779 | 783 |
780 template<typename Key, typename Value, typename Extractor, typename HashFunc tions, typename Traits, typename KeyTraits, typename Allocator> | 784 template<typename Key, typename Value, typename Extractor, typename HashFunc tions, typename Traits, typename KeyTraits, typename Allocator> |
781 inline void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTrait s, Allocator>::reinsert(ValueType& entry) | 785 inline void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTrait s, Allocator>::reinsert(ValueType& entry) |
782 { | 786 { |
783 ASSERT(m_table); | 787 ASSERT(m_table); |
784 ASSERT(!lookupForWriting(Extractor::extract(entry)).second); | 788 ASSERT(!lookupForWriting(Extractor::extract(entry)).second); |
785 ASSERT(!isDeletedBucket(*(lookupForWriting(Extractor::extract(entry)).fi rst))); | 789 ASSERT(!isDeletedBucket(*(lookupForWriting(Extractor::extract(entry)).fi rst))); |
786 #if DUMP_HASHTABLE_STATS | 790 #if DUMP_HASHTABLE_STATS |
787 atomicIncrement(&HashTableStats::numReinserts); | 791 atomicIncrement(&HashTableStats::numReinserts); |
(...skipping 373 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1161 inline bool operator!=(const HashTableIteratorAdapter<T, U>& a, const HashTa bleConstIteratorAdapter<T, U>& b) | 1165 inline bool operator!=(const HashTableIteratorAdapter<T, U>& a, const HashTa bleConstIteratorAdapter<T, U>& b) |
1162 { | 1166 { |
1163 return a.m_impl != b.m_impl; | 1167 return a.m_impl != b.m_impl; |
1164 } | 1168 } |
1165 | 1169 |
1166 } // namespace WTF | 1170 } // namespace WTF |
1167 | 1171 |
1168 #include "wtf/HashIterators.h" | 1172 #include "wtf/HashIterators.h" |
1169 | 1173 |
1170 #endif // WTF_HashTable_h | 1174 #endif // WTF_HashTable_h |
OLD | NEW |