Bug 1249698 - Use parent stack instead of vanished child stack. r=billm
authorWei-Cheng Pan <wpan@mozilla.com>
Tue, 26 Jul 2016 18:30:42 +0800
changeset 307605 0901574275090b099b3ae1d704297416689d06fe
parent 307604 893aa91455dec467b7257da0731261cc3fa2cd88
child 307606 df2fb7caf5e1918ff02ff97314eb69b7a54472d3
push id30516
push usercbook@mozilla.com
push dateTue, 02 Aug 2016 15:10:10 +0000
treeherdermozilla-central@f299890191b2 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbillm
bugs1249698
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 1249698 - Use parent stack instead of vanished child stack. r=billm MozReview-Commit-ID: LaX5K1uPZo9
js/ipc/JavaScriptTypes.ipdlh
js/ipc/WrapperAnswer.cpp
js/ipc/WrapperAnswer.h
js/ipc/WrapperOwner.cpp
--- a/js/ipc/JavaScriptTypes.ipdlh
+++ b/js/ipc/JavaScriptTypes.ipdlh
@@ -94,30 +94,35 @@ union JSIDVariant
 struct ReturnSuccess
 {
 };
 
 struct ReturnStopIteration
 {
 };
 
+struct ReturnDeadCPOW
+{
+};
+
 struct ReturnException
 {
     JSVariant exn;
 };
 
 struct ReturnObjectOpResult
 {
     uint32_t code;
 };
 
 union ReturnStatus
 {
     ReturnSuccess;
     ReturnStopIteration;
+    ReturnDeadCPOW;
     ReturnException;
     ReturnObjectOpResult;
 };
 
 union JSParam
 {
     void_t;     /* value is strictly an xpc out param */
     JSVariant;  /* actual value to pass through */
--- a/js/ipc/WrapperAnswer.cpp
+++ b/js/ipc/WrapperAnswer.cpp
@@ -69,26 +69,35 @@ WrapperAnswer::ok(ReturnStatus* rs, cons
 {
     *rs = result
           ? ReturnStatus(ReturnSuccess())
           : ReturnStatus(ReturnObjectOpResult(result.failureCode()));
     return true;
 }
 
 bool
+WrapperAnswer::deadCPOW(AutoJSAPI& jsapi, ReturnStatus* rs)
+{
+    JSContext* cx = jsapi.cx();
+    JS_ClearPendingException(cx);
+    *rs = ReturnStatus(ReturnDeadCPOW());
+    return true;
+}
+
+bool
 WrapperAnswer::RecvPreventExtensions(const ObjectId& objId, ReturnStatus* rs)
 {
     AutoJSAPI jsapi;
     if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects())))
         return false;
     JSContext* cx = jsapi.cx();
 
     RootedObject obj(cx, findObjectById(cx, objId));
     if (!obj)
-        return fail(jsapi, rs);
+        return deadCPOW(jsapi, rs);
 
     ObjectOpResult success;
     if (!JS_PreventExtensions(cx, obj, success))
         return fail(jsapi, rs);
 
     LOG("%s.preventExtensions()", ReceiverObj(objId));
     return ok(rs, success);
 }
@@ -110,17 +119,17 @@ WrapperAnswer::RecvGetPropertyDescriptor
     AutoJSAPI jsapi;
     if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects())))
         return false;
     JSContext* cx = jsapi.cx();
     EmptyDesc(out);
 
     RootedObject obj(cx, findObjectById(cx, objId));
     if (!obj)
-        return fail(jsapi, rs);
+        return deadCPOW(jsapi, rs);
 
     LOG("%s.getPropertyDescriptor(%s)", ReceiverObj(objId), Identifier(idVar));
 
     RootedId id(cx);
     if (!fromJSIDVariant(cx, idVar, &id))
         return fail(jsapi, rs);
 
     Rooted<PropertyDescriptor> desc(cx);
@@ -140,17 +149,17 @@ WrapperAnswer::RecvGetOwnPropertyDescrip
     AutoJSAPI jsapi;
     if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects())))
         return false;
     JSContext* cx = jsapi.cx();
     EmptyDesc(out);
 
     RootedObject obj(cx, findObjectById(cx, objId));
     if (!obj)
-        return fail(jsapi, rs);
+        return deadCPOW(jsapi, rs);
 
     LOG("%s.getOwnPropertyDescriptor(%s)", ReceiverObj(objId), Identifier(idVar));
 
     RootedId id(cx);
     if (!fromJSIDVariant(cx, idVar, &id))
         return fail(jsapi, rs);
 
     Rooted<PropertyDescriptor> desc(cx);
@@ -169,17 +178,17 @@ WrapperAnswer::RecvDefineProperty(const 
 {
     AutoJSAPI jsapi;
     if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects())))
         return false;
     JSContext* cx = jsapi.cx();
 
     RootedObject obj(cx, findObjectById(cx, objId));
     if (!obj)
-        return fail(jsapi, rs);
+        return deadCPOW(jsapi, rs);
 
     LOG("define %s[%s]", ReceiverObj(objId), Identifier(idVar));
 
     RootedId id(cx);
     if (!fromJSIDVariant(cx, idVar, &id))
         return fail(jsapi, rs);
 
     Rooted<PropertyDescriptor> desc(cx);
@@ -197,17 +206,17 @@ WrapperAnswer::RecvDelete(const ObjectId
 {
     AutoJSAPI jsapi;
     if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects())))
         return false;
     JSContext* cx = jsapi.cx();
 
     RootedObject obj(cx, findObjectById(cx, objId));
     if (!obj)
-        return fail(jsapi, rs);
+        return deadCPOW(jsapi, rs);
 
     LOG("delete %s[%s]", ReceiverObj(objId), Identifier(idVar));
 
     RootedId id(cx);
     if (!fromJSIDVariant(cx, idVar, &id))
         return fail(jsapi, rs);
 
     ObjectOpResult success;
@@ -223,17 +232,17 @@ WrapperAnswer::RecvHas(const ObjectId& o
     AutoJSAPI jsapi;
     if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects())))
         return false;
     JSContext* cx = jsapi.cx();
     *foundp = false;
 
     RootedObject obj(cx, findObjectById(cx, objId));
     if (!obj)
-        return fail(jsapi, rs);
+        return deadCPOW(jsapi, rs);
 
     LOG("%s.has(%s)", ReceiverObj(objId), Identifier(idVar));
 
     RootedId id(cx);
     if (!fromJSIDVariant(cx, idVar, &id))
         return fail(jsapi, rs);
 
     if (!JS_HasPropertyById(cx, obj, id, foundp))
@@ -248,17 +257,17 @@ WrapperAnswer::RecvHasOwn(const ObjectId
     AutoJSAPI jsapi;
     if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects())))
         return false;
     JSContext* cx = jsapi.cx();
     *foundp = false;
 
     RootedObject obj(cx, findObjectById(cx, objId));
     if (!obj)
-        return fail(jsapi, rs);
+        return deadCPOW(jsapi, rs);
 
     LOG("%s.hasOwn(%s)", ReceiverObj(objId), Identifier(idVar));
 
     RootedId id(cx);
     if (!fromJSIDVariant(cx, idVar, &id))
         return fail(jsapi, rs);
 
     if (!JS_HasOwnPropertyById(cx, obj, id, foundp))
@@ -276,17 +285,17 @@ WrapperAnswer::RecvGet(const ObjectId& o
     JSContext* cx = aes.cx();
 
     // The outparam will be written to the buffer, so it must be set even if
     // the parent won't read it.
     *result = UndefinedVariant();
 
     RootedObject obj(cx, findObjectById(cx, objId));
     if (!obj)
-        return fail(aes, rs);
+        return deadCPOW(aes, rs);
 
     RootedValue receiver(cx);
     if (!fromVariant(cx, receiverVar, &receiver))
         return fail(aes, rs);
 
     RootedId id(cx);
     if (!fromJSIDVariant(cx, idVar, &id))
         return fail(aes, rs);
@@ -309,17 +318,17 @@ WrapperAnswer::RecvSet(const ObjectId& o
 {
     // We may run scripted setters.
     AutoEntryScript aes(scopeForTargetObjects(),
                         "Cross-Process Object Wrapper 'set'");
     JSContext* cx = aes.cx();
 
     RootedObject obj(cx, findObjectById(cx, objId));
     if (!obj)
-        return fail(aes, rs);
+        return deadCPOW(aes, rs);
 
     LOG("set %s[%s] = %s", ReceiverObj(objId), Identifier(idVar), InVariant(value));
 
     RootedId id(cx);
     if (!fromJSIDVariant(cx, idVar, &id))
         return fail(aes, rs);
 
     RootedValue val(cx);
@@ -343,17 +352,17 @@ WrapperAnswer::RecvIsExtensible(const Ob
     AutoJSAPI jsapi;
     if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects())))
         return false;
     JSContext* cx = jsapi.cx();
     *result = false;
 
     RootedObject obj(cx, findObjectById(cx, objId));
     if (!obj)
-        return fail(jsapi, rs);
+        return deadCPOW(jsapi, rs);
 
     LOG("%s.isExtensible()", ReceiverObj(objId));
 
     bool extensible;
     if (!JS_IsExtensible(cx, obj, &extensible))
         return fail(jsapi, rs);
 
     *result = !!extensible;
@@ -373,17 +382,17 @@ WrapperAnswer::RecvCallOrConstruct(const
     JSContext* cx = aes.cx();
 
     // The outparam will be written to the buffer, so it must be set even if
     // the parent won't read it.
     *result = UndefinedVariant();
 
     RootedObject obj(cx, findObjectById(cx, objId));
     if (!obj)
-        return fail(aes, rs);
+        return deadCPOW(aes, rs);
 
     MOZ_ASSERT(argv.Length() >= 2);
 
     RootedValue objv(cx);
     if (!fromVariant(cx, argv[0], &objv))
         return fail(aes, rs);
 
     *result = JSVariant(UndefinedVariant());
@@ -468,17 +477,17 @@ WrapperAnswer::RecvHasInstance(const Obj
 {
     AutoJSAPI jsapi;
     if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects())))
         return false;
     JSContext* cx = jsapi.cx();
 
     RootedObject obj(cx, findObjectById(cx, objId));
     if (!obj)
-        return fail(jsapi, rs);
+        return deadCPOW(jsapi, rs);
 
     LOG("%s.hasInstance(%s)", ReceiverObj(objId), InVariant(vVar));
 
     RootedValue val(cx);
     if (!fromVariant(cx, vVar, &val))
         return fail(jsapi, rs);
 
     if (!JS_HasInstance(cx, obj, val, bp))
@@ -495,17 +504,17 @@ WrapperAnswer::RecvGetBuiltinClass(const
 
     AutoJSAPI jsapi;
     if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects())))
         return false;
     JSContext* cx = jsapi.cx();
 
     RootedObject obj(cx, findObjectById(cx, objId));
     if (!obj)
-        return fail(jsapi, rs);
+        return deadCPOW(jsapi, rs);
 
     LOG("%s.getBuiltinClass()", ReceiverObj(objId));
 
     js::ESClass cls;
     if (!js::GetBuiltinClass(cx, obj, &cls))
         return fail(jsapi, rs);
 
     *classValue = uint32_t(cls);
@@ -520,17 +529,17 @@ WrapperAnswer::RecvIsArray(const ObjectI
 
     AutoJSAPI jsapi;
     if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects())))
         return false;
     JSContext* cx = jsapi.cx();
 
     RootedObject obj(cx, findObjectById(cx, objId));
     if (!obj)
-        return fail(jsapi, rs);
+        return deadCPOW(jsapi, rs);
 
     LOG("%s.isArray()", ReceiverObj(objId));
 
     IsArrayAnswer answer;
     if (!JS::IsArray(cx, obj, &answer))
         return fail(jsapi, rs);
 
     *ans = uint32_t(answer);
@@ -565,17 +574,17 @@ WrapperAnswer::RecvGetPrototype(const Ob
 
     AutoJSAPI jsapi;
     if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects())))
         return false;
     JSContext* cx = jsapi.cx();
 
     RootedObject obj(cx, findObjectById(cx, objId));
     if (!obj)
-        return fail(jsapi, rs);
+        return deadCPOW(jsapi, rs);
 
     JS::RootedObject proto(cx);
     if (!JS_GetPrototype(cx, obj, &proto))
         return fail(jsapi, rs);
 
     if (!toObjectOrNullVariant(cx, proto, result))
         return fail(jsapi, rs);
 
@@ -593,17 +602,17 @@ WrapperAnswer::RecvGetPrototypeIfOrdinar
 
     AutoJSAPI jsapi;
     if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects())))
         return false;
     JSContext* cx = jsapi.cx();
 
     RootedObject obj(cx, findObjectById(cx, objId));
     if (!obj)
-        return fail(jsapi, rs);
+        return deadCPOW(jsapi, rs);
 
     JS::RootedObject proto(cx);
     if (!JS_GetPrototypeIfOrdinary(cx, obj, isOrdinary, &proto))
         return fail(jsapi, rs);
 
     if (!toObjectOrNullVariant(cx, proto, result))
         return fail(jsapi, rs);
 
@@ -618,17 +627,17 @@ WrapperAnswer::RecvRegExpToShared(const 
 {
     AutoJSAPI jsapi;
     if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects())))
         return false;
     JSContext* cx = jsapi.cx();
 
     RootedObject obj(cx, findObjectById(cx, objId));
     if (!obj)
-        return fail(jsapi, rs);
+        return deadCPOW(jsapi, rs);
 
     RootedString sourceJSStr(cx, JS_GetRegExpSource(cx, obj));
     if (!sourceJSStr)
         return fail(jsapi, rs);
     nsAutoJSString sourceStr;
     if (!sourceStr.init(cx, sourceJSStr))
         return fail(jsapi, rs);
     source->Assign(sourceStr);
@@ -644,17 +653,17 @@ WrapperAnswer::RecvGetPropertyKeys(const
 {
     AutoJSAPI jsapi;
     if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects())))
         return false;
     JSContext* cx = jsapi.cx();
 
     RootedObject obj(cx, findObjectById(cx, objId));
     if (!obj)
-        return fail(jsapi, rs);
+        return deadCPOW(jsapi, rs);
 
     LOG("%s.getPropertyKeys()", ReceiverObj(objId));
 
     AutoIdVector props(cx);
     if (!js::GetPropertyKeys(cx, obj, flags, &props))
         return fail(jsapi, rs);
 
     for (size_t i = 0; i < props.length(); i++) {
@@ -676,17 +685,17 @@ WrapperAnswer::RecvInstanceOf(const Obje
     if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects())))
         return false;
     JSContext* cx = jsapi.cx();
 
     *instanceof = false;
 
     RootedObject obj(cx, findObjectById(cx, objId));
     if (!obj)
-        return fail(jsapi, rs);
+        return deadCPOW(jsapi, rs);
 
     LOG("%s.instanceOf()", ReceiverObj(objId));
 
     nsID nsiid;
     ConvertID(iid, &nsiid);
 
     nsresult rv = xpc::HasInstance(cx, obj, &nsiid, instanceof);
     if (rv != NS_OK)
@@ -702,17 +711,17 @@ WrapperAnswer::RecvDOMInstanceOf(const O
     AutoJSAPI jsapi;
     if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects())))
         return false;
     JSContext* cx = jsapi.cx();
     *instanceof = false;
 
     RootedObject obj(cx, findObjectById(cx, objId));
     if (!obj)
-        return fail(jsapi, rs);
+        return deadCPOW(jsapi, rs);
 
     LOG("%s.domInstanceOf()", ReceiverObj(objId));
 
     bool tmp;
     if (!mozilla::dom::InterfaceHasInstance(cx, prototypeID, depth, obj, &tmp))
         return fail(jsapi, rs);
     *instanceof = tmp;
 
--- a/js/ipc/WrapperAnswer.h
+++ b/js/ipc/WrapperAnswer.h
@@ -68,14 +68,15 @@ class WrapperAnswer : public virtual Jav
                            ReturnStatus* rs, bool* instanceof);
 
     bool RecvDropObject(const ObjectId& objId);
 
   private:
     bool fail(dom::AutoJSAPI& jsapi, ReturnStatus* rs);
     bool ok(ReturnStatus* rs);
     bool ok(ReturnStatus* rs, const JS::ObjectOpResult& result);
+    bool deadCPOW(dom::AutoJSAPI& jsapi, ReturnStatus* rs);
 };
 
 } // namespace jsipc
 } // namespace mozilla
 
 #endif
--- a/js/ipc/WrapperOwner.cpp
+++ b/js/ipc/WrapperOwner.cpp
@@ -1071,16 +1071,21 @@ bool
 WrapperOwner::ok(JSContext* cx, const ReturnStatus& status)
 {
     if (status.type() == ReturnStatus::TReturnSuccess)
         return true;
 
     if (status.type() == ReturnStatus::TReturnStopIteration)
         return JS_ThrowStopIteration(cx);
 
+    if (status.type() == ReturnStatus::TReturnDeadCPOW) {
+        JS_ReportError(cx, "operation not possible on dead CPOW");
+        return false;
+    }
+
     RootedValue exn(cx);
     if (!fromVariant(cx, status.get_ReturnException().exn(), &exn))
         return false;
 
     JS_SetPendingException(cx, exn);
     return false;
 }