Add JSOP_LOOPENTRY for target of initial loop jump, bug 720169. r=dvander

This commit is contained in:
Brian Hackett 2012-01-23 13:51:01 -08:00
Родитель 7be6565932
Коммит 36e14bbce6
9 изменённых файлов: 48 добавлений и 8 удалений

Просмотреть файл

@ -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: