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

Side by Side Diff: third_party/WebKit/Source/platform/heap/TraceTraits.h

Issue 2065443002: Rename and improve "traceable" templates. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: comment rewording Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // 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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698