Bug 1279746 - Optimize xpc_TryUnmarkWrappedGrayObject, r=mccr8
authorOlli Pettay <Olli.Pettay@helsinki.fi>
Tue, 14 Jun 2016 13:14:21 +0100
changeset 301741 c3ca0a41a6619220c984820996d9d27f3b96f0c6
parent 301740 8bc3f9d3cad9ee2e5f21caa1fdcaeb107d88ed52
child 301742 bf15e558b3b9c28625b7d7b78f379bfd6ad3dcc1
push id78436
push useropettay@mozilla.com
push dateTue, 14 Jun 2016 12:34:03 +0000
treeherdermozilla-inbound@c3ca0a41a661 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmccr8
bugs1279746
milestone50.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 1279746 - Optimize xpc_TryUnmarkWrappedGrayObject, r=mccr8
js/xpconnect/idl/nsIXPConnect.idl
js/xpconnect/src/XPCWrappedJS.cpp
js/xpconnect/src/nsXPConnect.cpp
js/xpconnect/src/xpcprivate.h
--- a/js/xpconnect/idl/nsIXPConnect.idl
+++ b/js/xpconnect/idl/nsIXPConnect.idl
@@ -124,16 +124,24 @@ interface nsIXPConnectWrappedJS : nsIXPC
 
     void debugDump(in short depth);
 
     void aggregatedQueryInterface(in nsIIDRef uuid,
                                   [iid_is(uuid),retval] out nsQIResult result);
 
 };
 
+// Special interface to unmark the internal JSObject.
+// QIing to nsIXPConnectWrappedJSUnmarkGray does *not* addref, it only unmarks,
+// and QIing to nsIXPConnectWrappedJSUnmarkGray is always supposed to fail.
+[builtinclass, uuid(c02a0ce6-275f-4ea1-9c23-08494898b070)]
+interface nsIXPConnectWrappedJSUnmarkGray : nsIXPConnectWrappedJS
+{
+};
+
 /***************************************************************************/
 
 /**
  * This is a sort of a placeholder interface. It is not intended to be
  * implemented. It exists to give the nsIXPCSecurityManager an iid on
  * which to gate a specific activity in XPConnect.
  *
  * That activity is...
--- a/js/xpconnect/src/XPCWrappedJS.cpp
+++ b/js/xpconnect/src/XPCWrappedJS.cpp
@@ -199,16 +199,28 @@ nsXPCWrappedJS::QueryInterface(REFNSIID 
         *aInstancePtr =
             NS_CYCLE_COLLECTION_CLASSNAME(nsXPCWrappedJS)::Upcast(this);
         return NS_OK;
     }
 
     if (!IsValid())
         return NS_ERROR_UNEXPECTED;
 
+    if (aIID.Equals(NS_GET_IID(nsIXPConnectWrappedJSUnmarkGray))) {
+        *aInstancePtr = nullptr;
+
+        // No need to null check mJSObj because IsValid() call above did
+        // that already.
+        JS::ExposeObjectToActiveJS(mJSObj);
+
+        // Just return some error value since one isn't supposed to use
+        // nsIXPConnectWrappedJSUnmarkGray objects for anything.
+        return NS_ERROR_FAILURE;
+    }
+
     // Always check for this first so that our 'outer' can get this interface
     // from us without recurring into a call to the outer's QI!
     if (aIID.Equals(NS_GET_IID(nsIXPConnectWrappedJS))) {
         NS_ADDREF(this);
         *aInstancePtr = (void*) static_cast<nsIXPConnectWrappedJS*>(this);
         return NS_OK;
     }
 
--- a/js/xpconnect/src/nsXPConnect.cpp
+++ b/js/xpconnect/src/nsXPConnect.cpp
@@ -336,21 +336,20 @@ xpc_MarkInCCGeneration(nsISupports* aVar
           weak->RemovePurple();
         }
     }
 }
 
 void
 xpc_TryUnmarkWrappedGrayObject(nsISupports* aWrappedJS)
 {
-    nsCOMPtr<nsIXPConnectWrappedJS> wjs = do_QueryInterface(aWrappedJS);
-    if (wjs) {
-        // Unmarks gray JSObject.
-        static_cast<nsXPCWrappedJS*>(wjs.get())->GetJSObject();
-    }
+    nsCOMPtr<nsIXPConnectWrappedJSUnmarkGray> wjsug =
+      do_QueryInterface(aWrappedJS);
+    MOZ_ASSERT(!wjsug, "One should never be able to QI to "
+                       "nsIXPConnectWrappedJSUnmarkGray successfully!");
 }
 
 /***************************************************************************/
 /***************************************************************************/
 // nsIXPConnect interface methods...
 
 template<typename T>
 static inline T UnexpectedFailure(T rv)
--- a/js/xpconnect/src/xpcprivate.h
+++ b/js/xpconnect/src/xpcprivate.h
@@ -2324,25 +2324,26 @@ private:
 };
 
 /*************************/
 // nsXPCWrappedJS is a wrapper for a single JSObject for use from native code.
 // nsXPCWrappedJS objects are chained together to represent the various
 // interface on the single underlying (possibly aggregate) JSObject.
 
 class nsXPCWrappedJS final : protected nsAutoXPTCStub,
-                             public nsIXPConnectWrappedJS,
+                             public nsIXPConnectWrappedJSUnmarkGray,
                              public nsSupportsWeakReference,
                              public nsIPropertyBag,
                              public XPCRootSetElem
 {
 public:
     NS_DECL_CYCLE_COLLECTING_ISUPPORTS
     NS_DECL_NSIXPCONNECTJSOBJECTHOLDER
     NS_DECL_NSIXPCONNECTWRAPPEDJS
+    NS_DECL_NSIXPCONNECTWRAPPEDJSUNMARKGRAY
     NS_DECL_NSISUPPORTSWEAKREFERENCE
     NS_DECL_NSIPROPERTYBAG
 
     NS_DECL_CYCLE_COLLECTION_SKIPPABLE_CLASS_AMBIGUOUS(nsXPCWrappedJS, nsIXPConnectWrappedJS)
 
     NS_IMETHOD CallMethod(uint16_t methodIndex,
                           const XPTMethodDescriptor* info,
                           nsXPTCMiniVariant* params) override;