xpcom/glue/nsCycleCollectionParticipant.h

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

     1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 #ifndef nsCycleCollectionParticipant_h__
     7 #define nsCycleCollectionParticipant_h__
     9 #include "mozilla/MacroArgs.h"
    10 #include "mozilla/MacroForEach.h"
    11 #include "nsCycleCollectionNoteChild.h"
    12 #include "js/RootingAPI.h"
    14 #define NS_XPCOMCYCLECOLLECTIONPARTICIPANT_IID                                 \
    15 {                                                                              \
    16     0x9674489b,                                                                \
    17     0x1f6f,                                                                    \
    18     0x4550,                                                                    \
    19     { 0xa7, 0x30, 0xcc, 0xae, 0xdd, 0x10, 0x4c, 0xf9 }                         \
    20 }
    22 /**
    23  * Special IID to get at the base nsISupports for a class. Usually this is the
    24  * canonical nsISupports pointer, but in the case of tearoffs for example it is
    25  * the base nsISupports pointer of the tearoff. This allow the cycle collector
    26  * to have separate nsCycleCollectionParticipant's for tearoffs or aggregated
    27  * classes.
    28  */
    29 #define NS_CYCLECOLLECTIONISUPPORTS_IID                                        \
    30 {                                                                              \
    31     0xc61eac14,                                                                \
    32     0x5f7a,                                                                    \
    33     0x4481,                                                                    \
    34     { 0x96, 0x5e, 0x7e, 0xaa, 0x6e, 0xff, 0xa8, 0x5f }                         \
    35 }
    37 /**
    38  * Just holds the IID so NS_GET_IID works.
    39  */
    40 class nsCycleCollectionISupports
    41 {
    42 public:
    43     NS_DECLARE_STATIC_IID_ACCESSOR(NS_CYCLECOLLECTIONISUPPORTS_IID)
    44 };
    46 NS_DEFINE_STATIC_IID_ACCESSOR(nsCycleCollectionISupports,
    47                               NS_CYCLECOLLECTIONISUPPORTS_IID)
    49 namespace JS {
    50 template <class T> class Heap;
    51 } /* namespace JS */
    53 /*
    54  * A struct defining pure virtual methods which are called when tracing cycle
    55  * collection paticipants.  The appropriate method is called depending on the
    56  * type of JS GC thing.
    57  */
    58 struct TraceCallbacks
    59 {
    60     virtual void Trace(JS::Heap<JS::Value>* p, const char* name, void* closure) const = 0;
    61     virtual void Trace(JS::Heap<jsid>* p, const char* name, void* closure) const = 0;
    62     virtual void Trace(JS::Heap<JSObject*>* p, const char* name, void* closure) const = 0;
    63     virtual void Trace(JS::TenuredHeap<JSObject*>* p, const char* name, void* closure) const = 0;
    64     virtual void Trace(JS::Heap<JSString*>* p, const char* name, void* closure) const = 0;
    65     virtual void Trace(JS::Heap<JSScript*>* p, const char* name, void* closure) const = 0;
    66     virtual void Trace(JS::Heap<JSFunction*>* p, const char* name, void* closure) const = 0;
    67 };
    69 /*
    70  * An implementation of TraceCallbacks that calls a single function for all JS
    71  * GC thing types encountered.
    72  */
    73 struct TraceCallbackFunc : public TraceCallbacks
    74 {
    75     typedef void (* Func)(void* p, const char* name, void* closure);
    77     explicit TraceCallbackFunc(Func cb) : mCallback(cb) {}
    79     virtual void Trace(JS::Heap<JS::Value>* p, const char* name, void* closure) const MOZ_OVERRIDE;
    80     virtual void Trace(JS::Heap<jsid>* p, const char* name, void* closure) const MOZ_OVERRIDE;
    81     virtual void Trace(JS::Heap<JSObject*>* p, const char* name, void* closure) const MOZ_OVERRIDE;
    82     virtual void Trace(JS::TenuredHeap<JSObject*>* p, const char* name, void* closure) const MOZ_OVERRIDE;
    83     virtual void Trace(JS::Heap<JSString*>* p, const char* name, void* closure) const MOZ_OVERRIDE;
    84     virtual void Trace(JS::Heap<JSScript*>* p, const char* name, void* closure) const MOZ_OVERRIDE;
    85     virtual void Trace(JS::Heap<JSFunction*>* p, const char* name, void* closure) const MOZ_OVERRIDE;
    87   private:
    88     Func mCallback;
    89 };
    91 /**
    92  * Participant implementation classes
    93  */
    94 class NS_NO_VTABLE nsCycleCollectionParticipant
    95 {
    96 public:
    97     MOZ_CONSTEXPR nsCycleCollectionParticipant() : mMightSkip(false) {}
    98     MOZ_CONSTEXPR nsCycleCollectionParticipant(bool aSkip) : mMightSkip(aSkip) {}
   100     NS_IMETHOD Traverse(void *p, nsCycleCollectionTraversalCallback &cb) = 0;
   102     NS_IMETHOD_(void) Root(void *p) = 0;
   103     NS_IMETHOD_(void) Unlink(void *p) = 0;
   104     NS_IMETHOD_(void) Unroot(void *p) = 0;
   106     NS_IMETHOD_(void) Trace(void *p, const TraceCallbacks &cb, void *closure) {};
   108     // If CanSkip returns true, p is removed from the purple buffer during
   109     // a call to nsCycleCollector_forgetSkippable().
   110     // Note, calling CanSkip may remove objects from the purple buffer!
   111     // If aRemovingAllowed is true, p can be removed from the purple buffer.
   112     bool CanSkip(void *p, bool aRemovingAllowed)
   113     {
   114         return mMightSkip ? CanSkipReal(p, aRemovingAllowed) : false;
   115     }
   117     // If CanSkipInCC returns true, p is skipped when selecting roots for the
   118     // cycle collector graph.
   119     // Note, calling CanSkipInCC may remove other objects from the purple buffer!
   120     bool CanSkipInCC(void *p)
   121     {
   122         return mMightSkip ? CanSkipInCCReal(p) : false;
   123     }
   125     // If CanSkipThis returns true, p is not added to the graph.
   126     // This method is called during cycle collection, so don't
   127     // change the state of any objects!
   128     bool CanSkipThis(void *p)
   129     {
   130         return mMightSkip ? CanSkipThisReal(p) : false;
   131     }
   133     NS_IMETHOD_(void) DeleteCycleCollectable(void *n) = 0;
   135 protected:
   136     NS_IMETHOD_(bool) CanSkipReal(void *p, bool aRemovingAllowed)
   137     {
   138         NS_ASSERTION(false, "Forgot to implement CanSkipReal?");
   139         return false;
   140     }
   141     NS_IMETHOD_(bool) CanSkipInCCReal(void *p)
   142     {
   143         NS_ASSERTION(false, "Forgot to implement CanSkipInCCReal?");
   144         return false;
   145     }
   146     NS_IMETHOD_(bool) CanSkipThisReal(void *p)
   147     {
   148         NS_ASSERTION(false, "Forgot to implement CanSkipThisReal?");
   149         return false;
   150     }
   152 private:
   153     const bool mMightSkip;
   154 };
   156 class NS_NO_VTABLE nsScriptObjectTracer : public nsCycleCollectionParticipant
   157 {
   158 public:
   159     MOZ_CONSTEXPR nsScriptObjectTracer() : nsCycleCollectionParticipant(false) {}
   160     MOZ_CONSTEXPR nsScriptObjectTracer(bool aSkip) : nsCycleCollectionParticipant(aSkip) {}
   162     NS_IMETHOD_(void) Trace(void *p, const TraceCallbacks &cb, void *closure) = 0;
   164     static void NS_COM_GLUE NoteJSChild(void *aScriptThing, const char *name,
   165                                         void *aClosure);
   166 };
   168 class NS_NO_VTABLE nsXPCOMCycleCollectionParticipant : public nsScriptObjectTracer
   169 {
   170 public:
   171     MOZ_CONSTEXPR nsXPCOMCycleCollectionParticipant() : nsScriptObjectTracer(false) {}
   172     MOZ_CONSTEXPR nsXPCOMCycleCollectionParticipant(bool aSkip) : nsScriptObjectTracer(aSkip) {}
   174     NS_DECLARE_STATIC_IID_ACCESSOR(NS_XPCOMCYCLECOLLECTIONPARTICIPANT_IID)
   176     NS_IMETHOD_(void) Root(void *p);
   177     NS_IMETHOD_(void) Unroot(void *p);
   179     NS_IMETHOD_(void) Trace(void *p, const TraceCallbacks &cb, void *closure);
   181     static bool CheckForRightISupports(nsISupports *s);
   182 };
   184 NS_DEFINE_STATIC_IID_ACCESSOR(nsXPCOMCycleCollectionParticipant,
   185                               NS_XPCOMCYCLECOLLECTIONPARTICIPANT_IID)
   187 ///////////////////////////////////////////////////////////////////////////////
   188 // Helpers for implementing a QI to nsXPCOMCycleCollectionParticipant
   189 ///////////////////////////////////////////////////////////////////////////////
   191 #define NS_CYCLE_COLLECTION_CLASSNAME(_class)                                  \
   192         _class::NS_CYCLE_COLLECTION_INNERCLASS
   194 #define NS_IMPL_QUERY_CYCLE_COLLECTION(_class)                                 \
   195   if ( aIID.Equals(NS_GET_IID(nsXPCOMCycleCollectionParticipant)) ) {          \
   196     *aInstancePtr = NS_CYCLE_COLLECTION_PARTICIPANT(_class);                   \
   197     return NS_OK;                                                              \
   198   } else
   200 #define NS_IMPL_QUERY_CYCLE_COLLECTION_ISUPPORTS(_class)                       \
   201   if ( aIID.Equals(NS_GET_IID(nsCycleCollectionISupports)) ) {                 \
   202     *aInstancePtr = NS_CYCLE_COLLECTION_CLASSNAME(_class)::Upcast(this);       \
   203     return NS_OK;                                                              \
   204   } else
   206 #define NS_INTERFACE_MAP_ENTRY_CYCLE_COLLECTION(_class)                        \
   207   NS_IMPL_QUERY_CYCLE_COLLECTION(_class)
   209 #define NS_INTERFACE_MAP_ENTRY_CYCLE_COLLECTION_ISUPPORTS(_class)              \
   210   NS_IMPL_QUERY_CYCLE_COLLECTION_ISUPPORTS(_class)
   212 #define NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(_class)                      \
   213   NS_INTERFACE_MAP_ENTRY_CYCLE_COLLECTION(_class)                              \
   214   NS_INTERFACE_MAP_ENTRY_CYCLE_COLLECTION_ISUPPORTS(_class)
   216 #define NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(_class)                        \
   217   NS_INTERFACE_MAP_BEGIN(_class)                                               \
   218     NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(_class)
   220 #define NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(_class)              \
   221   NS_INTERFACE_MAP_BEGIN(_class)                                               \
   222     NS_INTERFACE_MAP_ENTRY_CYCLE_COLLECTION(_class)
   224 #define NS_INTERFACE_TABLE_TO_MAP_SEGUE_CYCLE_COLLECTION(_class)  \
   225   if (rv == NS_OK) return rv; \
   226   nsISupports* foundInterface; \
   227   NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(_class)
   229 #define NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(_class)            \
   230   NS_IMETHODIMP _class::QueryInterface(REFNSIID aIID, void** aInstancePtr)    \
   231   {                                                                           \
   232     NS_PRECONDITION(aInstancePtr, "null out param");                          \
   233                                                                               \
   234     if ( aIID.Equals(NS_GET_IID(nsXPCOMCycleCollectionParticipant)) ) {       \
   235       *aInstancePtr = NS_CYCLE_COLLECTION_PARTICIPANT(_class);                \
   236       return NS_OK;                                                           \
   237     }                                                                         \
   238     nsresult rv;
   240 #define NS_CYCLE_COLLECTION_UPCAST(obj, clazz)                                 \
   241   NS_CYCLE_COLLECTION_CLASSNAME(clazz)::Upcast(obj)
   243 #ifdef DEBUG
   244 #define NS_CHECK_FOR_RIGHT_PARTICIPANT(_ptr) _ptr->CheckForRightParticipant()
   245 #else
   246 #define NS_CHECK_FOR_RIGHT_PARTICIPANT(_ptr)
   247 #endif
   249 // The default implementation of this class template is empty, because it
   250 // should never be used: see the partial specializations below.
   251 template <typename T,
   252           bool IsXPCOM = mozilla::IsBaseOf<nsISupports, T>::value>
   253 struct DowncastCCParticipantImpl
   254 {
   255 };
   257 // Specialization for XPCOM CC participants
   258 template <typename T>
   259 struct DowncastCCParticipantImpl<T, true>
   260 {
   261   static T* Run(void *p)
   262   {
   263     nsISupports *s = static_cast<nsISupports*>(p);
   264     MOZ_ASSERT(NS_CYCLE_COLLECTION_CLASSNAME(T)::CheckForRightISupports(s),
   265                "not the nsISupports pointer we expect");
   266     T *rval =  NS_CYCLE_COLLECTION_CLASSNAME(T)::Downcast(s);
   267     NS_CHECK_FOR_RIGHT_PARTICIPANT(rval);
   268     return rval;
   269   }
   270 };
   272 // Specialization for native CC participants
   273 template <typename T>
   274 struct DowncastCCParticipantImpl<T, false>
   275 {
   276   static T* Run(void *p)
   277   {
   278     return static_cast<T*>(p);
   279   }
   280 };
   282 template <typename T>
   283 T* DowncastCCParticipant(void *p)
   284 {
   285   return DowncastCCParticipantImpl<T>::Run(p);
   286 }
   288 ///////////////////////////////////////////////////////////////////////////////
   289 // Helpers for implementing CanSkip methods
   290 ///////////////////////////////////////////////////////////////////////////////
   292 #define NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN(_class)                        \
   293   NS_IMETHODIMP_(bool)                                                         \
   294   NS_CYCLE_COLLECTION_CLASSNAME(_class)::CanSkipReal(void *p,                  \
   295                                                      bool aRemovingAllowed)    \
   296   {                                                                            \
   297     _class *tmp = DowncastCCParticipant<_class >(p);
   299 #define NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_END                                  \
   300     (void)tmp;                                                                 \
   301     return false;                                                              \
   302   }
   304 #define NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_BEGIN(_class)                  \
   305   NS_IMETHODIMP_(bool)                                                         \
   306   NS_CYCLE_COLLECTION_CLASSNAME(_class)::CanSkipInCCReal(void *p)              \
   307   {                                                                            \
   308     _class *tmp = DowncastCCParticipant<_class >(p);
   310 #define NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_END                            \
   311     (void)tmp;                                                                 \
   312     return false;                                                              \
   313   }
   315 #define NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_BEGIN(_class)                   \
   316   NS_IMETHODIMP_(bool)                                                         \
   317   NS_CYCLE_COLLECTION_CLASSNAME(_class)::CanSkipThisReal(void *p)              \
   318   {                                                                            \
   319     _class *tmp = DowncastCCParticipant<_class >(p);
   321 #define NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_END                             \
   322     (void)tmp;                                                                 \
   323     return false;                                                              \
   324   }
   326 ///////////////////////////////////////////////////////////////////////////////
   327 // Helpers for implementing nsCycleCollectionParticipant::Unlink
   328 //
   329 // You need to use NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED if you want
   330 // the base class Unlink version to be called before your own implementation.
   331 // You can use NS_IMPL_CYCLE_COLLECTION_UNLINK_END_INHERITED if you want the
   332 // base class Unlink to get called after your own implementation.  You should
   333 // never use them together.
   334 ///////////////////////////////////////////////////////////////////////////////
   336 #define NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(_class)                          \
   337   NS_IMETHODIMP_(void)                                                         \
   338   NS_CYCLE_COLLECTION_CLASSNAME(_class)::Unlink(void *p)                       \
   339   {                                                                            \
   340     _class *tmp = DowncastCCParticipant<_class >(p);
   342 #define NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(_class, _base_class)   \
   343   NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(_class)                                \
   344     nsISupports *s = static_cast<nsISupports*>(p);                             \
   345     NS_CYCLE_COLLECTION_CLASSNAME(_base_class)::Unlink(s);
   347 #define NS_IMPL_CYCLE_COLLECTION_UNLINK_HELPER(_field)                        \
   348   ImplCycleCollectionUnlink(tmp->_field);
   350 #define NS_IMPL_CYCLE_COLLECTION_UNLINK(...)                                   \
   351   MOZ_STATIC_ASSERT_VALID_ARG_COUNT(__VA_ARGS__);                              \
   352   MOZ_FOR_EACH(NS_IMPL_CYCLE_COLLECTION_UNLINK_HELPER, (), (__VA_ARGS__))
   354 #define NS_IMPL_CYCLE_COLLECTION_UNLINK_END                                    \
   355     (void)tmp;                                                                 \
   356   }
   358 #define NS_IMPL_CYCLE_COLLECTION_UNLINK_END_INHERITED(_base_class)             \
   359     nsISupports *s = static_cast<nsISupports*>(p);                             \
   360     NS_CYCLE_COLLECTION_CLASSNAME(_base_class)::Unlink(s);                     \
   361     (void)tmp;                                                                 \
   362   }
   364 #define NS_IMPL_CYCLE_COLLECTION_UNLINK_0(_class)                              \
   365   NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(_class)                                \
   366   NS_IMPL_CYCLE_COLLECTION_UNLINK_END
   369 ///////////////////////////////////////////////////////////////////////////////
   370 // Helpers for implementing nsCycleCollectionParticipant::Traverse
   371 ///////////////////////////////////////////////////////////////////////////////
   373 #define NS_IMPL_CYCLE_COLLECTION_DESCRIBE(_class, _refcnt)                     \
   374     cb.DescribeRefCountedNode(_refcnt, #_class);
   376 #define NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(_class)               \
   377   NS_IMETHODIMP                                                                \
   378   NS_CYCLE_COLLECTION_CLASSNAME(_class)::Traverse                              \
   379                          (void *p, nsCycleCollectionTraversalCallback &cb)     \
   380   {                                                                            \
   381     _class *tmp = DowncastCCParticipant<_class >(p);
   383 #define NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(_class)                        \
   384   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(_class)                     \
   385   NS_IMPL_CYCLE_COLLECTION_DESCRIBE(_class, tmp->mRefCnt.get())
   387 // Base class' CC participant should return NS_SUCCESS_INTERRUPTED_TRAVERSE
   388 // from Traverse if it wants derived classes to not traverse anything from
   389 // their CC participant.
   391 #define NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(_class, _base_class) \
   392   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(_class)                     \
   393     nsISupports *s = static_cast<nsISupports*>(p);                             \
   394     if (NS_CYCLE_COLLECTION_CLASSNAME(_base_class)::Traverse(s, cb)            \
   395         == NS_SUCCESS_INTERRUPTED_TRAVERSE) {                                  \
   396       return NS_SUCCESS_INTERRUPTED_TRAVERSE;                                  \
   397     }
   399 #define NS_IMPL_CYCLE_COLLECTION_TRAVERSE_HELPER(_field)                       \
   400   ImplCycleCollectionTraverse(cb, tmp->_field, #_field, 0);
   402 #define NS_IMPL_CYCLE_COLLECTION_TRAVERSE(...)                                 \
   403   MOZ_STATIC_ASSERT_VALID_ARG_COUNT(__VA_ARGS__);                              \
   404   MOZ_FOR_EACH(NS_IMPL_CYCLE_COLLECTION_TRAVERSE_HELPER, (), (__VA_ARGS__))
   406 #define NS_IMPL_CYCLE_COLLECTION_TRAVERSE_RAWPTR(_field)                       \
   407   CycleCollectionNoteChild(cb, tmp->_field, #_field);
   409 #define NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS                       \
   410   {                                                                            \
   411   TraceCallbackFunc noteJsChild(&nsScriptObjectTracer::NoteJSChild);           \
   412   Trace(p, noteJsChild, &cb);                                                  \
   413   }
   415 #define NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END                                  \
   416     (void)tmp;                                                                 \
   417     return NS_OK;                                                              \
   418   }
   420 ///////////////////////////////////////////////////////////////////////////////
   421 // Helpers for implementing nsScriptObjectTracer::Trace
   422 ///////////////////////////////////////////////////////////////////////////////
   424 #define NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(_class)                                 \
   425   void                                                                               \
   426   NS_CYCLE_COLLECTION_CLASSNAME(_class)::Trace(void *p,                              \
   427                                                const TraceCallbacks &aCallbacks,     \
   428                                                void *aClosure)                       \
   429   {                                                                                  \
   430     _class *tmp = DowncastCCParticipant<_class >(p);
   432 #define NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(_class, _base_class)    \
   433   NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(_class)                                 \
   434     nsISupports *s = static_cast<nsISupports*>(p);                             \
   435     NS_CYCLE_COLLECTION_CLASSNAME(_base_class)::Trace(s, aCallbacks, aClosure);
   437 #define NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(_field)              \
   438   if (tmp->_field)                                                             \
   439     aCallbacks.Trace(&tmp->_field, #_field, aClosure);
   441 #define NS_IMPL_CYCLE_COLLECTION_TRACE_JSVAL_MEMBER_CALLBACK(_field)           \
   442   aCallbacks.Trace(&tmp->_field, #_field, aClosure);
   444 // NB: The (void)tmp; hack in the TRACE_END macro exists to support
   445 // implementations that don't need to do anything in their Trace method.
   446 // Without this hack, some compilers warn about the unused tmp local.
   447 #define NS_IMPL_CYCLE_COLLECTION_TRACE_END                                     \
   448       (void)tmp;                                                               \
   449   }
   451 ///////////////////////////////////////////////////////////////////////////////
   452 // Helpers for implementing a concrete nsCycleCollectionParticipant
   453 ///////////////////////////////////////////////////////////////////////////////
   455 // If a class defines a participant, then QIing an instance of that class to
   456 // nsXPCOMCycleCollectionParticipant should produce that participant.
   457 #ifdef DEBUG
   458 #define NS_CHECK_FOR_RIGHT_PARTICIPANT_IMPL(_class)                            \
   459     virtual void CheckForRightParticipant()                                    \
   460     {                                                                          \
   461       nsXPCOMCycleCollectionParticipant *p;                                    \
   462       CallQueryInterface(this, &p);                                            \
   463       MOZ_ASSERT(p == &NS_CYCLE_COLLECTION_INNERNAME,                          \
   464                  #_class " should QI to its own CC participant");              \
   465     }
   466 #else
   467 #define NS_CHECK_FOR_RIGHT_PARTICIPANT_IMPL(_class)
   468 #endif
   470 #define NS_DECL_CYCLE_COLLECTION_CLASS_BODY_NO_UNLINK(_class, _base)           \
   471 public:                                                                        \
   472   NS_IMETHOD Traverse(void *p, nsCycleCollectionTraversalCallback &cb);        \
   473   NS_IMETHOD_(void) DeleteCycleCollectable(void *p)                            \
   474   {                                                                            \
   475     DowncastCCParticipant<_class>(p)->DeleteCycleCollectable();                \
   476   }                                                                            \
   477   static _class* Downcast(nsISupports* s)                                      \
   478   {                                                                            \
   479     return static_cast<_class*>(static_cast<_base*>(s));                       \
   480   }                                                                            \
   481   static nsISupports* Upcast(_class *p)                                        \
   482   {                                                                            \
   483     return NS_ISUPPORTS_CAST(_base*, p);                                       \
   484   }                                                                            \
   485   template <typename T>                                                        \
   486   friend nsISupports*                                                          \
   487   ToSupports(T* p, NS_CYCLE_COLLECTION_INNERCLASS* dummy);
   489 #define NS_DECL_CYCLE_COLLECTION_CLASS_BODY(_class, _base)                     \
   490   NS_DECL_CYCLE_COLLECTION_CLASS_BODY_NO_UNLINK(_class, _base)                 \
   491   NS_IMETHOD_(void) Unlink(void *p);
   493 #define NS_PARTICIPANT_AS(type, participant)                                   \
   494   const_cast<type*>(reinterpret_cast<const type*>(participant))
   496 #define NS_IMPL_GET_XPCOM_CYCLE_COLLECTION_PARTICIPANT(_class)                 \
   497   static MOZ_CONSTEXPR nsXPCOMCycleCollectionParticipant* GetParticipant()     \
   498   {                                                                            \
   499     return &_class::NS_CYCLE_COLLECTION_INNERNAME;                             \
   500   }
   502 /**
   503  * We use this macro to force that classes that inherit from a ccable class and
   504  * declare their own participant declare themselves as inherited cc classes.
   505  * To avoid possibly unnecessary vtables we only do this checking in debug
   506  * builds.
   507  */
   508 #ifdef DEBUG
   509 #define NOT_INHERITED_CANT_OVERRIDE virtual void BaseCycleCollectable() MOZ_FINAL {}
   510 #else
   511 #define NOT_INHERITED_CANT_OVERRIDE
   512 #endif
   514 #define NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(_class, _base)                \
   515 class NS_CYCLE_COLLECTION_INNERCLASS                                           \
   516  : public nsXPCOMCycleCollectionParticipant                                    \
   517 {                                                                              \
   518   NS_DECL_CYCLE_COLLECTION_CLASS_BODY(_class, _base)                           \
   519   NS_IMPL_GET_XPCOM_CYCLE_COLLECTION_PARTICIPANT(_class)                       \
   520 };                                                                             \
   521 NS_CHECK_FOR_RIGHT_PARTICIPANT_IMPL(_class)                                    \
   522 static NS_CYCLE_COLLECTION_INNERCLASS NS_CYCLE_COLLECTION_INNERNAME;           \
   523   NOT_INHERITED_CANT_OVERRIDE
   525 #define NS_DECL_CYCLE_COLLECTION_CLASS(_class)                                 \
   526   NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(_class, _class)
   528 // Cycle collector helper for ambiguous classes that can sometimes be skipped.
   529 #define NS_DECL_CYCLE_COLLECTION_SKIPPABLE_CLASS_AMBIGUOUS(_class, _base)        \
   530 class NS_CYCLE_COLLECTION_INNERCLASS                                             \
   531  : public nsXPCOMCycleCollectionParticipant                                      \
   532 {                                                                                \
   533 public:                                                                          \
   534   MOZ_CONSTEXPR NS_CYCLE_COLLECTION_INNERCLASS ()                                \
   535   : nsXPCOMCycleCollectionParticipant(true) {}                                   \
   536 private:                                                                         \
   537   NS_DECL_CYCLE_COLLECTION_CLASS_BODY(_class, _base)                             \
   538   NS_IMETHOD_(bool) CanSkipReal(void *p, bool aRemovingAllowed);                 \
   539   NS_IMETHOD_(bool) CanSkipInCCReal(void *p);                                    \
   540   NS_IMETHOD_(bool) CanSkipThisReal(void *p);                                    \
   541   NS_IMPL_GET_XPCOM_CYCLE_COLLECTION_PARTICIPANT(_class)                         \
   542 };                                                                               \
   543 NS_CHECK_FOR_RIGHT_PARTICIPANT_IMPL(_class)                                      \
   544 static NS_CYCLE_COLLECTION_INNERCLASS NS_CYCLE_COLLECTION_INNERNAME;             \
   545 NOT_INHERITED_CANT_OVERRIDE
   547 #define NS_DECL_CYCLE_COLLECTION_SKIPPABLE_CLASS(_class)                       \
   548         NS_DECL_CYCLE_COLLECTION_SKIPPABLE_CLASS_AMBIGUOUS(_class, _class)
   550 #define NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(_class, _base)          \
   551 class NS_CYCLE_COLLECTION_INNERCLASS                                                   \
   552  : public nsXPCOMCycleCollectionParticipant                                            \
   553 {                                                                                      \
   554   NS_DECL_CYCLE_COLLECTION_CLASS_BODY(_class, _base)                                   \
   555   NS_IMETHOD_(void) Trace(void *p, const TraceCallbacks &cb, void *closure);           \
   556   NS_IMPL_GET_XPCOM_CYCLE_COLLECTION_PARTICIPANT(_class)                               \
   557 };                                                                                     \
   558 NS_CHECK_FOR_RIGHT_PARTICIPANT_IMPL(_class)                                            \
   559 static NS_CYCLE_COLLECTION_INNERCLASS NS_CYCLE_COLLECTION_INNERNAME; \
   560 NOT_INHERITED_CANT_OVERRIDE
   562 #define NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS_AMBIGUOUS(_class, _base)   \
   563 class NS_CYCLE_COLLECTION_INNERCLASS                                                      \
   564  : public nsXPCOMCycleCollectionParticipant                                               \
   565 {                                                                                         \
   566 public:                                                                                   \
   567   MOZ_CONSTEXPR NS_CYCLE_COLLECTION_INNERCLASS ()                                         \
   568   : nsXPCOMCycleCollectionParticipant(true) {}                                            \
   569 private:                                                                                  \
   570   NS_DECL_CYCLE_COLLECTION_CLASS_BODY(_class, _base)                                      \
   571   NS_IMETHOD_(void) Trace(void *p, const TraceCallbacks &cb, void *closure);              \
   572   NS_IMETHOD_(bool) CanSkipReal(void *p, bool aRemovingAllowed);                          \
   573   NS_IMETHOD_(bool) CanSkipInCCReal(void *p);                                             \
   574   NS_IMETHOD_(bool) CanSkipThisReal(void *p);                                             \
   575   NS_IMPL_GET_XPCOM_CYCLE_COLLECTION_PARTICIPANT(_class)                                  \
   576 };                                                                                        \
   577 NS_CHECK_FOR_RIGHT_PARTICIPANT_IMPL(_class)                                               \
   578 static NS_CYCLE_COLLECTION_INNERCLASS NS_CYCLE_COLLECTION_INNERNAME; \
   579 NOT_INHERITED_CANT_OVERRIDE
   581 #define NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS(_class)  \
   582   NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS_AMBIGUOUS(_class, _class)
   584 #define NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS_INHERITED(_class,       \
   585                                                                          _base_class)  \
   586 class NS_CYCLE_COLLECTION_INNERCLASS                                                   \
   587  : public NS_CYCLE_COLLECTION_CLASSNAME(_base_class)                                   \
   588 {                                                                                      \
   589   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_BODY(_class, _base_class)                   \
   590   NS_IMETHOD_(void) Trace(void *p, const TraceCallbacks &cb, void *closure);           \
   591   NS_IMETHOD_(bool) CanSkipReal(void *p, bool aRemovingAllowed);                       \
   592   NS_IMETHOD_(bool) CanSkipInCCReal(void *p);                                          \
   593   NS_IMETHOD_(bool) CanSkipThisReal(void *p);                                          \
   594   NS_IMPL_GET_XPCOM_CYCLE_COLLECTION_PARTICIPANT(_class)                               \
   595 }; \
   596 NS_CHECK_FOR_RIGHT_PARTICIPANT_IMPL(_class)  \
   597 static NS_CYCLE_COLLECTION_INNERCLASS NS_CYCLE_COLLECTION_INNERNAME;
   599 #define NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(_class)  \
   600   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(_class, _class)
   602 #define NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_BODY_NO_UNLINK(_class,        \
   603                                                                 _base_class)   \
   604 public:                                                                        \
   605   NS_IMETHOD Traverse(void *p, nsCycleCollectionTraversalCallback &cb);        \
   606   static _class* Downcast(nsISupports* s)                                      \
   607   {                                                                            \
   608     return static_cast<_class*>(static_cast<_base_class*>(                     \
   609       NS_CYCLE_COLLECTION_CLASSNAME(_base_class)::Downcast(s)));               \
   610   }
   612 #define NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_BODY(_class, _base_class)     \
   613   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_BODY_NO_UNLINK(_class, _base_class) \
   614   NS_IMETHOD_(void) Unlink(void *p);
   616 #define NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(_class, _base_class)          \
   617 class NS_CYCLE_COLLECTION_INNERCLASS                                           \
   618  : public NS_CYCLE_COLLECTION_CLASSNAME(_base_class)                           \
   619 {                                                                              \
   620 public:                                                                        \
   621   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_BODY(_class, _base_class)           \
   622   NS_IMPL_GET_XPCOM_CYCLE_COLLECTION_PARTICIPANT(_class)                       \
   623 };                                                                             \
   624 NS_CHECK_FOR_RIGHT_PARTICIPANT_IMPL(_class)                                    \
   625 static NS_CYCLE_COLLECTION_INNERCLASS NS_CYCLE_COLLECTION_INNERNAME;
   627 #define NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_NO_UNLINK(_class,             \
   628                                                            _base_class)        \
   629 class NS_CYCLE_COLLECTION_INNERCLASS                                           \
   630  : public NS_CYCLE_COLLECTION_CLASSNAME(_base_class)                           \
   631 {                                                                              \
   632 public:                                                                        \
   633   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_BODY_NO_UNLINK(_class, _base_class) \
   634   NS_IMPL_GET_XPCOM_CYCLE_COLLECTION_PARTICIPANT(_class)                       \
   635 };                                                                             \
   636 NS_CHECK_FOR_RIGHT_PARTICIPANT_IMPL(_class)                                    \
   637 static NS_CYCLE_COLLECTION_INNERCLASS NS_CYCLE_COLLECTION_INNERNAME;
   639 #define NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(_class,                 \
   640                                                                _base_class)            \
   641 class NS_CYCLE_COLLECTION_INNERCLASS                                                   \
   642  : public NS_CYCLE_COLLECTION_CLASSNAME(_base_class)                                   \
   643 {                                                                                      \
   644   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_BODY(_class, _base_class)                   \
   645   NS_IMETHOD_(void) Trace(void *p, const TraceCallbacks &cb, void *closure);           \
   646   NS_IMPL_GET_XPCOM_CYCLE_COLLECTION_PARTICIPANT(_class)                               \
   647 };                                                                                     \
   648 NS_CHECK_FOR_RIGHT_PARTICIPANT_IMPL(_class)                                            \
   649 static NS_CYCLE_COLLECTION_INNERCLASS NS_CYCLE_COLLECTION_INNERNAME;
   651 // Cycle collector participant declarations.
   653 #define NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS_BODY(_class)                     \
   654   public:                                                                      \
   655     NS_IMETHOD_(void) Root(void *n);                                           \
   656     NS_IMETHOD_(void) Unlink(void *n);                                         \
   657     NS_IMETHOD_(void) Unroot(void *n);                                         \
   658     NS_IMETHOD Traverse(void *n, nsCycleCollectionTraversalCallback &cb);      \
   659     NS_IMETHOD_(void) DeleteCycleCollectable(void *n)                          \
   660     {                                                                          \
   661       DowncastCCParticipant<_class>(n)->DeleteCycleCollectable();              \
   662     }                                                                          \
   663     static _class* Downcast(void* s)                                           \
   664     {                                                                          \
   665       return DowncastCCParticipant<_class>(s);                                 \
   666     }                                                                          \
   667     static void* Upcast(_class *p)                                             \
   668     {                                                                          \
   669       return static_cast<void*>(p);                                            \
   670     }
   672 #define NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(_class)                          \
   673   void DeleteCycleCollectable(void)                                            \
   674   {                                                                            \
   675     delete this;                                                               \
   676   }                                                                            \
   677   class NS_CYCLE_COLLECTION_INNERCLASS                                         \
   678    : public nsCycleCollectionParticipant                                       \
   679   {                                                                            \
   680     NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS_BODY(_class)                         \
   681     static MOZ_CONSTEXPR nsCycleCollectionParticipant* GetParticipant()        \
   682     {                                                                          \
   683       return &_class::NS_CYCLE_COLLECTION_INNERNAME;                           \
   684     }                                                                          \
   685   };                                                                           \
   686   static NS_CYCLE_COLLECTION_INNERCLASS NS_CYCLE_COLLECTION_INNERNAME;
   688 #define NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(_class)            \
   689   void DeleteCycleCollectable(void)                                            \
   690   {                                                                            \
   691     delete this;                                                               \
   692   }                                                                            \
   693   class NS_CYCLE_COLLECTION_INNERCLASS                                         \
   694    : public nsScriptObjectTracer                                               \
   695   {                                                                            \
   696     NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS_BODY(_class)                         \
   697     NS_IMETHOD_(void) Trace(void *p, const TraceCallbacks &cb, void *closure); \
   698     static MOZ_CONSTEXPR nsScriptObjectTracer* GetParticipant()                \
   699     {                                                                          \
   700       return &_class::NS_CYCLE_COLLECTION_INNERNAME;                           \
   701     }                                                                          \
   702   };                                                                           \
   703   static NS_CYCLE_COLLECTION_INNERCLASS NS_CYCLE_COLLECTION_INNERNAME;
   705 #define NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(_class, _root_function)           \
   706   NS_IMETHODIMP_(void)                                                         \
   707   NS_CYCLE_COLLECTION_CLASSNAME(_class)::Root(void *p)                         \
   708   {                                                                            \
   709     _class *tmp = static_cast<_class*>(p);                                     \
   710     tmp->_root_function();                                                     \
   711   }
   713 #define NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(_class, _unroot_function)       \
   714   NS_IMETHODIMP_(void)                                                         \
   715   NS_CYCLE_COLLECTION_CLASSNAME(_class)::Unroot(void *p)                       \
   716   {                                                                            \
   717     _class *tmp = static_cast<_class*>(p);                                     \
   718     tmp->_unroot_function();                                                   \
   719   }
   721 #define NS_IMPL_CYCLE_COLLECTION_CLASS(_class) \
   722  _class::NS_CYCLE_COLLECTION_INNERCLASS _class::NS_CYCLE_COLLECTION_INNERNAME;
   724 // NB: This is not something you usually want to use.  It is here to allow
   725 // adding things to the CC graph to help debugging via CC logs, but it does not
   726 // traverse or unlink anything, so it is useless for anything else.
   727 #define NS_IMPL_CYCLE_COLLECTION_0(_class)                                     \
   728   NS_IMPL_CYCLE_COLLECTION_CLASS(_class)                                       \
   729   NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(_class)                                \
   730   NS_IMPL_CYCLE_COLLECTION_UNLINK_END                                          \
   731   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(_class)                              \
   732   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
   734 #define NS_IMPL_CYCLE_COLLECTION(_class, ...)                                  \
   735   NS_IMPL_CYCLE_COLLECTION_CLASS(_class)                                       \
   736   NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(_class)                                \
   737   NS_IMPL_CYCLE_COLLECTION_UNLINK(__VA_ARGS__)                                 \
   738   NS_IMPL_CYCLE_COLLECTION_UNLINK_END                                          \
   739   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(_class)                              \
   740   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(__VA_ARGS__)                               \
   741   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
   743 #define NS_IMPL_CYCLE_COLLECTION_INHERITED(_class, _base, ...)                 \
   744   NS_IMPL_CYCLE_COLLECTION_CLASS(_class)                                       \
   745   NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(_class, _base)               \
   746   NS_IMPL_CYCLE_COLLECTION_UNLINK(__VA_ARGS__)                                 \
   747   NS_IMPL_CYCLE_COLLECTION_UNLINK_END                                          \
   748   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(_class, _base)             \
   749   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(__VA_ARGS__)                               \
   750   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
   752 #define NS_CYCLE_COLLECTION_NOTE_EDGE_NAME CycleCollectionNoteEdgeName
   754 #endif // nsCycleCollectionParticipant_h__

mercurial