зеркало из https://github.com/mozilla/gecko-dev.git
Add JSOP_LOOPENTRY for target of initial loop jump, bug 720169. r=dvander
This commit is contained in:
Родитель
7be6565932
Коммит
36e14bbce6
|
@ -539,7 +539,7 @@ UpdateLineNumberNotes(JSContext *cx, BytecodeEmitter *bce, uintN line)
|
|||
}
|
||||
|
||||
static ptrdiff_t
|
||||
EmitTraceOp(JSContext *cx, BytecodeEmitter *bce, ParseNode *nextpn)
|
||||
EmitLoopHead(JSContext *cx, BytecodeEmitter *bce, ParseNode *nextpn)
|
||||
{
|
||||
if (nextpn) {
|
||||
/*
|
||||
|
@ -557,6 +557,21 @@ EmitTraceOp(JSContext *cx, BytecodeEmitter *bce, ParseNode *nextpn)
|
|||
return Emit1(cx, bce, JSOP_LOOPHEAD);
|
||||
}
|
||||
|
||||
static bool
|
||||
EmitLoopEntry(JSContext *cx, BytecodeEmitter *bce, ParseNode *nextpn)
|
||||
{
|
||||
if (nextpn) {
|
||||
/* Update the line number, as for LOOPHEAD. */
|
||||
JS_ASSERT_IF(nextpn->isKind(PNK_STATEMENTLIST), nextpn->isArity(PN_LIST));
|
||||
if (nextpn->isKind(PNK_STATEMENTLIST) && nextpn->pn_head)
|
||||
nextpn = nextpn->pn_head;
|
||||
if (!UpdateLineNumberNotes(cx, bce, nextpn->pn_pos.begin.lineno))
|
||||
return false;
|
||||
}
|
||||
|
||||
return Emit1(cx, bce, JSOP_LOOPENTRY) >= 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* If op is JOF_TYPESET (see the type barriers comment in jsinfer.h), reserve
|
||||
* a type set to store its result.
|
||||
|
@ -4831,7 +4846,7 @@ EmitForIn(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn, ptrdiff_t top)
|
|||
|
||||
top = bce->offset();
|
||||
SET_STATEMENT_TOP(&stmtInfo, top);
|
||||
if (EmitTraceOp(cx, bce, NULL) < 0)
|
||||
if (EmitLoopHead(cx, bce, NULL) < 0)
|
||||
return false;
|
||||
|
||||
#ifdef DEBUG
|
||||
|
@ -4874,6 +4889,8 @@ EmitForIn(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn, ptrdiff_t top)
|
|||
* Fixup the goto that starts the loop to jump down to JSOP_MOREITER.
|
||||
*/
|
||||
SetJumpOffsetAt(bce, jmp);
|
||||
if (!EmitLoopEntry(cx, bce, NULL))
|
||||
return false;
|
||||
if (Emit1(cx, bce, JSOP_MOREITER) < 0)
|
||||
return false;
|
||||
ptrdiff_t beq = EmitJump(cx, bce, JSOP_IFNE, top - bce->offset());
|
||||
|
@ -4978,7 +4995,9 @@ EmitNormalFor(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn, ptrdiff_t top)
|
|||
SET_STATEMENT_TOP(&stmtInfo, top);
|
||||
|
||||
/* Emit code for the loop body. */
|
||||
if (EmitTraceOp(cx, bce, forBody) < 0)
|
||||
if (EmitLoopHead(cx, bce, forBody) < 0)
|
||||
return false;
|
||||
if (jmp == -1 && !EmitLoopEntry(cx, bce, forBody))
|
||||
return false;
|
||||
if (!EmitTree(cx, bce, forBody))
|
||||
return false;
|
||||
|
@ -5026,6 +5045,8 @@ EmitNormalFor(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn, ptrdiff_t top)
|
|||
/* Fix up the goto from top to target the loop condition. */
|
||||
JS_ASSERT(jmp >= 0);
|
||||
SetJumpOffsetAt(bce, jmp);
|
||||
if (!EmitLoopEntry(cx, bce, forHead->pn_kid2))
|
||||
return false;
|
||||
|
||||
if (!EmitTree(cx, bce, forHead->pn_kid2))
|
||||
return false;
|
||||
|
@ -5191,9 +5212,11 @@ EmitDo(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
|
|||
return false;
|
||||
|
||||
/* Compile the loop body. */
|
||||
ptrdiff_t top = EmitTraceOp(cx, bce, pn->pn_left);
|
||||
ptrdiff_t top = EmitLoopHead(cx, bce, pn->pn_left);
|
||||
if (top < 0)
|
||||
return false;
|
||||
if (!EmitLoopEntry(cx, bce, NULL))
|
||||
return false;
|
||||
|
||||
StmtInfo stmtInfo;
|
||||
PushStatement(bce, &stmtInfo, STMT_DO_LOOP, top);
|
||||
|
@ -5259,7 +5282,7 @@ EmitWhile(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn, ptrdiff_t top)
|
|||
if (jmp < 0)
|
||||
return false;
|
||||
|
||||
top = EmitTraceOp(cx, bce, pn->pn_right);
|
||||
top = EmitLoopHead(cx, bce, pn->pn_right);
|
||||
if (top < 0)
|
||||
return false;
|
||||
|
||||
|
@ -5267,6 +5290,8 @@ EmitWhile(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn, ptrdiff_t top)
|
|||
return false;
|
||||
|
||||
SetJumpOffsetAt(bce, jmp);
|
||||
if (!EmitLoopEntry(cx, bce, pn->pn_left))
|
||||
return false;
|
||||
if (!EmitTree(cx, bce, pn->pn_left))
|
||||
return false;
|
||||
|
||||
|
@ -6497,12 +6522,14 @@ frontend::EmitTree(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
|
|||
ptrdiff_t jmp = EmitJump(cx, bce, JSOP_FILTER, 0);
|
||||
if (jmp < 0)
|
||||
return JS_FALSE;
|
||||
top = EmitTraceOp(cx, bce, pn->pn_right);
|
||||
top = EmitLoopHead(cx, bce, pn->pn_right);
|
||||
if (top < 0)
|
||||
return JS_FALSE;
|
||||
if (!EmitTree(cx, bce, pn->pn_right))
|
||||
return JS_FALSE;
|
||||
SetJumpOffsetAt(bce, jmp);
|
||||
if (!EmitLoopEntry(cx, bce, NULL))
|
||||
return false;
|
||||
if (EmitJump(cx, bce, JSOP_ENDFILTER, top - bce->offset()) < 0)
|
||||
return JS_FALSE;
|
||||
break;
|
||||
|
|
|
@ -815,7 +815,7 @@ ScriptAnalysis::analyzeLifetimes(JSContext *cx)
|
|||
|
||||
jsbytecode *entrypc = script->code + entry;
|
||||
|
||||
if (JSOp(*entrypc) == JSOP_GOTO)
|
||||
if (JSOp(*entrypc) == JSOP_GOTO || JSOp(*entrypc) == JSOP_FILTER)
|
||||
loop->entry = entry + GET_JUMP_OFFSET(entrypc);
|
||||
else
|
||||
loop->entry = targetOffset;
|
||||
|
@ -823,6 +823,8 @@ ScriptAnalysis::analyzeLifetimes(JSContext *cx)
|
|||
/* Do-while loop at the start of the script. */
|
||||
loop->entry = targetOffset;
|
||||
}
|
||||
JS_ASSERT(script->code[loop->entry] == JSOP_LOOPHEAD ||
|
||||
script->code[loop->entry] == JSOP_LOOPENTRY);
|
||||
} else {
|
||||
for (unsigned i = 0; i < savedCount; i++) {
|
||||
LifetimeVariable &var = *saved[i];
|
||||
|
|
|
@ -3430,6 +3430,7 @@ ScriptAnalysis::analyzeTypesBytecode(JSContext *cx, unsigned offset,
|
|||
case JSOP_POP:
|
||||
case JSOP_NOP:
|
||||
case JSOP_LOOPHEAD:
|
||||
case JSOP_LOOPENTRY:
|
||||
case JSOP_GOTO:
|
||||
case JSOP_IFEQ:
|
||||
case JSOP_IFNE:
|
||||
|
|
|
@ -1803,6 +1803,7 @@ ADD_EMPTY_CASE(JSOP_STARTXML)
|
|||
ADD_EMPTY_CASE(JSOP_STARTXMLEXPR)
|
||||
#endif
|
||||
ADD_EMPTY_CASE(JSOP_LOOPHEAD)
|
||||
ADD_EMPTY_CASE(JSOP_LOOPENTRY)
|
||||
END_EMPTY_CASES
|
||||
|
||||
BEGIN_CASE(JSOP_LABEL)
|
||||
|
|
|
@ -3921,6 +3921,8 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
|
|||
next = js_GetSrcNoteOffset(sn, 0);
|
||||
tail = js_GetSrcNoteOffset(sn, 1);
|
||||
JS_ASSERT(pc[next] == JSOP_POP);
|
||||
JS_ASSERT(pc[cond] == JSOP_LOOPENTRY);
|
||||
cond += JSOP_LOOPENTRY_LENGTH;
|
||||
JS_ASSERT(pc[cond] == JSOP_MOREITER);
|
||||
DECOMPILE_CODE(pc + oplen, next - oplen);
|
||||
lval = POP_STR();
|
||||
|
|
|
@ -572,3 +572,6 @@ OPDEF(JSOP_TOID, 225, "toid", NULL, 1, 1, 1, 0, JOF_BYTE)
|
|||
|
||||
/* Push the implicit 'this' value for calls to the associated name. */
|
||||
OPDEF(JSOP_IMPLICITTHIS, 226, "implicitthis", "", 3, 0, 1, 0, JOF_ATOM)
|
||||
|
||||
/* This opcode is the target of the entry jump for some loop. */
|
||||
OPDEF(JSOP_LOOPENTRY, 227, "loopentry", NULL, 1, 0, 0, 0, JOF_BYTE)
|
||||
|
|
|
@ -226,7 +226,7 @@ JS_XDRFindClassById(JSXDRState *xdr, uint32_t id);
|
|||
* and saved versions. If deserialization fails, the data should be
|
||||
* invalidated if possible.
|
||||
*/
|
||||
#define JSXDR_BYTECODE_VERSION (0xb973c0de - 103)
|
||||
#define JSXDR_BYTECODE_VERSION (0xb973c0de - 104)
|
||||
|
||||
/*
|
||||
* Library-private functions.
|
||||
|
|
|
@ -3226,6 +3226,9 @@ mjit::Compiler::generateMethod()
|
|||
}
|
||||
END_CASE(JSOP_LOOPHEAD)
|
||||
|
||||
BEGIN_CASE(JSOP_LOOPENTRY)
|
||||
END_CASE(JSOP_LOOPENTRY)
|
||||
|
||||
BEGIN_CASE(JSOP_DEBUGGER)
|
||||
{
|
||||
prepareStubCall(Uses(0));
|
||||
|
|
|
@ -1897,6 +1897,7 @@ LoopState::analyzeLoopBody(unsigned frame)
|
|||
break;
|
||||
|
||||
case JSOP_LOOPHEAD:
|
||||
case JSOP_LOOPENTRY:
|
||||
case JSOP_POP:
|
||||
case JSOP_ZERO:
|
||||
case JSOP_ONE:
|
||||
|
|
Загрузка…
Ссылка в новой задаче