Bug 386025 - Expose cycle-collection symbols, r=graydon
authorbenjamin@smedbergs.us
Mon, 06 Aug 2007 07:34:02 -0700
changeset 4305 9119e2dc0aea7349896706f53e30edfd6276a297
parent 4304 d8e588aa488ce5e6de133e7168c8567004d7b7c7
child 4306 eb4dcd5a2a7a2ece407d89e9b0ca1b36f035e9a4
push idunknown
push userunknown
push dateunknown
reviewersgraydon
bugs386025
milestone1.9a8pre
Bug 386025 - Expose cycle-collection symbols, r=graydon
content/base/src/nsNodeUtils.h
content/xbl/src/nsXBLProtoImplMember.h
js/src/xpconnect/idl/nsIXPConnect.idl
xpcom/base/Makefile.in
xpcom/base/nsCycleCollectionParticipant.cpp
xpcom/base/nsCycleCollectionParticipant.h
xpcom/base/nsCycleCollector.cpp
xpcom/base/nsCycleCollector.h
xpcom/build/nsXPCOM.h
xpcom/build/nsXPCOMPrivate.h
xpcom/ds/nsVariant.h
xpcom/glue/Makefile.in
xpcom/glue/nsCycleCollectionParticipant.cpp
xpcom/glue/nsCycleCollectionParticipant.h
xpcom/glue/nsISupportsImpl.h
xpcom/glue/objs.mk
xpcom/glue/standalone/nsXPCOMGlue.cpp
xpcom/stub/nsXPComStub.cpp
--- a/content/base/src/nsNodeUtils.h
+++ b/content/base/src/nsNodeUtils.h
@@ -44,17 +44,17 @@
 
 struct JSContext;
 struct JSObject;
 class nsINode;
 class nsNodeInfoManager;
 class nsIVariant;
 class nsIDOMUserDataHandler;
 template<class E> class nsCOMArray;
-struct nsCycleCollectionTraversalCallback;
+class nsCycleCollectionTraversalCallback;
 struct CharacterDataChangeInfo;
 
 class nsNodeUtils
 {
 public:
   /**
    * Send CharacterDataChanged notifications to nsIMutationObservers.
    * @param aContent  Node whose data changed
--- a/content/xbl/src/nsXBLProtoImplMember.h
+++ b/content/xbl/src/nsXBLProtoImplMember.h
@@ -46,17 +46,17 @@
 #include "nsString.h"
 #include "nsIJSRuntimeService.h"
 #include "nsIServiceManager.h"
 #include "nsReadableUtils.h"
 
 class nsIScriptContext;
 struct JSRuntime;
 class nsIJSRuntimeService;
-struct nsCycleCollectionTraversalCallback;
+class nsCycleCollectionTraversalCallback;
 
 struct nsXBLTextWithLineNumber
 {
   PRUnichar* mText;
   PRUint32 mLineNumber;
 
   nsXBLTextWithLineNumber() :
     mText(nsnull),
--- a/js/src/xpconnect/idl/nsIXPConnect.idl
+++ b/js/src/xpconnect/idl/nsIXPConnect.idl
@@ -145,17 +145,17 @@
 interface nsIXPCScriptable;
 interface nsIXPConnect;
 interface nsIXPConnectWrappedNative;
 interface nsIInterfaceInfo;
 interface nsIXPCSecurityManager;
 interface nsIPrincipal;
 
 %{C++
-struct nsCycleCollectionTraversalCallback;
+class nsCycleCollectionTraversalCallback;
 %}
 
 /***************************************************************************/
 [uuid(8916a320-d118-11d3-8f3a-0010a4e73d9a)]
 interface nsIXPConnectJSObjectHolder : nsISupports
 {
     readonly attribute JSObjectPtr      JSObject;
 };
--- a/xpcom/base/Makefile.in
+++ b/xpcom/base/Makefile.in
@@ -60,17 +60,16 @@ CPPSRCS		= \
 		nsErrorService.cpp \
 		nsExceptionService.cpp \
 		nsMemoryImpl.cpp \
 		nsTraceRefcntImpl.cpp \
 		nsInterfaceRequestorAgg.cpp \
 		nsUUIDGenerator.cpp \
 		nsSystemInfo.cpp \
 		nsCycleCollector.cpp \
-		nsCycleCollectionParticipant.cpp \
 		$(NULL)
 
 ifdef GC_LEAK_DETECTOR
 CSRCS += nsGarbageCollector.c
 CPPSRCS += nsLeakDetector.cpp
 REQUIRES	+= boehm
 endif
 
@@ -113,17 +112,16 @@ SDK_XPIDLSRCS   = \
 		nsIWeakReference.idl	   \
 		nsrootidl.idl		   \
 
 SDK_HEADERS     = \
 		nsError.h \
 		nsISupportsBase.h \
 		nscore.h \
 		nsCycleCollector.h \
-		nsCycleCollectionParticipant.h
 
 XPIDLSRCS	= \
 		nsIConsoleListener.idl \
 		nsIConsoleMessage.idl \
 		nsIConsoleService.idl \
 		nsIErrorService.idl \
 		nsIException.idl \
 		nsIExceptionService.idl \
deleted file mode 100644
--- a/xpcom/base/nsCycleCollectionParticipant.cpp
+++ /dev/null
@@ -1,84 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is mozilla.org code.
- *
- * The Initial Developer of the Original Code is
- * The Mozilla Foundation.
- * Portions created by the Initial Developer are Copyright (C) 2006
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either of the GNU General Public License Version 2 or later (the "GPL"),
- * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-#include "nsCycleCollectionParticipant.h"
-#include "nsCOMPtr.h"
-
-NS_IMETHODIMP
-nsXPCOMCycleCollectionParticipant::Root(void *p)
-{
-    nsISupports *s = static_cast<nsISupports*>(p);
-    NS_ADDREF(s);
-    return NS_OK;
-}
-
-NS_IMETHODIMP
-nsXPCOMCycleCollectionParticipant::Unlink(void *p)
-{
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsXPCOMCycleCollectionParticipant::Unroot(void *p)
-{
-    nsISupports *s = static_cast<nsISupports*>(p);
-    NS_RELEASE(s);
-    return NS_OK;
-}
-
-NS_IMETHODIMP 
-nsXPCOMCycleCollectionParticipant::Traverse
-    (void *p, nsCycleCollectionTraversalCallback &cb)
-{
-  return NS_OK;
-}
-
-NS_IMETHODIMP_(void)
-nsXPCOMCycleCollectionParticipant::UnmarkPurple(nsISupports *n)
-{
-}
-
-#ifdef DEBUG
-PRBool
-nsXPCOMCycleCollectionParticipant::CheckForRightISupports(nsISupports *s)
-{
-    nsCOMPtr<nsISupports> foo;
-    s->QueryInterface(NS_GET_IID(nsCycleCollectionISupports),
-                      getter_AddRefs(foo));
-    return s == foo;
-}
-#endif
deleted file mode 100644
--- a/xpcom/base/nsCycleCollectionParticipant.h
+++ /dev/null
@@ -1,476 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is mozilla.org code.
- *
- * The Initial Developer of the Original Code is
- * The Mozilla Foundation.
- * Portions created by the Initial Developer are Copyright (C) 2006
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either of the GNU General Public License Version 2 or later (the "GPL"),
- * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-#ifndef nsCycleCollectionParticipant_h__
-#define nsCycleCollectionParticipant_h__
-
-#include "nsISupports.h"
-
-#define NS_CYCLECOLLECTIONPARTICIPANT_IID                                      \
-{                                                                              \
-    0x8057ad9e,                                                                \
-    0x3ecc,                                                                    \
-    0x4e89,                                                                    \
-    { 0x89, 0xac, 0x0a, 0x71, 0xf3, 0x8b, 0x14, 0xc2 }                         \
-}
-
-/**
- * Special IID to get at the base nsISupports for a class. Usually this is the
- * canonical nsISupports pointer, but in the case of tearoffs for example it is
- * the base nsISupports pointer of the tearoff. This allow the cycle collector
- * to have separate nsCycleCollectionParticipant's for tearoffs or aggregated
- * classes.
- */
-#define NS_CYCLECOLLECTIONISUPPORTS_IID                                        \
-{                                                                              \
-    0xc61eac14,                                                                \
-    0x5f7a,                                                                    \
-    0x4481,                                                                    \
-    { 0x96, 0x5e, 0x7e, 0xaa, 0x6e, 0xff, 0xa8, 0x5f }                         \
-}
-
-/**
- * Just holds the IID so NS_GET_IID works.
- */
-class NS_COM nsCycleCollectionISupports
-{
-public:
-    NS_DECLARE_STATIC_IID_ACCESSOR(NS_CYCLECOLLECTIONISUPPORTS_IID)
-};
-
-NS_DEFINE_STATIC_IID_ACCESSOR(nsCycleCollectionISupports, 
-                              NS_CYCLECOLLECTIONISUPPORTS_IID)
-
-#undef  IMETHOD_VISIBILITY
-#define IMETHOD_VISIBILITY NS_VISIBILITY_DEFAULT
-
-class nsCycleCollectionParticipant;
-
-struct nsCycleCollectionTraversalCallback
-{
-    // You must call DescribeNode() with an accurate refcount,
-    // otherwise cycle collection will fail, and probably crash.
-#ifdef DEBUG_CC
-    virtual void DescribeNode(size_t refcount,
-                              size_t objsz,
-                              const char *objname) = 0;
-#else
-    virtual void DescribeNode(size_t refcount) = 0;
-#endif
-    virtual void NoteScriptChild(PRUint32 langID, void *child) = 0;
-    virtual void NoteXPCOMChild(nsISupports *child) = 0;
-    virtual void NoteNativeChild(void *child,
-                                 nsCycleCollectionParticipant *helper) = 0;
-};
-
-class NS_NO_VTABLE nsCycleCollectionParticipant
-{
-public:
-    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;
-};
-
-class NS_COM nsXPCOMCycleCollectionParticipant
-    : public nsCycleCollectionParticipant
-{
-public:
-    NS_DECLARE_STATIC_IID_ACCESSOR(NS_CYCLECOLLECTIONPARTICIPANT_IID)
-
-    NS_IMETHOD Traverse(void *p, nsCycleCollectionTraversalCallback &cb);
-
-    NS_IMETHOD Root(void *p);
-    NS_IMETHOD Unlink(void *p);
-    NS_IMETHOD Unroot(void *p);
-
-    NS_IMETHOD_(void) UnmarkPurple(nsISupports *p);
-
-#ifdef DEBUG
-    NS_EXTERNAL_VIS_(PRBool) CheckForRightISupports(nsISupports *s);
-#endif
-};
-
-NS_DEFINE_STATIC_IID_ACCESSOR(nsXPCOMCycleCollectionParticipant, 
-                              NS_CYCLECOLLECTIONPARTICIPANT_IID)
-
-#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_NAME(_class)                                       \
-        _class##_cycleCollectorGlobal
-
-#define NS_IMPL_QUERY_CYCLE_COLLECTION(_class)                                 \
-  if ( aIID.Equals(NS_GET_IID(nsXPCOMCycleCollectionParticipant)) ) {          \
-    *aInstancePtr = & NS_CYCLE_COLLECTION_NAME(_class);                        \
-    return NS_OK;                                                              \
-  } else
-
-#define NS_IMPL_QUERY_CYCLE_COLLECTION_ISUPPORTS(_class)                       \
-  if ( aIID.Equals(NS_GET_IID(nsCycleCollectionISupports)) )                   \
-    foundInterface = NS_CYCLE_COLLECTION_CLASSNAME(_class)::Upcast(this);      \
-  else
-
-#define NS_INTERFACE_MAP_ENTRY_CYCLE_COLLECTION(_class)                        \
-  NS_IMPL_QUERY_CYCLE_COLLECTION(_class)
-
-#define NS_INTERFACE_MAP_ENTRY_CYCLE_COLLECTION_ISUPPORTS(_class)              \
-  NS_IMPL_QUERY_CYCLE_COLLECTION_ISUPPORTS(_class)
-
-#define NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(_class)                      \
-  NS_INTERFACE_MAP_ENTRY_CYCLE_COLLECTION(_class)                              \
-  NS_INTERFACE_MAP_ENTRY_CYCLE_COLLECTION_ISUPPORTS(_class)
-
-#define NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(_class)                        \
-  NS_INTERFACE_MAP_BEGIN(_class)                                               \
-    NS_INTERFACE_MAP_ENTRY_CYCLE_COLLECTION(_class)                            \
-    NS_INTERFACE_MAP_ENTRY_CYCLE_COLLECTION_ISUPPORTS(_class)
-
-#define NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(_class)              \
-  NS_INTERFACE_MAP_BEGIN(_class)                                               \
-    NS_INTERFACE_MAP_ENTRY_CYCLE_COLLECTION(_class)
-
-///////////////////////////////////////////////////////////////////////////////
-// Helpers for implementing nsCycleCollectionParticipant::Unlink
-///////////////////////////////////////////////////////////////////////////////
-
-#define NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(_class)                          \
-  NS_IMETHODIMP                                                                \
-  NS_CYCLE_COLLECTION_CLASSNAME(_class)::Unlink(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)                       \
-  {                                                                            \
-    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);
-
-#define NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_NATIVE(_class)                   \
-  NS_IMETHODIMP                                                                \
-  NS_CYCLE_COLLECTION_CLASSNAME(_class)::Unlink(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();
-
-#define NS_IMPL_CYCLE_COLLECTION_UNLINK_NSTARRAY(_field)                       \
-    tmp->_field.Clear();
-
-#define NS_IMPL_CYCLE_COLLECTION_UNLINK_END                                    \
-    return NS_OK;                                                              \
-  }
-
-#define NS_IMPL_CYCLE_COLLECTION_UNLINK_0(_class)                              \
-  NS_IMETHODIMP                                                                \
-  NS_CYCLE_COLLECTION_CLASSNAME(_class)::Unlink(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)                       \
-  {                                                                            \
-    return NS_OK;                                                              \
-  }
-
-
-///////////////////////////////////////////////////////////////////////////////
-// Helpers for implementing nsCycleCollectionParticipant::Traverse
-///////////////////////////////////////////////////////////////////////////////
-
-#ifdef DEBUG_CC
-#define NS_IMPL_CYCLE_COLLECTION_DESCRIBE(_class)                              \
-    cb.DescribeNode(tmp->mRefCnt.get(), sizeof(_class), #_class);
-#else
-#define NS_IMPL_CYCLE_COLLECTION_DESCRIBE(_class)                              \
-    cb.DescribeNode(tmp->mRefCnt.get());
-#endif
-
-#define NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(_class)                        \
-  NS_IMETHODIMP                                                                \
-  NS_CYCLE_COLLECTION_CLASSNAME(_class)::Traverse                              \
-                         (void *p,                                             \
-                          nsCycleCollectionTraversalCallback &cb)              \
-  {                                                                            \
-    nsISupports *s = static_cast<nsISupports*>(p);                             \
-    NS_ASSERTION(CheckForRightISupports(s),                                    \
-                 "not the nsISupports pointer we expect");                     \
-    _class *tmp = Downcast(s);                                                 \
-    NS_IMPL_CYCLE_COLLECTION_DESCRIBE(_class)
-
-#define NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(_class, _base_class) \
-  NS_IMETHODIMP                                                                \
-  NS_CYCLE_COLLECTION_CLASSNAME(_class)::Traverse                              \
-                         (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));                           \
-    NS_CYCLE_COLLECTION_CLASSNAME(_base_class)::Traverse(s, cb);
-
-#define NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_BEGIN(_class)                 \
-  NS_IMETHODIMP                                                                \
-  NS_CYCLE_COLLECTION_CLASSNAME(_class)::Traverse                              \
-                         (void *p,                                             \
-                          nsCycleCollectionTraversalCallback &cb)              \
-  {                                                                            \
-    _class *tmp = static_cast<_class*>(p);                                     \
-    NS_IMPL_CYCLE_COLLECTION_DESCRIBE(_class)
-
-#define NS_IMPL_CYCLE_COLLECTION_TRAVERSE_RAWPTR(_field)                       \
-    cb.NoteXPCOMChild(tmp->_field);
-
-#define NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(_field)                     \
-    cb.NoteXPCOMChild(tmp->_field.get());
-
-#define NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR_AMBIGUOUS(_field, _base)    \
-    cb.NoteXPCOMChild(NS_ISUPPORTS_CAST(_base*, tmp->_field));
-
-#define NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMARRAY(_field)                   \
-    {                                                                          \
-      PRInt32 i;                                                               \
-      for (i = 0; i < tmp->_field.Count(); ++i)                                \
-        cb.NoteXPCOMChild(tmp->_field[i]);                                     \
-    }
-
-#define NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_PTR(_ptr, _ptr_class)         \
-  cb.NoteNativeChild(_ptr, &NS_CYCLE_COLLECTION_NATIVE_NAME(_ptr_class));
-
-#define NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_MEMBER(_field, _field_class)  \
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_PTR(tmp->_field, _field_class)
-
-#define NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSTARRAY(_array, _element_class)     \
-    {                                                                          \
-      PRUint32 i, length = (_array).Length();                                  \
-      for (i = 0; i < length; ++i)                                             \
-        NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_PTR((_array)[i],              \
-                                                     _element_class);          \
-    }
-
-#define NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSTARRAY_MEMBER(_field,              \
-                                                          _element_class)      \
-    NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSTARRAY(tmp->_field, _element_class)
-
-#define NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END                                  \
-    return NS_OK;                                                              \
-  }
-
-///////////////////////////////////////////////////////////////////////////////
-// Helpers for implementing a concrete nsCycleCollectionParticipant 
-///////////////////////////////////////////////////////////////////////////////
-
-#define NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(_class, _base)                \
-class NS_CYCLE_COLLECTION_INNERCLASS                                           \
- : public nsXPCOMCycleCollectionParticipant                                    \
-{                                                                              \
-public:                                                                        \
-  NS_IMETHOD Unlink(void *p);                                                  \
-  NS_IMETHOD Traverse(void *p,                                                 \
-                      nsCycleCollectionTraversalCallback &cb);                 \
-  NS_IMETHOD_(void) UnmarkPurple(nsISupports *s)                               \
-  {                                                                            \
-    Downcast(s)->UnmarkPurple();                                               \
-  }                                                                            \
-  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(_class)                                 \
-  NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(_class, _class)
-
-#define NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(_class, _base_class)          \
-class NS_CYCLE_COLLECTION_INNERCLASS                                           \
- : public NS_CYCLE_COLLECTION_CLASSNAME(_base_class)                           \
-{                                                                              \
-public:                                                                        \
-  NS_IMETHOD Unlink(void *p);                                                  \
-  NS_IMETHOD Traverse(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_NO_UNLINK(_class,             \
-                                                           _base_class)        \
-class NS_CYCLE_COLLECTION_INNERCLASS                                           \
- : public NS_CYCLE_COLLECTION_CLASSNAME(_base_class)                           \
-{                                                                              \
-public:                                                                        \
-  NS_IMETHOD Traverse(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)));               \
-  }                                                                            \
-};
-
-/**
- * This implements a stub UnmarkPurple 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) UnmarkPurple()                                          \
-  {                                                                            \
-  }                                                                            \
-
-#define NS_IMPL_CYCLE_COLLECTION_CLASS(_class)                                 \
-  static NS_CYCLE_COLLECTION_CLASSNAME(_class)                                 \
-    NS_CYCLE_COLLECTION_NAME(_class);
-
-#define NS_CYCLE_COLLECTION_NATIVE_INNERNAME                                   \
-        _cycleCollectorGlobal
-
-#define NS_CYCLE_COLLECTION_NATIVE_NAME(_class)                                \
-        _class::NS_CYCLE_COLLECTION_NATIVE_INNERNAME
-
-#define NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(_class)                          \
-  class NS_CYCLE_COLLECTION_INNERCLASS                                         \
-   : public nsCycleCollectionParticipant                                       \
-  {                                                                            \
-  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_CYCLE_COLLECTION_INNERCLASS                                        \
-      NS_CYCLE_COLLECTION_NATIVE_INNERNAME;
-
-#define NS_IMPL_CYCLE_COLLECTION_NATIVE_CLASS(_class)                          \
-  NS_CYCLE_COLLECTION_CLASSNAME(_class) NS_CYCLE_COLLECTION_NATIVE_NAME(_class);
-
-#define NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(_class, _root_function)           \
-  NS_IMETHODIMP                                                                \
-  NS_CYCLE_COLLECTION_CLASSNAME(_class)::Root(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)                       \
-  {                                                                            \
-    _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)                                        \
- NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(_class)                                 \
- NS_IMPL_CYCLE_COLLECTION_UNLINK_END                                           \
- NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(_class)                               \
- NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
-
-#define NS_IMPL_CYCLE_COLLECTION_1(_class, _f)                                 \
- NS_IMPL_CYCLE_COLLECTION_CLASS(_class)                                        \
- NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(_class)                                 \
- NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(_f)                                  \
- NS_IMPL_CYCLE_COLLECTION_UNLINK_END                                           \
- NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(_class)                               \
- NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(_f)                                \
- NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
-
-#define NS_IMPL_CYCLE_COLLECTION_2(_class, _f1, _f2)                           \
- NS_IMPL_CYCLE_COLLECTION_CLASS(_class)                                        \
- NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(_class)                                 \
- NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(_f1)                                 \
- NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(_f2)                                 \
- NS_IMPL_CYCLE_COLLECTION_UNLINK_END                                           \
- NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(_class)                               \
- NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(_f1)                               \
- NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(_f2)                               \
- NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
-
-#define NS_IMPL_CYCLE_COLLECTION_3(_class, _f1, _f2, _f3)                      \
- NS_IMPL_CYCLE_COLLECTION_CLASS(_class)                                        \
- NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(_class)                                 \
- NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(_f1)                                 \
- NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(_f2)                                 \
- NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(_f3)                                 \
- NS_IMPL_CYCLE_COLLECTION_UNLINK_END                                           \
- NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(_class)                               \
- NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(_f1)                               \
- NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(_f2)                               \
- NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(_f3)                               \
- NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
-
-#endif // nsCycleCollectionParticipant_h__
--- a/xpcom/base/nsCycleCollector.cpp
+++ b/xpcom/base/nsCycleCollector.cpp
@@ -1105,24 +1105,24 @@ public:
     PRUint32 Count() const { return mPtrToNodeMap.entryCount; }
 
     PtrInfo* AddNode(void *s, nsCycleCollectionParticipant *aParticipant);
     void Traverse(PtrInfo* aPtrInfo);
 
 private:
     // nsCycleCollectionTraversalCallback methods.
 #ifdef DEBUG_CC
-    void DescribeNode(size_t refCount, size_t objSz, const char *objName);
+    NS_METHOD_(void) DescribeNode(nsrefcnt refCount, size_t objSz, const char *objName);
 #else
-    void DescribeNode(size_t refCount);
+    NS_METHOD_(void) DescribeNode(nsrefcnt refCount);
 #endif
-    void NoteXPCOMChild(nsISupports *child);
-    void NoteNativeChild(void *child,
-                         nsCycleCollectionParticipant *participant);
-    void NoteScriptChild(PRUint32 langID, void *child);
+    NS_METHOD_(void) NoteXPCOMChild(nsISupports *child);
+    NS_METHOD_(void) NoteNativeChild(void *child,
+                                     nsCycleCollectionParticipant *participant);
+    NS_METHOD_(void) NoteScriptChild(PRUint32 langID, void *child);
 };
 
 GCGraphBuilder::GCGraphBuilder(GCGraph &aGraph,
                                nsCycleCollectionLanguageRuntime **aRuntimes)
     : mNodeBuilder(aGraph.mNodes),
       mEdgeBuilder(aGraph.mEdges),
       mRuntimes(aRuntimes)
 {
@@ -1177,19 +1177,19 @@ GCGraphBuilder::Traverse(PtrInfo* aPtrIn
         Fault("script pointer traversal failed", aPtrInfo);
     }
 
     mCurrPi->mLastChild = mEdgeBuilder.Mark();
 }
 
 void 
 #ifdef DEBUG_CC
-GCGraphBuilder::DescribeNode(size_t refCount, size_t objSz, const char *objName)
+GCGraphBuilder::DescribeNode(nsrefcnt refCount, size_t objSz, const char *objName)
 #else
-GCGraphBuilder::DescribeNode(size_t refCount)
+GCGraphBuilder::DescribeNode(nsrefcnt refCount)
 #endif
 {
 #ifdef DEBUG_CC
     mCurrPi->mBytes = objSz;
     mCurrPi->mName = PL_strdup(objName);
 #endif
 
     if (refCount == 0)
@@ -1841,17 +1841,17 @@ public:
                 Fault("checking suppression on wrong type of pointer", s);
                 return PR_TRUE;
             }
             cp->Traverse(s, *this);
         }
         return mSuppressThisNode;
     }
 
-    void DescribeNode(size_t refCount, size_t objSz, const char *objName)
+    void DescribeNode(nsrefcnt refCount, size_t objSz, const char *objName)
     {
         mSuppressThisNode = (PL_strstr(sSuppressionList, objName) != nsnull);
     }
 
     void NoteXPCOMChild(nsISupports *child) {}
     void NoteScriptChild(PRUint32 langID, void *child) {}
     void NoteNativeChild(void *child,
                          nsCycleCollectionParticipant *participant) {}
@@ -2514,17 +2514,17 @@ void
 nsCycleCollector_forgetRuntime(PRUint32 langID)
 {
     if (sCollector)
         sCollector->ForgetRuntime(langID);
 }
 
 
 PRBool
-nsCycleCollector_suspect(nsISupports *n)
+NS_CycleCollectorSuspect(nsISupports *n)
 {
     if (sCollector)
         return sCollector->Suspect(n);
     return PR_FALSE;
 }
 
 
 void 
@@ -2534,17 +2534,17 @@ nsCycleCollector_suspectCurrent(nsISuppo
         PRBool res = sCollector->Suspect(n, PR_TRUE);
         NS_ASSERTION(res || sCollector->mParams.mDoNothing,
                      "suspectCurrent should not fail");
     }
 }
 
 
 PRBool
-nsCycleCollector_forget(nsISupports *n)
+NS_CycleCollectorForget(nsISupports *n)
 {
     if (sCollector)
         return sCollector->Forget(n);
     return PR_FALSE;
 }
 
 
 void 
--- a/xpcom/base/nsCycleCollector.h
+++ b/xpcom/base/nsCycleCollector.h
@@ -46,19 +46,19 @@ class nsCycleCollectionParticipant;
 
 struct nsCycleCollectionLanguageRuntime
 {
     virtual nsresult BeginCycleCollection() = 0;
     virtual nsresult FinishCycleCollection() = 0;
     virtual nsCycleCollectionParticipant *ToParticipant(void *p) = 0;
 };
 
-NS_COM PRBool nsCycleCollector_suspect(nsISupports *n);
+// PRBool nsCycleCollector_suspect(nsISupports *n);
 NS_COM void nsCycleCollector_suspectCurrent(nsISupports *n);
-NS_COM PRBool nsCycleCollector_forget(nsISupports *n);
+// NS_COM PRBool nsCycleCollector_forget(nsISupports *n);
 nsresult nsCycleCollector_startup();
 NS_COM void nsCycleCollector_collect();
 void nsCycleCollector_shutdown();
 
 #ifdef DEBUG
 NS_COM void nsCycleCollector_DEBUG_shouldBeFreed(nsISupports *n);
 NS_COM void nsCycleCollector_DEBUG_wasFreed(nsISupports *n);
 #endif
--- a/xpcom/build/nsXPCOM.h
+++ b/xpcom/build/nsXPCOM.h
@@ -59,16 +59,18 @@
 # define NS_LogInit                  NS_LogInit_P
 # define NS_LogTerm                  NS_LogTerm_P
 # define NS_LogAddRef                NS_LogAddRef_P
 # define NS_LogRelease               NS_LogRelease_P
 # define NS_LogCtor                  NS_LogCtor_P
 # define NS_LogDtor                  NS_LogDtor_P
 # define NS_LogCOMPtrAddRef          NS_LogCOMPtrAddRef_P
 # define NS_LogCOMPtrRelease         NS_LogCOMPtrRelease_P
+# define NS_CycleCollectorSuspect    NS_CycleCollectorSuspect_P
+# define NS_CycleCollectorForget     NS_CycleCollectorForget_P
 #endif
 
 #include "nscore.h"
 #include "nsXPCOMCID.h"
 
 #ifdef __cplusplus
 #define DECL_CLASS(c) class c
 #else
@@ -449,16 +451,27 @@ NS_LogRelease(void *aPtr, nsrefcnt aNewR
 
 XPCOM_API(void)
 NS_LogCOMPtrAddRef(void *aCOMPtr, nsISupports *aObject);
 
 XPCOM_API(void)
 NS_LogCOMPtrRelease(void *aCOMPtr, nsISupports *aObject);
 
 /**
+ * The XPCOM cycle collector analyzes and breaks reference cycles between
+ * participating XPCOM objects. All objects in the cycle must implement
+ * nsCycleCollectionParticipant to break cycles correctly.
+ */
+XPCOM_API(PRBool)
+NS_CycleCollectorSuspect(nsISupports *n);
+
+XPCOM_API(PRBool)
+NS_CycleCollectorForget(nsISupports *n);
+
+/**
  * Categories (in the category manager service) used by XPCOM:
  */
 
 /**
  * A category which is read after component registration but before
  * the "xpcom-startup" notifications. Each category entry is treated
  * as the contract ID of a service which implements
  * nsIDirectoryServiceProvider. Each directory service provider is
--- a/xpcom/build/nsXPCOMPrivate.h
+++ b/xpcom/build/nsXPCOMPrivate.h
@@ -109,16 +109,17 @@ typedef void       (* xpcomVoidFunc)();
 typedef void       (* LogAddRefFunc)(void*, nsrefcnt, const char*, PRUint32);
 typedef void       (* LogReleaseFunc)(void*, nsrefcnt, const char*);
 typedef void       (* LogCtorFunc)(void*, const char*, PRUint32);
 typedef void       (* LogCOMPtrFunc)(void*, nsISupports*);
 
 typedef nsresult   (* GetXPTCallStubFunc)(REFNSIID, nsIXPTCProxy*, nsISomeInterface**);
 typedef void       (* DestroyXPTCallStubFunc)(nsISomeInterface*);
 typedef nsresult   (* InvokeByIndexFunc)(nsISupports*, PRUint32, PRUint32, nsXPTCVariant*);
+typedef PRBool     (* CycleCollectorFunc)(nsISupports*);
 
 // PRIVATE AND DEPRECATED
 typedef NS_CALLBACK(XPCOMExitRoutine)(void);
 
 typedef nsresult   (* RegisterXPCOMExitRoutineFunc)(XPCOMExitRoutine exitRoutine, PRUint32 priority);
 typedef nsresult   (* UnregisterXPCOMExitRoutineFunc)(XPCOMExitRoutine exitRoutine);
 
 typedef struct XPCOMFunctions{
@@ -177,16 +178,18 @@ typedef struct XPCOMFunctions{
     LogReleaseFunc logReleaseFunc;
     LogCtorFunc logCtorFunc;
     LogCtorFunc logDtorFunc;
     LogCOMPtrFunc logCOMPtrAddRefFunc;
     LogCOMPtrFunc logCOMPtrReleaseFunc;
     GetXPTCallStubFunc getXPTCallStubFunc;
     DestroyXPTCallStubFunc destroyXPTCallStubFunc;
     InvokeByIndexFunc invokeByIndexFunc;
+    CycleCollectorFunc cycleSuspectFunc;
+    CycleCollectorFunc cycleForgetFunc;
 
 } XPCOMFunctions;
 
 typedef nsresult (PR_CALLBACK *GetFrozenFunctionsFunc)(XPCOMFunctions *entryPoints, const char* libraryPath);
 XPCOM_API(nsresult)
 NS_GetFrozenFunctions(XPCOMFunctions *entryPoints, const char* libraryPath);
 
 // think hard before changing this
--- a/xpcom/ds/nsVariant.h
+++ b/xpcom/ds/nsVariant.h
@@ -38,17 +38,17 @@
  * ***** END LICENSE BLOCK ***** */
 
 /* The long avoided variant support for xpcom. */
 
 #include "nsIVariant.h"
 #include "nsStringFwd.h"
 #include "xpt_struct.h"
 
-struct nsCycleCollectionTraversalCallback;
+class nsCycleCollectionTraversalCallback;
 
 /** 
  * Map the nsAUTF8String, nsUTF8String classes to the nsACString and
  * nsCString classes respectively for now.  These defines need to be removed
  * once Jag lands his nsUTF8String implementation.
  */
 #define nsAUTF8String nsACString
 #define nsUTF8String nsCString
--- a/xpcom/glue/Makefile.in
+++ b/xpcom/glue/Makefile.in
@@ -106,16 +106,17 @@ SDK_HEADERS = \
 		nsMemory.h \
 		nsTraceRefcnt.h \
 		nsWeakReference.h \
 		nsComponentManagerUtils.h \
 		nsServiceManagerUtils.h \
 		nsVersionComparator.h \
 		nsIClassInfoImpl.h \
 		nsTObserverArray.h \
+		nsCycleCollectionParticipant.h \
 		$(NULL)
 
 EXPORTS = \
 		nsThreadUtils.h \
 		nsProxyRelease.h \
 		nsXPTCUtils.h \
 		$(NULL)
 
new file mode 100644
--- /dev/null
+++ b/xpcom/glue/nsCycleCollectionParticipant.cpp
@@ -0,0 +1,82 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * The Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2006
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsCycleCollectionParticipant.h"
+#include "nsCOMPtr.h"
+
+nsresult
+nsXPCOMCycleCollectionParticipant::Root(void *p)
+{
+    nsISupports *s = static_cast<nsISupports*>(p);
+    NS_ADDREF(s);
+    return NS_OK;
+}
+
+nsresult
+nsXPCOMCycleCollectionParticipant::Unlink(void *p)
+{
+  return NS_OK;
+}
+
+nsresult
+nsXPCOMCycleCollectionParticipant::Unroot(void *p)
+{
+    nsISupports *s = static_cast<nsISupports*>(p);
+    NS_RELEASE(s);
+    return NS_OK;
+}
+
+nsresult
+nsXPCOMCycleCollectionParticipant::Traverse
+    (void *p, nsCycleCollectionTraversalCallback &cb)
+{
+  return NS_OK;
+}
+
+void
+nsXPCOMCycleCollectionParticipant::UnmarkPurple(nsISupports *n)
+{
+}
+
+PRBool
+nsXPCOMCycleCollectionParticipant::CheckForRightISupports(nsISupports *s)
+{
+    nsCOMPtr<nsISupports> foo;
+    s->QueryInterface(NS_GET_IID(nsCycleCollectionISupports),
+                      getter_AddRefs(foo));
+    return s == foo;
+}
new file mode 100644
--- /dev/null
+++ b/xpcom/glue/nsCycleCollectionParticipant.h
@@ -0,0 +1,474 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * The Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2006
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsCycleCollectionParticipant_h__
+#define nsCycleCollectionParticipant_h__
+
+#include "nsISupports.h"
+
+#define NS_CYCLECOLLECTIONPARTICIPANT_IID                                      \
+{                                                                              \
+    0x9674489b,                                                                \
+    0x1f6f,                                                                    \
+    0x4550,                                                                    \
+    { 0xa7, 0x30, 0xcc, 0xae, 0xdd, 0x10, 0x4c, 0xf9 }                         \
+}
+
+/**
+ * Special IID to get at the base nsISupports for a class. Usually this is the
+ * canonical nsISupports pointer, but in the case of tearoffs for example it is
+ * the base nsISupports pointer of the tearoff. This allow the cycle collector
+ * to have separate nsCycleCollectionParticipant's for tearoffs or aggregated
+ * classes.
+ */
+#define NS_CYCLECOLLECTIONISUPPORTS_IID                                        \
+{                                                                              \
+    0xc61eac14,                                                                \
+    0x5f7a,                                                                    \
+    0x4481,                                                                    \
+    { 0x96, 0x5e, 0x7e, 0xaa, 0x6e, 0xff, 0xa8, 0x5f }                         \
+}
+
+/**
+ * Just holds the IID so NS_GET_IID works.
+ */
+class nsCycleCollectionISupports
+{
+public:
+    NS_DECLARE_STATIC_IID_ACCESSOR(NS_CYCLECOLLECTIONISUPPORTS_IID)
+};
+
+NS_DEFINE_STATIC_IID_ACCESSOR(nsCycleCollectionISupports, 
+                              NS_CYCLECOLLECTIONISUPPORTS_IID)
+
+class nsCycleCollectionParticipant;
+
+class NS_NO_VTABLE nsCycleCollectionTraversalCallback
+{
+public:
+    // You must call DescribeNode() with an accurate refcount,
+    // otherwise cycle collection will fail, and probably crash.
+#ifdef DEBUG_CC
+    NS_IMETHOD_(void) DescribeNode(nsrefcnt refcount,
+                                   size_t objsz,
+                                   const char *objname) = 0;
+#else
+    NS_IMETHOD_(void) DescribeNode(nsrefcnt refcount) = 0;
+#endif
+    NS_IMETHOD_(void) NoteScriptChild(PRUint32 langID, void *child) = 0;
+    NS_IMETHOD_(void) NoteXPCOMChild(nsISupports *child) = 0;
+    NS_IMETHOD_(void) NoteNativeChild(void *child,
+                                      nsCycleCollectionParticipant *helper) = 0;
+};
+
+class NS_NO_VTABLE nsCycleCollectionParticipant
+{
+public:
+    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;
+};
+
+NS_DEFINE_STATIC_IID_ACCESSOR(nsCycleCollectionParticipant, 
+                              NS_CYCLECOLLECTIONPARTICIPANT_IID)
+
+#undef IMETHOD_VISIBILITY
+#define IMETHOD_VISIBILITY NS_COM_GLUE
+
+class NS_COM_GLUE nsXPCOMCycleCollectionParticipant
+    : public nsCycleCollectionParticipant
+{
+public:
+    NS_IMETHOD Traverse(void *p, nsCycleCollectionTraversalCallback &cb);
+
+    NS_IMETHOD Root(void *p);
+    NS_IMETHOD Unlink(void *p);
+    NS_IMETHOD Unroot(void *p);
+
+    NS_IMETHOD_(void) UnmarkPurple(nsISupports *p);
+
+    PRBool 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_NAME(_class)                                       \
+        _class##_cycleCollectorGlobal
+
+#define NS_IMPL_QUERY_CYCLE_COLLECTION(_class)                                 \
+  if ( aIID.Equals(NS_GET_IID(nsXPCOMCycleCollectionParticipant)) ) {          \
+    *aInstancePtr = & NS_CYCLE_COLLECTION_NAME(_class);                        \
+    return NS_OK;                                                              \
+  } else
+
+#define NS_IMPL_QUERY_CYCLE_COLLECTION_ISUPPORTS(_class)                       \
+  if ( aIID.Equals(NS_GET_IID(nsCycleCollectionISupports)) )                   \
+    foundInterface = NS_CYCLE_COLLECTION_CLASSNAME(_class)::Upcast(this);      \
+  else
+
+#define NS_INTERFACE_MAP_ENTRY_CYCLE_COLLECTION(_class)                        \
+  NS_IMPL_QUERY_CYCLE_COLLECTION(_class)
+
+#define NS_INTERFACE_MAP_ENTRY_CYCLE_COLLECTION_ISUPPORTS(_class)              \
+  NS_IMPL_QUERY_CYCLE_COLLECTION_ISUPPORTS(_class)
+
+#define NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(_class)                      \
+  NS_INTERFACE_MAP_ENTRY_CYCLE_COLLECTION(_class)                              \
+  NS_INTERFACE_MAP_ENTRY_CYCLE_COLLECTION_ISUPPORTS(_class)
+
+#define NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(_class)                        \
+  NS_INTERFACE_MAP_BEGIN(_class)                                               \
+    NS_INTERFACE_MAP_ENTRY_CYCLE_COLLECTION(_class)                            \
+    NS_INTERFACE_MAP_ENTRY_CYCLE_COLLECTION_ISUPPORTS(_class)
+
+#define NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(_class)              \
+  NS_INTERFACE_MAP_BEGIN(_class)                                               \
+    NS_INTERFACE_MAP_ENTRY_CYCLE_COLLECTION(_class)
+
+///////////////////////////////////////////////////////////////////////////////
+// Helpers for implementing nsCycleCollectionParticipant::Unlink
+///////////////////////////////////////////////////////////////////////////////
+
+#define NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(_class)                          \
+  NS_IMETHODIMP                                                                \
+  NS_CYCLE_COLLECTION_CLASSNAME(_class)::Unlink(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)                       \
+  {                                                                            \
+    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);
+
+#define NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_NATIVE(_class)                   \
+  NS_IMETHODIMP                                                                \
+  NS_CYCLE_COLLECTION_CLASSNAME(_class)::Unlink(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();
+
+#define NS_IMPL_CYCLE_COLLECTION_UNLINK_NSTARRAY(_field)                       \
+    tmp->_field.Clear();
+
+#define NS_IMPL_CYCLE_COLLECTION_UNLINK_END                                    \
+    return NS_OK;                                                              \
+  }
+
+#define NS_IMPL_CYCLE_COLLECTION_UNLINK_0(_class)                              \
+  NS_IMETHODIMP                                                                \
+  NS_CYCLE_COLLECTION_CLASSNAME(_class)::Unlink(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)                       \
+  {                                                                            \
+    return NS_OK;                                                              \
+  }
+
+
+///////////////////////////////////////////////////////////////////////////////
+// Helpers for implementing nsCycleCollectionParticipant::Traverse
+///////////////////////////////////////////////////////////////////////////////
+
+#ifdef DEBUG_CC
+#define NS_IMPL_CYCLE_COLLECTION_DESCRIBE(_class)                              \
+    cb.DescribeNode(tmp->mRefCnt.get(), sizeof(_class), #_class);
+#else
+#define NS_IMPL_CYCLE_COLLECTION_DESCRIBE(_class)                              \
+    cb.DescribeNode(tmp->mRefCnt.get());
+#endif
+
+#define NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(_class)                        \
+  NS_IMETHODIMP                                                                \
+  NS_CYCLE_COLLECTION_CLASSNAME(_class)::Traverse                              \
+                         (void *p,                                             \
+                          nsCycleCollectionTraversalCallback &cb)              \
+  {                                                                            \
+    nsISupports *s = static_cast<nsISupports*>(p);                             \
+    NS_ASSERTION(CheckForRightISupports(s),                                    \
+                 "not the nsISupports pointer we expect");                     \
+    _class *tmp = Downcast(s);                                                 \
+    NS_IMPL_CYCLE_COLLECTION_DESCRIBE(_class)
+
+#define NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(_class, _base_class) \
+  NS_IMETHODIMP                                                                \
+  NS_CYCLE_COLLECTION_CLASSNAME(_class)::Traverse                              \
+                         (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));                           \
+    NS_CYCLE_COLLECTION_CLASSNAME(_base_class)::Traverse(s, cb);
+
+#define NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_BEGIN(_class)                 \
+  NS_IMETHODIMP                                                                \
+  NS_CYCLE_COLLECTION_CLASSNAME(_class)::Traverse                              \
+                         (void *p,                                             \
+                          nsCycleCollectionTraversalCallback &cb)              \
+  {                                                                            \
+    _class *tmp = static_cast<_class*>(p);                                     \
+    NS_IMPL_CYCLE_COLLECTION_DESCRIBE(_class)
+
+#define NS_IMPL_CYCLE_COLLECTION_TRAVERSE_RAWPTR(_field)                       \
+    cb.NoteXPCOMChild(tmp->_field);
+
+#define NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(_field)                     \
+    cb.NoteXPCOMChild(tmp->_field.get());
+
+#define NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR_AMBIGUOUS(_field, _base)    \
+    cb.NoteXPCOMChild(NS_ISUPPORTS_CAST(_base*, tmp->_field));
+
+#define NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMARRAY(_field)                   \
+    {                                                                          \
+      PRInt32 i;                                                               \
+      for (i = 0; i < tmp->_field.Count(); ++i)                                \
+        cb.NoteXPCOMChild(tmp->_field[i]);                                     \
+    }
+
+#define NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_PTR(_ptr, _ptr_class)         \
+  cb.NoteNativeChild(_ptr, &NS_CYCLE_COLLECTION_NATIVE_NAME(_ptr_class));
+
+#define NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_MEMBER(_field, _field_class)  \
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_PTR(tmp->_field, _field_class)
+
+#define NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSTARRAY(_array, _element_class)     \
+    {                                                                          \
+      PRUint32 i, length = (_array).Length();                                  \
+      for (i = 0; i < length; ++i)                                             \
+        NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_PTR((_array)[i],              \
+                                                     _element_class);          \
+    }
+
+#define NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSTARRAY_MEMBER(_field,              \
+                                                          _element_class)      \
+    NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSTARRAY(tmp->_field, _element_class)
+
+#define NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END                                  \
+    return NS_OK;                                                              \
+  }
+
+///////////////////////////////////////////////////////////////////////////////
+// Helpers for implementing a concrete nsCycleCollectionParticipant 
+///////////////////////////////////////////////////////////////////////////////
+
+#define NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(_class, _base)                \
+class NS_CYCLE_COLLECTION_INNERCLASS                                           \
+ : public nsXPCOMCycleCollectionParticipant                                    \
+{                                                                              \
+public:                                                                        \
+  NS_IMETHOD Unlink(void *p);                                                  \
+  NS_IMETHOD Traverse(void *p,                                                 \
+                      nsCycleCollectionTraversalCallback &cb);                 \
+  NS_IMETHOD_(void) UnmarkPurple(nsISupports *s)                               \
+  {                                                                            \
+    Downcast(s)->UnmarkPurple();                                               \
+  }                                                                            \
+  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(_class)                                 \
+  NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(_class, _class)
+
+#define NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(_class, _base_class)          \
+class NS_CYCLE_COLLECTION_INNERCLASS                                           \
+ : public NS_CYCLE_COLLECTION_CLASSNAME(_base_class)                           \
+{                                                                              \
+public:                                                                        \
+  NS_IMETHOD Unlink(void *p);                                                  \
+  NS_IMETHOD Traverse(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_NO_UNLINK(_class,             \
+                                                           _base_class)        \
+class NS_CYCLE_COLLECTION_INNERCLASS                                           \
+ : public NS_CYCLE_COLLECTION_CLASSNAME(_base_class)                           \
+{                                                                              \
+public:                                                                        \
+  NS_IMETHOD Traverse(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)));               \
+  }                                                                            \
+};
+
+/**
+ * This implements a stub UnmarkPurple 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) UnmarkPurple()                                          \
+  {                                                                            \
+  }                                                                            \
+
+#define NS_IMPL_CYCLE_COLLECTION_CLASS(_class)                                 \
+  static NS_CYCLE_COLLECTION_CLASSNAME(_class)                                 \
+    NS_CYCLE_COLLECTION_NAME(_class);
+
+#define NS_CYCLE_COLLECTION_NATIVE_INNERNAME                                   \
+        _cycleCollectorGlobal
+
+#define NS_CYCLE_COLLECTION_NATIVE_NAME(_class)                                \
+        _class::NS_CYCLE_COLLECTION_NATIVE_INNERNAME
+
+#define NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(_class)                          \
+  class NS_CYCLE_COLLECTION_INNERCLASS                                         \
+   : public nsCycleCollectionParticipant                                       \
+  {                                                                            \
+  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_CYCLE_COLLECTION_INNERCLASS                                        \
+      NS_CYCLE_COLLECTION_NATIVE_INNERNAME;
+
+#define NS_IMPL_CYCLE_COLLECTION_NATIVE_CLASS(_class)                          \
+  NS_CYCLE_COLLECTION_CLASSNAME(_class) NS_CYCLE_COLLECTION_NATIVE_NAME(_class);
+
+#define NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(_class, _root_function)           \
+  NS_IMETHODIMP                                                                \
+  NS_CYCLE_COLLECTION_CLASSNAME(_class)::Root(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)                       \
+  {                                                                            \
+    _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)                                        \
+ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(_class)                                 \
+ NS_IMPL_CYCLE_COLLECTION_UNLINK_END                                           \
+ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(_class)                               \
+ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+
+#define NS_IMPL_CYCLE_COLLECTION_1(_class, _f)                                 \
+ NS_IMPL_CYCLE_COLLECTION_CLASS(_class)                                        \
+ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(_class)                                 \
+ NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(_f)                                  \
+ NS_IMPL_CYCLE_COLLECTION_UNLINK_END                                           \
+ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(_class)                               \
+ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(_f)                                \
+ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+
+#define NS_IMPL_CYCLE_COLLECTION_2(_class, _f1, _f2)                           \
+ NS_IMPL_CYCLE_COLLECTION_CLASS(_class)                                        \
+ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(_class)                                 \
+ NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(_f1)                                 \
+ NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(_f2)                                 \
+ NS_IMPL_CYCLE_COLLECTION_UNLINK_END                                           \
+ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(_class)                               \
+ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(_f1)                               \
+ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(_f2)                               \
+ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+
+#define NS_IMPL_CYCLE_COLLECTION_3(_class, _f1, _f2, _f3)                      \
+ NS_IMPL_CYCLE_COLLECTION_CLASS(_class)                                        \
+ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(_class)                                 \
+ NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(_f1)                                 \
+ NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(_f2)                                 \
+ NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(_f3)                                 \
+ NS_IMPL_CYCLE_COLLECTION_UNLINK_END                                           \
+ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(_class)                               \
+ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(_f1)                               \
+ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(_f2)                               \
+ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(_f3)                               \
+ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+
+#endif // nsCycleCollectionParticipant_h__
--- a/xpcom/glue/nsISupportsImpl.h
+++ b/xpcom/glue/nsISupportsImpl.h
@@ -129,17 +129,17 @@ public:
       return 2;
     }
 
     nsrefcnt tmp = get();
     PRBool purple = static_cast<PRBool>(NS_PURPLE_BIT_SET(mValue));
 
     if (NS_UNLIKELY(purple)) {
       NS_ASSERTION(tmp != 0, "purple ISupports pointer with zero refcnt");
-      if (!nsCycleCollector_forget(owner))
+      if (!NS_CycleCollectorForget(owner))
         tmp |= NS_PURPLE_BIT;
     }
 
     mValue = tmp + 1;
     return mValue;
   }
 
   void stabilizeForDeletion(nsISupports *owner)
@@ -154,20 +154,20 @@ public:
 
     nsrefcnt tmp = get();
     NS_ASSERTION(tmp >= 1, "decr() called with zero refcnt");
 
     PRBool purple = static_cast<PRBool>(NS_PURPLE_BIT_SET(mValue));
     PRBool shouldBePurple = tmp > 1;
 
     if (NS_UNLIKELY(shouldBePurple && !purple)) {
-      if (!nsCycleCollector_suspect(owner))
+      if (!NS_CycleCollectorSuspect(owner))
         shouldBePurple = PR_FALSE;
     } else if (NS_UNLIKELY(tmp == 1 && purple)) {
-      if (!nsCycleCollector_forget(owner)) {
+      if (!NS_CycleCollectorForget(owner)) {
         NS_NOTREACHED("forget should not fail when reference count hits 0");
       }
     }
 
     --tmp;
 
     if (shouldBePurple)
       mValue = tmp | NS_PURPLE_BIT;
--- a/xpcom/glue/objs.mk
+++ b/xpcom/glue/objs.mk
@@ -58,16 +58,17 @@ XPCOM_GLUE_SRC_LCPPSRCS =        \
   nsGREGlue.cpp                  \
   nsVersionComparator.cpp        \
   nsTHashtable.cpp               \
   nsQuickSort.cpp                \
   nsVoidArray.cpp                \
   nsTArray.cpp                   \
   nsThreadUtils.cpp              \
   nsTObserverArray.cpp           \
+  nsCycleCollectionParticipant.cpp \
   $(NULL)
 
 XPCOM_GLUE_SRC_CPPSRCS = $(addprefix $(topsrcdir)/xpcom/glue/, $(XPCOM_GLUE_SRC_LCPPSRCS))
 
 # nsGenericFactory is not really all that helpful in the standalone glue,
 # and it has a bad dependency on the NSPR AtomicIncrement function, so we
 # only build it for the dependent XPCOM glue and builtin to xpcom-core.
 
--- a/xpcom/glue/standalone/nsXPCOMGlue.cpp
+++ b/xpcom/glue/standalone/nsXPCOMGlue.cpp
@@ -512,8 +512,26 @@ NS_InvokeByIndex(nsISupports* that, PRUi
                  PRUint32 paramCount, nsXPTCVariant* params)
 {
     if (!xpcomFunctions.invokeByIndexFunc)
         return NS_ERROR_NOT_INITIALIZED;
 
     return xpcomFunctions.invokeByIndexFunc(that, methodIndex,
                                             paramCount, params);
 }
+
+XPCOM_API(PRBool)
+NS_CycleCollectorSuspect(nsISupports* obj)
+{
+    if (!xpcomFunctions.cycleSuspectFunc)
+        return PR_FALSE;
+
+    return xpcomFunctions.cycleSuspectFunc(obj);
+}
+
+XPCOM_API(PRBool)
+NS_CycleCollectorForget(nsISupports* obj)
+{
+    if (!xpcomFunctions.cycleForgetFunc)
+        return PR_FALSE;
+
+    return xpcomFunctions.cycleForgetFunc(obj);
+}
--- a/xpcom/stub/nsXPComStub.cpp
+++ b/xpcom/stub/nsXPComStub.cpp
@@ -109,17 +109,19 @@ static const XPCOMFunctions kFrozenFunct
     &NS_LogAddRef_P,
     &NS_LogRelease_P,
     &NS_LogCtor_P,
     &NS_LogDtor_P,
     &NS_LogCOMPtrAddRef_P,
     &NS_LogCOMPtrRelease_P,
     &NS_GetXPTCallStub_P,
     &NS_DestroyXPTCallStub_P,
-    &NS_InvokeByIndex_P
+    &NS_InvokeByIndex_P,
+    &NS_CycleCollectorSuspect_P,
+    &NS_CycleCollectorForget_P
 };
 
 EXPORT_XPCOM_API(nsresult)
 NS_GetFrozenFunctions(XPCOMFunctions *functions, const char* /* libraryPath */)
 {
     if (!functions)
         return NS_ERROR_OUT_OF_MEMORY;
 
@@ -500,8 +502,22 @@ NS_CStringToUTF16(const nsACString &aSrc
 }
 
 #undef NS_UTF16ToCString
 EXPORT_XPCOM_API(nsresult)
 NS_UTF16ToCString(const nsAString &aSrc, nsCStringEncoding aDestEncoding, nsACString &aDest)
 {
   return NS_UTF16ToCString_P(aSrc, aDestEncoding, aDest);
 }
+
+#undef NS_CycleCollectorSuspect
+EXPORT_XPCOM_API(PRBool)
+NS_CycleCollectorSuspect(nsISupports* obj)
+{
+  return NS_CycleCollectorSuspect_P(obj);
+}
+
+#undef NS_CycleCollectorForget
+EXPORT_XPCOM_API(PRBool)
+NS_CycleCollectorForget(nsISupports* obj)
+{
+  return NS_CycleCollectorForget_P(obj);
+}