Index: Source/platform/heap/Visitor.h |
diff --git a/Source/platform/heap/Visitor.h b/Source/platform/heap/Visitor.h |
index 66ede6214f5f2703f9e713ee1263b6a8548d1dfe..4c793153679d22ef6f6ad9540c9e6d8bb7729f1f 100644 |
--- a/Source/platform/heap/Visitor.h |
+++ b/Source/platform/heap/Visitor.h |
@@ -187,6 +187,75 @@ public: |
template<typename T> class TraceTrait<const T> : public TraceTrait<T> { }; |
+// If ENABLE_EAGER_TRACING_BY_DEFAULT is set to 1, GCed objects will |
+// be eagerly traced by default. A class type can opt out by declaring |
+// a TraceEagerlyTrait<> specialization, mapping the value to 'false' |
+// (see the WILL_NOT_BE_EAGERLY_TRACED() macro below.) |
+#define ENABLE_EAGER_TRACING_BY_DEFAULT 0 |
+ |
+// DISABLE_ALL_EAGER_TRACING provides the "kill switch" for eager |
+// tracing; setting it to 1 will disable the use of eager tracing |
+// entirely. That is, eager tracing is disabled even if traits have |
+// been declared. |
+#define DISABLE_ALL_EAGER_TRACING 0 |
+ |
+// If TraceEagerlyTrait<T>::value is true, then the marker thread should |
+// invoke trace() on not-yet-marked objects deriving from class T right |
+// away, and not queue their trace callbacks on its marker stack. |
+// |
+// Specific template specializations of TraceEagerlyTrait<T> can be used |
+// to declare that eager tracing should always be used when tracing over |
+// GCed objects with class type T. If the trait's boolean 'value' is |
+// mapped to 'true' that is; declare it as 'false' to disable eager tracing. |
+// |
+// The trait can be declared to enable/disable eager tracing for a class T |
+// and any of its subclasses, or just to the class T (but none of its subclasses.) |
+// |
+template<typename T, typename Enabled = void> |
+class TraceEagerlyTrait { |
+public: |
+ static const bool value = ENABLE_EAGER_TRACING_BY_DEFAULT; |
+}; |
+ |
+#define WILL_BE_EAGERLY_TRACED(TYPE) \ |
+template<typename U> \ |
+class TraceEagerlyTrait<U, typename WTF::EnableIf<WTF::IsSubclass<U, TYPE>::value>::Type> { \ |
+public: \ |
+ static const bool value = true; \ |
+} |
+ |
+#define WILL_NOT_BE_EAGERLY_TRACED(TYPE) \ |
+template<typename U> \ |
+class TraceEagerlyTrait<U, typename WTF::EnableIf<WTF::IsSubclass<U, TYPE>::value>::Type> { \ |
+public: \ |
+ static const bool value = false; \ |
+} |
+ |
+// Limit eager tracing to only apply to TYPE (but not any of its subclasses.) |
+#define WILL_BE_EAGERLY_TRACED_CLASS(TYPE) \ |
+template<> \ |
+class TraceEagerlyTrait<TYPE> { \ |
+public: \ |
+ static const bool value = true; \ |
+} |
+ |
+#define WILL_NOT_BE_EAGERLY_TRACED_CLASS(TYPE) \ |
+template<> \ |
+class TraceEagerlyTrait<TYPE> { \ |
+public: \ |
+ static const bool value = false; \ |
+} |
+ |
+// Set to 1 if you want collections to be eagerly traced regardless |
+// of whether the elements are eagerly traceable or not. |
+#define ENABLE_EAGER_HEAP_COLLECTION_TRACING ENABLE_EAGER_TRACING_BY_DEFAULT |
+ |
+#if ENABLE_EAGER_HEAP_COLLECTION_TRACING |
+#define IS_EAGERLY_TRACED_HEAP_COLLECTION(Type) true |
+#else |
+#define IS_EAGERLY_TRACED_HEAP_COLLECTION(Type) TraceEagerlyTrait<Type>::value |
+#endif |
+ |
template<typename Collection> |
struct OffHeapCollectionTraceTrait; |
@@ -329,6 +398,8 @@ public: |
// mark method above to automatically provide the callback |
// function. |
virtual void mark(const void*, TraceCallback) = 0; |
+ |
+ template<typename T> void markNoTracing(const T* pointer) { mark(pointer, reinterpret_cast<TraceCallback>(0)); } |
void markNoTracing(const void* pointer) { mark(pointer, reinterpret_cast<TraceCallback>(0)); } |
void markNoTracing(HeapObjectHeader* header) { mark(header, reinterpret_cast<TraceCallback>(0)); } |
void markNoTracing(FinalizedHeapObjectHeader* header) { mark(header, reinterpret_cast<TraceCallback>(0)); } |
@@ -394,6 +465,7 @@ public: |
#endif |
virtual bool isMarked(const void*) = 0; |
+ virtual bool ensureMarked(const void*) = 0; |
template<typename T> inline bool isAlive(T* obj) |
{ |
@@ -422,10 +494,11 @@ public: |
#endif |
// Macro to declare methods needed for each typed heap. |
-#define DECLARE_VISITOR_METHODS(Type) \ |
- DEBUG_ONLY(void checkGCInfo(const Type*, const GCInfo*);) \ |
- virtual void mark(const Type*, TraceCallback) = 0; \ |
- virtual bool isMarked(const Type*) = 0; |
+#define DECLARE_VISITOR_METHODS(Type) \ |
+ DEBUG_ONLY(void checkGCInfo(const Type*, const GCInfo*);) \ |
+ virtual void mark(const Type*, TraceCallback) = 0; \ |
+ virtual bool isMarked(const Type*) = 0; \ |
+ virtual bool ensureMarked(const Type*) = 0; |
FOR_EACH_TYPED_HEAP(DECLARE_VISITOR_METHODS) |
#undef DECLARE_VISITOR_METHODS |
@@ -502,6 +575,14 @@ public: |
// method on the visitor. The second argument is the static trace method |
// of the trait, which by default calls the instance method |
// trace(Visitor*) on the object. |
+ // |
+ // If the trait allows it, invoke the trace callback right here on the |
+ // not-yet-marked object. |
+ if (!DISABLE_ALL_EAGER_TRACING && TraceEagerlyTrait<T>::value) { |
+ if (visitor->ensureMarked(t)) |
+ TraceTrait<T>::trace(visitor, const_cast<T*>(t)); |
+ return; |
+ } |
visitor->mark(const_cast<T*>(t), &TraceTrait<T>::trace); |
} |
@@ -592,13 +673,18 @@ public: |
#define USING_GARBAGE_COLLECTED_MIXIN(TYPE) \ |
public: \ |
- virtual void adjustAndMark(blink::Visitor* visitor) const override \ |
+ virtual void adjustAndMark(blink::Visitor* visitor) const override \ |
{ \ |
typedef WTF::IsSubclassOfTemplate<typename WTF::RemoveConst<TYPE>::Type, blink::GarbageCollected> IsSubclassOfGarbageCollected; \ |
- COMPILE_ASSERT(IsSubclassOfGarbageCollected::value, OnlyGarbageCollectedObjectsCanHaveGarbageCollectedMixins); \ |
+ COMPILE_ASSERT(IsSubclassOfGarbageCollected::value, OnlyGarbageCollectedObjectsCanHaveGarbageCollectedMixins); \ |
+ if (!DISABLE_ALL_EAGER_TRACING && TraceEagerlyTrait<TYPE>::value) { \ |
+ if (visitor->ensureMarked(static_cast<const TYPE*>(this))) \ |
+ TraceTrait<TYPE>::trace(visitor, const_cast<TYPE*>(this)); \ |
+ return; \ |
+ } \ |
visitor->mark(static_cast<const TYPE*>(this), &blink::TraceTrait<TYPE>::trace); \ |
} \ |
- virtual bool isHeapObjectAlive(blink::Visitor* visitor) const override \ |
+ virtual bool isHeapObjectAlive(blink::Visitor* visitor) const override \ |
{ \ |
return visitor->isAlive(this); \ |
} \ |