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
--- 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,