Bug 570663: turn a tableswitch on trace into a no-op if it has no cases, r=njn
authorDavid Mandelin <dmandelin@mozilla.com>
Mon, 16 Aug 2010 18:56:04 -0700
changeset 50709 f9ec16f321166293fff565502218e51954b03d45
parent 50708 3a8430b73a91dfbd95ced9877729cbc8901589b6
child 50711 6b6187bfe4fece3d87a49093a366366fefb59dd1
push idunknown
push userunknown
push dateunknown
reviewersnjn
bugs570663
milestone2.0b4pre
Bug 570663: turn a tableswitch on trace into a no-op if it has no cases, r=njn
js/src/jstracer.cpp
js/src/trace-test/tests/basic/bug570663-1.js
js/src/trace-test/tests/basic/bug570663-2.js
--- a/js/src/jstracer.cpp
+++ b/js/src/jstracer.cpp
@@ -8728,23 +8728,32 @@ TraceRecorder::tableswitch()
         high = GET_JUMP_OFFSET(pc);
     } else {
         pc += JUMPX_OFFSET_LEN;
         low = GET_JUMPX_OFFSET(pc);
         pc += JUMPX_OFFSET_LEN;
         high = GET_JUMPX_OFFSET(pc);
     }
 
+    /* 
+     * If there are no cases, this is a no-op. The default case immediately
+     * follows in the bytecode and is always taken, so we need no special
+     * action to handle it.
+     */
+    int count = high + 1 - low;
+    if (count == 0)
+        return ARECORD_CONTINUE;
+
     /* Cap maximum table-switch size for modesty. */
-    if ((high + 1 - low) > MAX_TABLE_SWITCH)
+    if (count > MAX_TABLE_SWITCH)
         return InjectStatus(switchop());
 
     /* Generate switch LIR. */
     SwitchInfo* si = new (traceAlloc()) SwitchInfo();
-    si->count = high + 1 - low;
+    si->count = count;
     si->table = 0;
     si->index = (uint32) -1;
     LIns* diff = lir->ins2(LIR_subi, v_ins, lir->insImmI(low));
     LIns* cmp = lir->ins2(LIR_ltui, diff, lir->insImmI(si->count));
     lir->insGuard(LIR_xf, cmp, createGuardRecord(snapshot(DEFAULT_EXIT)));
     lir->insStore(diff, lir->insImmP(&si->index), 0, ACCSET_OTHER);
     VMSideExit* exit = snapshot(CASE_EXIT);
     exit->switchInfo = si;
new file mode 100644
--- /dev/null
+++ b/js/src/trace-test/tests/basic/bug570663-1.js
@@ -0,0 +1,4 @@
+// don't crash
+for (var a = 0; a < 4; a++) {
+  switch (NaN) {}
+}
new file mode 100644
--- /dev/null
+++ b/js/src/trace-test/tests/basic/bug570663-2.js
@@ -0,0 +1,12 @@
+function f() {
+    var x;
+    for (var a = 0; a < 4; a++) {
+	switch (NaN) {
+	default:
+	    x = a;
+	}
+    }
+    assertEq(x, 3);
+}
+
+f();