Bug 1438727: [Part 11] Implement JSOP_DIV in CacheIR r=jandem
authorMatthew Gaudet <mgaudet@mozilla.com>
Tue, 01 May 2018 13:56:32 -0400
changeset 483696 5b25886cfb6444c950bb40b01c306b0d74d1abc3
parent 483695 b0ff1059472bf9435ae1c99dcd1a1471045262ba
child 483697 7cb598e5f90c43782070de16aa1e82c7182483c5
push id9719
push userffxbld-merge
push dateFri, 24 Aug 2018 17:49:46 +0000
treeherdermozilla-beta@719ec98fba77 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjandem
bugs1438727
milestone63.0a1
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 1438727: [Part 11] Implement JSOP_DIV in CacheIR r=jandem
js/src/jit/BaselineIC.cpp
js/src/jit/CacheIR.cpp
js/src/jit/CacheIR.h
js/src/jit/CacheIRCompiler.cpp
js/src/jit/CacheIRCompiler.h
js/src/jit/IonBuilder.cpp
js/src/jit/IonIC.cpp
--- a/js/src/jit/BaselineIC.cpp
+++ b/js/src/jit/BaselineIC.cpp
@@ -4952,16 +4952,17 @@ DoCacheIRBinaryArithFallback(JSContext* 
     // Ensure we're only generating for an enabled opcode.
     switch(op) {
       case JSOP_ADD:
       case JSOP_SUB:
       case JSOP_BITOR:
       case JSOP_BITXOR:
       case JSOP_BITAND:
       case JSOP_MUL:
+      case JSOP_DIV:
         break;
       default:
         return false; // Fallback to shared IC.
     }
 
     FallbackICSpew(cx, stub, "CacheIRBinaryArith(%s,%d,%d)", CodeName[op],
             int(lhs.isDouble() ? JSVAL_TYPE_DOUBLE : lhs.extractNonDoubleType()),
             int(rhs.isDouble() ? JSVAL_TYPE_DOUBLE : rhs.extractNonDoubleType()));
--- a/js/src/jit/CacheIR.cpp
+++ b/js/src/jit/CacheIR.cpp
@@ -5154,17 +5154,18 @@ BinaryArithIRGenerator::tryAttachDouble(
     return true;
 }
 
 bool
 BinaryArithIRGenerator::tryAttachInt32()
 {
     if (op_ != JSOP_ADD && op_ != JSOP_SUB &&
         op_ != JSOP_BITOR && op_ != JSOP_BITAND &&
-        op_ != JSOP_BITXOR && op_ != JSOP_MUL)
+        op_ != JSOP_BITXOR && op_ != JSOP_MUL &&
+        op_ != JSOP_DIV)
     {
         return false;
     }
 
     if (!lhs_.isInt32() || !rhs_.isInt32())
         return false;
 
     ValOperandId lhsId(writer.setInputOperandId(0));
@@ -5181,16 +5182,20 @@ BinaryArithIRGenerator::tryAttachInt32()
       case JSOP_SUB:
         writer.int32SubResult(lhsIntId, rhsIntId);
         trackAttached("BinaryArith.Int32.Sub");
         break;
       case JSOP_MUL:
         writer.int32MulResult(lhsIntId, rhsIntId);
         trackAttached("BinaryArith.Int32.Mul");
         break;
+      case JSOP_DIV:
+        writer.int32DivResult(lhsIntId, rhsIntId);
+        trackAttached("BinaryArith.Int32.Div");
+        break;
       case JSOP_BITOR:
         writer.int32BitOrResult(lhsIntId, rhsIntId);
         trackAttached("BinaryArith.Int32.BitOr");
         break;
       case JSOP_BITXOR:
         writer.int32BitXOrResult(lhsIntId, rhsIntId);
         trackAttached("BinaryArith.Int32.BitXOr");
         break;
@@ -5206,17 +5211,17 @@ BinaryArithIRGenerator::tryAttachInt32()
     return true;
 }
 
 bool
 BinaryArithIRGenerator::tryAttachBooleanWithInt32()
 {
     if (op_ != JSOP_ADD && op_ != JSOP_SUB &&
         op_ != JSOP_BITOR && op_ != JSOP_BITAND &&
-        op_ != JSOP_BITXOR && op_!= JSOP_MUL)
+        op_ != JSOP_BITXOR && op_ != JSOP_MUL && op_ != JSOP_DIV)
         return false;
 
     if (!(lhs_.isBoolean() && (rhs_.isBoolean() || rhs_.isInt32())) &&
         !(rhs_.isBoolean() && (lhs_.isBoolean() || lhs_.isInt32())))
         return false;
 
 
     ValOperandId lhsId(writer.setInputOperandId(0));
@@ -5235,16 +5240,20 @@ BinaryArithIRGenerator::tryAttachBoolean
       case JSOP_SUB:
         writer.int32SubResult(lhsIntId, rhsIntId);
         trackAttached("BinaryArith.BooleanInt32.Sub");
         break;
       case JSOP_MUL:
         writer.int32MulResult(lhsIntId, rhsIntId);
         trackAttached("BinaryArith.BooleanInt32.Mul");
         break;
+      case JSOP_DIV:
+        writer.int32DivResult(lhsIntId, rhsIntId);
+        trackAttached("BinaryArith.BooleanInt32.Div");
+        break;
       case JSOP_BITOR:
         writer.int32BitOrResult(lhsIntId, rhsIntId);
         trackAttached("BinaryArith.BooleanInt32.BitOr");
         break;
       case JSOP_BITXOR:
         writer.int32BitXOrResult(lhsIntId, rhsIntId);
         trackAttached("BinaryArith.BooleanInt32.BitXOr");
         break;
--- a/js/src/jit/CacheIR.h
+++ b/js/src/jit/CacheIR.h
@@ -293,16 +293,17 @@ extern const char* CacheKindNames[];
     _(LoadInstanceOfObjectResult)         \
     _(LoadTypeOfObjectResult)             \
     _(DoubleAddResult)                    \
     _(DoubleSubResult)                    \
     _(DoubleMulResult)                    \
     _(Int32AddResult)                     \
     _(Int32SubResult)                     \
     _(Int32MulResult)                     \
+    _(Int32DivResult)                     \
     _(Int32BitOrResult)                   \
     _(Int32BitXorResult)                  \
     _(Int32BitAndResult)                  \
     _(Int32NotResult)                     \
     _(Int32NegationResult)                \
     _(DoubleNegationResult)               \
     _(LoadInt32TruthyResult)              \
     _(LoadDoubleTruthyResult)             \
@@ -1025,16 +1026,20 @@ class MOZ_RAII CacheIRWriter : public JS
     void int32SubResult(Int32OperandId lhs, Int32OperandId rhs) {
         writeOpWithOperandId(CacheOp::Int32SubResult, lhs);
         writeOperandId(rhs);
     }
     void int32MulResult(Int32OperandId lhs, Int32OperandId rhs) {
         writeOpWithOperandId(CacheOp::Int32MulResult, lhs);
         writeOperandId(rhs);
     }
+    void int32DivResult(Int32OperandId lhs, Int32OperandId rhs) {
+        writeOpWithOperandId(CacheOp::Int32DivResult, lhs);
+        writeOperandId(rhs);
+    }
     void int32BitOrResult(Int32OperandId lhs, Int32OperandId rhs) {
         writeOpWithOperandId(CacheOp::Int32BitOrResult, lhs);
         writeOperandId(rhs);
     }
     void int32BitXOrResult(Int32OperandId lhs, Int32OperandId rhs) {
         writeOpWithOperandId(CacheOp::Int32BitXorResult, lhs);
         writeOperandId(rhs);
     }
--- a/js/src/jit/CacheIRCompiler.cpp
+++ b/js/src/jit/CacheIRCompiler.cpp
@@ -2053,16 +2053,49 @@ CacheIRCompiler::emitInt32MulResult()
     // Result is -0 if exactly one of lhs or rhs is negative.
     masm.or32(rhs, scratch);
     masm.branchTest32(Assembler::Signed, scratch, scratch, failure->label());
 
     masm.bind(&done);
     EmitStoreResult(masm, lhs, JSVAL_TYPE_INT32, output);
     return true;
 }
+
+bool
+CacheIRCompiler::emitInt32DivResult()
+{
+    AutoOutputRegister output(*this);
+    Register lhs = allocator.useRegister(masm, reader.int32OperandId());
+    Register rhs = allocator.useRegister(masm, reader.int32OperandId());
+    AutoScratchRegister rem(allocator, masm);
+
+    FailurePath* failure;
+    if (!addFailurePath(&failure))
+        return false;
+
+    // Prevent division by 0.
+    masm.branchTest32(Assembler::Zero, rhs, rhs, failure->label());
+
+    // Prevent negative 0 and -2147483648 / -1.
+    masm.branch32(Assembler::Equal, lhs, Imm32(INT32_MIN), failure->label());
+
+    Label notZero;
+    masm.branch32(Assembler::NotEqual, lhs, Imm32(0), &notZero);
+    masm.branchTest32(Assembler::Signed, rhs, rhs, failure->label());
+    masm.bind(&notZero);
+
+    LiveRegisterSet volatileRegs(GeneralRegisterSet::Volatile(), liveVolatileFloatRegs());
+    masm.flexibleDivMod32(rhs, lhs, rem, false, volatileRegs);
+
+    // A remainder implies a double result.
+    masm.branchTest32(Assembler::NonZero, rem, rem, failure->label());
+    EmitStoreResult(masm, lhs, JSVAL_TYPE_INT32, output);
+    return true;
+}
+
 bool
 CacheIRCompiler::emitInt32BitOrResult()
 {
     AutoOutputRegister output(*this);
 
     Register lhs = allocator.useRegister(masm, reader.int32OperandId());
     Register rhs = allocator.useRegister(masm, reader.int32OperandId());
 
--- a/js/src/jit/CacheIRCompiler.h
+++ b/js/src/jit/CacheIRCompiler.h
@@ -53,16 +53,17 @@ namespace jit {
     _(LoadBooleanResult)                  \
     _(LoadInt32ArrayLengthResult)         \
     _(DoubleAddResult)                    \
     _(DoubleSubResult)                    \
     _(DoubleMulResult)                    \
     _(Int32AddResult)                     \
     _(Int32SubResult)                     \
     _(Int32MulResult)                     \
+    _(Int32DivResult)                     \
     _(Int32BitOrResult)                   \
     _(Int32BitXorResult)                  \
     _(Int32BitAndResult)                  \
     _(Int32NegationResult)                \
     _(Int32NotResult)                     \
     _(DoubleNegationResult)               \
     _(TruncateDoubleToUInt32)             \
     _(LoadArgumentsObjectLengthResult)    \
--- a/js/src/jit/IonBuilder.cpp
+++ b/js/src/jit/IonBuilder.cpp
@@ -3567,23 +3567,24 @@ IonBuilder::arithTrySharedStub(bool* emi
         MOZ_ASSERT_IF(op == JSOP_MUL,
                       left->maybeConstantValue() && left->maybeConstantValue()->toInt32() == -1);
         MOZ_ASSERT_IF(op != JSOP_MUL, !left);
         stub = MUnaryCache::New(alloc(), right);
         break;
       case JSOP_ADD:
       case JSOP_SUB:
       case JSOP_MUL:
+      case JSOP_DIV:
+
         // If not disabled, prefer the cache IR stub.
         if (!JitOptions.disableCacheIRBinaryArith) {
             stub = MBinaryCache::New(alloc(), left, right);
             break;
         }
         MOZ_FALLTHROUGH;
-      case JSOP_DIV:
       case JSOP_MOD:
       case JSOP_POW:
         stub = MBinarySharedStub::New(alloc(), left, right);
         break;
       default:
         MOZ_CRASH("unsupported arith");
     }
 
--- a/js/src/jit/IonIC.cpp
+++ b/js/src/jit/IonIC.cpp
@@ -574,16 +574,20 @@ IonBinaryArithIC::update(JSContext* cx, 
       case JSOP_SUB:
         if (!SubValues(cx, &lhsCopy, &rhsCopy, ret))
             return false;
         break;
       case JSOP_MUL:
         if (!MulValues(cx, &lhsCopy, &rhsCopy, ret))
             return false;
         break;
+      case JSOP_DIV:
+        if (!DivValues(cx, &lhsCopy, &rhsCopy, ret))
+            return false;
+        break;
       case JSOP_BITOR: {
         int32_t result;
         if (!BitOr(cx, lhs, rhs, &result))
             return false;
         ret.setInt32(result);
         break;
       }
       case JSOP_BITXOR: {