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.

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

mercurial