Bug 1434717: Part 6: Implement UnaryArith IC for doubles r=tcampbell
☠☠ backed out by 11e086a7d463 ☠ ☠
authorMatthew Gaudet <mgaudet@mozilla.com>
Wed, 07 Feb 2018 14:22:48 -0500
changeset 456728 bf1d9d0ebbe7f81b6b928b60f00df13ef1d9c8de
parent 456727 5c5ec856f0a6c47adba9208e2c8de09c9f255e81
child 456729 286c42a171d891d29c4afc214a34a806cb65f0bb
push id8799
push usermtabara@mozilla.com
push dateThu, 01 Mar 2018 16:46:23 +0000
treeherdermozilla-beta@15334014dc67 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerstcampbell
bugs1434717
milestone60.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 1434717: Part 6: Implement UnaryArith IC for doubles r=tcampbell
js/src/jit/CacheIR.cpp
js/src/jit/CacheIR.h
js/src/jit/CacheIRCompiler.cpp
js/src/jit/CacheIRCompiler.h
--- a/js/src/jit/CacheIR.cpp
+++ b/js/src/jit/CacheIR.cpp
@@ -4702,16 +4702,18 @@ UnaryArithIRGenerator::trackAttached(con
 #endif
 }
 
 bool
 UnaryArithIRGenerator::tryAttachStub()
 {
     if (tryAttachInt32())
         return true;
+    if (tryAttachNumber())
+        return true;
 
     trackAttached(IRGenerator::NotAttached);
     return false;
 }
 
 bool
 UnaryArithIRGenerator::tryAttachInt32()
 {
@@ -4731,9 +4733,36 @@ UnaryArithIRGenerator::tryAttachInt32()
         trackAttached("UnaryArith.Int32Neg");
         break;
       default:
         MOZ_CRASH("Unexected OP");
     }
 
     writer.returnFromIC();
     return true;
+}
+
+bool
+UnaryArithIRGenerator::tryAttachNumber()
+{
+    if (!val_.isNumber() || !res_.isNumber() || !cx_->runtime()->jitSupportsFloatingPoint)
+        return false;
+
+    ValOperandId valId(writer.setInputOperandId(0));
+    writer.guardType(valId, JSVAL_TYPE_DOUBLE);
+    Int32OperandId truncatedId;
+    switch (op_) {
+      case JSOP_BITNOT:
+        truncatedId = writer.truncateDoubleToUInt32(valId);
+        writer.int32NotResult(truncatedId);
+        trackAttached("UnaryArith.DoubleNot");
+        break;
+      case JSOP_NEG:
+        writer.doubleNegationResult(valId);
+        trackAttached("UnaryArith.DoubleNeg");
+        break;
+      default:
+        MOZ_CRASH("Unexpected OP");
+    }
+
+    writer.returnFromIC();
+    return true;
 }
\ No newline at end of file
--- a/js/src/jit/CacheIR.h
+++ b/js/src/jit/CacheIR.h
@@ -204,16 +204,18 @@ extern const char* CacheKindNames[];
     _(GuardXrayExpandoShapeAndDefaultProto) \
     _(GuardFunctionPrototype)             \
     _(LoadStackValue)                     \
     _(LoadObject)                         \
     _(LoadProto)                          \
     _(LoadEnclosingEnvironment)           \
     _(LoadWrapperTarget)                  \
                                           \
+    _(TruncateDoubleToUInt32)             \
+                                          \
     _(MegamorphicLoadSlotResult)          \
     _(MegamorphicLoadSlotByValueResult)   \
     _(MegamorphicStoreSlot)               \
     _(MegamorphicSetElement)              \
     _(MegamorphicHasPropResult)           \
                                           \
     /* See CacheIR.cpp 'DOM proxies' comment. */ \
     _(LoadDOMExpandoValue)                \
@@ -271,16 +273,17 @@ extern const char* CacheKindNames[];
     _(CallObjectHasSparseElementResult)   \
     _(LoadUndefinedResult)                \
     _(LoadBooleanResult)                  \
     _(LoadStringResult)                   \
     _(LoadInstanceOfObjectResult)         \
     _(LoadTypeOfObjectResult)             \
     _(Int32NotResult)                     \
     _(Int32NegationResult)                \
+    _(DoubleNegationResult)               \
     _(LoadInt32TruthyResult)              \
     _(LoadDoubleTruthyResult)             \
     _(LoadStringTruthyResult)             \
     _(LoadObjectTruthyResult)             \
     _(LoadValueResult)                    \
                                           \
     _(CallStringSplitResult)              \
                                           \
@@ -720,16 +723,23 @@ class MOZ_RAII CacheIRWriter : public JS
 
     ObjOperandId loadWrapperTarget(ObjOperandId obj) {
         ObjOperandId res(nextOperandId_++);
         writeOpWithOperandId(CacheOp::LoadWrapperTarget, obj);
         writeOperandId(res);
         return res;
     }
 
+    Int32OperandId truncateDoubleToUInt32(ValOperandId val) {
+        Int32OperandId res(nextOperandId_++);
+        writeOpWithOperandId(CacheOp::TruncateDoubleToUInt32, val);
+        writeOperandId(res);
+        return res;
+    }
+
     ValOperandId loadDOMExpandoValue(ObjOperandId obj) {
         ValOperandId res(nextOperandId_++);
         writeOpWithOperandId(CacheOp::LoadDOMExpandoValue, obj);
         writeOperandId(res);
         return res;
     }
     void guardDOMExpandoMissingOrGuardShape(ValOperandId expando, Shape* shape) {
         writeOpWithOperandId(CacheOp::GuardDOMExpandoMissingOrGuardShape, expando);
@@ -910,16 +920,19 @@ class MOZ_RAII CacheIRWriter : public JS
     }
 
     void int32NotResult(Int32OperandId id) {
         writeOpWithOperandId(CacheOp::Int32NotResult, id);
     }
     void int32NegationResult(Int32OperandId id) {
         writeOpWithOperandId(CacheOp::Int32NegationResult, id);
     }
+    void doubleNegationResult(ValOperandId val) {
+        writeOpWithOperandId(CacheOp::DoubleNegationResult, val);
+    }
     void loadBooleanResult(bool val) {
         writeOp(CacheOp::LoadBooleanResult);
         buffer_.writeByte(uint32_t(val));
     }
     void loadUndefinedResult() {
         writeOp(CacheOp::LoadUndefinedResult);
     }
     void loadStringResult(JSString* str) {
@@ -1671,16 +1684,17 @@ class MOZ_RAII GetIntrinsicIRGenerator :
 
 class MOZ_RAII UnaryArithIRGenerator : public IRGenerator
 {
     JSOp op_;
     HandleValue val_;
     HandleValue res_;
 
     bool tryAttachInt32();
+    bool tryAttachNumber();
 
     void trackAttached(const char* name);
 
   public:
     UnaryArithIRGenerator(JSContext* cx, HandleScript, jsbytecode* pc, ICState::Mode mode,
                           JSOp op, HandleValue val, HandleValue res);
 
     bool tryAttachStub();
--- a/js/src/jit/CacheIRCompiler.cpp
+++ b/js/src/jit/CacheIRCompiler.cpp
@@ -13,16 +13,17 @@
 
 #include "jit/MacroAssembler-inl.h"
 #include "vm/JSCompartment-inl.h"
 
 using namespace js;
 using namespace js::jit;
 
 using mozilla::Maybe;
+using mozilla::BitwiseCast;
 
 ValueOperand
 CacheRegisterAllocator::useValueRegister(MacroAssembler& masm, ValOperandId op)
 {
     OperandLocation& loc = operandLocations_[op.id()];
 
     switch (loc.kind()) {
       case OperandLocation::ValueReg:
@@ -1825,16 +1826,75 @@ CacheIRCompiler::emitInt32NotResult()
     AutoOutputRegister output(*this);
     Register val = allocator.useRegister(masm, reader.int32OperandId());
     masm.not32(val);
     masm.tagValue(JSVAL_TYPE_INT32, val, output.valueReg());
     return true;
 }
 
 bool
+CacheIRCompiler::emitDoubleNegationResult()
+{
+    AutoOutputRegister output(*this);
+    ValueOperand val = allocator.useValueRegister(masm, reader.valOperandId());
+
+    FailurePath* failure;
+    if (!addFailurePath(&failure))
+        return false;
+
+    // If we're compiling a Baseline IC, FloatReg0 is always available.
+    Label failurePopReg, done;
+    if (mode_ != Mode::Baseline)
+        masm.push(FloatReg0);
+
+    masm.ensureDouble(val, FloatReg0, (mode_ != Mode::Baseline) ? &failurePopReg : failure->label());
+    masm.negateDouble(FloatReg0);
+    masm.boxDouble(FloatReg0, output.valueReg(), FloatReg0);
+
+    if (mode_ != Mode::Baseline) {
+        masm.pop(FloatReg0);
+        masm.jump(&done);
+
+        masm.bind(&failurePopReg);
+        masm.pop(FloatReg0);
+        masm.jump(failure->label());
+    }
+
+    masm.bind(&done);
+    return true;
+}
+
+bool
+CacheIRCompiler::emitTruncateDoubleToUInt32()
+{
+    ValueOperand val = allocator.useValueRegister(masm, reader.valOperandId());
+    Register res = allocator.defineRegister(masm, reader.int32OperandId());
+
+    Label doneTruncate,  truncateABICall;
+    if (mode_ != Mode::Baseline)
+        masm.push(FloatReg0);
+
+    masm.unboxDouble(val, FloatReg0);
+    masm.branchTruncateDoubleMaybeModUint32(FloatReg0, res, &truncateABICall);
+    masm.jump(&doneTruncate);
+
+    masm.bind(&truncateABICall);
+    masm.setupUnalignedABICall(res);
+    masm.passABIArg(FloatReg0, MoveOp::DOUBLE);
+    masm.callWithABI(BitwiseCast<void*, int32_t(*)(double)>(JS::ToInt32),
+                     MoveOp::GENERAL, CheckUnsafeCallWithABI::DontCheckOther);
+    masm.storeCallInt32Result(res);
+
+    masm.bind(&doneTruncate);
+    if (mode_ != Mode::Baseline)
+        masm.pop(FloatReg0);
+    return true;
+}
+
+bool
 CacheIRCompiler::emitLoadArgumentsObjectLengthResult()
 {
     AutoOutputRegister output(*this);
     Register obj = allocator.useRegister(masm, reader.objOperandId());
     AutoScratchRegisterMaybeOutput scratch(allocator, masm, output);
 
     FailurePath* failure;
     if (!addFailurePath(&failure))
--- a/js/src/jit/CacheIRCompiler.h
+++ b/js/src/jit/CacheIRCompiler.h
@@ -42,16 +42,18 @@ namespace jit {
     _(LoadWrapperTarget)                  \
     _(LoadDOMExpandoValue)                \
     _(LoadDOMExpandoValueIgnoreGeneration)\
     _(LoadUndefinedResult)                \
     _(LoadBooleanResult)                  \
     _(LoadInt32ArrayLengthResult)         \
     _(Int32NegationResult)                \
     _(Int32NotResult)                     \
+    _(DoubleNegationResult)               \
+    _(TruncateDoubleToUInt32)             \
     _(LoadArgumentsObjectLengthResult)    \
     _(LoadFunctionLengthResult)           \
     _(LoadStringLengthResult)             \
     _(LoadStringCharResult)               \
     _(LoadArgumentsObjectArgResult)       \
     _(LoadInstanceOfObjectResult)         \
     _(LoadDenseElementResult)             \
     _(LoadDenseElementHoleResult)         \