Bug 616262 - Avoid cycle collection participant global variables adding static initializers. r=smaug,r=mccr8,r=Waldo
authorMike Hommey <mh+mozilla@glandium.org>
Mon, 04 Jun 2012 08:30:26 +0200
changeset 97018 83369c1bb9af922f6de3ad2cfebc8df50959a5ab
parent 97017 04c7d09b664fd64d45a00e9b0d08e890af86804a
child 97103 c3190d71504491cc6010205e31278e7ae6906e13
push id862
push userpastithas@mozilla.com
push dateThu, 21 Jun 2012 07:13:20 +0000
treeherderfx-team@df2e5f99504a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug, mccr8, Waldo
bugs616262
milestone16.0a1
Bug 616262 - Avoid cycle collection participant global variables adding static initializers. r=smaug,r=mccr8,r=Waldo
accessible/src/base/AccEvent.cpp
accessible/src/base/NotificationController.cpp
accessible/src/generic/Accessible.cpp
content/base/public/nsContentUtils.h
content/base/src/nsNodeInfoManager.cpp
content/events/src/nsEventListenerManager.cpp
content/xbl/src/nsXBLBinding.cpp
content/xbl/src/nsXBLInsertionPoint.cpp
content/xbl/src/nsXBLPrototypeBinding.cpp
content/xul/content/src/nsXULElement.cpp
content/xul/templates/src/nsXMLBinding.cpp
content/xul/templates/src/nsXULTemplateQueryProcessorXML.cpp
dom/base/nsGlobalWindow.cpp
editor/txmgr/src/nsTransactionItem.cpp
editor/txmgr/src/nsTransactionStack.cpp
js/xpconnect/src/XPCWrappedJS.cpp
js/xpconnect/src/XPCWrappedNative.cpp
js/xpconnect/src/nsXPConnect.cpp
js/xpconnect/src/xpcprivate.h
xpcom/base/nsAgg.h
xpcom/glue/nsCycleCollectionParticipant.cpp
xpcom/glue/nsCycleCollectionParticipant.h
--- 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)                                        \