blob: 797e373cf5a9a05b903627f16ed4d1bb88f9aab4 [file] [log] [blame]
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef WrapperVisitor_h
#define WrapperVisitor_h
#include "platform/PlatformExport.h"
#include "platform/wtf/Allocator.h"
namespace v8 {
class Value;
template <class T>
class PersistentBase;
}
namespace blink {
template <typename T>
class TraceTrait;
template <typename T>
class Member;
class ScriptWrappable;
template <typename T>
class TraceWrapperV8Reference;
class TraceWrapperBase;
template <typename T>
class TraceWrapperMember;
/**
* Declares non-virtual traceWrappers method. Should be used on
* non-ScriptWrappable classes which should participate in wrapper tracing (e.g.
* StyleEngine):
*
* class StyleEngine: public TraceWrapperBase {
* public:
* DECLARE_TRACE_WRAPPERS();
* };
*/
#define DECLARE_TRACE_WRAPPERS() \
void TraceWrappers(const WrapperVisitor* visitor) const
/**
* Declares virtual traceWrappers method. It is used in ScriptWrappable, can be
* used to override the method in the subclasses, and can be used by
* non-ScriptWrappable classes which expect to be inherited.
*/
#define DECLARE_VIRTUAL_TRACE_WRAPPERS() virtual DECLARE_TRACE_WRAPPERS()
/**
* Provides definition of traceWrappers method. Custom code will usually call
* visitor->traceWrappers with all objects which could contribute to the set of
* reachable wrappers:
*
* DEFINE_TRACE_WRAPPERS(NodeRareData)
* {
* visitor->traceWrappers(m_nodeLists);
* visitor->traceWrappers(m_mutationObserverData);
* }
*/
#define DEFINE_TRACE_WRAPPERS(T) \
void T::TraceWrappers(const WrapperVisitor* visitor) const
#define DECLARE_TRACE_WRAPPERS_AFTER_DISPATCH() \
void TraceWrappersAfterDispatch(const WrapperVisitor*) const
#define DEFINE_TRACE_WRAPPERS_AFTER_DISPATCH(T) \
void T::TraceWrappersAfterDispatch(const WrapperVisitor* visitor) const
#define DEFINE_INLINE_TRACE_WRAPPERS() DECLARE_TRACE_WRAPPERS()
#define DEFINE_INLINE_VIRTUAL_TRACE_WRAPPERS() DECLARE_VIRTUAL_TRACE_WRAPPERS()
#define DEFINE_TRAIT_FOR_TRACE_WRAPPERS(ClassName) \
template <> \
inline void TraceTrait<ClassName>::TraceMarkedWrapper( \
const WrapperVisitor* visitor, const void* t) { \
const ClassName* traceable = ToWrapperTracingType(t); \
DCHECK(GetHeapObjectHeader(t)->IsWrapperHeaderMarked()); \
traceable->TraceWrappers(visitor); \
}
// ###########################################################################
// TODO(hlopko): Get rid of virtual calls using CRTP
class PLATFORM_EXPORT WrapperVisitor {
USING_FAST_MALLOC(WrapperVisitor);
public:
template <typename T>
static NOINLINE void MissedWriteBarrier() {
NOTREACHED();
}
template <typename T>
void TraceWrappers(const T* traceable) const {
static_assert(sizeof(T), "T must be fully defined");
if (!traceable) {
return;
}
if (TraceTrait<T>::GetHeapObjectHeader(traceable)
->IsWrapperHeaderMarked()) {
return;
}
MarkAndPushToMarkingDeque(traceable);
}
/**
* Trace all wrappers of |t|.
*
* If you cannot use TraceWrapperMember & the corresponding traceWrappers()
* for some reason (e.g., due to sizeof(TraceWrapperMember)), you can use
* Member and |traceWrappersWithManualWriteBarrier()|. See below.
*/
template <typename T>
void TraceWrappers(const TraceWrapperMember<T>& t) const {
TraceWrappers(t.Get());
}
/**
* Require all users of manual write barriers to make this explicit in their
* |traceWrappers| definition. Be sure to add
* |ScriptWrappableVisitor::writeBarrier(this, new_value)| after all
* assignments to the field. Otherwise, the objects may be collected
* prematurely.
*/
template <typename T>
void TraceWrappersWithManualWriteBarrier(const Member<T>& t) const {
TraceWrappers(t.Get());
}
template <typename T>
void TraceWrappersWithManualWriteBarrier(const WeakMember<T>& t) const {
TraceWrappers(t.Get());
}
template <typename T>
void TraceWrappersWithManualWriteBarrier(const T* traceable) const {
TraceWrappers(traceable);
}
virtual void TraceWrappers(
const TraceWrapperV8Reference<v8::Value>&) const = 0;
virtual void MarkWrapper(const v8::PersistentBase<v8::Value>*) const = 0;
virtual void DispatchTraceWrappers(const TraceWrapperBase*) const = 0;
virtual bool MarkWrapperHeader(HeapObjectHeader*) const = 0;
virtual void MarkWrappersInAllWorlds(const ScriptWrappable*) const = 0;
void MarkWrappersInAllWorlds(const TraceWrapperBase*) const {
// TraceWrapperBase cannot point to V8 and thus doesn't need to
// mark wrappers.
}
template <typename T>
ALWAYS_INLINE void MarkAndPushToMarkingDeque(const T* traceable) const {
if (PushToMarkingDeque(TraceTrait<T>::TraceMarkedWrapper,
TraceTrait<T>::GetHeapObjectHeader,
WrapperVisitor::MissedWriteBarrier<T>, traceable)) {
TraceTrait<T>::MarkWrapperNoTracing(this, traceable);
}
}
protected:
// Returns true if pushing to the marking deque was successful.
virtual bool PushToMarkingDeque(
void (*trace_wrappers_callback)(const WrapperVisitor*, const void*),
HeapObjectHeader* (*heap_object_header_callback)(const void*),
void (*missed_write_barrier_callback)(void),
const void*) const = 0;
};
} // namespace blink
#endif // WrapperVisitor_h