author | Brian Hackett <bhackett1024@gmail.com> |
Mon, 03 Oct 2011 14:43:09 -0700 | |
changeset 78031 | 28a549e9041047f280aaeff17139021c2711294a |
parent 78030 | ae1ba25d7d07e1df9c75f9c4d2b72eff4bc7722c |
child 78032 | c6405a1d4b2271705bf1f74a73cf4d1808afe108 |
push id | 2350 |
push user | bhackett@mozilla.com |
push date | Mon, 03 Oct 2011 21:43:30 +0000 |
treeherder | mozilla-inbound@28a549e90410 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | dvander |
bugs | 689892 |
milestone | 10.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
|
--- a/js/src/jsanalyze.h +++ b/js/src/jsanalyze.h @@ -1090,16 +1090,19 @@ class ScriptAnalysis types::TypeSet *poppedTypes(uint32 offset, uint32 which) { return getValueTypes(poppedValue(offset, which)); } types::TypeSet *poppedTypes(const jsbytecode *pc, uint32 which) { return getValueTypes(poppedValue(pc, which)); } + /* Whether an arithmetic operation is operating on integers, with an integer result. */ + bool integerOperation(JSContext *cx, jsbytecode *pc); + bool trackUseChain(const SSAValue &v) { JS_ASSERT_IF(v.kind() == SSAValue::VAR, trackSlot(v.varSlot())); return v.kind() != SSAValue::EMPTY && (v.kind() != SSAValue::VAR || !v.varInitial()); } /* * Get the use chain for an SSA value. May be invalid for some opcodes in
--- a/js/src/jsinfer.cpp +++ b/js/src/jsinfer.cpp @@ -4268,16 +4268,59 @@ ScriptAnalysis::followEscapingArguments( } if (op == JSOP_GETLOCAL) return followEscapingArguments(cx, SSAValue::PushedValue(use->offset, 0), seen); return false; } +bool +ScriptAnalysis::integerOperation(JSContext *cx, jsbytecode *pc) +{ + uint32 offset = pc - script->code; + JS_ASSERT(offset < script->length); + + switch (JSOp(*pc)) { + + case JSOP_INCARG: + case JSOP_DECARG: + case JSOP_ARGINC: + case JSOP_ARGDEC: + case JSOP_INCLOCAL: + case JSOP_DECLOCAL: + case JSOP_LOCALINC: + case JSOP_LOCALDEC: { + if (pushedTypes(pc, 0)->getKnownTypeTag(cx) != JSVAL_TYPE_INT32) + return false; + uint32 slot = GetBytecodeSlot(script, pc); + if (trackSlot(slot)) { + if (poppedTypes(pc, 0)->getKnownTypeTag(cx) != JSVAL_TYPE_INT32) + return false; + } + return true; + } + + case JSOP_ADD: + case JSOP_SUB: + case JSOP_MUL: + case JSOP_DIV: + if (pushedTypes(pc, 0)->getKnownTypeTag(cx) != JSVAL_TYPE_INT32) + return false; + if (poppedTypes(pc, 0)->getKnownTypeTag(cx) != JSVAL_TYPE_INT32) + return false; + if (poppedTypes(pc, 1)->getKnownTypeTag(cx) != JSVAL_TYPE_INT32) + return false; + return true; + + default: + return true; + } +} + /* * Persistent constraint clearing out newScript and definite properties from * an object should a property on another object get a setter. */ class TypeConstraintClearDefiniteSetter : public TypeConstraint { public: TypeObject *object;
--- a/js/src/methodjit/LoopState.cpp +++ b/js/src/methodjit/LoopState.cpp @@ -984,16 +984,19 @@ LoopState::cannotIntegerOverflow(const C * Compute a slot and constant such that the result of the binary op is * 'slot + constant', where slot is expressed in terms of its value at * the head of the loop. */ JS_ASSERT(pushed.v.kind() == SSAValue::PUSHED); jsbytecode *PC = ssa->getFrame(pushed.frame).script->code + pushed.v.pushedOffset(); ScriptAnalysis *analysis = ssa->getFrame(pushed.frame).script->analysis(); + if (!analysis->integerOperation(cx, PC)) + return false; + uint32 baseSlot = UNASSIGNED; int32 baseConstant = 0; JSOp op = JSOp(*PC); switch (op) { case JSOP_INCLOCAL: case JSOP_LOCALINC: case JSOP_INCARG: @@ -1526,16 +1529,18 @@ LoopState::getLoopTestAccess(const SSAVa case JSOP_INCLOCAL: case JSOP_DECLOCAL: case JSOP_LOCALINC: case JSOP_LOCALDEC: case JSOP_INCARG: case JSOP_DECARG: case JSOP_ARGINC: case JSOP_ARGDEC: { + if (!outerAnalysis->integerOperation(cx, pc)) + return false; uint32 slot = GetBytecodeSlot(outerScript, pc); if (outerAnalysis->slotEscapes(slot)) return false; *pslot = slot; if (cs->format & JOF_POST) { if (cs->format & JOF_INC) *pconstant = -1; @@ -1663,21 +1668,21 @@ LoopState::analyzeLoopIncrements() for (uint32 slot = ArgSlot(0); slot < LocalSlot(outerScript, outerScript->nfixed); slot++) { if (outerAnalysis->slotEscapes(slot)) continue; uint32 offset = outerAnalysis->liveness(slot).onlyWrite(lifetime); if (offset == uint32(-1) || offset < lifetime->lastBlock) continue; - JSOp op = JSOp(outerScript->code[offset]); + jsbytecode *pc = outerScript->code + offset; + JSOp op = JSOp(*pc); const JSCodeSpec *cs = &js_CodeSpec[op]; if (cs->format & (JOF_INC | JOF_DEC)) { - TypeSet *types = outerAnalysis->pushedTypes(offset); - if (types->getKnownTypeTag(cx) != JSVAL_TYPE_INT32) + if (!outerAnalysis->integerOperation(cx, pc)) continue; Increment inc; inc.slot = slot; inc.offset = offset; increments.append(inc); } } @@ -2132,17 +2137,17 @@ LoopState::getEntryValue(const CrossSSAV switch (op) { case JSOP_GETLOCAL: case JSOP_LOCALINC: case JSOP_INCLOCAL: case JSOP_GETARG: case JSOP_ARGINC: case JSOP_INCARG: { - if (cv.frame != CrossScriptSSA::OUTER_FRAME) + if (cv.frame != CrossScriptSSA::OUTER_FRAME || !analysis->integerOperation(cx, pc)) return false; uint32 slot = GetBytecodeSlot(outerScript, pc); if (outerAnalysis->slotEscapes(slot)) return false; uint32 write = outerAnalysis->liveness(slot).firstWrite(lifetime); if (write != uint32(-1) && write < v.pushedOffset()) { /* Variable has been modified since the start of the loop. */ return false;