Fix for(;;) loops to use one branch per iter (after initial iter; 441477, r=jorendorff).

This commit is contained in:
Brendan Eich
2008-06-26 17:49:01 -07:00
parent 6302680e08
commit eba68c02ab
3 changed files with 105 additions and 65 deletions

View File

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