From 5270447ff4dff2a4956231e6181a615da0ffcf8e Mon Sep 17 00:00:00 2001 From: Bill McCloskey Date: Tue, 4 Nov 2014 17:39:34 -0800 Subject: [PATCH] Bug 1091964 - [e10s] Cache isCallable and isConstructor for CPOWs (r=mrbkap) --- js/ipc/JavaScriptBase.h | 16 ------- js/ipc/JavaScriptTypes.ipdlh | 2 + js/ipc/PJavaScript.ipdl | 3 -- js/ipc/WrapperAnswer.cpp | 41 ----------------- js/ipc/WrapperAnswer.h | 3 -- js/ipc/WrapperOwner.cpp | 88 +++++++++++++++++------------------- js/ipc/WrapperOwner.h | 5 -- 7 files changed, 44 insertions(+), 114 deletions(-) diff --git a/js/ipc/JavaScriptBase.h b/js/ipc/JavaScriptBase.h index a80e784f3af2..2ae230bb0f7a 100644 --- a/js/ipc/JavaScriptBase.h +++ b/js/ipc/JavaScriptBase.h @@ -116,14 +116,6 @@ class JavaScriptBase : public WrapperOwner, public WrapperAnswer, public Base return Answer::RecvDOMInstanceOf(ObjectId::deserialize(objId), prototypeID, depth, rs, instanceof); } - bool RecvIsCallable(const uint64_t &objId, bool *result) { - return Answer::RecvIsCallable(ObjectId::deserialize(objId), result); - } - - bool RecvIsConstructor(const uint64_t &objId, bool *result) { - return Answer::RecvIsConstructor(ObjectId::deserialize(objId), result); - } - bool RecvDropObject(const uint64_t &objId) { return Answer::RecvDropObject(ObjectId::deserialize(objId)); } @@ -215,14 +207,6 @@ class JavaScriptBase : public WrapperOwner, public WrapperAnswer, public Base return Base::SendDOMInstanceOf(objId.serialize(), prototypeID, depth, rs, instanceof); } - bool SendIsCallable(const ObjectId &objId, bool *result) { - return Base::SendIsCallable(objId.serialize(), result); - } - - bool SendIsConstructor(const ObjectId &objId, bool *result) { - return Base::SendIsConstructor(objId.serialize(), result); - } - /* The following code is needed to suppress a bogus MSVC warning (C4250). */ virtual bool toObjectVariant(JSContext *cx, JSObject *obj, ObjectVariant *objVarp) { diff --git a/js/ipc/JavaScriptTypes.ipdlh b/js/ipc/JavaScriptTypes.ipdlh index a5c57792b7b7..975e3aa39e19 100644 --- a/js/ipc/JavaScriptTypes.ipdlh +++ b/js/ipc/JavaScriptTypes.ipdlh @@ -35,6 +35,8 @@ struct LocalObject struct RemoteObject { uint64_t serializedId; + bool isCallable; + bool isConstructor; }; union ObjectVariant diff --git a/js/ipc/PJavaScript.ipdl b/js/ipc/PJavaScript.ipdl index 6638ce19f3bc..8f89fd139ca5 100644 --- a/js/ipc/PJavaScript.ipdl +++ b/js/ipc/PJavaScript.ipdl @@ -46,9 +46,6 @@ both: prio(high) sync InstanceOf(uint64_t objId, JSIID iid) returns (ReturnStatus rs, bool instanceof); prio(high) sync DOMInstanceOf(uint64_t objId, int prototypeID, int depth) returns (ReturnStatus rs, bool instanceof); - prio(high) sync IsCallable(uint64_t objId) returns (bool result); - prio(high) sync IsConstructor(uint64_t objId) returns (bool result); - parent: async __delete__(); }; diff --git a/js/ipc/WrapperAnswer.cpp b/js/ipc/WrapperAnswer.cpp index e2ef50b309bb..fa8a6a9f2f32 100644 --- a/js/ipc/WrapperAnswer.cpp +++ b/js/ipc/WrapperAnswer.cpp @@ -662,47 +662,6 @@ WrapperAnswer::RecvDOMInstanceOf(const ObjectId &objId, const int &prototypeID, return ok(rs); } -bool -WrapperAnswer::RecvIsCallable(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::RecvIsConstructor(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) { diff --git a/js/ipc/WrapperAnswer.h b/js/ipc/WrapperAnswer.h index 180bad5abaac..772416abb2b8 100644 --- a/js/ipc/WrapperAnswer.h +++ b/js/ipc/WrapperAnswer.h @@ -62,9 +62,6 @@ class WrapperAnswer : public virtual JavaScriptShared bool RecvDOMInstanceOf(const ObjectId &objId, const int &prototypeID, const int &depth, ReturnStatus *rs, bool *instanceof); - bool RecvIsCallable(const ObjectId &objId, bool *result); - bool RecvIsConstructor(const ObjectId &objId, bool *result); - bool RecvDropObject(const ObjectId &objId); private: diff --git a/js/ipc/WrapperOwner.cpp b/js/ipc/WrapperOwner.cpp index 3bbb1414fd3f..8eb6b30ae2a8 100644 --- a/js/ipc/WrapperOwner.cpp +++ b/js/ipc/WrapperOwner.cpp @@ -18,12 +18,32 @@ using namespace JS; using namespace mozilla; using namespace mozilla::jsipc; +struct AuxCPOWData +{ + ObjectId id; + bool isCallable; + bool isConstructor; + + AuxCPOWData(ObjectId id, bool isCallable, bool isConstructor) + : id(id), + isCallable(isCallable), + isConstructor(isConstructor) + {} +}; + WrapperOwner::WrapperOwner(JSRuntime *rt) : JavaScriptShared(rt), inactive_(false) { } +static inline AuxCPOWData * +AuxCPOWDataOf(JSObject *obj) +{ + MOZ_ASSERT(IsCPOW(obj)); + return static_cast(GetProxyExtra(obj, 1).toPrivate()); +} + static inline WrapperOwner * OwnerOf(JSObject *obj) { @@ -36,13 +56,9 @@ WrapperOwner::idOfUnchecked(JSObject *obj) { MOZ_ASSERT(IsCPOW(obj)); - Value v = GetProxyExtra(obj, 1); - MOZ_ASSERT(v.isDouble()); - - ObjectId objId = ObjectId::deserialize(BitwiseCast(v.toDouble())); - MOZ_ASSERT(!objId.isNull()); - - return objId; + AuxCPOWData *aux = AuxCPOWDataOf(obj); + MOZ_ASSERT(!aux->id.isNull()); + return aux->id; } ObjectId @@ -689,6 +705,10 @@ void CPOWProxyHandler::finalize(JSFreeOp *fop, JSObject *proxy) const { OwnerOf(proxy)->drop(proxy); + + AuxCPOWData *aux = AuxCPOWDataOf(proxy); + if (aux) + delete aux; } void @@ -700,47 +720,15 @@ CPOWProxyHandler::objectMoved(JSObject *proxy, const JSObject *old) const bool CPOWProxyHandler::isCallable(JSObject *proxy) const { - WrapperOwner *parent = OwnerOf(proxy); - if (!parent->active()) - return false; - return parent->isCallable(proxy); -} - -bool -WrapperOwner::isCallable(JSObject *obj) -{ - ObjectId objId = idOf(obj); - - bool callable = false; - if (!SendIsCallable(objId, &callable)) { - NS_WARNING("IPC isCallable() failed"); - return false; - } - - return callable; + AuxCPOWData *aux = AuxCPOWDataOf(proxy); + return aux->isCallable; } 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 (!SendIsConstructor(objId, &constructor)) { - NS_WARNING("IPC isConstructor() failed"); - return false; - } - - return constructor; + AuxCPOWData *aux = AuxCPOWDataOf(proxy); + return aux->isConstructor; } void @@ -895,6 +883,12 @@ WrapperOwner::ok(JSContext *cx, const ReturnStatus &status) return false; } +static RemoteObject +MakeRemoteObject(ObjectId id, JSObject *obj) +{ + return RemoteObject(id.serialize(), JS::IsCallable(obj), JS::IsConstructor(obj)); +} + bool WrapperOwner::toObjectVariant(JSContext *cx, JSObject *objArg, ObjectVariant *objVarp) { @@ -916,7 +910,7 @@ WrapperOwner::toObjectVariant(JSContext *cx, JSObject *objArg, ObjectVariant *ob ObjectId id = objectIdMap(waiveXray).find(obj); if (!id.isNull()) { MOZ_ASSERT(id.hasXrayWaiver() == waiveXray); - *objVarp = RemoteObject(id.serialize()); + *objVarp = MakeRemoteObject(id, obj); return true; } @@ -931,7 +925,7 @@ WrapperOwner::toObjectVariant(JSContext *cx, JSObject *objArg, ObjectVariant *ob if (!objectIdMap(waiveXray).add(cx, obj, id)) return false; - *objVarp = RemoteObject(id.serialize()); + *objVarp = MakeRemoteObject(id, obj); return true; } @@ -970,8 +964,10 @@ WrapperOwner::fromRemoteObjectVariant(JSContext *cx, RemoteObject objVar) // Incref once we know the decref will be called. incref(); + AuxCPOWData *aux = new AuxCPOWData(objId, objVar.isCallable(), objVar.isConstructor()); + SetProxyExtra(obj, 0, PrivateValue(this)); - SetProxyExtra(obj, 1, DoubleValue(BitwiseCast(objId.serialize()))); + SetProxyExtra(obj, 1, PrivateValue(aux)); } if (!JS_WrapObject(cx, &obj)) diff --git a/js/ipc/WrapperOwner.h b/js/ipc/WrapperOwner.h index 47bad3ccfd47..5ff469dc233a 100644 --- a/js/ipc/WrapperOwner.h +++ b/js/ipc/WrapperOwner.h @@ -61,8 +61,6 @@ class WrapperOwner : public virtual JavaScriptShared bool objectClassIs(JSContext *cx, JS::HandleObject obj, js::ESClassValue classValue); const char* className(JSContext *cx, JS::HandleObject proxy); bool regexp_toShared(JSContext *cx, JS::HandleObject proxy, js::RegExpGuard *g); - bool isCallable(JSObject *obj); - bool isConstructor(JSObject *obj); nsresult instanceOf(JSObject *obj, const nsID *id, bool *bp); @@ -151,9 +149,6 @@ class WrapperOwner : public virtual JavaScriptShared ReturnStatus *rs, bool *instanceof) = 0; virtual bool SendDOMInstanceOf(const ObjectId &objId, const int &prototypeID, const int &depth, ReturnStatus *rs, bool *instanceof) = 0; - - virtual bool SendIsCallable(const ObjectId &objId, bool *result) = 0; - virtual bool SendIsConstructor(const ObjectId &objId, bool *result) = 0; }; bool