1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/xpcom/glue/nsCycleCollectionParticipant.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,754 @@ 1.4 +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#ifndef nsCycleCollectionParticipant_h__ 1.10 +#define nsCycleCollectionParticipant_h__ 1.11 + 1.12 +#include "mozilla/MacroArgs.h" 1.13 +#include "mozilla/MacroForEach.h" 1.14 +#include "nsCycleCollectionNoteChild.h" 1.15 +#include "js/RootingAPI.h" 1.16 + 1.17 +#define NS_XPCOMCYCLECOLLECTIONPARTICIPANT_IID \ 1.18 +{ \ 1.19 + 0x9674489b, \ 1.20 + 0x1f6f, \ 1.21 + 0x4550, \ 1.22 + { 0xa7, 0x30, 0xcc, 0xae, 0xdd, 0x10, 0x4c, 0xf9 } \ 1.23 +} 1.24 + 1.25 +/** 1.26 + * Special IID to get at the base nsISupports for a class. Usually this is the 1.27 + * canonical nsISupports pointer, but in the case of tearoffs for example it is 1.28 + * the base nsISupports pointer of the tearoff. This allow the cycle collector 1.29 + * to have separate nsCycleCollectionParticipant's for tearoffs or aggregated 1.30 + * classes. 1.31 + */ 1.32 +#define NS_CYCLECOLLECTIONISUPPORTS_IID \ 1.33 +{ \ 1.34 + 0xc61eac14, \ 1.35 + 0x5f7a, \ 1.36 + 0x4481, \ 1.37 + { 0x96, 0x5e, 0x7e, 0xaa, 0x6e, 0xff, 0xa8, 0x5f } \ 1.38 +} 1.39 + 1.40 +/** 1.41 + * Just holds the IID so NS_GET_IID works. 1.42 + */ 1.43 +class nsCycleCollectionISupports 1.44 +{ 1.45 +public: 1.46 + NS_DECLARE_STATIC_IID_ACCESSOR(NS_CYCLECOLLECTIONISUPPORTS_IID) 1.47 +}; 1.48 + 1.49 +NS_DEFINE_STATIC_IID_ACCESSOR(nsCycleCollectionISupports, 1.50 + NS_CYCLECOLLECTIONISUPPORTS_IID) 1.51 + 1.52 +namespace JS { 1.53 +template <class T> class Heap; 1.54 +} /* namespace JS */ 1.55 + 1.56 +/* 1.57 + * A struct defining pure virtual methods which are called when tracing cycle 1.58 + * collection paticipants. The appropriate method is called depending on the 1.59 + * type of JS GC thing. 1.60 + */ 1.61 +struct TraceCallbacks 1.62 +{ 1.63 + virtual void Trace(JS::Heap<JS::Value>* p, const char* name, void* closure) const = 0; 1.64 + virtual void Trace(JS::Heap<jsid>* p, const char* name, void* closure) const = 0; 1.65 + virtual void Trace(JS::Heap<JSObject*>* p, const char* name, void* closure) const = 0; 1.66 + virtual void Trace(JS::TenuredHeap<JSObject*>* p, const char* name, void* closure) const = 0; 1.67 + virtual void Trace(JS::Heap<JSString*>* p, const char* name, void* closure) const = 0; 1.68 + virtual void Trace(JS::Heap<JSScript*>* p, const char* name, void* closure) const = 0; 1.69 + virtual void Trace(JS::Heap<JSFunction*>* p, const char* name, void* closure) const = 0; 1.70 +}; 1.71 + 1.72 +/* 1.73 + * An implementation of TraceCallbacks that calls a single function for all JS 1.74 + * GC thing types encountered. 1.75 + */ 1.76 +struct TraceCallbackFunc : public TraceCallbacks 1.77 +{ 1.78 + typedef void (* Func)(void* p, const char* name, void* closure); 1.79 + 1.80 + explicit TraceCallbackFunc(Func cb) : mCallback(cb) {} 1.81 + 1.82 + virtual void Trace(JS::Heap<JS::Value>* p, const char* name, void* closure) const MOZ_OVERRIDE; 1.83 + virtual void Trace(JS::Heap<jsid>* p, const char* name, void* closure) const MOZ_OVERRIDE; 1.84 + virtual void Trace(JS::Heap<JSObject*>* p, const char* name, void* closure) const MOZ_OVERRIDE; 1.85 + virtual void Trace(JS::TenuredHeap<JSObject*>* p, const char* name, void* closure) const MOZ_OVERRIDE; 1.86 + virtual void Trace(JS::Heap<JSString*>* p, const char* name, void* closure) const MOZ_OVERRIDE; 1.87 + virtual void Trace(JS::Heap<JSScript*>* p, const char* name, void* closure) const MOZ_OVERRIDE; 1.88 + virtual void Trace(JS::Heap<JSFunction*>* p, const char* name, void* closure) const MOZ_OVERRIDE; 1.89 + 1.90 + private: 1.91 + Func mCallback; 1.92 +}; 1.93 + 1.94 +/** 1.95 + * Participant implementation classes 1.96 + */ 1.97 +class NS_NO_VTABLE nsCycleCollectionParticipant 1.98 +{ 1.99 +public: 1.100 + MOZ_CONSTEXPR nsCycleCollectionParticipant() : mMightSkip(false) {} 1.101 + MOZ_CONSTEXPR nsCycleCollectionParticipant(bool aSkip) : mMightSkip(aSkip) {} 1.102 + 1.103 + NS_IMETHOD Traverse(void *p, nsCycleCollectionTraversalCallback &cb) = 0; 1.104 + 1.105 + NS_IMETHOD_(void) Root(void *p) = 0; 1.106 + NS_IMETHOD_(void) Unlink(void *p) = 0; 1.107 + NS_IMETHOD_(void) Unroot(void *p) = 0; 1.108 + 1.109 + NS_IMETHOD_(void) Trace(void *p, const TraceCallbacks &cb, void *closure) {}; 1.110 + 1.111 + // If CanSkip returns true, p is removed from the purple buffer during 1.112 + // a call to nsCycleCollector_forgetSkippable(). 1.113 + // Note, calling CanSkip may remove objects from the purple buffer! 1.114 + // If aRemovingAllowed is true, p can be removed from the purple buffer. 1.115 + bool CanSkip(void *p, bool aRemovingAllowed) 1.116 + { 1.117 + return mMightSkip ? CanSkipReal(p, aRemovingAllowed) : false; 1.118 + } 1.119 + 1.120 + // If CanSkipInCC returns true, p is skipped when selecting roots for the 1.121 + // cycle collector graph. 1.122 + // Note, calling CanSkipInCC may remove other objects from the purple buffer! 1.123 + bool CanSkipInCC(void *p) 1.124 + { 1.125 + return mMightSkip ? CanSkipInCCReal(p) : false; 1.126 + } 1.127 + 1.128 + // If CanSkipThis returns true, p is not added to the graph. 1.129 + // This method is called during cycle collection, so don't 1.130 + // change the state of any objects! 1.131 + bool CanSkipThis(void *p) 1.132 + { 1.133 + return mMightSkip ? CanSkipThisReal(p) : false; 1.134 + } 1.135 + 1.136 + NS_IMETHOD_(void) DeleteCycleCollectable(void *n) = 0; 1.137 + 1.138 +protected: 1.139 + NS_IMETHOD_(bool) CanSkipReal(void *p, bool aRemovingAllowed) 1.140 + { 1.141 + NS_ASSERTION(false, "Forgot to implement CanSkipReal?"); 1.142 + return false; 1.143 + } 1.144 + NS_IMETHOD_(bool) CanSkipInCCReal(void *p) 1.145 + { 1.146 + NS_ASSERTION(false, "Forgot to implement CanSkipInCCReal?"); 1.147 + return false; 1.148 + } 1.149 + NS_IMETHOD_(bool) CanSkipThisReal(void *p) 1.150 + { 1.151 + NS_ASSERTION(false, "Forgot to implement CanSkipThisReal?"); 1.152 + return false; 1.153 + } 1.154 + 1.155 +private: 1.156 + const bool mMightSkip; 1.157 +}; 1.158 + 1.159 +class NS_NO_VTABLE nsScriptObjectTracer : public nsCycleCollectionParticipant 1.160 +{ 1.161 +public: 1.162 + MOZ_CONSTEXPR nsScriptObjectTracer() : nsCycleCollectionParticipant(false) {} 1.163 + MOZ_CONSTEXPR nsScriptObjectTracer(bool aSkip) : nsCycleCollectionParticipant(aSkip) {} 1.164 + 1.165 + NS_IMETHOD_(void) Trace(void *p, const TraceCallbacks &cb, void *closure) = 0; 1.166 + 1.167 + static void NS_COM_GLUE NoteJSChild(void *aScriptThing, const char *name, 1.168 + void *aClosure); 1.169 +}; 1.170 + 1.171 +class NS_NO_VTABLE nsXPCOMCycleCollectionParticipant : public nsScriptObjectTracer 1.172 +{ 1.173 +public: 1.174 + MOZ_CONSTEXPR nsXPCOMCycleCollectionParticipant() : nsScriptObjectTracer(false) {} 1.175 + MOZ_CONSTEXPR nsXPCOMCycleCollectionParticipant(bool aSkip) : nsScriptObjectTracer(aSkip) {} 1.176 + 1.177 + NS_DECLARE_STATIC_IID_ACCESSOR(NS_XPCOMCYCLECOLLECTIONPARTICIPANT_IID) 1.178 + 1.179 + NS_IMETHOD_(void) Root(void *p); 1.180 + NS_IMETHOD_(void) Unroot(void *p); 1.181 + 1.182 + NS_IMETHOD_(void) Trace(void *p, const TraceCallbacks &cb, void *closure); 1.183 + 1.184 + static bool CheckForRightISupports(nsISupports *s); 1.185 +}; 1.186 + 1.187 +NS_DEFINE_STATIC_IID_ACCESSOR(nsXPCOMCycleCollectionParticipant, 1.188 + NS_XPCOMCYCLECOLLECTIONPARTICIPANT_IID) 1.189 + 1.190 +/////////////////////////////////////////////////////////////////////////////// 1.191 +// Helpers for implementing a QI to nsXPCOMCycleCollectionParticipant 1.192 +/////////////////////////////////////////////////////////////////////////////// 1.193 + 1.194 +#define NS_CYCLE_COLLECTION_CLASSNAME(_class) \ 1.195 + _class::NS_CYCLE_COLLECTION_INNERCLASS 1.196 + 1.197 +#define NS_IMPL_QUERY_CYCLE_COLLECTION(_class) \ 1.198 + if ( aIID.Equals(NS_GET_IID(nsXPCOMCycleCollectionParticipant)) ) { \ 1.199 + *aInstancePtr = NS_CYCLE_COLLECTION_PARTICIPANT(_class); \ 1.200 + return NS_OK; \ 1.201 + } else 1.202 + 1.203 +#define NS_IMPL_QUERY_CYCLE_COLLECTION_ISUPPORTS(_class) \ 1.204 + if ( aIID.Equals(NS_GET_IID(nsCycleCollectionISupports)) ) { \ 1.205 + *aInstancePtr = NS_CYCLE_COLLECTION_CLASSNAME(_class)::Upcast(this); \ 1.206 + return NS_OK; \ 1.207 + } else 1.208 + 1.209 +#define NS_INTERFACE_MAP_ENTRY_CYCLE_COLLECTION(_class) \ 1.210 + NS_IMPL_QUERY_CYCLE_COLLECTION(_class) 1.211 + 1.212 +#define NS_INTERFACE_MAP_ENTRY_CYCLE_COLLECTION_ISUPPORTS(_class) \ 1.213 + NS_IMPL_QUERY_CYCLE_COLLECTION_ISUPPORTS(_class) 1.214 + 1.215 +#define NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(_class) \ 1.216 + NS_INTERFACE_MAP_ENTRY_CYCLE_COLLECTION(_class) \ 1.217 + NS_INTERFACE_MAP_ENTRY_CYCLE_COLLECTION_ISUPPORTS(_class) 1.218 + 1.219 +#define NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(_class) \ 1.220 + NS_INTERFACE_MAP_BEGIN(_class) \ 1.221 + NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(_class) 1.222 + 1.223 +#define NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(_class) \ 1.224 + NS_INTERFACE_MAP_BEGIN(_class) \ 1.225 + NS_INTERFACE_MAP_ENTRY_CYCLE_COLLECTION(_class) 1.226 + 1.227 +#define NS_INTERFACE_TABLE_TO_MAP_SEGUE_CYCLE_COLLECTION(_class) \ 1.228 + if (rv == NS_OK) return rv; \ 1.229 + nsISupports* foundInterface; \ 1.230 + NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(_class) 1.231 + 1.232 +#define NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(_class) \ 1.233 + NS_IMETHODIMP _class::QueryInterface(REFNSIID aIID, void** aInstancePtr) \ 1.234 + { \ 1.235 + NS_PRECONDITION(aInstancePtr, "null out param"); \ 1.236 + \ 1.237 + if ( aIID.Equals(NS_GET_IID(nsXPCOMCycleCollectionParticipant)) ) { \ 1.238 + *aInstancePtr = NS_CYCLE_COLLECTION_PARTICIPANT(_class); \ 1.239 + return NS_OK; \ 1.240 + } \ 1.241 + nsresult rv; 1.242 + 1.243 +#define NS_CYCLE_COLLECTION_UPCAST(obj, clazz) \ 1.244 + NS_CYCLE_COLLECTION_CLASSNAME(clazz)::Upcast(obj) 1.245 + 1.246 +#ifdef DEBUG 1.247 +#define NS_CHECK_FOR_RIGHT_PARTICIPANT(_ptr) _ptr->CheckForRightParticipant() 1.248 +#else 1.249 +#define NS_CHECK_FOR_RIGHT_PARTICIPANT(_ptr) 1.250 +#endif 1.251 + 1.252 +// The default implementation of this class template is empty, because it 1.253 +// should never be used: see the partial specializations below. 1.254 +template <typename T, 1.255 + bool IsXPCOM = mozilla::IsBaseOf<nsISupports, T>::value> 1.256 +struct DowncastCCParticipantImpl 1.257 +{ 1.258 +}; 1.259 + 1.260 +// Specialization for XPCOM CC participants 1.261 +template <typename T> 1.262 +struct DowncastCCParticipantImpl<T, true> 1.263 +{ 1.264 + static T* Run(void *p) 1.265 + { 1.266 + nsISupports *s = static_cast<nsISupports*>(p); 1.267 + MOZ_ASSERT(NS_CYCLE_COLLECTION_CLASSNAME(T)::CheckForRightISupports(s), 1.268 + "not the nsISupports pointer we expect"); 1.269 + T *rval = NS_CYCLE_COLLECTION_CLASSNAME(T)::Downcast(s); 1.270 + NS_CHECK_FOR_RIGHT_PARTICIPANT(rval); 1.271 + return rval; 1.272 + } 1.273 +}; 1.274 + 1.275 +// Specialization for native CC participants 1.276 +template <typename T> 1.277 +struct DowncastCCParticipantImpl<T, false> 1.278 +{ 1.279 + static T* Run(void *p) 1.280 + { 1.281 + return static_cast<T*>(p); 1.282 + } 1.283 +}; 1.284 + 1.285 +template <typename T> 1.286 +T* DowncastCCParticipant(void *p) 1.287 +{ 1.288 + return DowncastCCParticipantImpl<T>::Run(p); 1.289 +} 1.290 + 1.291 +/////////////////////////////////////////////////////////////////////////////// 1.292 +// Helpers for implementing CanSkip methods 1.293 +/////////////////////////////////////////////////////////////////////////////// 1.294 + 1.295 +#define NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN(_class) \ 1.296 + NS_IMETHODIMP_(bool) \ 1.297 + NS_CYCLE_COLLECTION_CLASSNAME(_class)::CanSkipReal(void *p, \ 1.298 + bool aRemovingAllowed) \ 1.299 + { \ 1.300 + _class *tmp = DowncastCCParticipant<_class >(p); 1.301 + 1.302 +#define NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_END \ 1.303 + (void)tmp; \ 1.304 + return false; \ 1.305 + } 1.306 + 1.307 +#define NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_BEGIN(_class) \ 1.308 + NS_IMETHODIMP_(bool) \ 1.309 + NS_CYCLE_COLLECTION_CLASSNAME(_class)::CanSkipInCCReal(void *p) \ 1.310 + { \ 1.311 + _class *tmp = DowncastCCParticipant<_class >(p); 1.312 + 1.313 +#define NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_END \ 1.314 + (void)tmp; \ 1.315 + return false; \ 1.316 + } 1.317 + 1.318 +#define NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_BEGIN(_class) \ 1.319 + NS_IMETHODIMP_(bool) \ 1.320 + NS_CYCLE_COLLECTION_CLASSNAME(_class)::CanSkipThisReal(void *p) \ 1.321 + { \ 1.322 + _class *tmp = DowncastCCParticipant<_class >(p); 1.323 + 1.324 +#define NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_END \ 1.325 + (void)tmp; \ 1.326 + return false; \ 1.327 + } 1.328 + 1.329 +/////////////////////////////////////////////////////////////////////////////// 1.330 +// Helpers for implementing nsCycleCollectionParticipant::Unlink 1.331 +// 1.332 +// You need to use NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED if you want 1.333 +// the base class Unlink version to be called before your own implementation. 1.334 +// You can use NS_IMPL_CYCLE_COLLECTION_UNLINK_END_INHERITED if you want the 1.335 +// base class Unlink to get called after your own implementation. You should 1.336 +// never use them together. 1.337 +/////////////////////////////////////////////////////////////////////////////// 1.338 + 1.339 +#define NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(_class) \ 1.340 + NS_IMETHODIMP_(void) \ 1.341 + NS_CYCLE_COLLECTION_CLASSNAME(_class)::Unlink(void *p) \ 1.342 + { \ 1.343 + _class *tmp = DowncastCCParticipant<_class >(p); 1.344 + 1.345 +#define NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(_class, _base_class) \ 1.346 + NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(_class) \ 1.347 + nsISupports *s = static_cast<nsISupports*>(p); \ 1.348 + NS_CYCLE_COLLECTION_CLASSNAME(_base_class)::Unlink(s); 1.349 + 1.350 +#define NS_IMPL_CYCLE_COLLECTION_UNLINK_HELPER(_field) \ 1.351 + ImplCycleCollectionUnlink(tmp->_field); 1.352 + 1.353 +#define NS_IMPL_CYCLE_COLLECTION_UNLINK(...) \ 1.354 + MOZ_STATIC_ASSERT_VALID_ARG_COUNT(__VA_ARGS__); \ 1.355 + MOZ_FOR_EACH(NS_IMPL_CYCLE_COLLECTION_UNLINK_HELPER, (), (__VA_ARGS__)) 1.356 + 1.357 +#define NS_IMPL_CYCLE_COLLECTION_UNLINK_END \ 1.358 + (void)tmp; \ 1.359 + } 1.360 + 1.361 +#define NS_IMPL_CYCLE_COLLECTION_UNLINK_END_INHERITED(_base_class) \ 1.362 + nsISupports *s = static_cast<nsISupports*>(p); \ 1.363 + NS_CYCLE_COLLECTION_CLASSNAME(_base_class)::Unlink(s); \ 1.364 + (void)tmp; \ 1.365 + } 1.366 + 1.367 +#define NS_IMPL_CYCLE_COLLECTION_UNLINK_0(_class) \ 1.368 + NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(_class) \ 1.369 + NS_IMPL_CYCLE_COLLECTION_UNLINK_END 1.370 + 1.371 + 1.372 +/////////////////////////////////////////////////////////////////////////////// 1.373 +// Helpers for implementing nsCycleCollectionParticipant::Traverse 1.374 +/////////////////////////////////////////////////////////////////////////////// 1.375 + 1.376 +#define NS_IMPL_CYCLE_COLLECTION_DESCRIBE(_class, _refcnt) \ 1.377 + cb.DescribeRefCountedNode(_refcnt, #_class); 1.378 + 1.379 +#define NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(_class) \ 1.380 + NS_IMETHODIMP \ 1.381 + NS_CYCLE_COLLECTION_CLASSNAME(_class)::Traverse \ 1.382 + (void *p, nsCycleCollectionTraversalCallback &cb) \ 1.383 + { \ 1.384 + _class *tmp = DowncastCCParticipant<_class >(p); 1.385 + 1.386 +#define NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(_class) \ 1.387 + NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(_class) \ 1.388 + NS_IMPL_CYCLE_COLLECTION_DESCRIBE(_class, tmp->mRefCnt.get()) 1.389 + 1.390 +// Base class' CC participant should return NS_SUCCESS_INTERRUPTED_TRAVERSE 1.391 +// from Traverse if it wants derived classes to not traverse anything from 1.392 +// their CC participant. 1.393 + 1.394 +#define NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(_class, _base_class) \ 1.395 + NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(_class) \ 1.396 + nsISupports *s = static_cast<nsISupports*>(p); \ 1.397 + if (NS_CYCLE_COLLECTION_CLASSNAME(_base_class)::Traverse(s, cb) \ 1.398 + == NS_SUCCESS_INTERRUPTED_TRAVERSE) { \ 1.399 + return NS_SUCCESS_INTERRUPTED_TRAVERSE; \ 1.400 + } 1.401 + 1.402 +#define NS_IMPL_CYCLE_COLLECTION_TRAVERSE_HELPER(_field) \ 1.403 + ImplCycleCollectionTraverse(cb, tmp->_field, #_field, 0); 1.404 + 1.405 +#define NS_IMPL_CYCLE_COLLECTION_TRAVERSE(...) \ 1.406 + MOZ_STATIC_ASSERT_VALID_ARG_COUNT(__VA_ARGS__); \ 1.407 + MOZ_FOR_EACH(NS_IMPL_CYCLE_COLLECTION_TRAVERSE_HELPER, (), (__VA_ARGS__)) 1.408 + 1.409 +#define NS_IMPL_CYCLE_COLLECTION_TRAVERSE_RAWPTR(_field) \ 1.410 + CycleCollectionNoteChild(cb, tmp->_field, #_field); 1.411 + 1.412 +#define NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS \ 1.413 + { \ 1.414 + TraceCallbackFunc noteJsChild(&nsScriptObjectTracer::NoteJSChild); \ 1.415 + Trace(p, noteJsChild, &cb); \ 1.416 + } 1.417 + 1.418 +#define NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END \ 1.419 + (void)tmp; \ 1.420 + return NS_OK; \ 1.421 + } 1.422 + 1.423 +/////////////////////////////////////////////////////////////////////////////// 1.424 +// Helpers for implementing nsScriptObjectTracer::Trace 1.425 +/////////////////////////////////////////////////////////////////////////////// 1.426 + 1.427 +#define NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(_class) \ 1.428 + void \ 1.429 + NS_CYCLE_COLLECTION_CLASSNAME(_class)::Trace(void *p, \ 1.430 + const TraceCallbacks &aCallbacks, \ 1.431 + void *aClosure) \ 1.432 + { \ 1.433 + _class *tmp = DowncastCCParticipant<_class >(p); 1.434 + 1.435 +#define NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(_class, _base_class) \ 1.436 + NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(_class) \ 1.437 + nsISupports *s = static_cast<nsISupports*>(p); \ 1.438 + NS_CYCLE_COLLECTION_CLASSNAME(_base_class)::Trace(s, aCallbacks, aClosure); 1.439 + 1.440 +#define NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(_field) \ 1.441 + if (tmp->_field) \ 1.442 + aCallbacks.Trace(&tmp->_field, #_field, aClosure); 1.443 + 1.444 +#define NS_IMPL_CYCLE_COLLECTION_TRACE_JSVAL_MEMBER_CALLBACK(_field) \ 1.445 + aCallbacks.Trace(&tmp->_field, #_field, aClosure); 1.446 + 1.447 +// NB: The (void)tmp; hack in the TRACE_END macro exists to support 1.448 +// implementations that don't need to do anything in their Trace method. 1.449 +// Without this hack, some compilers warn about the unused tmp local. 1.450 +#define NS_IMPL_CYCLE_COLLECTION_TRACE_END \ 1.451 + (void)tmp; \ 1.452 + } 1.453 + 1.454 +/////////////////////////////////////////////////////////////////////////////// 1.455 +// Helpers for implementing a concrete nsCycleCollectionParticipant 1.456 +/////////////////////////////////////////////////////////////////////////////// 1.457 + 1.458 +// If a class defines a participant, then QIing an instance of that class to 1.459 +// nsXPCOMCycleCollectionParticipant should produce that participant. 1.460 +#ifdef DEBUG 1.461 +#define NS_CHECK_FOR_RIGHT_PARTICIPANT_IMPL(_class) \ 1.462 + virtual void CheckForRightParticipant() \ 1.463 + { \ 1.464 + nsXPCOMCycleCollectionParticipant *p; \ 1.465 + CallQueryInterface(this, &p); \ 1.466 + MOZ_ASSERT(p == &NS_CYCLE_COLLECTION_INNERNAME, \ 1.467 + #_class " should QI to its own CC participant"); \ 1.468 + } 1.469 +#else 1.470 +#define NS_CHECK_FOR_RIGHT_PARTICIPANT_IMPL(_class) 1.471 +#endif 1.472 + 1.473 +#define NS_DECL_CYCLE_COLLECTION_CLASS_BODY_NO_UNLINK(_class, _base) \ 1.474 +public: \ 1.475 + NS_IMETHOD Traverse(void *p, nsCycleCollectionTraversalCallback &cb); \ 1.476 + NS_IMETHOD_(void) DeleteCycleCollectable(void *p) \ 1.477 + { \ 1.478 + DowncastCCParticipant<_class>(p)->DeleteCycleCollectable(); \ 1.479 + } \ 1.480 + static _class* Downcast(nsISupports* s) \ 1.481 + { \ 1.482 + return static_cast<_class*>(static_cast<_base*>(s)); \ 1.483 + } \ 1.484 + static nsISupports* Upcast(_class *p) \ 1.485 + { \ 1.486 + return NS_ISUPPORTS_CAST(_base*, p); \ 1.487 + } \ 1.488 + template <typename T> \ 1.489 + friend nsISupports* \ 1.490 + ToSupports(T* p, NS_CYCLE_COLLECTION_INNERCLASS* dummy); 1.491 + 1.492 +#define NS_DECL_CYCLE_COLLECTION_CLASS_BODY(_class, _base) \ 1.493 + NS_DECL_CYCLE_COLLECTION_CLASS_BODY_NO_UNLINK(_class, _base) \ 1.494 + NS_IMETHOD_(void) Unlink(void *p); 1.495 + 1.496 +#define NS_PARTICIPANT_AS(type, participant) \ 1.497 + const_cast<type*>(reinterpret_cast<const type*>(participant)) 1.498 + 1.499 +#define NS_IMPL_GET_XPCOM_CYCLE_COLLECTION_PARTICIPANT(_class) \ 1.500 + static MOZ_CONSTEXPR nsXPCOMCycleCollectionParticipant* GetParticipant() \ 1.501 + { \ 1.502 + return &_class::NS_CYCLE_COLLECTION_INNERNAME; \ 1.503 + } 1.504 + 1.505 +/** 1.506 + * We use this macro to force that classes that inherit from a ccable class and 1.507 + * declare their own participant declare themselves as inherited cc classes. 1.508 + * To avoid possibly unnecessary vtables we only do this checking in debug 1.509 + * builds. 1.510 + */ 1.511 +#ifdef DEBUG 1.512 +#define NOT_INHERITED_CANT_OVERRIDE virtual void BaseCycleCollectable() MOZ_FINAL {} 1.513 +#else 1.514 +#define NOT_INHERITED_CANT_OVERRIDE 1.515 +#endif 1.516 + 1.517 +#define NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(_class, _base) \ 1.518 +class NS_CYCLE_COLLECTION_INNERCLASS \ 1.519 + : public nsXPCOMCycleCollectionParticipant \ 1.520 +{ \ 1.521 + NS_DECL_CYCLE_COLLECTION_CLASS_BODY(_class, _base) \ 1.522 + NS_IMPL_GET_XPCOM_CYCLE_COLLECTION_PARTICIPANT(_class) \ 1.523 +}; \ 1.524 +NS_CHECK_FOR_RIGHT_PARTICIPANT_IMPL(_class) \ 1.525 +static NS_CYCLE_COLLECTION_INNERCLASS NS_CYCLE_COLLECTION_INNERNAME; \ 1.526 + NOT_INHERITED_CANT_OVERRIDE 1.527 + 1.528 +#define NS_DECL_CYCLE_COLLECTION_CLASS(_class) \ 1.529 + NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(_class, _class) 1.530 + 1.531 +// Cycle collector helper for ambiguous classes that can sometimes be skipped. 1.532 +#define NS_DECL_CYCLE_COLLECTION_SKIPPABLE_CLASS_AMBIGUOUS(_class, _base) \ 1.533 +class NS_CYCLE_COLLECTION_INNERCLASS \ 1.534 + : public nsXPCOMCycleCollectionParticipant \ 1.535 +{ \ 1.536 +public: \ 1.537 + MOZ_CONSTEXPR NS_CYCLE_COLLECTION_INNERCLASS () \ 1.538 + : nsXPCOMCycleCollectionParticipant(true) {} \ 1.539 +private: \ 1.540 + NS_DECL_CYCLE_COLLECTION_CLASS_BODY(_class, _base) \ 1.541 + NS_IMETHOD_(bool) CanSkipReal(void *p, bool aRemovingAllowed); \ 1.542 + NS_IMETHOD_(bool) CanSkipInCCReal(void *p); \ 1.543 + NS_IMETHOD_(bool) CanSkipThisReal(void *p); \ 1.544 + NS_IMPL_GET_XPCOM_CYCLE_COLLECTION_PARTICIPANT(_class) \ 1.545 +}; \ 1.546 +NS_CHECK_FOR_RIGHT_PARTICIPANT_IMPL(_class) \ 1.547 +static NS_CYCLE_COLLECTION_INNERCLASS NS_CYCLE_COLLECTION_INNERNAME; \ 1.548 +NOT_INHERITED_CANT_OVERRIDE 1.549 + 1.550 +#define NS_DECL_CYCLE_COLLECTION_SKIPPABLE_CLASS(_class) \ 1.551 + NS_DECL_CYCLE_COLLECTION_SKIPPABLE_CLASS_AMBIGUOUS(_class, _class) 1.552 + 1.553 +#define NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(_class, _base) \ 1.554 +class NS_CYCLE_COLLECTION_INNERCLASS \ 1.555 + : public nsXPCOMCycleCollectionParticipant \ 1.556 +{ \ 1.557 + NS_DECL_CYCLE_COLLECTION_CLASS_BODY(_class, _base) \ 1.558 + NS_IMETHOD_(void) Trace(void *p, const TraceCallbacks &cb, void *closure); \ 1.559 + NS_IMPL_GET_XPCOM_CYCLE_COLLECTION_PARTICIPANT(_class) \ 1.560 +}; \ 1.561 +NS_CHECK_FOR_RIGHT_PARTICIPANT_IMPL(_class) \ 1.562 +static NS_CYCLE_COLLECTION_INNERCLASS NS_CYCLE_COLLECTION_INNERNAME; \ 1.563 +NOT_INHERITED_CANT_OVERRIDE 1.564 + 1.565 +#define NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS_AMBIGUOUS(_class, _base) \ 1.566 +class NS_CYCLE_COLLECTION_INNERCLASS \ 1.567 + : public nsXPCOMCycleCollectionParticipant \ 1.568 +{ \ 1.569 +public: \ 1.570 + MOZ_CONSTEXPR NS_CYCLE_COLLECTION_INNERCLASS () \ 1.571 + : nsXPCOMCycleCollectionParticipant(true) {} \ 1.572 +private: \ 1.573 + NS_DECL_CYCLE_COLLECTION_CLASS_BODY(_class, _base) \ 1.574 + NS_IMETHOD_(void) Trace(void *p, const TraceCallbacks &cb, void *closure); \ 1.575 + NS_IMETHOD_(bool) CanSkipReal(void *p, bool aRemovingAllowed); \ 1.576 + NS_IMETHOD_(bool) CanSkipInCCReal(void *p); \ 1.577 + NS_IMETHOD_(bool) CanSkipThisReal(void *p); \ 1.578 + NS_IMPL_GET_XPCOM_CYCLE_COLLECTION_PARTICIPANT(_class) \ 1.579 +}; \ 1.580 +NS_CHECK_FOR_RIGHT_PARTICIPANT_IMPL(_class) \ 1.581 +static NS_CYCLE_COLLECTION_INNERCLASS NS_CYCLE_COLLECTION_INNERNAME; \ 1.582 +NOT_INHERITED_CANT_OVERRIDE 1.583 + 1.584 +#define NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS(_class) \ 1.585 + NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS_AMBIGUOUS(_class, _class) 1.586 + 1.587 +#define NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS_INHERITED(_class, \ 1.588 + _base_class) \ 1.589 +class NS_CYCLE_COLLECTION_INNERCLASS \ 1.590 + : public NS_CYCLE_COLLECTION_CLASSNAME(_base_class) \ 1.591 +{ \ 1.592 + NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_BODY(_class, _base_class) \ 1.593 + NS_IMETHOD_(void) Trace(void *p, const TraceCallbacks &cb, void *closure); \ 1.594 + NS_IMETHOD_(bool) CanSkipReal(void *p, bool aRemovingAllowed); \ 1.595 + NS_IMETHOD_(bool) CanSkipInCCReal(void *p); \ 1.596 + NS_IMETHOD_(bool) CanSkipThisReal(void *p); \ 1.597 + NS_IMPL_GET_XPCOM_CYCLE_COLLECTION_PARTICIPANT(_class) \ 1.598 +}; \ 1.599 +NS_CHECK_FOR_RIGHT_PARTICIPANT_IMPL(_class) \ 1.600 +static NS_CYCLE_COLLECTION_INNERCLASS NS_CYCLE_COLLECTION_INNERNAME; 1.601 + 1.602 +#define NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(_class) \ 1.603 + NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(_class, _class) 1.604 + 1.605 +#define NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_BODY_NO_UNLINK(_class, \ 1.606 + _base_class) \ 1.607 +public: \ 1.608 + NS_IMETHOD Traverse(void *p, nsCycleCollectionTraversalCallback &cb); \ 1.609 + static _class* Downcast(nsISupports* s) \ 1.610 + { \ 1.611 + return static_cast<_class*>(static_cast<_base_class*>( \ 1.612 + NS_CYCLE_COLLECTION_CLASSNAME(_base_class)::Downcast(s))); \ 1.613 + } 1.614 + 1.615 +#define NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_BODY(_class, _base_class) \ 1.616 + NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_BODY_NO_UNLINK(_class, _base_class) \ 1.617 + NS_IMETHOD_(void) Unlink(void *p); 1.618 + 1.619 +#define NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(_class, _base_class) \ 1.620 +class NS_CYCLE_COLLECTION_INNERCLASS \ 1.621 + : public NS_CYCLE_COLLECTION_CLASSNAME(_base_class) \ 1.622 +{ \ 1.623 +public: \ 1.624 + NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_BODY(_class, _base_class) \ 1.625 + NS_IMPL_GET_XPCOM_CYCLE_COLLECTION_PARTICIPANT(_class) \ 1.626 +}; \ 1.627 +NS_CHECK_FOR_RIGHT_PARTICIPANT_IMPL(_class) \ 1.628 +static NS_CYCLE_COLLECTION_INNERCLASS NS_CYCLE_COLLECTION_INNERNAME; 1.629 + 1.630 +#define NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_NO_UNLINK(_class, \ 1.631 + _base_class) \ 1.632 +class NS_CYCLE_COLLECTION_INNERCLASS \ 1.633 + : public NS_CYCLE_COLLECTION_CLASSNAME(_base_class) \ 1.634 +{ \ 1.635 +public: \ 1.636 + NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_BODY_NO_UNLINK(_class, _base_class) \ 1.637 + NS_IMPL_GET_XPCOM_CYCLE_COLLECTION_PARTICIPANT(_class) \ 1.638 +}; \ 1.639 +NS_CHECK_FOR_RIGHT_PARTICIPANT_IMPL(_class) \ 1.640 +static NS_CYCLE_COLLECTION_INNERCLASS NS_CYCLE_COLLECTION_INNERNAME; 1.641 + 1.642 +#define NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(_class, \ 1.643 + _base_class) \ 1.644 +class NS_CYCLE_COLLECTION_INNERCLASS \ 1.645 + : public NS_CYCLE_COLLECTION_CLASSNAME(_base_class) \ 1.646 +{ \ 1.647 + NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_BODY(_class, _base_class) \ 1.648 + NS_IMETHOD_(void) Trace(void *p, const TraceCallbacks &cb, void *closure); \ 1.649 + NS_IMPL_GET_XPCOM_CYCLE_COLLECTION_PARTICIPANT(_class) \ 1.650 +}; \ 1.651 +NS_CHECK_FOR_RIGHT_PARTICIPANT_IMPL(_class) \ 1.652 +static NS_CYCLE_COLLECTION_INNERCLASS NS_CYCLE_COLLECTION_INNERNAME; 1.653 + 1.654 +// Cycle collector participant declarations. 1.655 + 1.656 +#define NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS_BODY(_class) \ 1.657 + public: \ 1.658 + NS_IMETHOD_(void) Root(void *n); \ 1.659 + NS_IMETHOD_(void) Unlink(void *n); \ 1.660 + NS_IMETHOD_(void) Unroot(void *n); \ 1.661 + NS_IMETHOD Traverse(void *n, nsCycleCollectionTraversalCallback &cb); \ 1.662 + NS_IMETHOD_(void) DeleteCycleCollectable(void *n) \ 1.663 + { \ 1.664 + DowncastCCParticipant<_class>(n)->DeleteCycleCollectable(); \ 1.665 + } \ 1.666 + static _class* Downcast(void* s) \ 1.667 + { \ 1.668 + return DowncastCCParticipant<_class>(s); \ 1.669 + } \ 1.670 + static void* Upcast(_class *p) \ 1.671 + { \ 1.672 + return static_cast<void*>(p); \ 1.673 + } 1.674 + 1.675 +#define NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(_class) \ 1.676 + void DeleteCycleCollectable(void) \ 1.677 + { \ 1.678 + delete this; \ 1.679 + } \ 1.680 + class NS_CYCLE_COLLECTION_INNERCLASS \ 1.681 + : public nsCycleCollectionParticipant \ 1.682 + { \ 1.683 + NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS_BODY(_class) \ 1.684 + static MOZ_CONSTEXPR nsCycleCollectionParticipant* GetParticipant() \ 1.685 + { \ 1.686 + return &_class::NS_CYCLE_COLLECTION_INNERNAME; \ 1.687 + } \ 1.688 + }; \ 1.689 + static NS_CYCLE_COLLECTION_INNERCLASS NS_CYCLE_COLLECTION_INNERNAME; 1.690 + 1.691 +#define NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(_class) \ 1.692 + void DeleteCycleCollectable(void) \ 1.693 + { \ 1.694 + delete this; \ 1.695 + } \ 1.696 + class NS_CYCLE_COLLECTION_INNERCLASS \ 1.697 + : public nsScriptObjectTracer \ 1.698 + { \ 1.699 + NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS_BODY(_class) \ 1.700 + NS_IMETHOD_(void) Trace(void *p, const TraceCallbacks &cb, void *closure); \ 1.701 + static MOZ_CONSTEXPR nsScriptObjectTracer* GetParticipant() \ 1.702 + { \ 1.703 + return &_class::NS_CYCLE_COLLECTION_INNERNAME; \ 1.704 + } \ 1.705 + }; \ 1.706 + static NS_CYCLE_COLLECTION_INNERCLASS NS_CYCLE_COLLECTION_INNERNAME; 1.707 + 1.708 +#define NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(_class, _root_function) \ 1.709 + NS_IMETHODIMP_(void) \ 1.710 + NS_CYCLE_COLLECTION_CLASSNAME(_class)::Root(void *p) \ 1.711 + { \ 1.712 + _class *tmp = static_cast<_class*>(p); \ 1.713 + tmp->_root_function(); \ 1.714 + } 1.715 + 1.716 +#define NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(_class, _unroot_function) \ 1.717 + NS_IMETHODIMP_(void) \ 1.718 + NS_CYCLE_COLLECTION_CLASSNAME(_class)::Unroot(void *p) \ 1.719 + { \ 1.720 + _class *tmp = static_cast<_class*>(p); \ 1.721 + tmp->_unroot_function(); \ 1.722 + } 1.723 + 1.724 +#define NS_IMPL_CYCLE_COLLECTION_CLASS(_class) \ 1.725 + _class::NS_CYCLE_COLLECTION_INNERCLASS _class::NS_CYCLE_COLLECTION_INNERNAME; 1.726 + 1.727 +// NB: This is not something you usually want to use. It is here to allow 1.728 +// adding things to the CC graph to help debugging via CC logs, but it does not 1.729 +// traverse or unlink anything, so it is useless for anything else. 1.730 +#define NS_IMPL_CYCLE_COLLECTION_0(_class) \ 1.731 + NS_IMPL_CYCLE_COLLECTION_CLASS(_class) \ 1.732 + NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(_class) \ 1.733 + NS_IMPL_CYCLE_COLLECTION_UNLINK_END \ 1.734 + NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(_class) \ 1.735 + NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END 1.736 + 1.737 +#define NS_IMPL_CYCLE_COLLECTION(_class, ...) \ 1.738 + NS_IMPL_CYCLE_COLLECTION_CLASS(_class) \ 1.739 + NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(_class) \ 1.740 + NS_IMPL_CYCLE_COLLECTION_UNLINK(__VA_ARGS__) \ 1.741 + NS_IMPL_CYCLE_COLLECTION_UNLINK_END \ 1.742 + NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(_class) \ 1.743 + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(__VA_ARGS__) \ 1.744 + NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END 1.745 + 1.746 +#define NS_IMPL_CYCLE_COLLECTION_INHERITED(_class, _base, ...) \ 1.747 + NS_IMPL_CYCLE_COLLECTION_CLASS(_class) \ 1.748 + NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(_class, _base) \ 1.749 + NS_IMPL_CYCLE_COLLECTION_UNLINK(__VA_ARGS__) \ 1.750 + NS_IMPL_CYCLE_COLLECTION_UNLINK_END \ 1.751 + NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(_class, _base) \ 1.752 + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(__VA_ARGS__) \ 1.753 + NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END 1.754 + 1.755 +#define NS_CYCLE_COLLECTION_NOTE_EDGE_NAME CycleCollectionNoteEdgeName 1.756 + 1.757 +#endif // nsCycleCollectionParticipant_h__