Bug 616262 - Avoid cycle collection participant global variables adding static initializers. r=smaug,r=mccr8,r=Waldo

This commit is contained in:
Mike Hommey 2012-06-04 08:30:26 +02:00
Родитель 373f2d749a
Коммит fcf0451143
22 изменённых файлов: 403 добавлений и 247 удалений

Просмотреть файл

@ -88,7 +88,7 @@ AccEvent::CreateXPCOMObject()
////////////////////////////////////////////////////////////////////////////////
// AccEvent cycle collection
NS_IMPL_CYCLE_COLLECTION_CLASS(AccEvent)
NS_IMPL_CYCLE_COLLECTION_NATIVE_CLASS(AccEvent)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_NATIVE(AccEvent)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mAccessible)

Просмотреть файл

@ -56,7 +56,7 @@ NotificationController::~NotificationController()
NS_IMPL_ADDREF(NotificationController)
NS_IMPL_RELEASE(NotificationController)
NS_IMPL_CYCLE_COLLECTION_CLASS(NotificationController)
NS_IMPL_CYCLE_COLLECTION_NATIVE_CLASS(NotificationController)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_NATIVE(NotificationController)
if (tmp->mDocument)
@ -812,7 +812,7 @@ NotificationController::ContentInsertion::
return haveToUpdate;
}
NS_IMPL_CYCLE_COLLECTION_CLASS(NotificationController::ContentInsertion)
NS_IMPL_CYCLE_COLLECTION_NATIVE_CLASS(NotificationController::ContentInsertion)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_NATIVE(NotificationController::ContentInsertion)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mContainer)

Просмотреть файл

@ -111,7 +111,7 @@ Accessible::QueryInterface(REFNSIID aIID, void** aInstancePtr)
*aInstancePtr = nsnull;
if (aIID.Equals(NS_GET_IID(nsXPCOMCycleCollectionParticipant))) {
*aInstancePtr = &NS_CYCLE_COLLECTION_NAME(Accessible);
*aInstancePtr = NS_CYCLE_COLLECTION_PARTICIPANT(Accessible);
return NS_OK;
}

Просмотреть файл

@ -2158,7 +2158,7 @@ typedef nsCharSeparatedTokenizerTemplate<nsContentUtils::IsHTMLWhitespace>
#define NS_HOLD_JS_OBJECTS(obj, clazz) \
nsContentUtils::HoldJSObjects(NS_CYCLE_COLLECTION_UPCAST(obj, clazz), \
&NS_CYCLE_COLLECTION_NAME(clazz))
NS_CYCLE_COLLECTION_PARTICIPANT(clazz))
#define NS_DROP_JS_OBJECTS(obj, clazz) \
nsContentUtils::DropJSObjects(NS_CYCLE_COLLECTION_UPCAST(obj, clazz))

Просмотреть файл

@ -130,7 +130,7 @@ nsNodeInfoManager::~nsNodeInfoManager()
}
NS_IMPL_CYCLE_COLLECTION_CLASS(nsNodeInfoManager)
NS_IMPL_CYCLE_COLLECTION_NATIVE_CLASS(nsNodeInfoManager)
NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(nsNodeInfoManager, AddRef)
NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(nsNodeInfoManager, Release)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NATIVE_0(nsNodeInfoManager)

Просмотреть файл

@ -145,7 +145,7 @@ nsEventListenerManager::Shutdown()
nsDOMEvent::Shutdown();
}
NS_IMPL_CYCLE_COLLECTION_CLASS(nsEventListenerManager)
NS_IMPL_CYCLE_COLLECTION_NATIVE_CLASS(nsEventListenerManager)
NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(nsEventListenerManager, AddRef)
NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(nsEventListenerManager, Release)

Просмотреть файл

@ -257,7 +257,7 @@ TraverseKey(nsISupports* aKey, nsInsertionPointList* aData, void* aClosure)
return PL_DHASH_NEXT;
}
NS_IMPL_CYCLE_COLLECTION_CLASS(nsXBLBinding)
NS_IMPL_CYCLE_COLLECTION_NATIVE_CLASS(nsXBLBinding)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_NATIVE(nsXBLBinding)
// XXX Probably can't unlink mPrototypeBinding->XBLDocumentInfo(), because
// mPrototypeBinding is weak.

Просмотреть файл

@ -24,7 +24,7 @@ nsXBLInsertionPoint::~nsXBLInsertionPoint()
}
}
NS_IMPL_CYCLE_COLLECTION_CLASS(nsXBLInsertionPoint)
NS_IMPL_CYCLE_COLLECTION_NATIVE_CLASS(nsXBLInsertionPoint)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_NATIVE(nsXBLInsertionPoint)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMARRAY(mElements)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mDefaultContentTemplate)

Просмотреть файл

@ -227,7 +227,7 @@ private:
PRUint32 nsXBLInsertionPointEntry::gRefCnt = 0;
nsFixedSizeAllocator* nsXBLInsertionPointEntry::kPool;
NS_IMPL_CYCLE_COLLECTION_CLASS(nsXBLInsertionPointEntry)
NS_IMPL_CYCLE_COLLECTION_NATIVE_CLASS(nsXBLInsertionPointEntry)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_NATIVE(nsXBLInsertionPointEntry)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mInsertionParent)
if (tmp->mDefaultContent) {

Просмотреть файл

@ -755,7 +755,7 @@ nsScriptEventHandlerOwnerTearoff::CompileEventHandler(
if (!elem->mHoldsScriptObject) {
rv = nsContentUtils::HoldJSObjects(
elem, &NS_CYCLE_COLLECTION_NAME(nsXULPrototypeNode));
elem, NS_CYCLE_COLLECTION_PARTICIPANT(nsXULPrototypeNode));
NS_ENSURE_SUCCESS(rv, rv);
}
@ -3098,7 +3098,7 @@ nsXULPrototypeScript::Set(JSScript* aObject)
}
nsresult rv = nsContentUtils::HoldJSObjects(
this, &NS_CYCLE_COLLECTION_NAME(nsXULPrototypeNode));
this, NS_CYCLE_COLLECTION_PARTICIPANT(nsXULPrototypeNode));
if (NS_SUCCEEDED(rv)) {
mScriptObject.mObject = aObject;
}

Просмотреть файл

@ -10,7 +10,7 @@
NS_IMPL_ADDREF(nsXMLBindingSet)
NS_IMPL_RELEASE(nsXMLBindingSet)
NS_IMPL_CYCLE_COLLECTION_CLASS(nsXMLBindingSet)
NS_IMPL_CYCLE_COLLECTION_NATIVE_CLASS(nsXMLBindingSet)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_NATIVE(nsXMLBindingSet)
nsXMLBinding* binding = tmp->mFirst;

Просмотреть файл

@ -85,7 +85,7 @@ TraverseRuleToBindingsMap(nsISupports* aKey, nsXMLBindingSet* aMatch, void* aCon
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(*cb, "mRuleToBindingsMap key");
cb->NoteXPCOMChild(aKey);
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(*cb, "mRuleToBindingsMap value");
cb->NoteNativeChild(aMatch, &NS_CYCLE_COLLECTION_NAME(nsXMLBindingSet));
cb->NoteNativeChild(aMatch, NS_CYCLE_COLLECTION_PARTICIPANT(nsXMLBindingSet));
return PL_DHASH_NEXT;
}

Просмотреть файл

@ -538,7 +538,7 @@ nsTimeout::~nsTimeout()
MOZ_COUNT_DTOR(nsTimeout);
}
NS_IMPL_CYCLE_COLLECTION_CLASS(nsTimeout)
NS_IMPL_CYCLE_COLLECTION_NATIVE_CLASS(nsTimeout)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NATIVE_0(nsTimeout)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_BEGIN(nsTimeout)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR_AMBIGUOUS(mWindow,
@ -1225,7 +1225,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsGlobalWindow)
for (nsTimeout* timeout = tmp->FirstTimeout();
tmp->IsTimeout(timeout);
timeout = timeout->Next()) {
cb.NoteNativeChild(timeout, &NS_CYCLE_COLLECTION_NAME(nsTimeout));
cb.NoteNativeChild(timeout, NS_CYCLE_COLLECTION_PARTICIPANT(nsTimeout));
}
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mLocalStorage)

Просмотреть файл

@ -43,7 +43,7 @@ nsTransactionItem::Release() {
return mRefCnt;
}
NS_IMPL_CYCLE_COLLECTION_CLASS(nsTransactionItem)
NS_IMPL_CYCLE_COLLECTION_NATIVE_CLASS(nsTransactionItem)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_NATIVE(nsTransactionItem)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mTransaction)

Просмотреть файл

@ -95,7 +95,7 @@ nsTransactionStack::DoTraverse(nsCycleCollectionTraversalCallback &cb)
static_cast<nsTransactionItem*>(mQue.ObjectAt(i));
if (item) {
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "transaction stack mQue[i]");
cb.NoteNativeChild(item, &NS_CYCLE_COLLECTION_NAME(nsTransactionItem));
cb.NoteNativeChild(item, NS_CYCLE_COLLECTION_PARTICIPANT(nsTransactionItem));
}
}
}

Просмотреть файл

@ -17,8 +17,9 @@
NS_IMPL_CYCLE_COLLECTION_CLASS(nsXPCWrappedJS)
NS_IMETHODIMP
NS_CYCLE_COLLECTION_CLASSNAME(nsXPCWrappedJS)::Traverse
(void *p, nsCycleCollectionTraversalCallback &cb)
NS_CYCLE_COLLECTION_CLASSNAME(nsXPCWrappedJS)::TraverseImpl
(NS_CYCLE_COLLECTION_CLASSNAME(nsXPCWrappedJS) *that, void *p,
nsCycleCollectionTraversalCallback &cb)
{
nsISupports *s = static_cast<nsISupports*>(p);
NS_ASSERTION(CheckForRightISupports(s),
@ -98,7 +99,7 @@ nsXPCWrappedJS::QueryInterface(REFNSIID aIID, void** aInstancePtr)
}
if ( aIID.Equals(NS_GET_IID(nsXPCOMCycleCollectionParticipant)) ) {
*aInstancePtr = & NS_CYCLE_COLLECTION_NAME(nsXPCWrappedJS);
*aInstancePtr = NS_CYCLE_COLLECTION_PARTICIPANT(nsXPCWrappedJS);
return NS_OK;
}

Просмотреть файл

@ -44,7 +44,7 @@ xpc_OkToHandOutWrapper(nsWrapperCache *cache)
NS_IMPL_CYCLE_COLLECTION_CLASS(XPCWrappedNative)
NS_IMETHODIMP
NS_CYCLE_COLLECTION_CLASSNAME(XPCWrappedNative)::Unlink(void *p)
NS_CYCLE_COLLECTION_CLASSNAME(XPCWrappedNative)::UnlinkImpl(void *p)
{
XPCWrappedNative *tmp = static_cast<XPCWrappedNative*>(p);
tmp->ExpireWrapper();
@ -52,8 +52,9 @@ NS_CYCLE_COLLECTION_CLASSNAME(XPCWrappedNative)::Unlink(void *p)
}
NS_IMETHODIMP
NS_CYCLE_COLLECTION_CLASSNAME(XPCWrappedNative)::Traverse(void *p,
nsCycleCollectionTraversalCallback &cb)
NS_CYCLE_COLLECTION_CLASSNAME(XPCWrappedNative)::TraverseImpl
(NS_CYCLE_COLLECTION_CLASSNAME(XPCWrappedNative) *that, void *p,
nsCycleCollectionTraversalCallback &cb)
{
XPCWrappedNative *tmp = static_cast<XPCWrappedNative*>(p);
if (!tmp->IsValid())

Просмотреть файл

@ -543,28 +543,33 @@ nsXPConnect::FinishTraverse()
return NS_OK;
}
class nsXPConnectParticipant: public nsCycleCollectionParticipant
{
public:
static NS_METHOD RootImpl(void *n)
{
return NS_OK;
}
static NS_METHOD UnlinkImpl(void *n)
{
return NS_OK;
}
static NS_METHOD UnrootImpl(void *n)
{
return NS_OK;
}
static NS_METHOD TraverseImpl(nsXPConnectParticipant *that, void *n,
nsCycleCollectionTraversalCallback &cb);
};
static CCParticipantVTable<nsXPConnectParticipant>::Type XPConnect_cycleCollectorGlobal = {
NS_IMPL_CYCLE_COLLECTION_NATIVE_VTABLE(nsXPConnectParticipant)
};
nsCycleCollectionParticipant *
nsXPConnect::GetParticipant()
{
return this;
}
NS_IMETHODIMP
nsXPConnect::Root(void *p)
{
return NS_OK;
}
NS_IMETHODIMP
nsXPConnect::Unlink(void *p)
{
return NS_OK;
}
NS_IMETHODIMP
nsXPConnect::Unroot(void *p)
{
return NS_OK;
return XPConnect_cycleCollectorGlobal.GetParticipant();
}
JSBool
@ -756,8 +761,9 @@ WrapperIsNotMainThreadOnly(XPCWrappedNative *wrapper)
return NS_FAILED(CallQueryInterface(wrapper->Native(), &participant));
}
NS_IMETHODIMP
nsXPConnect::Traverse(void *p, nsCycleCollectionTraversalCallback &cb)
NS_METHOD
nsXPConnectParticipant::TraverseImpl(nsXPConnectParticipant *that, void *p,
nsCycleCollectionTraversalCallback &cb)
{
JSGCTraceKind traceKind = js_GetGCThingTraceKind(p);
JSObject *obj = nsnull;
@ -843,7 +849,7 @@ nsXPConnect::Traverse(void *p, nsCycleCollectionTraversalCallback &cb)
TraversalTracer trc(cb);
JS_TracerInit(&trc, GetRuntime()->GetJSRuntime(), NoteJSChild);
JS_TracerInit(&trc, nsXPConnect::GetRuntimeInstance()->GetJSRuntime(), NoteJSChild);
trc.eagerlyTraceWeakMaps = false;
JS_TraceChildren(&trc, p, traceKind);
@ -897,11 +903,11 @@ nsXPConnect::GetOutstandingRequests(JSContext* cx)
class JSContextParticipant : public nsCycleCollectionParticipant
{
public:
NS_IMETHOD Root(void *n)
static NS_METHOD RootImpl(void *n)
{
return NS_OK;
}
NS_IMETHOD Unlink(void *n)
static NS_METHOD UnlinkImpl(void *n)
{
JSContext *cx = static_cast<JSContext*>(n);
JSAutoRequest ar(cx);
@ -909,11 +915,12 @@ public:
JS_SetGlobalObject(cx, NULL);
return NS_OK;
}
NS_IMETHOD Unroot(void *n)
static NS_METHOD UnrootImpl(void *n)
{
return NS_OK;
}
NS_IMETHODIMP Traverse(void *n, nsCycleCollectionTraversalCallback &cb)
static NS_METHOD TraverseImpl(JSContextParticipant *that, void *n,
nsCycleCollectionTraversalCallback &cb)
{
JSContext *cx = static_cast<JSContext*>(n);
@ -932,20 +939,22 @@ public:
}
};
static JSContextParticipant JSContext_cycleCollectorGlobal;
static CCParticipantVTable<JSContextParticipant>::Type JSContext_cycleCollectorGlobal = {
NS_IMPL_CYCLE_COLLECTION_NATIVE_VTABLE(JSContextParticipant)
};
// static
nsCycleCollectionParticipant*
nsXPConnect::JSContextParticipant()
{
return &JSContext_cycleCollectorGlobal;
return JSContext_cycleCollectorGlobal.GetParticipant();
}
NS_IMETHODIMP_(void)
nsXPConnect::NoteJSContext(JSContext *aJSContext,
nsCycleCollectionTraversalCallback &aCb)
{
aCb.NoteNativeChild(aJSContext, &JSContext_cycleCollectorGlobal);
aCb.NoteNativeChild(aJSContext, JSContext_cycleCollectorGlobal.GetParticipant());
}

Просмотреть файл

@ -478,7 +478,6 @@ class nsXPConnect : public nsIXPConnect,
public nsIThreadObserver,
public nsSupportsWeakReference,
public nsCycleCollectionJSRuntime,
public nsCycleCollectionParticipant,
public nsIJSRuntimeService,
public nsIThreadJSContextStack,
public nsIJSEngineTelemetryStats
@ -539,13 +538,6 @@ public:
nsresult GetInfoForIID(const nsIID * aIID, nsIInterfaceInfo** info);
nsresult GetInfoForName(const char * name, nsIInterfaceInfo** info);
// nsCycleCollectionParticipant
NS_IMETHOD Root(void *p);
NS_IMETHOD Unlink(void *p);
NS_IMETHOD Unroot(void *p);
NS_IMETHOD Traverse(void *p,
nsCycleCollectionTraversalCallback &cb);
// nsCycleCollectionLanguageRuntime
virtual bool NotifyLeaveMainThread();
virtual void NotifyEnterCycleCollectionThread();
@ -2555,9 +2547,9 @@ public:
{
NS_DECL_CYCLE_COLLECTION_CLASS_BODY_NO_UNLINK(XPCWrappedNative,
XPCWrappedNative)
NS_IMETHOD Root(void *p) { return NS_OK; }
NS_IMETHOD Unlink(void *p);
NS_IMETHOD Unroot(void *p) { return NS_OK; }
static NS_METHOD RootImpl(void *p) { return NS_OK; }
static NS_METHOD UnlinkImpl(void *p);
static NS_METHOD UnrootImpl(void *p) { return NS_OK; }
};
NS_CYCLE_COLLECTION_PARTICIPANT_INSTANCE
NS_DECL_CYCLE_COLLECTION_UNMARK_PURPLE_STUB(XPCWrappedNative)

Просмотреть файл

@ -72,10 +72,11 @@ class NS_CYCLE_COLLECTION_INNERCLASS \
: public nsXPCOMCycleCollectionParticipant \
{ \
public: \
NS_IMETHOD Unlink(void *p); \
NS_IMETHOD Traverse(void *p, \
nsCycleCollectionTraversalCallback &cb); \
NS_IMETHOD_(void) UnmarkIfPurple(nsISupports *p) \
static NS_METHOD UnlinkImpl(void *p); \
static NS_METHOD TraverseImpl(NS_CYCLE_COLLECTION_INNERCLASS *that, \
void *p, \
nsCycleCollectionTraversalCallback &cb); \
static NS_METHOD_(void) UnmarkIfPurpleImpl(nsISupports *p) \
{ \
Downcast(p)->UnmarkIfPurple(); \
} \
@ -263,14 +264,14 @@ _class::AggregatedQueryInterface(REFNSIID aIID, void** aInstancePtr) \
if (aIID.Equals(IsPartOfAggregated() ? \
NS_GET_IID(nsCycleCollectionParticipant) : \
NS_GET_IID(nsAggregatedCycleCollectionParticipant))) \
foundInterface = & NS_CYCLE_COLLECTION_NAME(_class); \
foundInterface = NS_CYCLE_COLLECTION_PARTICIPANT(_class); \
else
#define NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_AGGREGATED(_class) \
NS_IMETHODIMP \
NS_CYCLE_COLLECTION_CLASSNAME(_class)::Traverse \
(void *p, \
nsCycleCollectionTraversalCallback &cb) \
NS_METHOD \
NS_CYCLE_COLLECTION_CLASSNAME(_class)::TraverseImpl \
(NS_CYCLE_COLLECTION_CLASSNAME(_class) *that, \
void *p, nsCycleCollectionTraversalCallback &cb) \
{ \
nsISupports *s = static_cast<nsISupports*>(p); \
NS_ASSERTION(CheckForRightISupports(s), \

Просмотреть файл

@ -6,8 +6,9 @@
#include "nsCycleCollectionParticipant.h"
#include "nsCOMPtr.h"
static void
NoteChild(void *aScriptThing, const char *name, void *aClosure)
void
nsScriptObjectTracer::NoteJSChild(void *aScriptThing, const char *name,
void *aClosure)
{
nsCycleCollectionTraversalCallback *cb =
static_cast<nsCycleCollectionTraversalCallback*>(aClosure);
@ -15,15 +16,8 @@ NoteChild(void *aScriptThing, const char *name, void *aClosure)
cb->NoteJSChild(aScriptThing);
}
void
nsScriptObjectTracer::TraverseScriptObjects(void *p,
nsCycleCollectionTraversalCallback &cb)
{
Trace(p, NoteChild, &cb);
}
nsresult
nsXPCOMCycleCollectionParticipant::Root(void *p)
nsXPCOMCycleCollectionParticipant::RootImpl(void *p)
{
nsISupports *s = static_cast<nsISupports*>(p);
NS_ADDREF(s);
@ -31,13 +25,13 @@ nsXPCOMCycleCollectionParticipant::Root(void *p)
}
nsresult
nsXPCOMCycleCollectionParticipant::Unlink(void *p)
nsXPCOMCycleCollectionParticipant::UnlinkImpl(void *p)
{
return NS_OK;
}
nsresult
nsXPCOMCycleCollectionParticipant::Unroot(void *p)
nsXPCOMCycleCollectionParticipant::UnrootImpl(void *p)
{
nsISupports *s = static_cast<nsISupports*>(p);
NS_RELEASE(s);
@ -45,20 +39,21 @@ nsXPCOMCycleCollectionParticipant::Unroot(void *p)
}
nsresult
nsXPCOMCycleCollectionParticipant::Traverse
(void *p, nsCycleCollectionTraversalCallback &cb)
nsXPCOMCycleCollectionParticipant::TraverseImpl
(nsXPCOMCycleCollectionParticipant* that, void *p,
nsCycleCollectionTraversalCallback &cb)
{
return NS_OK;
}
void
nsXPCOMCycleCollectionParticipant::UnmarkIfPurple(nsISupports *n)
nsXPCOMCycleCollectionParticipant::UnmarkIfPurpleImpl(nsISupports *n)
{
}
NS_IMETHODIMP_(void)
nsXPCOMCycleCollectionParticipant::Trace(void *p, TraceCallback cb,
void *closure)
nsXPCOMCycleCollectionParticipant::TraceImpl(void *p, TraceCallback cb,
void *closure)
{
}

Просмотреть файл

@ -6,6 +6,7 @@
#ifndef nsCycleCollectionParticipant_h__
#define nsCycleCollectionParticipant_h__
#include "mozilla/TypeTraits.h"
#include "nsISupports.h"
#define NS_CYCLECOLLECTIONPARTICIPANT_IID \
@ -43,7 +44,18 @@ public:
NS_DEFINE_STATIC_IID_ACCESSOR(nsCycleCollectionISupports,
NS_CYCLECOLLECTIONISUPPORTS_IID)
/**
* Forward declarations
*/
class nsCycleCollectionParticipant;
class nsScriptObjectTracer;
class nsXPCOMCycleCollectionParticipant;
/**
* Callback definitions
*/
typedef void
(* TraceCallback)(void *p, const char *name, void *closure);
class NS_NO_VTABLE nsCycleCollectionTraversalCallback
{
@ -97,27 +109,162 @@ protected:
PRUint32 mFlags;
};
class NS_NO_VTABLE nsCycleCollectionParticipant
/**
* VTables
*
* When using global scope static initialization for simple types with virtual
* member functions, GCC creates static initializer functions. In order to
* avoid this from happening, cycle collection participants are defined as
* function tables.
*
* The Traverse function may require calling another function from the cycle
* collection participant function table, so a pointer to the function table
* is given to it. Using member function pointers would be less awkward, but
* in MSVC, the size of such a member function pointer depends on the class
* the function is member of. This makes it hard to make them compatible with
* a generic function table. Moreover, static initialization of the function
* table then uses a static initializer function.
*
* Finally, it is not possible to use an initializer list for non-aggregate
* types. Separate types are thus required for static initialization. For
* convenience and to avoid repetitions that could lead to discrepancies,
* function table members for sub-types are declared independently, and
* different aggregate types are defined for static initialization.
*/
/* Base functions for nsCycleCollectionParticipant */
template <typename T>
struct nsCycleCollectionParticipantVTableCommon
{
nsresult (NS_STDCALL *TraverseReal)
(T *that, void *p, nsCycleCollectionTraversalCallback &cb);
nsresult (NS_STDCALL *Root)(void *p);
nsresult (NS_STDCALL *Unlink)(void *p);
nsresult (NS_STDCALL *Unroot)(void *p);
bool (NS_STDCALL *CanSkipReal)(void *p, bool aRemovingAllowed);
bool (NS_STDCALL *CanSkipInCCReal)(void *p);
bool (NS_STDCALL *CanSkipThisReal)(void *p);
};
typedef nsCycleCollectionParticipantVTableCommon<nsCycleCollectionParticipant>
nsCycleCollectionParticipantVTable;
/* Additional functions for nsScriptObjectTracer */
struct nsScriptObjectTracerVTable
{
void (NS_STDCALL *Trace)(void *p, TraceCallback cb, void *closure);
};
/* Additional functions for nsXPCOMCycleCollectionParticipant */
struct nsXPCOMCycleCollectionParticipantVTable
{
void (NS_STDCALL *UnmarkIfPurple)(nsISupports *p);
};
/**
* Types for static initialization
*
* Considering T, the cycle collection participant class, subclass of either
* nsCycleCollectionParticipant, nsScriptObjectTracer or
* nsXPCOMCycleCollectionParticipant, static initialization goes as follows:
*
* CCParticipantVTable<T>::type T::_cycleCollectorGlobal = {{...} ...};
*
* CCParticipantVTable<T>::type automatically defines the right type considering
* what particular cycle collection participant class T derives from.
*
* The NS_IMPL_CYCLE_COLLECTION_NATIVE_VTABLE(classname),
* NS_IMPL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_VTABLE(classname), and
* NS_IMPL_CYCLE_COLLECTION_VTABLE(classname) macros may be used as helpers
* for static initialization:
*
* CCParticipantVTable<T>::type T::_cycleCollectorGlobal = {
* NS_IMPL_CYCLE_COLLECTION_NATIVE_VTABLE(classname);
* };
*/
enum nsCycleCollectionParticipantType
{
eInvalid,
eCycleCollectionParticipant,
eScriptObjectTracer,
eXPCOMCycleCollectionParticipant
};
template <typename T, enum nsCycleCollectionParticipantType ParticipantType>
struct CCParticipantVTableImpl { };
/* CCParticipantVTable for nsCycleCollectionParticipant */
template <typename T>
struct CCParticipantVTableImpl<T, eCycleCollectionParticipant>
{
nsCycleCollectionParticipant *GetParticipant()
{
return reinterpret_cast<nsCycleCollectionParticipant *>(this);
}
nsCycleCollectionParticipantVTableCommon<T> cycleCollectionParticipant;
};
/* CCParticipantVTable for nsScriptObjectTracer */
template <typename T>
struct CCParticipantVTableImpl<T, eScriptObjectTracer>
{
nsScriptObjectTracer *GetParticipant()
{
return reinterpret_cast<nsScriptObjectTracer *>(this);
}
nsCycleCollectionParticipantVTableCommon<T> cycleCollectionParticipant;
nsScriptObjectTracerVTable scriptObjectTracer;
};
/* CCParticipantVTable for nsXPCOMCycleCollectionParticipant */
template <typename T>
struct CCParticipantVTableImpl<T, eXPCOMCycleCollectionParticipant>
{
nsXPCOMCycleCollectionParticipant *GetParticipant()
{
return reinterpret_cast<nsXPCOMCycleCollectionParticipant *>(this);
}
nsCycleCollectionParticipantVTableCommon<T> cycleCollectionParticipant;
nsScriptObjectTracerVTable scriptObjectTracer;
nsXPCOMCycleCollectionParticipantVTable XPCOMCycleCollectionParticipant;
};
template <typename T>
struct CCParticipantVTable
{
static const enum nsCycleCollectionParticipantType ParticipantType =
mozilla::IsBaseOf<nsXPCOMCycleCollectionParticipant, T>::value ? eXPCOMCycleCollectionParticipant :
mozilla::IsBaseOf<nsScriptObjectTracer, T>::value ? eScriptObjectTracer :
mozilla::IsBaseOf<nsCycleCollectionParticipant, T>::value ? eCycleCollectionParticipant :
eInvalid;
typedef CCParticipantVTableImpl<T, ParticipantType> Type;
};
/**
* Participant implementation classes
*/
class nsCycleCollectionParticipant : public nsCycleCollectionParticipantVTable
{
public:
nsCycleCollectionParticipant() : mMightSkip(false) {}
nsCycleCollectionParticipant(bool aSkip) : mMightSkip(aSkip) {}
static const bool isSkippable = false;
NS_DECLARE_STATIC_IID_ACCESSOR(NS_CYCLECOLLECTIONPARTICIPANT_IID)
NS_IMETHOD Traverse(void *p, nsCycleCollectionTraversalCallback &cb) = 0;
NS_IMETHOD Root(void *p) = 0;
NS_IMETHOD Unlink(void *p) = 0;
NS_IMETHOD Unroot(void *p) = 0;
// Helper function to avoid painful syntax for member function call using
// the VTable entry.
NS_METHOD Traverse(void *p, nsCycleCollectionTraversalCallback &cb) {
return TraverseReal(this, p, cb);
}
// If CanSkip returns true, p is removed from the purple buffer during
// a call to nsCycleCollector_forgetSkippable().
// Note, calling CanSkip may remove objects from the purple buffer!
// If aRemovingAllowed is true, p can be removed from the purple buffer.
bool CanSkip(void *p, bool aRemovingAllowed)
{
return mMightSkip ? CanSkipReal(p, aRemovingAllowed) : false;
return CanSkipReal ? CanSkipReal(p, aRemovingAllowed) : false;
}
// If CanSkipInCC returns true, p is skipped when selecting roots for the
@ -125,7 +272,7 @@ public:
// Note, calling CanSkipInCC may remove other objects from the purple buffer!
bool CanSkipInCC(void *p)
{
return mMightSkip ? CanSkipInCCReal(p) : false;
return CanSkipInCCReal ? CanSkipInCCReal(p) : false;
}
// If CanSkipThis returns true, p is not added to the graph.
@ -133,73 +280,39 @@ public:
// change the state of any objects!
bool CanSkipThis(void *p)
{
return mMightSkip ? CanSkipThisReal(p) : false;
return CanSkipThisReal ? CanSkipThisReal(p) : false;
}
protected:
NS_IMETHOD_(bool) CanSkipReal(void *p, bool aRemovingAllowed)
{
NS_ASSERTION(false, "Forgot to implement CanSkipReal?");
return false;
}
NS_IMETHOD_(bool) CanSkipInCCReal(void *p)
{
NS_ASSERTION(false, "Forgot to implement CanSkipInCCReal?");
return false;
}
NS_IMETHOD_(bool) CanSkipThisReal(void *p)
{
NS_ASSERTION(false, "Forgot to implement CanSkipThisReal?");
return false;
}
bool mMightSkip;
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsCycleCollectionParticipant,
NS_CYCLECOLLECTIONPARTICIPANT_IID)
#undef IMETHOD_VISIBILITY
#define IMETHOD_VISIBILITY NS_COM_GLUE
typedef void
(* TraceCallback)(void *p, const char *name, void *closure);
class NS_NO_VTABLE nsScriptObjectTracer : public nsCycleCollectionParticipant
class nsScriptObjectTracer
: public nsCycleCollectionParticipant, public nsScriptObjectTracerVTable
{
public:
nsScriptObjectTracer() : nsCycleCollectionParticipant(false) {}
nsScriptObjectTracer(bool aSkip) : nsCycleCollectionParticipant(aSkip) {}
NS_IMETHOD_(void) Trace(void *p, TraceCallback cb, void *closure) = 0;
void NS_COM_GLUE TraverseScriptObjects(void *p,
nsCycleCollectionTraversalCallback &cb);
static void NS_COM_GLUE NoteJSChild(void *aScriptThing, const char *name,
void *aClosure);
};
class NS_COM_GLUE nsXPCOMCycleCollectionParticipant
: public nsScriptObjectTracer
class nsXPCOMCycleCollectionParticipant
: public nsScriptObjectTracer, public nsXPCOMCycleCollectionParticipantVTable
{
public:
nsXPCOMCycleCollectionParticipant()
: nsScriptObjectTracer(false) {}
nsXPCOMCycleCollectionParticipant(bool aSkip)
: nsScriptObjectTracer(aSkip) {}
static NS_METHOD TraverseImpl(nsXPCOMCycleCollectionParticipant *that,
void *p, nsCycleCollectionTraversalCallback &cb);
NS_IMETHOD Traverse(void *p, nsCycleCollectionTraversalCallback &cb);
static NS_METHOD RootImpl(void *p);
static NS_METHOD UnlinkImpl(void *p);
static NS_METHOD UnrootImpl(void *p);
NS_IMETHOD Root(void *p);
NS_IMETHOD Unlink(void *p);
NS_IMETHOD Unroot(void *p);
static NS_METHOD_(void) TraceImpl(void *p, TraceCallback cb, void *closure);
NS_IMETHOD_(void) Trace(void *p, TraceCallback cb, void *closure);
static NS_METHOD_(void) UnmarkIfPurpleImpl(nsISupports *p);
NS_IMETHOD_(void) UnmarkIfPurple(nsISupports *p);
bool CheckForRightISupports(nsISupports *s);
static bool CheckForRightISupports(nsISupports *s);
};
#undef IMETHOD_VISIBILITY
#define IMETHOD_VISIBILITY NS_VISIBILITY_HIDDEN
///////////////////////////////////////////////////////////////////////////////
// Helpers for implementing a QI to nsXPCOMCycleCollectionParticipant
///////////////////////////////////////////////////////////////////////////////
@ -213,12 +326,12 @@ public:
#define NS_CYCLE_COLLECTION_INNERNAME \
_cycleCollectorGlobal
#define NS_CYCLE_COLLECTION_NAME(_class) \
_class::NS_CYCLE_COLLECTION_INNERNAME
#define NS_CYCLE_COLLECTION_PARTICIPANT(_class) \
_class::NS_CYCLE_COLLECTION_INNERNAME.GetParticipant()
#define NS_IMPL_QUERY_CYCLE_COLLECTION(_class) \
if ( aIID.Equals(NS_GET_IID(nsXPCOMCycleCollectionParticipant)) ) { \
*aInstancePtr = & NS_CYCLE_COLLECTION_NAME(_class); \
*aInstancePtr = NS_CYCLE_COLLECTION_PARTICIPANT(_class); \
return NS_OK; \
} else
@ -257,7 +370,7 @@ public:
NS_PRECONDITION(aInstancePtr, "null out param"); \
\
if ( aIID.Equals(NS_GET_IID(nsXPCOMCycleCollectionParticipant)) ) { \
*aInstancePtr = &NS_CYCLE_COLLECTION_NAME(_class); \
*aInstancePtr = NS_CYCLE_COLLECTION_PARTICIPANT(_class); \
return NS_OK; \
} \
nsresult rv;
@ -270,8 +383,8 @@ public:
///////////////////////////////////////////////////////////////////////////////
#define NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN(_class) \
NS_IMETHODIMP_(bool) \
NS_CYCLE_COLLECTION_CLASSNAME(_class)::CanSkipReal(void *p, \
NS_METHOD_(bool) \
NS_CYCLE_COLLECTION_CLASSNAME(_class)::CanSkipImpl(void *p, \
bool aRemovingAllowed) \
{ \
nsISupports *s = static_cast<nsISupports*>(p); \
@ -285,8 +398,8 @@ public:
}
#define NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_BEGIN(_class) \
NS_IMETHODIMP_(bool) \
NS_CYCLE_COLLECTION_CLASSNAME(_class)::CanSkipInCCReal(void *p) \
NS_METHOD_(bool) \
NS_CYCLE_COLLECTION_CLASSNAME(_class)::CanSkipInCCImpl(void *p) \
{ \
nsISupports *s = static_cast<nsISupports*>(p); \
NS_ASSERTION(CheckForRightISupports(s), \
@ -299,8 +412,8 @@ public:
}
#define NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_BEGIN(_class) \
NS_IMETHODIMP_(bool) \
NS_CYCLE_COLLECTION_CLASSNAME(_class)::CanSkipThisReal(void *p) \
NS_METHOD_(bool) \
NS_CYCLE_COLLECTION_CLASSNAME(_class)::CanSkipThisImpl(void *p) \
{ \
nsISupports *s = static_cast<nsISupports*>(p); \
NS_ASSERTION(CheckForRightISupports(s), \
@ -317,8 +430,8 @@ public:
///////////////////////////////////////////////////////////////////////////////
#define NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(_class) \
NS_IMETHODIMP \
NS_CYCLE_COLLECTION_CLASSNAME(_class)::Unlink(void *p) \
NS_METHOD \
NS_CYCLE_COLLECTION_CLASSNAME(_class)::UnlinkImpl(void *p) \
{ \
nsISupports *s = static_cast<nsISupports*>(p); \
NS_ASSERTION(CheckForRightISupports(s), \
@ -326,18 +439,18 @@ public:
_class *tmp = Downcast(s);
#define NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(_class, _base_class) \
NS_IMETHODIMP \
NS_CYCLE_COLLECTION_CLASSNAME(_class)::Unlink(void *p) \
NS_METHOD \
NS_CYCLE_COLLECTION_CLASSNAME(_class)::UnlinkImpl(void *p) \
{ \
nsISupports *s = static_cast<nsISupports*>(p); \
NS_ASSERTION(CheckForRightISupports(s), \
"not the nsISupports pointer we expect"); \
_class *tmp = static_cast<_class*>(Downcast(s)); \
NS_CYCLE_COLLECTION_CLASSNAME(_base_class)::Unlink(s);
NS_CYCLE_COLLECTION_CLASSNAME(_base_class)::UnlinkImpl(s);
#define NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_NATIVE(_class) \
NS_IMETHODIMP \
NS_CYCLE_COLLECTION_CLASSNAME(_class)::Unlink(void *p) \
NS_METHOD \
NS_CYCLE_COLLECTION_CLASSNAME(_class)::UnlinkImpl(void *p) \
{ \
_class *tmp = static_cast<_class*>(p);
@ -356,8 +469,8 @@ public:
}
#define NS_IMPL_CYCLE_COLLECTION_UNLINK_0(_class) \
NS_IMETHODIMP \
NS_CYCLE_COLLECTION_CLASSNAME(_class)::Unlink(void *p) \
NS_METHOD \
NS_CYCLE_COLLECTION_CLASSNAME(_class)::UnlinkImpl(void *p) \
{ \
NS_ASSERTION(CheckForRightISupports(static_cast<nsISupports*>(p)), \
"not the nsISupports pointer we expect"); \
@ -365,8 +478,8 @@ public:
}
#define NS_IMPL_CYCLE_COLLECTION_UNLINK_NATIVE_0(_class) \
NS_IMETHODIMP \
NS_CYCLE_COLLECTION_CLASSNAME(_class)::Unlink(void *p) \
NS_METHOD \
NS_CYCLE_COLLECTION_CLASSNAME(_class)::UnlinkImpl(void *p) \
{ \
return NS_OK; \
}
@ -380,9 +493,9 @@ public:
cb.DescribeRefCountedNode(_refcnt, sizeof(_class), #_class);
#define NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(_class) \
NS_IMETHODIMP \
NS_CYCLE_COLLECTION_CLASSNAME(_class)::Traverse \
(void *p, \
NS_METHOD \
NS_CYCLE_COLLECTION_CLASSNAME(_class)::TraverseImpl \
(NS_CYCLE_COLLECTION_CLASSNAME(_class) *that, void *p,\
nsCycleCollectionTraversalCallback &cb) \
{ \
nsISupports *s = static_cast<nsISupports*>(p); \
@ -402,15 +515,15 @@ public:
#define NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(_class, _base_class) \
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(_class) \
if (NS_CYCLE_COLLECTION_CLASSNAME(_base_class)::Traverse(s, cb) == \
NS_SUCCESS_INTERRUPTED_TRAVERSE) { \
if (NS_CYCLE_COLLECTION_CLASSNAME(_base_class)::TraverseImpl(that, s, cb) \
== NS_SUCCESS_INTERRUPTED_TRAVERSE) { \
return NS_SUCCESS_INTERRUPTED_TRAVERSE; \
}
#define NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_BEGIN(_class) \
NS_IMETHODIMP \
NS_CYCLE_COLLECTION_CLASSNAME(_class)::Traverse \
(void *p, \
NS_METHOD \
NS_CYCLE_COLLECTION_CLASSNAME(_class)::TraverseImpl \
(NS_CYCLE_COLLECTION_CLASSNAME(_class) *that, void *p,\
nsCycleCollectionTraversalCallback &cb) \
{ \
_class *tmp = static_cast<_class*>(p); \
@ -453,7 +566,7 @@ public:
#define NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_PTR(_ptr, _ptr_class, _name) \
PR_BEGIN_MACRO \
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, _name); \
cb.NoteNativeChild(_ptr, &NS_CYCLE_COLLECTION_NAME(_ptr_class)); \
cb.NoteNativeChild(_ptr, NS_CYCLE_COLLECTION_PARTICIPANT(_ptr_class)); \
PR_END_MACRO;
#define NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_MEMBER(_field, _field_class) \
@ -485,7 +598,7 @@ public:
#_field)
#define NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS \
TraverseScriptObjects(p, cb);
that->Trace(p, &nsScriptObjectTracer::NoteJSChild, &cb);
#define NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END \
return NS_OK; \
@ -497,9 +610,9 @@ public:
#define NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(_class) \
void \
NS_CYCLE_COLLECTION_CLASSNAME(_class)::Trace(void *p, \
TraceCallback aCallback, \
void *aClosure) \
NS_CYCLE_COLLECTION_CLASSNAME(_class)::TraceImpl(void *p, \
TraceCallback aCallback, \
void *aClosure) \
{ \
nsISupports *s = static_cast<nsISupports*>(p); \
NS_ASSERTION(CheckForRightISupports(s), \
@ -508,23 +621,23 @@ public:
#define NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(_class, _base_class) \
void \
NS_CYCLE_COLLECTION_CLASSNAME(_class)::Trace(void *p, \
TraceCallback aCallback, \
void *aClosure) \
NS_CYCLE_COLLECTION_CLASSNAME(_class)::TraceImpl(void *p, \
TraceCallback aCallback, \
void *aClosure) \
{ \
nsISupports *s = static_cast<nsISupports*>(p); \
NS_ASSERTION(CheckForRightISupports(s), \
"not the nsISupports pointer we expect"); \
_class *tmp = static_cast<_class*>(Downcast(s)); \
NS_CYCLE_COLLECTION_CLASSNAME(_base_class)::Trace(s, \
aCallback, \
aClosure);
NS_CYCLE_COLLECTION_CLASSNAME(_base_class)::TraceImpl(s, \
aCallback, \
aClosure);
#define NS_IMPL_CYCLE_COLLECTION_TRACE_NATIVE_BEGIN(_class) \
void \
NS_CYCLE_COLLECTION_CLASSNAME(_class)::Trace(void *p, \
TraceCallback aCallback, \
void *aClosure) \
NS_CYCLE_COLLECTION_CLASSNAME(_class)::TraceImpl(void *p, \
TraceCallback aCallback, \
void *aClosure) \
{ \
_class *tmp = static_cast<_class*>(p);
@ -553,13 +666,14 @@ public:
///////////////////////////////////////////////////////////////////////////////
#define NS_CYCLE_COLLECTION_PARTICIPANT_INSTANCE \
static NS_CYCLE_COLLECTION_INNERCLASS NS_CYCLE_COLLECTION_INNERNAME;
static CCParticipantVTable<NS_CYCLE_COLLECTION_INNERCLASS>::Type \
NS_CYCLE_COLLECTION_INNERNAME;
#define NS_DECL_CYCLE_COLLECTION_CLASS_BODY_NO_UNLINK(_class, _base) \
public: \
NS_IMETHOD Traverse(void *p, \
nsCycleCollectionTraversalCallback &cb); \
NS_IMETHOD_(void) UnmarkIfPurple(nsISupports *s) \
static NS_METHOD TraverseImpl(NS_CYCLE_COLLECTION_CLASSNAME(_class) *that, \
void *p, nsCycleCollectionTraversalCallback &cb); \
static NS_METHOD_(void) UnmarkIfPurpleImpl(nsISupports *s) \
{ \
Downcast(s)->UnmarkIfPurple(); \
} \
@ -574,7 +688,7 @@ public: \
#define NS_DECL_CYCLE_COLLECTION_CLASS_BODY(_class, _base) \
NS_DECL_CYCLE_COLLECTION_CLASS_BODY_NO_UNLINK(_class, _base) \
NS_IMETHOD Unlink(void *p);
static NS_METHOD UnlinkImpl(void *p);
#define NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(_class, _base) \
class NS_CYCLE_COLLECTION_INNERCLASS \
@ -592,13 +706,11 @@ NS_CYCLE_COLLECTION_PARTICIPANT_INSTANCE
class NS_CYCLE_COLLECTION_INNERCLASS \
: public nsXPCOMCycleCollectionParticipant \
{ \
public: \
NS_CYCLE_COLLECTION_INNERCLASS () : nsXPCOMCycleCollectionParticipant(true) {} \
NS_DECL_CYCLE_COLLECTION_CLASS_BODY(_class, _base) \
protected: \
NS_IMETHOD_(bool) CanSkipReal(void *p, bool aRemovingAllowed); \
NS_IMETHOD_(bool) CanSkipInCCReal(void *p); \
NS_IMETHOD_(bool) CanSkipThisReal(void *p); \
static const bool isSkippable = true; \
static NS_METHOD_(bool) CanSkipImpl(void *p, bool aRemovingAllowed); \
static NS_METHOD_(bool) CanSkipInCCImpl(void *p); \
static NS_METHOD_(bool) CanSkipThisImpl(void *p); \
}; \
NS_CYCLE_COLLECTION_PARTICIPANT_INSTANCE
@ -613,15 +725,15 @@ class NS_CYCLE_COLLECTION_INNERCLASS \
: public nsXPCOMCycleCollectionParticipant \
{ \
NS_DECL_CYCLE_COLLECTION_CLASS_BODY_NO_UNLINK(_class, _class) \
NS_IMETHOD Root(void *p) \
static NS_METHOD RootImpl(void *p) \
{ \
return NS_OK; \
} \
NS_IMETHOD Unlink(void *p) \
static NS_METHOD UnlinkImpl(void *p) \
{ \
return NS_OK; \
} \
NS_IMETHOD Unroot(void *p) \
static NS_METHOD UnrootImpl(void *p) \
{ \
return NS_OK; \
} \
@ -633,7 +745,7 @@ class NS_CYCLE_COLLECTION_INNERCLASS \
: public nsXPCOMCycleCollectionParticipant \
{ \
NS_DECL_CYCLE_COLLECTION_CLASS_BODY(_class, _base) \
NS_IMETHOD_(void) Trace(void *p, TraceCallback cb, void *closure); \
static NS_METHOD_(void) TraceImpl(void *p, TraceCallback cb, void *closure); \
}; \
NS_CYCLE_COLLECTION_PARTICIPANT_INSTANCE
@ -641,14 +753,12 @@ NS_CYCLE_COLLECTION_PARTICIPANT_INSTANCE
class NS_CYCLE_COLLECTION_INNERCLASS \
: public nsXPCOMCycleCollectionParticipant \
{ \
public: \
NS_CYCLE_COLLECTION_INNERCLASS () : nsXPCOMCycleCollectionParticipant(true) {} \
NS_DECL_CYCLE_COLLECTION_CLASS_BODY(_class, _base) \
NS_IMETHOD_(void) Trace(void *p, TraceCallback cb, void *closure); \
protected: \
NS_IMETHOD_(bool) CanSkipReal(void *p, bool aRemovingAllowed); \
NS_IMETHOD_(bool) CanSkipInCCReal(void *p); \
NS_IMETHOD_(bool) CanSkipThisReal(void *p); \
static const bool isSkippable = true; \
static NS_METHOD_(void) TraceImpl(void *p, TraceCallback cb, void *closure); \
static NS_METHOD_(bool) CanSkipImpl(void *p, bool aRemovingAllowed); \
static NS_METHOD_(bool) CanSkipInCCImpl(void *p); \
static NS_METHOD_(bool) CanSkipThisImpl(void *p); \
}; \
NS_CYCLE_COLLECTION_PARTICIPANT_INSTANCE
@ -660,18 +770,12 @@ NS_CYCLE_COLLECTION_PARTICIPANT_INSTANCE
class NS_CYCLE_COLLECTION_INNERCLASS \
: public NS_CYCLE_COLLECTION_CLASSNAME(_base_class) \
{ \
public: \
NS_CYCLE_COLLECTION_INNERCLASS () \
: NS_CYCLE_COLLECTION_CLASSNAME(_base_class)() \
{ \
mMightSkip = true; \
} \
NS_IMETHOD_(void) Trace(void *p, TraceCallback cb, void *closure); \
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_BODY(_class, _base_class) \
protected: \
NS_IMETHOD_(bool) CanSkipReal(void *p, bool aRemovingAllowed); \
NS_IMETHOD_(bool) CanSkipInCCReal(void *p); \
NS_IMETHOD_(bool) CanSkipThisReal(void *p); \
static const bool isSkippable = true; \
static NS_METHOD_(void) TraceImpl(void *p, TraceCallback cb, void *closure); \
static NS_METHOD_(bool) CanSkipImpl(void *p, bool aRemovingAllowed); \
static NS_METHOD_(bool) CanSkipInCCImpl(void *p); \
static NS_METHOD_(bool) CanSkipThisImpl(void *p); \
}; \
NS_CYCLE_COLLECTION_PARTICIPANT_INSTANCE
@ -681,8 +785,8 @@ NS_CYCLE_COLLECTION_PARTICIPANT_INSTANCE
#define NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_BODY_NO_UNLINK(_class, \
_base_class) \
public: \
NS_IMETHOD Traverse(void *p, \
nsCycleCollectionTraversalCallback &cb); \
static NS_METHOD TraverseImpl(NS_CYCLE_COLLECTION_CLASSNAME(_class) *that, \
void *p, nsCycleCollectionTraversalCallback &cb); \
static _class* Downcast(nsISupports* s) \
{ \
return static_cast<_class*>(static_cast<_base_class*>( \
@ -691,7 +795,7 @@ public: \
#define NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_BODY(_class, _base_class) \
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_BODY_NO_UNLINK(_class, _base_class) \
NS_IMETHOD Unlink(void *p);
static NS_METHOD UnlinkImpl(void *p);
#define NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(_class, _base_class) \
class NS_CYCLE_COLLECTION_INNERCLASS \
@ -717,9 +821,8 @@ NS_CYCLE_COLLECTION_PARTICIPANT_INSTANCE
class NS_CYCLE_COLLECTION_INNERCLASS \
: public NS_CYCLE_COLLECTION_CLASSNAME(_base_class) \
{ \
public: \
NS_IMETHOD_(void) Trace(void *p, TraceCallback cb, void *closure); \
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_BODY(_class, _base_class) \
static NS_METHOD_(void) TraceImpl(void *p, TraceCallback cb, void *closure); \
}; \
NS_CYCLE_COLLECTION_PARTICIPANT_INSTANCE
@ -734,22 +837,75 @@ NS_CYCLE_COLLECTION_PARTICIPANT_INSTANCE
{ \
} \
#define NS_IMPL_CYCLE_COLLECTION_CLASS(_class) \
NS_CYCLE_COLLECTION_CLASSNAME(_class) NS_CYCLE_COLLECTION_NAME(_class);
/**
* Dummy class with a definition for CanSkip* function members, but no
* implementation.
*/
struct SkippableDummy
{
static NS_METHOD_(bool) CanSkipImpl(void *p, bool aRemovingAllowed);
static NS_METHOD_(bool) CanSkipInCCImpl(void *p);
static NS_METHOD_(bool) CanSkipThisImpl(void *p);
};
#define NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS_BODY \
/**
* Skippable<T> defines a class that always has definitions for CanSkip*
* function members, so that T::isSkippable ? &Skippable<T>::CanSkip* : NULL
* can compile when T::isSkippable is false and T doesn't have CanSkip*
* definitions (which, as not being skippable, it's not supposed to have).
*/
template <class T>
struct Skippable
: public mozilla::Conditional<T::isSkippable, T, SkippableDummy>::Type
{ };
#define NS_IMPL_CYCLE_COLLECTION_NATIVE_VTABLE(_class) \
{ \
&_class::TraverseImpl, \
&_class::RootImpl, \
&_class::UnlinkImpl, \
&_class::UnrootImpl, \
_class::isSkippable ? &Skippable<_class>::CanSkipImpl : NULL, \
_class::isSkippable ? &Skippable<_class>::CanSkipInCCImpl : NULL, \
_class::isSkippable ? &Skippable<_class>::CanSkipThisImpl : NULL \
}
#define NS_IMPL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_VTABLE(_class) \
NS_IMPL_CYCLE_COLLECTION_NATIVE_VTABLE(_class), \
{ &_class::TraceImpl }
#define NS_IMPL_CYCLE_COLLECTION_VTABLE(_class) \
NS_IMPL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_VTABLE(_class), \
{ &_class::UnmarkIfPurpleImpl }
#define NS_IMPL_CYCLE_COLLECTION_NATIVE_CLASS(_class) \
CCParticipantVTable<NS_CYCLE_COLLECTION_CLASSNAME(_class)> \
::Type _class::NS_CYCLE_COLLECTION_INNERNAME = \
{ NS_IMPL_CYCLE_COLLECTION_NATIVE_VTABLE(NS_CYCLE_COLLECTION_CLASSNAME(_class)) };
#define NS_IMPL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(_class) \
CCParticipantVTable<NS_CYCLE_COLLECTION_CLASSNAME(_class)> \
::Type _class::NS_CYCLE_COLLECTION_INNERNAME = \
{ NS_IMPL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_VTABLE(NS_CYCLE_COLLECTION_CLASSNAME(_class)) };
#define NS_IMPL_CYCLE_COLLECTION_CLASS(_class) \
CCParticipantVTable<NS_CYCLE_COLLECTION_CLASSNAME(_class)> \
::Type _class::NS_CYCLE_COLLECTION_INNERNAME = \
{ NS_IMPL_CYCLE_COLLECTION_VTABLE(NS_CYCLE_COLLECTION_CLASSNAME(_class)) };
#define NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS_BODY(_class) \
public: \
NS_IMETHOD Root(void *n); \
NS_IMETHOD Unlink(void *n); \
NS_IMETHOD Unroot(void *n); \
NS_IMETHOD Traverse(void *n, \
nsCycleCollectionTraversalCallback &cb);
static NS_METHOD RootImpl(void *n); \
static NS_METHOD UnlinkImpl(void *n); \
static NS_METHOD UnrootImpl(void *n); \
static NS_METHOD TraverseImpl(NS_CYCLE_COLLECTION_CLASSNAME(_class) *that, \
void *n, nsCycleCollectionTraversalCallback &cb);
#define NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(_class) \
class NS_CYCLE_COLLECTION_INNERCLASS \
: public nsCycleCollectionParticipant \
{ \
NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS_BODY \
NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS_BODY(_class) \
}; \
NS_CYCLE_COLLECTION_PARTICIPANT_INSTANCE
@ -757,14 +913,15 @@ NS_CYCLE_COLLECTION_PARTICIPANT_INSTANCE
class NS_CYCLE_COLLECTION_INNERCLASS \
: public nsScriptObjectTracer \
{ \
NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS_BODY \
NS_IMETHOD_(void) Trace(void *p, TraceCallback cb, void *closure); \
NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS_BODY(_class) \
static NS_METHOD_(void) TraceImpl(void *p, TraceCallback cb, \
void *closure); \
}; \
NS_CYCLE_COLLECTION_PARTICIPANT_INSTANCE
#define NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(_class, _root_function) \
NS_IMETHODIMP \
NS_CYCLE_COLLECTION_CLASSNAME(_class)::Root(void *p) \
NS_METHOD \
NS_CYCLE_COLLECTION_CLASSNAME(_class)::RootImpl(void *p) \
{ \
_class *tmp = static_cast<_class*>(p); \
tmp->_root_function(); \
@ -772,8 +929,8 @@ NS_CYCLE_COLLECTION_PARTICIPANT_INSTANCE
}
#define NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(_class, _unroot_function) \
NS_IMETHODIMP \
NS_CYCLE_COLLECTION_CLASSNAME(_class)::Unroot(void *p) \
NS_METHOD \
NS_CYCLE_COLLECTION_CLASSNAME(_class)::UnrootImpl(void *p) \
{ \
_class *tmp = static_cast<_class*>(p); \
tmp->_unroot_function(); \