#ifndef Visitor_h
#define Visitor_h
#include "platform/PlatformExport.h"
#include "platform/heap/ThreadState.h"
#include "wtf/Assertions.h"
#include "wtf/Deque.h"
#include "wtf/Forward.h"
#include "wtf/HashMap.h"
#include "wtf/HashSet.h"
#include "wtf/HashTraits.h"
#include "wtf/ListHashSet.h"
#include "wtf/OwnPtr.h"
#include "wtf/RefPtr.h"
#include "wtf/TypeTraits.h"
#ifndef NDEBUG
#define DEBUG_ONLY(x) x
#else
#define DEBUG_ONLY(x)
#endif
namespace WebCore {
class FinalizedHeapObjectHeader;
template<typename T> class GarbageCollectedFinalized;
class HeapObjectHeader;
template<typename T> class Member;
template<typename T> class WeakMember;
class Visitor;
template<bool needsTracing, bool isWeak, bool markWeakMembersStrongly, typename T, typename Traits> struct CollectionBackingTraceTrait;
template<typename T, void (T::*method)(Visitor*)>
struct TraceMethodDelegate {
static void trampoline(Visitor* visitor, void* self) { (reinterpret_cast<T*>(self)->*method)(visitor); }
};
struct GCInfo {
bool hasFinalizer() const { return m_nonTrivialFinalizer; }
TraceCallback m_trace;
FinalizationCallback m_finalize;
bool m_nonTrivialFinalizer;
};
template<typename T, bool isGarbageCollectedFinalized>
struct FinalizerTraitImpl;
template<typename T>
struct FinalizerTraitImpl<T, true> {
static void finalize(void* obj) { static_cast<T*>(obj)->finalizeGarbageCollectedObject(); };
};
template<typename T>
struct FinalizerTraitImpl<T, false> {
static void finalize(void* obj) { };
};
template<typename T>
struct FinalizerTrait {
static const bool nonTrivialFinalizer = WTF::IsSubclassOfTemplate<T, GarbageCollectedFinalized>::value;
static void finalize(void* obj) { FinalizerTraitImpl<T, nonTrivialFinalizer>::finalize(obj); }
};
template<typename T> struct GCInfoTrait;
template<typename T> class GarbageCollected;
class GarbageCollectedMixin;
template<typename T, bool = WTF::IsSubclassOfTemplate<T, GarbageCollected>::value> class NeedsAdjustAndMark;
template<typename T>
class NeedsAdjustAndMark<T, true> {
public:
static const bool value = false;
};
template<typename T>
class NeedsAdjustAndMark<T, false> {
public:
static const bool value = WTF::IsSubclass<T, GarbageCollectedMixin>::value;
};
template<typename T, bool = NeedsAdjustAndMark<T>::value> class DefaultTraceTrait;
template<typename T>
class TraceTrait {
public:
static void trace(Visitor* visitor, void* self)
{
static_cast<T*>(self)->trace(visitor);
}
static void mark(Visitor* visitor, const T* t)
{
DefaultTraceTrait<T>::mark(visitor, t);
}
#ifndef NDEBUG
static void checkGCInfo(Visitor* visitor, const T* t)
{
DefaultTraceTrait<T>::checkGCInfo(visitor, t);
}
#endif
};
template<typename T> class TraceTrait<const T> : public TraceTrait<T> { };
template<typename Collection>
struct OffHeapCollectionTraceTrait;
template<typename T>
struct ObjectAliveTrait {
static bool isAlive(Visitor*, T*);
};
class PLATFORM_EXPORT Visitor {
public:
virtual ~Visitor() { }
template<typename T>
void mark(T* t)
{
if (!t)
return;
#ifndef NDEBUG
TraceTrait<T>::checkGCInfo(this, t);
#endif
TraceTrait<T>::mark(this, t);
}
template<typename T>
void trace(const Member<T>& t)
{
mark(t.get());
}
template<typename T>
void trace(T* t)
{
mark(t);
}
template<typename T>
void trace(const WeakMember<T>& t)
{
registerWeakCell(t.cell());
}
template<typename T>
void trace(const T& t)
{
const_cast<T&>(t).trace(this);
}
template<typename T, size_t inlineCapacity>
void trace(const Vector<T, inlineCapacity, WTF::DefaultAllocator>& vector)
{
OffHeapCollectionTraceTrait<Vector<T, inlineCapacity, WTF::DefaultAllocator> >::trace(this, vector);
}
template<typename T, typename U, typename V>
void trace(const HashSet<T, U, V, WTF::DefaultAllocator>& hashSet)
{
OffHeapCollectionTraceTrait<HashSet<T, U, V, WTF::DefaultAllocator> >::trace(this, hashSet);
}
template<typename T, size_t inlineCapacity, typename U>
void trace(const ListHashSet<T, inlineCapacity, U>& hashSet)
{
OffHeapCollectionTraceTrait<ListHashSet<T, inlineCapacity, U> >::trace(this, hashSet);
}
template<typename T, size_t N>
void trace(const Deque<T, N>& deque)
{
OffHeapCollectionTraceTrait<Deque<T, N> >::trace(this, deque);
}
template<typename T, typename U, typename V, typename W, typename X>
void trace(const HashMap<T, U, V, W, X, WTF::DefaultAllocator>& map)
{
OffHeapCollectionTraceTrait<HashMap<T, U, V, W, X, WTF::DefaultAllocator> >::trace(this, map);
}
template<typename T>
void trace(const OwnPtr<T>& t)
{
if (t)
t->trace(this);
}
template<typename T>
void trace(const RefPtr<T>&)
{
#if ENABLE(OILPAN)
ASSERT_NOT_REACHED();
#endif
}
#if !ENABLE(OILPAN)
template<typename T>
void trace(const RawPtr<T>&)
{
}
#endif
virtual void mark(const void*, TraceCallback) = 0;
virtual void mark(HeapObjectHeader*, TraceCallback) = 0;
virtual void mark(FinalizedHeapObjectHeader*, TraceCallback) = 0;
virtual void registerWeakMembers(const void* object, WeakPointerCallback callback) { registerWeakMembers(object, object, callback); }
virtual void registerWeakMembers(const void*, const void*, WeakPointerCallback) = 0;
template<typename T, void (T::*method)(Visitor*)>
void registerWeakMembers(const T* obj)
{
registerWeakMembers(obj, &TraceMethodDelegate<T, method>::trampoline);
}
template<typename T>
void registerWeakCell(T** cell)
{
registerWeakCell(reinterpret_cast<void**>(cell), &handleWeakCell<T>);
}
virtual bool isMarked(const void*) = 0;
template<typename T> inline bool isAlive(T* obj)
{
return ObjectAliveTrait<T>::isAlive(this, obj);
}
template<typename T> inline bool isAlive(const Member<T>& member)
{
return isAlive(member.get());
}
#ifndef NDEBUG
void checkGCInfo(const void*, const GCInfo*);
#endif
#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;
FOR_EACH_TYPED_HEAP(DECLARE_VISITOR_METHODS)
#undef DECLARE_VISITOR_METHODS
protected:
virtual void registerWeakCell(void**, WeakPointerCallback) = 0;
private:
template<typename T>
static void handleWeakCell(Visitor* self, void* obj)
{
T** cell = reinterpret_cast<T**>(obj);
if (*cell && !self->isAlive(*cell))
*cell = 0;
}
};
template<typename T, typename HashFunctions, typename Traits>
struct OffHeapCollectionTraceTrait<WTF::HashSet<T, HashFunctions, Traits, WTF::DefaultAllocator> > {
typedef WTF::HashSet<T, HashFunctions, Traits, WTF::DefaultAllocator> HashSet;
static void trace(Visitor* visitor, const HashSet& set)
{
if (set.isEmpty())
return;
if (WTF::ShouldBeTraced<Traits>::value) {
HashSet& iterSet = const_cast<HashSet&>(set);
for (typename HashSet::iterator it = iterSet.begin(), end = iterSet.end(); it != end; ++it)
CollectionBackingTraceTrait<WTF::ShouldBeTraced<Traits>::value, Traits::isWeak, false, T, Traits>::mark(visitor, *it);
}
COMPILE_ASSERT(!Traits::isWeak, WeakOffHeapCollectionsConsideredDangerous0);
}
};
template<typename T, size_t inlineCapacity, typename HashFunctions>
struct OffHeapCollectionTraceTrait<WTF::ListHashSet<T, inlineCapacity, HashFunctions> > {
typedef WTF::ListHashSet<T, inlineCapacity, HashFunctions> ListHashSet;
static void trace(Visitor* visitor, const ListHashSet& set)
{
if (set.isEmpty())
return;
ListHashSet& iterSet = const_cast<ListHashSet&>(set);
for (typename ListHashSet::iterator it = iterSet.begin(), end = iterSet.end(); it != end; ++it)
visitor->trace(*it);
}
};
template<typename Key, typename Value, typename HashFunctions, typename KeyTraits, typename ValueTraits>
struct OffHeapCollectionTraceTrait<WTF::HashMap<Key, Value, HashFunctions, KeyTraits, ValueTraits, WTF::DefaultAllocator> > {
typedef WTF::HashMap<Key, Value, HashFunctions, KeyTraits, ValueTraits, WTF::DefaultAllocator> HashMap;
static void trace(Visitor* visitor, const HashMap& map)
{
if (map.isEmpty())
return;
if (WTF::ShouldBeTraced<KeyTraits>::value || WTF::ShouldBeTraced<ValueTraits>::value) {
HashMap& iterMap = const_cast<HashMap&>(map);
for (typename HashMap::iterator it = iterMap.begin(), end = iterMap.end(); it != end; ++it) {
CollectionBackingTraceTrait<WTF::ShouldBeTraced<KeyTraits>::value, KeyTraits::isWeak, false, Key, KeyTraits>::mark(visitor, it->key);
CollectionBackingTraceTrait<WTF::ShouldBeTraced<ValueTraits>::value, ValueTraits::isWeak, false, Value, ValueTraits>::mark(visitor, it->value);
}
}
COMPILE_ASSERT(!KeyTraits::isWeak, WeakOffHeapCollectionsConsideredDangerous1);
COMPILE_ASSERT(!ValueTraits::isWeak, WeakOffHeapCollectionsConsideredDangerous2);
}
};
template<typename T, size_t N>
struct OffHeapCollectionTraceTrait<WTF::Vector<T, N, WTF::DefaultAllocator> > {
typedef WTF::Vector<T, N, WTF::DefaultAllocator> Vector;
static void trace(Visitor* visitor, const Vector& vector)
{
if (vector.isEmpty())
return;
for (typename Vector::const_iterator it = vector.begin(), end = vector.end(); it != end; ++it)
TraceTrait<T>::trace(visitor, const_cast<T*>(it));
}
};
template<typename T, size_t N>
struct OffHeapCollectionTraceTrait<WTF::Deque<T, N> > {
typedef WTF::Deque<T, N> Deque;
static void trace(Visitor* visitor, const Deque& deque)
{
if (deque.isEmpty())
return;
for (typename Deque::const_iterator it = deque.begin(), end = deque.end(); it != end; ++it)
TraceTrait<T>::trace(visitor, const_cast<T*>(&(*it)));
}
};
template<typename T, typename Traits = WTF::VectorTraits<T> >
class HeapVectorBacking;
template<typename Table>
class HeapHashTableBacking {
public:
static void finalize(void* pointer);
};
template<typename T>
class DefaultTraceTrait<T, false> {
public:
static void mark(Visitor* visitor, const T* t)
{
visitor->mark(const_cast<T*>(t), &TraceTrait<T>::trace);
}
#ifndef NDEBUG
static void checkGCInfo(Visitor* visitor, const T* t)
{
visitor->checkGCInfo(const_cast<T*>(t), GCInfoTrait<T>::get());
}
#endif
};
template<typename T>
class DefaultTraceTrait<T, true> {
public:
static void mark(Visitor* visitor, const T* self)
{
self->adjustAndMark(visitor);
}
#ifndef NDEBUG
static void checkGCInfo(Visitor*, const T*) { }
#endif
};
template<typename T, bool = NeedsAdjustAndMark<T>::value> class DefaultObjectAliveTrait;
template<typename T>
class DefaultObjectAliveTrait<T, false> {
public:
static bool isAlive(Visitor* visitor, T* obj)
{
return visitor->isMarked(obj);
}
};
template<typename T>
class DefaultObjectAliveTrait<T, true> {
public:
static bool isAlive(Visitor* visitor, T* obj)
{
return obj->isAlive(visitor);
}
};
template<typename T> bool ObjectAliveTrait<T>::isAlive(Visitor* visitor, T* obj)
{
return DefaultObjectAliveTrait<T>::isAlive(visitor, obj);
}
class GarbageCollectedMixin {
public:
virtual void adjustAndMark(Visitor*) const = 0;
virtual bool isAlive(Visitor*) const = 0;
};
#define USING_GARBAGE_COLLECTED_MIXIN(TYPE) \
public: \
virtual void adjustAndMark(Visitor* visitor) const OVERRIDE \
{ \
typedef WTF::IsSubclassOfTemplate<TYPE, WebCore::GarbageCollected> IsSubclassOfGarbageCollected; \
COMPILE_ASSERT(IsSubclassOfGarbageCollected::value, OnlyGarbageCollectedObjectsCanHaveGarbageCollectedMixins); \
visitor->mark(this, &TraceTrait<TYPE>::trace);\
} \
virtual bool isAlive(Visitor* visitor) const OVERRIDE \
{ \
return visitor->isAlive(this); \
}
#if ENABLE(OILPAN)
#define WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(TYPE) USING_GARBAGE_COLLECTED_MIXIN(TYPE)
#else
#define WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(TYPE)
#endif
template<typename T>
struct GCInfoAtBase {
static const GCInfo* get()
{
static const GCInfo gcInfo = {
TraceTrait<T>::trace,
FinalizerTrait<T>::finalize,
FinalizerTrait<T>::nonTrivialFinalizer,
};
return &gcInfo;
}
};
template<typename T> class GarbageCollected;
template<typename T, bool = WTF::IsSubclassOfTemplate<T, GarbageCollected>::value> struct GetGarbageCollectedBase;
template<typename T>
struct GetGarbageCollectedBase<T, true> {
typedef typename T::GarbageCollectedBase type;
};
template<typename T>
struct GetGarbageCollectedBase<T, false> {
typedef T type;
};
template<typename T>
struct GCInfoTrait {
static const GCInfo* get()
{
return GCInfoAtBase<typename GetGarbageCollectedBase<T>::type>::get();
}
};
}
#endif