From 49e1f7bbd70fc49397473e40ee2830f4e3cb4907 Mon Sep 17 00:00:00 2001 From: Olli Pettay Date: Wed, 29 Jul 2015 13:28:45 +0300 Subject: [PATCH] Bug 1183604, add some more assertions to help implementing new cycle collectable classes, r=mccr8 --HG-- extra : rebase_source : e9f4bf6a9dce11e816b0f4f0cf1bfad61f831eeb --- dom/base/nsWrapperCache.h | 2 ++ dom/bindings/BindingUtils.h | 56 +++++++++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+) diff --git a/dom/base/nsWrapperCache.h b/dom/base/nsWrapperCache.h index b6f37ca78b4c..af645a66a8b4 100644 --- a/dom/base/nsWrapperCache.h +++ b/dom/base/nsWrapperCache.h @@ -322,8 +322,10 @@ private: nsScriptObjectTracer* aTracer); #ifdef DEBUG +public: void CheckCCWrapperTraversal(void* aScriptObjectHolder, nsScriptObjectTracer* aTracer); +private: #endif // DEBUG /** diff --git a/dom/bindings/BindingUtils.h b/dom/bindings/BindingUtils.h index fc2e0ab85b8d..2e5d9b766470 100644 --- a/dom/bindings/BindingUtils.h +++ b/dom/bindings/BindingUtils.h @@ -879,6 +879,56 @@ struct TypeNeedsOuterization IsBaseOf::value || IsSame::value; }; +#ifdef DEBUG +template::value> +struct CheckWrapperCacheTracing +{ + static inline void Check(T* aObject) + { + } +}; + +template +struct CheckWrapperCacheTracing +{ + static void Check(T* aObject) + { + // Rooting analysis thinks QueryInterface may GC, but we're dealing with + // a subset of QueryInterface, C++ only types here. + JS::AutoSuppressGCAnalysis nogc; + + nsWrapperCache* wrapperCacheFromQI = nullptr; + aObject->QueryInterface(NS_GET_IID(nsWrapperCache), + reinterpret_cast(&wrapperCacheFromQI)); + + MOZ_ASSERT(wrapperCacheFromQI, + "Missing nsWrapperCache from QueryInterface implementation?"); + + if (!wrapperCacheFromQI->GetWrapperPreserveColor()) { + // Can't assert that we trace the wrapper, since we don't have any + // wrapper to trace. + return; + } + + nsISupports* ccISupports = nullptr; + aObject->QueryInterface(NS_GET_IID(nsCycleCollectionISupports), + reinterpret_cast(&ccISupports)); + MOZ_ASSERT(ccISupports, + "nsWrapperCache object which isn't cycle collectable?"); + + nsXPCOMCycleCollectionParticipant* participant = nullptr; + CallQueryInterface(ccISupports, &participant); + MOZ_ASSERT(participant, "Can't QI to CycleCollectionParticipant?"); + + bool wasPreservingWrapper = wrapperCacheFromQI->PreservingWrapper(); + wrapperCacheFromQI->SetPreservingWrapper(true); + wrapperCacheFromQI->CheckCCWrapperTraversal(ccISupports, participant); + wrapperCacheFromQI->SetPreservingWrapper(wasPreservingWrapper); + } +}; + +#endif + template MOZ_ALWAYS_INLINE bool DoGetOrCreateDOMReflector(JSContext* cx, T* value, @@ -903,6 +953,12 @@ DoGetOrCreateDOMReflector(JSContext* cx, T* value, // figure out whether WrapObject() threw. return false; } + +#ifdef DEBUG + if (IsBaseOf::value) { + CheckWrapperCacheTracing::Check(value); + } +#endif } #ifdef DEBUG