Don't emit constant guards for switch and ifop (455605, r=danderson).
authorAndreas Gal <gal@mozilla.com>
Mon, 22 Sep 2008 17:58:25 -0700
changeset 19604 385c9e591c97d92a8923a2bc4de7ae3a92f974ab
parent 19603 b50bfddb2f330a597e1ff519246b483ccf9a289f
child 19605 b222647a14cb9bb942b62c714511a324a7701ec9
push idunknown
push userunknown
push dateunknown
reviewersdanderson
bugs455605
milestone1.9.1b1pre
Don't emit constant guards for switch and ifop (455605, r=danderson).
js/src/jstracer.cpp
js/src/trace-test.js
--- a/js/src/jstracer.cpp
+++ b/js/src/jstracer.cpp
@@ -2966,72 +2966,72 @@ LIns* TraceRecorder::f2i(LIns* f)
 {
     return lir->insCall(F_DoubleToInt32, &f);
 }
 
 bool
 TraceRecorder::ifop()
 {
     jsval& v = stackval(-1);
+    LIns* v_ins = get(&v);
+    /* no need to guard if condition is constant */
+    if (v_ins->isconst() || v_ins->isconstq())
+        return true;
     if (JSVAL_TAG(v) == JSVAL_BOOLEAN) {
         guard(JSVAL_TO_BOOLEAN(v) != 1,
-              lir->ins_eq0(lir->ins2i(LIR_eq, get(&v), 1)),
+              lir->ins_eq0(lir->ins2i(LIR_eq, v_ins, 1)),
               BRANCH_EXIT);
     } else if (JSVAL_IS_OBJECT(v)) {
-        guard(JSVAL_IS_NULL(v), lir->ins_eq0(get(&v)), BRANCH_EXIT);
+        guard(JSVAL_IS_NULL(v), lir->ins_eq0(v_ins), BRANCH_EXIT);
     } else if (isNumber(v)) {
         jsdouble d = asNumber(v);
         jsdpun u;
         u.d = 0;
-        LIns* v_ins = get(&v);
-
-        // Only insert the guard if the condition is not constant, since in 
-        // that case at runtime we would always take the same path as the
-        // interpreter is taking right now and hence there is no need for
-        // a guard.        
-        if (!v_ins->isconst() && !v_ins->isconstq()) {
-            guard(d == 0 || JSDOUBLE_IS_NaN(d),
-                  lir->ins2(LIR_feq, v_ins, lir->insImmq(u.u64)),
-                  BRANCH_EXIT);
-        }
+        guard(d == 0 || JSDOUBLE_IS_NaN(d),
+              lir->ins2(LIR_feq, v_ins, lir->insImmq(u.u64)),
+              BRANCH_EXIT);
     } else if (JSVAL_IS_STRING(v)) {
         guard(JSSTRING_LENGTH(JSVAL_TO_STRING(v)) == 0,
               lir->ins_eq0(lir->ins2(LIR_piand,
                                      lir->insLoad(LIR_ldp, 
-                                                  get(&v), 
+                                                  v_ins, 
                                                   (int)offsetof(JSString, length)),
                                      INS_CONSTPTR(JSSTRING_LENGTH_MASK))),
               BRANCH_EXIT);
     } else {
         JS_NOT_REACHED("ifop");
     }
     return true;
 }
 
 bool
 TraceRecorder::switchop()
 {
     jsval& v = stackval(-1);
+    LIns* v_ins = get(&v);
+    /* no need to guard if condition is constant */
+    if (v_ins->isconst() || v_ins->isconstq())
+        return true;
     if (isNumber(v)) {
         jsdouble d = asNumber(v);
         jsdpun u;
         u.d = d;
         guard(true,
-              addName(lir->ins2(LIR_feq, get(&v), lir->insImmq(u.u64)),
+              addName(lir->ins2(LIR_feq, v_ins, lir->insImmq(u.u64)),
                       "guard(switch on numeric)"),
               BRANCH_EXIT);
     } else if (JSVAL_IS_STRING(v)) {
-        LIns* args[] = { get(&v), INS_CONSTPTR(JSVAL_TO_STRING(v)) };
+        LIns* args[] = { v_ins, INS_CONSTPTR(JSVAL_TO_STRING(v)) };
         guard(true,
               addName(lir->ins_eq0(lir->ins_eq0(lir->insCall(F_EqualStrings, args))),
                       "guard(switch on string)"),
               BRANCH_EXIT);
     } else if (JSVAL_IS_BOOLEAN(v)) {
         guard(true,
-              addName(lir->ins2(LIR_eq, get(&v), lir->insImm(JSVAL_TO_BOOLEAN(v))),
+              addName(lir->ins2(LIR_eq, v_ins, lir->insImm(JSVAL_TO_BOOLEAN(v))),
                       "guard(switch on boolean)"),
               BRANCH_EXIT);
     } else {
         ABORT_TRACE("switch on object, null, or undefined");
     }
     return true;
 }
 
--- a/js/src/trace-test.js
+++ b/js/src/trace-test.js
@@ -1264,16 +1264,24 @@ testNegZero2();
 function testConstSwitch() {
     var x;
     for (var j=0;j<5;++j) { switch(1.1) { case NaN: case 2: } x = 2; }
     return x;
 }
 testConstSwitch.expected = 2;
 test(testConstSwitch);
 
+function testConstSwitch2() {
+    var x;
+    for (var j = 0; j < 4; ++j) { switch(0/0) { } }
+    return "ok";
+}
+testConstSwitch2.expected = "ok";
+test(testConstSwitch2);
+
 function testConstIf() {
     var x;
     for (var j=0;j<5;++j) { if (1.1 || 5) { } x = 2;}
     return x;
 }
 testConstIf.expected = 2;
 test(testConstIf);