Bug 884268 - Part b: Move nsContentUtils::PreserveWrapper to nsWrapperCache; r=smaug
authorMs2ger <ms2ger@gmail.com>
Sun, 23 Jun 2013 09:15:42 +0200
changeset 147646 d4c35209af10b65863fe5ef1e29cb61e41b577ed
parent 147645 c4618e8cb8ff22d27d675c6fb033f478ba4bff5e
child 147647 6fe13dc22c5697b72d66ee48ad692d39c350f5ee
push id2697
push userbbajaj@mozilla.com
push dateMon, 05 Aug 2013 18:49:53 +0000
treeherdermozilla-beta@dfec938c7b63 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs884268
milestone24.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 884268 - Part b: Move nsContentUtils::PreserveWrapper to nsWrapperCache; r=smaug
content/base/public/nsContentUtils.h
content/xbl/src/nsXBLProtoImpl.cpp
dom/base/nsDOMClassInfo.cpp
dom/base/nsWrapperCache.cpp
dom/base/nsWrapperCache.h
dom/bindings/BindingUtils.cpp
dom/bindings/Codegen.py
dom/bindings/DOMJSProxyHandler.cpp
js/xpconnect/src/XPCJSRuntime.cpp
js/xpconnect/wrappers/XrayWrapper.cpp
--- a/content/base/public/nsContentUtils.h
+++ b/content/base/public/nsContentUtils.h
@@ -1258,42 +1258,16 @@ public:
    *                            drop
    */
   static void DropJSObjects(void* aScriptObjectHolder);
 
 #ifdef DEBUG
   static bool AreJSObjectsHeld(void* aScriptObjectHolder); 
 #endif
 
-  static void PreserveWrapper(nsISupports* aScriptObjectHolder,
-                              nsWrapperCache* aCache)
-  {
-    if (!aCache->PreservingWrapper()) {
-      nsISupports *ccISupports;
-      aScriptObjectHolder->QueryInterface(NS_GET_IID(nsCycleCollectionISupports),
-                                          reinterpret_cast<void**>(&ccISupports));
-      MOZ_ASSERT(ccISupports);
-      nsXPCOMCycleCollectionParticipant* participant;
-      CallQueryInterface(ccISupports, &participant);
-      PreserveWrapper(ccISupports, aCache, participant);
-    }
-  }
-  static void PreserveWrapper(void* aScriptObjectHolder,
-                              nsWrapperCache* aCache,
-                              nsScriptObjectTracer* aTracer)
-  {
-    if (!aCache->PreservingWrapper()) {
-      HoldJSObjects(aScriptObjectHolder, aTracer);
-      aCache->SetPreservingWrapper(true);
-#ifdef DEBUG
-      // Make sure the cycle collector will be able to traverse to the wrapper.
-      aCache->CheckCCWrapperTraversal(aScriptObjectHolder, aTracer);
-#endif
-    }
-  }
   static void ReleaseWrapper(void* aScriptObjectHolder,
                              nsWrapperCache* aCache);
 
   /*
    * Notify when the first XUL menu is opened and when the all XUL menus are
    * closed. At opening, aInstalling should be TRUE, otherwise, it should be
    * FALSE.
    */
--- a/content/xbl/src/nsXBLProtoImpl.cpp
+++ b/content/xbl/src/nsXBLProtoImpl.cpp
@@ -189,17 +189,17 @@ nsXBLProtoImpl::InitTargetObjects(nsXBLP
   // concrete base class.  We need to alter the object so that our concrete class is interposed
   // between the object and its base class.  We become the new base class of the object, and the
   // object's old base class becomes the new class' base class.
   rv = aBinding->InitClass(mClassName, cx, global, value, aTargetClassObject, aTargetIsNew);
   if (NS_FAILED(rv)) {
     return rv;
   }
 
-  nsContentUtils::PreserveWrapper(aBoundElement, aBoundElement);
+  aBoundElement->PreserveWrapper(aBoundElement);
 
   wrapper.swap(*aScriptObjectHolder);
   
   return rv;
 }
 
 nsresult
 nsXBLProtoImpl::CompilePrototypeMembers(nsXBLPrototypeBinding* aBinding)
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -5081,18 +5081,17 @@ nsNodeSH::GetFlags(uint32_t *aFlags)
   *aFlags = DOMCLASSINFO_STANDARD_FLAGS | nsIClassInfo::CONTENT_NODE;
 
   return NS_OK;
 }
 
 void
 nsNodeSH::PreserveWrapper(nsISupports *aNative)
 {
-  nsINode *node = static_cast<nsINode*>(aNative);
-  nsContentUtils::PreserveWrapper(aNative, node);
+  static_cast<nsINode*>(aNative)->PreserveWrapper(aNative);
 }
 
 // EventTarget helper
 
 NS_IMETHODIMP
 nsEventTargetSH::PreCreate(nsISupports *nativeObj, JSContext *cx,
                            JSObject *aGlobalObj, JSObject **parentObj)
 {
@@ -5117,17 +5116,17 @@ nsEventTargetSH::AddProperty(nsIXPConnec
   return NS_OK;
 }
 
 void
 nsEventTargetSH::PreserveWrapper(nsISupports *aNative)
 {
   nsDOMEventTargetHelper *target =
     nsDOMEventTargetHelper::FromSupports(aNative);
-  nsContentUtils::PreserveWrapper(aNative, target);
+  target->PreserveWrapper(aNative);
 }
 
 // IDBEventTarget helper
 
 NS_IMETHODIMP
 IDBEventTargetSH::PreCreate(nsISupports *aNativeObj, JSContext *aCx,
                             JSObject *aGlobalObj, JSObject **aParentObj)
 {
--- a/dom/base/nsWrapperCache.cpp
+++ b/dom/base/nsWrapperCache.cpp
@@ -2,16 +2,27 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsWrapperCacheInlines.h"
 
 #include "nsCycleCollectionTraversalCallback.h"
+#include "nsCycleCollector.h"
+
+using namespace mozilla;
+using namespace mozilla::dom;
+
+/* static */ void
+nsWrapperCache::HoldJSObjects(void* aScriptObjectHolder,
+                              nsScriptObjectTracer* aTracer)
+{
+  cyclecollector::AddJSHolder(aScriptObjectHolder, aTracer);
+}
 
 #ifdef DEBUG
 
 class DebugWrapperTraversalCallback : public nsCycleCollectionTraversalCallback
 {
 public:
   DebugWrapperTraversalCallback(void* aWrapper)
     : mFound(false)
--- a/dom/base/nsWrapperCache.h
+++ b/dom/base/nsWrapperCache.h
@@ -209,20 +209,45 @@ public:
   }
 
   void UnsetFlags(uint32_t aFlagsToUnset)
   {
     MOZ_ASSERT((aFlagsToUnset & kWrapperFlagsMask) == 0, "Bad flag mask");
     mFlags &= ~aFlagsToUnset;
   }
 
+  void PreserveWrapper(nsISupports* aScriptObjectHolder)
+  {
+    if (PreservingWrapper()) {
+      return;
+    }
+
+    nsISupports* ccISupports;
+    aScriptObjectHolder->QueryInterface(NS_GET_IID(nsCycleCollectionISupports),
+                                        reinterpret_cast<void**>(&ccISupports));
+    MOZ_ASSERT(ccISupports);
+
+    nsXPCOMCycleCollectionParticipant* participant;
+    CallQueryInterface(ccISupports, &participant);
+    PreserveWrapper(ccISupports, participant);
+  }
+
+  void PreserveWrapper(void* aScriptObjectHolder, nsScriptObjectTracer* aTracer)
+  {
+    if (PreservingWrapper()) {
+      return;
+    }
+
+    HoldJSObjects(aScriptObjectHolder, aTracer);
+    SetPreservingWrapper(true);
 #ifdef DEBUG
-  void CheckCCWrapperTraversal(void* aScriptObjectHolder,
-                               nsScriptObjectTracer* aTracer);
-#endif // DEBUG
+    // Make sure the cycle collector will be able to traverse to the wrapper.
+    CheckCCWrapperTraversal(aScriptObjectHolder, aTracer);
+#endif
+  }
 
 private:
   JSObject *GetWrapperJSObject() const
   {
     return mWrapper;
   }
 
   void SetWrapperJSObject(JSObject* aWrapper)
@@ -251,16 +276,24 @@ private:
   }
 
   void UnsetWrapperFlags(uint32_t aFlagsToUnset)
   {
     MOZ_ASSERT((aFlagsToUnset & ~kWrapperFlagsMask) == 0, "Bad wrapper flag bits");
     mFlags &= ~aFlagsToUnset;
   }
 
+  static void HoldJSObjects(void* aScriptObjectHolder,
+                            nsScriptObjectTracer* aTracer);
+
+#ifdef DEBUG
+  void CheckCCWrapperTraversal(void* aScriptObjectHolder,
+                               nsScriptObjectTracer* aTracer);
+#endif // DEBUG
+
   /**
    * If this bit is set then we're preserving the wrapper, which in effect ties
    * the lifetime of the JS object stored in the cache to the lifetime of the
    * native object. We rely on the cycle collector to break the cycle that this
    * causes between the native object and the JS object, so it is important that
    * any native object that supports preserving of its wrapper
    * traces/traverses/unlinks the cached JS object (see
    * NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER,
--- a/dom/bindings/BindingUtils.cpp
+++ b/dom/bindings/BindingUtils.cpp
@@ -635,17 +635,17 @@ NativeInterface2JSObjectAndThrowIfFailed
 
 bool
 TryPreserveWrapper(JSObject* obj)
 {
   if (nsISupports* native = UnwrapDOMObjectToISupports(obj)) {
     nsWrapperCache* cache = nullptr;
     CallQueryInterface(native, &cache);
     if (cache) {
-      nsContentUtils::PreserveWrapper(native, cache);
+      cache->PreserveWrapper(native);
     }
     return true;
   }
 
   // If this DOMClass is not cycle collected, then it isn't wrappercached,
   // so it does not need to be preserved. If it is cycle collected, then
   // we can't tell if it is wrappercached or not, so we just return false.
   const DOMClass* domClass = GetDOMClass(obj);
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -933,22 +933,22 @@ class CGAddPropertyHook(CGAbstractClassH
         args = [Argument('JSContext*', 'cx'), Argument('JS::Handle<JSObject*>', 'obj'),
                 Argument('JS::Handle<jsid>', 'id'), Argument('JS::MutableHandle<JS::Value>', 'vp')]
         CGAbstractClassHook.__init__(self, descriptor, ADDPROPERTY_HOOK_NAME,
                                      'JSBool', args)
 
     def generate_code(self):
         assert not self.descriptor.workers and self.descriptor.wrapperCache
         if self.descriptor.nativeOwnership == 'nsisupports':
-            preserveArgs = "reinterpret_cast<nsISupports*>(self), self"
-        else:
-            preserveArgs = "self, self, NS_CYCLE_COLLECTION_PARTICIPANT(%s)" % self.descriptor.nativeType
+            preserveArgs = "reinterpret_cast<nsISupports*>(self)"
+        else:
+            preserveArgs = "self, NS_CYCLE_COLLECTION_PARTICIPANT(%s)" % self.descriptor.nativeType
         return ("  // We don't want to preserve if we don't have a wrapper.\n"
                 "  if (self->GetWrapperPreserveColor()) {\n"
-                "    nsContentUtils::PreserveWrapper(%s);\n"
+                "    self->PreserveWrapper(%s);\n"
                 "  }\n"
                 "  return true;" % preserveArgs)
 
 def DeferredFinalizeSmartPtr(descriptor):
     if descriptor.nativeOwnership == 'owned':
         smartPtr = 'nsAutoPtr<%s>'
     else:
         assert descriptor.nativeOwnership == 'refcounted'
@@ -8357,21 +8357,17 @@ class CGBindingRoot(CGThing):
         descriptors = config.getDescriptors(webIDLFile=webIDLFile,
                                             hasInterfaceOrInterfacePrototypeObject=True,
                                             skipGen=False)
         def descriptorRequiresPreferences(desc):
             iface = desc.interface
             return any(m.getExtendedAttribute("Pref") for m in iface.members + [iface]);
         requiresPreferences = any(descriptorRequiresPreferences(d) for d in descriptors)
         hasOwnedDescriptors = any(d.nativeOwnership == 'owned' for d in descriptors)
-        def descriptorRequiresContentUtils(desc):
-            return ((desc.concrete and not desc.proxy and
-                     not desc.workers and desc.wrapperCache) or
-                    desc.interface.hasInterfaceObject())
-        requiresContentUtils = any(descriptorRequiresContentUtils(d) for d in descriptors)
+        requiresContentUtils = any(d.interface.hasInterfaceObject() for d in descriptors)
         def descriptorHasChromeOnlyMembers(desc):
             return any(isChromeOnly(a) for a in desc.interface.members)
         hasChromeOnlyMembers = any(descriptorHasChromeOnlyMembers(d) for d in descriptors)
         # XXXkhuey ugly hack but this is going away soon.
         isEventTarget = webIDLFile.endswith("EventTarget.webidl")
         hasWorkerStuff = len(config.getDescriptors(webIDLFile=webIDLFile,
                                                    workers=True)) != 0
         mainDictionaries = config.getDictionaries(webIDLFile=webIDLFile,
--- a/dom/bindings/DOMJSProxyHandler.cpp
+++ b/dom/bindings/DOMJSProxyHandler.cpp
@@ -127,17 +127,17 @@ DOMProxyHandler::EnsureExpandoObject(JSC
   if (!expando) {
     return nullptr;
   }
 
   nsISupports* native = UnwrapDOMObject<nsISupports>(obj);
   nsWrapperCache* cache;
   CallQueryInterface(native, &cache);
   if (expandoAndGeneration) {
-    nsContentUtils::PreserveWrapper(native, cache);
+    cache->PreserveWrapper(native);
     expandoAndGeneration->expando.setObject(*expando);
 
     return expando;
   }
 
   XPCWrappedNativeScope* scope = xpc::GetObjectScope(obj);
   if (!scope->RegisterDOMExpandoObject(obj)) {
     return nullptr;
--- a/js/xpconnect/src/XPCJSRuntime.cpp
+++ b/js/xpconnect/src/XPCJSRuntime.cpp
@@ -2527,17 +2527,17 @@ PreserveWrapper(JSContext *cx, JSObject 
 
     if (!IS_WN_REFLECTOR(obj))
         return mozilla::dom::TryPreserveWrapper(obj);
 
     nsISupports *supports = XPCWrappedNative::Get(obj)->Native();
 
     // For pre-Paris DOM bindings objects, we only support Node.
     if (nsCOMPtr<nsINode> node = do_QueryInterface(supports)) {
-        nsContentUtils::PreserveWrapper(supports, node);
+        node->PreserveWrapper(supports);
         return true;
     }
     return false;
 }
 
 static nsresult
 ReadSourceFromFilename(JSContext *cx, const char *filename, jschar **src, uint32_t *len)
 {
--- a/js/xpconnect/wrappers/XrayWrapper.cpp
+++ b/js/xpconnect/wrappers/XrayWrapper.cpp
@@ -1277,17 +1277,17 @@ void
 DOMXrayTraits::preserveWrapper(JSObject *target)
 {
     nsISupports *identity = mozilla::dom::UnwrapDOMObjectToISupports(target);
     if (!identity)
         return;
     nsWrapperCache* cache = nullptr;
     CallQueryInterface(identity, &cache);
     if (cache)
-        nsContentUtils::PreserveWrapper(identity, cache);
+        cache->PreserveWrapper(identity);
 }
 
 JSObject*
 DOMXrayTraits::createHolder(JSContext *cx, JSObject *wrapper)
 {
     return JS_NewObjectWithGivenProto(cx, nullptr, nullptr,
                                       JS_GetGlobalForObject(cx, wrapper));
 }