author | David Mandelin <dmandelin@mozilla.com> |
Thu, 26 Aug 2010 14:06:07 -0700 | |
changeset 53511 | 169f616ec5bcf7d8ac4f59cc220fa47a6534e3d8 |
parent 53510 | 24c6d6f82b902680c4c9570eb56fcae8c58e1d68 |
child 53512 | 77a3aa93531913d5aa7dac1abe6760df69083ef6 |
push id | 15660 |
push user | rsayre@mozilla.com |
push date | Sat, 11 Sep 2010 19:16:24 +0000 |
treeherder | mozilla-central@f1bd314e64ac [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | dvander |
bugs | 590380 |
milestone | 2.0b5pre |
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
|
--- a/js/src/jsemit.cpp +++ b/js/src/jsemit.cpp @@ -193,16 +193,20 @@ UpdateDepth(JSContext *cx, JSCodeGenerat case JSOP_PROPINC: case JSOP_PROPDEC: depth += 1; break; case JSOP_NAMEINC: case JSOP_NAMEDEC: case JSOP_INCNAME: case JSOP_DECNAME: + case JSOP_GNAMEINC: + case JSOP_GNAMEDEC: + case JSOP_INCGNAME: + case JSOP_DECGNAME: depth += 2; break; default: break; } if (depth > cg->maxStackDepth) cg->maxStackDepth = depth; }
--- a/js/src/jsopcode.tbl +++ b/js/src/jsopcode.tbl @@ -394,20 +394,20 @@ OPDEF(JSOP_THROWING, 151,"throwing" /* Set and get return value pseudo-register in stack frame. */ OPDEF(JSOP_SETRVAL, 152,"setrval", NULL, 1, 1, 0, 2, JOF_BYTE) OPDEF(JSOP_RETRVAL, 153,"retrval", NULL, 1, 0, 0, 0, JOF_BYTE) /* Free variable references that must either be found on the global or a ReferenceError */ OPDEF(JSOP_GETGNAME, 154,"getgname", NULL, 3, 0, 1, 19, JOF_ATOM|JOF_NAME|JOF_GNAME) OPDEF(JSOP_SETGNAME, 155,"setgname", NULL, 3, 2, 1, 3, JOF_ATOM|JOF_NAME|JOF_SET|JOF_DETECTING|JOF_GNAME) -OPDEF(JSOP_INCGNAME, 156,"incgname", NULL, 3, 0, 1, 15, JOF_ATOM|JOF_NAME|JOF_INC|JOF_TMPSLOT2|JOF_GNAME) -OPDEF(JSOP_DECGNAME, 157,"decgname", NULL, 3, 0, 1, 15, JOF_ATOM|JOF_NAME|JOF_DEC|JOF_TMPSLOT2|JOF_GNAME) -OPDEF(JSOP_GNAMEINC, 158,"gnameinc", NULL, 3, 0, 1, 15, JOF_ATOM|JOF_NAME|JOF_INC|JOF_POST|JOF_TMPSLOT2|JOF_GNAME) -OPDEF(JSOP_GNAMEDEC, 159,"gnamedec", NULL, 3, 0, 1, 15, JOF_ATOM|JOF_NAME|JOF_DEC|JOF_POST|JOF_TMPSLOT2|JOF_GNAME) +OPDEF(JSOP_INCGNAME, 156,"incgname", NULL, 3, 0, 1, 15, JOF_ATOM|JOF_NAME|JOF_INC|JOF_TMPSLOT3|JOF_GNAME) +OPDEF(JSOP_DECGNAME, 157,"decgname", NULL, 3, 0, 1, 15, JOF_ATOM|JOF_NAME|JOF_DEC|JOF_TMPSLOT3|JOF_GNAME) +OPDEF(JSOP_GNAMEINC, 158,"gnameinc", NULL, 3, 0, 1, 15, JOF_ATOM|JOF_NAME|JOF_INC|JOF_POST|JOF_TMPSLOT3|JOF_GNAME) +OPDEF(JSOP_GNAMEDEC, 159,"gnamedec", NULL, 3, 0, 1, 15, JOF_ATOM|JOF_NAME|JOF_DEC|JOF_POST|JOF_TMPSLOT3|JOF_GNAME) /* Regular expression literal requiring special "fork on exec" handling. */ OPDEF(JSOP_REGEXP, 160,"regexp", NULL, 3, 0, 1, 19, JOF_REGEXP) /* XML (ECMA-357, a.k.a. "E4X") support. */ OPDEF(JSOP_DEFXMLNS, 161,"defxmlns", NULL, 1, 1, 0, 0, JOF_BYTE) OPDEF(JSOP_ANYNAME, 162,"anyname", NULL, 1, 0, 1, 19, JOF_BYTE|JOF_XMLNAME) OPDEF(JSOP_QNAMEPART, 163,"qnamepart", NULL, 3, 0, 1, 19, JOF_ATOM|JOF_XMLNAME)
--- a/js/src/methodjit/Compiler.cpp +++ b/js/src/methodjit/Compiler.cpp @@ -762,16 +762,17 @@ mjit::Compiler::generateMethod() BEGIN_CASE(JSOP_INCNAME) jsop_nameinc(op, stubs::IncName, fullAtomIndex(PC)); break; END_CASE(JSOP_INCNAME) BEGIN_CASE(JSOP_INCGNAME) jsop_gnameinc(op, stubs::IncGlobalName, fullAtomIndex(PC)); + break; END_CASE(JSOP_INCGNAME) BEGIN_CASE(JSOP_INCPROP) jsop_propinc(op, stubs::IncProp, fullAtomIndex(PC)); break; END_CASE(JSOP_INCPROP) BEGIN_CASE(JSOP_INCELEM) @@ -780,16 +781,17 @@ mjit::Compiler::generateMethod() BEGIN_CASE(JSOP_DECNAME) jsop_nameinc(op, stubs::DecName, fullAtomIndex(PC)); break; END_CASE(JSOP_DECNAME) BEGIN_CASE(JSOP_DECGNAME) jsop_gnameinc(op, stubs::DecGlobalName, fullAtomIndex(PC)); + break; END_CASE(JSOP_DECGNAME) BEGIN_CASE(JSOP_DECPROP) jsop_propinc(op, stubs::DecProp, fullAtomIndex(PC)); break; END_CASE(JSOP_DECPROP) BEGIN_CASE(JSOP_DECELEM) @@ -798,16 +800,17 @@ mjit::Compiler::generateMethod() BEGIN_CASE(JSOP_NAMEINC) jsop_nameinc(op, stubs::NameInc, fullAtomIndex(PC)); break; END_CASE(JSOP_NAMEINC) BEGIN_CASE(JSOP_GNAMEINC) jsop_gnameinc(op, stubs::GlobalNameInc, fullAtomIndex(PC)); + break; END_CASE(JSOP_GNAMEINC) BEGIN_CASE(JSOP_PROPINC) jsop_propinc(op, stubs::PropInc, fullAtomIndex(PC)); break; END_CASE(JSOP_PROPINC) BEGIN_CASE(JSOP_ELEMINC) @@ -816,16 +819,17 @@ mjit::Compiler::generateMethod() BEGIN_CASE(JSOP_NAMEDEC) jsop_nameinc(op, stubs::NameDec, fullAtomIndex(PC)); break; END_CASE(JSOP_NAMEDEC) BEGIN_CASE(JSOP_GNAMEDEC) jsop_gnameinc(op, stubs::GlobalNameDec, fullAtomIndex(PC)); + break; END_CASE(JSOP_GNAMEDEC) BEGIN_CASE(JSOP_PROPDEC) jsop_propinc(op, stubs::PropDec, fullAtomIndex(PC)); break; END_CASE(JSOP_PROPDEC) BEGIN_CASE(JSOP_ELEMDEC) @@ -2942,20 +2946,98 @@ mjit::Compiler::jsop_this() stubcc.rejoin(Changes(1)); } } void mjit::Compiler::jsop_gnameinc(JSOp op, VoidStubAtom stub, uint32 index) { JSAtom *atom = script->getAtom(index); +#if defined JS_MONOIC + jsbytecode *next = &PC[JSOP_GNAMEINC_LENGTH]; + bool pop = (JSOp(*next) == JSOP_POP) && !analysis[next].nincoming; + int amt = (op == JSOP_GNAMEINC || op == JSOP_INCGNAME) ? -1 : 1; + + if (pop || (op == JSOP_INCGNAME || op == JSOP_DECGNAME)) { + /* These cases are easy, the original value is not observed. */ + + jsop_getgname(index); + // V + + frame.push(Int32Value(amt)); + // V 1 + + /* Use sub since it calls ValueToNumber instead of string concat. */ + jsop_binary(JSOP_SUB, stubs::Sub); + // N+1 + + jsop_bindgname(); + // V+1 OBJ + + frame.dup2(); + // V+1 OBJ V+1 OBJ + + frame.shift(-3); + // OBJ OBJ V+1 + + frame.shift(-1); + // OBJ V+1 + + jsop_setgname(index); + // V+1 + + if (pop) + frame.pop(); + } else { + /* The pre-value is observed, making this more tricky. */ + + jsop_getgname(index); + // V + + jsop_pos(); + // N + + frame.dup(); + // N N + + frame.push(Int32Value(-amt)); + // N N 1 + + jsop_binary(JSOP_ADD, stubs::Add); + // N N+1 + + jsop_bindgname(); + // N N+1 OBJ + + frame.dup2(); + // N N+1 OBJ N+1 OBJ + + frame.shift(-3); + // N OBJ OBJ N+1 + + frame.shift(-1); + // N OBJ N+1 + + jsop_setgname(index); + // N N+1 + + frame.pop(); + // N + } + + if (pop) + PC += JSOP_POP_LENGTH; +#else prepareStubCall(Uses(0)); masm.move(ImmPtr(atom), Registers::ArgReg1); stubCall(stub); frame.pushSynced(); +#endif + + PC += JSOP_GNAMEINC_LENGTH; } void mjit::Compiler::jsop_nameinc(JSOp op, VoidStubAtom stub, uint32 index) { JSAtom *atom = script->getAtom(index); #if defined JS_POLYIC jsbytecode *next = &PC[JSOP_NAMEINC_LENGTH];
--- a/js/src/methodjit/MonoIC.cpp +++ b/js/src/methodjit/MonoIC.cpp @@ -134,30 +134,36 @@ PatchSetFallback(VMFrame &f, ic::MICInfo void JS_FASTCALL ic::SetGlobalName(VMFrame &f, uint32 index) { JSObject *obj = f.fp()->getScopeChain()->getGlobal(); ic::MICInfo &mic = f.fp()->getScript()->mics[index]; JSAtom *atom = f.fp()->getScript()->getAtom(GET_INDEX(f.regs.pc)); jsid id = ATOM_TO_JSID(atom); + // The property cache doesn't like inc ops, so we use a simpler + // stub for that case. + VoidStubAtom stub = js_CodeSpec[*f.regs.pc].format & (JOF_INC | JOF_DEC) + ? stubs::SetGlobalNameDumb + : stubs::SetGlobalName; + JS_ASSERT(mic.kind == ic::MICInfo::SET); JS_LOCK_OBJ(f.cx, obj); JSScope *scope = obj->scope(); JSScopeProperty *sprop = scope->lookup(id); if (!sprop || !sprop->hasDefaultGetterOrIsMethod() || !sprop->writable() || !SPROP_HAS_VALID_SLOT(sprop, scope)) { JS_UNLOCK_SCOPE(f.cx, scope); if (sprop) PatchSetFallback(f, mic); - stubs::SetGlobalName(f, atom); + stub(f, atom); return; } uint32 shape = obj->shape(); uint32 slot = sprop->slot; JS_UNLOCK_SCOPE(f.cx, scope); mic.u.name.touched = true; @@ -183,18 +189,18 @@ ic::SetGlobalName(VMFrame &f, uint32 ind #elif defined JS_CPU_ARM // mic.load actually points to the LDR instruction which fetches the offset, but 'repatch' // knows how to dereference it to find the integer value. stores.repatch(mic.load.dataLabel32AtOffset(0), slot); #elif defined JS_PUNBOX64 stores.repatch(mic.load.dataLabel32AtOffset(mic.patchValueOffset), slot); #endif - /* Do load anyway... this time. */ - stubs::SetGlobalName(f, atom); + // Actually implement the op the slow way. + stub(f, atom); } #ifdef JS_CPU_X86 ic::NativeCallCompiler::NativeCallCompiler() : jumps(SystemAllocPolicy()) {}
--- a/js/src/methodjit/StubCalls.cpp +++ b/js/src/methodjit/StubCalls.cpp @@ -303,16 +303,33 @@ stubs::SetName(VMFrame &f, JSAtom *origA THROW(); } } while (0); f.regs.sp[-2] = f.regs.sp[-1]; } void JS_FASTCALL +stubs::SetGlobalNameDumb(VMFrame &f, JSAtom *atom) +{ + JSContext *cx = f.cx; + + Value rval = f.regs.sp[-1]; + Value &lref = f.regs.sp[-2]; + JSObject *obj = ValueToObject(cx, &lref); + if (!obj) + THROW(); + jsid id = ATOM_TO_JSID(atom); + if (!obj->setProperty(cx, id, &rval)) + THROW(); + + f.regs.sp[-2] = f.regs.sp[-1]; +} + +void JS_FASTCALL stubs::SetGlobalName(VMFrame &f, JSAtom *atom) { SetName(f, atom); } static JSObject * NameOp(VMFrame &f, JSObject *obj, bool callname = false) {
--- a/js/src/methodjit/StubCalls.h +++ b/js/src/methodjit/StubCalls.h @@ -77,16 +77,17 @@ void * JS_FASTCALL InvokeTracer(VMFrame #else void * JS_FASTCALL InvokeTracer(VMFrame &f); #endif void JS_FASTCALL BindName(VMFrame &f); JSObject * JS_FASTCALL BindGlobalName(VMFrame &f); void JS_FASTCALL SetName(VMFrame &f, JSAtom *atom); void JS_FASTCALL SetGlobalName(VMFrame &f, JSAtom *atom); +void JS_FASTCALL SetGlobalNameDumb(VMFrame &f, JSAtom *atom); void JS_FASTCALL Name(VMFrame &f); void JS_FASTCALL GetProp(VMFrame &f); void JS_FASTCALL GetElem(VMFrame &f); void JS_FASTCALL CallElem(VMFrame &f); void JS_FASTCALL SetElem(VMFrame &f); void JS_FASTCALL Length(VMFrame &f); void JS_FASTCALL CallName(VMFrame &f); void JS_FASTCALL GetUpvar(VMFrame &f, uint32 index);