Bug 956293 - Don't pass RegExp proto to CloneRegExpObject. r=h4writer
authorJan de Mooij <jdemooij@mozilla.com>
Fri, 03 Jan 2014 18:58:56 +0100
changeset 162071 a95b638234d5996ba886eb0449a2828d43eaa09a
parent 162070 f6f9b16eb13b3eb0c3f9d1ae79a3f1d3f82b03e5
child 162097 8f0d4afd151e6e474ec7f9a7ae358b2f58433991
push id38080
push userjandemooij@gmail.com
push dateFri, 03 Jan 2014 17:59:27 +0000
treeherdermozilla-inbound@a95b638234d5 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersh4writer
bugs956293
milestone29.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 956293 - Don't pass RegExp proto to CloneRegExpObject. r=h4writer
js/src/jit/BaselineCompiler.cpp
js/src/jit/CodeGenerator.cpp
js/src/jit/CompileInfo-inl.h
js/src/jit/IonBuilder.cpp
js/src/jit/MIR.h
js/src/jsreflect.cpp
js/src/jsscript.h
js/src/jsscriptinlines.h
js/src/vm/Interpreter.cpp
js/src/vm/RegExpObject.cpp
js/src/vm/RegExpObject.h
--- a/js/src/jit/BaselineCompiler.cpp
+++ b/js/src/jit/BaselineCompiler.cpp
@@ -1192,33 +1192,27 @@ BaselineCompiler::emit_JSOP_STRING()
 
 bool
 BaselineCompiler::emit_JSOP_OBJECT()
 {
     frame.push(ObjectValue(*script->getObject(pc)));
     return true;
 }
 
-typedef JSObject *(*CloneRegExpObjectFn)(JSContext *, JSObject *, JSObject *);
+typedef JSObject *(*CloneRegExpObjectFn)(JSContext *, JSObject *);
 static const VMFunction CloneRegExpObjectInfo =
     FunctionInfo<CloneRegExpObjectFn>(CloneRegExpObject);
 
 bool
 BaselineCompiler::emit_JSOP_REGEXP()
 {
-    RootedObject reObj(cx, script->getRegExp(GET_UINT32_INDEX(pc)));
-    RootedObject proto(cx, script->global().getOrCreateRegExpPrototype(cx));
-    if (!proto)
-        return false;
+    RootedObject reObj(cx, script->getRegExp(pc));
 
     prepareVMCall();
-
-    pushArg(ImmGCPtr(proto));
     pushArg(ImmGCPtr(reObj));
-
     if (!callVM(CloneRegExpObjectInfo))
         return false;
 
     // Box and push return value.
     masm.tagValue(JSVAL_TYPE_OBJECT, ReturnReg, R0);
     frame.push(R0);
     return true;
 }
--- a/js/src/jit/CodeGenerator.cpp
+++ b/js/src/jit/CodeGenerator.cpp
@@ -748,26 +748,23 @@ CodeGenerator::visitDoubleToString(LDoub
 
     masm.movePtr(ImmPtr(&GetIonContext()->runtime->staticStrings().intStaticTable), output);
     masm.loadPtr(BaseIndex(output, temp, ScalePointer), output);
 
     masm.bind(ool->rejoin());
     return true;
 }
 
-typedef JSObject *(*CloneRegExpObjectFn)(JSContext *, JSObject *, JSObject *);
+typedef JSObject *(*CloneRegExpObjectFn)(JSContext *, JSObject *);
 static const VMFunction CloneRegExpObjectInfo =
     FunctionInfo<CloneRegExpObjectFn>(CloneRegExpObject);
 
 bool
 CodeGenerator::visitRegExp(LRegExp *lir)
 {
-    JSObject *proto = lir->mir()->getRegExpPrototype();
-
-    pushArg(ImmGCPtr(proto));
     pushArg(ImmGCPtr(lir->mir()->source()));
     return callVM(CloneRegExpObjectInfo, lir);
 }
 
 typedef bool (*RegExpTestRawFn)(JSContext *cx, HandleObject regexp,
                                 HandleString input, bool *result);
 static const VMFunction RegExpTestRawInfo = FunctionInfo<RegExpTestRawFn>(regexp_test_raw);
 
--- a/js/src/jit/CompileInfo-inl.h
+++ b/js/src/jit/CompileInfo-inl.h
@@ -12,17 +12,17 @@
 #include "jsscriptinlines.h"
 
 using namespace js;
 using namespace jit;
 
 inline RegExpObject *
 CompileInfo::getRegExp(jsbytecode *pc) const
 {
-    return script_->getRegExp(GET_UINT32_INDEX(pc));
+    return script_->getRegExp(pc);
 }
 
 inline JSFunction *
 CompileInfo::getFunction(jsbytecode *pc) const
 {
     return script_->getFunction(GET_UINT32_INDEX(pc));
 }
 
--- a/js/src/jit/IonBuilder.cpp
+++ b/js/src/jit/IonBuilder.cpp
@@ -9061,19 +9061,17 @@ IonBuilder::jsop_regexp(RegExpObject *re
         DebugOnly<uint32_t> origFlags = reobj->getFlags();
         DebugOnly<uint32_t> staticsFlags = res->getFlags();
         JS_ASSERT((origFlags & staticsFlags) == staticsFlags);
 
         if (!reobj->global() && !reobj->sticky())
             mustClone = false;
     }
 
-    JSObject *prototype = reobj->getProto();
-
-    MRegExp *regexp = MRegExp::New(alloc(), constraints(), reobj, prototype, mustClone);
+    MRegExp *regexp = MRegExp::New(alloc(), constraints(), reobj, mustClone);
     current->add(regexp);
     current->push(regexp);
 
     regexp->setMovable();
 
     // The MRegExp is set to be movable.
     // That would be incorrect for global/sticky, because lastIndex could be wrong.
     // Therefore setting the lastIndex to 0. That is faster than removing the movable flag.
--- a/js/src/jit/MIR.h
+++ b/js/src/jit/MIR.h
@@ -4776,49 +4776,41 @@ class MDefFun : public MUnaryInstruction
     bool possiblyCalls() const {
         return true;
     }
 };
 
 class MRegExp : public MNullaryInstruction
 {
     CompilerRoot<RegExpObject *> source_;
-    CompilerRootObject prototype_;
     bool mustClone_;
 
-    MRegExp(types::CompilerConstraintList *constraints, RegExpObject *source, JSObject *prototype, bool mustClone)
+    MRegExp(types::CompilerConstraintList *constraints, RegExpObject *source, bool mustClone)
       : source_(source),
-        prototype_(prototype),
         mustClone_(mustClone)
     {
         setResultType(MIRType_Object);
-
-        JS_ASSERT(source->getProto() == prototype);
         setResultTypeSet(MakeSingletonTypeSet(constraints, source));
     }
 
   public:
     INSTRUCTION_HEADER(RegExp)
 
     static MRegExp *New(TempAllocator &alloc, types::CompilerConstraintList *constraints,
-                        RegExpObject *source, JSObject *prototype,
-                        bool mustClone)
-    {
-        return new(alloc) MRegExp(constraints, source, prototype, mustClone);
+                        RegExpObject *source, bool mustClone)
+    {
+        return new(alloc) MRegExp(constraints, source, mustClone);
     }
 
     bool mustClone() const {
         return mustClone_;
     }
     RegExpObject *source() const {
         return source_;
     }
-    JSObject *getRegExpPrototype() const {
-        return prototype_;
-    }
     AliasSet getAliasSet() const {
         return AliasSet::None();
     }
     bool possiblyCalls() const {
         return true;
     }
 };
 
--- a/js/src/jsreflect.cpp
+++ b/js/src/jsreflect.cpp
@@ -2885,21 +2885,17 @@ ASTSerializer::literal(ParseNode *pn, Mu
         val.setString(pn->pn_atom);
         break;
 
       case PNK_REGEXP:
       {
         RootedObject re1(cx, pn->as<RegExpLiteral>().objbox()->object);
         LOCAL_ASSERT(re1 && re1->is<RegExpObject>());
 
-        RootedObject proto(cx);
-        if (!js_GetClassPrototype(cx, JSProto_RegExp, &proto))
-            return false;
-
-        RootedObject re2(cx, CloneRegExpObject(cx, re1, proto));
+        RootedObject re2(cx, CloneRegExpObject(cx, re1));
         if (!re2)
             return false;
 
         val.setObject(*re2);
         break;
       }
 
       case PNK_NUMBER:
--- a/js/src/jsscript.h
+++ b/js/src/jsscript.h
@@ -1385,16 +1385,17 @@ class JSScript : public js::gc::Barriere
         return JSVersion(version);
     }
 
     inline JSFunction *getFunction(size_t index);
     inline JSFunction *getCallerFunction();
     inline JSFunction *functionOrCallerFunction();
 
     inline js::RegExpObject *getRegExp(size_t index);
+    inline js::RegExpObject *getRegExp(jsbytecode *pc);
 
     const js::Value &getConst(size_t index) {
         js::ConstArray *arr = consts();
         JS_ASSERT(index < arr->length);
         return arr->vector[index];
     }
 
     js::StaticBlockObject *getBlockScope(jsbytecode *pc);
--- a/js/src/jsscriptinlines.h
+++ b/js/src/jsscriptinlines.h
@@ -86,16 +86,23 @@ JSScript::getRegExp(size_t index)
 {
     js::ObjectArray *arr = regexps();
     JS_ASSERT(uint32_t(index) < arr->length);
     JSObject *obj = arr->vector[index];
     JS_ASSERT(obj->is<js::RegExpObject>());
     return (js::RegExpObject *) obj;
 }
 
+inline js::RegExpObject *
+JSScript::getRegExp(jsbytecode *pc)
+{
+    JS_ASSERT(containsPC(pc) && containsPC(pc + sizeof(uint32_t)));
+    return getRegExp(GET_UINT32_INDEX(pc));
+}
+
 inline js::GlobalObject &
 JSScript::global() const
 {
     /*
      * A JSScript always marks its compartment's global (via bindings) so we
      * can assert that maybeGlobal is non-null here.
      */
     js::AutoThreadSafeAccess ts(this);
--- a/js/src/vm/Interpreter.cpp
+++ b/js/src/vm/Interpreter.cpp
@@ -2774,21 +2774,17 @@ CASE(JSOP_OBJECT)
 END_CASE(JSOP_OBJECT)
 
 CASE(JSOP_REGEXP)
 {
     /*
      * Push a regexp object cloned from the regexp literal object mapped by the
      * bytecode at pc.
      */
-    uint32_t index = GET_UINT32_INDEX(REGS.pc);
-    JSObject *proto = REGS.fp()->global().getOrCreateRegExpPrototype(cx);
-    if (!proto)
-        goto error;
-    JSObject *obj = CloneRegExpObject(cx, script->getRegExp(index), proto);
+    JSObject *obj = CloneRegExpObject(cx, script->getRegExp(REGS.pc));
     if (!obj)
         goto error;
     PUSH_OBJECT(*obj);
 }
 END_CASE(JSOP_REGEXP)
 
 CASE(JSOP_ZERO)
     PUSH_INT32(0);
--- a/js/src/vm/RegExpObject.cpp
+++ b/js/src/vm/RegExpObject.cpp
@@ -89,30 +89,28 @@ RegExpObjectBuilder::build(HandleAtom so
 {
     if (!getOrCreate())
         return nullptr;
 
     return reobj_->init(cx, source, flags) ? reobj_.get() : nullptr;
 }
 
 RegExpObject *
-RegExpObjectBuilder::clone(Handle<RegExpObject *> other, Handle<RegExpObject *> proto)
+RegExpObjectBuilder::clone(Handle<RegExpObject *> other)
 {
     RootedTypeObject type(cx, other->type());
-    JS_ASSERT(type->proto().toObject() == proto);
-
     if (!getOrCreateClone(type))
         return nullptr;
 
     /*
      * Check that the RegExpShared for the original is okay to use in
      * the clone -- if the |RegExpStatics| provides more flags we'll
      * need a different |RegExpShared|.
      */
-    RegExpStatics *res = proto->getParent()->as<GlobalObject>().getRegExpStatics();
+    RegExpStatics *res = other->getProto()->getParent()->as<GlobalObject>().getRegExpStatics();
     RegExpFlag origFlags = other->getFlags();
     RegExpFlag staticsFlags = res->getFlags();
     if ((origFlags & staticsFlags) != staticsFlags) {
         RegExpFlag newFlags = RegExpFlag(origFlags | staticsFlags);
         Rooted<JSAtom *> source(cx, other->getSource());
         return build(source, newFlags);
     }
 
@@ -776,22 +774,21 @@ RegExpCompartment::sizeOfExcludingThis(m
     n += map_.sizeOfExcludingThis(mallocSizeOf);
     n += inUse_.sizeOfExcludingThis(mallocSizeOf);
     return n;
 }
 
 /* Functions */
 
 JSObject *
-js::CloneRegExpObject(JSContext *cx, JSObject *obj_, JSObject *proto_)
+js::CloneRegExpObject(JSContext *cx, JSObject *obj_)
 {
     RegExpObjectBuilder builder(cx);
     Rooted<RegExpObject*> regex(cx, &obj_->as<RegExpObject>());
-    Rooted<RegExpObject*> proto(cx, &proto_->as<RegExpObject>());
-    JSObject *res = builder.clone(regex, proto);
+    JSObject *res = builder.clone(regex);
     JS_ASSERT(res->type() == regex->type());
     return res;
 }
 
 bool
 js::ParseRegExpFlags(JSContext *cx, JSString *flagStr, RegExpFlag *flagsOut)
 {
     size_t n = flagStr->length();
--- a/js/src/vm/RegExpObject.h
+++ b/js/src/vm/RegExpObject.h
@@ -79,21 +79,21 @@ class RegExpObjectBuilder
     RegExpObjectBuilder(ExclusiveContext *cx, RegExpObject *reobj = nullptr);
 
     RegExpObject *reobj() { return reobj_; }
 
     RegExpObject *build(HandleAtom source, RegExpFlag flags);
     RegExpObject *build(HandleAtom source, RegExpShared &shared);
 
     /* Perform a VM-internal clone. */
-    RegExpObject *clone(Handle<RegExpObject*> other, Handle<RegExpObject*> proto);
+    RegExpObject *clone(Handle<RegExpObject*> other);
 };
 
 JSObject *
-CloneRegExpObject(JSContext *cx, JSObject *obj, JSObject *proto);
+CloneRegExpObject(JSContext *cx, JSObject *obj);
 
 /*
  * A RegExpShared is the compiled representation of a regexp. A RegExpShared is
  * potentially pointed to by multiple RegExpObjects. Additionally, C++ code may
  * have pointers to RegExpShareds on the stack. The RegExpShareds are kept in a
  * cache so that they can be reused when compiling the same regex string.
  *
  * During a GC, the trace hook for RegExpObject clears any pointers to