| 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 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 90 #endif | 90 #endif |
| 91 | 91 |
| 92 template<typename Key, typename Value, typename Extractor, typename HashFunc
tions, typename Traits, typename KeyTraits, typename Allocator> | 92 template<typename Key, typename Value, typename Extractor, typename HashFunc
tions, typename Traits, typename KeyTraits, typename Allocator> |
| 93 class HashTable; | 93 class HashTable; |
| 94 template<typename Key, typename Value, typename Extractor, typename HashFunc
tions, typename Traits, typename KeyTraits, typename Allocator> | 94 template<typename Key, typename Value, typename Extractor, typename HashFunc
tions, typename Traits, typename KeyTraits, typename Allocator> |
| 95 class HashTableIterator; | 95 class HashTableIterator; |
| 96 template<typename Key, typename Value, typename Extractor, typename HashFunc
tions, typename Traits, typename KeyTraits, typename Allocator> | 96 template<typename Key, typename Value, typename Extractor, typename HashFunc
tions, typename Traits, typename KeyTraits, typename Allocator> |
| 97 class HashTableConstIterator; | 97 class HashTableConstIterator; |
| 98 template<typename Value, typename HashFunctions, typename HashTraits, typena
me Allocator> | 98 template<typename Value, typename HashFunctions, typename HashTraits, typena
me Allocator> |
| 99 class LinkedHashSet; | 99 class LinkedHashSet; |
| 100 template<WeakHandlingFlag x, typename T, typename U, typename V, typename W,
typename X, typename Y, typename Z> | |
| 101 struct WeakProcessingHashTableHelper; | |
| 102 | 100 |
| 103 typedef enum { HashItemKnownGood } HashItemKnownGoodTag; | 101 typedef enum { HashItemKnownGood } HashItemKnownGoodTag; |
| 104 | 102 |
| 105 template<typename Key, typename Value, typename Extractor, typename HashFunc
tions, typename Traits, typename KeyTraits, typename Allocator> | 103 template<typename Key, typename Value, typename Extractor, typename HashFunc
tions, typename Traits, typename KeyTraits, typename Allocator> |
| 106 class HashTableConstIterator { | 104 class HashTableConstIterator { |
| 107 private: | 105 private: |
| 108 typedef HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTrait
s, Allocator> HashTableType; | 106 typedef HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTrait
s, Allocator> HashTableType; |
| 109 typedef HashTableIterator<Key, Value, Extractor, HashFunctions, Traits,
KeyTraits, Allocator> iterator; | 107 typedef HashTableIterator<Key, Value, Extractor, HashFunctions, Traits,
KeyTraits, Allocator> iterator; |
| 110 typedef HashTableConstIterator<Key, Value, Extractor, HashFunctions, Tra
its, KeyTraits, Allocator> const_iterator; | 108 typedef HashTableConstIterator<Key, Value, Extractor, HashFunctions, Tra
its, KeyTraits, Allocator> const_iterator; |
| 111 typedef Value ValueType; | 109 typedef Value ValueType; |
| (...skipping 444 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 556 bool m_queueFlag:1; | 554 bool m_queueFlag:1; |
| 557 #if ENABLE(ASSERT) | 555 #if ENABLE(ASSERT) |
| 558 unsigned m_modifications; | 556 unsigned m_modifications; |
| 559 #endif | 557 #endif |
| 560 | 558 |
| 561 #if DUMP_HASHTABLE_STATS_PER_TABLE | 559 #if DUMP_HASHTABLE_STATS_PER_TABLE |
| 562 public: | 560 public: |
| 563 mutable OwnPtr<Stats> m_stats; | 561 mutable OwnPtr<Stats> m_stats; |
| 564 #endif | 562 #endif |
| 565 | 563 |
| 566 template<WeakHandlingFlag x, typename T, typename U, typename V, typenam
e W, typename X, typename Y, typename Z> friend struct WeakProcessingHashTableHe
lper; | |
| 567 template<typename T, typename U, typename V, typename W> friend class Li
nkedHashSet; | 564 template<typename T, typename U, typename V, typename W> friend class Li
nkedHashSet; |
| 568 }; | 565 }; |
| 569 | 566 |
| 570 // Set all the bits to one after the most significant bit: 00110101010 -> 00
111111111. | 567 // Set all the bits to one after the most significant bit: 00110101010 -> 00
111111111. |
| 571 template<unsigned size> struct OneifyLowBits; | 568 template<unsigned size> struct OneifyLowBits; |
| 572 template<> | 569 template<> |
| 573 struct OneifyLowBits<0> { | 570 struct OneifyLowBits<0> { |
| 574 static const unsigned value = 0; | 571 static const unsigned value = 0; |
| 575 }; | 572 }; |
| 576 template<unsigned number> | 573 template<unsigned number> |
| (...skipping 567 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1144 } | 1141 } |
| 1145 | 1142 |
| 1146 template<typename Key, typename Value, typename Extractor, typename HashFunc
tions, typename Traits, typename KeyTraits, typename Allocator> | 1143 template<typename Key, typename Value, typename Extractor, typename HashFunc
tions, typename Traits, typename KeyTraits, typename Allocator> |
| 1147 HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator
>& HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>
::operator=(const HashTable& other) | 1144 HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator
>& HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>
::operator=(const HashTable& other) |
| 1148 { | 1145 { |
| 1149 HashTable tmp(other); | 1146 HashTable tmp(other); |
| 1150 swap(tmp); | 1147 swap(tmp); |
| 1151 return *this; | 1148 return *this; |
| 1152 } | 1149 } |
| 1153 | 1150 |
| 1154 template<WeakHandlingFlag weakHandlingFlag, typename Key, typename Value, ty
pename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, t
ypename Allocator> | |
| 1155 struct WeakProcessingHashTableHelper; | |
| 1156 | |
| 1157 template<typename Key, typename Value, typename Extractor, typename HashFunc
tions, typename Traits, typename KeyTraits, typename Allocator> | |
| 1158 struct WeakProcessingHashTableHelper<NoWeakHandlingInCollections, Key, Value
, Extractor, HashFunctions, Traits, KeyTraits, Allocator> { | |
| 1159 static void process(typename Allocator::Visitor* visitor, void* closure)
{ } | |
| 1160 static void ephemeronIteration(typename Allocator::Visitor* visitor, voi
d* closure) { } | |
| 1161 static void ephemeronIterationDone(typename Allocator::Visitor* visitor,
void* closure) { } | |
| 1162 }; | |
| 1163 | |
| 1164 template<typename Key, typename Value, typename Extractor, typename HashFunc
tions, typename Traits, typename KeyTraits, typename Allocator> | |
| 1165 struct WeakProcessingHashTableHelper<WeakHandlingInCollections, Key, Value,
Extractor, HashFunctions, Traits, KeyTraits, Allocator> { | |
| 1166 // Used for purely weak and for weak-and-strong tables (ephemerons). | |
| 1167 static void process(typename Allocator::Visitor* visitor, void* closure) | |
| 1168 { | |
| 1169 typedef HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyT
raits, Allocator> HashTableType; | |
| 1170 HashTableType* table = reinterpret_cast<HashTableType*>(closure); | |
| 1171 if (table->m_table) { | |
| 1172 // This is run as part of weak processing after full | |
| 1173 // marking. The backing store is therefore marked if | |
| 1174 // we get here. | |
| 1175 ASSERT(visitor->isAlive(table->m_table)); | |
| 1176 // Now perform weak processing (this is a no-op if the backing | |
| 1177 // was accessible through an iterator and was already marked | |
| 1178 // strongly). | |
| 1179 typedef typename HashTableType::ValueType ValueType; | |
| 1180 for (ValueType* element = table->m_table + table->m_tableSize -
1; element >= table->m_table; element--) { | |
| 1181 if (!HashTableType::isEmptyOrDeletedBucket(*element)) { | |
| 1182 // At this stage calling trace can make no difference | |
| 1183 // (everything is already traced), but we use the | |
| 1184 // return value to remove things from the collection. | |
| 1185 if (TraceInCollectionTrait<WeakHandlingInCollections, We
akPointersActWeak, ValueType, Traits>::trace(visitor, *element)) { | |
| 1186 table->registerModification(); | |
| 1187 HashTableType::deleteBucket(*element); // Also calls
the destructor. | |
| 1188 table->m_deletedCount++; | |
| 1189 table->m_keyCount--; | |
| 1190 // We don't rehash the backing until the next add | |
| 1191 // or delete, because that would cause allocation | |
| 1192 // during GC. | |
| 1193 } | |
| 1194 } | |
| 1195 } | |
| 1196 } | |
| 1197 } | |
| 1198 | |
| 1199 // Called repeatedly for tables that have both weak and strong pointers. | |
| 1200 static void ephemeronIteration(typename Allocator::Visitor* visitor, voi
d* closure) | |
| 1201 { | |
| 1202 typedef HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyT
raits, Allocator> HashTableType; | |
| 1203 HashTableType* table = reinterpret_cast<HashTableType*>(closure); | |
| 1204 if (table->m_table) { | |
| 1205 // Check the hash table for elements that we now know will not | |
| 1206 // be removed by weak processing. Those elements need to have | |
| 1207 // their strong pointers traced. | |
| 1208 typedef typename HashTableType::ValueType ValueType; | |
| 1209 for (ValueType* element = table->m_table + table->m_tableSize -
1; element >= table->m_table; element--) { | |
| 1210 if (!HashTableType::isEmptyOrDeletedBucket(*element)) | |
| 1211 TraceInCollectionTrait<WeakHandlingInCollections, WeakPo
intersActWeak, ValueType, Traits>::trace(visitor, *element); | |
| 1212 } | |
| 1213 } | |
| 1214 } | |
| 1215 | |
| 1216 // Called when the ephemeron iteration is done and before running the pe
r thread | |
| 1217 // weak processing. It is guaranteed to be called before any thread is r
esumed. | |
| 1218 static void ephemeronIterationDone(typename Allocator::Visitor* visitor,
void* closure) | |
| 1219 { | |
| 1220 typedef HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyT
raits, Allocator> HashTableType; | |
| 1221 HashTableType* table = reinterpret_cast<HashTableType*>(closure); | |
| 1222 ASSERT(Allocator::weakTableRegistered(visitor, table)); | |
| 1223 table->clearEnqueued(); | |
| 1224 } | |
| 1225 }; | |
| 1226 | |
| 1227 template<typename Key, typename Value, typename Extractor, typename HashFunc
tions, typename Traits, typename KeyTraits, typename Allocator> | |
| 1228 void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allo
cator>::trace(typename Allocator::Visitor* visitor) | |
| 1229 { | |
| 1230 // If someone else already marked the backing and queued up the trace | |
| 1231 // and/or weak callback then we are done. This optimization does not | |
| 1232 // happen for ListHashSet since its iterator does not point at the | |
| 1233 // backing. | |
| 1234 if (!m_table || visitor->isAlive(m_table)) | |
| 1235 return; | |
| 1236 // Normally, we mark the backing store without performing trace. This | |
| 1237 // means it is marked live, but the pointers inside it are not marked. | |
| 1238 // Instead we will mark the pointers below. However, for backing | |
| 1239 // stores that contain weak pointers the handling is rather different. | |
| 1240 // We don't mark the backing store here, so the marking GC will leave | |
| 1241 // the backing unmarked. If the backing is found in any other way than | |
| 1242 // through its HashTable (ie from an iterator) then the mark bit will | |
| 1243 // be set and the pointers will be marked strongly, avoiding problems | |
| 1244 // with iterating over things that disappear due to weak processing | |
| 1245 // while we are iterating over them. We register the backing store | |
| 1246 // pointer for delayed marking which will take place after we know if | |
| 1247 // the backing is reachable from elsewhere. We also register a | |
| 1248 // weakProcessing callback which will perform weak processing if needed. | |
| 1249 if (Traits::weakHandlingFlag == NoWeakHandlingInCollections) { | |
| 1250 Allocator::markNoTracing(visitor, m_table); | |
| 1251 } else { | |
| 1252 Allocator::registerDelayedMarkNoTracing(visitor, m_table); | |
| 1253 Allocator::registerWeakMembers(visitor, this, m_table, WeakProcessin
gHashTableHelper<Traits::weakHandlingFlag, Key, Value, Extractor, HashFunctions,
Traits, KeyTraits, Allocator>::process); | |
| 1254 } | |
| 1255 if (ShouldBeTraced<Traits>::value) { | |
| 1256 if (Traits::weakHandlingFlag == WeakHandlingInCollections) { | |
| 1257 // If we have both strong and weak pointers in the collection | |
| 1258 // then we queue up the collection for fixed point iteration a | |
| 1259 // la Ephemerons: | |
| 1260 // http://dl.acm.org/citation.cfm?doid=263698.263733 - see also | |
| 1261 // http://www.jucs.org/jucs_14_21/eliminating_cycles_in_weak | |
| 1262 ASSERT(!enqueued() || Allocator::weakTableRegistered(visitor, th
is)); | |
| 1263 if (!enqueued()) { | |
| 1264 Allocator::registerWeakTable(visitor, this, | |
| 1265 WeakProcessingHashTableHelper<Traits::weakHandlingFlag,
Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::ephemeronIt
eration, | |
| 1266 WeakProcessingHashTableHelper<Traits::weakHandlingFlag,
Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::ephemeronIt
erationDone); | |
| 1267 setEnqueued(); | |
| 1268 } | |
| 1269 // We don't need to trace the elements here, since registering | |
| 1270 // as a weak table above will cause them to be traced (perhaps | |
| 1271 // several times). It's better to wait until everything else is | |
| 1272 // traced before tracing the elements for the first time; this | |
| 1273 // may reduce (by one) the number of iterations needed to get | |
| 1274 // to a fixed point. | |
| 1275 return; | |
| 1276 } | |
| 1277 for (ValueType* element = m_table + m_tableSize - 1; element >= m_ta
ble; element--) { | |
| 1278 if (!isEmptyOrDeletedBucket(*element)) | |
| 1279 Allocator::template trace<ValueType, Traits>(visitor, *eleme
nt); | |
| 1280 } | |
| 1281 } | |
| 1282 } | |
| 1283 | |
| 1284 // iterator adapters | 1151 // iterator adapters |
| 1285 | 1152 |
| 1286 template<typename HashTableType, typename Traits> struct HashTableConstItera
torAdapter { | 1153 template<typename HashTableType, typename Traits> struct HashTableConstItera
torAdapter { |
| 1287 HashTableConstIteratorAdapter() {} | 1154 HashTableConstIteratorAdapter() {} |
| 1288 HashTableConstIteratorAdapter(const typename HashTableType::const_iterat
or& impl) : m_impl(impl) {} | 1155 HashTableConstIteratorAdapter(const typename HashTableType::const_iterat
or& impl) : m_impl(impl) {} |
| 1289 typedef typename Traits::IteratorConstGetType GetType; | 1156 typedef typename Traits::IteratorConstGetType GetType; |
| 1290 typedef typename HashTableType::ValueTraits::IteratorConstGetType Source
GetType; | 1157 typedef typename HashTableType::ValueTraits::IteratorConstGetType Source
GetType; |
| 1291 | 1158 |
| 1292 GetType get() const { return const_cast<GetType>(SourceGetType(m_impl.ge
t())); } | 1159 GetType get() const { return const_cast<GetType>(SourceGetType(m_impl.ge
t())); } |
| 1293 typename Traits::IteratorConstReferenceType operator*() const { return T
raits::getToReferenceConstConversion(get()); } | 1160 typename Traits::IteratorConstReferenceType operator*() const { return T
raits::getToReferenceConstConversion(get()); } |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1380 CollectionIterator end(toBeRemoved.end()); | 1247 CollectionIterator end(toBeRemoved.end()); |
| 1381 for (CollectionIterator it(toBeRemoved.begin()); it != end; ++it) | 1248 for (CollectionIterator it(toBeRemoved.begin()); it != end; ++it) |
| 1382 collection.remove(*it); | 1249 collection.remove(*it); |
| 1383 } | 1250 } |
| 1384 | 1251 |
| 1385 } // namespace WTF | 1252 } // namespace WTF |
| 1386 | 1253 |
| 1387 #include "wtf/HashIterators.h" | 1254 #include "wtf/HashIterators.h" |
| 1388 | 1255 |
| 1389 #endif // WTF_HashTable_h | 1256 #endif // WTF_HashTable_h |
| OLD | NEW |