Bug 582766 - JIT vastly slows down Data Manager (let in .nextSibling loop makes TM loop way too often). r=dvander.
authorNicholas Nethercote <nnethercote@mozilla.com>
Sun, 01 Aug 2010 18:03:12 -0700
changeset 48798 06d0143b4f7e94c4e7f2f79e9e2ed5a9402e49ef
parent 48680 1c7d7b849b21d383a38979becff23d764c99f8dc
child 48799 fd1faf906f0067bbb687189594489a1d62d0366a
push id14825
push userrsayre@mozilla.com
push dateWed, 04 Aug 2010 07:47:43 +0000
treeherdermozilla-central@c761f8e85b8c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdvander
bugs582766
milestone2.0b3pre
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 582766 - JIT vastly slows down Data Manager (let in .nextSibling loop makes TM loop way too often). r=dvander.
js/src/jstracer.cpp
js/src/trace-test/tests/basic/testBug582766.js
--- a/js/src/jstracer.cpp
+++ b/js/src/jstracer.cpp
@@ -4934,27 +4934,33 @@ TraceRecorder::closeLoop(SlotMap& slotMa
             debug_only_printf(LC_TMTracer,
                               "Joining type-unstable trace to target fragment %p.\n",
                               (void*)peer);
             peer->dependentTrees.addUnique(tree);
             tree->linkedTrees.addUnique(peer);
         }
     } 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());
 
     debug_only_printf(LC_TMTreeVis, "TREEVIS CLOSELOOP EXIT=%p PEER=%p\n", (void*)exit, (void*)peer);
 
     JS_ASSERT(LookupLoop(traceMonitor, tree->ip, tree->globalObj, tree->globalShape, tree->argc) ==
               tree->first);
new file mode 100644
--- /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);