Bug 1456035: Part 2 - Add fast path for XPCWrappedJS QueryInterface with native helper. r?mccr8 draft
authorKris Maglione <maglione.k@gmail.com>
Sun, 22 Apr 2018 20:37:51 -0700
changeset 786392 53d1951499c93c9afd416ad827b62603752c7f62
parent 786391 5ac61de74016b7de90a3b83534b53d2d2315523b
child 786393 74d0d8ee44442efb7f5f9f3b01b42d845d28f97f
push id107444
push usermaglione.k@gmail.com
push dateMon, 23 Apr 2018 04:22:11 +0000
reviewersmccr8
bugs1456035
milestone61.0a1
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,22 @@ 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))) {
+        success = mozQI->QueriesTo(aIID);
+        if (success)
+            retObj.set(jsobj);
+    } else 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 +275,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,