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 // IWYU pragma: private, include "nsISupports.h"
7 
8 
9 #ifndef nsISupportsImpl_h__
10 #define nsISupportsImpl_h__
11 
12 #include "nscore.h"
13 #include "nsISupportsBase.h"
14 #include "nsISupportsUtils.h"
15 
16 
17 #if !defined(XPCOM_GLUE_AVOID_NSPR)
18 #include "prthread.h" /* needed for thread-safety checks */
19 #endif // !XPCOM_GLUE_AVOID_NSPR
20 
21 #include "nsDebug.h"
22 #include "nsXPCOM.h"
23 #include "mozilla/Atomics.h"
24 #include "mozilla/Attributes.h"
25 #include "mozilla/Assertions.h"
26 #include "mozilla/Compiler.h"
27 #include "mozilla/Likely.h"
28 #include "mozilla/MacroArgs.h"
29 #include "mozilla/MacroForEach.h"
30 #include "mozilla/TypeTraits.h"
31 
32 #define MOZ_ASSERT_TYPE_OK_FOR_REFCOUNTING(X) \
33   static_assert(!mozilla::IsDestructible<X>::value, \
34                 "Reference-counted class " #X " should not have a public destructor. " \
35                 "Make this class's destructor non-public");
36 
37 inline nsISupports*
ToSupports(nsISupports * aSupports)38 ToSupports(nsISupports* aSupports)
39 {
40   return aSupports;
41 }
42 
43 inline nsISupports*
ToCanonicalSupports(nsISupports * aSupports)44 ToCanonicalSupports(nsISupports* aSupports)
45 {
46   return nullptr;
47 }
48 
49 ////////////////////////////////////////////////////////////////////////////////
50 // Macros to help detect thread-safety:
51 
52 #ifdef MOZ_THREAD_SAFETY_OWNERSHIP_CHECKS_SUPPORTED
53 
54 class nsAutoOwningThread
55 {
56 public:
nsAutoOwningThread()57   nsAutoOwningThread() { mThread = PR_GetCurrentThread(); }
GetThread()58   void* GetThread() const { return mThread; }
59 
60 private:
61   void* mThread;
62 };
63 
64 #define NS_DECL_OWNINGTHREAD            nsAutoOwningThread _mOwningThread;
65 #define NS_ASSERT_OWNINGTHREAD_AGGREGATE(agg, _class) \
66   NS_CheckThreadSafe(agg->_mOwningThread.GetThread(), #_class " not thread-safe")
67 #define NS_ASSERT_OWNINGTHREAD(_class) NS_ASSERT_OWNINGTHREAD_AGGREGATE(this, _class)
68 #else // !DEBUG && !(NIGHTLY_BUILD && !MOZ_PROFILING)
69 
70 #define NS_DECL_OWNINGTHREAD            /* nothing */
71 #define NS_ASSERT_OWNINGTHREAD_AGGREGATE(agg, _class) ((void)0)
72 #define NS_ASSERT_OWNINGTHREAD(_class)  ((void)0)
73 
74 #endif // DEBUG || (NIGHTLY_BUILD && !MOZ_PROFILING)
75 
76 
77 // Macros for reference-count and constructor logging
78 
79 #if defined(NS_BUILD_REFCNT_LOGGING)
80 
81 #define NS_LOG_ADDREF(_p, _rc, _type, _size) \
82   NS_LogAddRef((_p), (_rc), (_type), (uint32_t) (_size))
83 
84 #define NS_LOG_RELEASE(_p, _rc, _type) \
85   NS_LogRelease((_p), (_rc), (_type))
86 
87 #include "mozilla/TypeTraits.h"
88 #define MOZ_ASSERT_CLASSNAME(_type)                         \
89   static_assert(mozilla::IsClass<_type>::value,             \
90                 "Token '" #_type "' is not a class type.")
91 
92 // Note that the following constructor/destructor logging macros are redundant
93 // for refcounted objects that log via the NS_LOG_ADDREF/NS_LOG_RELEASE macros.
94 // Refcount logging is preferred.
95 #define MOZ_COUNT_CTOR(_type)                                 \
96 do {                                                          \
97   MOZ_ASSERT_CLASSNAME(_type);                                \
98   NS_LogCtor((void*)this, #_type, sizeof(*this));             \
99 } while (0)
100 
101 #define MOZ_COUNT_CTOR_INHERITED(_type, _base)                    \
102 do {                                                              \
103   MOZ_ASSERT_CLASSNAME(_type);                                    \
104   MOZ_ASSERT_CLASSNAME(_base);                                    \
105   NS_LogCtor((void*)this, #_type, sizeof(*this) - sizeof(_base)); \
106 } while (0)
107 
108 #define MOZ_LOG_CTOR(_ptr, _name, _size) \
109 do {                                     \
110   NS_LogCtor((void*)_ptr, _name, _size); \
111 } while (0)
112 
113 #define MOZ_COUNT_DTOR(_type)                                 \
114 do {                                                          \
115   MOZ_ASSERT_CLASSNAME(_type);                                \
116   NS_LogDtor((void*)this, #_type, sizeof(*this));             \
117 } while (0)
118 
119 #define MOZ_COUNT_DTOR_INHERITED(_type, _base)                    \
120 do {                                                              \
121   MOZ_ASSERT_CLASSNAME(_type);                                    \
122   MOZ_ASSERT_CLASSNAME(_base);                                    \
123   NS_LogDtor((void*)this, #_type, sizeof(*this) - sizeof(_base)); \
124 } while (0)
125 
126 #define MOZ_LOG_DTOR(_ptr, _name, _size) \
127 do {                                     \
128   NS_LogDtor((void*)_ptr, _name, _size); \
129 } while (0)
130 
131 /* nsCOMPtr.h allows these macros to be defined by clients
132  * These logging functions require dynamic_cast<void*>, so they don't
133  * do anything useful if we don't have dynamic_cast<void*>.
134  * Note: The explicit comparison to nullptr is needed to avoid warnings
135  *       when _p is a nullptr itself. */
136 #define NSCAP_LOG_ASSIGNMENT(_c, _p)                                \
137   if (_p != nullptr)                                                \
138     NS_LogCOMPtrAddRef((_c),static_cast<nsISupports*>(_p))
139 
140 #define NSCAP_LOG_RELEASE(_c, _p)                                   \
141   if (_p)                                                           \
142     NS_LogCOMPtrRelease((_c), static_cast<nsISupports*>(_p))
143 
144 #else /* !NS_BUILD_REFCNT_LOGGING */
145 
146 #define NS_LOG_ADDREF(_p, _rc, _type, _size)
147 #define NS_LOG_RELEASE(_p, _rc, _type)
148 #define MOZ_COUNT_CTOR(_type)
149 #define MOZ_COUNT_CTOR_INHERITED(_type, _base)
150 #define MOZ_LOG_CTOR(_ptr, _name, _size)
151 #define MOZ_COUNT_DTOR(_type)
152 #define MOZ_COUNT_DTOR_INHERITED(_type, _base)
153 #define MOZ_LOG_DTOR(_ptr, _name, _size)
154 
155 #endif /* NS_BUILD_REFCNT_LOGGING */
156 
157 
158 // Support for ISupports classes which interact with cycle collector.
159 
160 #define NS_NUMBER_OF_FLAGS_IN_REFCNT 2
161 #define NS_IN_PURPLE_BUFFER (1 << 0)
162 #define NS_IS_PURPLE (1 << 1)
163 #define NS_REFCOUNT_CHANGE (1 << NS_NUMBER_OF_FLAGS_IN_REFCNT)
164 #define NS_REFCOUNT_VALUE(_val) (_val >> NS_NUMBER_OF_FLAGS_IN_REFCNT)
165 
166 class nsCycleCollectingAutoRefCnt
167 {
168 public:
nsCycleCollectingAutoRefCnt()169   nsCycleCollectingAutoRefCnt() : mRefCntAndFlags(0) {}
170 
nsCycleCollectingAutoRefCnt(uintptr_t aValue)171   explicit nsCycleCollectingAutoRefCnt(uintptr_t aValue)
172     : mRefCntAndFlags(aValue << NS_NUMBER_OF_FLAGS_IN_REFCNT)
173   {
174   }
175 
176   nsCycleCollectingAutoRefCnt(const nsCycleCollectingAutoRefCnt&) = delete;
177   void operator=(const nsCycleCollectingAutoRefCnt&) = delete;
178 
incr(nsISupports * aOwner)179   MOZ_ALWAYS_INLINE uintptr_t incr(nsISupports* aOwner)
180   {
181     return incr(aOwner, nullptr);
182   }
183 
incr(void * aOwner,nsCycleCollectionParticipant * aCp)184   MOZ_ALWAYS_INLINE uintptr_t incr(void* aOwner,
185                                    nsCycleCollectionParticipant* aCp)
186   {
187     mRefCntAndFlags += NS_REFCOUNT_CHANGE;
188     mRefCntAndFlags &= ~NS_IS_PURPLE;
189     // For incremental cycle collection, use the purple buffer to track objects
190     // that have been AddRef'd.
191     if (!IsInPurpleBuffer()) {
192       mRefCntAndFlags |= NS_IN_PURPLE_BUFFER;
193       // Refcount isn't zero, so Suspect won't delete anything.
194       MOZ_ASSERT(get() > 0);
195       NS_CycleCollectorSuspect3(aOwner, aCp, this, nullptr);
196     }
197     return NS_REFCOUNT_VALUE(mRefCntAndFlags);
198   }
199 
stabilizeForDeletion()200   MOZ_ALWAYS_INLINE void stabilizeForDeletion()
201   {
202     // Set refcnt to 1 and mark us to be in the purple buffer.
203     // This way decr won't call suspect again.
204     mRefCntAndFlags = NS_REFCOUNT_CHANGE | NS_IN_PURPLE_BUFFER;
205   }
206 
207   MOZ_ALWAYS_INLINE uintptr_t decr(nsISupports* aOwner,
208                                    bool* aShouldDelete = nullptr)
209   {
210     return decr(aOwner, nullptr, aShouldDelete);
211   }
212 
213   MOZ_ALWAYS_INLINE uintptr_t decr(void* aOwner,
214                                    nsCycleCollectionParticipant* aCp,
215                                    bool* aShouldDelete = nullptr)
216   {
217     MOZ_ASSERT(get() > 0);
218     if (!IsInPurpleBuffer()) {
219       mRefCntAndFlags -= NS_REFCOUNT_CHANGE;
220       mRefCntAndFlags |= (NS_IN_PURPLE_BUFFER | NS_IS_PURPLE);
221       uintptr_t retval = NS_REFCOUNT_VALUE(mRefCntAndFlags);
222       // Suspect may delete 'aOwner' and 'this'!
223       NS_CycleCollectorSuspect3(aOwner, aCp, this, aShouldDelete);
224       return retval;
225     }
226     mRefCntAndFlags -= NS_REFCOUNT_CHANGE;
227     mRefCntAndFlags |= (NS_IN_PURPLE_BUFFER | NS_IS_PURPLE);
228     return NS_REFCOUNT_VALUE(mRefCntAndFlags);
229   }
230 
RemovePurple()231   MOZ_ALWAYS_INLINE void RemovePurple()
232   {
233     MOZ_ASSERT(IsPurple(), "must be purple");
234     mRefCntAndFlags &= ~NS_IS_PURPLE;
235   }
236 
RemoveFromPurpleBuffer()237   MOZ_ALWAYS_INLINE void RemoveFromPurpleBuffer()
238   {
239     MOZ_ASSERT(IsInPurpleBuffer());
240     mRefCntAndFlags &= ~(NS_IS_PURPLE | NS_IN_PURPLE_BUFFER);
241   }
242 
IsPurple()243   MOZ_ALWAYS_INLINE bool IsPurple() const
244   {
245     return !!(mRefCntAndFlags & NS_IS_PURPLE);
246   }
247 
IsInPurpleBuffer()248   MOZ_ALWAYS_INLINE bool IsInPurpleBuffer() const
249   {
250     return !!(mRefCntAndFlags & NS_IN_PURPLE_BUFFER);
251   }
252 
get()253   MOZ_ALWAYS_INLINE nsrefcnt get() const
254   {
255     return NS_REFCOUNT_VALUE(mRefCntAndFlags);
256   }
257 
nsrefcnt()258   MOZ_ALWAYS_INLINE operator nsrefcnt() const
259   {
260     return get();
261   }
262 
263 private:
264   uintptr_t mRefCntAndFlags;
265 };
266 
267 class nsAutoRefCnt
268 {
269 public:
nsAutoRefCnt()270   nsAutoRefCnt() : mValue(0) {}
nsAutoRefCnt(nsrefcnt aValue)271   explicit nsAutoRefCnt(nsrefcnt aValue) : mValue(aValue) {}
272 
273   nsAutoRefCnt(const nsAutoRefCnt&) = delete;
274   void operator=(const nsAutoRefCnt&) = delete;
275 
276   // only support prefix increment/decrement
277   nsrefcnt operator++() { return ++mValue; }
278   nsrefcnt operator--() { return --mValue; }
279 
280   nsrefcnt operator=(nsrefcnt aValue) { return (mValue = aValue); }
nsrefcnt()281   operator nsrefcnt() const { return mValue; }
get()282   nsrefcnt get() const { return mValue; }
283 
284   static const bool isThreadSafe = false;
285 private:
286   nsrefcnt operator++(int) = delete;
287   nsrefcnt operator--(int) = delete;
288   nsrefcnt mValue;
289 };
290 
291 namespace mozilla {
292 class ThreadSafeAutoRefCnt
293 {
294 public:
ThreadSafeAutoRefCnt()295   ThreadSafeAutoRefCnt() : mValue(0) {}
ThreadSafeAutoRefCnt(nsrefcnt aValue)296   explicit ThreadSafeAutoRefCnt(nsrefcnt aValue) : mValue(aValue) {}
297 
298   ThreadSafeAutoRefCnt(const ThreadSafeAutoRefCnt&) = delete;
299   void operator=(const ThreadSafeAutoRefCnt&) = delete;
300 
301   // only support prefix increment/decrement
302   MOZ_ALWAYS_INLINE nsrefcnt operator++() { return ++mValue; }
303   MOZ_ALWAYS_INLINE nsrefcnt operator--() { return --mValue; }
304 
305   MOZ_ALWAYS_INLINE nsrefcnt operator=(nsrefcnt aValue)
306   {
307     return (mValue = aValue);
308   }
nsrefcnt()309   MOZ_ALWAYS_INLINE operator nsrefcnt() const { return mValue; }
get()310   MOZ_ALWAYS_INLINE nsrefcnt get() const { return mValue; }
311 
312   static const bool isThreadSafe = true;
313 private:
314   nsrefcnt operator++(int) = delete;
315   nsrefcnt operator--(int) = delete;
316   // In theory, RelaseAcquire consistency (but no weaker) is sufficient for
317   // the counter. Making it weaker could speed up builds on ARM (but not x86),
318   // but could break pre-existing code that assumes sequential consistency.
319   Atomic<nsrefcnt> mValue;
320 };
321 } // namespace mozilla
322 
323 ///////////////////////////////////////////////////////////////////////////////
324 
325 /**
326  * Declare the reference count variable and the implementations of the
327  * AddRef and QueryInterface methods.
328  */
329 
330 #define NS_DECL_ISUPPORTS                                                     \
331 public:                                                                       \
332   NS_IMETHOD QueryInterface(REFNSIID aIID,                                    \
333                             void** aInstancePtr) override;                    \
334   NS_IMETHOD_(MozExternalRefCountType) AddRef(void) override;                 \
335   NS_IMETHOD_(MozExternalRefCountType) Release(void) override;                \
336   typedef mozilla::FalseType HasThreadSafeRefCnt;                             \
337 protected:                                                                    \
338   nsAutoRefCnt mRefCnt;                                                       \
339   NS_DECL_OWNINGTHREAD                                                        \
340 public:
341 
342 #define NS_DECL_THREADSAFE_ISUPPORTS                                          \
343 public:                                                                       \
344   NS_IMETHOD QueryInterface(REFNSIID aIID,                                    \
345                             void** aInstancePtr) override;                    \
346   NS_IMETHOD_(MozExternalRefCountType) AddRef(void) override;                 \
347   NS_IMETHOD_(MozExternalRefCountType) Release(void) override;                \
348   typedef mozilla::TrueType HasThreadSafeRefCnt;                              \
349 protected:                                                                    \
350   ::mozilla::ThreadSafeAutoRefCnt mRefCnt;                                    \
351   NS_DECL_OWNINGTHREAD                                                        \
352 public:
353 
354 #define NS_DECL_CYCLE_COLLECTING_ISUPPORTS                                    \
355 public:                                                                       \
356   NS_IMETHOD QueryInterface(REFNSIID aIID,                                    \
357                             void** aInstancePtr) override;                    \
358   NS_IMETHOD_(MozExternalRefCountType) AddRef(void) override;                 \
359   NS_IMETHOD_(MozExternalRefCountType) Release(void) override;                \
360   NS_IMETHOD_(void) DeleteCycleCollectable(void);                             \
361   typedef mozilla::FalseType HasThreadSafeRefCnt;                             \
362 protected:                                                                    \
363   nsCycleCollectingAutoRefCnt mRefCnt;                                        \
364   NS_DECL_OWNINGTHREAD                                                        \
365 public:
366 
367 
368 ///////////////////////////////////////////////////////////////////////////////
369 
370 /*
371  * Implementation of AddRef and Release for non-nsISupports (ie "native")
372  * cycle-collected classes that use the purple buffer to avoid leaks.
373  */
374 
375 #define NS_IMPL_CC_NATIVE_ADDREF_BODY(_class)                                 \
376     MOZ_ASSERT_TYPE_OK_FOR_REFCOUNTING(_class)                                \
377     MOZ_ASSERT(int32_t(mRefCnt) >= 0, "illegal refcnt");                      \
378     NS_ASSERT_OWNINGTHREAD(_class);                                           \
379     nsrefcnt count =                                                          \
380       mRefCnt.incr(static_cast<void*>(this),                                  \
381                    _class::NS_CYCLE_COLLECTION_INNERCLASS::GetParticipant()); \
382     NS_LOG_ADDREF(this, count, #_class, sizeof(*this));                       \
383     return count;
384 
385 #define NS_IMPL_CC_NATIVE_RELEASE_BODY(_class)                                \
386     MOZ_ASSERT(int32_t(mRefCnt) > 0, "dup release");                          \
387     NS_ASSERT_OWNINGTHREAD(_class);                                           \
388     nsrefcnt count =                                                          \
389       mRefCnt.decr(static_cast<void*>(this),                                  \
390                    _class::NS_CYCLE_COLLECTION_INNERCLASS::GetParticipant()); \
391     NS_LOG_RELEASE(this, count, #_class);                                     \
392     return count;
393 
394 #define NS_IMPL_CYCLE_COLLECTING_NATIVE_ADDREF(_class)                        \
395 NS_METHOD_(MozExternalRefCountType) _class::AddRef(void)                      \
396 {                                                                             \
397   NS_IMPL_CC_NATIVE_ADDREF_BODY(_class)                                       \
398 }
399 
400 #define NS_IMPL_CYCLE_COLLECTING_NATIVE_RELEASE_WITH_LAST_RELEASE(_class, _last) \
401 NS_METHOD_(MozExternalRefCountType) _class::Release(void)                        \
402 {                                                                                \
403     MOZ_ASSERT(int32_t(mRefCnt) > 0, "dup release");                             \
404     NS_ASSERT_OWNINGTHREAD(_class);                                              \
405     bool shouldDelete = false;                                                   \
406     nsrefcnt count =                                                             \
407       mRefCnt.decr(static_cast<void*>(this),                                     \
408                    _class::NS_CYCLE_COLLECTION_INNERCLASS::GetParticipant(),     \
409                    &shouldDelete);                                               \
410     NS_LOG_RELEASE(this, count, #_class);                                        \
411     if (count == 0) {                                                            \
412         mRefCnt.incr(static_cast<void*>(this),                                   \
413                      _class::NS_CYCLE_COLLECTION_INNERCLASS::GetParticipant());  \
414         _last;                                                                   \
415         mRefCnt.decr(static_cast<void*>(this),                                   \
416                      _class::NS_CYCLE_COLLECTION_INNERCLASS::GetParticipant());  \
417         if (shouldDelete) {                                                      \
418             mRefCnt.stabilizeForDeletion();                                      \
419             DeleteCycleCollectable();                                            \
420         }                                                                        \
421     }                                                                            \
422     return count;                                                                \
423 }
424 
425 #define NS_IMPL_CYCLE_COLLECTING_NATIVE_RELEASE(_class)                       \
426 NS_METHOD_(MozExternalRefCountType) _class::Release(void)                     \
427 {                                                                             \
428   NS_IMPL_CC_NATIVE_RELEASE_BODY(_class)                                      \
429 }
430 
431 #define NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(_class)            \
432 public:                                                                       \
433   NS_METHOD_(MozExternalRefCountType) AddRef(void) {                          \
434     NS_IMPL_CC_NATIVE_ADDREF_BODY(_class)                                     \
435   }                                                                           \
436   NS_METHOD_(MozExternalRefCountType) Release(void) {                         \
437     NS_IMPL_CC_NATIVE_RELEASE_BODY(_class)                                    \
438   }                                                                           \
439   typedef mozilla::FalseType HasThreadSafeRefCnt;                             \
440 protected:                                                                    \
441   nsCycleCollectingAutoRefCnt mRefCnt;                                        \
442   NS_DECL_OWNINGTHREAD                                                        \
443 public:
444 
445 
446 ///////////////////////////////////////////////////////////////////////////////
447 
448 /**
449  * Use this macro to declare and implement the AddRef & Release methods for a
450  * given non-XPCOM <i>_class</i>.
451  *
452  * @param _class The name of the class implementing the method
453  * @param _destroy A statement that is executed when the object's
454  *   refcount drops to zero.
455  * @param optional override Mark the AddRef & Release methods as overrides.
456  */
457 #define NS_INLINE_DECL_REFCOUNTING_WITH_DESTROY(_class, _destroy, ...)        \
458 public:                                                                       \
459   NS_METHOD_(MozExternalRefCountType) AddRef(void) __VA_ARGS__ {              \
460     MOZ_ASSERT_TYPE_OK_FOR_REFCOUNTING(_class)                                \
461     MOZ_ASSERT(int32_t(mRefCnt) >= 0, "illegal refcnt");                      \
462     NS_ASSERT_OWNINGTHREAD(_class);                                           \
463     ++mRefCnt;                                                                \
464     NS_LOG_ADDREF(this, mRefCnt, #_class, sizeof(*this));                     \
465     return mRefCnt;                                                           \
466   }                                                                           \
467   NS_METHOD_(MozExternalRefCountType) Release(void) __VA_ARGS__ {             \
468     MOZ_ASSERT(int32_t(mRefCnt) > 0, "dup release");                          \
469     NS_ASSERT_OWNINGTHREAD(_class);                                           \
470     --mRefCnt;                                                                \
471     NS_LOG_RELEASE(this, mRefCnt, #_class);                                   \
472     if (mRefCnt == 0) {                                                       \
473       mRefCnt = 1; /* stabilize */                                            \
474       _destroy;                                                               \
475       return 0;                                                               \
476     }                                                                         \
477     return mRefCnt;                                                           \
478   }                                                                           \
479   typedef mozilla::FalseType HasThreadSafeRefCnt;                             \
480 protected:                                                                    \
481   nsAutoRefCnt mRefCnt;                                                       \
482   NS_DECL_OWNINGTHREAD                                                        \
483 public:
484 
485 /**
486  * Use this macro to declare and implement the AddRef & Release methods for a
487  * given non-XPCOM <i>_class</i>.
488  *
489  * @param _class The name of the class implementing the method
490  * @param optional override Mark the AddRef & Release methods as overrides.
491  */
492 #define NS_INLINE_DECL_REFCOUNTING(_class, ...)                               \
493   NS_INLINE_DECL_REFCOUNTING_WITH_DESTROY(_class, delete(this), __VA_ARGS__)
494 
495 #define NS_INLINE_DECL_THREADSAFE_REFCOUNTING_META(_class, _decl, ...)        \
496 public:                                                                       \
497   _decl(MozExternalRefCountType) AddRef(void) __VA_ARGS__ {                   \
498     MOZ_ASSERT_TYPE_OK_FOR_REFCOUNTING(_class)                                \
499     MOZ_ASSERT(int32_t(mRefCnt) >= 0, "illegal refcnt");                      \
500     nsrefcnt count = ++mRefCnt;                                               \
501     NS_LOG_ADDREF(this, count, #_class, sizeof(*this));                       \
502     return (nsrefcnt) count;                                                  \
503   }                                                                           \
504   _decl(MozExternalRefCountType) Release(void) __VA_ARGS__ {                  \
505     MOZ_ASSERT(int32_t(mRefCnt) > 0, "dup release");                          \
506     nsrefcnt count = --mRefCnt;                                               \
507     NS_LOG_RELEASE(this, count, #_class);                                     \
508     if (count == 0) {                                                         \
509       delete (this);                                                          \
510       return 0;                                                               \
511     }                                                                         \
512     return count;                                                             \
513   }                                                                           \
514   typedef mozilla::TrueType HasThreadSafeRefCnt;                              \
515 protected:                                                                    \
516   ::mozilla::ThreadSafeAutoRefCnt mRefCnt;                                    \
517 public:
518 
519 /**
520  * Use this macro to declare and implement the AddRef & Release methods for a
521  * given non-XPCOM <i>_class</i> in a threadsafe manner.
522  *
523  * DOES NOT DO REFCOUNT STABILIZATION!
524  *
525  * @param _class The name of the class implementing the method
526  */
527 #define NS_INLINE_DECL_THREADSAFE_REFCOUNTING(_class, ...)                    \
528 NS_INLINE_DECL_THREADSAFE_REFCOUNTING_META(_class, NS_METHOD_, __VA_ARGS__)
529 
530 /**
531  * Like NS_INLINE_DECL_THREADSAFE_REFCOUNTING with AddRef & Release declared
532  * virtual.
533  */
534 #define NS_INLINE_DECL_THREADSAFE_VIRTUAL_REFCOUNTING(_class, ...)            \
535 NS_INLINE_DECL_THREADSAFE_REFCOUNTING_META(_class, NS_IMETHOD_, __VA_ARGS__)
536 
537 /**
538  * Use this macro to implement the AddRef method for a given <i>_class</i>
539  * @param _class The name of the class implementing the method
540  */
541 #define NS_IMPL_ADDREF(_class)                                                \
542 NS_IMETHODIMP_(MozExternalRefCountType) _class::AddRef(void)                  \
543 {                                                                             \
544   MOZ_ASSERT_TYPE_OK_FOR_REFCOUNTING(_class)                                  \
545   MOZ_ASSERT(int32_t(mRefCnt) >= 0, "illegal refcnt");                        \
546   if (!mRefCnt.isThreadSafe)                                                  \
547     NS_ASSERT_OWNINGTHREAD(_class);                                           \
548   nsrefcnt count = ++mRefCnt;                                                 \
549   NS_LOG_ADDREF(this, count, #_class, sizeof(*this));                         \
550   return count;                                                               \
551 }
552 
553 /**
554  * Use this macro to implement the AddRef method for a given <i>_class</i>
555  * implemented as a wholly owned aggregated object intended to implement
556  * interface(s) for its owner
557  * @param _class The name of the class implementing the method
558  * @param _aggregator the owning/containing object
559  */
560 #define NS_IMPL_ADDREF_USING_AGGREGATOR(_class, _aggregator)                  \
561 NS_IMETHODIMP_(MozExternalRefCountType) _class::AddRef(void)                  \
562 {                                                                             \
563   MOZ_ASSERT_TYPE_OK_FOR_REFCOUNTING(_class)                                  \
564   NS_PRECONDITION(_aggregator, "null aggregator");                            \
565   return (_aggregator)->AddRef();                                             \
566 }
567 
568 /**
569  * Use this macro to implement the Release method for a given
570  * <i>_class</i>.
571  * @param _class The name of the class implementing the method
572  * @param _destroy A statement that is executed when the object's
573  *   refcount drops to zero.
574  *
575  * For example,
576  *
577  *   NS_IMPL_RELEASE_WITH_DESTROY(Foo, Destroy(this))
578  *
579  * will cause
580  *
581  *   Destroy(this);
582  *
583  * to be invoked when the object's refcount drops to zero. This
584  * allows for arbitrary teardown activity to occur (e.g., deallocation
585  * of object allocated with placement new).
586  */
587 #define NS_IMPL_RELEASE_WITH_DESTROY(_class, _destroy)                        \
588 NS_IMETHODIMP_(MozExternalRefCountType) _class::Release(void)                 \
589 {                                                                             \
590   MOZ_ASSERT(int32_t(mRefCnt) > 0, "dup release");                            \
591   if (!mRefCnt.isThreadSafe)                                                  \
592     NS_ASSERT_OWNINGTHREAD(_class);                                           \
593   nsrefcnt count = --mRefCnt;                                                 \
594   NS_LOG_RELEASE(this, count, #_class);                                       \
595   if (count == 0) {                                                           \
596     mRefCnt = 1; /* stabilize */                                              \
597     _destroy;                                                                 \
598     return 0;                                                                 \
599   }                                                                           \
600   return count;                                                               \
601 }
602 
603 /**
604  * Use this macro to implement the Release method for a given <i>_class</i>
605  * @param _class The name of the class implementing the method
606  *
607  * A note on the 'stabilization' of the refcnt to one. At that point,
608  * the object's refcount will have gone to zero. The object's
609  * destructor may trigger code that attempts to QueryInterface() and
610  * Release() 'this' again. Doing so will temporarily increment and
611  * decrement the refcount. (Only a logic error would make one try to
612  * keep a permanent hold on 'this'.)  To prevent re-entering the
613  * destructor, we make sure that no balanced refcounting can return
614  * the refcount to |0|.
615  */
616 #define NS_IMPL_RELEASE(_class) \
617   NS_IMPL_RELEASE_WITH_DESTROY(_class, delete (this))
618 
619 /**
620  * Use this macro to implement the Release method for a given <i>_class</i>
621  * implemented as a wholly owned aggregated object intended to implement
622  * interface(s) for its owner
623  * @param _class The name of the class implementing the method
624  * @param _aggregator the owning/containing object
625  */
626 #define NS_IMPL_RELEASE_USING_AGGREGATOR(_class, _aggregator)                 \
627 NS_IMETHODIMP_(MozExternalRefCountType) _class::Release(void)                 \
628 {                                                                             \
629   NS_PRECONDITION(_aggregator, "null aggregator");                            \
630   return (_aggregator)->Release();                                            \
631 }
632 
633 
634 #define NS_IMPL_CYCLE_COLLECTING_ADDREF(_class)                               \
635 NS_IMETHODIMP_(MozExternalRefCountType) _class::AddRef(void)                  \
636 {                                                                             \
637   MOZ_ASSERT_TYPE_OK_FOR_REFCOUNTING(_class)                                  \
638   MOZ_ASSERT(int32_t(mRefCnt) >= 0, "illegal refcnt");                        \
639   NS_ASSERT_OWNINGTHREAD(_class);                                             \
640   nsISupports *base = NS_CYCLE_COLLECTION_CLASSNAME(_class)::Upcast(this);    \
641   nsrefcnt count = mRefCnt.incr(base);                                        \
642   NS_LOG_ADDREF(this, count, #_class, sizeof(*this));                         \
643   return count;                                                               \
644 }
645 
646 #define NS_IMPL_CYCLE_COLLECTING_RELEASE_WITH_DESTROY(_class, _destroy)       \
647 NS_IMETHODIMP_(MozExternalRefCountType) _class::Release(void)                 \
648 {                                                                             \
649   MOZ_ASSERT(int32_t(mRefCnt) > 0, "dup release");                            \
650   NS_ASSERT_OWNINGTHREAD(_class);                                             \
651   nsISupports *base = NS_CYCLE_COLLECTION_CLASSNAME(_class)::Upcast(this);    \
652   nsrefcnt count = mRefCnt.decr(base);                                        \
653   NS_LOG_RELEASE(this, count, #_class);                                       \
654   return count;                                                               \
655 }                                                                             \
656 NS_IMETHODIMP_(void) _class::DeleteCycleCollectable(void)                     \
657 {                                                                             \
658   _destroy;                                                                   \
659 }
660 
661 #define NS_IMPL_CYCLE_COLLECTING_RELEASE(_class)                              \
662   NS_IMPL_CYCLE_COLLECTING_RELEASE_WITH_DESTROY(_class, delete (this))
663 
664 // _LAST_RELEASE can be useful when certain resources should be released
665 // as soon as we know the object will be deleted.
666 #define NS_IMPL_CYCLE_COLLECTING_RELEASE_WITH_LAST_RELEASE(_class, _last)     \
667 NS_IMETHODIMP_(MozExternalRefCountType) _class::Release(void)                 \
668 {                                                                             \
669   MOZ_ASSERT(int32_t(mRefCnt) > 0, "dup release");                            \
670   NS_ASSERT_OWNINGTHREAD(_class);                                             \
671   bool shouldDelete = false;                                                  \
672   nsISupports *base = NS_CYCLE_COLLECTION_CLASSNAME(_class)::Upcast(this);    \
673   nsrefcnt count = mRefCnt.decr(base, &shouldDelete);                         \
674   NS_LOG_RELEASE(this, count, #_class);                                       \
675   if (count == 0) {                                                           \
676       mRefCnt.incr(base);                                                     \
677       _last;                                                                  \
678       mRefCnt.decr(base);                                                     \
679       if (shouldDelete) {                                                     \
680           mRefCnt.stabilizeForDeletion();                                     \
681           DeleteCycleCollectable();                                           \
682       }                                                                       \
683   }                                                                           \
684   return count;                                                               \
685 }                                                                             \
686 NS_IMETHODIMP_(void) _class::DeleteCycleCollectable(void)                     \
687 {                                                                             \
688   delete this;                                                                \
689 }
690 
691 ///////////////////////////////////////////////////////////////////////////////
692 
693 /**
694  * There are two ways of implementing QueryInterface, and we use both:
695  *
696  * Table-driven QueryInterface uses a static table of IID->offset mappings
697  * and a shared helper function. Using it tends to reduce codesize and improve
698  * runtime performance (due to processor cache hits).
699  *
700  * Macro-driven QueryInterface generates a QueryInterface function directly
701  * using common macros. This is necessary if special QueryInterface features
702  * are being used (such as tearoffs and conditional interfaces).
703  *
704  * These methods can be combined into a table-driven function call followed
705  * by custom code for tearoffs and conditionals.
706  */
707 
708 struct QITableEntry
709 {
710   const nsIID* iid;     // null indicates end of the QITableEntry array
711   int32_t   offset;
712 };
713 
714 nsresult NS_FASTCALL
715 NS_TableDrivenQI(void* aThis, REFNSIID aIID,
716                  void** aInstancePtr, const QITableEntry* aEntries);
717 
718 /**
719  * Implement table-driven queryinterface
720  */
721 
722 #define NS_INTERFACE_TABLE_HEAD(_class)                                       \
723 NS_IMETHODIMP _class::QueryInterface(REFNSIID aIID, void** aInstancePtr)      \
724 {                                                                             \
725   NS_ASSERTION(aInstancePtr,                                                  \
726                "QueryInterface requires a non-NULL destination!");            \
727   nsresult rv = NS_ERROR_FAILURE;
728 
729 #define NS_INTERFACE_TABLE_BEGIN                                              \
730   static const QITableEntry table[] = {
731 
732 #define NS_INTERFACE_TABLE_ENTRY(_class, _interface)                          \
733   { &NS_GET_IID(_interface),                                                  \
734     int32_t(reinterpret_cast<char*>(                                          \
735                         static_cast<_interface*>((_class*) 0x1000)) -         \
736                reinterpret_cast<char*>((_class*) 0x1000))                     \
737   },
738 
739 #define NS_INTERFACE_TABLE_ENTRY_AMBIGUOUS(_class, _interface, _implClass)    \
740   { &NS_GET_IID(_interface),                                                  \
741     int32_t(reinterpret_cast<char*>(                                          \
742                         static_cast<_interface*>(                             \
743                                        static_cast<_implClass*>(              \
744                                                       (_class*) 0x1000))) -   \
745                reinterpret_cast<char*>((_class*) 0x1000))                     \
746   },
747 
748 /*
749  * XXX: we want to use mozilla::ArrayLength (or equivalent,
750  * MOZ_ARRAY_LENGTH) in this condition, but some versions of GCC don't
751  * see that the static_assert condition is actually constant in those
752  * cases, even with constexpr support (?).
753  */
754 #define NS_INTERFACE_TABLE_END_WITH_PTR(_ptr)                                 \
755   { nullptr, 0 } };                                                           \
756   static_assert((sizeof(table)/sizeof(table[0])) > 1, "need at least 1 interface"); \
757   rv = NS_TableDrivenQI(static_cast<void*>(_ptr),                             \
758                         aIID, aInstancePtr, table);
759 
760 #define NS_INTERFACE_TABLE_END                                                \
761   NS_INTERFACE_TABLE_END_WITH_PTR(this)
762 
763 #define NS_INTERFACE_TABLE_TAIL                                               \
764   return rv;                                                                  \
765 }
766 
767 #define NS_INTERFACE_TABLE_TAIL_INHERITING(_baseclass)                        \
768   if (NS_SUCCEEDED(rv))                                                       \
769     return rv;                                                                \
770   return _baseclass::QueryInterface(aIID, aInstancePtr);                      \
771 }
772 
773 #define NS_INTERFACE_TABLE_TAIL_USING_AGGREGATOR(_aggregator)                 \
774   if (NS_SUCCEEDED(rv))                                                       \
775     return rv;                                                                \
776   NS_ASSERTION(_aggregator, "null aggregator");                               \
777   return _aggregator->QueryInterface(aIID, aInstancePtr)                      \
778 }
779 
780 /**
781  * This implements query interface with two assumptions: First, the
782  * class in question implements nsISupports and its own interface and
783  * nothing else. Second, the implementation of the class's primary
784  * inheritance chain leads to its own interface.
785  *
786  * @param _class The name of the class implementing the method
787  * @param _classiiddef The name of the #define symbol that defines the IID
788  * for the class (e.g. NS_ISUPPORTS_IID)
789  */
790 
791 #define NS_IMPL_QUERY_HEAD(_class)                                            \
792 NS_IMETHODIMP _class::QueryInterface(REFNSIID aIID, void** aInstancePtr)      \
793 {                                                                             \
794   NS_ASSERTION(aInstancePtr,                                                  \
795                "QueryInterface requires a non-NULL destination!");            \
796   nsISupports* foundInterface;
797 
798 #define NS_IMPL_QUERY_BODY(_interface)                                        \
799   if ( aIID.Equals(NS_GET_IID(_interface)) )                                  \
800     foundInterface = static_cast<_interface*>(this);                          \
801   else
802 
803 #define NS_IMPL_QUERY_BODY_CONDITIONAL(_interface, condition)                 \
804   if ( (condition) && aIID.Equals(NS_GET_IID(_interface)))                    \
805     foundInterface = static_cast<_interface*>(this);                          \
806   else
807 
808 #define NS_IMPL_QUERY_BODY_AMBIGUOUS(_interface, _implClass)                  \
809   if ( aIID.Equals(NS_GET_IID(_interface)) )                                  \
810     foundInterface = static_cast<_interface*>(                                \
811                                     static_cast<_implClass*>(this));          \
812   else
813 
814 #define NS_IMPL_QUERY_BODY_AGGREGATED(_interface, _aggregate)                 \
815   if ( aIID.Equals(NS_GET_IID(_interface)) )                                  \
816     foundInterface = static_cast<_interface*>(_aggregate);                    \
817   else
818 
819 #define NS_IMPL_QUERY_TAIL_GUTS                                               \
820     foundInterface = 0;                                                       \
821   nsresult status;                                                            \
822   if ( !foundInterface )                                                      \
823     {                                                                         \
824       /* nsISupports should be handled by this point. If not, fail. */        \
825       MOZ_ASSERT(!aIID.Equals(NS_GET_IID(nsISupports)));                      \
826       status = NS_NOINTERFACE;                                                \
827     }                                                                         \
828   else                                                                        \
829     {                                                                         \
830       NS_ADDREF(foundInterface);                                              \
831       status = NS_OK;                                                         \
832     }                                                                         \
833   *aInstancePtr = foundInterface;                                             \
834   return status;                                                              \
835 }
836 
837 #define NS_IMPL_QUERY_TAIL_INHERITING(_baseclass)                             \
838     foundInterface = 0;                                                       \
839   nsresult status;                                                            \
840   if ( !foundInterface )                                                      \
841     status = _baseclass::QueryInterface(aIID, (void**)&foundInterface);       \
842   else                                                                        \
843     {                                                                         \
844       NS_ADDREF(foundInterface);                                              \
845       status = NS_OK;                                                         \
846     }                                                                         \
847   *aInstancePtr = foundInterface;                                             \
848   return status;                                                              \
849 }
850 
851 #define NS_IMPL_QUERY_TAIL_USING_AGGREGATOR(_aggregator)                      \
852     foundInterface = 0;                                                       \
853   nsresult status;                                                            \
854   if ( !foundInterface ) {                                                    \
855     NS_ASSERTION(_aggregator, "null aggregator");                             \
856     status = _aggregator->QueryInterface(aIID, (void**)&foundInterface);      \
857   } else                                                                      \
858     {                                                                         \
859       NS_ADDREF(foundInterface);                                              \
860       status = NS_OK;                                                         \
861     }                                                                         \
862   *aInstancePtr = foundInterface;                                             \
863   return status;                                                              \
864 }
865 
866 #define NS_IMPL_QUERY_TAIL(_supports_interface)                               \
867   NS_IMPL_QUERY_BODY_AMBIGUOUS(nsISupports, _supports_interface)              \
868   NS_IMPL_QUERY_TAIL_GUTS
869 
870 
871 /*
872   This is the new scheme.  Using this notation now will allow us to switch to
873   a table driven mechanism when it's ready.  Note the difference between this
874   and the (currently) underlying NS_IMPL_QUERY_INTERFACE mechanism.  You must
875   explicitly mention |nsISupports| when using the interface maps.
876 */
877 #define NS_INTERFACE_MAP_BEGIN(_implClass)      NS_IMPL_QUERY_HEAD(_implClass)
878 #define NS_INTERFACE_MAP_ENTRY(_interface)      NS_IMPL_QUERY_BODY(_interface)
879 #define NS_INTERFACE_MAP_ENTRY_CONDITIONAL(_interface, condition)             \
880   NS_IMPL_QUERY_BODY_CONDITIONAL(_interface, condition)
881 #define NS_INTERFACE_MAP_ENTRY_AGGREGATED(_interface,_aggregate)              \
882   NS_IMPL_QUERY_BODY_AGGREGATED(_interface,_aggregate)
883 
884 #define NS_INTERFACE_MAP_END                    NS_IMPL_QUERY_TAIL_GUTS
885 #define NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(_interface, _implClass)              \
886   NS_IMPL_QUERY_BODY_AMBIGUOUS(_interface, _implClass)
887 #define NS_INTERFACE_MAP_END_INHERITING(_baseClass)                           \
888   NS_IMPL_QUERY_TAIL_INHERITING(_baseClass)
889 #define NS_INTERFACE_MAP_END_AGGREGATED(_aggregator)                          \
890   NS_IMPL_QUERY_TAIL_USING_AGGREGATOR(_aggregator)
891 
892 #define NS_INTERFACE_TABLE0(_class)                                           \
893   NS_INTERFACE_TABLE_BEGIN                                                    \
894     NS_INTERFACE_TABLE_ENTRY(_class, nsISupports)                             \
895   NS_INTERFACE_TABLE_END
896 
897 #define NS_INTERFACE_TABLE(aClass, ...)                                       \
898   MOZ_STATIC_ASSERT_VALID_ARG_COUNT(__VA_ARGS__);                             \
899   NS_INTERFACE_TABLE_BEGIN                                                    \
900     MOZ_FOR_EACH(NS_INTERFACE_TABLE_ENTRY, (aClass,), (__VA_ARGS__))          \
901     NS_INTERFACE_TABLE_ENTRY_AMBIGUOUS(aClass, nsISupports,                   \
902                                        MOZ_ARG_1(__VA_ARGS__))                \
903   NS_INTERFACE_TABLE_END
904 
905 #define NS_IMPL_QUERY_INTERFACE0(_class)                                      \
906   NS_INTERFACE_TABLE_HEAD(_class)                                             \
907   NS_INTERFACE_TABLE0(_class)                                                 \
908   NS_INTERFACE_TABLE_TAIL
909 
910 #define NS_IMPL_QUERY_INTERFACE(aClass, ...)                                  \
911   NS_INTERFACE_TABLE_HEAD(aClass)                                             \
912   NS_INTERFACE_TABLE(aClass, __VA_ARGS__)                                     \
913   NS_INTERFACE_TABLE_TAIL
914 
915 /**
916  * Declare that you're going to inherit from something that already
917  * implements nsISupports, but also implements an additional interface, thus
918  * causing an ambiguity. In this case you don't need another mRefCnt, you
919  * just need to forward the definitions to the appropriate superclass. E.g.
920  *
921  * class Bar : public Foo, public nsIBar {  // both provide nsISupports
922  * public:
923  *   NS_DECL_ISUPPORTS_INHERITED
924  *   ...other nsIBar and Bar methods...
925  * };
926  */
927 #define NS_DECL_ISUPPORTS_INHERITED                                           \
928 public:                                                                       \
929   NS_IMETHOD QueryInterface(REFNSIID aIID,                                    \
930                             void** aInstancePtr) override;                \
931   NS_IMETHOD_(MozExternalRefCountType) AddRef(void) override;             \
932   NS_IMETHOD_(MozExternalRefCountType) Release(void) override;            \
933 
934 /**
935  * These macros can be used in conjunction with NS_DECL_ISUPPORTS_INHERITED
936  * to implement the nsISupports methods, forwarding the invocations to a
937  * superclass that already implements nsISupports.
938  *
939  * Note that I didn't make these inlined because they're virtual methods.
940  */
941 
942 #define NS_IMPL_ADDREF_INHERITED(Class, Super)                                \
943 NS_IMETHODIMP_(MozExternalRefCountType) Class::AddRef(void)                   \
944 {                                                                             \
945   MOZ_ASSERT_TYPE_OK_FOR_REFCOUNTING(Class)                                   \
946   nsrefcnt r = Super::AddRef();                                               \
947   NS_LOG_ADDREF(this, r, #Class, sizeof(*this));                              \
948   return r;                                                                   \
949 }
950 
951 #define NS_IMPL_RELEASE_INHERITED(Class, Super)                               \
952 NS_IMETHODIMP_(MozExternalRefCountType) Class::Release(void)                  \
953 {                                                                             \
954   nsrefcnt r = Super::Release();                                              \
955   NS_LOG_RELEASE(this, r, #Class);                                            \
956   return r;                                                                   \
957 }
958 
959 /**
960  * As above but not logging the addref/release; needed if the base
961  * class might be aggregated.
962  */
963 #define NS_IMPL_NONLOGGING_ADDREF_INHERITED(Class, Super)                     \
964 NS_IMETHODIMP_(MozExternalRefCountType) Class::AddRef(void)                   \
965 {                                                                             \
966   MOZ_ASSERT_TYPE_OK_FOR_REFCOUNTING(Class)                                   \
967   return Super::AddRef();                                                     \
968 }
969 
970 #define NS_IMPL_NONLOGGING_RELEASE_INHERITED(Class, Super)                    \
971 NS_IMETHODIMP_(MozExternalRefCountType) Class::Release(void)                  \
972 {                                                                             \
973   return Super::Release();                                                    \
974 }
975 
976 #define NS_INTERFACE_TABLE_INHERITED0(Class) /* Nothing to do here */
977 
978 #define NS_INTERFACE_TABLE_INHERITED(aClass, ...)                             \
979   MOZ_STATIC_ASSERT_VALID_ARG_COUNT(__VA_ARGS__);                             \
980   NS_INTERFACE_TABLE_BEGIN                                                    \
981     MOZ_FOR_EACH(NS_INTERFACE_TABLE_ENTRY, (aClass,), (__VA_ARGS__))          \
982   NS_INTERFACE_TABLE_END
983 
984 #define NS_IMPL_QUERY_INTERFACE_INHERITED(aClass, aSuper, ...)                \
985   NS_INTERFACE_TABLE_HEAD(aClass)                                             \
986   NS_INTERFACE_TABLE_INHERITED(aClass, __VA_ARGS__)                           \
987   NS_INTERFACE_TABLE_TAIL_INHERITING(aSuper)
988 
989 /**
990  * Convenience macros for implementing all nsISupports methods for
991  * a simple class.
992  * @param _class The name of the class implementing the method
993  * @param _classiiddef The name of the #define symbol that defines the IID
994  * for the class (e.g. NS_ISUPPORTS_IID)
995  */
996 
997 #define NS_IMPL_ISUPPORTS0(_class)                                            \
998   NS_IMPL_ADDREF(_class)                                                      \
999   NS_IMPL_RELEASE(_class)                                                     \
1000   NS_IMPL_QUERY_INTERFACE0(_class)
1001 
1002 #define NS_IMPL_ISUPPORTS(aClass, ...)                                        \
1003   NS_IMPL_ADDREF(aClass)                                                      \
1004   NS_IMPL_RELEASE(aClass)                                                     \
1005   NS_IMPL_QUERY_INTERFACE(aClass, __VA_ARGS__)
1006 
1007 #define NS_IMPL_ISUPPORTS_INHERITED0(aClass, aSuper)                          \
1008     NS_INTERFACE_TABLE_HEAD(aClass)                                           \
1009     NS_INTERFACE_TABLE_TAIL_INHERITING(aSuper)                                \
1010     NS_IMPL_ADDREF_INHERITED(aClass, aSuper)                                  \
1011     NS_IMPL_RELEASE_INHERITED(aClass, aSuper)                                 \
1012 
1013 #define NS_IMPL_ISUPPORTS_INHERITED(aClass, aSuper, ...)                      \
1014   NS_IMPL_QUERY_INTERFACE_INHERITED(aClass, aSuper, __VA_ARGS__)              \
1015   NS_IMPL_ADDREF_INHERITED(aClass, aSuper)                                    \
1016   NS_IMPL_RELEASE_INHERITED(aClass, aSuper)
1017 
1018 /*
1019  * Macro to glue together a QI that starts with an interface table
1020  * and segues into an interface map (e.g. it uses singleton classinfo
1021  * or tearoffs).
1022  */
1023 #define NS_INTERFACE_TABLE_TO_MAP_SEGUE \
1024   if (rv == NS_OK) return rv; \
1025   nsISupports* foundInterface;
1026 
1027 
1028 ///////////////////////////////////////////////////////////////////////////////
1029 /**
1030  *
1031  * Threadsafe implementations of the ISupports convenience macros.
1032  *
1033  * @note  These are not available when linking against the standalone glue,
1034  *        because the implementation requires PR_ symbols.
1035  */
1036 #define NS_INTERFACE_MAP_END_THREADSAFE NS_IMPL_QUERY_TAIL_GUTS
1037 
1038 /**
1039  * Macro to generate nsIClassInfo methods for classes which do not have
1040  * corresponding nsIFactory implementations.
1041  */
1042 #define NS_IMPL_THREADSAFE_CI(_class)                                         \
1043 NS_IMETHODIMP                                                                 \
1044 _class::GetInterfaces(uint32_t* _count, nsIID*** _array)                      \
1045 {                                                                             \
1046   return NS_CI_INTERFACE_GETTER_NAME(_class)(_count, _array);                 \
1047 }                                                                             \
1048                                                                               \
1049 NS_IMETHODIMP                                                                 \
1050 _class::GetScriptableHelper(nsIXPCScriptable** _retval)                       \
1051 {                                                                             \
1052   *_retval = nullptr;                                                         \
1053   return NS_OK;                                                               \
1054 }                                                                             \
1055                                                                               \
1056 NS_IMETHODIMP                                                                 \
1057 _class::GetContractID(char** _contractID)                                     \
1058 {                                                                             \
1059   *_contractID = nullptr;                                                     \
1060   return NS_OK;                                                               \
1061 }                                                                             \
1062                                                                               \
1063 NS_IMETHODIMP                                                                 \
1064 _class::GetClassDescription(char** _classDescription)                         \
1065 {                                                                             \
1066   *_classDescription = nullptr;                                               \
1067   return NS_OK;                                                               \
1068 }                                                                             \
1069                                                                               \
1070 NS_IMETHODIMP                                                                 \
1071 _class::GetClassID(nsCID** _classID)                                          \
1072 {                                                                             \
1073   *_classID = nullptr;                                                        \
1074   return NS_OK;                                                               \
1075 }                                                                             \
1076                                                                               \
1077 NS_IMETHODIMP                                                                 \
1078 _class::GetFlags(uint32_t* _flags)                                            \
1079 {                                                                             \
1080   *_flags = nsIClassInfo::THREADSAFE;                                         \
1081   return NS_OK;                                                               \
1082 }                                                                             \
1083                                                                               \
1084 NS_IMETHODIMP                                                                 \
1085 _class::GetClassIDNoAlloc(nsCID* _classIDNoAlloc)                             \
1086 {                                                                             \
1087   return NS_ERROR_NOT_AVAILABLE;                                              \
1088 }
1089 
1090 #endif
1091