OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef TraceTraits_h | 5 #ifndef TraceTraits_h |
6 #define TraceTraits_h | 6 #define TraceTraits_h |
7 | 7 |
8 #include "platform/heap/GCInfo.h" | 8 #include "platform/heap/GCInfo.h" |
9 #include "platform/heap/Heap.h" | 9 #include "platform/heap/Heap.h" |
10 #include "platform/heap/InlinedGlobalMarkingVisitor.h" | 10 #include "platform/heap/InlinedGlobalMarkingVisitor.h" |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
97 // the dangling pointer. | 97 // the dangling pointer. |
98 // Release builds don't have the ASSERT, but it is OK because | 98 // Release builds don't have the ASSERT, but it is OK because |
99 // release builds will crash at the following self->adjustAndMark | 99 // release builds will crash at the following self->adjustAndMark |
100 // because all the entries of the orphaned arenas are zeroed out and | 100 // because all the entries of the orphaned arenas are zeroed out and |
101 // thus the item does not have a valid vtable. | 101 // thus the item does not have a valid vtable. |
102 ASSERT(!pageFromObject(self)->orphaned()); | 102 ASSERT(!pageFromObject(self)->orphaned()); |
103 self->adjustAndMark(visitor); | 103 self->adjustAndMark(visitor); |
104 } | 104 } |
105 }; | 105 }; |
106 | 106 |
107 template<typename T, bool needsTracing> | 107 template<typename T, bool isTraceable> |
108 struct TraceIfEnabled; | 108 struct TraceIfEnabled; |
109 | 109 |
110 template<typename T> | 110 template<typename T> |
111 struct TraceIfEnabled<T, false> { | 111 struct TraceIfEnabled<T, false> { |
112 STATIC_ONLY(TraceIfEnabled); | 112 STATIC_ONLY(TraceIfEnabled); |
113 template<typename VisitorDispatcher> | 113 template<typename VisitorDispatcher> |
114 static void trace(VisitorDispatcher, T&) | 114 static void trace(VisitorDispatcher, T&) |
115 { | 115 { |
116 static_assert(!WTF::NeedsTracing<T>::value, "T should not be traced"); | 116 static_assert(!WTF::IsTraceable<T>::value, "T should not be traced"); |
117 } | 117 } |
118 }; | 118 }; |
119 | 119 |
120 template<typename T> | 120 template<typename T> |
121 struct TraceIfEnabled<T, true> { | 121 struct TraceIfEnabled<T, true> { |
122 STATIC_ONLY(TraceIfEnabled); | 122 STATIC_ONLY(TraceIfEnabled); |
123 template<typename VisitorDispatcher> | 123 template<typename VisitorDispatcher> |
124 static void trace(VisitorDispatcher visitor, T& t) | 124 static void trace(VisitorDispatcher visitor, T& t) |
125 { | 125 { |
126 static_assert(WTF::NeedsTracing<T>::value || WTF::IsWeak<T>::value, "T s
hould be traced"); | 126 static_assert(WTF::IsTraceable<T>::value, "T should not be traced"); |
127 visitor->trace(t); | 127 visitor->trace(t); |
128 } | 128 } |
129 }; | 129 }; |
130 | 130 |
131 template<bool needsTracing, WTF::WeakHandlingFlag weakHandlingFlag, WTF::ShouldW
eakPointersBeMarkedStrongly strongify, typename T, typename Traits> struct Trace
CollectionIfEnabled; | 131 template<bool isTraceable, WTF::WeakHandlingFlag weakHandlingFlag, WTF::ShouldWe
akPointersBeMarkedStrongly strongify, typename T, typename Traits> struct TraceC
ollectionIfEnabled; |
132 | 132 |
133 template<WTF::ShouldWeakPointersBeMarkedStrongly strongify, typename T, typename
Traits> | 133 template<WTF::ShouldWeakPointersBeMarkedStrongly strongify, typename T, typename
Traits> |
134 struct TraceCollectionIfEnabled<false, WTF::NoWeakHandlingInCollections, strongi
fy, T, Traits> { | 134 struct TraceCollectionIfEnabled<false, WTF::NoWeakHandlingInCollections, strongi
fy, T, Traits> { |
135 STATIC_ONLY(TraceCollectionIfEnabled); | 135 STATIC_ONLY(TraceCollectionIfEnabled); |
136 template<typename VisitorDispatcher> | 136 template<typename VisitorDispatcher> |
137 static bool trace(VisitorDispatcher, T&) | 137 static bool trace(VisitorDispatcher, T&) |
138 { | 138 { |
139 static_assert(!WTF::NeedsTracingTrait<Traits>::value, "Traits should not
be traced"); | 139 static_assert(!WTF::IsTraceableInCollectionTrait<Traits>::value, "T shou
ld not be traced"); |
140 return false; | 140 return false; |
141 } | 141 } |
142 }; | 142 }; |
143 | 143 |
144 template<bool needsTracing, WTF::WeakHandlingFlag weakHandlingFlag, WTF::ShouldW
eakPointersBeMarkedStrongly strongify, typename T, typename Traits> | 144 template<bool isTraceable, WTF::WeakHandlingFlag weakHandlingFlag, WTF::ShouldWe
akPointersBeMarkedStrongly strongify, typename T, typename Traits> |
145 struct TraceCollectionIfEnabled { | 145 struct TraceCollectionIfEnabled { |
146 STATIC_ONLY(TraceCollectionIfEnabled); | 146 STATIC_ONLY(TraceCollectionIfEnabled); |
147 template<typename VisitorDispatcher> | 147 template<typename VisitorDispatcher> |
148 static bool trace(VisitorDispatcher visitor, T& t) | 148 static bool trace(VisitorDispatcher visitor, T& t) |
149 { | 149 { |
150 static_assert(WTF::NeedsTracingTrait<Traits>::value || weakHandlingFlag
== WTF::WeakHandlingInCollections, "Traits should be traced"); | 150 static_assert(WTF::IsTraceableInCollectionTrait<Traits>::value || weakHa
ndlingFlag == WTF::WeakHandlingInCollections, "Traits should be traced"); |
151 return WTF::TraceInCollectionTrait<weakHandlingFlag, strongify, T, Trait
s>::trace(visitor, t); | 151 return WTF::TraceInCollectionTrait<weakHandlingFlag, strongify, T, Trait
s>::trace(visitor, t); |
152 } | 152 } |
153 }; | 153 }; |
154 | 154 |
155 // The TraceTrait is used to specify how to mark an object pointer and | 155 // The TraceTrait is used to specify how to mark an object pointer and |
156 // how to trace all of the pointers in the object. | 156 // how to trace all of the pointers in the object. |
157 // | 157 // |
158 // By default, the 'trace' method implemented on an object itself is | 158 // By default, the 'trace' method implemented on an object itself is |
159 // used to trace the pointers to other heap objects inside the object. | 159 // used to trace the pointers to other heap objects inside the object. |
160 // | 160 // |
(...skipping 19 matching lines...) Expand all Loading... |
180 { | 180 { |
181 AdjustAndMarkTrait<T>::mark(visitor, t); | 181 AdjustAndMarkTrait<T>::mark(visitor, t); |
182 } | 182 } |
183 }; | 183 }; |
184 | 184 |
185 template<typename T> class TraceTrait<const T> : public TraceTrait<T> { }; | 185 template<typename T> class TraceTrait<const T> : public TraceTrait<T> { }; |
186 | 186 |
187 template<typename T> | 187 template<typename T> |
188 void TraceTrait<T>::trace(Visitor* visitor, void* self) | 188 void TraceTrait<T>::trace(Visitor* visitor, void* self) |
189 { | 189 { |
190 static_assert(WTF::NeedsTracing<T>::value || WTF::IsWeak<T>::value, "T shoul
d be traced"); | 190 static_assert(WTF::IsTraceable<T>::value, "T should not be traced"); |
191 if (visitor->getMarkingMode() == Visitor::GlobalMarking) { | 191 if (visitor->getMarkingMode() == Visitor::GlobalMarking) { |
192 // Switch to inlined global marking dispatch. | 192 // Switch to inlined global marking dispatch. |
193 static_cast<T*>(self)->trace(InlinedGlobalMarkingVisitor(visitor->state(
))); | 193 static_cast<T*>(self)->trace(InlinedGlobalMarkingVisitor(visitor->state(
))); |
194 } else { | 194 } else { |
195 static_cast<T*>(self)->trace(visitor); | 195 static_cast<T*>(self)->trace(visitor); |
196 } | 196 } |
197 } | 197 } |
198 | 198 |
199 template<typename T> | 199 template<typename T> |
200 void TraceTrait<T>::trace(InlinedGlobalMarkingVisitor visitor, void* self) | 200 void TraceTrait<T>::trace(InlinedGlobalMarkingVisitor visitor, void* self) |
201 { | 201 { |
202 static_assert(WTF::NeedsTracing<T>::value || WTF::IsWeak<T>::value, "T shoul
d be traced"); | 202 static_assert(WTF::IsTraceable<T>::value, "T should not be traced"); |
203 static_cast<T*>(self)->trace(visitor); | 203 static_cast<T*>(self)->trace(visitor); |
204 } | 204 } |
205 | 205 |
206 template<typename T, typename Traits> | 206 template<typename T, typename Traits> |
207 struct TraceTrait<HeapVectorBacking<T, Traits>> { | 207 struct TraceTrait<HeapVectorBacking<T, Traits>> { |
208 STATIC_ONLY(TraceTrait); | 208 STATIC_ONLY(TraceTrait); |
209 using Backing = HeapVectorBacking<T, Traits>; | 209 using Backing = HeapVectorBacking<T, Traits>; |
210 | 210 |
211 template<typename VisitorDispatcher> | 211 template<typename VisitorDispatcher> |
212 static void trace(VisitorDispatcher visitor, void* self) | 212 static void trace(VisitorDispatcher visitor, void* self) |
213 { | 213 { |
214 static_assert(!WTF::IsWeak<T>::value, "weakness in HeapVectors and Deque
s are not supported"); | 214 static_assert(!WTF::IsWeak<T>::value, "weakness in HeapVectors and HeapD
eques are not supported"); |
215 if (WTF::NeedsTracingTrait<Traits>::value) | 215 if (WTF::IsTraceableInCollectionTrait<Traits>::value) |
216 WTF::TraceInCollectionTrait<WTF::NoWeakHandlingInCollections, WTF::W
eakPointersActWeak, HeapVectorBacking<T, Traits>, void>::trace(visitor, self); | 216 WTF::TraceInCollectionTrait<WTF::NoWeakHandlingInCollections, WTF::W
eakPointersActWeak, HeapVectorBacking<T, Traits>, void>::trace(visitor, self); |
217 } | 217 } |
218 | 218 |
219 template<typename VisitorDispatcher> | 219 template<typename VisitorDispatcher> |
220 static void mark(VisitorDispatcher visitor, const Backing* backing) | 220 static void mark(VisitorDispatcher visitor, const Backing* backing) |
221 { | 221 { |
222 AdjustAndMarkTrait<Backing>::mark(visitor, backing); | 222 AdjustAndMarkTrait<Backing>::mark(visitor, backing); |
223 } | 223 } |
224 }; | 224 }; |
225 | 225 |
226 // The trace trait for the heap hashtable backing is used when we find a | 226 // The trace trait for the heap hashtable backing is used when we find a |
227 // direct pointer to the backing from the conservative stack scanner. This | 227 // direct pointer to the backing from the conservative stack scanner. This |
228 // normally indicates that there is an ongoing iteration over the table, and so | 228 // normally indicates that there is an ongoing iteration over the table, and so |
229 // we disable weak processing of table entries. When the backing is found | 229 // we disable weak processing of table entries. When the backing is found |
230 // through the owning hash table we mark differently, in order to do weak | 230 // through the owning hash table we mark differently, in order to do weak |
231 // processing. | 231 // processing. |
232 template<typename Table> | 232 template<typename Table> |
233 struct TraceTrait<HeapHashTableBacking<Table>> { | 233 struct TraceTrait<HeapHashTableBacking<Table>> { |
234 STATIC_ONLY(TraceTrait); | 234 STATIC_ONLY(TraceTrait); |
235 using Backing = HeapHashTableBacking<Table>; | 235 using Backing = HeapHashTableBacking<Table>; |
236 using Traits = typename Table::ValueTraits; | 236 using Traits = typename Table::ValueTraits; |
237 | 237 |
238 template<typename VisitorDispatcher> | 238 template<typename VisitorDispatcher> |
239 static void trace(VisitorDispatcher visitor, void* self) | 239 static void trace(VisitorDispatcher visitor, void* self) |
240 { | 240 { |
241 if (WTF::NeedsTracingTrait<Traits>::value || Traits::weakHandlingFlag ==
WTF::WeakHandlingInCollections) | 241 if (WTF::IsTraceableInCollectionTrait<Traits>::value || Traits::weakHand
lingFlag == WTF::WeakHandlingInCollections) |
242 WTF::TraceInCollectionTrait<WTF::NoWeakHandlingInCollections, WTF::W
eakPointersActStrong, Backing, void>::trace(visitor, self); | 242 WTF::TraceInCollectionTrait<WTF::NoWeakHandlingInCollections, WTF::W
eakPointersActStrong, Backing, void>::trace(visitor, self); |
243 } | 243 } |
244 | 244 |
245 template<typename VisitorDispatcher> | 245 template<typename VisitorDispatcher> |
246 static void mark(VisitorDispatcher visitor, const Backing* backing) | 246 static void mark(VisitorDispatcher visitor, const Backing* backing) |
247 { | 247 { |
248 AdjustAndMarkTrait<Backing>::mark(visitor, backing); | 248 AdjustAndMarkTrait<Backing>::mark(visitor, backing); |
249 } | 249 } |
250 }; | 250 }; |
251 | 251 |
252 // This trace trait for std::pair will null weak members if their referent is | 252 // This trace trait for std::pair will null weak members if their referent is |
253 // collected. If you have a collection that contain weakness it does not remove | 253 // collected. If you have a collection that contain weakness it does not remove |
254 // entries from the collection that contain nulled weak members. | 254 // entries from the collection that contain nulled weak members. |
255 template<typename T, typename U> | 255 template<typename T, typename U> |
256 class TraceTrait<std::pair<T, U>> { | 256 class TraceTrait<std::pair<T, U>> { |
257 STATIC_ONLY(TraceTrait); | 257 STATIC_ONLY(TraceTrait); |
258 public: | 258 public: |
259 static const bool firstNeedsTracing = WTF::NeedsTracing<T>::value || WTF::Is
Weak<T>::value; | 259 static const bool firstIsTraceable = WTF::IsTraceable<T>::value; |
260 static const bool secondNeedsTracing = WTF::NeedsTracing<U>::value || WTF::I
sWeak<U>::value; | 260 static const bool secondIsTraceable = WTF::IsTraceable<U>::value; |
261 template<typename VisitorDispatcher> | 261 template<typename VisitorDispatcher> |
262 static void trace(VisitorDispatcher visitor, std::pair<T, U>* pair) | 262 static void trace(VisitorDispatcher visitor, std::pair<T, U>* pair) |
263 { | 263 { |
264 TraceIfEnabled<T, firstNeedsTracing>::trace(visitor, pair->first); | 264 TraceIfEnabled<T, firstIsTraceable>::trace(visitor, pair->first); |
265 TraceIfEnabled<U, secondNeedsTracing>::trace(visitor, pair->second); | 265 TraceIfEnabled<U, secondIsTraceable>::trace(visitor, pair->second); |
266 } | 266 } |
267 }; | 267 }; |
268 | 268 |
269 // If eager tracing leads to excessively deep |trace()| call chains (and | 269 // If eager tracing leads to excessively deep |trace()| call chains (and |
270 // the system stack usage that this brings), the marker implementation will | 270 // the system stack usage that this brings), the marker implementation will |
271 // switch to using an explicit mark stack. Recursive and deep object graphs | 271 // switch to using an explicit mark stack. Recursive and deep object graphs |
272 // are uncommon for Blink objects. | 272 // are uncommon for Blink objects. |
273 // | 273 // |
274 // A class type can opt out of eager tracing by declaring a TraceEagerlyTrait<> | 274 // A class type can opt out of eager tracing by declaring a TraceEagerlyTrait<> |
275 // specialization, mapping the trait's |value| to |false| (see the | 275 // specialization, mapping the trait's |value| to |false| (see the |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
347 }; | 347 }; |
348 | 348 |
349 template<typename ValueArg, size_t inlineCapacity> class HeapListHashSetAllocato
r; | 349 template<typename ValueArg, size_t inlineCapacity> class HeapListHashSetAllocato
r; |
350 template<typename T, size_t inlineCapacity> | 350 template<typename T, size_t inlineCapacity> |
351 class TraceEagerlyTrait<WTF::ListHashSetNode<T, HeapListHashSetAllocator<T, inli
neCapacity>>> { | 351 class TraceEagerlyTrait<WTF::ListHashSetNode<T, HeapListHashSetAllocator<T, inli
neCapacity>>> { |
352 STATIC_ONLY(TraceEagerlyTrait); | 352 STATIC_ONLY(TraceEagerlyTrait); |
353 public: | 353 public: |
354 static const bool value = false; | 354 static const bool value = false; |
355 }; | 355 }; |
356 | 356 |
357 template <typename T> struct RemoveHeapPointerWrapperTypes { | |
358 STATIC_ONLY(RemoveHeapPointerWrapperTypes); | |
359 using Type = typename WTF::RemoveTemplate<typename WTF::RemoveTemplate<T, Me
mber>::Type, WeakMember>::Type; | |
360 }; | |
361 | |
362 // FIXME: Oilpan: TraceIfNeeded should be implemented ala: | |
363 // NeedsTracing<T>::value || IsWeakMember<T>::value. It should not need to test | |
364 // raw pointer types. | |
365 template<typename T> | 357 template<typename T> |
366 struct TraceIfNeeded : public TraceIfEnabled<T, WTF::NeedsTracing<T>::value || I
sGarbageCollectedType<typename RemoveHeapPointerWrapperTypes<typename std::remov
e_pointer<T>::type>::Type>::value> { | 358 struct TraceIfNeeded : public TraceIfEnabled<T, WTF::IsTraceable<T>::value> { |
367 STATIC_ONLY(TraceIfNeeded); | 359 STATIC_ONLY(TraceIfNeeded); |
368 }; | 360 }; |
369 | 361 |
370 } // namespace blink | 362 } // namespace blink |
371 | 363 |
372 namespace WTF { | 364 namespace WTF { |
373 | 365 |
374 // Catch-all for types that have a way to trace that don't have special | 366 // Catch-all for types that have a way to trace that don't have special |
375 // handling for weakness in collections. This means that if this type | 367 // handling for weakness in collections. This means that if this type |
376 // contains WeakMember fields, they will simply be zeroed, but the entry | 368 // contains WeakMember fields, they will simply be zeroed, but the entry |
377 // will not be removed from the collection. This always happens for | 369 // will not be removed from the collection. This always happens for |
378 // things in vectors, which don't currently support special handling of | 370 // things in vectors, which don't currently support special handling of |
379 // weak elements. | 371 // weak elements. |
380 template<ShouldWeakPointersBeMarkedStrongly strongify, typename T, typename Trai
ts> | 372 template<ShouldWeakPointersBeMarkedStrongly strongify, typename T, typename Trai
ts> |
381 struct TraceInCollectionTrait<NoWeakHandlingInCollections, strongify, T, Traits>
{ | 373 struct TraceInCollectionTrait<NoWeakHandlingInCollections, strongify, T, Traits>
{ |
382 template<typename VisitorDispatcher> | 374 template<typename VisitorDispatcher> |
383 static bool trace(VisitorDispatcher visitor, T& t) | 375 static bool trace(VisitorDispatcher visitor, T& t) |
384 { | 376 { |
385 ASSERT(NeedsTracingTrait<Traits>::value); | 377 DCHECK(IsTraceableInCollectionTrait<Traits>::value); |
386 visitor->trace(t); | 378 visitor->trace(t); |
387 return false; | 379 return false; |
388 } | 380 } |
389 }; | 381 }; |
390 | 382 |
391 // Catch-all for things that have HashTrait support for tracing with weakness. | 383 // Catch-all for things that have HashTrait support for tracing with weakness. |
392 template<ShouldWeakPointersBeMarkedStrongly strongify, typename T, typename Trai
ts> | 384 template<ShouldWeakPointersBeMarkedStrongly strongify, typename T, typename Trai
ts> |
393 struct TraceInCollectionTrait<WeakHandlingInCollections, strongify, T, Traits> { | 385 struct TraceInCollectionTrait<WeakHandlingInCollections, strongify, T, Traits> { |
394 template<typename VisitorDispatcher> | 386 template<typename VisitorDispatcher> |
395 static bool trace(VisitorDispatcher visitor, T& t) | 387 static bool trace(VisitorDispatcher visitor, T& t) |
(...skipping 17 matching lines...) Expand all Loading... |
413 // traces only slots that are not zeroed out. This is because if | 405 // traces only slots that are not zeroed out. This is because if |
414 // the object has a vtable, the zeroed slot means that it is | 406 // the object has a vtable, the zeroed slot means that it is |
415 // an unused slot (Remember that the unused slots are guaranteed | 407 // an unused slot (Remember that the unused slots are guaranteed |
416 // to be zeroed out by VectorUnusedSlotClearer). | 408 // to be zeroed out by VectorUnusedSlotClearer). |
417 // | 409 // |
418 // - An object that can be initialized with memset. In this case, | 410 // - An object that can be initialized with memset. In this case, |
419 // HeapVectorBacking traces all slots including unused slots. | 411 // HeapVectorBacking traces all slots including unused slots. |
420 // This is fine because the fact that the object can be initialized | 412 // This is fine because the fact that the object can be initialized |
421 // with memset indicates that it is safe to treat the zerod slot | 413 // with memset indicates that it is safe to treat the zerod slot |
422 // as a valid object. | 414 // as a valid object. |
423 static_assert(!NeedsTracingTrait<Traits>::value || Traits::canClearUnuse
dSlotsWithMemset || std::is_polymorphic<T>::value, "HeapVectorBacking doesn't su
pport objects that cannot be cleared as unused with memset."); | 415 static_assert(!IsTraceableInCollectionTrait<Traits>::value || Traits::ca
nClearUnusedSlotsWithMemset || std::is_polymorphic<T>::value, "HeapVectorBacking
doesn't support objects that cannot be cleared as unused with memset."); |
424 | 416 |
425 // This trace method is instantiated for vectors where | 417 // This trace method is instantiated for vectors where |
426 // NeedsTracingTrait<Traits>::value is false, but the trace method | 418 // IsTraceableInCollectionTrait<Traits>::value is false, but the trace m
ethod |
427 // should not be called. Thus we cannot static-assert | 419 // should not be called. Thus we cannot static-assert |
428 // NeedsTracingTrait<Traits>::value but should runtime-assert it. | 420 // IsTraceableInCollectionTrait<Traits>::value but should runtime-assert
it. |
429 ASSERT(NeedsTracingTrait<Traits>::value); | 421 DCHECK(IsTraceableInCollectionTrait<Traits>::value); |
430 | 422 |
431 T* array = reinterpret_cast<T*>(self); | 423 T* array = reinterpret_cast<T*>(self); |
432 blink::HeapObjectHeader* header = blink::HeapObjectHeader::fromPayload(s
elf); | 424 blink::HeapObjectHeader* header = blink::HeapObjectHeader::fromPayload(s
elf); |
433 ASSERT(header->checkHeader()); | 425 ASSERT(header->checkHeader()); |
434 // Use the payload size as recorded by the heap to determine how many | 426 // Use the payload size as recorded by the heap to determine how many |
435 // elements to trace. | 427 // elements to trace. |
436 size_t length = header->payloadSize() / sizeof(T); | 428 size_t length = header->payloadSize() / sizeof(T); |
437 if (std::is_polymorphic<T>::value) { | 429 if (std::is_polymorphic<T>::value) { |
438 for (size_t i = 0; i < length; ++i) { | 430 for (size_t i = 0; i < length; ++i) { |
439 if (blink::vTableInitialized(&array[i])) | 431 if (blink::vTableInitialized(&array[i])) |
440 blink::TraceIfEnabled<T, NeedsTracingTrait<Traits>::value>::
trace(visitor, array[i]); | 432 blink::TraceIfEnabled<T, IsTraceableInCollectionTrait<Traits
>::value>::trace(visitor, array[i]); |
441 } | 433 } |
442 } else { | 434 } else { |
443 #ifdef ANNOTATE_CONTIGUOUS_CONTAINER | 435 #ifdef ANNOTATE_CONTIGUOUS_CONTAINER |
444 // As commented above, HeapVectorBacking can trace unused slots | 436 // As commented above, HeapVectorBacking can trace unused slots |
445 // (which are already zeroed out). | 437 // (which are already zeroed out). |
446 ANNOTATE_CHANGE_SIZE(array, length, 0, length); | 438 ANNOTATE_CHANGE_SIZE(array, length, 0, length); |
447 #endif | 439 #endif |
448 for (size_t i = 0; i < length; ++i) | 440 for (size_t i = 0; i < length; ++i) |
449 blink::TraceIfEnabled<T, NeedsTracingTrait<Traits>::value>::trac
e(visitor, array[i]); | 441 blink::TraceIfEnabled<T, IsTraceableInCollectionTrait<Traits>::v
alue>::trace(visitor, array[i]); |
450 } | 442 } |
451 return false; | 443 return false; |
452 } | 444 } |
453 }; | 445 }; |
454 | 446 |
455 // This trace method is used only for on-stack HeapHashTables found in | 447 // This trace method is used only for on-stack HeapHashTables found in |
456 // conservative scanning. On-heap HeapHashTables are traced by HashTable::trace. | 448 // conservative scanning. On-heap HeapHashTables are traced by HashTable::trace. |
457 template<ShouldWeakPointersBeMarkedStrongly strongify, typename Table> | 449 template<ShouldWeakPointersBeMarkedStrongly strongify, typename Table> |
458 struct TraceInCollectionTrait<NoWeakHandlingInCollections, strongify, blink::Hea
pHashTableBacking<Table>, void> { | 450 struct TraceInCollectionTrait<NoWeakHandlingInCollections, strongify, blink::Hea
pHashTableBacking<Table>, void> { |
459 using Value = typename Table::ValueType; | 451 using Value = typename Table::ValueType; |
460 using Traits = typename Table::ValueTraits; | 452 using Traits = typename Table::ValueTraits; |
461 | 453 |
462 template<typename VisitorDispatcher> | 454 template<typename VisitorDispatcher> |
463 static bool trace(VisitorDispatcher visitor, void* self) | 455 static bool trace(VisitorDispatcher visitor, void* self) |
464 { | 456 { |
465 static_assert(strongify == WTF::WeakPointersActStrong, "An on-stack Heap
HashTable needs to be visited strongly."); | 457 static_assert(strongify == WTF::WeakPointersActStrong, "An on-stack Heap
HashTable needs to be visited strongly."); |
466 | 458 |
467 ASSERT(NeedsTracingTrait<Traits>::value || Traits::weakHandlingFlag == W
eakHandlingInCollections); | 459 DCHECK(IsTraceableInCollectionTrait<Traits>::value || Traits::weakHandli
ngFlag == WeakHandlingInCollections); |
468 Value* array = reinterpret_cast<Value*>(self); | 460 Value* array = reinterpret_cast<Value*>(self); |
469 blink::HeapObjectHeader* header = blink::HeapObjectHeader::fromPayload(s
elf); | 461 blink::HeapObjectHeader* header = blink::HeapObjectHeader::fromPayload(s
elf); |
470 ASSERT(header->checkHeader()); | 462 ASSERT(header->checkHeader()); |
471 // Use the payload size as recorded by the heap to determine how many | 463 // Use the payload size as recorded by the heap to determine how many |
472 // elements to trace. | 464 // elements to trace. |
473 size_t length = header->payloadSize() / sizeof(Value); | 465 size_t length = header->payloadSize() / sizeof(Value); |
474 for (size_t i = 0; i < length; ++i) { | 466 for (size_t i = 0; i < length; ++i) { |
475 if (!HashTableHelper<Value, typename Table::ExtractorType, typename
Table::KeyTraitsType>::isEmptyOrDeletedBucket(array[i])) | 467 if (!HashTableHelper<Value, typename Table::ExtractorType, typename
Table::KeyTraitsType>::isEmptyOrDeletedBucket(array[i])) |
476 blink::TraceCollectionIfEnabled<NeedsTracingTrait<Traits>::value
, Traits::weakHandlingFlag, strongify, Value, Traits>::trace(visitor, array[i]); | 468 blink::TraceCollectionIfEnabled<IsTraceableInCollectionTrait<Tra
its>::value, Traits::weakHandlingFlag, strongify, Value, Traits>::trace(visitor,
array[i]); |
477 } | 469 } |
478 return false; | 470 return false; |
479 } | 471 } |
480 }; | 472 }; |
481 | 473 |
482 // This specialization of TraceInCollectionTrait is for the backing of | 474 // This specialization of TraceInCollectionTrait is for the backing of |
483 // HeapListHashSet. This is for the case that we find a reference to the | 475 // HeapListHashSet. This is for the case that we find a reference to the |
484 // backing from the stack. That probably means we have a GC while we are in a | 476 // backing from the stack. That probably means we have a GC while we are in a |
485 // ListHashSet method since normal API use does not put pointers to the backing | 477 // ListHashSet method since normal API use does not put pointers to the backing |
486 // on the stack. | 478 // on the stack. |
(...skipping 24 matching lines...) Expand all Loading... |
511 }; | 503 }; |
512 | 504 |
513 // Key value pairs, as used in HashMap. To disambiguate template choice we have | 505 // Key value pairs, as used in HashMap. To disambiguate template choice we have |
514 // to have two versions, first the one with no special weak handling, then the | 506 // to have two versions, first the one with no special weak handling, then the |
515 // one with weak handling. | 507 // one with weak handling. |
516 template<ShouldWeakPointersBeMarkedStrongly strongify, typename Key, typename Va
lue, typename Traits> | 508 template<ShouldWeakPointersBeMarkedStrongly strongify, typename Key, typename Va
lue, typename Traits> |
517 struct TraceInCollectionTrait<NoWeakHandlingInCollections, strongify, KeyValuePa
ir<Key, Value>, Traits> { | 509 struct TraceInCollectionTrait<NoWeakHandlingInCollections, strongify, KeyValuePa
ir<Key, Value>, Traits> { |
518 template<typename VisitorDispatcher> | 510 template<typename VisitorDispatcher> |
519 static bool trace(VisitorDispatcher visitor, KeyValuePair<Key, Value>& self) | 511 static bool trace(VisitorDispatcher visitor, KeyValuePair<Key, Value>& self) |
520 { | 512 { |
521 ASSERT(NeedsTracingTrait<Traits>::value); | 513 DCHECK(IsTraceableInCollectionTrait<Traits>::value); |
522 blink::TraceCollectionIfEnabled<NeedsTracingTrait<typename Traits::KeyTr
aits>::value, NoWeakHandlingInCollections, strongify, Key, typename Traits::KeyT
raits>::trace(visitor, self.key); | 514 blink::TraceCollectionIfEnabled<IsTraceableInCollectionTrait<typename Tr
aits::KeyTraits>::value, NoWeakHandlingInCollections, strongify, Key, typename T
raits::KeyTraits>::trace(visitor, self.key); |
523 blink::TraceCollectionIfEnabled<NeedsTracingTrait<typename Traits::Value
Traits>::value, NoWeakHandlingInCollections, strongify, Value, typename Traits::
ValueTraits>::trace(visitor, self.value); | 515 blink::TraceCollectionIfEnabled<IsTraceableInCollectionTrait<typename Tr
aits::ValueTraits>::value, NoWeakHandlingInCollections, strongify, Value, typena
me Traits::ValueTraits>::trace(visitor, self.value); |
524 return false; | 516 return false; |
525 } | 517 } |
526 }; | 518 }; |
527 | 519 |
528 template<ShouldWeakPointersBeMarkedStrongly strongify, typename Key, typename Va
lue, typename Traits> | 520 template<ShouldWeakPointersBeMarkedStrongly strongify, typename Key, typename Va
lue, typename Traits> |
529 struct TraceInCollectionTrait<WeakHandlingInCollections, strongify, KeyValuePair
<Key, Value>, Traits> { | 521 struct TraceInCollectionTrait<WeakHandlingInCollections, strongify, KeyValuePair
<Key, Value>, Traits> { |
530 template<typename VisitorDispatcher> | 522 template<typename VisitorDispatcher> |
531 static bool trace(VisitorDispatcher visitor, KeyValuePair<Key, Value>& self) | 523 static bool trace(VisitorDispatcher visitor, KeyValuePair<Key, Value>& self) |
532 { | 524 { |
533 // This is the core of the ephemeron-like functionality. If there is | 525 // This is the core of the ephemeron-like functionality. If there is |
534 // weakness on the key side then we first check whether there are | 526 // weakness on the key side then we first check whether there are |
535 // dead weak pointers on that side, and if there are we don't mark the | 527 // dead weak pointers on that side, and if there are we don't mark the |
536 // value side (yet). Conversely if there is weakness on the value side | 528 // value side (yet). Conversely if there is weakness on the value side |
537 // we check that first and don't mark the key side yet if we find dead | 529 // we check that first and don't mark the key side yet if we find dead |
538 // weak pointers. | 530 // weak pointers. |
539 // Corner case: If there is weakness on both the key and value side, | 531 // Corner case: If there is weakness on both the key and value side, |
540 // and there are also strong pointers on the both sides then we could | 532 // and there are also strong pointers on the both sides then we could |
541 // unexpectedly leak. The scenario is that the weak pointer on the key | 533 // unexpectedly leak. The scenario is that the weak pointer on the key |
542 // side is alive, which causes the strong pointer on the key side to be | 534 // side is alive, which causes the strong pointer on the key side to be |
543 // marked. If that then results in the object pointed to by the weak | 535 // marked. If that then results in the object pointed to by the weak |
544 // pointer on the value side being marked live, then the whole | 536 // pointer on the value side being marked live, then the whole |
545 // key-value entry is leaked. To avoid unexpected leaking, we disallow | 537 // key-value entry is leaked. To avoid unexpected leaking, we disallow |
546 // this case, but if you run into this assert, please reach out to Blink | 538 // this case, but if you run into this assert, please reach out to Blink |
547 // reviewers, and we may relax it. | 539 // reviewers, and we may relax it. |
548 const bool keyIsWeak = Traits::KeyTraits::weakHandlingFlag == WeakHandli
ngInCollections; | 540 const bool keyIsWeak = Traits::KeyTraits::weakHandlingFlag == WeakHandli
ngInCollections; |
549 const bool valueIsWeak = Traits::ValueTraits::weakHandlingFlag == WeakHa
ndlingInCollections; | 541 const bool valueIsWeak = Traits::ValueTraits::weakHandlingFlag == WeakHa
ndlingInCollections; |
550 const bool keyHasStrongRefs = NeedsTracingTrait<typename Traits::KeyTrai
ts>::value; | 542 const bool keyHasStrongRefs = IsTraceableInCollectionTrait<typename Trai
ts::KeyTraits>::value; |
551 const bool valueHasStrongRefs = NeedsTracingTrait<typename Traits::Value
Traits>::value; | 543 const bool valueHasStrongRefs = IsTraceableInCollectionTrait<typename Tr
aits::ValueTraits>::value; |
552 static_assert(!keyIsWeak || !valueIsWeak || !keyHasStrongRefs || !valueH
asStrongRefs, "this configuration is disallowed to avoid unexpected leaks"); | 544 static_assert(!keyIsWeak || !valueIsWeak || !keyHasStrongRefs || !valueH
asStrongRefs, "this configuration is disallowed to avoid unexpected leaks"); |
553 if ((valueIsWeak && !keyIsWeak) || (valueIsWeak && keyIsWeak && !valueHa
sStrongRefs)) { | 545 if ((valueIsWeak && !keyIsWeak) || (valueIsWeak && keyIsWeak && !valueHa
sStrongRefs)) { |
554 // Check value first. | 546 // Check value first. |
555 bool deadWeakObjectsFoundOnValueSide = blink::TraceCollectionIfEnabl
ed<NeedsTracingTrait<typename Traits::ValueTraits>::value, Traits::ValueTraits::
weakHandlingFlag, strongify, Value, typename Traits::ValueTraits>::trace(visitor
, self.value); | 547 bool deadWeakObjectsFoundOnValueSide = blink::TraceCollectionIfEnabl
ed<IsTraceableInCollectionTrait<typename Traits::ValueTraits>::value, Traits::Va
lueTraits::weakHandlingFlag, strongify, Value, typename Traits::ValueTraits>::tr
ace(visitor, self.value); |
556 if (deadWeakObjectsFoundOnValueSide) | 548 if (deadWeakObjectsFoundOnValueSide) |
557 return true; | 549 return true; |
558 return blink::TraceCollectionIfEnabled<NeedsTracingTrait<typename Tr
aits::KeyTraits>::value, Traits::KeyTraits::weakHandlingFlag, strongify, Key, ty
pename Traits::KeyTraits>::trace(visitor, self.key); | 550 return blink::TraceCollectionIfEnabled<IsTraceableInCollectionTrait<
typename Traits::KeyTraits>::value, Traits::KeyTraits::weakHandlingFlag, strongi
fy, Key, typename Traits::KeyTraits>::trace(visitor, self.key); |
559 } | 551 } |
560 // Check key first. | 552 // Check key first. |
561 bool deadWeakObjectsFoundOnKeySide = blink::TraceCollectionIfEnabled<Nee
dsTracingTrait<typename Traits::KeyTraits>::value, Traits::KeyTraits::weakHandli
ngFlag, strongify, Key, typename Traits::KeyTraits>::trace(visitor, self.key); | 553 bool deadWeakObjectsFoundOnKeySide = blink::TraceCollectionIfEnabled<IsT
raceableInCollectionTrait<typename Traits::KeyTraits>::value, Traits::KeyTraits:
:weakHandlingFlag, strongify, Key, typename Traits::KeyTraits>::trace(visitor, s
elf.key); |
562 if (deadWeakObjectsFoundOnKeySide) | 554 if (deadWeakObjectsFoundOnKeySide) |
563 return true; | 555 return true; |
564 return blink::TraceCollectionIfEnabled<NeedsTracingTrait<typename Traits
::ValueTraits>::value, Traits::ValueTraits::weakHandlingFlag, strongify, Value,
typename Traits::ValueTraits>::trace(visitor, self.value); | 556 return blink::TraceCollectionIfEnabled<IsTraceableInCollectionTrait<type
name Traits::ValueTraits>::value, Traits::ValueTraits::weakHandlingFlag, strongi
fy, Value, typename Traits::ValueTraits>::trace(visitor, self.value); |
565 } | 557 } |
566 }; | 558 }; |
567 | 559 |
568 // Nodes used by LinkedHashSet. Again we need two versions to disambiguate the | 560 // Nodes used by LinkedHashSet. Again we need two versions to disambiguate the |
569 // template. | 561 // template. |
570 template<ShouldWeakPointersBeMarkedStrongly strongify, typename Value, typename
Allocator, typename Traits> | 562 template<ShouldWeakPointersBeMarkedStrongly strongify, typename Value, typename
Allocator, typename Traits> |
571 struct TraceInCollectionTrait<NoWeakHandlingInCollections, strongify, LinkedHash
SetNode<Value, Allocator>, Traits> { | 563 struct TraceInCollectionTrait<NoWeakHandlingInCollections, strongify, LinkedHash
SetNode<Value, Allocator>, Traits> { |
572 template<typename VisitorDispatcher> | 564 template<typename VisitorDispatcher> |
573 static bool trace(VisitorDispatcher visitor, LinkedHashSetNode<Value, Alloca
tor>& self) | 565 static bool trace(VisitorDispatcher visitor, LinkedHashSetNode<Value, Alloca
tor>& self) |
574 { | 566 { |
575 ASSERT(NeedsTracingTrait<Traits>::value); | 567 DCHECK(IsTraceableInCollectionTrait<Traits>::value); |
576 return TraceInCollectionTrait<NoWeakHandlingInCollections, strongify, Va
lue, typename Traits::ValueTraits>::trace(visitor, self.m_value); | 568 return TraceInCollectionTrait<NoWeakHandlingInCollections, strongify, Va
lue, typename Traits::ValueTraits>::trace(visitor, self.m_value); |
577 } | 569 } |
578 }; | 570 }; |
579 | 571 |
580 template<ShouldWeakPointersBeMarkedStrongly strongify, typename Value, typename
Allocator, typename Traits> | 572 template<ShouldWeakPointersBeMarkedStrongly strongify, typename Value, typename
Allocator, typename Traits> |
581 struct TraceInCollectionTrait<WeakHandlingInCollections, strongify, LinkedHashSe
tNode<Value, Allocator>, Traits> { | 573 struct TraceInCollectionTrait<WeakHandlingInCollections, strongify, LinkedHashSe
tNode<Value, Allocator>, Traits> { |
582 template<typename VisitorDispatcher> | 574 template<typename VisitorDispatcher> |
583 static bool trace(VisitorDispatcher visitor, LinkedHashSetNode<Value, Alloca
tor>& self) | 575 static bool trace(VisitorDispatcher visitor, LinkedHashSetNode<Value, Alloca
tor>& self) |
584 { | 576 { |
585 return TraceInCollectionTrait<WeakHandlingInCollections, strongify, Valu
e, typename Traits::ValueTraits>::trace(visitor, self.m_value); | 577 return TraceInCollectionTrait<WeakHandlingInCollections, strongify, Valu
e, typename Traits::ValueTraits>::trace(visitor, self.m_value); |
586 } | 578 } |
587 }; | 579 }; |
588 | 580 |
589 // ListHashSetNode pointers (a ListHashSet is implemented as a hash table of | 581 // ListHashSetNode pointers (a ListHashSet is implemented as a hash table of |
590 // these pointers). | 582 // these pointers). |
591 template<ShouldWeakPointersBeMarkedStrongly strongify, typename Value, size_t in
lineCapacity, typename Traits> | 583 template<ShouldWeakPointersBeMarkedStrongly strongify, typename Value, size_t in
lineCapacity, typename Traits> |
592 struct TraceInCollectionTrait<NoWeakHandlingInCollections, strongify, ListHashSe
tNode<Value, blink::HeapListHashSetAllocator<Value, inlineCapacity>>*, Traits> { | 584 struct TraceInCollectionTrait<NoWeakHandlingInCollections, strongify, ListHashSe
tNode<Value, blink::HeapListHashSetAllocator<Value, inlineCapacity>>*, Traits> { |
593 using Node = ListHashSetNode<Value, blink::HeapListHashSetAllocator<Value, i
nlineCapacity>>; | 585 using Node = ListHashSetNode<Value, blink::HeapListHashSetAllocator<Value, i
nlineCapacity>>; |
594 | 586 |
595 template<typename VisitorDispatcher> | 587 template<typename VisitorDispatcher> |
596 static bool trace(VisitorDispatcher visitor, Node* node) | 588 static bool trace(VisitorDispatcher visitor, Node* node) |
597 { | 589 { |
598 ASSERT(NeedsTracingTrait<Traits>::value); | 590 DCHECK(IsTraceableInCollectionTrait<Traits>::value); |
599 traceListHashSetValue(visitor, node->m_value); | 591 traceListHashSetValue(visitor, node->m_value); |
600 // Just mark the node without tracing because we already traced the | 592 // Just mark the node without tracing because we already traced the |
601 // contents, and there is no need to trace the next and prev fields | 593 // contents, and there is no need to trace the next and prev fields |
602 // since iterating over the hash table backing will find the whole | 594 // since iterating over the hash table backing will find the whole |
603 // chain. | 595 // chain. |
604 visitor->markNoTracing(node); | 596 visitor->markNoTracing(node); |
605 return false; | 597 return false; |
606 } | 598 } |
607 }; | 599 }; |
608 | 600 |
609 } // namespace WTF | 601 } // namespace WTF |
610 | 602 |
611 #endif | 603 #endif |
OLD | NEW |