Bug 1456035: Part 2 - Add fast path for XPCWrappedJS QueryInterface with native helper. r=mccr8
authorKris Maglione <maglione.k@gmail.com>
Sun, 22 Apr 2018 20:37:51 -0700
changeset 415684 0102a61e38ae9c52d35b8239ccb24f48718a2b5b
parent 415683 a442c0b9dbbe4266c14928aad8e04b9b08e0429b
child 415685 affc06c38acd82a0773dd09465c2602e636fc08e
push id33901
push userapavel@mozilla.com
push dateThu, 26 Apr 2018 06:05:37 +0000
treeherdermozilla-central@b62ad926cf2a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmccr8
bugs1456035
milestone61.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 1456035: Part 2 - Add fast path for XPCWrappedJS QueryInterface with native helper. r=mccr8 When the QueryInterface method for an XPCWrappedJS class is implemented by the native helper, we can avoid a lot of overhead by simply asking it if it supports a given interface rather than going through all of the JSAPI call and exception handling overhead we'd need otherwise. MozReview-Commit-ID: FVAN3oYRE9I
js/xpconnect/src/XPCWrappedJSClass.cpp
--- a/js/xpconnect/src/XPCWrappedJSClass.cpp
+++ b/js/xpconnect/src/XPCWrappedJSClass.cpp
@@ -15,16 +15,17 @@
 #include "AccessCheck.h"
 #include "nsJSUtils.h"
 #include "nsPrintfCString.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/dom/BindingUtils.h"
 #include "mozilla/dom/DOMException.h"
 #include "mozilla/dom/DOMExceptionBinding.h"
 #include "mozilla/dom/DOMPrefs.h"
+#include "mozilla/dom/MozQueryInterface.h"
 #include "mozilla/jsipc/CrossProcessObjectWrappers.h"
 
 #include "jsapi.h"
 #include "jsfriendapi.h"
 
 using namespace xpc;
 using namespace JS;
 using namespace mozilla;
@@ -227,18 +228,24 @@ nsXPCWrappedJSClass::CallQueryInterfaceO
         const nsXPTInterfaceInfo* info = nsXPTInterfaceInfo::ByIID(aIID);
         if (!info || info->IsBuiltinClass() ||
             (!info->IsScriptable() && !allowNonScriptable))
         {
             return nullptr;
         }
     }
 
-    id = xpc_NewIDObject(cx, jsobj, aIID);
-    if (id) {
+    dom::MozQueryInterface* mozQI = nullptr;
+    if (NS_SUCCEEDED(UNWRAP_OBJECT(MozQueryInterface, &fun, mozQI))) {
+        if (mozQI->QueriesTo(aIID))
+            return jsobj.get();
+        return nullptr;
+    }
+
+    if ((id = xpc_NewIDObject(cx, jsobj, aIID))) {
         // Throwing NS_NOINTERFACE is the prescribed way to fail QI from JS. It
         // is not an exception that is ever worth reporting, but we don't want
         // to eat all exceptions either.
 
         {
             RootedValue arg(cx, JS::ObjectValue(*id));
             success = JS_CallFunctionValue(cx, jsobj, fun, HandleValueArray(arg), &retval);
         }
@@ -270,21 +277,21 @@ nsXPCWrappedJSClass::CallQueryInterfaceO
 
                     if (rv == NS_NOINTERFACE)
                         JS_ClearPendingException(cx);
                 }
             }
         } else if (!success) {
             NS_WARNING("QI hook ran OOMed - this is probably a bug!");
         }
+
+        if (success)
+            success = JS_ValueToObject(cx, retval, &retObj);
     }
 
-    if (success)
-        success = JS_ValueToObject(cx, retval, &retObj);
-
     return success ? retObj.get() : nullptr;
 }
 
 /***************************************************************************/
 
 static bool
 GetNamedPropertyAsVariantRaw(XPCCallContext& ccx,
                              HandleObject aJSObj,