Bug 1065811 - Stop statically computing callability/constructibility on CPOWs. r=billm
authorBobby Holley <bobbyholley@gmail.com>
Thu, 25 Sep 2014 13:13:29 +0200
changeset 207251 8fb1ab37e3e08e8565c722f73853f599e3b033e2
parent 207250 d9edbc602839774e3d790386725be870986099b4
child 207252 bc71142337a34496ae657fcade46e04c1214b71f
push id27550
push userryanvm@gmail.com
push dateThu, 25 Sep 2014 20:46:48 +0000
treeherdermozilla-central@9e3d649b80a2 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbillm
bugs1065811
milestone35.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 1065811 - Stop statically computing callability/constructibility on CPOWs. r=billm
js/ipc/JavaScriptBase.h
js/ipc/PJavaScript.ipdl
js/ipc/WrapperAnswer.cpp
js/ipc/WrapperAnswer.h
js/ipc/WrapperOwner.cpp
js/ipc/WrapperOwner.h
--- a/js/ipc/JavaScriptBase.h
+++ b/js/ipc/JavaScriptBase.h
@@ -106,16 +106,24 @@ class JavaScriptBase : public WrapperOwn
                           ReturnStatus *rs, bool *instanceof) {
         return Answer::AnswerInstanceOf(objId, iid, rs, instanceof);
     }
     bool AnswerDOMInstanceOf(const ObjectId &objId, const int &prototypeID, const int &depth,
                              ReturnStatus *rs, bool *instanceof) {
         return Answer::AnswerDOMInstanceOf(objId, prototypeID, depth, rs, instanceof);
     }
 
+    bool AnswerIsCallable(const ObjectId &objId, bool *result) {
+        return Answer::AnswerIsCallable(objId, result);
+    }
+
+    bool AnswerIsConstructor(const ObjectId &objId, bool *result) {
+        return Answer::AnswerIsConstructor(objId, result);
+    }
+
     bool RecvDropObject(const ObjectId &objId) {
         return Answer::RecvDropObject(objId);
     }
 
     /*** Dummy call handlers ***/
 
     bool SendDropObject(const ObjectId &objId) {
         return Base::SendDropObject(objId);
@@ -191,16 +199,24 @@ class JavaScriptBase : public WrapperOwn
                         ReturnStatus *rs, bool *instanceof) {
         return Base::CallInstanceOf(objId, iid, rs, instanceof);
     }
     bool CallDOMInstanceOf(const ObjectId &objId, const int &prototypeID, const int &depth,
                            ReturnStatus *rs, bool *instanceof) {
         return Base::CallDOMInstanceOf(objId, prototypeID, depth, rs, instanceof);
     }
 
+    bool CallIsCallable(const ObjectId &objId, bool *result) {
+        return Base::CallIsCallable(objId, result);
+    }
+
+    bool CallIsConstructor(const ObjectId &objId, bool *result) {
+        return Base::CallIsConstructor(objId, result);
+    }
+
     /* The following code is needed to suppress a bogus MSVC warning (C4250). */
 
     virtual bool toObjectVariant(JSContext *cx, JSObject *obj, ObjectVariant *objVarp) {
         return WrapperOwner::toObjectVariant(cx, obj, objVarp);
     }
     virtual JSObject *fromObjectVariant(JSContext *cx, ObjectVariant objVar) {
         return WrapperOwner::fromObjectVariant(cx, objVar);
     }
--- a/js/ipc/PJavaScript.ipdl
+++ b/js/ipc/PJavaScript.ipdl
@@ -40,14 +40,17 @@ both:
     rpc HasInstance(uint64_t objId, JSVariant v) returns (ReturnStatus rs, bool has);
     rpc ObjectClassIs(uint64_t objId, uint32_t classValue) returns (bool result);
     rpc ClassName(uint64_t objId) returns (nsString name);
 
     rpc GetPropertyNames(uint64_t objId, uint32_t flags) returns (ReturnStatus rs, nsString[] names);
     rpc InstanceOf(uint64_t objId, JSIID iid) returns (ReturnStatus rs, bool instanceof);
     rpc DOMInstanceOf(uint64_t objId, int prototypeID, int depth) returns (ReturnStatus rs, bool instanceof);
 
+    rpc IsCallable(uint64_t objId) returns (bool result);
+    rpc IsConstructor(uint64_t objId) returns (bool result);
+
 parent:
     async __delete__();
 };
 
 }
 }
--- a/js/ipc/WrapperAnswer.cpp
+++ b/js/ipc/WrapperAnswer.cpp
@@ -631,16 +631,57 @@ WrapperAnswer::AnswerDOMInstanceOf(const
     if (!mozilla::dom::InterfaceHasInstance(cx, prototypeID, depth, obj, &tmp))
         return fail(cx, rs);
     *instanceof = tmp;
 
     return ok(rs);
 }
 
 bool
+WrapperAnswer::AnswerIsCallable(const ObjectId &objId, bool *result)
+{
+    AutoSafeJSContext cx;
+    JSAutoRequest request(cx);
+
+    RootedObject obj(cx, findObjectById(cx, objId));
+    if (!obj) {
+        // This is very unfortunate, but we have no choice.
+        *result = false;
+        return true;
+    }
+    JSAutoCompartment ac(cx, obj); // Not really necessary here, but be safe.
+
+    LOG("%s.isCallable()", ReceiverObj(objId));
+
+    *result = JS::IsCallable(obj);
+    return true;
+}
+
+bool
+WrapperAnswer::AnswerIsConstructor(const ObjectId &objId, bool *result)
+{
+    AutoSafeJSContext cx;
+    JSAutoRequest request(cx);
+
+    RootedObject obj(cx, findObjectById(cx, objId));
+    if (!obj) {
+        // This is very unfortunate, but we have no choice.
+        *result = false;
+        return true;
+    }
+    JSAutoCompartment ac(cx, obj); // Not really necessary here, but be safe.
+
+    LOG("%s.isConstructor()", ReceiverObj(objId));
+
+    *result = JS::IsConstructor(obj);
+    return true;
+}
+
+
+bool
 WrapperAnswer::RecvDropObject(const ObjectId &objId)
 {
     JSObject *obj = findObjectById(objId);
     if (obj) {
         objectIds_.remove(obj);
         objects_.remove(objId);
     }
     return true;
--- a/js/ipc/WrapperAnswer.h
+++ b/js/ipc/WrapperAnswer.h
@@ -55,16 +55,19 @@ class WrapperAnswer : public virtual Jav
 
     bool AnswerGetPropertyNames(const ObjectId &objId, const uint32_t &flags,
                                 ReturnStatus *rs, nsTArray<nsString> *names);
     bool AnswerInstanceOf(const ObjectId &objId, const JSIID &iid,
                           ReturnStatus *rs, bool *instanceof);
     bool AnswerDOMInstanceOf(const ObjectId &objId, const int &prototypeID, const int &depth,
                              ReturnStatus *rs, bool *instanceof);
 
+    bool AnswerIsCallable(const ObjectId &objId, bool *result);
+    bool AnswerIsConstructor(const ObjectId &objId, bool *result);
+
     bool RecvDropObject(const ObjectId &objId);
 
   private:
     bool fail(JSContext *cx, ReturnStatus *rs);
     bool ok(ReturnStatus *rs);
 };
 
 } // mozilla
--- a/js/ipc/WrapperOwner.cpp
+++ b/js/ipc/WrapperOwner.cpp
@@ -658,32 +658,59 @@ CPOWProxyHandler::finalize(JSFreeOp *fop
 
 void
 CPOWProxyHandler::objectMoved(JSObject *proxy, const JSObject *old) const
 {
     OwnerOf(proxy)->updatePointer(proxy, old);
 }
 
 bool
-CPOWProxyHandler::isCallable(JSObject *obj) const
+CPOWProxyHandler::isCallable(JSObject *proxy) const
 {
-    return OwnerOf(obj)->isCallable(obj);
-}
-
-bool
-CPOWProxyHandler::isConstructor(JSObject *obj) const
-{
-    return isCallable(obj);
+    WrapperOwner *parent = OwnerOf(proxy);
+    if (!parent->active())
+        return false;
+    return parent->isCallable(proxy);
 }
 
 bool
 WrapperOwner::isCallable(JSObject *obj)
 {
     ObjectId objId = idOf(obj);
-    return !!(objId & OBJECT_IS_CALLABLE);
+
+    bool callable = false;
+    if (!CallIsCallable(objId, &callable)) {
+        NS_WARNING("IPC isCallable() failed");
+        return false;
+    }
+
+    return callable;
+}
+
+bool
+CPOWProxyHandler::isConstructor(JSObject *proxy) const
+{
+    WrapperOwner *parent = OwnerOf(proxy);
+    if (!parent->active())
+        return false;
+    return parent->isConstructor(proxy);
+}
+
+bool
+WrapperOwner::isConstructor(JSObject *obj)
+{
+    ObjectId objId = idOf(obj);
+
+    bool constructor = false;
+    if (!CallIsConstructor(objId, &constructor)) {
+        NS_WARNING("IPC isConstructor() failed");
+        return false;
+    }
+
+    return constructor;
 }
 
 void
 WrapperOwner::drop(JSObject *obj)
 {
     ObjectId objId = idOf(obj);
 
     cpows_.remove(objId);
--- a/js/ipc/WrapperOwner.h
+++ b/js/ipc/WrapperOwner.h
@@ -56,17 +56,17 @@ class WrapperOwner : public virtual Java
     // SpiderMonkey Extensions.
     bool isExtensible(JSContext *cx, JS::HandleObject proxy, bool *extensible);
     bool callOrConstruct(JSContext *cx, JS::HandleObject proxy, const JS::CallArgs &args,
                          bool construct);
     bool hasInstance(JSContext *cx, JS::HandleObject proxy, JS::MutableHandleValue v, bool *bp);
     bool objectClassIs(JSContext *cx, JS::HandleObject obj, js::ESClassValue classValue);
     const char* className(JSContext *cx, JS::HandleObject proxy);
     bool isCallable(JSObject *obj);
-    // isConstructable is implemented here as isCallable.
+    bool isConstructor(JSObject *obj);
 
     nsresult instanceOf(JSObject *obj, const nsID *id, bool *bp);
 
     bool toString(JSContext *cx, JS::HandleObject callee, JS::CallArgs &args);
 
     /*
      * Check that |obj| is a DOM wrapper whose prototype chain contains
      * |prototypeID| at depth |depth|.
@@ -142,16 +142,19 @@ class WrapperOwner : public virtual Java
     virtual bool CallClassName(const ObjectId &objId, nsString *result) = 0;
 
     virtual bool CallGetPropertyNames(const ObjectId &objId, const uint32_t &flags,
                                       ReturnStatus *rs, nsTArray<nsString> *names) = 0;
     virtual bool CallInstanceOf(const ObjectId &objId, const JSIID &iid,
                                 ReturnStatus *rs, bool *instanceof) = 0;
     virtual bool CallDOMInstanceOf(const ObjectId &objId, const int &prototypeID, const int &depth,
                                    ReturnStatus *rs, bool *instanceof) = 0;
+
+    virtual bool CallIsCallable(const ObjectId &objId, bool *result) = 0;
+    virtual bool CallIsConstructor(const ObjectId &objId, bool *result) = 0;
 };
 
 bool
 IsCPOW(JSObject *obj);
 
 bool
 IsWrappedCPOW(JSObject *obj);