| OLD | NEW |
| (Empty) |
| 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/HashMap.h" | |
| 40 #include "wtf/HashTraits.h" | |
| 41 #include "wtf/InstanceCounter.h" | |
| 42 #include "wtf/OwnPtr.h" | |
| 43 #include "wtf/RefPtr.h" | |
| 44 #include "wtf/TypeTraits.h" | |
| 45 #include "wtf/WeakPtr.h" | |
| 46 #if ENABLE(GC_PROFILING) | |
| 47 #include "wtf/text/WTFString.h" | |
| 48 #endif | |
| 49 | |
| 50 #if ENABLE(ASSERT) | |
| 51 #define DEBUG_ONLY(x) x | |
| 52 #else | |
| 53 #define DEBUG_ONLY(x) | |
| 54 #endif | |
| 55 | |
| 56 namespace blink { | |
| 57 | |
| 58 class FinalizedHeapObjectHeader; | |
| 59 template<typename T> class GarbageCollectedFinalized; | |
| 60 class HeapObjectHeader; | |
| 61 template<typename T> class Member; | |
| 62 template<typename T> class WeakMember; | |
| 63 class Visitor; | |
| 64 | |
| 65 template<bool needsTracing, WTF::WeakHandlingFlag weakHandlingFlag, WTF::ShouldW
eakPointersBeMarkedStrongly strongify, typename T, typename Traits> struct Colle
ctionBackingTraceTrait; | |
| 66 | |
| 67 // The TraceMethodDelegate is used to convert a trace method for type T to a Tra
ceCallback. | |
| 68 // This allows us to pass a type's trace method as a parameter to the Persistent
Node | |
| 69 // constructor. The PersistentNode constructor needs the specific trace method d
ue an issue | |
| 70 // with the Windows compiler which instantiates even unused variables. This caus
es problems | |
| 71 // in header files where we have only forward declarations of classes. | |
| 72 template<typename T, void (T::*method)(Visitor*)> | |
| 73 struct TraceMethodDelegate { | |
| 74 static void trampoline(Visitor* visitor, void* self) { (reinterpret_cast<T*>
(self)->*method)(visitor); } | |
| 75 }; | |
| 76 | |
| 77 // GCInfo contains meta-data associated with objects allocated in the | |
| 78 // Blink heap. This meta-data consists of a function pointer used to | |
| 79 // trace the pointers in the object during garbage collection, an | |
| 80 // indication of whether or not the object needs a finalization | |
| 81 // callback, and a function pointer used to finalize the object when | |
| 82 // the garbage collector determines that the object is no longer | |
| 83 // reachable. There is a GCInfo struct for each class that directly | |
| 84 // inherits from GarbageCollected or GarbageCollectedFinalized. | |
| 85 struct GCInfo { | |
| 86 bool hasFinalizer() const { return m_nonTrivialFinalizer; } | |
| 87 bool hasVTable() const { return m_hasVTable; } | |
| 88 TraceCallback m_trace; | |
| 89 FinalizationCallback m_finalize; | |
| 90 bool m_nonTrivialFinalizer; | |
| 91 bool m_hasVTable; | |
| 92 #if ENABLE(GC_PROFILING) | |
| 93 // |m_className| is held as a reference to prevent dtor being called at exit
. | |
| 94 const String& m_className; | |
| 95 #endif | |
| 96 }; | |
| 97 | |
| 98 // The FinalizerTraitImpl specifies how to finalize objects. Object | |
| 99 // that inherit from GarbageCollectedFinalized are finalized by | |
| 100 // calling their 'finalize' method which by default will call the | |
| 101 // destructor on the object. | |
| 102 template<typename T, bool isGarbageCollectedFinalized> | |
| 103 struct FinalizerTraitImpl; | |
| 104 | |
| 105 template<typename T> | |
| 106 struct FinalizerTraitImpl<T, true> { | |
| 107 static void finalize(void* obj) { static_cast<T*>(obj)->finalizeGarbageColle
ctedObject(); }; | |
| 108 }; | |
| 109 | |
| 110 template<typename T> | |
| 111 struct FinalizerTraitImpl<T, false> { | |
| 112 static void finalize(void* obj) { }; | |
| 113 }; | |
| 114 | |
| 115 // The FinalizerTrait is used to determine if a type requires | |
| 116 // finalization and what finalization means. | |
| 117 // | |
| 118 // By default classes that inherit from GarbageCollectedFinalized need | |
| 119 // finalization and finalization means calling the 'finalize' method | |
| 120 // of the object. The FinalizerTrait can be specialized if the default | |
| 121 // behavior is not desired. | |
| 122 template<typename T> | |
| 123 struct FinalizerTrait { | |
| 124 static const bool nonTrivialFinalizer = WTF::IsSubclassOfTemplate<typename W
TF::RemoveConst<T>::Type, GarbageCollectedFinalized>::value; | |
| 125 static void finalize(void* obj) { FinalizerTraitImpl<T, nonTrivialFinalizer>
::finalize(obj); } | |
| 126 }; | |
| 127 | |
| 128 // Trait to get the GCInfo structure for types that have their | |
| 129 // instances allocated in the Blink garbage-collected heap. | |
| 130 template<typename T> struct GCInfoTrait; | |
| 131 | |
| 132 template<typename T> class GarbageCollected; | |
| 133 class GarbageCollectedMixin; | |
| 134 template<typename T, bool = WTF::IsSubclassOfTemplate<typename WTF::RemoveConst<
T>::Type, GarbageCollected>::value> class NeedsAdjustAndMark; | |
| 135 | |
| 136 template<typename T> | |
| 137 class NeedsAdjustAndMark<T, true> { | |
| 138 public: | |
| 139 static const bool value = false; | |
| 140 }; | |
| 141 | |
| 142 template <typename T> const bool NeedsAdjustAndMark<T, true>::value; | |
| 143 | |
| 144 template<typename T> | |
| 145 class NeedsAdjustAndMark<T, false> { | |
| 146 public: | |
| 147 static const bool value = WTF::IsSubclass<typename WTF::RemoveConst<T>::Type
, GarbageCollectedMixin>::value; | |
| 148 }; | |
| 149 | |
| 150 template <typename T> const bool NeedsAdjustAndMark<T, false>::value; | |
| 151 | |
| 152 template<typename T, bool = NeedsAdjustAndMark<T>::value> class DefaultTraceTrai
t; | |
| 153 | |
| 154 // The TraceTrait is used to specify how to mark an object pointer and | |
| 155 // how to trace all of the pointers in the object. | |
| 156 // | |
| 157 // By default, the 'trace' method implemented on an object itself is | |
| 158 // used to trace the pointers to other heap objects inside the object. | |
| 159 // | |
| 160 // However, the TraceTrait can be specialized to use a different | |
| 161 // implementation. A common case where a TraceTrait specialization is | |
| 162 // needed is when multiple inheritance leads to pointers that are not | |
| 163 // to the start of the object in the Blink garbage-collected heap. In | |
| 164 // that case the pointer has to be adjusted before marking. | |
| 165 template<typename T> | |
| 166 class TraceTrait { | |
| 167 public: | |
| 168 // Default implementation of TraceTrait<T>::trace just statically | |
| 169 // dispatches to the trace method of the class T. | |
| 170 static void trace(Visitor* visitor, void* self) | |
| 171 { | |
| 172 } | |
| 173 | |
| 174 static void mark(Visitor* visitor, const T* t) | |
| 175 { | |
| 176 } | |
| 177 }; | |
| 178 | |
| 179 template<typename T> class TraceTrait<const T> : public TraceTrait<T> { }; | |
| 180 | |
| 181 template<typename Collection> | |
| 182 struct OffHeapCollectionTraceTrait; | |
| 183 | |
| 184 template<typename T> | |
| 185 struct ObjectAliveTrait { | |
| 186 static bool isAlive(Visitor*, T*); | |
| 187 }; | |
| 188 | |
| 189 // Visitor is used to traverse the Blink object graph. Used for the | |
| 190 // marking phase of the mark-sweep garbage collector. | |
| 191 // | |
| 192 // Pointers are marked and pushed on the marking stack by calling the | |
| 193 // |mark| method with the pointer as an argument. | |
| 194 // | |
| 195 // Pointers within objects are traced by calling the |trace| methods | |
| 196 // with the object as an argument. Tracing objects will mark all of the | |
| 197 // contained pointers and push them on the marking stack. | |
| 198 class PLATFORM_EXPORT Visitor { | |
| 199 public: | |
| 200 virtual ~Visitor() { } | |
| 201 | |
| 202 template<typename T> | |
| 203 static void verifyGarbageCollectedIfMember(T*) | |
| 204 { | |
| 205 } | |
| 206 | |
| 207 template<typename T> | |
| 208 static void verifyGarbageCollectedIfMember(Member<T>* t) | |
| 209 { | |
| 210 } | |
| 211 | |
| 212 // One-argument templated mark method. This uses the static type of | |
| 213 // the argument to get the TraceTrait. By default, the mark method | |
| 214 // of the TraceTrait just calls the virtual two-argument mark method on this | |
| 215 // visitor, where the second argument is the static trace method of the trai
t. | |
| 216 template<typename T> | |
| 217 void mark(T* t) | |
| 218 { | |
| 219 } | |
| 220 | |
| 221 // Member version of the one-argument templated trace method. | |
| 222 template<typename T> | |
| 223 void trace(const Member<T>& t) | |
| 224 { | |
| 225 } | |
| 226 | |
| 227 // Fallback method used only when we need to trace raw pointers of T. | |
| 228 // This is the case when a member is a union where we do not support members
. | |
| 229 template<typename T> | |
| 230 void trace(const T* t) | |
| 231 { | |
| 232 } | |
| 233 | |
| 234 template<typename T> | |
| 235 void trace(T* t) | |
| 236 { | |
| 237 } | |
| 238 | |
| 239 // WeakMember version of the templated trace method. It doesn't keep | |
| 240 // the traced thing alive, but will write null to the WeakMember later | |
| 241 // if the pointed-to object is dead. It's lying for this to be const, | |
| 242 // but the overloading resolver prioritizes constness too high when | |
| 243 // picking the correct overload, so all these trace methods have to have | |
| 244 // the same constness on their argument to allow the type to decide. | |
| 245 template<typename T> | |
| 246 void trace(const WeakMember<T>& t) | |
| 247 { | |
| 248 } | |
| 249 | |
| 250 template<typename T> | |
| 251 void traceInCollection(T& t, WTF::ShouldWeakPointersBeMarkedStrongly strongi
fy) | |
| 252 { | |
| 253 } | |
| 254 | |
| 255 // Fallback trace method for part objects to allow individual trace methods | |
| 256 // to trace through a part object with visitor->trace(m_partObject). This | |
| 257 // takes a const argument, because otherwise it will match too eagerly: a | |
| 258 // non-const argument would match a non-const Vector<T>& argument better | |
| 259 // than the specialization that takes const Vector<T>&. For a similar reason
, | |
| 260 // the other specializations take a const argument even though they are | |
| 261 // usually used with non-const arguments, otherwise this function would matc
h | |
| 262 // too well. | |
| 263 template<typename T> | |
| 264 void trace(const T& t) | |
| 265 { | |
| 266 } | |
| 267 | |
| 268 // The following trace methods are for off-heap collections. | |
| 269 template<typename T, size_t inlineCapacity> | |
| 270 void trace(const Vector<T, inlineCapacity>& vector) | |
| 271 { | |
| 272 } | |
| 273 | |
| 274 template<typename T, size_t N> | |
| 275 void trace(const Deque<T, N>& deque) | |
| 276 { | |
| 277 } | |
| 278 | |
| 279 #if !ENABLE(OILPAN) | |
| 280 // These trace methods are needed to allow compiling and calling trace on | |
| 281 // transition types. We need to support calls in the non-oilpan build | |
| 282 // because a fully transitioned type (which will have its trace method | |
| 283 // called) might trace a field that is in transition. Once transition types | |
| 284 // are removed these can be removed. | |
| 285 template<typename T> void trace(const OwnPtr<T>&) { } | |
| 286 template<typename T> void trace(const RefPtr<T>&) { } | |
| 287 template<typename T> void trace(const RawPtr<T>&) { } | |
| 288 template<typename T> void trace(const WeakPtr<T>&) { } | |
| 289 #endif | |
| 290 | |
| 291 // This method marks an object and adds it to the set of objects | |
| 292 // that should have their trace method called. Since not all | |
| 293 // objects have vtables we have to have the callback as an | |
| 294 // explicit argument, but we can use the templated one-argument | |
| 295 // mark method above to automatically provide the callback | |
| 296 // function. | |
| 297 virtual void mark(const void*, TraceCallback) = 0; | |
| 298 virtual void markNoTracing(const void* pointer) { mark(pointer, reinterpret_
cast<TraceCallback>(0)); } | |
| 299 virtual void markNoTracing(HeapObjectHeader* header) { mark(header, reinterp
ret_cast<TraceCallback>(0)); } | |
| 300 virtual void markNoTracing(FinalizedHeapObjectHeader* header) { mark(header,
reinterpret_cast<TraceCallback>(0)); } | |
| 301 | |
| 302 // Used to mark objects during conservative scanning. | |
| 303 virtual void mark(HeapObjectHeader*, TraceCallback) = 0; | |
| 304 virtual void mark(FinalizedHeapObjectHeader*, TraceCallback) = 0; | |
| 305 | |
| 306 // Used to delay the marking of objects until the usual marking | |
| 307 // including emphemeron iteration is done. This is used to delay | |
| 308 // the marking of collection backing stores until we know if they | |
| 309 // are reachable from locations other than the collection front | |
| 310 // object. If collection backings are reachable from other | |
| 311 // locations we strongify them to avoid issues with iterators and | |
| 312 // weak processing. | |
| 313 virtual void registerDelayedMarkNoTracing(const void*) = 0; | |
| 314 | |
| 315 // If the object calls this during the regular trace callback, then the | |
| 316 // WeakPointerCallback argument may be called later, when the strong roots | |
| 317 // have all been found. The WeakPointerCallback will normally use isAlive | |
| 318 // to find out whether some pointers are pointing to dying objects. When | |
| 319 // the WeakPointerCallback is done the object must have purged all pointers | |
| 320 // to objects where isAlive returned false. In the weak callback it is not | |
| 321 // allowed to touch other objects (except using isAlive) or to allocate on | |
| 322 // the GC heap. Note that even removing things from HeapHashSet or | |
| 323 // HeapHashMap can cause an allocation if the backing store resizes, but | |
| 324 // these collections know to remove WeakMember elements safely. | |
| 325 // | |
| 326 // The weak pointer callbacks are run on the thread that owns the | |
| 327 // object and other threads are not stopped during the | |
| 328 // callbacks. Since isAlive is used in the callback to determine | |
| 329 // if objects pointed to are alive it is crucial that the object | |
| 330 // pointed to belong to the same thread as the object receiving | |
| 331 // the weak callback. Since other threads have been resumed the | |
| 332 // mark bits are not valid for objects from other threads. | |
| 333 virtual void registerWeakMembers(const void* object, WeakPointerCallback cal
lback) { registerWeakMembers(object, object, callback); } | |
| 334 virtual void registerWeakMembers(const void*, const void*, WeakPointerCallba
ck) = 0; | |
| 335 | |
| 336 template<typename T, void (T::*method)(Visitor*)> | |
| 337 void registerWeakMembers(const T* obj) | |
| 338 { | |
| 339 registerWeakMembers(obj, &TraceMethodDelegate<T, method>::trampoline); | |
| 340 } | |
| 341 | |
| 342 // For simple cases where you just want to zero out a cell when the thing | |
| 343 // it is pointing at is garbage, you can use this. This will register a | |
| 344 // callback for each cell that needs to be zeroed, so if you have a lot of | |
| 345 // weak cells in your object you should still consider using | |
| 346 // registerWeakMembers above. | |
| 347 // | |
| 348 // In contrast to registerWeakMembers, the weak cell callbacks are | |
| 349 // run on the thread performing garbage collection. Therefore, all | |
| 350 // threads are stopped during weak cell callbacks. | |
| 351 template<typename T> | |
| 352 void registerWeakCell(T** cell) | |
| 353 { | |
| 354 registerWeakCell(reinterpret_cast<void**>(cell), &handleWeakCell<T>); | |
| 355 } | |
| 356 | |
| 357 virtual void registerWeakTable(const void*, EphemeronCallback, EphemeronCall
back) = 0; | |
| 358 #if ENABLE(ASSERT) | |
| 359 virtual bool weakTableRegistered(const void*) = 0; | |
| 360 #endif | |
| 361 | |
| 362 virtual bool isMarked(const void*) = 0; | |
| 363 | |
| 364 template<typename T> inline bool isAlive(T* obj) | |
| 365 { | |
| 366 // Check that we actually know the definition of T when tracing. | |
| 367 COMPILE_ASSERT(sizeof(T), WeNeedToKnowTheDefinitionOfTheTypeWeAreTracing
); | |
| 368 // The strongification of collections relies on the fact that once a | |
| 369 // collection has been strongified, there is no way that it can contain | |
| 370 // non-live entries, so no entries will be removed. Since you can't set | |
| 371 // the mark bit on a null pointer, that means that null pointers are | |
| 372 // always 'alive'. | |
| 373 if (!obj) | |
| 374 return true; | |
| 375 return ObjectAliveTrait<T>::isAlive(this, obj); | |
| 376 } | |
| 377 template<typename T> inline bool isAlive(const Member<T>& member) | |
| 378 { | |
| 379 return isAlive(member.get()); | |
| 380 } | |
| 381 template<typename T> inline bool isAlive(RawPtr<T> ptr) | |
| 382 { | |
| 383 return isAlive(ptr.get()); | |
| 384 } | |
| 385 | |
| 386 // Macro to declare methods needed for each typed heap. | |
| 387 #define DECLARE_VISITOR_METHODS(Type) \ | |
| 388 virtual void mark(const Type*, TraceCallback) = 0; \ | |
| 389 virtual bool isMarked(const Type*) = 0; | |
| 390 | |
| 391 FOR_EACH_TYPED_HEAP(DECLARE_VISITOR_METHODS) | |
| 392 #undef DECLARE_VISITOR_METHODS | |
| 393 | |
| 394 #if ENABLE(GC_PROFILE_MARKING) | |
| 395 void setHostInfo(void* object, const String& name) | |
| 396 { | |
| 397 m_hostObject = object; | |
| 398 m_hostName = name; | |
| 399 } | |
| 400 #endif | |
| 401 | |
| 402 protected: | |
| 403 virtual void registerWeakCell(void**, WeakPointerCallback) = 0; | |
| 404 #if ENABLE(GC_PROFILE_MARKING) | |
| 405 void* m_hostObject; | |
| 406 String m_hostName; | |
| 407 #endif | |
| 408 | |
| 409 private: | |
| 410 template<typename T> | |
| 411 static void handleWeakCell(Visitor* self, void* obj) | |
| 412 { | |
| 413 T** cell = reinterpret_cast<T**>(obj); | |
| 414 if (*cell && !self->isAlive(*cell)) | |
| 415 *cell = 0; | |
| 416 } | |
| 417 }; | |
| 418 | |
| 419 // We trace vectors by using the trace trait on each element, which means you | |
| 420 // can have vectors of general objects (not just pointers to objects) that can | |
| 421 // be traced. | |
| 422 template<typename T, size_t N> | |
| 423 struct OffHeapCollectionTraceTrait<WTF::Vector<T, N, WTF::DefaultAllocator> > { | |
| 424 typedef WTF::Vector<T, N, WTF::DefaultAllocator> Vector; | |
| 425 | |
| 426 static void trace(Visitor* visitor, const Vector& vector) | |
| 427 { | |
| 428 } | |
| 429 }; | |
| 430 | |
| 431 template<typename T, size_t N> | |
| 432 struct OffHeapCollectionTraceTrait<WTF::Deque<T, N> > { | |
| 433 typedef WTF::Deque<T, N> Deque; | |
| 434 | |
| 435 static void trace(Visitor* visitor, const Deque& deque) | |
| 436 { | |
| 437 } | |
| 438 }; | |
| 439 | |
| 440 template<typename T, typename Traits = WTF::VectorTraits<T> > | |
| 441 class HeapVectorBacking; | |
| 442 | |
| 443 template<typename Table> | |
| 444 class HeapHashTableBacking { | |
| 445 public: | |
| 446 static void finalize(void* pointer); | |
| 447 }; | |
| 448 | |
| 449 template<typename T> | |
| 450 class DefaultTraceTrait<T, false> { | |
| 451 public: | |
| 452 static void mark(Visitor* visitor, const T* t) | |
| 453 { | |
| 454 } | |
| 455 }; | |
| 456 | |
| 457 template<typename T> | |
| 458 class DefaultTraceTrait<T, true> { | |
| 459 public: | |
| 460 static void mark(Visitor* visitor, const T* self) | |
| 461 { | |
| 462 if (!self) | |
| 463 return; | |
| 464 | |
| 465 // Before doing adjustAndMark we need to check if the page is orphaned | |
| 466 // since we cannot call adjustAndMark if so, as there will be no vtable. | |
| 467 // If orphaned just mark the page as traced. | |
| 468 BaseHeapPage* heapPage = pageHeaderFromObject(self); | |
| 469 if (heapPage->orphaned()) { | |
| 470 heapPage->setTracedAfterOrphaned(); | |
| 471 return; | |
| 472 } | |
| 473 self->adjustAndMark(visitor); | |
| 474 } | |
| 475 }; | |
| 476 | |
| 477 template<typename T, bool = NeedsAdjustAndMark<T>::value> class DefaultObjectAli
veTrait; | |
| 478 | |
| 479 template<typename T> | |
| 480 class DefaultObjectAliveTrait<T, false> { | |
| 481 public: | |
| 482 static bool isAlive(Visitor* visitor, T* obj) | |
| 483 { | |
| 484 return visitor->isMarked(obj); | |
| 485 } | |
| 486 }; | |
| 487 | |
| 488 template<typename T> | |
| 489 class DefaultObjectAliveTrait<T, true> { | |
| 490 public: | |
| 491 static bool isAlive(Visitor* visitor, T* obj) | |
| 492 { | |
| 493 return obj->isAlive(visitor); | |
| 494 } | |
| 495 }; | |
| 496 | |
| 497 template<typename T> bool ObjectAliveTrait<T>::isAlive(Visitor* visitor, T* obj) | |
| 498 { | |
| 499 return DefaultObjectAliveTrait<T>::isAlive(visitor, obj); | |
| 500 } | |
| 501 | |
| 502 // The GarbageCollectedMixin interface and helper macro | |
| 503 // USING_GARBAGE_COLLECTED_MIXIN can be used to automatically define | |
| 504 // TraceTrait/ObjectAliveTrait on non-leftmost deriving classes | |
| 505 // which need to be garbage collected. | |
| 506 // | |
| 507 // Consider the following case: | |
| 508 // class B {}; | |
| 509 // class A : public GarbageCollected, public B {}; | |
| 510 // | |
| 511 // We can't correctly handle "Member<B> p = &a" as we can't compute addr of | |
| 512 // object header statically. This can be solved by using GarbageCollectedMixin: | |
| 513 // class B : public GarbageCollectedMixin {}; | |
| 514 // class A : public GarbageCollected, public B { | |
| 515 // USING_GARBAGE_COLLECTED_MIXIN(A) | |
| 516 // }; | |
| 517 // | |
| 518 // With the helper, as long as we are using Member<B>, TypeTrait<B> will | |
| 519 // dispatch adjustAndMark dynamically to find collect addr of the object header. | |
| 520 // Note that this is only enabled for Member<B>. For Member<A> which we can | |
| 521 // compute the object header addr statically, this dynamic dispatch is not used. | |
| 522 | |
| 523 class PLATFORM_EXPORT GarbageCollectedMixin { | |
| 524 public: | |
| 525 virtual void adjustAndMark(Visitor*) const { }; | |
| 526 virtual bool isAlive(Visitor*) const { return true; }; | |
| 527 virtual void trace(Visitor*) { } | |
| 528 }; | |
| 529 | |
| 530 #define USING_GARBAGE_COLLECTED_MIXIN(TYPE) \ | |
| 531 public: \ | |
| 532 virtual void adjustAndMark(blink::Visitor* visitor) const override \ | |
| 533 { \ | |
| 534 typedef WTF::IsSubclassOfTemplate<typename WTF::RemoveConst<TYPE>::Type,
blink::GarbageCollected> IsSubclassOfGarbageCollected; \ | |
| 535 COMPILE_ASSERT(IsSubclassOfGarbageCollected::value, OnlyGarbageCollected
ObjectsCanHaveGarbageCollectedMixins); \ | |
| 536 visitor->mark(static_cast<const TYPE*>(this), &blink::TraceTrait<TYPE>::
trace); \ | |
| 537 } \ | |
| 538 virtual bool isAlive(blink::Visitor* visitor) const override \ | |
| 539 { \ | |
| 540 return visitor->isAlive(this); \ | |
| 541 } \ | |
| 542 private: | |
| 543 | |
| 544 #if ENABLE(OILPAN) | |
| 545 #define WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(TYPE) USING_GARBAGE_COLLECTED_MIXI
N(TYPE) | |
| 546 #else | |
| 547 #define WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(TYPE) | |
| 548 #endif | |
| 549 | |
| 550 #if ENABLE(GC_PROFILING) | |
| 551 template<typename T> | |
| 552 struct TypenameStringTrait { | |
| 553 static const String& get() | |
| 554 { | |
| 555 DEFINE_STATIC_LOCAL(String, typenameString, (WTF::extractTypeNameFromFun
ctionName(WTF::extractNameFunction<T>()))); | |
| 556 return typenameString; | |
| 557 } | |
| 558 }; | |
| 559 #endif | |
| 560 | |
| 561 template<typename T> | |
| 562 struct GCInfoAtBase { | |
| 563 static const GCInfo* get() | |
| 564 { | |
| 565 static const GCInfo gcInfo = { | |
| 566 TraceTrait<T>::trace, | |
| 567 FinalizerTrait<T>::finalize, | |
| 568 FinalizerTrait<T>::nonTrivialFinalizer, | |
| 569 WTF::IsPolymorphic<T>::value, | |
| 570 #if ENABLE(GC_PROFILING) | |
| 571 TypenameStringTrait<T>::get() | |
| 572 #endif | |
| 573 }; | |
| 574 return &gcInfo; | |
| 575 } | |
| 576 }; | |
| 577 | |
| 578 template<typename T> class GarbageCollected; | |
| 579 template<typename T, bool = WTF::IsSubclassOfTemplate<typename WTF::RemoveConst<
T>::Type, GarbageCollected>::value> struct GetGarbageCollectedBase; | |
| 580 | |
| 581 template<typename T> | |
| 582 struct GetGarbageCollectedBase<T, true> { | |
| 583 typedef typename T::GarbageCollectedBase type; | |
| 584 }; | |
| 585 | |
| 586 template<typename T> | |
| 587 struct GetGarbageCollectedBase<T, false> { | |
| 588 typedef T type; | |
| 589 }; | |
| 590 | |
| 591 template<typename T> | |
| 592 struct GCInfoTrait { | |
| 593 static const GCInfo* get() | |
| 594 { | |
| 595 return GCInfoAtBase<typename GetGarbageCollectedBase<T>::type>::get(); | |
| 596 } | |
| 597 }; | |
| 598 | |
| 599 } | |
| 600 | |
| 601 #endif | |
| OLD | NEW |