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