Coverage Report

Created: 2018-09-25 14:53

/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__