Back out 3ab1dcfb2218 and 46ae4bf4aaf4 (bug 622301) for Windows PGO bustage
authorPhil Ringnalda <philringnalda@gmail.com>
Sat, 14 Jan 2012 18:56:00 -0800
changeset 84469 b641c65643b99c258bafc9de9377506b2a9604e0
parent 84468 75c21e9321d62eda1d53cb66b2a4542f6054cee6
child 84470 59cb54c6dfe12005af95a12314dd88eb46e0cccc
push id4917
push userphilringnalda@gmail.com
push dateSun, 15 Jan 2012 03:40:04 +0000
treeherdermozilla-inbound@b641c65643b9 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs622301
milestone12.0a1
backs out3ab1dcfb2218efb5d24a582bb160aa10e7cce891
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
Back out 3ab1dcfb2218 and 46ae4bf4aaf4 (bug 622301) for Windows PGO bustage
content/canvas/src/CustomQS_Canvas2D.h
content/canvas/src/CustomQS_WebGL.h
js/xpconnect/src/XPCQuickStubs.cpp
js/xpconnect/src/XPCQuickStubs.h
js/xpconnect/src/nsDOMQS.h
js/xpconnect/src/qsgen.py
--- a/content/canvas/src/CustomQS_Canvas2D.h
+++ b/content/canvas/src/CustomQS_Canvas2D.h
@@ -53,17 +53,17 @@ typedef NS_STDCALL_FUNCPROTO(nsresult, C
 static JSBool
 Canvas2D_SetStyleHelper(JSContext *cx, JSObject *obj, jsid id, jsval *vp,
                         CanvasStyleSetterType setfunc)
 {
     XPC_QS_ASSERT_CONTEXT_OK(cx);
     nsIDOMCanvasRenderingContext2D *self;
     xpc_qsSelfRef selfref;
     JS::AutoValueRooter tvr(cx);
-    if (!xpc_qsUnwrapThis(cx, obj, &self, &selfref.ptr, tvr.jsval_addr(), nsnull))
+    if (!xpc_qsUnwrapThis(cx, obj, nsnull, &self, &selfref.ptr, tvr.jsval_addr(), nsnull))
         return JS_FALSE;
 
     nsresult rv = NS_OK;
     if (JSVAL_IS_STRING(*vp)) {
         xpc_qsDOMString arg0(cx, *vp, vp,
                              xpc_qsDOMString::eDefaultNullBehavior,
                              xpc_qsDOMString::eDefaultUndefinedBehavior);
         if (!arg0.IsValid())
@@ -91,17 +91,17 @@ Canvas2D_SetStyleHelper(JSContext *cx, J
 static JSBool
 Canvas2D_GetStyleHelper(JSContext *cx, JSObject *obj, jsid id, jsval *vp,
                         CanvasStyleGetterType getfunc)
 {
     XPC_QS_ASSERT_CONTEXT_OK(cx);
     nsIDOMCanvasRenderingContext2D *self;
     xpc_qsSelfRef selfref;
     XPCLazyCallContext lccx(JS_CALLER, cx, obj);
-    if (!xpc_qsUnwrapThis(cx, obj, &self, &selfref.ptr, vp, &lccx))
+    if (!xpc_qsUnwrapThis(cx, obj, nsnull, &self, &selfref.ptr, vp, &lccx))
         return JS_FALSE;
     nsresult rv;
 
     nsString resultString;
     nsCOMPtr<nsISupports> resultInterface;
     PRInt32 resultType;
     rv = (self->*getfunc)(resultString, getter_AddRefs(resultInterface), &resultType);
     if (NS_FAILED(rv))
@@ -298,17 +298,17 @@ nsIDOMCanvasRenderingContext2D_GetImageD
 
     JSObject *obj = JS_THIS_OBJECT(cx, vp);
     if (!obj)
         return JS_FALSE;
 
     nsIDOMCanvasRenderingContext2D *self;
     xpc_qsSelfRef selfref;
     JS::AutoValueRooter tvr(cx);
-    if (!xpc_qsUnwrapThis(cx, obj, &self, &selfref.ptr, tvr.jsval_addr(), nsnull))
+    if (!xpc_qsUnwrapThis(cx, obj, nsnull, &self, &selfref.ptr, tvr.jsval_addr(), nsnull))
         return JS_FALSE;
 
     if (argc < 4)
         return xpc_qsThrow(cx, NS_ERROR_XPC_NOT_ENOUGH_ARGS);
 
     jsval *argv = JS_ARGV(cx, vp);
 
     jsdouble xd, yd, width, height;
@@ -357,17 +357,17 @@ nsIDOMCanvasRenderingContext2D_PutImageD
     if (!obj)
         return JS_FALSE;
 
     nsresult rv;
 
     nsIDOMCanvasRenderingContext2D *self;
     xpc_qsSelfRef selfref;
     JS::AutoValueRooter tvr(cx);
-    if (!xpc_qsUnwrapThis(cx, obj, &self, &selfref.ptr, tvr.jsval_addr(), nsnull))
+    if (!xpc_qsUnwrapThis(cx, obj, nsnull, &self, &selfref.ptr, tvr.jsval_addr(), nsnull))
         return JS_FALSE;
 
     if (argc < 3)
         return xpc_qsThrow(cx, NS_ERROR_XPC_NOT_ENOUGH_ARGS);
 
     jsval *argv = JS_ARGV(cx, vp);
 
     if (JSVAL_IS_PRIMITIVE(argv[0]))
--- a/content/canvas/src/CustomQS_WebGL.h
+++ b/content/canvas/src/CustomQS_WebGL.h
@@ -88,17 +88,17 @@ nsIDOMWebGLRenderingContext_BufferData(J
     XPC_QS_ASSERT_CONTEXT_OK(cx);
     JSObject *obj = JS_THIS_OBJECT(cx, vp);
     if (!obj)
         return JS_FALSE;
 
     nsIDOMWebGLRenderingContext *self;
     xpc_qsSelfRef selfref;
     JS::AutoValueRooter tvr(cx);
-    if (!xpc_qsUnwrapThis(cx, obj, &self, &selfref.ptr, tvr.jsval_addr(), nsnull))
+    if (!xpc_qsUnwrapThis(cx, obj, nsnull, &self, &selfref.ptr, tvr.jsval_addr(), nsnull))
         return JS_FALSE;
 
     if (argc < 3)
         return xpc_qsThrow(cx, NS_ERROR_XPC_NOT_ENOUGH_ARGS);
 
     jsval *argv = JS_ARGV(cx, vp);
 
     int32_t target;
@@ -161,17 +161,17 @@ nsIDOMWebGLRenderingContext_BufferSubDat
     XPC_QS_ASSERT_CONTEXT_OK(cx);
     JSObject *obj = JS_THIS_OBJECT(cx, vp);
     if (!obj)
         return JS_FALSE;
 
     nsIDOMWebGLRenderingContext *self;
     xpc_qsSelfRef selfref;
     JS::AutoValueRooter tvr(cx);
-    if (!xpc_qsUnwrapThis(cx, obj, &self, &selfref.ptr, tvr.jsval_addr(), nsnull))
+    if (!xpc_qsUnwrapThis(cx, obj, nsnull, &self, &selfref.ptr, tvr.jsval_addr(), nsnull))
         return JS_FALSE;
 
     if (argc < 3)
         return xpc_qsThrow(cx, NS_ERROR_XPC_NOT_ENOUGH_ARGS);
 
     jsval *argv = JS_ARGV(cx, vp);
 
     int32_t target;
@@ -235,17 +235,17 @@ nsIDOMWebGLRenderingContext_ReadPixels(J
     if (!obj)
         return JS_FALSE;
 
     nsresult rv;
 
     nsIDOMWebGLRenderingContext *self;
     xpc_qsSelfRef selfref;
     JS::AutoValueRooter tvr(cx);
-    if (!xpc_qsUnwrapThis(cx, obj, &self, &selfref.ptr, tvr.jsval_addr(), nsnull))
+    if (!xpc_qsUnwrapThis(cx, obj, nsnull, &self, &selfref.ptr, tvr.jsval_addr(), nsnull))
         return JS_FALSE;
 
     if (argc < 7)
         return xpc_qsThrow(cx, NS_ERROR_XPC_NOT_ENOUGH_ARGS);
 
     jsval *argv = JS_ARGV(cx, vp);
 
     // arguments common to all cases
@@ -295,17 +295,17 @@ nsIDOMWebGLRenderingContext_TexImage2D(J
     if (!obj)
         return JS_FALSE;
 
     nsresult rv;
 
     nsIDOMWebGLRenderingContext *self;
     xpc_qsSelfRef selfref;
     JS::AutoValueRooter tvr(cx);
-    if (!xpc_qsUnwrapThis(cx, obj, &self, &selfref.ptr, tvr.jsval_addr(), nsnull))
+    if (!xpc_qsUnwrapThis(cx, obj, nsnull, &self, &selfref.ptr, tvr.jsval_addr(), nsnull))
         return JS_FALSE;
 
     if (argc < 6 || argc == 7 || argc == 8)
         return xpc_qsThrow(cx, NS_ERROR_XPC_NOT_ENOUGH_ARGS);
 
     jsval *argv = JS_ARGV(cx, vp);
 
     // arguments common to all cases
@@ -416,17 +416,17 @@ nsIDOMWebGLRenderingContext_TexSubImage2
     if (!obj)
         return JS_FALSE;
 
     nsresult rv;
 
     nsIDOMWebGLRenderingContext *self;
     xpc_qsSelfRef selfref;
     JS::AutoValueRooter tvr(cx);
-    if (!xpc_qsUnwrapThis(cx, obj, &self, &selfref.ptr, tvr.jsval_addr(), nsnull))
+    if (!xpc_qsUnwrapThis(cx, obj, nsnull, &self, &selfref.ptr, tvr.jsval_addr(), nsnull))
         return JS_FALSE;
 
     if (argc < 7 || argc == 8)
         return xpc_qsThrow(cx, NS_ERROR_XPC_NOT_ENOUGH_ARGS);
 
     jsval *argv = JS_ARGV(cx, vp);
 
     // arguments common to all cases
@@ -527,17 +527,17 @@ helper_nsIDOMWebGLRenderingContext_Unifo
     if (!obj)
         return JS_FALSE;
 
     nsresult rv;
 
     nsIDOMWebGLRenderingContext *self;
     xpc_qsSelfRef selfref;
     JS::AutoValueRooter tvr(cx);
-    if (!xpc_qsUnwrapThis(cx, obj, &self, &selfref.ptr, tvr.jsval_addr(), nsnull))
+    if (!xpc_qsUnwrapThis(cx, obj, nsnull, &self, &selfref.ptr, tvr.jsval_addr(), nsnull))
         return JS_FALSE;
 
     if (argc < 2)
         return xpc_qsThrow(cx, NS_ERROR_XPC_NOT_ENOUGH_ARGS);
 
     jsval *argv = JS_ARGV(cx, vp);
 
     nsIWebGLUniformLocation *location;
@@ -601,17 +601,17 @@ helper_nsIDOMWebGLRenderingContext_Unifo
     if (!obj)
         return JS_FALSE;
 
     nsresult rv;
 
     nsIDOMWebGLRenderingContext *self;
     xpc_qsSelfRef selfref;
     JS::AutoValueRooter tvr(cx);
-    if (!xpc_qsUnwrapThis(cx, obj, &self, &selfref.ptr, tvr.jsval_addr(), nsnull))
+    if (!xpc_qsUnwrapThis(cx, obj, nsnull, &self, &selfref.ptr, tvr.jsval_addr(), nsnull))
         return JS_FALSE;
 
     if (argc < 2)
         return xpc_qsThrow(cx, NS_ERROR_XPC_NOT_ENOUGH_ARGS);
 
     jsval *argv = JS_ARGV(cx, vp);
 
     nsIWebGLUniformLocation *location;
@@ -673,17 +673,17 @@ helper_nsIDOMWebGLRenderingContext_Unifo
     XPC_QS_ASSERT_CONTEXT_OK(cx);
     JSObject *obj = JS_THIS_OBJECT(cx, vp);
     if (!obj)
         return JS_FALSE;
 
     nsIDOMWebGLRenderingContext *self;
     xpc_qsSelfRef selfref;
     JS::AutoValueRooter tvr(cx);
-    if (!xpc_qsUnwrapThis(cx, obj, &self, &selfref.ptr, tvr.jsval_addr(), nsnull))
+    if (!xpc_qsUnwrapThis(cx, obj, nsnull, &self, &selfref.ptr, tvr.jsval_addr(), nsnull))
         return JS_FALSE;
 
     if (argc < 3)
         return xpc_qsThrow(cx, NS_ERROR_XPC_NOT_ENOUGH_ARGS);
 
     jsval *argv = JS_ARGV(cx, vp);
 
     nsIWebGLUniformLocation *location;
@@ -746,17 +746,17 @@ helper_nsIDOMWebGLRenderingContext_Verte
     XPC_QS_ASSERT_CONTEXT_OK(cx);
     JSObject *obj = JS_THIS_OBJECT(cx, vp);
     if (!obj)
         return JS_FALSE;
 
     nsIDOMWebGLRenderingContext *self;
     xpc_qsSelfRef selfref;
     JS::AutoValueRooter tvr(cx);
-    if (!xpc_qsUnwrapThis(cx, obj, &self, &selfref.ptr, tvr.jsval_addr(), nsnull))
+    if (!xpc_qsUnwrapThis(cx, obj, nsnull, &self, &selfref.ptr, tvr.jsval_addr(), nsnull))
         return JS_FALSE;
 
     if (argc < 2)
         return xpc_qsThrow(cx, NS_ERROR_XPC_NOT_ENOUGH_ARGS);
 
     jsval *argv = JS_ARGV(cx, vp);
 
     uint32_t location;
--- a/js/xpconnect/src/XPCQuickStubs.cpp
+++ b/js/xpconnect/src/XPCQuickStubs.cpp
@@ -773,68 +773,32 @@ getNativeFromWrapper(JSContext *cx,
     return getNative(wrapper->GetIdentityObject(), wrapper->GetOffsets(),
                      wrapper->GetFlatJSObject(), iid, ppThis, pThisRef, vp);
 }
 
 
 nsresult
 getWrapper(JSContext *cx,
            JSObject *obj,
+           JSObject *callee,
            XPCWrappedNative **wrapper,
            JSObject **cur,
            XPCWrappedNativeTearOff **tearoff)
 {
-
-    // We can have at most three layers in need of unwrapping here:
-    // * A (possible) security wrapper
-    // * A (possible) Xray waiver
-    // * A (possible) outer window
-    //
-    // The underlying call to js::Unwrap recursively unwraps, but stops if it
-    // hits an outer object. Thus, we need to make at most two unwrapping
-    // calls: one to handle security wrappers and waivers, and one to handle
-    // outer objects.
-    if (js::IsWrapper(obj)) {
-        obj = XPCWrapper::Unwrap(cx, obj);
-        if (obj && js::IsWrapper(obj)) {
-            MOZ_ASSERT(js::Wrapper::wrapperHandler(obj)->isOuterWindow());
-            obj = XPCWrapper::Unwrap(cx, obj);
-        }
-
-        // The safe unwrap might have failed for SCRIPT_ACCESS_ONLY objects. If it
-        // didn't fail though, we should be done with wrappers.
-        if (!obj)
-            return NS_ERROR_XPC_SECURITY_MANAGER_VETO;
-        MOZ_ASSERT(!js::IsWrapper(obj));
+    if (XPCWrapper::IsSecurityWrapper(obj) &&
+        !(obj = XPCWrapper::Unwrap(cx, obj))) {
+        return NS_ERROR_XPC_SECURITY_MANAGER_VETO;
     }
 
-    // Start with sane values.
-    *wrapper = nsnull;
-    *cur = nsnull;
+    *cur = obj;
     *tearoff = nsnull;
 
-    // Handle tearoffs.
-    //
-    // If |obj| is of the tearoff class, that means we're dealing with a JS
-    // object reflection of a particular interface (ie, |foo.nsIBar|). These
-    // JS objects are parented to their wrapper, so we snag the tearoff object
-    // along the way (if desired), and then set |obj| to its parent.
-    if (js::GetObjectClass(obj) == &XPC_WN_Tearoff_JSClass) {
-        *tearoff = (XPCWrappedNativeTearOff*) js::GetObjectPrivate(obj);
-        obj = js::GetObjectParent(obj);
-    }
-
-    // If we've got a WN or slim wrapper, store things the way callers expect.
-    // Otherwise, leave things null and return.
-    if (IS_WRAPPER_CLASS(js::GetObjectClass(obj))) {
-        if (IS_WN_WRAPPER_OBJECT(obj))
-            *wrapper = (XPCWrappedNative*) js::GetObjectPrivate(obj);
-        else
-            *cur = obj;
-    }
+    *wrapper =
+        XPCWrappedNative::GetWrappedNativeOfJSObject(cx, obj, callee, cur,
+                                                     tearoff);
 
     return NS_OK;
 }
 
 nsresult
 castNative(JSContext *cx,
            XPCWrappedNative *wrapper,
            JSObject *cur,
@@ -942,17 +906,17 @@ xpc_qsUnwrapArgImpl(JSContext *cx,
 
     XPCWrappedNative *wrapper;
     XPCWrappedNativeTearOff *tearoff;
     JSObject *obj2;
     if (mozilla::dom::binding::instanceIsProxy(src)) {
         wrapper = nsnull;
         obj2 = src;
     } else {
-        rv = getWrapper(cx, src, &wrapper, &obj2, &tearoff);
+        rv = getWrapper(cx, src, nsnull, &wrapper, &obj2, &tearoff);
         NS_ENSURE_SUCCESS(rv, rv);
     }
 
     if (wrapper || obj2) {
         if (NS_FAILED(castNative(cx, wrapper, obj2, tearoff, iid, ppArg,
                                  ppArgRef, vp, nsnull)))
             return NS_ERROR_XPC_BAD_CONVERT_JS;
         return NS_OK;
--- a/js/xpconnect/src/XPCQuickStubs.h
+++ b/js/xpconnect/src/XPCQuickStubs.h
@@ -436,16 +436,17 @@ xpc_qsJsvalToWcharStr(JSContext *cx, jsv
 
 /** Convert an nsString to JSString, returning true on success. This will sometimes modify |str| to be empty. */
 JSBool
 xpc_qsStringToJsstring(JSContext *cx, nsString &str, JSString **rval);
 
 nsresult
 getWrapper(JSContext *cx,
            JSObject *obj,
+           JSObject *callee,
            XPCWrappedNative **wrapper,
            JSObject **cur,
            XPCWrappedNativeTearOff **tearoff);
 
 nsresult
 castNative(JSContext *cx,
            XPCWrappedNative *wrapper,
            JSObject *cur,
@@ -471,59 +472,61 @@ castNative(JSContext *cx,
  * XOWs, XPCNativeWrappers, and SafeJSObjectWrappers.
  *
  * Requires a request on @a cx.
  */
 template <class T>
 inline JSBool
 xpc_qsUnwrapThis(JSContext *cx,
                  JSObject *obj,
+                 JSObject *callee,
                  T **ppThis,
                  nsISupports **pThisRef,
                  jsval *pThisVal,
                  XPCLazyCallContext *lccx,
                  bool failureFatal = true)
 {
     XPCWrappedNative *wrapper;
     XPCWrappedNativeTearOff *tearoff;
-    nsresult rv = getWrapper(cx, obj, &wrapper, &obj, &tearoff);
+    nsresult rv = getWrapper(cx, obj, callee, &wrapper, &obj, &tearoff);
     if (NS_SUCCEEDED(rv))
         rv = castNative(cx, wrapper, obj, tearoff, NS_GET_TEMPLATE_IID(T),
                         reinterpret_cast<void **>(ppThis), pThisRef, pThisVal,
                         lccx);
 
     if (failureFatal)
         return NS_SUCCEEDED(rv) || xpc_qsThrow(cx, rv);
 
     if (NS_FAILED(rv))
         *ppThis = nsnull;
     return true;
 }
 
 inline nsISupports*
 castNativeFromWrapper(JSContext *cx,
                       JSObject *obj,
+                      JSObject *callee,
                       PRUint32 interfaceBit,
                       nsISupports **pRef,
                       jsval *pVal,
                       XPCLazyCallContext *lccx,
                       nsresult *rv NS_OUTPARAM)
 {
     XPCWrappedNative *wrapper;
     XPCWrappedNativeTearOff *tearoff;
     JSObject *cur;
 
-    if (IS_WRAPPER_CLASS(js::GetObjectClass(obj))) {
+    if (!callee && IS_WRAPPER_CLASS(js::GetObjectClass(obj))) {
         cur = obj;
         wrapper = IS_WN_WRAPPER_OBJECT(cur) ?
                   (XPCWrappedNative*)xpc_GetJSPrivate(obj) :
                   nsnull;
         tearoff = nsnull;
     } else {
-        *rv = getWrapper(cx, obj, &wrapper, &cur, &tearoff);
+        *rv = getWrapper(cx, obj, callee, &wrapper, &cur, &tearoff);
         if (NS_FAILED(*rv))
             return nsnull;
     }
 
     nsISupports *native;
     if (wrapper) {
         native = wrapper->GetIdentityObject();
         cur = wrapper->GetFlatJSObject();
@@ -609,17 +612,17 @@ castNativeArgFromWrapper(JSContext *cx,
                          nsISupports **pArgRef,
                          jsval *vp,
                          nsresult *rv NS_OUTPARAM)
 {
     JSObject *src = xpc_qsUnwrapObj(v, pArgRef, rv);
     if (!src)
         return nsnull;
 
-    return castNativeFromWrapper(cx, src, bit, pArgRef, vp, nsnull, rv);
+    return castNativeFromWrapper(cx, src, nsnull, bit, pArgRef, vp, nsnull, rv);
 }
 
 inline nsWrapperCache*
 xpc_qsGetWrapperCache(nsWrapperCache *cache)
 {
     return cache;
 }
 
--- a/js/xpconnect/src/nsDOMQS.h
+++ b/js/xpconnect/src/nsDOMQS.h
@@ -39,24 +39,25 @@
 
 #include "nsDOMClassInfoID.h"
 
 #define DEFINE_UNWRAP_CAST(_interface, _base, _bit)                           \
 template <>                                                                   \
 inline JSBool                                                                 \
 xpc_qsUnwrapThis<_interface>(JSContext *cx,                                   \
                              JSObject *obj,                                   \
+                             JSObject *callee,                                \
                              _interface **ppThis,                             \
                              nsISupports **pThisRef,                          \
                              jsval *pThisVal,                                 \
                              XPCLazyCallContext *lccx,                        \
                              bool failureFatal)                               \
 {                                                                             \
     nsresult rv;                                                              \
-    nsISupports *native = castNativeFromWrapper(cx, obj, _bit,                \
+    nsISupports *native = castNativeFromWrapper(cx, obj, callee, _bit,        \
                                                 pThisRef, pThisVal, lccx,     \
                                                 &rv);                         \
     *ppThis = NULL;  /* avoids uninitialized warnings in callers */           \
     if (failureFatal && !native)                                              \
         return xpc_qsThrow(cx, rv);                                           \
     *ppThis = static_cast<_interface*>(static_cast<_base*>(native));          \
     return true;                                                              \
 }                                                                             \
@@ -102,25 +103,26 @@ castToElement(nsIContent *content, jsval
     *pVal = val;
     return true;
 }
 
 template <>
 inline JSBool
 xpc_qsUnwrapThis<nsGenericElement>(JSContext *cx,
                                    JSObject *obj,
+                                   JSObject *callee,
                                    nsGenericElement **ppThis,
                                    nsISupports **pThisRef,
                                    jsval *pThisVal,
                                    XPCLazyCallContext *lccx,
                                    bool failureFatal)
 {
     nsIContent *content;
     jsval val;
-    JSBool ok = xpc_qsUnwrapThis<nsIContent>(cx, obj, &content,
+    JSBool ok = xpc_qsUnwrapThis<nsIContent>(cx, obj, callee, &content,
                                              pThisRef, &val, lccx,
                                              failureFatal);
     if (ok) {
         if (failureFatal || content)
           ok = castToElement(content, val, ppThis, pThisVal);
         if (failureFatal && !ok)
             xpc_qsThrow(cx, NS_ERROR_XPC_BAD_OP_ON_WN_PROTO);
     }
--- a/js/xpconnect/src/qsgen.py
+++ b/js/xpconnect/src/qsgen.py
@@ -858,16 +858,22 @@ def writeQuickStub(f, customMethodCalls,
         raise UserError(member.iface.name + '.' + member.name + ": "
                         "Unwrapping this failure must be fatal when we have a ccx")
 
     if haveCcx:
         f.write("    XPCCallContext ccx(JS_CALLER, cx, obj, "
                 "JSVAL_TO_OBJECT(JS_CALLEE(cx, vp)));\n")
         if isInterfaceType(member.realtype):
             f.write("    XPCLazyCallContext lccx(ccx);\n")
+    elif isInterfaceType(member.realtype):
+        if isMethod:
+            f.write("    JSObject *callee = "
+                    "JSVAL_TO_OBJECT(JS_CALLEE(cx, vp));\n")
+        elif isGetter:
+            f.write("    JSObject *callee = nsnull;\n")
 
     # Get the 'self' pointer.
     if customMethodCall is None or not 'thisType' in customMethodCall:
         f.write("    %s *self;\n" % member.iface.name)
     else:
         f.write("    %s *self;\n" % customMethodCall['thisType'])
     f.write("    xpc_qsSelfRef selfref;\n")
     # Don't use FromCcx for getters or setters; the way we construct the ccx in
@@ -889,20 +895,20 @@ def writeQuickStub(f, customMethodCalls,
 
         if unwrapThisFailureFatal:
             unwrapFatalArg = "true"
         else:
             unwrapFatalArg = "false"
 
         if not isSetter and isInterfaceType(member.realtype):
             f.write("    XPCLazyCallContext lccx(JS_CALLER, cx, obj);\n")
-            f.write("    if (!xpc_qsUnwrapThis(cx, obj, &self, "
+            f.write("    if (!xpc_qsUnwrapThis(cx, obj, callee, &self, "
                     "&selfref.ptr, %s, &lccx, %s))\n" % (pthisval, unwrapFatalArg))
         else:
-            f.write("    if (!xpc_qsUnwrapThis(cx, obj, &self, "
+            f.write("    if (!xpc_qsUnwrapThis(cx, obj, nsnull, &self, "
                     "&selfref.ptr, %s, nsnull, %s))\n" % (pthisval, unwrapFatalArg))
         f.write("        return JS_FALSE;\n")
 
         if not unwrapThisFailureFatal:
             f.write("      if (!self) {\n")
             if (isGetter):
                 f.write("        *vp = JSVAL_NULL;\n")
             f.write("        return JS_TRUE;\n")