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

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

Issue 152883002: (Concept patch) Simplify WTF::HashTable::add() return value for size and performance (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Created 6 years, 10 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
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 188 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698