|
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/. */ |
|
5 |
|
6 #ifndef nsCycleCollectionParticipant_h__ |
|
7 #define nsCycleCollectionParticipant_h__ |
|
8 |
|
9 #include "mozilla/MacroArgs.h" |
|
10 #include "mozilla/MacroForEach.h" |
|
11 #include "nsCycleCollectionNoteChild.h" |
|
12 #include "js/RootingAPI.h" |
|
13 |
|
14 #define NS_XPCOMCYCLECOLLECTIONPARTICIPANT_IID \ |
|
15 { \ |
|
16 0x9674489b, \ |
|
17 0x1f6f, \ |
|
18 0x4550, \ |
|
19 { 0xa7, 0x30, 0xcc, 0xae, 0xdd, 0x10, 0x4c, 0xf9 } \ |
|
20 } |
|
21 |
|
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 } |
|
36 |
|
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 }; |
|
45 |
|
46 NS_DEFINE_STATIC_IID_ACCESSOR(nsCycleCollectionISupports, |
|
47 NS_CYCLECOLLECTIONISUPPORTS_IID) |
|
48 |
|
49 namespace JS { |
|
50 template <class T> class Heap; |
|
51 } /* namespace JS */ |
|
52 |
|
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 }; |
|
68 |
|
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); |
|
76 |
|
77 explicit TraceCallbackFunc(Func cb) : mCallback(cb) {} |
|
78 |
|
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; |
|
86 |
|
87 private: |
|
88 Func mCallback; |
|
89 }; |
|
90 |
|
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) {} |
|
99 |
|
100 NS_IMETHOD Traverse(void *p, nsCycleCollectionTraversalCallback &cb) = 0; |
|
101 |
|
102 NS_IMETHOD_(void) Root(void *p) = 0; |
|
103 NS_IMETHOD_(void) Unlink(void *p) = 0; |
|
104 NS_IMETHOD_(void) Unroot(void *p) = 0; |
|
105 |
|
106 NS_IMETHOD_(void) Trace(void *p, const TraceCallbacks &cb, void *closure) {}; |
|
107 |
|
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 } |
|
116 |
|
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 } |
|
124 |
|
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 } |
|
132 |
|
133 NS_IMETHOD_(void) DeleteCycleCollectable(void *n) = 0; |
|
134 |
|
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 } |
|
151 |
|
152 private: |
|
153 const bool mMightSkip; |
|
154 }; |
|
155 |
|
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) {} |
|
161 |
|
162 NS_IMETHOD_(void) Trace(void *p, const TraceCallbacks &cb, void *closure) = 0; |
|
163 |
|
164 static void NS_COM_GLUE NoteJSChild(void *aScriptThing, const char *name, |
|
165 void *aClosure); |
|
166 }; |
|
167 |
|
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) {} |
|
173 |
|
174 NS_DECLARE_STATIC_IID_ACCESSOR(NS_XPCOMCYCLECOLLECTIONPARTICIPANT_IID) |
|
175 |
|
176 NS_IMETHOD_(void) Root(void *p); |
|
177 NS_IMETHOD_(void) Unroot(void *p); |
|
178 |
|
179 NS_IMETHOD_(void) Trace(void *p, const TraceCallbacks &cb, void *closure); |
|
180 |
|
181 static bool CheckForRightISupports(nsISupports *s); |
|
182 }; |
|
183 |
|
184 NS_DEFINE_STATIC_IID_ACCESSOR(nsXPCOMCycleCollectionParticipant, |
|
185 NS_XPCOMCYCLECOLLECTIONPARTICIPANT_IID) |
|
186 |
|
187 /////////////////////////////////////////////////////////////////////////////// |
|
188 // Helpers for implementing a QI to nsXPCOMCycleCollectionParticipant |
|
189 /////////////////////////////////////////////////////////////////////////////// |
|
190 |
|
191 #define NS_CYCLE_COLLECTION_CLASSNAME(_class) \ |
|
192 _class::NS_CYCLE_COLLECTION_INNERCLASS |
|
193 |
|
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 |
|
199 |
|
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 |
|
205 |
|
206 #define NS_INTERFACE_MAP_ENTRY_CYCLE_COLLECTION(_class) \ |
|
207 NS_IMPL_QUERY_CYCLE_COLLECTION(_class) |
|
208 |
|
209 #define NS_INTERFACE_MAP_ENTRY_CYCLE_COLLECTION_ISUPPORTS(_class) \ |
|
210 NS_IMPL_QUERY_CYCLE_COLLECTION_ISUPPORTS(_class) |
|
211 |
|
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) |
|
215 |
|
216 #define NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(_class) \ |
|
217 NS_INTERFACE_MAP_BEGIN(_class) \ |
|
218 NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(_class) |
|
219 |
|
220 #define NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(_class) \ |
|
221 NS_INTERFACE_MAP_BEGIN(_class) \ |
|
222 NS_INTERFACE_MAP_ENTRY_CYCLE_COLLECTION(_class) |
|
223 |
|
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) |
|
228 |
|
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; |
|
239 |
|
240 #define NS_CYCLE_COLLECTION_UPCAST(obj, clazz) \ |
|
241 NS_CYCLE_COLLECTION_CLASSNAME(clazz)::Upcast(obj) |
|
242 |
|
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 |
|
248 |
|
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 }; |
|
256 |
|
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 }; |
|
271 |
|
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 }; |
|
281 |
|
282 template <typename T> |
|
283 T* DowncastCCParticipant(void *p) |
|
284 { |
|
285 return DowncastCCParticipantImpl<T>::Run(p); |
|
286 } |
|
287 |
|
288 /////////////////////////////////////////////////////////////////////////////// |
|
289 // Helpers for implementing CanSkip methods |
|
290 /////////////////////////////////////////////////////////////////////////////// |
|
291 |
|
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); |
|
298 |
|
299 #define NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_END \ |
|
300 (void)tmp; \ |
|
301 return false; \ |
|
302 } |
|
303 |
|
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); |
|
309 |
|
310 #define NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_END \ |
|
311 (void)tmp; \ |
|
312 return false; \ |
|
313 } |
|
314 |
|
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); |
|
320 |
|
321 #define NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_END \ |
|
322 (void)tmp; \ |
|
323 return false; \ |
|
324 } |
|
325 |
|
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 /////////////////////////////////////////////////////////////////////////////// |
|
335 |
|
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); |
|
341 |
|
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); |
|
346 |
|
347 #define NS_IMPL_CYCLE_COLLECTION_UNLINK_HELPER(_field) \ |
|
348 ImplCycleCollectionUnlink(tmp->_field); |
|
349 |
|
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__)) |
|
353 |
|
354 #define NS_IMPL_CYCLE_COLLECTION_UNLINK_END \ |
|
355 (void)tmp; \ |
|
356 } |
|
357 |
|
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 } |
|
363 |
|
364 #define NS_IMPL_CYCLE_COLLECTION_UNLINK_0(_class) \ |
|
365 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(_class) \ |
|
366 NS_IMPL_CYCLE_COLLECTION_UNLINK_END |
|
367 |
|
368 |
|
369 /////////////////////////////////////////////////////////////////////////////// |
|
370 // Helpers for implementing nsCycleCollectionParticipant::Traverse |
|
371 /////////////////////////////////////////////////////////////////////////////// |
|
372 |
|
373 #define NS_IMPL_CYCLE_COLLECTION_DESCRIBE(_class, _refcnt) \ |
|
374 cb.DescribeRefCountedNode(_refcnt, #_class); |
|
375 |
|
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); |
|
382 |
|
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()) |
|
386 |
|
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. |
|
390 |
|
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 } |
|
398 |
|
399 #define NS_IMPL_CYCLE_COLLECTION_TRAVERSE_HELPER(_field) \ |
|
400 ImplCycleCollectionTraverse(cb, tmp->_field, #_field, 0); |
|
401 |
|
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__)) |
|
405 |
|
406 #define NS_IMPL_CYCLE_COLLECTION_TRAVERSE_RAWPTR(_field) \ |
|
407 CycleCollectionNoteChild(cb, tmp->_field, #_field); |
|
408 |
|
409 #define NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS \ |
|
410 { \ |
|
411 TraceCallbackFunc noteJsChild(&nsScriptObjectTracer::NoteJSChild); \ |
|
412 Trace(p, noteJsChild, &cb); \ |
|
413 } |
|
414 |
|
415 #define NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END \ |
|
416 (void)tmp; \ |
|
417 return NS_OK; \ |
|
418 } |
|
419 |
|
420 /////////////////////////////////////////////////////////////////////////////// |
|
421 // Helpers for implementing nsScriptObjectTracer::Trace |
|
422 /////////////////////////////////////////////////////////////////////////////// |
|
423 |
|
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); |
|
431 |
|
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); |
|
436 |
|
437 #define NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(_field) \ |
|
438 if (tmp->_field) \ |
|
439 aCallbacks.Trace(&tmp->_field, #_field, aClosure); |
|
440 |
|
441 #define NS_IMPL_CYCLE_COLLECTION_TRACE_JSVAL_MEMBER_CALLBACK(_field) \ |
|
442 aCallbacks.Trace(&tmp->_field, #_field, aClosure); |
|
443 |
|
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 } |
|
450 |
|
451 /////////////////////////////////////////////////////////////////////////////// |
|
452 // Helpers for implementing a concrete nsCycleCollectionParticipant |
|
453 /////////////////////////////////////////////////////////////////////////////// |
|
454 |
|
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 |
|
469 |
|
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); |
|
488 |
|
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); |
|
492 |
|
493 #define NS_PARTICIPANT_AS(type, participant) \ |
|
494 const_cast<type*>(reinterpret_cast<const type*>(participant)) |
|
495 |
|
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 } |
|
501 |
|
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 |
|
513 |
|
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 |
|
524 |
|
525 #define NS_DECL_CYCLE_COLLECTION_CLASS(_class) \ |
|
526 NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(_class, _class) |
|
527 |
|
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 |
|
546 |
|
547 #define NS_DECL_CYCLE_COLLECTION_SKIPPABLE_CLASS(_class) \ |
|
548 NS_DECL_CYCLE_COLLECTION_SKIPPABLE_CLASS_AMBIGUOUS(_class, _class) |
|
549 |
|
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 |
|
561 |
|
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 |
|
580 |
|
581 #define NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS(_class) \ |
|
582 NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS_AMBIGUOUS(_class, _class) |
|
583 |
|
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; |
|
598 |
|
599 #define NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(_class) \ |
|
600 NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(_class, _class) |
|
601 |
|
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 } |
|
611 |
|
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); |
|
615 |
|
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; |
|
626 |
|
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; |
|
638 |
|
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; |
|
650 |
|
651 // Cycle collector participant declarations. |
|
652 |
|
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 } |
|
671 |
|
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; |
|
687 |
|
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; |
|
704 |
|
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 } |
|
712 |
|
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 } |
|
720 |
|
721 #define NS_IMPL_CYCLE_COLLECTION_CLASS(_class) \ |
|
722 _class::NS_CYCLE_COLLECTION_INNERCLASS _class::NS_CYCLE_COLLECTION_INNERNAME; |
|
723 |
|
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 |
|
733 |
|
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 |
|
742 |
|
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 |
|
751 |
|
752 #define NS_CYCLE_COLLECTION_NOTE_EDGE_NAME CycleCollectionNoteEdgeName |
|
753 |
|
754 #endif // nsCycleCollectionParticipant_h__ |