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