diff --git a/js/src/jstracer.cpp b/js/src/jstracer.cpp index a2b0b6392458..9a30a39b88e9 100644 --- a/js/src/jstracer.cpp +++ b/js/src/jstracer.cpp @@ -4939,17 +4939,23 @@ TraceRecorder::closeLoop(SlotMap& slotMap, VMSideExit* exit) } } else { exit->exitType = LOOP_EXIT; - exit->target = tree; debug_only_printf(LC_TMTreeVis, "TREEVIS CHANGEEXIT EXIT=%p TYPE=%s\n", (void*)exit, getExitName(LOOP_EXIT)); JS_ASSERT((fragment == fragment->root) == !!loopLabel); if (loopLabel) { lir->insBranch(LIR_j, NULL, loopLabel); - fragment->lastIns = lir->ins1(LIR_livep, lirbuf->state); - } else { - fragment->lastIns = lir->insGuard(LIR_x, NULL, createGuardRecord(exit)); + lir->ins1(LIR_livep, lirbuf->state); } + + exit->target = tree; + /* + * This guard is dead code. However, it must be present because it + * can keep alive values on the stack. Without it, StackFilter can + * remove some stack stores that it shouldn't. See bug 582766 comment + * 19. + */ + fragment->lastIns = lir->insGuard(LIR_x, NULL, createGuardRecord(exit)); } CHECK_STATUS_A(compile()); diff --git a/js/src/trace-test/tests/basic/testBug582766.js b/js/src/trace-test/tests/basic/testBug582766.js new file mode 100644 index 000000000000..cfcafbed08c7 --- /dev/null +++ b/js/src/trace-test/tests/basic/testBug582766.js @@ -0,0 +1,18 @@ +expected = 4; + +var fourth = { nextSibling: null }; +var third = { nextSibling: fourth }; +var second = { nextSibling: third }; +var first = { nextSibling: second }; + +function f() { + let loopcount = 0; + for (let node = first; node; node = node.nextSibling) { + loopcount++; + } + return loopcount; +} + +actual = f(); + +assertEq(actual, expected);