Line data Source code
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 :
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 8853 : 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 :
87 5144 : 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 8 : class NS_NO_VTABLE nsCycleCollectionParticipant
114 : {
115 : public:
116 0 : constexpr explicit nsCycleCollectionParticipant(bool aSkip,
117 : bool aTraverseShouldTrace = false)
118 0 : : mMightSkip(aSkip)
119 0 : , mTraverseShouldTrace(aTraverseShouldTrace)
120 : {
121 0 : }
122 :
123 : NS_IMETHOD TraverseNative(void* aPtr, nsCycleCollectionTraversalCallback& aCb) = 0;
124 :
125 2572 : nsresult TraverseNativeAndJS(void* aPtr,
126 : nsCycleCollectionTraversalCallback& aCb)
127 : {
128 2572 : nsresult rv = TraverseNative(aPtr, aCb);
129 2572 : if (mTraverseShouldTrace) {
130 : // Note, we always call Trace, even if Traverse returned
131 : // NS_SUCCESS_INTERRUPTED_TRAVERSE.
132 2572 : TraceCallbackFunc noteJsChild(&nsCycleCollectionParticipant::NoteJSChild);
133 2572 : Trace(aPtr, noteJsChild, &aCb);
134 : }
135 2572 : return rv;
136 : }
137 :
138 : // Implemented in nsCycleCollectorTraceJSHelpers.cpp.
139 : static void NoteJSChild(JS::GCCellPtr aGCThing, const char* aName,
140 : void* aClosure);
141 :
142 : NS_IMETHOD_(void) Root(void* aPtr) = 0;
143 : NS_IMETHOD_(void) Unlink(void* aPtr) = 0;
144 : NS_IMETHOD_(void) Unroot(void* aPtr) = 0;
145 : NS_IMETHOD_(const char*) ClassName() = 0;
146 :
147 315 : NS_IMETHOD_(void) Trace(void* aPtr, const TraceCallbacks& aCb,
148 315 : void* aClosure) {}
149 :
150 : // CanSkip is called during nsCycleCollector_forgetSkippable. If it returns
151 : // true, aPtr is removed from the purple buffer and therefore might be left
152 : // out from the cycle collector graph the next time that's constructed (unless
153 : // it's reachable in some other way).
154 : //
155 : // CanSkip is allowed to expand the set of certainly-alive objects by removing
156 : // other objects from the purple buffer, marking JS things black (in the GC
157 : // sense), and so forth. Furthermore, if aRemovingAllowed is true, this call
158 : // is allowed to remove aPtr itself from the purple buffer.
159 : //
160 : // Things can return true from CanSkip if either they know they have no
161 : // outgoing edges at all in the cycle collection graph (because then they
162 : // can't be parts of a cycle) or they know for sure they're alive.
163 0 : bool CanSkip(void* aPtr, bool aRemovingAllowed)
164 : {
165 0 : return mMightSkip ? CanSkipReal(aPtr, aRemovingAllowed) : false;
166 : }
167 :
168 : // CanSkipInCC is called during construction of the initial set of roots for
169 : // the cycle collector graph. If it returns true, aPtr is left out of that
170 : // set of roots. Note that the set of roots includes whatever is in the
171 : // purple buffer (after earlier CanSkip calls) plus various other sources of
172 : // roots, so an object can end up having CanSkipInCC called on it even if it
173 : // returned true from CanSkip. One example of this would be an object that
174 : // can potentially trace JS things.
175 : //
176 : // CanSkipInCC is allowed to remove other objects from the purple buffer but
177 : // should not remove aPtr and should not mark JS things black. It should also
178 : // not modify any reference counts.
179 : //
180 : // Things can return true from CanSkipInCC if either they know they have no
181 : // outgoing edges at all in the cycle collection graph or they know for sure
182 : // they're alive _and_ none of their outgoing edges are to gray (in the GC
183 : // sense) gcthings. See also nsWrapperCache::HasNothingToTrace and
184 : // nsWrapperCache::IsBlackAndDoesNotNeedTracing. The restriction on not
185 : // having outgoing edges to gray gcthings is because if we _do_ have them that
186 : // means we have a "strong" edge to a JS thing and since we're alive we need
187 : // to trace through it and mark keep them alive. Outgoing edges to C++ things
188 : // don't matter here, because the criteria for when a CC participant is
189 : // considered alive are slightly different for JS and C++ things: JS things
190 : // are only considered alive when reachable via an edge from a live thing,
191 : // while C++ things are also considered alive when their refcount exceeds the
192 : // number of edges via which they are reachable.
193 0 : bool CanSkipInCC(void* aPtr)
194 : {
195 0 : return mMightSkip ? CanSkipInCCReal(aPtr) : false;
196 : }
197 :
198 : // CanSkipThis is called during construction of the cycle collector graph,
199 : // when we traverse an edge to aPtr and consider adding it to the graph. If
200 : // it returns true, aPtr is not added to the graph.
201 : //
202 : // CanSkipThis is not allowed to change the liveness or reference count of any
203 : // objects.
204 : //
205 : // Things can return true from CanSkipThis if either they know they have no
206 : // outgoing edges at all in the cycle collection graph or they know for sure
207 : // they're alive.
208 : //
209 : // Note that CanSkipThis doesn't have to worry about outgoing edges to gray GC
210 : // things, because if this object could have those it already got added to the
211 : // graph during root set construction. An object should never have
212 : // CanSkipThis called on it if it has outgoing strong references to JS things.
213 0 : bool CanSkipThis(void* aPtr)
214 : {
215 0 : return mMightSkip ? CanSkipThisReal(aPtr) : false;
216 : }
217 :
218 : NS_IMETHOD_(void) DeleteCycleCollectable(void* aPtr) = 0;
219 :
220 : protected:
221 0 : NS_IMETHOD_(bool) CanSkipReal(void* aPtr, bool aRemovingAllowed)
222 : {
223 0 : NS_ASSERTION(false, "Forgot to implement CanSkipReal?");
224 0 : return false;
225 : }
226 0 : NS_IMETHOD_(bool) CanSkipInCCReal(void* aPtr)
227 : {
228 0 : NS_ASSERTION(false, "Forgot to implement CanSkipInCCReal?");
229 0 : return false;
230 : }
231 0 : NS_IMETHOD_(bool) CanSkipThisReal(void* aPtr)
232 : {
233 0 : NS_ASSERTION(false, "Forgot to implement CanSkipThisReal?");
234 0 : return false;
235 : }
236 :
237 : private:
238 : const bool mMightSkip;
239 : const bool mTraverseShouldTrace;
240 : };
241 :
242 : class NS_NO_VTABLE nsScriptObjectTracer : public nsCycleCollectionParticipant
243 : {
244 : public:
245 0 : constexpr explicit nsScriptObjectTracer(bool aSkip)
246 0 : : nsCycleCollectionParticipant(aSkip, true)
247 : {
248 0 : }
249 :
250 : NS_IMETHOD_(void) Trace(void* aPtr, const TraceCallbacks& aCb,
251 : void* aClosure) override = 0;
252 :
253 : };
254 :
255 : class NS_NO_VTABLE nsXPCOMCycleCollectionParticipant : public nsScriptObjectTracer
256 : {
257 : public:
258 0 : constexpr explicit nsXPCOMCycleCollectionParticipant(bool aSkip)
259 0 : : nsScriptObjectTracer(aSkip)
260 : {
261 0 : }
262 :
263 : NS_DECLARE_STATIC_IID_ACCESSOR(NS_XPCOMCYCLECOLLECTIONPARTICIPANT_IID)
264 :
265 : NS_IMETHOD_(void) Root(void* aPtr) override;
266 : NS_IMETHOD_(void) Unroot(void* aPtr) override;
267 :
268 : NS_IMETHOD_(void) Trace(void* aPtr, const TraceCallbacks& aCb,
269 : void* aClosure) override;
270 :
271 : static bool CheckForRightISupports(nsISupports* aSupports);
272 : };
273 :
274 : NS_DEFINE_STATIC_IID_ACCESSOR(nsXPCOMCycleCollectionParticipant,
275 : NS_XPCOMCYCLECOLLECTIONPARTICIPANT_IID)
276 :
277 : ///////////////////////////////////////////////////////////////////////////////
278 : // Helpers for implementing a QI to nsXPCOMCycleCollectionParticipant
279 : ///////////////////////////////////////////////////////////////////////////////
280 :
281 : #define NS_CYCLE_COLLECTION_CLASSNAME(_class) \
282 : _class::NS_CYCLE_COLLECTION_INNERCLASS
283 :
284 : #define NS_IMPL_QUERY_CYCLE_COLLECTION(_class) \
285 : if ( aIID.Equals(NS_GET_IID(nsXPCOMCycleCollectionParticipant)) ) { \
286 : *aInstancePtr = NS_CYCLE_COLLECTION_PARTICIPANT(_class); \
287 : return NS_OK; \
288 : } else
289 :
290 : #define NS_IMPL_QUERY_CYCLE_COLLECTION_ISUPPORTS(_class) \
291 : if ( aIID.Equals(NS_GET_IID(nsCycleCollectionISupports)) ) { \
292 : *aInstancePtr = NS_CYCLE_COLLECTION_CLASSNAME(_class)::Upcast(this); \
293 : return NS_OK; \
294 : } else
295 :
296 : #define NS_INTERFACE_MAP_ENTRY_CYCLE_COLLECTION(_class) \
297 : NS_IMPL_QUERY_CYCLE_COLLECTION(_class)
298 :
299 : #define NS_INTERFACE_MAP_ENTRY_CYCLE_COLLECTION_ISUPPORTS(_class) \
300 : NS_IMPL_QUERY_CYCLE_COLLECTION_ISUPPORTS(_class)
301 :
302 : #define NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(_class) \
303 : NS_INTERFACE_MAP_ENTRY_CYCLE_COLLECTION(_class) \
304 : NS_INTERFACE_MAP_ENTRY_CYCLE_COLLECTION_ISUPPORTS(_class)
305 :
306 : #define NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(_class) \
307 : NS_INTERFACE_MAP_BEGIN(_class) \
308 : NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(_class)
309 :
310 : #define NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(_class) \
311 : NS_INTERFACE_MAP_BEGIN(_class) \
312 : NS_INTERFACE_MAP_ENTRY_CYCLE_COLLECTION(_class)
313 :
314 : #define NS_INTERFACE_TABLE_TO_MAP_SEGUE_CYCLE_COLLECTION(_class) \
315 : if (rv == NS_OK) return rv; \
316 : nsISupports* foundInterface; \
317 : NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(_class)
318 :
319 : #define NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(_class) \
320 : NS_IMETHODIMP _class::QueryInterface(REFNSIID aIID, void** aInstancePtr) \
321 : { \
322 : NS_PRECONDITION(aInstancePtr, "null out param"); \
323 : \
324 : if ( aIID.Equals(NS_GET_IID(nsXPCOMCycleCollectionParticipant)) ) { \
325 : *aInstancePtr = NS_CYCLE_COLLECTION_PARTICIPANT(_class); \
326 : return NS_OK; \
327 : } \
328 : nsresult rv;
329 :
330 : #define NS_CYCLE_COLLECTION_UPCAST(obj, clazz) \
331 : NS_CYCLE_COLLECTION_CLASSNAME(clazz)::Upcast(obj)
332 :
333 : #ifdef DEBUG
334 : #define NS_CHECK_FOR_RIGHT_PARTICIPANT(_ptr) _ptr->CheckForRightParticipant()
335 : #else
336 : #define NS_CHECK_FOR_RIGHT_PARTICIPANT(_ptr)
337 : #endif
338 :
339 : // The default implementation of this class template is empty, because it
340 : // should never be used: see the partial specializations below.
341 : template<typename T,
342 : bool IsXPCOM = mozilla::IsBaseOf<nsISupports, T>::value>
343 : struct DowncastCCParticipantImpl
344 : {
345 : };
346 :
347 : // Specialization for XPCOM CC participants
348 : template<typename T>
349 : struct DowncastCCParticipantImpl<T, true>
350 : {
351 13099 : static T* Run(void* aPtr)
352 : {
353 13099 : nsISupports* s = static_cast<nsISupports*>(aPtr);
354 13099 : MOZ_ASSERT(NS_CYCLE_COLLECTION_CLASSNAME(T)::CheckForRightISupports(s),
355 : "not the nsISupports pointer we expect");
356 13099 : T* rval = NS_CYCLE_COLLECTION_CLASSNAME(T)::Downcast(s);
357 13099 : NS_CHECK_FOR_RIGHT_PARTICIPANT(rval);
358 13099 : return rval;
359 : }
360 : };
361 :
362 : // Specialization for native CC participants
363 : template<typename T>
364 : struct DowncastCCParticipantImpl<T, false>
365 : {
366 1140 : static T* Run(void* aPtr) { return static_cast<T*>(aPtr); }
367 : };
368 :
369 : template<typename T>
370 : T*
371 14239 : DowncastCCParticipant(void* aPtr)
372 : {
373 14239 : return DowncastCCParticipantImpl<T>::Run(aPtr);
374 : }
375 :
376 : ///////////////////////////////////////////////////////////////////////////////
377 : // Helpers for implementing CanSkip methods
378 : ///////////////////////////////////////////////////////////////////////////////
379 :
380 : // See documentation for nsCycleCollectionParticipant::CanSkip for documentation
381 : // about this method.
382 : #define NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN(_class) \
383 : NS_IMETHODIMP_(bool) \
384 : NS_CYCLE_COLLECTION_CLASSNAME(_class)::CanSkipReal(void *p, \
385 : bool aRemovingAllowed) \
386 : { \
387 : _class *tmp = DowncastCCParticipant<_class >(p);
388 :
389 : #define NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_END \
390 : (void)tmp; \
391 : return false; \
392 : }
393 :
394 : // See documentation for nsCycleCollectionParticipant::CanSkipInCC for
395 : // documentation about this method.
396 : #define NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_BEGIN(_class) \
397 : NS_IMETHODIMP_(bool) \
398 : NS_CYCLE_COLLECTION_CLASSNAME(_class)::CanSkipInCCReal(void *p) \
399 : { \
400 : _class *tmp = DowncastCCParticipant<_class >(p);
401 :
402 : #define NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_END \
403 : (void)tmp; \
404 : return false; \
405 : }
406 :
407 : // See documentation for nsCycleCollectionParticipant::CanSkipThis for
408 : // documentation about this method.
409 : #define NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_BEGIN(_class) \
410 : NS_IMETHODIMP_(bool) \
411 : NS_CYCLE_COLLECTION_CLASSNAME(_class)::CanSkipThisReal(void *p) \
412 : { \
413 : _class *tmp = DowncastCCParticipant<_class >(p);
414 :
415 : #define NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_END \
416 : (void)tmp; \
417 : return false; \
418 : }
419 :
420 : ///////////////////////////////////////////////////////////////////////////////
421 : // Helpers for implementing nsCycleCollectionParticipant::Unlink
422 : //
423 : // You need to use NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED if you want
424 : // the base class Unlink version to be called before your own implementation.
425 : // You can use NS_IMPL_CYCLE_COLLECTION_UNLINK_END_INHERITED if you want the
426 : // base class Unlink to get called after your own implementation. You should
427 : // never use them together.
428 : ///////////////////////////////////////////////////////////////////////////////
429 :
430 : #define NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(_class) \
431 : NS_IMETHODIMP_(void) \
432 : NS_CYCLE_COLLECTION_CLASSNAME(_class)::Unlink(void *p) \
433 : { \
434 : _class *tmp = DowncastCCParticipant<_class >(p);
435 :
436 : #define NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(_class, _base_class) \
437 : NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(_class) \
438 : nsISupports *s = static_cast<nsISupports*>(p); \
439 : NS_CYCLE_COLLECTION_CLASSNAME(_base_class)::Unlink(s);
440 :
441 : #define NS_IMPL_CYCLE_COLLECTION_UNLINK_HELPER(_field) \
442 : ImplCycleCollectionUnlink(tmp->_field);
443 :
444 : #define NS_IMPL_CYCLE_COLLECTION_UNLINK(...) \
445 : MOZ_FOR_EACH(NS_IMPL_CYCLE_COLLECTION_UNLINK_HELPER, (), (__VA_ARGS__))
446 :
447 : #define NS_IMPL_CYCLE_COLLECTION_UNLINK_END \
448 : (void)tmp; \
449 : }
450 :
451 : #define NS_IMPL_CYCLE_COLLECTION_UNLINK_END_INHERITED(_base_class) \
452 : nsISupports *s = static_cast<nsISupports*>(p); \
453 : NS_CYCLE_COLLECTION_CLASSNAME(_base_class)::Unlink(s); \
454 : (void)tmp; \
455 : }
456 :
457 : #define NS_IMPL_CYCLE_COLLECTION_UNLINK_0(_class) \
458 : NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(_class) \
459 : NS_IMPL_CYCLE_COLLECTION_UNLINK_END
460 :
461 :
462 : ///////////////////////////////////////////////////////////////////////////////
463 : // Helpers for implementing nsCycleCollectionParticipant::Traverse
464 : ///////////////////////////////////////////////////////////////////////////////
465 :
466 : #define NS_IMPL_CYCLE_COLLECTION_DESCRIBE(_class, _refcnt) \
467 : cb.DescribeRefCountedNode(_refcnt, #_class);
468 :
469 : #define NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(_class) \
470 : NS_IMETHODIMP \
471 : NS_CYCLE_COLLECTION_CLASSNAME(_class)::TraverseNative \
472 : (void *p, nsCycleCollectionTraversalCallback &cb) \
473 : { \
474 : _class *tmp = DowncastCCParticipant<_class >(p);
475 :
476 : #define NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(_class) \
477 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(_class) \
478 : NS_IMPL_CYCLE_COLLECTION_DESCRIBE(_class, tmp->mRefCnt.get())
479 :
480 : // Base class' CC participant should return NS_SUCCESS_INTERRUPTED_TRAVERSE
481 : // from Traverse if it wants derived classes to not traverse anything from
482 : // their CC participant.
483 :
484 : #define NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(_class, _base_class) \
485 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(_class) \
486 : nsISupports *s = static_cast<nsISupports*>(p); \
487 : if (NS_CYCLE_COLLECTION_CLASSNAME(_base_class)::TraverseNative(s, cb) \
488 : == NS_SUCCESS_INTERRUPTED_TRAVERSE) { \
489 : return NS_SUCCESS_INTERRUPTED_TRAVERSE; \
490 : }
491 :
492 : #define NS_IMPL_CYCLE_COLLECTION_TRAVERSE_HELPER(_field) \
493 : ImplCycleCollectionTraverse(cb, tmp->_field, #_field, 0);
494 :
495 : #define NS_IMPL_CYCLE_COLLECTION_TRAVERSE(...) \
496 : MOZ_FOR_EACH(NS_IMPL_CYCLE_COLLECTION_TRAVERSE_HELPER, (), (__VA_ARGS__))
497 :
498 : #define NS_IMPL_CYCLE_COLLECTION_TRAVERSE_RAWPTR(_field) \
499 : CycleCollectionNoteChild(cb, tmp->_field, #_field);
500 :
501 : #define NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END \
502 : (void)tmp; \
503 : return NS_OK; \
504 : }
505 :
506 : ///////////////////////////////////////////////////////////////////////////////
507 : // Helpers for implementing nsScriptObjectTracer::Trace
508 : ///////////////////////////////////////////////////////////////////////////////
509 :
510 : #define NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(_class) \
511 : void \
512 : NS_CYCLE_COLLECTION_CLASSNAME(_class)::Trace(void *p, \
513 : const TraceCallbacks &aCallbacks, \
514 : void *aClosure) \
515 : { \
516 : _class *tmp = DowncastCCParticipant<_class >(p);
517 :
518 : #define NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(_class, _base_class) \
519 : NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(_class) \
520 : nsISupports *s = static_cast<nsISupports*>(p); \
521 : NS_CYCLE_COLLECTION_CLASSNAME(_base_class)::Trace(s, aCallbacks, aClosure);
522 :
523 : #define NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(_field) \
524 : aCallbacks.Trace(&tmp->_field, #_field, aClosure);
525 :
526 : // NB: The (void)tmp; hack in the TRACE_END macro exists to support
527 : // implementations that don't need to do anything in their Trace method.
528 : // Without this hack, some compilers warn about the unused tmp local.
529 : #define NS_IMPL_CYCLE_COLLECTION_TRACE_END \
530 : (void)tmp; \
531 : }
532 :
533 : ///////////////////////////////////////////////////////////////////////////////
534 : // Helpers for implementing a concrete nsCycleCollectionParticipant
535 : ///////////////////////////////////////////////////////////////////////////////
536 :
537 : // If a class defines a participant, then QIing an instance of that class to
538 : // nsXPCOMCycleCollectionParticipant should produce that participant.
539 : #ifdef DEBUG
540 : #define NS_CHECK_FOR_RIGHT_PARTICIPANT_BASE \
541 : virtual void CheckForRightParticipant()
542 : #define NS_CHECK_FOR_RIGHT_PARTICIPANT_DERIVED \
543 : virtual void CheckForRightParticipant() override
544 : #define NS_CHECK_FOR_RIGHT_PARTICIPANT_BODY(_class) \
545 : { \
546 : nsXPCOMCycleCollectionParticipant *p; \
547 : CallQueryInterface(this, &p); \
548 : MOZ_ASSERT(p == &NS_CYCLE_COLLECTION_INNERNAME, \
549 : #_class " should QI to its own CC participant"); \
550 : }
551 : #define NS_CHECK_FOR_RIGHT_PARTICIPANT_IMPL(_class) \
552 : NS_CHECK_FOR_RIGHT_PARTICIPANT_BASE \
553 : NS_CHECK_FOR_RIGHT_PARTICIPANT_BODY(_class)
554 : #define NS_CHECK_FOR_RIGHT_PARTICIPANT_IMPL_INHERITED(_class) \
555 : NS_CHECK_FOR_RIGHT_PARTICIPANT_DERIVED \
556 : NS_CHECK_FOR_RIGHT_PARTICIPANT_BODY(_class)
557 : #else
558 : #define NS_CHECK_FOR_RIGHT_PARTICIPANT_IMPL(_class)
559 : #define NS_CHECK_FOR_RIGHT_PARTICIPANT_IMPL_INHERITED(_class)
560 : #endif
561 :
562 : #define NS_DECL_CYCLE_COLLECTION_CLASS_NAME_METHOD(_class) \
563 : NS_IMETHOD_(const char*) ClassName() override { return #_class; };
564 :
565 :
566 : #define NS_DECL_CYCLE_COLLECTION_CLASS_BODY_NO_UNLINK(_class, _base) \
567 : public: \
568 : NS_IMETHOD TraverseNative(void *p, nsCycleCollectionTraversalCallback &cb) \
569 : override; \
570 : NS_DECL_CYCLE_COLLECTION_CLASS_NAME_METHOD(_class) \
571 : NS_IMETHOD_(void) DeleteCycleCollectable(void *p) override \
572 : { \
573 : DowncastCCParticipant<_class>(p)->DeleteCycleCollectable(); \
574 : } \
575 : static _class* Downcast(nsISupports* s) \
576 : { \
577 : return static_cast<_class*>(static_cast<_base*>(s)); \
578 : } \
579 : static nsISupports* Upcast(_class *p) \
580 : { \
581 : return NS_ISUPPORTS_CAST(_base*, p); \
582 : } \
583 : template<typename T> \
584 : friend nsISupports* \
585 : ToSupports(T* p, NS_CYCLE_COLLECTION_INNERCLASS* dummy);
586 :
587 : #define NS_DECL_CYCLE_COLLECTION_CLASS_BODY(_class, _base) \
588 : NS_DECL_CYCLE_COLLECTION_CLASS_BODY_NO_UNLINK(_class, _base) \
589 : NS_IMETHOD_(void) Unlink(void *p) override;
590 :
591 : #define NS_PARTICIPANT_AS(type, participant) \
592 : const_cast<type*>(reinterpret_cast<const type*>(participant))
593 :
594 : #define NS_IMPL_GET_XPCOM_CYCLE_COLLECTION_PARTICIPANT(_class) \
595 : static constexpr nsXPCOMCycleCollectionParticipant* GetParticipant() \
596 : { \
597 : return &_class::NS_CYCLE_COLLECTION_INNERNAME; \
598 : }
599 :
600 : /**
601 : * We use this macro to force that classes that inherit from a ccable class and
602 : * declare their own participant declare themselves as inherited cc classes.
603 : * To avoid possibly unnecessary vtables we only do this checking in debug
604 : * builds.
605 : */
606 : #ifdef DEBUG
607 : #define NOT_INHERITED_CANT_OVERRIDE virtual void BaseCycleCollectable() final {}
608 : #else
609 : #define NOT_INHERITED_CANT_OVERRIDE
610 : #endif
611 :
612 : #define NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(_class, _base) \
613 : class NS_CYCLE_COLLECTION_INNERCLASS \
614 : : public nsXPCOMCycleCollectionParticipant \
615 : { \
616 : public: \
617 : constexpr explicit NS_CYCLE_COLLECTION_INNERCLASS (bool aSkip = false) \
618 : : nsXPCOMCycleCollectionParticipant(aSkip) {} \
619 : private: \
620 : NS_DECL_CYCLE_COLLECTION_CLASS_BODY(_class, _base) \
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_CLASS(_class) \
628 : NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(_class, _class)
629 :
630 : // Cycle collector helper for ambiguous classes that can sometimes be skipped.
631 : #define NS_DECL_CYCLE_COLLECTION_SKIPPABLE_CLASS_AMBIGUOUS(_class, _base) \
632 : class NS_CYCLE_COLLECTION_INNERCLASS \
633 : : public nsXPCOMCycleCollectionParticipant \
634 : { \
635 : public: \
636 : constexpr explicit NS_CYCLE_COLLECTION_INNERCLASS (bool aSkip = true) \
637 : /* Ignore aSkip: we always want skippability. */ \
638 : : nsXPCOMCycleCollectionParticipant(true) {} \
639 : private: \
640 : NS_DECL_CYCLE_COLLECTION_CLASS_BODY(_class, _base) \
641 : NS_IMETHOD_(bool) CanSkipReal(void *p, bool aRemovingAllowed) override; \
642 : NS_IMETHOD_(bool) CanSkipInCCReal(void *p) override; \
643 : NS_IMETHOD_(bool) CanSkipThisReal(void *p) override; \
644 : NS_IMPL_GET_XPCOM_CYCLE_COLLECTION_PARTICIPANT(_class) \
645 : }; \
646 : NS_CHECK_FOR_RIGHT_PARTICIPANT_IMPL(_class) \
647 : static NS_CYCLE_COLLECTION_INNERCLASS NS_CYCLE_COLLECTION_INNERNAME; \
648 : NOT_INHERITED_CANT_OVERRIDE
649 :
650 : #define NS_DECL_CYCLE_COLLECTION_SKIPPABLE_CLASS(_class) \
651 : NS_DECL_CYCLE_COLLECTION_SKIPPABLE_CLASS_AMBIGUOUS(_class, _class)
652 :
653 : #define NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(_class, _base) \
654 : class NS_CYCLE_COLLECTION_INNERCLASS \
655 : : public nsXPCOMCycleCollectionParticipant \
656 : { \
657 : public: \
658 : constexpr explicit NS_CYCLE_COLLECTION_INNERCLASS (bool aSkip = false) \
659 : : nsXPCOMCycleCollectionParticipant(aSkip) {} \
660 : private: \
661 : NS_DECL_CYCLE_COLLECTION_CLASS_BODY(_class, _base) \
662 : NS_IMETHOD_(void) Trace(void *p, const TraceCallbacks &cb, void *closure) override; \
663 : NS_IMPL_GET_XPCOM_CYCLE_COLLECTION_PARTICIPANT(_class) \
664 : }; \
665 : NS_CHECK_FOR_RIGHT_PARTICIPANT_IMPL(_class) \
666 : static NS_CYCLE_COLLECTION_INNERCLASS NS_CYCLE_COLLECTION_INNERNAME; \
667 : NOT_INHERITED_CANT_OVERRIDE
668 :
669 : #define NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS_AMBIGUOUS(_class, _base) \
670 : class NS_CYCLE_COLLECTION_INNERCLASS \
671 : : public nsXPCOMCycleCollectionParticipant \
672 : { \
673 : public: \
674 : constexpr explicit NS_CYCLE_COLLECTION_INNERCLASS (bool aSkip = true) \
675 : /* Ignore aSkip: we always want skippability. */ \
676 : : nsXPCOMCycleCollectionParticipant(true) {} \
677 : private: \
678 : NS_DECL_CYCLE_COLLECTION_CLASS_BODY(_class, _base) \
679 : NS_IMETHOD_(void) Trace(void *p, const TraceCallbacks &cb, void *closure) override; \
680 : NS_IMETHOD_(bool) CanSkipReal(void *p, bool aRemovingAllowed) override; \
681 : NS_IMETHOD_(bool) CanSkipInCCReal(void *p) override; \
682 : NS_IMETHOD_(bool) CanSkipThisReal(void *p) override; \
683 : NS_IMPL_GET_XPCOM_CYCLE_COLLECTION_PARTICIPANT(_class) \
684 : }; \
685 : NS_CHECK_FOR_RIGHT_PARTICIPANT_IMPL(_class) \
686 : static NS_CYCLE_COLLECTION_INNERCLASS NS_CYCLE_COLLECTION_INNERNAME; \
687 : NOT_INHERITED_CANT_OVERRIDE
688 :
689 : #define NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS(_class) \
690 : NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS_AMBIGUOUS(_class, _class)
691 :
692 : #define NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS_INHERITED(_class, \
693 : _base_class) \
694 : class NS_CYCLE_COLLECTION_INNERCLASS \
695 : : public NS_CYCLE_COLLECTION_CLASSNAME(_base_class) \
696 : { \
697 : public: \
698 : constexpr explicit NS_CYCLE_COLLECTION_INNERCLASS (bool aSkip = true) \
699 : /* Ignore aSkip: we always want skippability. */ \
700 : : NS_CYCLE_COLLECTION_CLASSNAME(_base_class) (true) {} \
701 : private: \
702 : NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_BODY(_class, _base_class) \
703 : NS_IMETHOD_(void) Trace(void *p, const TraceCallbacks &cb, void *closure) override; \
704 : NS_IMETHOD_(bool) CanSkipReal(void *p, bool aRemovingAllowed) override; \
705 : NS_IMETHOD_(bool) CanSkipInCCReal(void *p) override; \
706 : NS_IMETHOD_(bool) CanSkipThisReal(void *p) override; \
707 : NS_IMPL_GET_XPCOM_CYCLE_COLLECTION_PARTICIPANT(_class) \
708 : }; \
709 : NS_CHECK_FOR_RIGHT_PARTICIPANT_IMPL_INHERITED(_class) \
710 : static NS_CYCLE_COLLECTION_INNERCLASS NS_CYCLE_COLLECTION_INNERNAME;
711 :
712 : #define NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(_class) \
713 : NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(_class, _class)
714 :
715 : #define NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_BODY_NO_UNLINK(_class, \
716 : _base_class) \
717 : public: \
718 : NS_IMETHOD TraverseNative(void *p, nsCycleCollectionTraversalCallback &cb) \
719 : override; \
720 : NS_DECL_CYCLE_COLLECTION_CLASS_NAME_METHOD(_class) \
721 : static _class* Downcast(nsISupports* s) \
722 : { \
723 : return static_cast<_class*>(static_cast<_base_class*>( \
724 : NS_CYCLE_COLLECTION_CLASSNAME(_base_class)::Downcast(s))); \
725 : }
726 :
727 : #define NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_BODY(_class, _base_class) \
728 : NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_BODY_NO_UNLINK(_class, _base_class) \
729 : NS_IMETHOD_(void) Unlink(void *p) override;
730 :
731 : #define NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(_class, _base_class) \
732 : class NS_CYCLE_COLLECTION_INNERCLASS \
733 : : public NS_CYCLE_COLLECTION_CLASSNAME(_base_class) \
734 : { \
735 : public: \
736 : constexpr explicit NS_CYCLE_COLLECTION_INNERCLASS (bool aSkip = false) \
737 : : NS_CYCLE_COLLECTION_CLASSNAME(_base_class) (aSkip) {} \
738 : private: \
739 : NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_BODY(_class, _base_class) \
740 : NS_IMPL_GET_XPCOM_CYCLE_COLLECTION_PARTICIPANT(_class) \
741 : }; \
742 : NS_CHECK_FOR_RIGHT_PARTICIPANT_IMPL_INHERITED(_class) \
743 : static NS_CYCLE_COLLECTION_INNERCLASS NS_CYCLE_COLLECTION_INNERNAME;
744 :
745 : #define NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_NO_UNLINK(_class, \
746 : _base_class) \
747 : class NS_CYCLE_COLLECTION_INNERCLASS \
748 : : public NS_CYCLE_COLLECTION_CLASSNAME(_base_class) \
749 : { \
750 : public: \
751 : constexpr explicit NS_CYCLE_COLLECTION_INNERCLASS (bool aSkip = false) \
752 : : NS_CYCLE_COLLECTION_CLASSNAME(_base_class) (aSkip) {} \
753 : private: \
754 : NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_BODY_NO_UNLINK(_class, _base_class) \
755 : NS_IMPL_GET_XPCOM_CYCLE_COLLECTION_PARTICIPANT(_class) \
756 : }; \
757 : NS_CHECK_FOR_RIGHT_PARTICIPANT_IMPL_INHERITED(_class) \
758 : static NS_CYCLE_COLLECTION_INNERCLASS NS_CYCLE_COLLECTION_INNERNAME;
759 :
760 : #define NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(_class, \
761 : _base_class) \
762 : class NS_CYCLE_COLLECTION_INNERCLASS \
763 : : public NS_CYCLE_COLLECTION_CLASSNAME(_base_class) \
764 : { \
765 : public: \
766 : constexpr explicit NS_CYCLE_COLLECTION_INNERCLASS (bool aSkip = false) \
767 : : NS_CYCLE_COLLECTION_CLASSNAME(_base_class) (aSkip) {} \
768 : private: \
769 : NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_BODY(_class, _base_class) \
770 : NS_IMETHOD_(void) Trace(void *p, const TraceCallbacks &cb, void *closure) \
771 : override; \
772 : NS_IMPL_GET_XPCOM_CYCLE_COLLECTION_PARTICIPANT(_class) \
773 : }; \
774 : NS_CHECK_FOR_RIGHT_PARTICIPANT_IMPL_INHERITED(_class) \
775 : static NS_CYCLE_COLLECTION_INNERCLASS NS_CYCLE_COLLECTION_INNERNAME;
776 :
777 : // Cycle collector participant declarations.
778 :
779 : #define NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS_BODY(_class) \
780 : public: \
781 : NS_IMETHOD_(void) Root(void *n) override; \
782 : NS_IMETHOD_(void) Unlink(void *n) override; \
783 : NS_IMETHOD_(void) Unroot(void *n) override; \
784 : NS_IMETHOD TraverseNative(void *n, nsCycleCollectionTraversalCallback &cb) \
785 : override; \
786 : NS_DECL_CYCLE_COLLECTION_CLASS_NAME_METHOD(_class) \
787 : NS_IMETHOD_(void) DeleteCycleCollectable(void *n) override \
788 : { \
789 : DowncastCCParticipant<_class>(n)->DeleteCycleCollectable(); \
790 : } \
791 : static _class* Downcast(void* s) \
792 : { \
793 : return DowncastCCParticipant<_class>(s); \
794 : } \
795 : static void* Upcast(_class *p) \
796 : { \
797 : return static_cast<void*>(p); \
798 : }
799 :
800 : #define NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(_class) \
801 : void DeleteCycleCollectable(void) \
802 : { \
803 : delete this; \
804 : } \
805 : class NS_CYCLE_COLLECTION_INNERCLASS \
806 : : public nsCycleCollectionParticipant \
807 : { \
808 : public: \
809 : constexpr explicit NS_CYCLE_COLLECTION_INNERCLASS (bool aSkip = false) \
810 : : nsCycleCollectionParticipant(aSkip) {} \
811 : private: \
812 : NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS_BODY(_class) \
813 : static constexpr nsCycleCollectionParticipant* GetParticipant() \
814 : { \
815 : return &_class::NS_CYCLE_COLLECTION_INNERNAME; \
816 : } \
817 : }; \
818 : static NS_CYCLE_COLLECTION_INNERCLASS NS_CYCLE_COLLECTION_INNERNAME;
819 :
820 : #define NS_DECL_CYCLE_COLLECTION_SKIPPABLE_NATIVE_CLASS(_class) \
821 : void DeleteCycleCollectable(void) \
822 : { \
823 : delete this; \
824 : } \
825 : class NS_CYCLE_COLLECTION_INNERCLASS \
826 : : public nsCycleCollectionParticipant \
827 : { \
828 : public: \
829 : constexpr explicit NS_CYCLE_COLLECTION_INNERCLASS (bool aSkip = true) \
830 : /* Ignore aSkip: we always want skippability. */ \
831 : : nsCycleCollectionParticipant(true) {} \
832 : private: \
833 : NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS_BODY(_class) \
834 : NS_IMETHOD_(bool) CanSkipReal(void *p, bool aRemovingAllowed) override; \
835 : NS_IMETHOD_(bool) CanSkipInCCReal(void *p) override; \
836 : NS_IMETHOD_(bool) CanSkipThisReal(void *p) override; \
837 : static nsCycleCollectionParticipant* GetParticipant() \
838 : { \
839 : return &_class::NS_CYCLE_COLLECTION_INNERNAME; \
840 : } \
841 : }; \
842 : static NS_CYCLE_COLLECTION_INNERCLASS NS_CYCLE_COLLECTION_INNERNAME;
843 :
844 : #define NS_DECL_CYCLE_COLLECTION_SKIPPABLE_NATIVE_CLASS_WITH_CUSTOM_DELETE(_class) \
845 : class NS_CYCLE_COLLECTION_INNERCLASS \
846 : : public nsCycleCollectionParticipant \
847 : { \
848 : public: \
849 : constexpr NS_CYCLE_COLLECTION_INNERCLASS () \
850 : : nsCycleCollectionParticipant(true) {} \
851 : private: \
852 : NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS_BODY(_class) \
853 : NS_IMETHOD_(bool) CanSkipReal(void *p, bool aRemovingAllowed) override; \
854 : NS_IMETHOD_(bool) CanSkipInCCReal(void *p) override; \
855 : NS_IMETHOD_(bool) CanSkipThisReal(void *p) override; \
856 : static nsCycleCollectionParticipant* GetParticipant() \
857 : { \
858 : return &_class::NS_CYCLE_COLLECTION_INNERNAME; \
859 : } \
860 : }; \
861 : static NS_CYCLE_COLLECTION_INNERCLASS NS_CYCLE_COLLECTION_INNERNAME;
862 :
863 : #define NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(_class) \
864 : void DeleteCycleCollectable(void) \
865 : { \
866 : delete this; \
867 : } \
868 : class NS_CYCLE_COLLECTION_INNERCLASS \
869 : : public nsScriptObjectTracer \
870 : { \
871 : public: \
872 : constexpr explicit NS_CYCLE_COLLECTION_INNERCLASS (bool aSkip = false) \
873 : : nsScriptObjectTracer(aSkip) {} \
874 : private: \
875 : NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS_BODY(_class) \
876 : NS_IMETHOD_(void) Trace(void *p, const TraceCallbacks &cb, void *closure) \
877 : override; \
878 : static constexpr nsScriptObjectTracer* GetParticipant() \
879 : { \
880 : return &_class::NS_CYCLE_COLLECTION_INNERNAME; \
881 : } \
882 : }; \
883 : static NS_CYCLE_COLLECTION_INNERCLASS NS_CYCLE_COLLECTION_INNERNAME;
884 :
885 : #define NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(_class, _root_function) \
886 : NS_IMETHODIMP_(void) \
887 : NS_CYCLE_COLLECTION_CLASSNAME(_class)::Root(void *p) \
888 : { \
889 : _class *tmp = static_cast<_class*>(p); \
890 : tmp->_root_function(); \
891 : }
892 :
893 : #define NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(_class, _unroot_function) \
894 : NS_IMETHODIMP_(void) \
895 : NS_CYCLE_COLLECTION_CLASSNAME(_class)::Unroot(void *p) \
896 : { \
897 : _class *tmp = static_cast<_class*>(p); \
898 : tmp->_unroot_function(); \
899 : }
900 :
901 : #define NS_IMPL_CYCLE_COLLECTION_CLASS(_class) \
902 : _class::NS_CYCLE_COLLECTION_INNERCLASS _class::NS_CYCLE_COLLECTION_INNERNAME;
903 :
904 : // NB: This is not something you usually want to use. It is here to allow
905 : // adding things to the CC graph to help debugging via CC logs, but it does not
906 : // traverse or unlink anything, so it is useless for anything else.
907 : #define NS_IMPL_CYCLE_COLLECTION_0(_class) \
908 : NS_IMPL_CYCLE_COLLECTION_CLASS(_class) \
909 : NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(_class) \
910 : NS_IMPL_CYCLE_COLLECTION_UNLINK_END \
911 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(_class) \
912 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
913 :
914 : #define NS_IMPL_CYCLE_COLLECTION(_class, ...) \
915 : NS_IMPL_CYCLE_COLLECTION_CLASS(_class) \
916 : NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(_class) \
917 : NS_IMPL_CYCLE_COLLECTION_UNLINK(__VA_ARGS__) \
918 : NS_IMPL_CYCLE_COLLECTION_UNLINK_END \
919 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(_class) \
920 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE(__VA_ARGS__) \
921 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
922 :
923 : // If you are looking for NS_IMPL_CYCLE_COLLECTION_INHERITED_0(_class, _base)
924 : // you should instead not declare any cycle collected stuff in _class, so it
925 : // will just inherit the CC declarations from _base.
926 :
927 : #define NS_IMPL_CYCLE_COLLECTION_INHERITED(_class, _base, ...) \
928 : NS_IMPL_CYCLE_COLLECTION_CLASS(_class) \
929 : NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(_class, _base) \
930 : NS_IMPL_CYCLE_COLLECTION_UNLINK(__VA_ARGS__) \
931 : NS_IMPL_CYCLE_COLLECTION_UNLINK_END \
932 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(_class, _base) \
933 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE(__VA_ARGS__) \
934 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
935 :
936 : #define NS_CYCLE_COLLECTION_NOTE_EDGE_NAME CycleCollectionNoteEdgeName
937 :
938 : #endif // nsCycleCollectionParticipant_h__
|