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