Fix for(;;) loops to use one branch per iter (after initial iter; 441477, r=jorendorff).
This commit is contained in:
@@ -1985,31 +1985,42 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop)
|
||||
cond = js_GetSrcNoteOffset(sn, 0);
|
||||
next = js_GetSrcNoteOffset(sn, 1);
|
||||
tail = js_GetSrcNoteOffset(sn, 2);
|
||||
LOCAL_ASSERT(tail + GetJumpOffset(pc+tail, pc+tail) == 0);
|
||||
|
||||
/*
|
||||
* If this loop has a condition, then pc points at a goto
|
||||
* targeting the condition.
|
||||
*/
|
||||
if (cond != tail) {
|
||||
LOCAL_ASSERT(*pc == JSOP_GOTO || *pc == JSOP_GOTOX);
|
||||
pc += (*pc == JSOP_GOTO)
|
||||
? JSOP_GOTO_LENGTH
|
||||
: JSOP_GOTOX_LENGTH;
|
||||
}
|
||||
LOCAL_ASSERT(tail == -GetJumpOffset(pc+tail, pc+tail));
|
||||
|
||||
/* Print the keyword and the possibly empty init-part. */
|
||||
js_printf(jp, "\tfor (%s;", rval);
|
||||
|
||||
if (pc[cond] == JSOP_IFEQ || pc[cond] == JSOP_IFEQX) {
|
||||
if (cond != tail) {
|
||||
/* Decompile the loop condition. */
|
||||
DECOMPILE_CODE(pc, cond);
|
||||
DECOMPILE_CODE(pc + cond, tail - cond);
|
||||
js_printf(jp, " %s", POP_STR());
|
||||
}
|
||||
|
||||
/* Need a semicolon whether or not there was a cond. */
|
||||
js_puts(jp, ";");
|
||||
|
||||
if (pc[next] != JSOP_GOTO && pc[next] != JSOP_GOTOX) {
|
||||
if (next != cond) {
|
||||
/* Decompile the loop updater. */
|
||||
DECOMPILE_CODE(pc + next, tail - next - 1);
|
||||
DECOMPILE_CODE(pc + next,
|
||||
cond - next - JSOP_POP_LENGTH);
|
||||
js_printf(jp, " %s", POP_STR());
|
||||
}
|
||||
|
||||
/* Do the loop body. */
|
||||
js_printf(jp, ") {\n");
|
||||
jp->indent += 4;
|
||||
oplen = (cond) ? js_CodeSpec[pc[cond]].length : 0;
|
||||
DECOMPILE_CODE(pc + cond + oplen, next - cond - oplen);
|
||||
DECOMPILE_CODE(pc, next);
|
||||
jp->indent -= 4;
|
||||
js_printf(jp, "\t}\n");
|
||||
|
||||
@@ -3834,32 +3845,37 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop)
|
||||
* 1. It is the complete expression consumed by a control
|
||||
* flow bytecode such as JSOP_TABLESWITCH whose syntax
|
||||
* always parenthesizes the controlling expression.
|
||||
* 2. It is the sole argument to a function call.
|
||||
* 3. It is the condition of an if statement and not of a
|
||||
* 2. It is the condition of a loop other than a for (;;).
|
||||
* 3. It is the sole argument to a function call.
|
||||
* 4. It is the condition of an if statement and not of a
|
||||
* ?: expression.
|
||||
*
|
||||
* But (first, before anything else) always parenthesize
|
||||
* if this genexp runs up against endpc and the next op is
|
||||
* not a while or do-while loop JSOP_IFNE* opcode. In such
|
||||
* cases, this Decompile activation has been recursively
|
||||
* called by a comma operator, &&, or || bytecode.
|
||||
* not a loop condition (JSOP_IFNE*) opcode. In such cases,
|
||||
* this Decompile activation has been recursively called by
|
||||
* a comma operator, &&, or || bytecode.
|
||||
*/
|
||||
LOCAL_ASSERT(pc + len < endpc ||
|
||||
pc2 = pc + len;
|
||||
LOCAL_ASSERT(pc2 < endpc ||
|
||||
endpc < outer->code + outer->length);
|
||||
LOCAL_ASSERT(ss2.top == 1);
|
||||
ss2.opcodes[0] = JSOP_POP;
|
||||
if (pc + len == endpc &&
|
||||
((JSOp) *endpc != JSOP_IFNE &&
|
||||
(JSOp) *endpc != JSOP_IFNEX)) {
|
||||
if (pc2 == endpc &&
|
||||
(JSOp) *endpc != JSOP_IFNE &&
|
||||
(JSOp) *endpc != JSOP_IFNEX) {
|
||||
op = JSOP_SETNAME;
|
||||
} else {
|
||||
op = (JSOp) pc[len];
|
||||
op = (JSOp) *pc2;
|
||||
op = ((js_CodeSpec[op].format & JOF_PARENHEAD) ||
|
||||
((op == JSOP_IFNE || op == JSOP_IFNEX) &&
|
||||
(!(sn2 = js_GetSrcNote(outer, pc2)) ||
|
||||
SN_TYPE(sn2) != SRC_GENEXP)) ||
|
||||
((js_CodeSpec[op].format & JOF_INVOKE) &&
|
||||
GET_ARGC(pc + len) == 1) ||
|
||||
(((op == JSOP_IFEQ || op == JSOP_IFEQX) &&
|
||||
(sn2 = js_GetSrcNote(outer, pc + len)) &&
|
||||
SN_TYPE(sn2) != SRC_COND)))
|
||||
GET_ARGC(pc2) == 1) ||
|
||||
((op == JSOP_IFEQ || op == JSOP_IFEQX) &&
|
||||
(sn2 = js_GetSrcNote(outer, pc2)) &&
|
||||
SN_TYPE(sn2) != SRC_COND))
|
||||
? JSOP_POP
|
||||
: JSOP_SETNAME;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user