author | Mike Hommey <mh+mozilla@glandium.org> |
Mon, 04 Jun 2012 08:30:26 +0200 | |
changeset 97117 | 83369c1bb9af922f6de3ad2cfebc8df50959a5ab |
parent 97116 | 04c7d09b664fd64d45a00e9b0d08e890af86804a |
child 97118 | c3190d71504491cc6010205e31278e7ae6906e13 |
push id | 10881 |
push user | emorley@mozilla.com |
push date | Wed, 20 Jun 2012 10:04:03 +0000 |
treeherder | mozilla-inbound@0aa408fd0505 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | smaug, mccr8, Waldo |
bugs | 616262 |
milestone | 16.0a1 |
first release with | nightly linux32
83369c1bb9af
/
16.0a1
/
20120620030535
/
files
nightly linux64
83369c1bb9af
/
16.0a1
/
20120620030535
/
files
nightly mac
83369c1bb9af
/
16.0a1
/
20120620030535
/
files
nightly win32
83369c1bb9af
/
16.0a1
/
20120620030535
/
files
nightly win64
83369c1bb9af
/
16.0a1
/
20120620030535
/
files
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
releases | nightly linux32
16.0a1
/
20120620030535
/
pushlog to previous
nightly linux64
16.0a1
/
20120620030535
/
pushlog to previous
nightly mac
16.0a1
/
20120620030535
/
pushlog to previous
nightly win32
16.0a1
/
20120620030535
/
pushlog to previous
nightly win64
16.0a1
/
20120620030535
/
pushlog to previous
|
--- a/accessible/src/base/AccEvent.cpp +++ b/accessible/src/base/AccEvent.cpp @@ -83,17 +83,17 @@ AccEvent::CreateXPCOMObject() nsAccEvent* event = new nsAccEvent(this); NS_IF_ADDREF(event); return event; } //////////////////////////////////////////////////////////////////////////////// // 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) NS_IMPL_CYCLE_COLLECTION_UNLINK_END NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_BEGIN(AccEvent) NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mAccessible"); cb.NoteXPCOMChild(static_cast<nsIAccessible*>(tmp->mAccessible));
--- a/accessible/src/base/NotificationController.cpp +++ b/accessible/src/base/NotificationController.cpp @@ -51,17 +51,17 @@ NotificationController::~NotificationCon } //////////////////////////////////////////////////////////////////////////////// // NotificationCollector: AddRef/Release and cycle collection 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) tmp->Shutdown(); NS_IMPL_CYCLE_COLLECTION_UNLINK_END NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_BEGIN(NotificationController) NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mDocument"); @@ -807,17 +807,17 @@ NotificationController::ContentInsertion } node = node->GetNextSibling(); } 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) NS_IMPL_CYCLE_COLLECTION_UNLINK_END NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_BEGIN(NotificationController::ContentInsertion) NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mContainer"); cb.NoteXPCOMChild(static_cast<nsIAccessible*>(tmp->mContainer.get()));
--- a/accessible/src/generic/Accessible.cpp +++ b/accessible/src/generic/Accessible.cpp @@ -106,17 +106,17 @@ NS_IMPL_RELEASE_INHERITED(Accessible, ns nsresult Accessible::QueryInterface(REFNSIID aIID, void** aInstancePtr) { // Custom-built QueryInterface() knows when we support nsIAccessibleSelectable // based on role attribute and aria-multiselectable *aInstancePtr = nsnull; if (aIID.Equals(NS_GET_IID(nsXPCOMCycleCollectionParticipant))) { - *aInstancePtr = &NS_CYCLE_COLLECTION_NAME(Accessible); + *aInstancePtr = NS_CYCLE_COLLECTION_PARTICIPANT(Accessible); return NS_OK; } if (aIID.Equals(NS_GET_IID(nsIAccessible))) { *aInstancePtr = static_cast<nsIAccessible*>(this); NS_ADDREF_THIS(); return NS_OK; }
--- a/content/base/public/nsContentUtils.h +++ b/content/base/public/nsContentUtils.h @@ -2153,17 +2153,17 @@ private: static nsString* sModifierSeparator; }; typedef nsCharSeparatedTokenizerTemplate<nsContentUtils::IsHTMLWhitespace> HTMLSplitOnSpacesTokenizer; #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)) class NS_STACK_CLASS nsCxPusher { public:
--- a/content/base/src/nsNodeInfoManager.cpp +++ b/content/base/src/nsNodeInfoManager.cpp @@ -125,17 +125,17 @@ nsNodeInfoManager::~nsNodeInfoManager() PR_LOG(gNodeInfoManagerLeakPRLog, PR_LOG_DEBUG, ("NODEINFOMANAGER %p destroyed", this)); #endif nsLayoutStatics::Release(); } -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) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_BEGIN(nsNodeInfoManager) if (tmp->mDocument && nsCCUncollectableMarker::InGeneration(cb, tmp->mDocument->GetMarkedCCGeneration())) { return NS_SUCCESS_INTERRUPTED_TRAVERSE;
--- a/content/events/src/nsEventListenerManager.cpp +++ b/content/events/src/nsEventListenerManager.cpp @@ -140,17 +140,17 @@ nsEventListenerManager::RemoveAllListene } void 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) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_BEGIN(nsEventListenerManager) PRUint32 count = tmp->mListeners.Length(); for (PRUint32 i = 0; i < count; i++) { NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mListeners[i] mListener");
--- a/content/xbl/src/nsXBLBinding.cpp +++ b/content/xbl/src/nsXBLBinding.cpp @@ -252,17 +252,17 @@ TraverseKey(nsISupports* aKey, nsInserti cb.NoteXPCOMChild(aKey); if (aData) { NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSTARRAY(*aData, nsXBLInsertionPoint, "mInsertionPointTable value") } 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. if (tmp->mContent) { nsXBLBinding::UninstallAnonymousContent(tmp->mContent->OwnerDoc(), tmp->mContent); } NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mContent)
--- a/content/xbl/src/nsXBLInsertionPoint.cpp +++ b/content/xbl/src/nsXBLInsertionPoint.cpp @@ -19,17 +19,17 @@ nsXBLInsertionPoint::nsXBLInsertionPoint nsXBLInsertionPoint::~nsXBLInsertionPoint() { if (mDefaultContent) { nsXBLBinding::UninstallAnonymousContent(mDefaultContent->OwnerDoc(), mDefaultContent); } } -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) if (tmp->mDefaultContent) { nsXBLBinding::UninstallAnonymousContent(tmp->mDefaultContent->OwnerDoc(), tmp->mDefaultContent); } NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mDefaultContent)
--- a/content/xbl/src/nsXBLPrototypeBinding.cpp +++ b/content/xbl/src/nsXBLPrototypeBinding.cpp @@ -222,17 +222,17 @@ private: static nsFixedSizeAllocator* kPool; static PRUint32 gRefCnt; }; 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) { nsAutoScriptBlocker scriptBlocker; // mDefaultContent is a sort of anonymous content within the XBL // document, and we own and manage it. Unhook it here, since we're going // away. tmp->mDefaultContent->UnbindFromTree();
--- a/content/xul/content/src/nsXULElement.cpp +++ b/content/xul/content/src/nsXULElement.cpp @@ -750,17 +750,17 @@ nsScriptEventHandlerOwnerTearoff::Compil if (attr) { XUL_PROTOTYPE_ATTRIBUTE_METER(gNumCacheFills); // take a copy of the event handler, and tell the language about it. if (aHandler) { NS_ASSERTION(!attr->mEventHandler, "Leaking handler."); if (!elem->mHoldsScriptObject) { rv = nsContentUtils::HoldJSObjects( - elem, &NS_CYCLE_COLLECTION_NAME(nsXULPrototypeNode)); + elem, NS_CYCLE_COLLECTION_PARTICIPANT(nsXULPrototypeNode)); NS_ENSURE_SUCCESS(rv, rv); } elem->mHoldsScriptObject = true; } attr->mEventHandler = aHandler.get(); } @@ -3093,17 +3093,17 @@ nsXULPrototypeScript::Set(JSScript* aObj { NS_ASSERTION(!mScriptObject.mObject, "Leaking script object."); if (!aObject) { mScriptObject.mObject = nsnull; return; } nsresult rv = nsContentUtils::HoldJSObjects( - this, &NS_CYCLE_COLLECTION_NAME(nsXULPrototypeNode)); + this, NS_CYCLE_COLLECTION_PARTICIPANT(nsXULPrototypeNode)); if (NS_SUCCEEDED(rv)) { mScriptObject.mObject = aObject; } } //---------------------------------------------------------------------- // // nsXULPrototypeText
--- a/content/xul/templates/src/nsXMLBinding.cpp +++ b/content/xul/templates/src/nsXMLBinding.cpp @@ -5,17 +5,17 @@ #include "nsXULTemplateQueryProcessorXML.h" #include "nsXULTemplateResultXML.h" #include "nsXMLBinding.h" 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; while (binding) { binding->mExpr = nsnull; binding = binding->mNext; } NS_IMPL_CYCLE_COLLECTION_UNLINK_END
--- a/content/xul/templates/src/nsXULTemplateQueryProcessorXML.cpp +++ b/content/xul/templates/src/nsXULTemplateQueryProcessorXML.cpp @@ -80,17 +80,17 @@ nsXULTemplateResultSetXML::GetNext(nsISu static PLDHashOperator TraverseRuleToBindingsMap(nsISupports* aKey, nsXMLBindingSet* aMatch, void* aContext) { nsCycleCollectionTraversalCallback *cb = static_cast<nsCycleCollectionTraversalCallback*>(aContext); 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; } NS_IMPL_CYCLE_COLLECTION_CLASS(nsXULTemplateQueryProcessorXML) NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsXULTemplateQueryProcessorXML) if (tmp->mRuleToBindingsMap.IsInitialized()) { tmp->mRuleToBindingsMap.Clear(); }
--- a/dom/base/nsGlobalWindow.cpp +++ b/dom/base/nsGlobalWindow.cpp @@ -535,17 +535,17 @@ nsTimeout::~nsTimeout() --gTimeoutCnt; } #endif 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, nsIScriptGlobalObject) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mPrincipal) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mScriptHandler) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(nsTimeout, AddRef) @@ -1222,17 +1222,17 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN( NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mOpenerScriptPrincipal) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_MEMBER(mListenerManager, nsEventListenerManager) 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) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mSessionStorage) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mApplicationCache) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mDocumentPrincipal) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mDoc)
--- a/editor/txmgr/src/nsTransactionItem.cpp +++ b/editor/txmgr/src/nsTransactionItem.cpp @@ -38,17 +38,17 @@ nsTransactionItem::Release() { if (mRefCnt == 0) { mRefCnt = 1; delete this; return 0; } 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) if (tmp->mRedoStack) { tmp->mRedoStack->DoUnlink(); } if (tmp->mUndoStack) { tmp->mUndoStack->DoUnlink();
--- a/editor/txmgr/src/nsTransactionStack.cpp +++ b/editor/txmgr/src/nsTransactionStack.cpp @@ -90,12 +90,12 @@ nsTransactionStack::Clear() void nsTransactionStack::DoTraverse(nsCycleCollectionTraversalCallback &cb) { for (PRInt32 i = 0, qcount = mQue.GetSize(); i < qcount; ++i) { nsTransactionItem *item = 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)); } } }
--- a/js/xpconnect/src/XPCWrappedJS.cpp +++ b/js/xpconnect/src/XPCWrappedJS.cpp @@ -12,18 +12,19 @@ #include "nsThreadUtils.h" #include "nsTextFormatter.h" // NOTE: much of the fancy footwork is done in xpcstubs.cpp 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), "not the nsISupports pointer we expect"); nsXPCWrappedJS *tmp = Downcast(s); nsrefcnt refcnt = tmp->mRefCnt.get(); if (cb.WantDebugInfo()) { @@ -93,17 +94,17 @@ NS_IMETHODIMP nsXPCWrappedJS::QueryInterface(REFNSIID aIID, void** aInstancePtr) { if (nsnull == aInstancePtr) { NS_PRECONDITION(0, "null pointer"); return NS_ERROR_NULL_POINTER; } if ( aIID.Equals(NS_GET_IID(nsXPCOMCycleCollectionParticipant)) ) { - *aInstancePtr = & NS_CYCLE_COLLECTION_NAME(nsXPCWrappedJS); + *aInstancePtr = NS_CYCLE_COLLECTION_PARTICIPANT(nsXPCWrappedJS); return NS_OK; } if (aIID.Equals(NS_GET_IID(nsCycleCollectionISupports))) { *aInstancePtr = NS_CYCLE_COLLECTION_CLASSNAME(nsXPCWrappedJS)::Upcast(this); return NS_OK; }
--- a/js/xpconnect/src/XPCWrappedNative.cpp +++ b/js/xpconnect/src/XPCWrappedNative.cpp @@ -39,26 +39,27 @@ xpc_OkToHandOutWrapper(nsWrapperCache *c NeedsSOW(); } /***************************************************************************/ 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(); return NS_OK; } 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()) return NS_OK; if (NS_UNLIKELY(cb.WantDebugInfo())) { char name[72]; XPCNativeScriptableInfo* si = tmp->GetScriptableInfo();
--- a/js/xpconnect/src/nsXPConnect.cpp +++ b/js/xpconnect/src/nsXPConnect.cpp @@ -538,38 +538,43 @@ nsXPConnect::NotifyEnterMainThread() nsresult nsXPConnect::FinishTraverse() { if (mCycleCollectionContext) mCycleCollectionContext = nsnull; 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 xpc_GCThingIsGrayCCThing(void *thing) { return AddToCCKind(js_GetGCThingTraceKind(thing)) && xpc_IsGrayGCThing(thing); } @@ -751,18 +756,19 @@ WrapperIsNotMainThreadOnly(XPCWrappedNat // If the native participates in cycle collection then we know it can only // be used on the main thread, in that case we assume the wrapped native // can only be used on the main thread too. nsXPCOMCycleCollectionParticipant* participant; 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; js::Class *clazz = nsnull; // We do not want to add wrappers to the cycle collector if they're not // explicitly marked as main thread only, because the cycle collector isn't // able to deal with objects that might be used off of the main thread. We @@ -838,17 +844,17 @@ nsXPConnect::Traverse(void *p, nsCycleCo // GC. Any JS objects hanging from them will already be marked. Only do this // if cb.WantAllTraces() is false, otherwise we do want to know about all JS // objects to get better graphs and explanations. if (!cb.WantAllTraces() && isMarked) return NS_OK; TraversalTracer trc(cb); - JS_TracerInit(&trc, GetRuntime()->GetJSRuntime(), NoteJSChild); + JS_TracerInit(&trc, nsXPConnect::GetRuntimeInstance()->GetJSRuntime(), NoteJSChild); trc.eagerlyTraceWeakMaps = false; JS_TraceChildren(&trc, p, traceKind); if (traceKind != JSTRACE_OBJECT || dontTraverse) return NS_OK; if (clazz == &XPC_WN_Tearoff_JSClass) { // A tearoff holds a strong reference to its native object @@ -892,33 +898,34 @@ nsXPConnect::GetOutstandingRequests(JSCo --n; } return n; } 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); NS_ASSERTION(JS_GetGlobalObject(cx), "global object NULL before unlinking"); 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); // Add outstandingRequests to the count, if there are outstanding // requests the context needs to be kept alive and adding unknown // edges will ensure that any cycles this context is in won't be // collected. unsigned refCount = nsXPConnect::GetXPConnect()->GetOutstandingRequests(cx) + 1; @@ -927,30 +934,32 @@ public: NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "[global object]"); cb.NoteJSChild(global); } return NS_OK; } }; -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()); } /***************************************************************************/ /***************************************************************************/ // nsIXPConnect interface methods... inline nsresult UnexpectedFailure(nsresult rv)
--- a/js/xpconnect/src/xpcprivate.h +++ b/js/xpconnect/src/xpcprivate.h @@ -473,17 +473,16 @@ AddToCCKind(JSGCTraceKind kind) { return kind == JSTRACE_OBJECT || kind == JSTRACE_XML || kind == JSTRACE_SCRIPT; } class nsXPConnect : public nsIXPConnect, public nsIThreadObserver, public nsSupportsWeakReference, public nsCycleCollectionJSRuntime, - public nsCycleCollectionParticipant, public nsIJSRuntimeService, public nsIThreadJSContextStack, public nsIJSEngineTelemetryStats { public: // all the interface method declarations... NS_DECL_ISUPPORTS NS_DECL_NSIXPCONNECT @@ -534,23 +533,16 @@ public: JSBool IsShuttingDown() const {return mShuttingDown;} void EnsureGCBeforeCC() { mNeedGCBeforeCC = true; } void ClearGCBeforeCC() { mNeedGCBeforeCC = false; } 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(); virtual void NotifyLeaveCycleCollectionThread(); virtual void NotifyEnterMainThread(); virtual nsresult BeginCycleCollection(nsCycleCollectionTraversalCallback &cb); virtual nsresult FinishTraverse(); virtual nsCycleCollectionParticipant *GetParticipant(); @@ -2550,19 +2542,19 @@ public: // root/unrooting the JS objects from addrefing/releasing the // XPCWrappedNative during unlinking, which would make the JS objects // uncollectable to the JS GC. class NS_CYCLE_COLLECTION_INNERCLASS : public nsXPCOMCycleCollectionParticipant { 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) nsIPrincipal* GetObjectPrincipal() const; JSBool IsValid() const {return nsnull != mFlatJSObject;}
--- a/xpcom/base/nsAgg.h +++ b/xpcom/base/nsAgg.h @@ -67,20 +67,21 @@ private: \ public: \ #define NS_DECL_AGGREGATED_CYCLE_COLLECTION_CLASS(_class) \ 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(); \ } \ static _class* Downcast(nsISupports* s) \ { \ return (_class*)((char*)(s) - offsetof(_class, fAggregated)); \ } \ static nsISupports* Upcast(_class *p) \ @@ -258,24 +259,24 @@ nsresult if ( aIID.Equals(NS_GET_IID(nsISupports)) ) \ foundInterface = InnerObject(); \ else #define NS_IMPL_AGGREGATED_QUERY_CYCLE_COLLECTION(_class) \ 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), \ "not the nsISupports pointer we expect"); \ _class *tmp = static_cast<_class*>(Downcast(s)); \ if (!tmp->IsPartOfAggregated()) \ NS_IMPL_CYCLE_COLLECTION_DESCRIBE(_class, tmp->mRefCnt.get())
--- a/xpcom/glue/nsCycleCollectionParticipant.cpp +++ b/xpcom/glue/nsCycleCollectionParticipant.cpp @@ -1,69 +1,64 @@ /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #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); NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(*cb, name); 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); return NS_OK; } 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); return NS_OK; } 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) { } bool nsXPCOMCycleCollectionParticipant::CheckForRightISupports(nsISupports *s) { nsISupports* foo; s->QueryInterface(NS_GET_IID(nsCycleCollectionISupports),
--- a/xpcom/glue/nsCycleCollectionParticipant.h +++ b/xpcom/glue/nsCycleCollectionParticipant.h @@ -1,16 +1,17 @@ /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef nsCycleCollectionParticipant_h__ #define nsCycleCollectionParticipant_h__ +#include "mozilla/TypeTraits.h" #include "nsISupports.h" #define NS_CYCLECOLLECTIONPARTICIPANT_IID \ { \ 0x9674489b, \ 0x1f6f, \ 0x4550, \ { 0xa7, 0x30, 0xcc, 0xae, 0xdd, 0x10, 0x4c, 0xf9 } \ @@ -38,17 +39,28 @@ class nsCycleCollectionISupports { public: NS_DECLARE_STATIC_IID_ACCESSOR(NS_CYCLECOLLECTIONISUPPORTS_IID) }; 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 { public: // You must call DescribeRefCountedNode() with an accurate // refcount, otherwise cycle collection will fail, and probably crash. // If the callback cares about objsz or objname, it should // put WANT_DEBUG_INFO in mFlags. @@ -92,138 +104,239 @@ public: bool WantDebugInfo() const { return (mFlags & WANT_DEBUG_INFO) != 0; } bool WantAllTraces() const { return (mFlags & WANT_ALL_TRACES) != 0; } protected: nsCycleCollectionTraversalCallback() : mFlags(0) {} 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 // cycle collector graph. // 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. // This method is called during cycle collection, so don't // change the state of any objects! bool CanSkipThis(void *p) { - return mMightSkip ? CanSkipThisReal(p) : false; - } -protected: - NS_IMETHOD_(bool) CanSkipReal(void *p, bool aRemovingAllowed) - { - NS_ASSERTION(false, "Forgot to implement CanSkipReal?"); - return false; + return CanSkipThisReal ? CanSkipThisReal(p) : 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); - - NS_IMETHOD_(void) Trace(void *p, TraceCallback cb, void *closure); + static NS_METHOD_(void) TraceImpl(void *p, TraceCallback cb, void *closure); - NS_IMETHOD_(void) UnmarkIfPurple(nsISupports *p); + static NS_METHOD_(void) UnmarkIfPurpleImpl(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 /////////////////////////////////////////////////////////////////////////////// #define NS_CYCLE_COLLECTION_INNERCLASS \ cycleCollection #define NS_CYCLE_COLLECTION_CLASSNAME(_class) \ _class::NS_CYCLE_COLLECTION_INNERCLASS #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 #define NS_IMPL_QUERY_CYCLE_COLLECTION_ISUPPORTS(_class) \ if ( aIID.Equals(NS_GET_IID(nsCycleCollectionISupports)) ) { \ *aInstancePtr = NS_CYCLE_COLLECTION_CLASSNAME(_class)::Upcast(this); \ return NS_OK; \ } else @@ -252,97 +365,97 @@ public: NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(_class) #define NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(_class) \ NS_IMETHODIMP _class::QueryInterface(REFNSIID aIID, void** aInstancePtr) \ { \ 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; #define NS_CYCLE_COLLECTION_UPCAST(obj, clazz) \ NS_CYCLE_COLLECTION_CLASSNAME(clazz)::Upcast(obj) /////////////////////////////////////////////////////////////////////////////// // Helpers for implementing CanSkip methods /////////////////////////////////////////////////////////////////////////////// #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); \ NS_ASSERTION(CheckForRightISupports(s), \ "not the nsISupports pointer we expect"); \ _class *tmp = Downcast(s); #define NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_END \ (void)tmp; \ return false; \ } #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), \ "not the nsISupports pointer we expect"); \ _class *tmp = Downcast(s); #define NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_END \ (void)tmp; \ return false; \ } #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), \ "not the nsISupports pointer we expect"); \ _class *tmp = Downcast(s); #define NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_END \ (void)tmp; \ return false; \ } /////////////////////////////////////////////////////////////////////////////// // Helpers for implementing nsCycleCollectionParticipant::Unlink /////////////////////////////////////////////////////////////////////////////// #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), \ "not the nsISupports pointer we expect"); \ _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); #define NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(_field) \ tmp->_field = NULL; #define NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMARRAY(_field) \ tmp->_field.Clear(); @@ -351,43 +464,43 @@ public: tmp->_field.Clear(); #define NS_IMPL_CYCLE_COLLECTION_UNLINK_END \ (void)tmp; \ return NS_OK; \ } #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"); \ return NS_OK; \ } #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; \ } /////////////////////////////////////////////////////////////////////////////// // Helpers for implementing nsCycleCollectionParticipant::Traverse /////////////////////////////////////////////////////////////////////////////// #define NS_IMPL_CYCLE_COLLECTION_DESCRIBE(_class, _refcnt) \ 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); \ NS_ASSERTION(CheckForRightISupports(s), \ "not the nsISupports pointer we expect"); \ _class *tmp = static_cast<_class*>(Downcast(s)); #define NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(_class) \ @@ -397,25 +510,25 @@ public: // Base class' CC participant should return NS_SUCCESS_INTERRUPTED_TRAVERSE // from Traverse if it wants derived classes to not traverse anything from // their CC participant. #define NS_SUCCESS_INTERRUPTED_TRAVERSE \ NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_XPCOM, 2) #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); \ NS_IMPL_CYCLE_COLLECTION_DESCRIBE(_class, tmp->mRefCnt.get()) #define NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(_cb, _name) \ PR_BEGIN_MACRO \ if (NS_UNLIKELY((_cb).WantDebugInfo())) { \ @@ -448,17 +561,17 @@ public: NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, #_field "[i]"); \ cb.NoteXPCOMChild(tmp->_field[i]); \ } \ } #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) \ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_PTR(tmp->_field, _field_class, \ #_field) #define NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSTARRAY(_array, _element_class, \ _name) \ @@ -480,56 +593,56 @@ public: } #define NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSTARRAY_MEMBER(_field, \ _element_class) \ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSTARRAY(tmp->_field, _element_class, \ #_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; \ } /////////////////////////////////////////////////////////////////////////////// // Helpers for implementing nsScriptObjectTracer::Trace /////////////////////////////////////////////////////////////////////////////// #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), \ "not the nsISupports pointer we expect"); \ _class *tmp = Downcast(s); #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); #define NS_IMPL_CYCLE_COLLECTION_TRACE_JS_CALLBACK(_object, _name) \ if (_object) \ aCallback(_object, _name, aClosure); #define NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(_field) \ @@ -548,38 +661,39 @@ public: (void)tmp; \ } /////////////////////////////////////////////////////////////////////////////// // Helpers for implementing a concrete nsCycleCollectionParticipant /////////////////////////////////////////////////////////////////////////////// #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(); \ } \ static _class* Downcast(nsISupports* s) \ { \ return static_cast<_class*>(static_cast<_base*>(s)); \ } \ static nsISupports* Upcast(_class *p) \ { \ return NS_ISUPPORTS_CAST(_base*, p); \ } #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 \ : public nsXPCOMCycleCollectionParticipant \ { \ NS_DECL_CYCLE_COLLECTION_CLASS_BODY(_class, _base) \ }; \ NS_CYCLE_COLLECTION_PARTICIPANT_INSTANCE @@ -587,116 +701,106 @@ NS_CYCLE_COLLECTION_PARTICIPANT_INSTANCE #define NS_DECL_CYCLE_COLLECTION_CLASS(_class) \ NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(_class, _class) // Cycle collector helper for ambiguous classes that can sometimes be skipped. #define NS_DECL_CYCLE_COLLECTION_SKIPPABLE_CLASS_AMBIGUOUS(_class, _base) \ 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 #define NS_DECL_CYCLE_COLLECTION_SKIPPABLE_CLASS(_class) \ NS_DECL_CYCLE_COLLECTION_SKIPPABLE_CLASS_AMBIGUOUS(_class, _class) // Cycle collector helper for classes that don't want to unlink anything. // Note: if this is used a lot it might make sense to have a base class that // doesn't do anything in Root/Unlink/Unroot. #define NS_DECL_CYCLE_COLLECTION_CLASS_NO_UNLINK(_class) \ 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; \ } \ }; \ NS_CYCLE_COLLECTION_PARTICIPANT_INSTANCE #define NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(_class, _base) \ 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 #define NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS_AMBIGUOUS(_class, _base) \ 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 #define NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS(_class) \ NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS_AMBIGUOUS(_class, _class) #define NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS_INHERITED(_class, \ _base_class) \ 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 #define NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(_class) \ NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(_class, _class) #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*>( \ NS_CYCLE_COLLECTION_CLASSNAME(_base_class)::Downcast(s))); \ } #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 \ : public NS_CYCLE_COLLECTION_CLASSNAME(_base_class) \ { \ public: \ NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_BODY(_class, _base_class) \ }; \ @@ -712,73 +816,127 @@ public: }; \ NS_CYCLE_COLLECTION_PARTICIPANT_INSTANCE #define NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(_class, \ _base_class) \ 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 /** * This implements a stub UnmarkIfPurple function for classes that want to be * traversed but whose AddRef/Release functions don't add/remove them to/from * the purple buffer. If you're just using NS_DECL_CYCLE_COLLECTING_ISUPPORTS * then you don't need this. */ #define NS_DECL_CYCLE_COLLECTION_UNMARK_PURPLE_STUB(_class) \ NS_IMETHODIMP_(void) UnmarkIfPurple() \ { \ } \ +/** + * Dummy class with a definition for CanSkip* function members, but no + * implementation. + * Implementation was added to please Win PGO. (See bug 765159) + */ +struct SkippableDummy +{ + static NS_METHOD_(bool) CanSkipImpl(void *p, bool aRemovingAllowed) { return false; } + static NS_METHOD_(bool) CanSkipInCCImpl(void *p) { return false; } + static NS_METHOD_(bool) CanSkipThisImpl(void *p) { return false; } +}; + +/** + * 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) \ - NS_CYCLE_COLLECTION_CLASSNAME(_class) NS_CYCLE_COLLECTION_NAME(_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 \ +#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 #define NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(_class) \ 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(); \ return NS_OK; \ } #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(); \ return NS_OK; \ } #define NS_IMPL_CYCLE_COLLECTION_0(_class) \ NS_IMPL_CYCLE_COLLECTION_CLASS(_class) \