Bug 1067009 - Implement regexp_toShared for CPOWs. r=billm
authorBobby Holley <bobbyholley@gmail.com>
Wed, 01 Oct 2014 17:22:15 +0200
changeset 208195 41a8bae313cc3464fa21db9be558c8cf47b5c76c
parent 208194 b9a03ef2866326f6c777cc556dc5951c90599d52
child 208196 95e16edcc7454db26be3f8c535de3f5a1a9df20c
push id49867
push userbobbyholley@gmail.com
push dateWed, 01 Oct 2014 15:22:42 +0000
treeherdermozilla-inbound@95e16edcc745 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbillm
bugs1067009
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 1067009 - Implement regexp_toShared for 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
js/src/jsfriendapi.h
js/src/vm/RegExpObject.cpp
--- a/js/ipc/JavaScriptBase.h
+++ b/js/ipc/JavaScriptBase.h
@@ -92,16 +92,19 @@ class JavaScriptBase : public WrapperOwn
     }
     bool AnswerObjectClassIs(const uint64_t &objId, const uint32_t &classValue,
                              bool *result) {
         return Answer::AnswerObjectClassIs(ObjectId::deserialize(objId), classValue, result);
     }
     bool AnswerClassName(const uint64_t &objId, nsString *result) {
         return Answer::AnswerClassName(ObjectId::deserialize(objId), result);
     }
+    bool AnswerRegExpToShared(const uint64_t &objId, ReturnStatus *rs, nsString *source, uint32_t *flags) {
+        return Answer::AnswerRegExpToShared(ObjectId::deserialize(objId), rs, source, flags);
+    }
 
     bool AnswerGetPropertyNames(const uint64_t &objId, const uint32_t &flags,
                                 ReturnStatus *rs, nsTArray<nsString> *names) {
         return Answer::AnswerGetPropertyNames(ObjectId::deserialize(objId), flags, rs, names);
     }
     bool AnswerInstanceOf(const uint64_t &objId, const JSIID &iid,
                           ReturnStatus *rs, bool *instanceof) {
         return Answer::AnswerInstanceOf(ObjectId::deserialize(objId), iid, rs, instanceof);
@@ -186,16 +189,21 @@ class JavaScriptBase : public WrapperOwn
     bool CallObjectClassIs(const ObjectId &objId, const uint32_t &classValue,
                            bool *result) {
         return Base::CallObjectClassIs(objId.serialize(), classValue, result);
     }
     bool CallClassName(const ObjectId &objId, nsString *result) {
         return Base::CallClassName(objId.serialize(), result);
     }
 
+    bool CallRegExpToShared(const ObjectId &objId, ReturnStatus *rs,
+                            nsString *source, uint32_t *flags) {
+        return Base::CallRegExpToShared(objId.serialize(), rs, source, flags);
+    }
+
     bool CallGetPropertyNames(const ObjectId &objId, const uint32_t &flags,
                               ReturnStatus *rs, nsTArray<nsString> *names) {
         return Base::CallGetPropertyNames(objId.serialize(), flags, rs, names);
     }
     bool CallInstanceOf(const ObjectId &objId, const JSIID &iid,
                         ReturnStatus *rs, bool *instanceof) {
         return Base::CallInstanceOf(objId.serialize(), iid, rs, instanceof);
     }
--- a/js/ipc/PJavaScript.ipdl
+++ b/js/ipc/PJavaScript.ipdl
@@ -35,16 +35,17 @@ both:
     rpc Get(uint64_t objId, ObjectVariant receiver, nsString id) returns (ReturnStatus rs, JSVariant result);
     rpc Set(uint64_t objId, ObjectVariant receiver, nsString id, bool strict, JSVariant value) returns (ReturnStatus rs, JSVariant result);
 
     rpc IsExtensible(uint64_t objId) returns (ReturnStatus rs, bool result);
     rpc CallOrConstruct(uint64_t objId, JSParam[] argv, bool construct) returns (ReturnStatus rs, JSVariant result, JSParam[] outparams);
     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 RegExpToShared(uint64_t objId) returns (ReturnStatus rs, nsString source, uint32_t flags);
 
     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);
 
--- a/js/ipc/WrapperAnswer.cpp
+++ b/js/ipc/WrapperAnswer.cpp
@@ -548,16 +548,41 @@ WrapperAnswer::AnswerClassName(const Obj
 
     LOG("%s.className()", ReceiverObj(objId));
 
     *name = NS_ConvertASCIItoUTF16(js_ObjectClassName(cx, obj));
     return true;
 }
 
 bool
+WrapperAnswer::AnswerRegExpToShared(const ObjectId &objId, ReturnStatus *rs,
+                                    nsString *source, uint32_t *flags)
+{
+    AutoSafeJSContext cx;
+    RootedObject obj(cx, findObjectById(cx, objId));
+    if (!obj)
+        return fail(cx, rs);
+
+    JSAutoCompartment ac(cx, obj);
+    MOZ_RELEASE_ASSERT(JS_ObjectIsRegExp(cx, obj));
+
+    RootedString sourceJSStr(cx, JS_GetRegExpSource(cx, obj));
+    if (!sourceJSStr)
+        return fail(cx, rs);
+    nsAutoJSString sourceStr;
+    if (!sourceStr.init(cx, sourceJSStr))
+        return fail(cx, rs);
+    source->Assign(sourceStr);
+
+    *flags = JS_GetRegExpFlags(cx, obj);
+
+    return ok(rs);
+}
+
+bool
 WrapperAnswer::AnswerGetPropertyNames(const ObjectId &objId, const uint32_t &flags,
 				      ReturnStatus *rs, nsTArray<nsString> *names)
 {
     AutoSafeJSContext cx;
     JSAutoRequest request(cx);
 
     RootedObject obj(cx, findObjectById(cx, objId));
     if (!obj)
--- a/js/ipc/WrapperAnswer.h
+++ b/js/ipc/WrapperAnswer.h
@@ -47,16 +47,17 @@ class WrapperAnswer : public virtual Jav
                             bool *result);
     bool AnswerCallOrConstruct(const ObjectId &objId, const nsTArray<JSParam> &argv,
                                const bool &construct, ReturnStatus *rs, JSVariant *result,
                                nsTArray<JSParam> *outparams);
     bool AnswerHasInstance(const ObjectId &objId, const JSVariant &v, ReturnStatus *rs, bool *bp);
     bool AnswerObjectClassIs(const ObjectId &objId, const uint32_t &classValue,
                              bool *result);
     bool AnswerClassName(const ObjectId &objId, nsString *result);
+    bool AnswerRegExpToShared(const ObjectId &objId, ReturnStatus *rs, nsString *source, uint32_t *flags);
 
     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);
 
--- a/js/ipc/WrapperOwner.cpp
+++ b/js/ipc/WrapperOwner.cpp
@@ -86,16 +86,17 @@ class CPOWProxyHandler : public BaseProx
     virtual bool isExtensible(JSContext *cx, HandleObject proxy, bool *extensible) const MOZ_OVERRIDE;
     virtual bool call(JSContext *cx, HandleObject proxy, const CallArgs &args) const MOZ_OVERRIDE;
     virtual bool construct(JSContext *cx, HandleObject proxy, const CallArgs &args) const MOZ_OVERRIDE;
     virtual bool hasInstance(JSContext *cx, HandleObject proxy,
                              MutableHandleValue v, bool *bp) const MOZ_OVERRIDE;
     virtual bool objectClassIs(HandleObject obj, js::ESClassValue classValue,
                                JSContext *cx) const MOZ_OVERRIDE;
     virtual const char* className(JSContext *cx, HandleObject proxy) const MOZ_OVERRIDE;
+    virtual bool regexp_toShared(JSContext *cx, HandleObject proxy, RegExpGuard *g) const MOZ_OVERRIDE;
     virtual void finalize(JSFreeOp *fop, JSObject *proxy) const MOZ_OVERRIDE;
     virtual void objectMoved(JSObject *proxy, const JSObject *old) const MOZ_OVERRIDE;
     virtual bool isCallable(JSObject *obj) const MOZ_OVERRIDE;
     virtual bool isConstructor(JSObject *obj) const MOZ_OVERRIDE;
 
     static const char family;
     static const CPOWProxyHandler singleton;
 };
@@ -646,16 +647,47 @@ WrapperOwner::className(JSContext *cx, H
     if (!CallClassName(objId, &name))
         return "<error>";
 
     LOG_STACK();
 
     return ToNewCString(name);
 }
 
+bool
+CPOWProxyHandler::regexp_toShared(JSContext *cx, HandleObject proxy, RegExpGuard *g) const
+{
+    FORWARD(regexp_toShared, (cx, proxy, g));
+}
+
+bool
+WrapperOwner::regexp_toShared(JSContext *cx, HandleObject proxy, RegExpGuard *g)
+{
+    ObjectId objId = idOf(proxy);
+
+    ReturnStatus status;
+    nsString source;
+    unsigned flags = 0;
+    if (!CallRegExpToShared(objId, &status, &source, &flags))
+        return ipcfail(cx);
+
+    LOG_STACK();
+
+    if (!ok(cx, status))
+        return false;
+
+    RootedObject regexp(cx);
+    RootedObject global(cx, JS::CurrentGlobalOrNull(cx));
+    regexp = JS_NewUCRegExpObject(cx, global, source.get(), source.Length(), flags);
+    if (!regexp)
+        return false;
+
+    return js::RegExpToSharedNonInline(cx, regexp, g);
+}
+
 void
 CPOWProxyHandler::finalize(JSFreeOp *fop, JSObject *proxy) const
 {
     OwnerOf(proxy)->drop(proxy);
 }
 
 void
 CPOWProxyHandler::objectMoved(JSObject *proxy, const JSObject *old) const
--- a/js/ipc/WrapperOwner.h
+++ b/js/ipc/WrapperOwner.h
@@ -6,16 +6,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_jsipc_WrapperOwner_h__
 #define mozilla_jsipc_WrapperOwner_h__
 
 #include "JavaScriptShared.h"
 #include "mozilla/ipc/ProtocolUtils.h"
 #include "js/Class.h"
+#include "jsproxy.h"
 
 #ifdef XP_WIN
 #undef GetClassName
 #undef GetClassInfo
 #endif
 
 namespace mozilla {
 namespace jsipc {
@@ -50,16 +51,17 @@ class WrapperOwner : public virtual Java
              JS::HandleId id, JS::MutableHandleValue vp);
     bool set(JSContext *cx, JS::HandleObject proxy, JS::HandleObject receiver,
              JS::HandleId id, bool strict, JS::MutableHandleValue vp);
     bool keys(JSContext *cx, JS::HandleObject proxy, JS::AutoIdVector &props);
     // We use "iterate" provided by the base class here.
 
     // SpiderMonkey Extensions.
     bool isExtensible(JSContext *cx, JS::HandleObject proxy, bool *extensible);
+    bool regexp_toShared(JSContext *cx, JS::HandleObject proxy, js::RegExpGuard *g);
     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);
     bool isConstructor(JSObject *obj);
 
@@ -135,16 +137,18 @@ class WrapperOwner : public virtual Java
     virtual bool CallCallOrConstruct(const ObjectId &objId, const nsTArray<JSParam> &argv,
                                      const bool &construct, ReturnStatus *rs, JSVariant *result,
                                      nsTArray<JSParam> *outparams) = 0;
     virtual bool CallHasInstance(const ObjectId &objId, const JSVariant &v,
                                  ReturnStatus *rs, bool *bp) = 0;
     virtual bool CallObjectClassIs(const ObjectId &objId, const uint32_t &classValue,
                                    bool *result) = 0;
     virtual bool CallClassName(const ObjectId &objId, nsString *result) = 0;
+    virtual bool CallRegExpToShared(const ObjectId &objId, ReturnStatus *rs, nsString *source,
+                                    uint32_t *flags) = 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;
 
--- a/js/src/jsfriendapi.h
+++ b/js/src/jsfriendapi.h
@@ -1152,16 +1152,20 @@ CastToJSFreeOp(FreeOp *fop)
 extern JS_FRIEND_API(JSFlatString *)
 GetErrorTypeName(JSRuntime *rt, int16_t exnType);
 
 #ifdef JS_DEBUG
 extern JS_FRIEND_API(unsigned)
 GetEnterCompartmentDepth(JSContext* cx);
 #endif
 
+class RegExpGuard;
+extern JS_FRIEND_API(bool)
+RegExpToSharedNonInline(JSContext *cx, JS::HandleObject regexp, RegExpGuard *shared);
+
 /* Implemented in jswrapper.cpp. */
 typedef enum NukeReferencesToWindow {
     NukeWindowReferences,
     DontNukeWindowReferences
 } NukeReferencesToWindow;
 
 /*
  * These filters are designed to be ephemeral stack classes, and thus don't
--- a/js/src/vm/RegExpObject.cpp
+++ b/js/src/vm/RegExpObject.cpp
@@ -968,8 +968,14 @@ js::XDRScriptRegExpObject(XDRState<XDR_D
 JSObject *
 js::CloneScriptRegExpObject(JSContext *cx, RegExpObject &reobj)
 {
     /* NB: Keep this in sync with XDRScriptRegExpObject. */
 
     RootedAtom source(cx, reobj.getSource());
     return RegExpObject::createNoStatics(cx, source, reobj.getFlags(), nullptr, cx->tempLifoAlloc());
 }
+
+JS_FRIEND_API(bool)
+js::RegExpToSharedNonInline(JSContext *cx, HandleObject obj, js::RegExpGuard *g)
+{
+    return RegExpToShared(cx, obj, g);
+}