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 503 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
514 { | 514 { |
515 // isAllocationAllowed check should be at the last because it's | 515 // isAllocationAllowed check should be at the last because it's |
516 // expensive. | 516 // expensive. |
517 return m_keyCount * m_minLoad < m_tableSize | 517 return m_keyCount * m_minLoad < m_tableSize |
518 && m_tableSize > KeyTraits::minimumTableSize | 518 && m_tableSize > KeyTraits::minimumTableSize |
519 && Allocator::isAllocationAllowed(); | 519 && Allocator::isAllocationAllowed(); |
520 } | 520 } |
521 ValueType* expand(ValueType* entry = 0); | 521 ValueType* expand(ValueType* entry = 0); |
522 void shrink() { rehash(m_tableSize / 2, 0); } | 522 void shrink() { rehash(m_tableSize / 2, 0); } |
523 | 523 |
524 ValueType* expandBuffer(unsigned newTableSize, ValueType* entry, bool&); | |
525 ValueType* rehashTo(ValueType* newTable, unsigned newTableSize, ValueTyp
e* entry); | |
526 ValueType* rehash(unsigned newTableSize, ValueType* entry); | 524 ValueType* rehash(unsigned newTableSize, ValueType* entry); |
527 ValueType* reinsert(ValueType&); | 525 ValueType* reinsert(ValueType&); |
528 | 526 |
529 static void initializeBucket(ValueType& bucket); | 527 static void initializeBucket(ValueType& bucket); |
530 static void deleteBucket(ValueType& bucket) { bucket.~ValueType(); Trait
s::constructDeletedValue(bucket, Allocator::isGarbageCollected); } | 528 static void deleteBucket(ValueType& bucket) { bucket.~ValueType(); Trait
s::constructDeletedValue(bucket, Allocator::isGarbageCollected); } |
531 | 529 |
532 FullLookupType makeLookupResult(ValueType* position, bool found, unsigne
d hash) | 530 FullLookupType makeLookupResult(ValueType* position, bool found, unsigne
d hash) |
533 { return FullLookupType(LookupType(position, found), hash); } | 531 { return FullLookupType(LookupType(position, found), hash); } |
534 | 532 |
535 iterator makeIterator(ValueType* pos) { return iterator(pos, m_table + m
_tableSize, this); } | 533 iterator makeIterator(ValueType* pos) { return iterator(pos, m_table + m
_tableSize, this); } |
(...skipping 505 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1041 newSize = m_tableSize; | 1039 newSize = m_tableSize; |
1042 } else { | 1040 } else { |
1043 newSize = m_tableSize * 2; | 1041 newSize = m_tableSize * 2; |
1044 RELEASE_ASSERT(newSize > m_tableSize); | 1042 RELEASE_ASSERT(newSize > m_tableSize); |
1045 } | 1043 } |
1046 | 1044 |
1047 return rehash(newSize, entry); | 1045 return rehash(newSize, entry); |
1048 } | 1046 } |
1049 | 1047 |
1050 template<typename Key, typename Value, typename Extractor, typename HashFunc
tions, typename Traits, typename KeyTraits, typename Allocator> | 1048 template<typename Key, typename Value, typename Extractor, typename HashFunc
tions, typename Traits, typename KeyTraits, typename Allocator> |
1051 Value* HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Al
locator>::expandBuffer(unsigned newTableSize, Value* entry, bool& success) | 1049 Value* HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Al
locator>::rehash(unsigned newTableSize, Value* entry) |
1052 { | |
1053 success = false; | |
1054 ASSERT(m_tableSize < newTableSize); | |
1055 if (!Allocator::expandHashTableBacking(m_table, newTableSize * sizeof(Va
lueType))) | |
1056 return 0; | |
1057 | |
1058 success = true; | |
1059 | |
1060 Value* newEntry = nullptr; | |
1061 unsigned oldTableSize = m_tableSize; | |
1062 ValueType* originalTable = m_table; | |
1063 | |
1064 ValueType* temporaryTable = allocateTable(oldTableSize); | |
1065 for (unsigned i = 0; i < oldTableSize; i++) { | |
1066 if (&m_table[i] == entry) | |
1067 newEntry = &temporaryTable[i]; | |
1068 Mover<ValueType, Allocator, Traits::needsDestruction>::move(m_table[
i], temporaryTable[i]); | |
1069 } | |
1070 m_table = temporaryTable; | |
1071 | |
1072 if (Traits::emptyValueIsZero) { | |
1073 memset(originalTable, 0, newTableSize * sizeof(ValueType)); | |
1074 } else { | |
1075 for (unsigned i = 0; i < newTableSize; i++) | |
1076 initializeBucket(originalTable[i]); | |
1077 } | |
1078 newEntry = rehashTo(originalTable, newTableSize, newEntry); | |
1079 deleteAllBucketsAndDeallocate(temporaryTable, oldTableSize); | |
1080 | |
1081 return newEntry; | |
1082 } | |
1083 | |
1084 template<typename Key, typename Value, typename Extractor, typename HashFunction
s, typename Traits, typename KeyTraits, typename Allocator> | |
1085 Value* HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Al
locator>::rehashTo(ValueType* newTable, unsigned newTableSize, Value* entry) | |
1086 { | 1050 { |
1087 unsigned oldTableSize = m_tableSize; | 1051 unsigned oldTableSize = m_tableSize; |
1088 ValueType* oldTable = m_table; | 1052 ValueType* oldTable = m_table; |
1089 | 1053 |
1090 #if DUMP_HASHTABLE_STATS | 1054 #if DUMP_HASHTABLE_STATS |
1091 if (oldTableSize != 0) | 1055 if (oldTableSize != 0) |
1092 atomicIncrement(&HashTableStats::numRehashes); | 1056 atomicIncrement(&HashTableStats::numRehashes); |
1093 #endif | 1057 #endif |
1094 | 1058 |
1095 #if DUMP_HASHTABLE_STATS_PER_TABLE | 1059 #if DUMP_HASHTABLE_STATS_PER_TABLE |
1096 if (oldTableSize != 0) | 1060 if (oldTableSize != 0) |
1097 ++m_stats->numRehashes; | 1061 ++m_stats->numRehashes; |
1098 #endif | 1062 #endif |
1099 | 1063 |
1100 m_table = newTable; | 1064 m_table = allocateTable(newTableSize); |
1101 m_tableSize = newTableSize; | 1065 m_tableSize = newTableSize; |
1102 | 1066 |
1103 Value* newEntry = 0; | 1067 Value* newEntry = 0; |
1104 for (unsigned i = 0; i != oldTableSize; ++i) { | 1068 for (unsigned i = 0; i != oldTableSize; ++i) { |
1105 if (isEmptyOrDeletedBucket(oldTable[i])) { | 1069 if (isEmptyOrDeletedBucket(oldTable[i])) { |
1106 ASSERT(&oldTable[i] != entry); | 1070 ASSERT(&oldTable[i] != entry); |
1107 continue; | 1071 continue; |
1108 } | 1072 } |
| 1073 |
1109 Value* reinsertedEntry = reinsert(oldTable[i]); | 1074 Value* reinsertedEntry = reinsert(oldTable[i]); |
1110 if (&oldTable[i] == entry) { | 1075 if (&oldTable[i] == entry) { |
1111 ASSERT(!newEntry); | 1076 ASSERT(!newEntry); |
1112 newEntry = reinsertedEntry; | 1077 newEntry = reinsertedEntry; |
1113 } | 1078 } |
1114 } | 1079 } |
1115 | 1080 |
1116 m_deletedCount = 0; | 1081 m_deletedCount = 0; |
1117 | 1082 |
1118 return newEntry; | |
1119 } | |
1120 | |
1121 template<typename Key, typename Value, typename Extractor, typename HashFunc
tions, typename Traits, typename KeyTraits, typename Allocator> | |
1122 Value* HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Al
locator>::rehash(unsigned newTableSize, Value* entry) | |
1123 { | |
1124 unsigned oldTableSize = m_tableSize; | |
1125 ValueType* oldTable = m_table; | |
1126 | |
1127 #if DUMP_HASHTABLE_STATS | |
1128 if (oldTableSize != 0) | |
1129 atomicIncrement(&HashTableStats::numRehashes); | |
1130 #endif | |
1131 | |
1132 #if DUMP_HASHTABLE_STATS_PER_TABLE | |
1133 if (oldTableSize != 0) | |
1134 ++m_stats->numRehashes; | |
1135 #endif | |
1136 | |
1137 // The Allocator::isGarbageCollected check is not needed. | |
1138 // The check is just a static hint for a compiler to indicate that | |
1139 // Base::expandBuffer returns false if Allocator is a DefaultAllocator. | |
1140 if (Allocator::isGarbageCollected && newTableSize > oldTableSize) { | |
1141 bool success; | |
1142 Value* newEntry = expandBuffer(newTableSize, entry, success); | |
1143 if (success) | |
1144 return newEntry; | |
1145 } | |
1146 | |
1147 ValueType* newTable = allocateTable(newTableSize); | |
1148 Value* newEntry = rehashTo(newTable, newTableSize, entry); | |
1149 deleteAllBucketsAndDeallocate(oldTable, oldTableSize); | 1083 deleteAllBucketsAndDeallocate(oldTable, oldTableSize); |
1150 | 1084 |
1151 return newEntry; | 1085 return newEntry; |
1152 } | 1086 } |
1153 | 1087 |
1154 template<typename Key, typename Value, typename Extractor, typename HashFunc
tions, typename Traits, typename KeyTraits, typename Allocator> | 1088 template<typename Key, typename Value, typename Extractor, typename HashFunc
tions, typename Traits, typename KeyTraits, typename Allocator> |
1155 void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allo
cator>::clear() | 1089 void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allo
cator>::clear() |
1156 { | 1090 { |
1157 registerModification(); | 1091 registerModification(); |
1158 if (!m_table) | 1092 if (!m_table) |
(...skipping 285 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1444 CollectionIterator end(toBeRemoved.end()); | 1378 CollectionIterator end(toBeRemoved.end()); |
1445 for (CollectionIterator it(toBeRemoved.begin()); it != end; ++it) | 1379 for (CollectionIterator it(toBeRemoved.begin()); it != end; ++it) |
1446 collection.remove(*it); | 1380 collection.remove(*it); |
1447 } | 1381 } |
1448 | 1382 |
1449 } // namespace WTF | 1383 } // namespace WTF |
1450 | 1384 |
1451 #include "wtf/HashIterators.h" | 1385 #include "wtf/HashIterators.h" |
1452 | 1386 |
1453 #endif // WTF_HashTable_h | 1387 #endif // WTF_HashTable_h |
OLD | NEW |