Chromium Code Reviews| Index: Source/platform/heap/Visitor.h |
| diff --git a/Source/platform/heap/Visitor.h b/Source/platform/heap/Visitor.h |
| index 66ede6214f5f2703f9e713ee1263b6a8548d1dfe..e4a543a92f318939d5f4f2312cd509e4d3285e98 100644 |
| --- a/Source/platform/heap/Visitor.h |
| +++ b/Source/platform/heap/Visitor.h |
| @@ -187,6 +187,93 @@ public: |
| template<typename T> class TraceTrait<const T> : public TraceTrait<T> { }; |
| +// If TraceEagerlyTrait<T>::value is true, then the marker thread should |
| +// invoke trace() on unmarked objects deriving from class T right away, |
| +// and not queue its trace callback on the marker stack. |
| +template<typename T> class TraceEagerlyTrait; |
| + |
| +// 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. |
| +// |
| +// Should you want to declare that a class T and all its derived objects, |
| +// should all be eagerly traced - regardless of the particular class type |
| +// they end up being traced over - make T derive/inherit from the empty |
| +// class TraceEagerly. |
| +// |
| +// To express the opposite, that a class T and its derived classes should |
| +// never be eagerly traced, use TraceNonEagerly. This only makes sense |
| +// if enable eager tracing by default (see ENABLE_EAGER_TRACING_BY_DEFAULT |
| +// below.) |
| +class TraceEagerly { }; |
| +class TraceNonEagerly { }; |
| + |
| +// 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), or derive |
| +// from the TraceNonEagerly class. |
| +#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 or types derive from TraceEagerly. |
| +#define DISABLE_ALL_EAGER_TRACING 0 |
| + |
| +// If TraceEagerlyTrait<T>::value is true, then the marker thread should |
| +// invoke trace() on unmarked objects deriving from class T right away, |
| +// and not queue its trace callback on the marker stack. |
| +template<typename T> |
| +class TraceEagerlyTrait { |
| + typedef typename WTF::RemoveConst<T>::Type NonConstType; |
| + typedef WTF::IsSubclass<NonConstType, TraceEagerly> TraceEagerlySubclass; |
| + typedef WTF::IsSubclass<NonConstType, TraceNonEagerly> TraceNonEagerlySubclass; |
| +public: |
| + static const bool value = (DISABLE_ALL_EAGER_TRACING || TraceNonEagerlySubclass::value) ? false : (ENABLE_EAGER_TRACING_BY_DEFAULT || TraceEagerlySubclass::value); |
| +}; |
| + |
| +template<typename T> |
| +class TraceEagerlyTrait<Member<T>> { |
| +public: |
| + static const bool value = TraceEagerlyTrait<T>::value; |
| +}; |
| + |
| +template<typename T> |
| +class TraceEagerlyTrait<WeakMember<T>> { |
| +public: |
| + static const bool value = TraceEagerlyTrait<T>::value; |
| +}; |
| + |
| +#if ENABLE(OILPAN) |
| +#define WILL_BE_EAGERLY_TRACED(Type) \ |
| +template<> \ |
| +class TraceEagerlyTrait<Type> { \ |
| +public: \ |
| + static const bool value = true; \ |
| +} |
| +#define WILL_NOT_BE_EAGERLY_TRACED(Type) \ |
| +template<> \ |
| +class TraceEagerlyTrait<Type> { \ |
| +public: \ |
| + static const bool value = false; \ |
| +} |
| +#else |
| +#define WILL_BE_EAGERLY_TRACED(Type) |
| +#define WILL_NOT_BE_EAGERLY_TRACED(Type) |
| +#endif |
| + |
| +// 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 +416,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)); } |
|
kouhei (in TOK)
2014/11/28 01:00:57
insert space.
sof
2014/12/01 10:59:54
Done.
|
| 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 +483,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 +512,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 +593,13 @@ 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 trait allows it, invoke trace callback right here on unmarked objects. |
| + if (!DISABLE_ALL_EAGER_TRACING && TraceEagerlyTrait<T>::value) { |
| + if (!visitor->ensureMarked(t)) |
| + TraceTrait<T>::trace(visitor, const_cast<T*>(t)); |
|
haraken
2014/11/28 05:20:05
Just recursively tracing an object is not enough f
haraken
2014/11/28 12:39:27
Are you going to address this one? Or is it not a
sof
2014/11/28 12:44:27
I need to make progress on other fronts right now.
sof
2014/12/01 10:59:54
Now addressed, but a gnarlier issue to get right.
|
| + return; |
| + } |
| visitor->mark(const_cast<T*>(t), &TraceTrait<T>::trace); |
| } |
| @@ -592,13 +690,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); \ |
| } \ |