[JAEGER] Fast path for >>>; b=589932, r=dvander.
authorJan de Mooij <jandemooij@gmail.com>
Sat, 04 Sep 2010 15:19:52 -0400
changeset 74539 23706a77784890da0d27b4380f097228920a49b1
parent 74538 210c7d2a0ddcd1bffdb133a94155ff31d65eb38e
child 74540 a5f194447bea2b487d01638119eb6505edd59a0d
push id2
push userbsmedberg@mozilla.com
push dateFri, 19 Aug 2011 14:38:13 +0000
reviewersdvander
bugs589932
milestone2.0b6pre
[JAEGER] Fast path for >>>; b=589932, r=dvander.
js/src/methodjit/Compiler.cpp
js/src/methodjit/FastOps.cpp
js/src/trace-test/tests/jaeger/unsignedShiftZero.js
--- a/js/src/methodjit/Compiler.cpp
+++ b/js/src/methodjit/Compiler.cpp
@@ -822,20 +822,17 @@ mjit::Compiler::generateMethod()
             jsop_bitop(op);
           END_CASE(JSOP_LSH)
 
           BEGIN_CASE(JSOP_RSH)
             jsop_rsh();
           END_CASE(JSOP_RSH)
 
           BEGIN_CASE(JSOP_URSH)
-            prepareStubCall(Uses(2));
-            stubCall(stubs::Ursh);
-            frame.popn(2);
-            frame.pushSynced();
+            jsop_bitop(op);
           END_CASE(JSOP_URSH)
 
           BEGIN_CASE(JSOP_ADD)
             jsop_binary(op, stubs::Add);
           END_CASE(JSOP_ADD)
 
           BEGIN_CASE(JSOP_SUB)
             jsop_binary(op, stubs::Sub);
--- a/js/src/methodjit/FastOps.cpp
+++ b/js/src/methodjit/FastOps.cpp
@@ -327,27 +327,34 @@ mjit::Compiler::jsop_bitop(JSOp op)
         stub = stubs::BitAnd;
         break;
       case JSOP_BITXOR:
         stub = stubs::BitXor;
         break;
       case JSOP_LSH:
         stub = stubs::Lsh;
         break;
+      case JSOP_URSH:
+        stub = stubs::Ursh;
+        break;
       default:
         JS_NOT_REACHED("wat");
         return;
     }
 
     /* We only want to handle integers here. */
-    if (rhs->isNotType(JSVAL_TYPE_INT32) || lhs->isNotType(JSVAL_TYPE_INT32)) {
+    if (rhs->isNotType(JSVAL_TYPE_INT32) || lhs->isNotType(JSVAL_TYPE_INT32) || 
+        (op == JSOP_URSH && rhs->isConstant() && rhs->getValue().toInt32() % 32 == 0)) {
         prepareStubCall(Uses(2));
         stubCall(stub);
         frame.popn(2);
-        frame.pushSyncedType(JSVAL_TYPE_INT32);
+        if (op == JSOP_URSH)
+            frame.pushSynced();
+        else
+            frame.pushSyncedType(JSVAL_TYPE_INT32);
         return;
     }
            
     /* Test the types. */
     bool stubNeeded = false;
     if (!rhs->isTypeKnown()) {
         Jump rhsFail = frame.testInt32(Assembler::NotEqual, rhs);
         stubcc.linkExit(rhsFail, Uses(2));
@@ -355,21 +362,16 @@ mjit::Compiler::jsop_bitop(JSOp op)
         stubNeeded = true;
     }
     if (!lhs->isTypeKnown() && !frame.haveSameBacking(lhs, rhs)) {
         Jump lhsFail = frame.testInt32(Assembler::NotEqual, lhs);
         stubcc.linkExit(lhsFail, Uses(2));
         stubNeeded = true;
     }
 
-    if (stubNeeded) {
-        stubcc.leave();
-        stubcc.call(stub);
-    }
-
     if (lhs->isConstant() && rhs->isConstant()) {
         int32 L = lhs->getValue().toInt32();
         int32 R = rhs->getValue().toInt32();
 
         frame.popn(2);
         switch (op) {
           case JSOP_BITOR:
             frame.push(Int32Value(L | R));
@@ -378,16 +380,25 @@ mjit::Compiler::jsop_bitop(JSOp op)
             frame.push(Int32Value(L ^ R));
             return;
           case JSOP_BITAND:
             frame.push(Int32Value(L & R));
             return;
           case JSOP_LSH:
             frame.push(Int32Value(L << R));
             return;
+          case JSOP_URSH: 
+          {
+            uint32 unsignedL;
+            if (ValueToECMAUint32(cx, lhs->getValue(), &unsignedL)) {
+                frame.push(NumberValue(uint32(unsignedL >> (R & 31))));
+                return;
+            }
+            break;
+          }
           default:
             JS_NOT_REACHED("say wat");
         }
     }
 
     RegisterID reg;
 
     switch (op) {
@@ -427,26 +438,37 @@ mjit::Compiler::jsop_bitop(JSOp op)
             else
                 masm.or32(rhsReg, reg);
         }
 
         break;
       }
 
       case JSOP_LSH:
+      case JSOP_URSH:
       {
         /* Not commutative. */
         if (rhs->isConstant()) {
             RegisterID reg = frame.ownRegForData(lhs);
             int shift = rhs->getValue().toInt32() & 0x1F;
 
-            if (shift)
-                masm.lshift32(Imm32(shift), reg);
-
+            if (shift) {
+                if (op == JSOP_LSH)
+                    masm.lshift32(Imm32(shift), reg);
+                else
+                    masm.urshift32(Imm32(shift), reg);
+            }
+            if (stubNeeded) {
+                stubcc.leave();
+                stubcc.call(stub);
+            }
             frame.popn(2);
+            
+            /* x >>> 0 may result in a double, handled above. */
+            JS_ASSERT_IF(op == JSOP_URSH, shift >= 1);
             frame.pushTypedPayload(JSVAL_TYPE_INT32, reg);
 
             if (stubNeeded)
                 stubcc.rejoin(Changes(1));
 
             return;
         }
 #if defined(JS_CPU_X86) || defined(JS_CPU_X64)
@@ -457,32 +479,49 @@ mjit::Compiler::jsop_bitop(JSOp op)
         RegisterID rr = frame.tempRegForData(rhs);
 #endif
 
         frame.pinReg(rr);
         if (lhs->isConstant()) {
             reg = frame.allocReg();
             masm.move(Imm32(lhs->getValue().toInt32()), reg);
         } else {
-            reg = frame.ownRegForData(lhs);
+            reg = frame.copyDataIntoReg(lhs);
         }
         frame.unpinReg(rr);
-
-        masm.lshift32(rr, reg);
+        
+        if (op == JSOP_LSH) {
+            masm.lshift32(rr, reg);
+        } else {
+            masm.urshift32(rr, reg);
+            
+            Jump isNegative = masm.branch32(Assembler::LessThan, reg, Imm32(0));
+            stubcc.linkExit(isNegative, Uses(2));
+            stubNeeded = true;
+        }
         break;
       }
 
       default:
         JS_NOT_REACHED("NYI");
         return;
     }
 
+    if (stubNeeded) {
+        stubcc.leave();
+        stubcc.call(stub);
+    }
+
     frame.pop();
     frame.pop();
-    frame.pushTypedPayload(JSVAL_TYPE_INT32, reg);
+
+    if (op == JSOP_URSH)
+        frame.pushNumber(reg, true);
+    else
+        frame.pushTypedPayload(JSVAL_TYPE_INT32, reg);
 
     if (stubNeeded)
         stubcc.rejoin(Changes(1));
 }
 
 void
 mjit::Compiler::jsop_globalinc(JSOp op, uint32 index)
 {
new file mode 100644
--- /dev/null
+++ b/js/src/trace-test/tests/jaeger/unsignedShiftZero.js
@@ -0,0 +1,8 @@
+
+function f(a) { 
+    return a >>> 0; 
+};
+
+assertEq(f(-2147483647), 2147483649);
+assertEq(f(-2147483648), 2147483648);
+assertEq(f(-2147483649), 2147483647);