| 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 |