Bug 750570, part 1 - lift UnmarkIfPurple to the root CC participant. r=glandium,smaug
authorAndrew McCreight <amccreight@mozilla.com>
Fri, 24 Aug 2012 09:50:06 -0700
changeset 105347 786f414ea72681508af57225d8b2082332cdc758
parent 105346 88d90921b34838c4d4e880f80b987ebf819a3c20
child 105348 9077df78db40c7cf71f564831e66673be1e49e05
push id55
push usershu@rfrn.org
push dateThu, 30 Aug 2012 01:33:09 +0000
reviewersglandium, smaug
bugs750570
milestone17.0a1
Bug 750570, part 1 - lift UnmarkIfPurple to the root CC participant. r=glandium,smaug All CC classes are potentially cycle collectable, so we need to implement this function on the participant for all CC classes.
js/xpconnect/src/nsXPConnect.cpp
xpcom/base/nsAgg.h
xpcom/glue/nsCycleCollectionParticipant.cpp
xpcom/glue/nsCycleCollectionParticipant.h
--- a/js/xpconnect/src/nsXPConnect.cpp
+++ b/js/xpconnect/src/nsXPConnect.cpp
@@ -548,16 +548,19 @@ public:
     static NS_METHOD UnlinkImpl(void *n)
     {
         return NS_OK;
     }
     static NS_METHOD UnrootImpl(void *n)
     {
         return NS_OK;
     }
+    static NS_METHOD_(void) UnmarkIfPurpleImpl(void *n)
+    {
+    }
     static NS_METHOD TraverseImpl(nsXPConnectParticipant *that, void *n,
                                   nsCycleCollectionTraversalCallback &cb);
 };
 
 static const CCParticipantVTable<nsXPConnectParticipant>::Type
 XPConnect_cycleCollectorGlobal =
 {
   NS_IMPL_CYCLE_COLLECTION_NATIVE_VTABLE(nsXPConnectParticipant)
@@ -918,16 +921,19 @@ public:
         NS_ASSERTION(JS_GetGlobalObject(cx), "global object NULL before unlinking");
         JS_SetGlobalObject(cx, NULL);
         return NS_OK;
     }
     static NS_METHOD UnrootImpl(void *n)
     {
         return NS_OK;
     }
+    static NS_METHOD_(void) UnmarkIfPurpleImpl(void *n)
+    {
+    }
     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
@@ -2688,16 +2694,20 @@ public:
     {
         return NS_OK;
     }
 
     static NS_METHOD UnrootImpl(void *p)
     {
         return NS_OK;
     }
+
+    static NS_METHOD_(void) UnmarkIfPurpleImpl(void *n)
+    {
+    }
 };
 
 static const CCParticipantVTable<JSCompartmentParticipant>::Type
 JSCompartment_cycleCollectorGlobal = {
     NS_IMPL_CYCLE_COLLECTION_NATIVE_VTABLE(JSCompartmentParticipant)
 };
 
 nsCycleCollectionParticipant *
--- a/xpcom/base/nsAgg.h
+++ b/xpcom/base/nsAgg.h
@@ -71,19 +71,19 @@ public:                                 
 class NS_CYCLE_COLLECTION_INNERCLASS                                        \
  : public nsXPCOMCycleCollectionParticipant                                 \
 {                                                                           \
 public:                                                                     \
   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)                \
+  static NS_METHOD_(void) UnmarkIfPurpleImpl(void *p)                       \
   {                                                                         \
-    Downcast(p)->UnmarkIfPurple();                                          \
+    Downcast(static_cast<nsISupports *>(p))->UnmarkIfPurple();              \
   }                                                                         \
   static _class* Downcast(nsISupports* s)                                   \
   {                                                                         \
     return (_class*)((char*)(s) - offsetof(_class, fAggregated));           \
   }                                                                         \
   static nsISupports* Upcast(_class *p)                                     \
   {                                                                         \
     return p->InnerObject();                                                \
--- a/xpcom/glue/nsCycleCollectionParticipant.cpp
+++ b/xpcom/glue/nsCycleCollectionParticipant.cpp
@@ -20,42 +20,25 @@ nsresult
 nsXPCOMCycleCollectionParticipant::RootImpl(void *p)
 {
     nsISupports *s = static_cast<nsISupports*>(p);
     NS_ADDREF(s);
     return NS_OK;
 }
 
 nsresult
-nsXPCOMCycleCollectionParticipant::UnlinkImpl(void *p)
-{
-  return NS_OK;
-}
-
-nsresult
 nsXPCOMCycleCollectionParticipant::UnrootImpl(void *p)
 {
     nsISupports *s = static_cast<nsISupports*>(p);
     NS_RELEASE(s);
     return NS_OK;
 }
 
-nsresult
-nsXPCOMCycleCollectionParticipant::TraverseImpl
-    (nsXPCOMCycleCollectionParticipant* that, void *p,
-     nsCycleCollectionTraversalCallback &cb)
-{
-  return NS_OK;
-}
-
-void
-nsXPCOMCycleCollectionParticipant::UnmarkIfPurpleImpl(nsISupports *n)
-{
-}
-
+// We define a default trace function because some participants don't need
+// to trace anything, so it is okay for them not to define one.
 NS_IMETHODIMP_(void)
 nsXPCOMCycleCollectionParticipant::TraceImpl(void *p, TraceCallback cb,
                                              void *closure)
 {
 }
 
 bool
 nsXPCOMCycleCollectionParticipant::CheckForRightISupports(nsISupports *s)
--- a/xpcom/glue/nsCycleCollectionParticipant.h
+++ b/xpcom/glue/nsCycleCollectionParticipant.h
@@ -138,36 +138,32 @@ struct nsCycleCollectionParticipantVTabl
 {
     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);
 
+    void (NS_STDCALL *UnmarkIfPurple)(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 = {{...} ...};
@@ -227,17 +223,16 @@ struct CCParticipantVTableImpl<T, eXPCOM
 {
     nsXPCOMCycleCollectionParticipant *GetParticipant() const
     {
         return const_cast<nsXPCOMCycleCollectionParticipant *>
                (reinterpret_cast<const 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 :
@@ -293,31 +288,24 @@ NS_DEFINE_STATIC_IID_ACCESSOR(nsCycleCol
 class nsScriptObjectTracer
     : public nsCycleCollectionParticipant, public nsScriptObjectTracerVTable
 {
 public:
     static void NS_COM_GLUE NoteJSChild(void *aScriptThing, const char *name,
                                         void *aClosure);
 };
 
-class nsXPCOMCycleCollectionParticipant
-    : public nsScriptObjectTracer, public nsXPCOMCycleCollectionParticipantVTable
+class nsXPCOMCycleCollectionParticipant : public nsScriptObjectTracer
 {
 public:
-    static NS_METHOD TraverseImpl(nsXPCOMCycleCollectionParticipant *that,
-                                  void *p, nsCycleCollectionTraversalCallback &cb);
-
     static NS_METHOD RootImpl(void *p);
-    static NS_METHOD UnlinkImpl(void *p);
     static NS_METHOD UnrootImpl(void *p);
 
     static NS_METHOD_(void) TraceImpl(void *p, TraceCallback cb, void *closure);
 
-    static NS_METHOD_(void) UnmarkIfPurpleImpl(nsISupports *p);
-
     static bool CheckForRightISupports(nsISupports *s);
 };
 
 ///////////////////////////////////////////////////////////////////////////////
 // Helpers for implementing a QI to nsXPCOMCycleCollectionParticipant
 ///////////////////////////////////////////////////////////////////////////////
 
 #define NS_CYCLE_COLLECTION_INNERCLASS                                         \
@@ -670,19 +658,19 @@ public:
 #define NS_CYCLE_COLLECTION_PARTICIPANT_INSTANCE                               \
   static const CCParticipantVTable<NS_CYCLE_COLLECTION_INNERCLASS>::Type       \
       NS_CYCLE_COLLECTION_INNERNAME;
 
 #define NS_DECL_CYCLE_COLLECTION_CLASS_BODY_NO_UNLINK(_class, _base)           \
 public:                                                                        \
   static NS_METHOD TraverseImpl(NS_CYCLE_COLLECTION_CLASSNAME(_class) *that,   \
                             void *p, nsCycleCollectionTraversalCallback &cb);  \
-  static NS_METHOD_(void) UnmarkIfPurpleImpl(nsISupports *s)                   \
+  static NS_METHOD_(void) UnmarkIfPurpleImpl(void *s)                          \
   {                                                                            \
-    Downcast(s)->UnmarkIfPurple();                                             \
+    Downcast(static_cast<nsISupports *>(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);                                       \
@@ -714,39 +702,16 @@ class NS_CYCLE_COLLECTION_INNERCLASS    
   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)                \
-  static NS_METHOD RootImpl(void *p)                                           \
-  {                                                                            \
-    return NS_OK;                                                              \
-  }                                                                            \
-  static NS_METHOD UnlinkImpl(void *p)                                         \
-  {                                                                            \
-    return NS_OK;                                                              \
-  }                                                                            \
-  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)                           \
   static NS_METHOD_(void) TraceImpl(void *p, TraceCallback cb, void *closure); \
 };                                                                             \
 NS_CYCLE_COLLECTION_PARTICIPANT_INSTANCE
@@ -857,55 +822,65 @@ struct SkippableDummy
  * 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
 { };
 
+
+// VTables for the cycle collector participant implementations.
+
 #define NS_IMPL_CYCLE_COLLECTION_NATIVE_VTABLE(_class)                         \
   {                                                                            \
     &_class::TraverseImpl,                                                     \
     &_class::RootImpl,                                                         \
     &_class::UnlinkImpl,                                                       \
     &_class::UnrootImpl,                                                       \
+    &_class::UnmarkIfPurpleImpl,                                               \
     _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 }
+  NS_IMPL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_VTABLE(_class)
+
+
+// Cycle collector participant implementations.
 
 #define NS_IMPL_CYCLE_COLLECTION_NATIVE_CLASS(_class)                          \
   const 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)            \
   const 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)                                 \
   const CCParticipantVTable<NS_CYCLE_COLLECTION_CLASSNAME(_class)>             \
     ::Type _class::NS_CYCLE_COLLECTION_INNERNAME =                             \
   { NS_IMPL_CYCLE_COLLECTION_VTABLE(NS_CYCLE_COLLECTION_CLASSNAME(_class)) };
 
+
+// Cycle collector participant declarations.
+
 #define NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS_BODY(_class)                     \
   public:                                                                      \
     static NS_METHOD RootImpl(void *n);                                        \
     static NS_METHOD UnlinkImpl(void *n);                                      \
     static NS_METHOD UnrootImpl(void *n);                                      \
+    static NS_METHOD_(void) UnmarkIfPurpleImpl(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(_class)                        \