diff --git a/js/src/methodjit/Compiler.cpp b/js/src/methodjit/Compiler.cpp index 389f8a7a776..fcc453c8232 100644 --- a/js/src/methodjit/Compiler.cpp +++ b/js/src/methodjit/Compiler.cpp @@ -797,9 +797,6 @@ mjit::Compiler::generatePrologue() recompileCheckHelper(); - /* Update the initial types of arguments and locals with a use-before-def. */ - restoreAnalysisTypes(); - return Compile_Okay; } @@ -1489,7 +1486,7 @@ mjit::Compiler::generateMethod() if (!frame.discardForJoin(analysis->getAllocation(PC), opinfo->stackDepth)) return Compile_Error; - restoreAnalysisTypes(); + updateJoinVarTypes(); fallthrough = true; if (!cx->typeInferenceEnabled()) { @@ -2217,6 +2214,7 @@ mjit::Compiler::generateMethod() BEGIN_CASE(JSOP_GETARG) { + restoreVarType(); uint32 arg = GET_SLOTNO(PC); frame.pushArg(arg); } @@ -2224,6 +2222,7 @@ mjit::Compiler::generateMethod() BEGIN_CASE(JSOP_CALLARG) { + restoreVarType(); uint32 arg = GET_SLOTNO(PC); if (JSObject *singleton = pushedSingleton(0)) frame.push(ObjectValue(*singleton)); @@ -2239,7 +2238,7 @@ mjit::Compiler::generateMethod() BEGIN_CASE(JSOP_SETARG) { - jsbytecode *next = &PC[JSOP_SETLOCAL_LENGTH]; + jsbytecode *next = &PC[JSOP_SETARG_LENGTH]; bool pop = JSOp(*next) == JSOP_POP && !analysis->jumpTarget(next); frame.storeArg(GET_SLOTNO(PC), pop); updateVarType(); @@ -2254,6 +2253,13 @@ mjit::Compiler::generateMethod() BEGIN_CASE(JSOP_GETLOCAL) { + /* + * Update the var type unless we are about to pop the variable. + * Sync is not guaranteed for types of dead locals, and GETLOCAL + * followed by POP is not regarded as a use of the variable. + */ + if (PC[JSOP_GETLOCAL_LENGTH] != JSOP_POP) + restoreVarType(); uint32 slot = GET_SLOTNO(PC); frame.pushLocal(slot); } @@ -2360,7 +2366,7 @@ mjit::Compiler::generateMethod() BEGIN_CASE(JSOP_SETPROP) { - jsbytecode *next = &PC[JSOP_SETLOCAL_LENGTH]; + jsbytecode *next = &PC[JSOP_SETPROP_LENGTH]; bool pop = JSOp(*next) == JSOP_POP && !analysis->jumpTarget(next); if (!jsop_setprop(script->getAtom(fullAtomIndex(PC)), true, pop)) return Compile_Error; @@ -2370,7 +2376,7 @@ mjit::Compiler::generateMethod() BEGIN_CASE(JSOP_SETNAME) BEGIN_CASE(JSOP_SETMETHOD) { - jsbytecode *next = &PC[JSOP_SETLOCAL_LENGTH]; + jsbytecode *next = &PC[JSOP_SETNAME_LENGTH]; bool pop = JSOp(*next) == JSOP_POP && !analysis->jumpTarget(next); if (!jsop_setprop(script->getAtom(fullAtomIndex(PC)), true, pop)) return Compile_Error; @@ -2613,7 +2619,7 @@ mjit::Compiler::generateMethod() BEGIN_CASE(JSOP_SETGNAME) { - jsbytecode *next = &PC[JSOP_SETLOCAL_LENGTH]; + jsbytecode *next = &PC[JSOP_SETGNAME_LENGTH]; bool pop = JSOp(*next) == JSOP_POP && !analysis->jumpTarget(next); jsop_setgname(script->getAtom(fullAtomIndex(PC)), true, pop); } @@ -2672,6 +2678,7 @@ mjit::Compiler::generateMethod() BEGIN_CASE(JSOP_CALLLOCAL) { + restoreVarType(); uint32 slot = GET_SLOTNO(PC); if (JSObject *singleton = pushedSingleton(0)) frame.push(ObjectValue(*singleton)); @@ -6804,42 +6811,6 @@ mjit::Compiler::fixDoubleTypes(jsbytecode *target) } } -void -mjit::Compiler::restoreAnalysisTypes() -{ - if (!cx->typeInferenceEnabled()) - return; - - /* Update variable types for all new values at this bytecode. */ - const SlotValue *newv = analysis->newValues(PC); - if (newv) { - while (newv->slot) { - if (newv->slot < TotalSlots(script)) { - VarType &vt = a->varTypes[newv->slot]; - vt.types = analysis->getValueTypes(newv->value); - vt.type = vt.types->getKnownTypeTag(cx); - } - newv++; - } - } - - /* - * Restore known types of locals/args. Skip this for dead entries: the type - * may not be synced, and the slot will not be used anyways. - */ - for (uint32 slot = ArgSlot(0); slot < TotalSlots(script); slot++) { - JSValueType type = a->varTypes[slot].type; - if (type != JSVAL_TYPE_UNKNOWN && - (type != JSVAL_TYPE_DOUBLE || analysis->trackSlot(slot)) && - (!analysis->trackSlot(slot) || analysis->liveness(slot).live(PC - script->code))) { - FrameEntry *fe = frame.getSlotEntry(slot); - JS_ASSERT_IF(fe->isTypeKnown(), fe->isType(type)); - if (!fe->isTypeKnown()) - frame.learnType(fe, type, false); - } - } -} - void mjit::Compiler::watchGlobalReallocation() { @@ -6905,6 +6876,49 @@ mjit::Compiler::updateVarType() } } +void +mjit::Compiler::updateJoinVarTypes() +{ + if (!cx->typeInferenceEnabled()) + return; + + /* Update variable types for all new values at this bytecode. */ + const SlotValue *newv = analysis->newValues(PC); + if (newv) { + while (newv->slot) { + if (newv->slot < TotalSlots(script)) { + VarType &vt = a->varTypes[newv->slot]; + vt.types = analysis->getValueTypes(newv->value); + vt.type = vt.types->getKnownTypeTag(cx); + } + newv++; + } + } +} + +void +mjit::Compiler::restoreVarType() +{ + uint32 slot = GetBytecodeSlot(script, PC); + + if (slot >= analyze::TotalSlots(script)) + return; + + /* + * Restore the known type of a live local or argument. We ensure that types + * of tracked variables match their inferred type (as tracked in varTypes), + * but may have forgotten it due to a branch or syncAndForgetEverything. + */ + JSValueType type = a->varTypes[slot].type; + if (type != JSVAL_TYPE_UNKNOWN && + (type != JSVAL_TYPE_DOUBLE || analysis->trackSlot(slot))) { + FrameEntry *fe = frame.getSlotEntry(slot); + JS_ASSERT_IF(fe->isTypeKnown(), fe->isType(type)); + if (!fe->isTypeKnown()) + frame.learnType(fe, type, false); + } +} + JSValueType mjit::Compiler::knownPushedType(uint32 pushed) { diff --git a/js/src/methodjit/Compiler.h b/js/src/methodjit/Compiler.h index 3222d0b6ad7..936778b935b 100644 --- a/js/src/methodjit/Compiler.h +++ b/js/src/methodjit/Compiler.h @@ -535,9 +535,10 @@ class Compiler : public BaseCompiler CompileStatus prepareInferenceTypes(JSScript *script, ActiveFrame *a); void ensureDoubleArguments(); void fixDoubleTypes(jsbytecode *target); - void restoreAnalysisTypes(); void watchGlobalReallocation(); void updateVarType(); + void updateJoinVarTypes(); + void restoreVarType(); JSValueType knownPushedType(uint32 pushed); bool mayPushUndefined(uint32 pushed); types::TypeSet *pushedTypeSet(uint32 which); diff --git a/js/src/methodjit/FastOps.cpp b/js/src/methodjit/FastOps.cpp index d89fd9af94f..5250d7eff02 100644 --- a/js/src/methodjit/FastOps.cpp +++ b/js/src/methodjit/FastOps.cpp @@ -912,6 +912,8 @@ mjit::Compiler::jsop_andor(JSOp op, jsbytecode *target) bool mjit::Compiler::jsop_localinc(JSOp op, uint32 slot) { + restoreVarType(); + types::TypeSet *types = pushedTypeSet(0); JSValueType type = types ? types->getKnownTypeTag(cx) : JSVAL_TYPE_UNKNOWN; @@ -973,6 +975,8 @@ mjit::Compiler::jsop_localinc(JSOp op, uint32 slot) bool mjit::Compiler::jsop_arginc(JSOp op, uint32 slot) { + restoreVarType(); + types::TypeSet *types = pushedTypeSet(0); JSValueType type = types ? types->getKnownTypeTag(cx) : JSVAL_TYPE_UNKNOWN; diff --git a/js/src/methodjit/FrameState-inl.h b/js/src/methodjit/FrameState-inl.h index 8c026d58840..50e34745293 100644 --- a/js/src/methodjit/FrameState-inl.h +++ b/js/src/methodjit/FrameState-inl.h @@ -918,6 +918,9 @@ FrameState::learnType(FrameEntry *fe, JSValueType type, bool unsync) JS_ASSERT(!fe->isType(JSVAL_TYPE_DOUBLE)); JS_ASSERT(type != JSVAL_TYPE_UNKNOWN); + if (fe->isCopy()) + fe = fe->copyOf(); + if (type == JSVAL_TYPE_DOUBLE) JS_ASSERT(!fe->data.inRegister()); else diff --git a/js/src/methodjit/MethodJIT.cpp b/js/src/methodjit/MethodJIT.cpp index e979856a1d5..f1ad1bef575 100644 --- a/js/src/methodjit/MethodJIT.cpp +++ b/js/src/methodjit/MethodJIT.cpp @@ -873,6 +873,8 @@ mjit::EnterMethodJIT(JSContext *cx, StackFrame *fp, void *code, Value *stackLimi JS_ASSERT(cx->fp() == fp); FrameRegs &oldRegs = cx->regs(); + fp->scopeChain(); + JSBool ok; { AssertCompartmentUnchanged pcc(cx);