1 /* 2 * Copyright (C) 2013 Google Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are 6 * met: 7 * 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above 11 * copyright notice, this list of conditions and the following disclaimer 12 * in the documentation and/or other materials provided with the 13 * distribution. 14 * * Neither the name of Google Inc. nor the names of its 15 * contributors may be used to endorse or promote products derived from 16 * this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 #ifndef Visitor_h 32 #define Visitor_h 33 34 #include "platform/PlatformExport.h" 35 #include "platform/heap/ThreadState.h" 36 #include "wtf/Assertions.h" 37 #include "wtf/Deque.h" 38 #include "wtf/Forward.h" 39 #include "wtf/HashCountedSet.h" 40 #include "wtf/HashMap.h" 41 #include "wtf/HashSet.h" 42 #include "wtf/HashTraits.h" 43 #include "wtf/InstanceCounter.h" 44 #include "wtf/LinkedHashSet.h" 45 #include "wtf/ListHashSet.h" 46 #include "wtf/OwnPtr.h" 47 #include "wtf/RefPtr.h" 48 #include "wtf/TypeTraits.h" 49 #include "wtf/WeakPtr.h" 50 #if ENABLE(GC_TRACING) 51 #include "wtf/text/WTFString.h" 52 #endif 53 54 #ifndef NDEBUG 55 #define DEBUG_ONLY(x) x 56 #else 57 #define DEBUG_ONLY(x) 58 #endif 59 60 namespace WebCore { 61 62 class FinalizedHeapObjectHeader; 63 template<typename T> class GarbageCollectedFinalized; 64 class HeapObjectHeader; 65 template<typename T> class Member; 66 template<typename T> class WeakMember; 67 class Visitor; 68 69 enum ShouldWeakPointersBeMarkedStrongly { 70 WeakPointersActStrong, 71 WeakPointersActWeak 72 }; 73 74 template<bool needsTracing, WTF::WeakHandlingFlag weakHandlingFlag, ShouldWeakPointersBeMarkedStrongly strongify, typename T, typename Traits> struct CollectionBackingTraceTrait; 75 76 // The TraceMethodDelegate is used to convert a trace method for type T to a TraceCallback. 77 // This allows us to pass a type's trace method as a parameter to the PersistentNode 78 // constructor. The PersistentNode constructor needs the specific trace method due an issue 79 // with the Windows compiler which instantiates even unused variables. This causes problems 80 // in header files where we have only forward declarations of classes. 81 template<typename T, void (T::*method)(Visitor*)> 82 struct TraceMethodDelegate { 83 static void trampoline(Visitor* visitor, void* self) { (reinterpret_cast<T*>(self)->*method)(visitor); } 84 }; 85 86 // GCInfo contains meta-data associated with objects allocated in the 87 // Blink heap. This meta-data consists of a function pointer used to 88 // trace the pointers in the object during garbage collection, an 89 // indication of whether or not the object needs a finalization 90 // callback, and a function pointer used to finalize the object when 91 // the garbage collector determines that the object is no longer 92 // reachable. There is a GCInfo struct for each class that directly 93 // inherits from GarbageCollected or GarbageCollectedFinalized. 94 struct GCInfo { 95 bool hasFinalizer() const { return m_nonTrivialFinalizer; } 96 bool hasVTable() const { return m_hasVTable; } 97 TraceCallback m_trace; 98 FinalizationCallback m_finalize; 99 bool m_nonTrivialFinalizer; 100 bool m_hasVTable; 101 #if ENABLE(GC_TRACING) 102 // |m_className| is held as a reference to prevent dtor being called at exit. 103 const String& m_className; 104 #endif 105 }; 106 107 // The FinalizerTraitImpl specifies how to finalize objects. Object 108 // that inherit from GarbageCollectedFinalized are finalized by 109 // calling their 'finalize' method which by default will call the 110 // destructor on the object. 111 template<typename T, bool isGarbageCollectedFinalized> 112 struct FinalizerTraitImpl; 113 114 template<typename T> 115 struct FinalizerTraitImpl<T, true> { 116 static void finalize(void* obj) { static_cast<T*>(obj)->finalizeGarbageCollectedObject(); }; 117 }; 118 119 template<typename T> 120 struct FinalizerTraitImpl<T, false> { 121 static void finalize(void* obj) { }; 122 }; 123 124 // The FinalizerTrait is used to determine if a type requires 125 // finalization and what finalization means. 126 // 127 // By default classes that inherit from GarbageCollectedFinalized need 128 // finalization and finalization means calling the 'finalize' method 129 // of the object. The FinalizerTrait can be specialized if the default 130 // behavior is not desired. 131 template<typename T> 132 struct FinalizerTrait { 133 static const bool nonTrivialFinalizer = WTF::IsSubclassOfTemplate<typename WTF::RemoveConst<T>::Type, GarbageCollectedFinalized>::value; 134 static void finalize(void* obj) { FinalizerTraitImpl<T, nonTrivialFinalizer>::finalize(obj); } 135 }; 136 137 // Trait to get the GCInfo structure for types that have their 138 // instances allocated in the Blink garbage-collected heap. 139 template<typename T> struct GCInfoTrait; 140 141 template<typename T> class GarbageCollected; 142 class GarbageCollectedMixin; 143 template<typename T, bool = WTF::IsSubclassOfTemplate<typename WTF::RemoveConst<T>::Type, GarbageCollected>::value> class NeedsAdjustAndMark; 144 145 template<typename T> 146 class NeedsAdjustAndMark<T, true> { 147 public: 148 static const bool value = false; 149 }; 150 151 template<typename T> 152 class NeedsAdjustAndMark<T, false> { 153 public: 154 static const bool value = WTF::IsSubclass<typename WTF::RemoveConst<T>::Type, GarbageCollectedMixin>::value; 155 }; 156 157 template<typename T, bool = NeedsAdjustAndMark<T>::value> class DefaultTraceTrait; 158 159 // The TraceTrait is used to specify how to mark an object pointer and 160 // how to trace all of the pointers in the object. 161 // 162 // By default, the 'trace' method implemented on an object itself is 163 // used to trace the pointers to other heap objects inside the object. 164 // 165 // However, the TraceTrait can be specialized to use a different 166 // implementation. A common case where a TraceTrait specialization is 167 // needed is when multiple inheritance leads to pointers that are not 168 // to the start of the object in the Blink garbage-collected heap. In 169 // that case the pointer has to be adjusted before marking. 170 template<typename T> 171 class TraceTrait { 172 public: 173 // Default implementation of TraceTrait<T>::trace just statically 174 // dispatches to the trace method of the class T. 175 static void trace(Visitor* visitor, void* self) 176 { 177 static_cast<T*>(self)->trace(visitor); 178 } 179 180 static void mark(Visitor* visitor, const T* t) 181 { 182 DefaultTraceTrait<T>::mark(visitor, t); 183 } 184 185 #ifndef NDEBUG 186 static void checkGCInfo(Visitor* visitor, const T* t) 187 { 188 DefaultTraceTrait<T>::checkGCInfo(visitor, t); 189 } 190 #endif 191 }; 192 193 template<typename T> class TraceTrait<const T> : public TraceTrait<T> { }; 194 195 template<typename Collection> 196 struct OffHeapCollectionTraceTrait; 197 198 template<typename T> 199 struct ObjectAliveTrait { 200 static bool isAlive(Visitor*, T*); 201 }; 202 203 // Visitor is used to traverse the Blink object graph. Used for the 204 // marking phase of the mark-sweep garbage collector. 205 // 206 // Pointers are marked and pushed on the marking stack by calling the 207 // |mark| method with the pointer as an argument. 208 // 209 // Pointers within objects are traced by calling the |trace| methods 210 // with the object as an argument. Tracing objects will mark all of the 211 // contained pointers and push them on the marking stack. 212 class PLATFORM_EXPORT Visitor { 213 public: 214 virtual ~Visitor() { } 215 216 // One-argument templated mark method. This uses the static type of 217 // the argument to get the TraceTrait. By default, the mark method 218 // of the TraceTrait just calls the virtual two-argument mark method on this 219 // visitor, where the second argument is the static trace method of the trait. 220 template<typename T> 221 void mark(T* t) 222 { 223 if (!t) 224 return; 225 #ifndef NDEBUG 226 TraceTrait<T>::checkGCInfo(this, t); 227 #endif 228 TraceTrait<T>::mark(this, t); 229 } 230 231 // Member version of the one-argument templated trace method. 232 template<typename T> 233 void trace(const Member<T>& t) 234 { 235 t.verifyTypeIsGarbageCollected(); 236 mark(t.get()); 237 } 238 239 // Fallback method used only when we need to trace raw pointers of T. 240 // This is the case when a member is a union where we do not support members. 241 template<typename T> 242 void trace(const T* t) 243 { 244 mark(const_cast<T*>(t)); 245 } 246 247 template<typename T> 248 void trace(T* t) 249 { 250 mark(t); 251 } 252 253 // WeakMember version of the templated trace method. It doesn't keep 254 // the traced thing alive, but will write null to the WeakMember later 255 // if the pointed-to object is dead. It's lying for this to be const, 256 // but the overloading resolver prioritizes constness too high when 257 // picking the correct overload, so all these trace methods have to have 258 // the same constness on their argument to allow the type to decide. 259 template<typename T> 260 void trace(const WeakMember<T>& t) 261 { 262 // Check that we actually know the definition of T when tracing. 263 COMPILE_ASSERT(sizeof(T), WeNeedToKnowTheDefinitionOfTheTypeWeAreTracing); 264 registerWeakCell(const_cast<WeakMember<T>&>(t).cell()); 265 } 266 267 template<typename T> 268 void traceInCollection(T& t, ShouldWeakPointersBeMarkedStrongly strongify) 269 { 270 HashTraits<T>::traceInCollection(this, t, strongify); 271 } 272 273 // Fallback trace method for part objects to allow individual trace methods 274 // to trace through a part object with visitor->trace(m_partObject). This 275 // takes a const argument, because otherwise it will match too eagerly: a 276 // non-const argument would match a non-const Vector<T>& argument better 277 // than the specialization that takes const Vector<T>&. For a similar reason, 278 // the other specializations take a const argument even though they are 279 // usually used with non-const arguments, otherwise this function would match 280 // too well. 281 template<typename T> 282 void trace(const T& t) 283 { 284 const_cast<T&>(t).trace(this); 285 } 286 287 // The following trace methods are for off-heap collections. 288 template<typename T, size_t inlineCapacity> 289 void trace(const Vector<T, inlineCapacity>& vector) 290 { 291 OffHeapCollectionTraceTrait<Vector<T, inlineCapacity, WTF::DefaultAllocator> >::trace(this, vector); 292 } 293 294 template<typename T, typename U, typename V> 295 void trace(const HashSet<T, U, V>& hashSet) 296 { 297 OffHeapCollectionTraceTrait<HashSet<T, U, V> >::trace(this, hashSet); 298 } 299 300 template<typename T, size_t inlineCapacity, typename U> 301 void trace(const ListHashSet<T, inlineCapacity, U>& hashSet) 302 { 303 OffHeapCollectionTraceTrait<ListHashSet<T, inlineCapacity, U> >::trace(this, hashSet); 304 } 305 306 template<typename T, typename U> 307 void trace(const LinkedHashSet<T, U>& hashSet) 308 { 309 OffHeapCollectionTraceTrait<LinkedHashSet<T, U> >::trace(this, hashSet); 310 } 311 312 template<typename T, size_t N> 313 void trace(const Deque<T, N>& deque) 314 { 315 OffHeapCollectionTraceTrait<Deque<T, N> >::trace(this, deque); 316 } 317 318 template<typename T, typename U, typename V> 319 void trace(const HashCountedSet<T, U, V>& set) 320 { 321 OffHeapCollectionTraceTrait<HashCountedSet<T, U, V> >::trace(this, set); 322 } 323 324 template<typename T, typename U, typename V, typename W, typename X> 325 void trace(const HashMap<T, U, V, W, X, WTF::DefaultAllocator>& map) 326 { 327 OffHeapCollectionTraceTrait<HashMap<T, U, V, W, X, WTF::DefaultAllocator> >::trace(this, map); 328 } 329 330 // OwnPtrs that are traced are treated as part objects and the 331 // trace method of the owned object is called. 332 template<typename T> 333 void trace(const OwnPtr<T>& t) 334 { 335 if (t) 336 t->trace(this); 337 } 338 339 // This trace method is to trace a RefPtrWillBeMember when ENABLE(OILPAN) 340 // is not enabled. 341 // Remove this once we remove RefPtrWillBeMember. 342 template<typename T> 343 void trace(const RefPtr<T>&) 344 { 345 #if ENABLE(OILPAN) 346 // RefPtrs should never be traced. 347 ASSERT_NOT_REACHED(); 348 #endif 349 } 350 351 #if !ENABLE(OILPAN) 352 // Similarly, this trace method is to trace a RawPtrWillBeMember 353 // when ENABLE(OILPAN) is not enabled. 354 // Remove this once we remove RawPtrWillBeMember. 355 template<typename T> 356 void trace(const RawPtr<T>&) 357 { 358 } 359 #endif 360 361 // This trace method is to trace a WeakPtrWillBeMember when ENABLE(OILPAN) 362 // is not enabled. 363 // Remove this once we remove WeakPtrWillBeMember. 364 template<typename T> 365 void trace(const WeakPtr<T>&) 366 { 367 #if ENABLE(OILPAN) 368 // WeakPtrs should never be traced. 369 ASSERT_NOT_REACHED(); 370 #endif 371 } 372 373 // This method marks an object and adds it to the set of objects 374 // that should have their trace method called. Since not all 375 // objects have vtables we have to have the callback as an 376 // explicit argument, but we can use the templated one-argument 377 // mark method above to automatically provide the callback 378 // function. 379 virtual void mark(const void*, TraceCallback) = 0; 380 virtual void markNoTracing(const void* pointer) { mark(pointer, reinterpret_cast<TraceCallback>(0)); } 381 382 // Used to mark objects during conservative scanning. 383 virtual void mark(HeapObjectHeader*, TraceCallback) = 0; 384 virtual void mark(FinalizedHeapObjectHeader*, TraceCallback) = 0; 385 virtual void markConservatively(HeapObjectHeader*) = 0; 386 virtual void markConservatively(FinalizedHeapObjectHeader*) = 0; 387 388 // If the object calls this during the regular trace callback, then the 389 // WeakPointerCallback argument may be called later, when the strong roots 390 // have all been found. The WeakPointerCallback will normally use isAlive 391 // to find out whether some pointers are pointing to dying objects. When 392 // the WeakPointerCallback is done the object must have purged all pointers 393 // to objects where isAlive returned false. In the weak callback it is not 394 // allowed to touch other objects (except using isAlive) or to allocate on 395 // the GC heap. Note that even removing things from HeapHashSet or 396 // HeapHashMap can cause an allocation if the backing store resizes, but 397 // these collections know to remove WeakMember elements safely. 398 // 399 // The weak pointer callbacks are run on the thread that owns the 400 // object and other threads are not stopped during the 401 // callbacks. Since isAlive is used in the callback to determine 402 // if objects pointed to are alive it is crucial that the object 403 // pointed to belong to the same thread as the object receiving 404 // the weak callback. Since other threads have been resumed the 405 // mark bits are not valid for objects from other threads. 406 virtual void registerWeakMembers(const void* object, WeakPointerCallback callback) { registerWeakMembers(object, object, callback); } 407 virtual void registerWeakMembers(const void*, const void*, WeakPointerCallback) = 0; 408 409 template<typename T, void (T::*method)(Visitor*)> 410 void registerWeakMembers(const T* obj) 411 { 412 registerWeakMembers(obj, &TraceMethodDelegate<T, method>::trampoline); 413 } 414 415 // For simple cases where you just want to zero out a cell when the thing 416 // it is pointing at is garbage, you can use this. This will register a 417 // callback for each cell that needs to be zeroed, so if you have a lot of 418 // weak cells in your object you should still consider using 419 // registerWeakMembers above. 420 // 421 // In contrast to registerWeakMembers, the weak cell callbacks are 422 // run on the thread performing garbage collection. Therefore, all 423 // threads are stopped during weak cell callbacks. 424 template<typename T> 425 void registerWeakCell(T** cell) 426 { 427 registerWeakCell(reinterpret_cast<void**>(cell), &handleWeakCell<T>); 428 } 429 430 virtual bool isMarked(const void*) = 0; 431 432 template<typename T> inline bool isAlive(T* obj) 433 { 434 return !!obj && ObjectAliveTrait<T>::isAlive(this, obj); 435 } 436 template<typename T> inline bool isAlive(const Member<T>& member) 437 { 438 return isAlive(member.get()); 439 } 440 template<typename T> inline bool isAlive(RawPtr<T> ptr) 441 { 442 return isAlive(ptr.get()); 443 } 444 445 #ifndef NDEBUG 446 void checkGCInfo(const void*, const GCInfo*); 447 #endif 448 449 // Macro to declare methods needed for each typed heap. 450 #define DECLARE_VISITOR_METHODS(Type) \ 451 DEBUG_ONLY(void checkGCInfo(const Type*, const GCInfo*);) \ 452 virtual void mark(const Type*, TraceCallback) = 0; \ 453 virtual bool isMarked(const Type*) = 0; 454 455 FOR_EACH_TYPED_HEAP(DECLARE_VISITOR_METHODS) 456 #undef DECLARE_VISITOR_METHODS 457 458 #if ENABLE(GC_TRACING) 459 void setHostInfo(void* object, const String& name) 460 { 461 m_hostObject = object; 462 m_hostName = name; 463 } 464 #endif 465 466 protected: 467 virtual void registerWeakCell(void**, WeakPointerCallback) = 0; 468 #if ENABLE(GC_TRACING) 469 void* m_hostObject; 470 String m_hostName; 471 #endif 472 473 private: 474 template<typename T> 475 static void handleWeakCell(Visitor* self, void* obj) 476 { 477 T** cell = reinterpret_cast<T**>(obj); 478 if (*cell && !self->isAlive(*cell)) 479 *cell = 0; 480 } 481 }; 482 483 template<typename T, typename HashFunctions, typename Traits> 484 struct OffHeapCollectionTraceTrait<WTF::HashSet<T, HashFunctions, Traits, WTF::DefaultAllocator> > { 485 typedef WTF::HashSet<T, HashFunctions, Traits, WTF::DefaultAllocator> HashSet; 486 487 static void trace(Visitor* visitor, const HashSet& set) 488 { 489 if (set.isEmpty()) 490 return; 491 if (WTF::ShouldBeTraced<Traits>::value) { 492 HashSet& iterSet = const_cast<HashSet&>(set); 493 for (typename HashSet::iterator it = iterSet.begin(), end = iterSet.end(); it != end; ++it) { 494 const T& t = *it; 495 CollectionBackingTraceTrait<WTF::ShouldBeTraced<Traits>::value, Traits::weakHandlingFlag, WeakPointersActWeak, T, Traits>::trace(visitor, const_cast<T&>(t)); 496 } 497 } 498 COMPILE_ASSERT(Traits::weakHandlingFlag == WTF::NoWeakHandlingInCollections, WeakOffHeapCollectionsConsideredDangerous0); 499 } 500 }; 501 502 template<typename T, size_t inlineCapacity, typename HashFunctions> 503 struct OffHeapCollectionTraceTrait<ListHashSet<T, inlineCapacity, HashFunctions> > { 504 typedef WTF::ListHashSet<T, inlineCapacity, HashFunctions> ListHashSet; 505 506 static void trace(Visitor* visitor, const ListHashSet& set) 507 { 508 if (set.isEmpty()) 509 return; 510 ListHashSet& iterSet = const_cast<ListHashSet&>(set); 511 for (typename ListHashSet::iterator it = iterSet.begin(), end = iterSet.end(); it != end; ++it) 512 visitor->trace(*it); 513 } 514 }; 515 516 template<typename T, typename HashFunctions> 517 struct OffHeapCollectionTraceTrait<WTF::LinkedHashSet<T, HashFunctions> > { 518 typedef WTF::LinkedHashSet<T, HashFunctions> LinkedHashSet; 519 520 static void trace(Visitor* visitor, const LinkedHashSet& set) 521 { 522 if (set.isEmpty()) 523 return; 524 LinkedHashSet& iterSet = const_cast<LinkedHashSet&>(set); 525 for (typename LinkedHashSet::iterator it = iterSet.begin(), end = iterSet.end(); it != end; ++it) 526 visitor->trace(*it); 527 } 528 }; 529 530 template<typename Key, typename Value, typename HashFunctions, typename KeyTraits, typename ValueTraits> 531 struct OffHeapCollectionTraceTrait<WTF::HashMap<Key, Value, HashFunctions, KeyTraits, ValueTraits, WTF::DefaultAllocator> > { 532 typedef WTF::HashMap<Key, Value, HashFunctions, KeyTraits, ValueTraits, WTF::DefaultAllocator> HashMap; 533 534 static void trace(Visitor* visitor, const HashMap& map) 535 { 536 if (map.isEmpty()) 537 return; 538 if (WTF::ShouldBeTraced<KeyTraits>::value || WTF::ShouldBeTraced<ValueTraits>::value) { 539 HashMap& iterMap = const_cast<HashMap&>(map); 540 for (typename HashMap::iterator it = iterMap.begin(), end = iterMap.end(); it != end; ++it) { 541 CollectionBackingTraceTrait<WTF::ShouldBeTraced<KeyTraits>::value, KeyTraits::weakHandlingFlag, WeakPointersActWeak, typename HashMap::KeyType, KeyTraits>::trace(visitor, it->key); 542 CollectionBackingTraceTrait<WTF::ShouldBeTraced<ValueTraits>::value, ValueTraits::weakHandlingFlag, WeakPointersActWeak, typename HashMap::MappedType, ValueTraits>::trace(visitor, it->value); 543 } 544 } 545 COMPILE_ASSERT(KeyTraits::weakHandlingFlag == WTF::NoWeakHandlingInCollections, WeakOffHeapCollectionsConsideredDangerous1); 546 COMPILE_ASSERT(ValueTraits::weakHandlingFlag == WTF::NoWeakHandlingInCollections, WeakOffHeapCollectionsConsideredDangerous2); 547 } 548 }; 549 550 // We trace vectors by using the trace trait on each element, which means you 551 // can have vectors of general objects (not just pointers to objects) that can 552 // be traced. 553 template<typename T, size_t N> 554 struct OffHeapCollectionTraceTrait<WTF::Vector<T, N, WTF::DefaultAllocator> > { 555 typedef WTF::Vector<T, N, WTF::DefaultAllocator> Vector; 556 557 static void trace(Visitor* visitor, const Vector& vector) 558 { 559 if (vector.isEmpty()) 560 return; 561 for (typename Vector::const_iterator it = vector.begin(), end = vector.end(); it != end; ++it) 562 TraceTrait<T>::trace(visitor, const_cast<T*>(it)); 563 } 564 }; 565 566 template<typename T, size_t N> 567 struct OffHeapCollectionTraceTrait<WTF::Deque<T, N> > { 568 typedef WTF::Deque<T, N> Deque; 569 570 static void trace(Visitor* visitor, const Deque& deque) 571 { 572 if (deque.isEmpty()) 573 return; 574 for (typename Deque::const_iterator it = deque.begin(), end = deque.end(); it != end; ++it) 575 TraceTrait<T>::trace(visitor, const_cast<T*>(&(*it))); 576 } 577 }; 578 579 template<typename T, typename U, typename V> 580 struct OffHeapCollectionTraceTrait<WTF::HashCountedSet<T, U, V> > { 581 typedef WTF::HashCountedSet<T, U, V> Set; 582 583 static void trace(Visitor* visitor, const Set& set) 584 { 585 if (set.isEmpty()) 586 return; 587 for (typename Set::const_iterator it = set.begin(), end = set.end(); it != end; ++it) 588 TraceTrait<T>::trace(visitor, const_cast<T*>(&(it->key))); 589 } 590 }; 591 592 template<typename T, typename Traits = WTF::VectorTraits<T> > 593 class HeapVectorBacking; 594 595 template<typename Table> 596 class HeapHashTableBacking { 597 public: 598 static void finalize(void* pointer); 599 }; 600 601 template<typename T> 602 class DefaultTraceTrait<T, false> { 603 public: 604 static void mark(Visitor* visitor, const T* t) 605 { 606 // Default mark method of the trait just calls the two-argument mark 607 // method on the visitor. The second argument is the static trace method 608 // of the trait, which by default calls the instance method 609 // trace(Visitor*) on the object. 610 visitor->mark(const_cast<T*>(t), &TraceTrait<T>::trace); 611 } 612 613 #ifndef NDEBUG 614 static void checkGCInfo(Visitor* visitor, const T* t) 615 { 616 visitor->checkGCInfo(const_cast<T*>(t), GCInfoTrait<T>::get()); 617 } 618 #endif 619 }; 620 621 template<typename T> 622 class DefaultTraceTrait<T, true> { 623 public: 624 static void mark(Visitor* visitor, const T* self) 625 { 626 if (self) 627 self->adjustAndMark(visitor); 628 } 629 630 #ifndef NDEBUG 631 static void checkGCInfo(Visitor*, const T*) { } 632 #endif 633 }; 634 635 template<typename T, bool = NeedsAdjustAndMark<T>::value> class DefaultObjectAliveTrait; 636 637 template<typename T> 638 class DefaultObjectAliveTrait<T, false> { 639 public: 640 static bool isAlive(Visitor* visitor, T* obj) 641 { 642 return visitor->isMarked(obj); 643 } 644 }; 645 646 template<typename T> 647 class DefaultObjectAliveTrait<T, true> { 648 public: 649 static bool isAlive(Visitor* visitor, T* obj) 650 { 651 return obj->isAlive(visitor); 652 } 653 }; 654 655 template<typename T> bool ObjectAliveTrait<T>::isAlive(Visitor* visitor, T* obj) 656 { 657 return DefaultObjectAliveTrait<T>::isAlive(visitor, obj); 658 } 659 660 // The GarbageCollectedMixin interface and helper macro 661 // USING_GARBAGE_COLLECTED_MIXIN can be used to automatically define 662 // TraceTrait/ObjectAliveTrait on non-leftmost deriving classes 663 // which need to be garbage collected. 664 // 665 // Consider the following case: 666 // class B {}; 667 // class A : public GarbageCollected, public B {}; 668 // 669 // We can't correctly handle "Member<B> p = &a" as we can't compute addr of 670 // object header statically. This can be solved by using GarbageCollectedMixin: 671 // class B : public GarbageCollectedMixin {}; 672 // class A : public GarbageCollected, public B { 673 // USING_GARBAGE_COLLECTED_MIXIN(A) 674 // }; 675 // 676 // With the helper, as long as we are using Member<B>, TypeTrait<B> will 677 // dispatch adjustAndMark dynamically to find collect addr of the object header. 678 // Note that this is only enabled for Member<B>. For Member<A> which we can 679 // compute the object header addr statically, this dynamic dispatch is not used. 680 681 class GarbageCollectedMixin { 682 public: 683 virtual void adjustAndMark(Visitor*) const = 0; 684 virtual bool isAlive(Visitor*) const = 0; 685 }; 686 687 #define USING_GARBAGE_COLLECTED_MIXIN(TYPE) \ 688 public: \ 689 virtual void adjustAndMark(WebCore::Visitor* visitor) const OVERRIDE \ 690 { \ 691 typedef WTF::IsSubclassOfTemplate<typename WTF::RemoveConst<TYPE>::Type, WebCore::GarbageCollected> IsSubclassOfGarbageCollected; \ 692 COMPILE_ASSERT(IsSubclassOfGarbageCollected::value, OnlyGarbageCollectedObjectsCanHaveGarbageCollectedMixins); \ 693 visitor->mark(static_cast<const TYPE*>(this), &WebCore::TraceTrait<TYPE>::trace); \ 694 } \ 695 virtual bool isAlive(WebCore::Visitor* visitor) const OVERRIDE \ 696 { \ 697 return visitor->isAlive(this); \ 698 } \ 699 private: 700 701 #if ENABLE(OILPAN) 702 #define WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(TYPE) USING_GARBAGE_COLLECTED_MIXIN(TYPE) 703 #else 704 #define WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(TYPE) 705 #endif 706 707 #if ENABLE(GC_TRACING) 708 template<typename T> 709 struct TypenameStringTrait { 710 static const String& get() 711 { 712 DEFINE_STATIC_LOCAL(String, typenameString, (WTF::extractTypeNameFromFunctionName(WTF::extractNameFunction<T>()))); 713 return typenameString; 714 } 715 }; 716 #endif 717 718 template<typename T> 719 struct GCInfoAtBase { 720 static const GCInfo* get() 721 { 722 static const GCInfo gcInfo = { 723 TraceTrait<T>::trace, 724 FinalizerTrait<T>::finalize, 725 FinalizerTrait<T>::nonTrivialFinalizer, 726 WTF::IsPolymorphic<T>::value, 727 #if ENABLE(GC_TRACING) 728 TypenameStringTrait<T>::get() 729 #endif 730 }; 731 return &gcInfo; 732 } 733 }; 734 735 template<typename T> class GarbageCollected; 736 template<typename T, bool = WTF::IsSubclassOfTemplate<typename WTF::RemoveConst<T>::Type, GarbageCollected>::value> struct GetGarbageCollectedBase; 737 738 template<typename T> 739 struct GetGarbageCollectedBase<T, true> { 740 typedef typename T::GarbageCollectedBase type; 741 }; 742 743 template<typename T> 744 struct GetGarbageCollectedBase<T, false> { 745 typedef T type; 746 }; 747 748 template<typename T> 749 struct GCInfoTrait { 750 static const GCInfo* get() 751 { 752 return GCInfoAtBase<typename GetGarbageCollectedBase<T>::type>::get(); 753 } 754 }; 755 756 } 757 758 #endif 759