Bug 1175976: IonMonkey - Part2: Get the UnaryArith stub working in ionmonkey, r=jandem
authorHannes Verschore <hv1989@gmail.com>
Fri, 21 Aug 2015 10:14:24 +0200
changeset 258840 bb070785cc9b5fe060217af2a600ad7f10e63258
parent 258839 0f06efef9c6d626de9d1071c038f89ef9a9088d6
child 258841 07e73fa84838415bd184d5685e2efce47d24b988
push id29263
push userryanvm@gmail.com
push dateSun, 23 Aug 2015 21:18:49 +0000
treeherdermozilla-central@4ccdd06e51d7 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjandem
bugs1175976
milestone43.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 1175976: IonMonkey - Part2: Get the UnaryArith stub working in ionmonkey, r=jandem
js/src/jit/BaselineCompiler.cpp
js/src/jit/BaselineIC.cpp
js/src/jit/BaselineICList.h
js/src/jit/CodeGenerator.cpp
js/src/jit/IonBuilder.cpp
js/src/jit/IonBuilder.h
js/src/jit/MIR.cpp
js/src/jit/MIR.h
js/src/jit/SharedIC.cpp
js/src/jit/SharedIC.h
js/src/jit/SharedICList.h
--- a/js/src/jit/BaselineCompiler.cpp
+++ b/js/src/jit/BaselineCompiler.cpp
@@ -1623,17 +1623,17 @@ BaselineCompiler::emitBinaryArith()
 
 bool
 BaselineCompiler::emitUnaryArith()
 {
     // Keep top stack value in R0.
     frame.popRegsAndSync(1);
 
     // Call IC
-    ICUnaryArith_Fallback::Compiler stubCompiler(cx);
+    ICUnaryArith_Fallback::Compiler stubCompiler(cx, ICStubCompiler::Engine::Baseline);
     if (!emitOpIC(stubCompiler.getStub(&stubSpace_)))
         return false;
 
     // Mark R0 as pushed stack value.
     frame.push(R0);
     return true;
 }
 
--- a/js/src/jit/BaselineIC.cpp
+++ b/js/src/jit/BaselineIC.cpp
@@ -1,17 +1,16 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  * vim: set ts=8 sts=4 et sw=4 tw=99:
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "jit/BaselineIC.h"
 
-#include "mozilla/Casting.h"
 #include "mozilla/DebugOnly.h"
 #include "mozilla/SizePrintfMacros.h"
 #include "mozilla/TemplateLib.h"
 
 #include "jslibmath.h"
 #include "jstypes.h"
 
 #include "builtin/Eval.h"
@@ -37,17 +36,16 @@
 #include "jit/JitFrames-inl.h"
 #include "jit/MacroAssembler-inl.h"
 #include "jit/shared/Lowering-shared-inl.h"
 #include "vm/Interpreter-inl.h"
 #include "vm/ScopeObject-inl.h"
 #include "vm/StringObject-inl.h"
 #include "vm/UnboxedObject-inl.h"
 
-using mozilla::BitwiseCast;
 using mozilla::DebugOnly;
 
 namespace js {
 namespace jit {
 
 static void
 GuardReceiverObject(MacroAssembler& masm, ReceiverGuard guard,
                     Register object, Register scratch,
--- a/js/src/jit/BaselineICList.h
+++ b/js/src/jit/BaselineICList.h
@@ -44,20 +44,16 @@ namespace jit {
     _(ToBool_Int32)                              \
     _(ToBool_String)                             \
     _(ToBool_NullUndefined)                      \
     _(ToBool_Double)                             \
     _(ToBool_Object)                             \
                                                  \
     _(ToNumber_Fallback)                         \
                                                  \
-    _(UnaryArith_Fallback)                       \
-    _(UnaryArith_Int32)                          \
-    _(UnaryArith_Double)                         \
-                                                 \
     _(Call_Fallback)                             \
     _(Call_Scripted)                             \
     _(Call_AnyScripted)                          \
     _(Call_Native)                               \
     _(Call_ClassHook)                            \
     _(Call_ScriptedApplyArray)                   \
     _(Call_ScriptedApplyArguments)               \
     _(Call_ScriptedFunCall)                      \
--- a/js/src/jit/CodeGenerator.cpp
+++ b/js/src/jit/CodeGenerator.cpp
@@ -1724,16 +1724,20 @@ CodeGenerator::visitBinarySharedStub(LBi
     }
 }
 
 void
 CodeGenerator::visitUnarySharedStub(LUnarySharedStub* lir)
 {
     JSOp jsop = JSOp(*lir->mir()->resumePoint()->pc());
     switch (jsop) {
+      case JSOP_BITNOT:
+      case JSOP_NEG:
+        emitSharedStub(ICStub::Kind::UnaryArith_Fallback, lir);
+        break;
       default:
         MOZ_CRASH("Unsupported jsop in shared stubs.");
     }
 }
 
 typedef JSObject* (*LambdaFn)(JSContext*, HandleFunction, HandleObject);
 static const VMFunction LambdaInfo = FunctionInfo<LambdaFn>(js::Lambda);
 
@@ -7864,16 +7868,21 @@ CodeGenerator::linkSharedStubs(JSContext
         ICStub *stub = nullptr;
 
         switch (sharedStubs_[i].kind) {
           case ICStub::Kind::BinaryArith_Fallback: {
             ICBinaryArith_Fallback::Compiler stubCompiler(cx, ICStubCompiler::Engine::IonMonkey);
             stub = stubCompiler.getStub(&stubSpace_);
             break;
           }
+          case ICStub::Kind::UnaryArith_Fallback: {
+            ICUnaryArith_Fallback::Compiler stubCompiler(cx, ICStubCompiler::Engine::IonMonkey);
+            stub = stubCompiler.getStub(&stubSpace_);
+            break;
+          }
           default:
             MOZ_CRASH("Unsupported shared stub.");
         }
 
         if (!stub)
             return false;
 
         sharedStubs_[i].entry.setFirstStub(stub);
--- a/js/src/jit/IonBuilder.cpp
+++ b/js/src/jit/IonBuilder.cpp
@@ -4480,28 +4480,58 @@ IonBuilder::processThrow()
 bool
 IonBuilder::pushConstant(const Value& v)
 {
     current->push(constant(v));
     return true;
 }
 
 bool
+IonBuilder::bitnotTrySpecialized(bool* emitted, MDefinition* input)
+{
+    MOZ_ASSERT(*emitted == false);
+
+    // Try to emit a specialized bitnot instruction based on the input type
+    // of the operand.
+
+    if (input->mightBeType(MIRType_Object) || input->mightBeType(MIRType_Symbol))
+        return true;
+
+    MBitNot* ins = MBitNot::New(alloc(), input);
+    ins->setSpecialization(MIRType_Int32);
+
+    current->add(ins);
+    current->push(ins);
+
+    *emitted = true;
+    return true;
+}
+
+bool
 IonBuilder::jsop_bitnot()
 {
+    bool emitted = false;
+
     MDefinition* input = current->pop();
+
+    if (!forceInlineCaches()) {
+        if (!bitnotTrySpecialized(&emitted, input) || emitted)
+            return emitted;
+    }
+
+    if (!arithTrySharedStub(&emitted, JSOP_BITNOT, nullptr, input) || emitted)
+        return emitted;
+
+    // Not possible to optimize. Do a slow vm call.
     MBitNot* ins = MBitNot::New(alloc(), input);
 
     current->add(ins);
-    ins->infer();
-
     current->push(ins);
-    if (ins->isEffectful() && !resumeAfter(ins))
-        return false;
-    return true;
+    MOZ_ASSERT(ins->isEffectful());
+    return resumeAfter(ins);
 }
 bool
 IonBuilder::jsop_bitop(JSOp op)
 {
     // Pop inputs.
     MDefinition* right = current->pop();
     MDefinition* left = current->pop();
 
@@ -4667,31 +4697,52 @@ IonBuilder::binaryArithTrySpecializedOnB
     if (!maybeInsertResume())
         return false;
 
     *emitted = true;
     return true;
 }
 
 bool
-IonBuilder::binaryArithTrySharedStub(bool* emitted, JSOp op,
-                                     MDefinition* left, MDefinition* right)
+IonBuilder::arithTrySharedStub(bool* emitted, JSOp op,
+                               MDefinition* left, MDefinition* right)
 {
     MOZ_ASSERT(*emitted == false);
+    JSOp actualOp = JSOp(*pc);
 
     // Try to emit a shared stub cache.
 
     if (js_JitOptions.disableSharedStubs)
         return true;
 
-    // It is not possible for shared stubs to impersonate another op.
-    if (JSOp(*pc) != op)
-        return true;
-
-    MBinarySharedStub *stub = MBinarySharedStub::New(alloc(), left, right);
+    // The actual jsop 'jsop_pos' is not supported yet.
+    if (actualOp == JSOP_POS)
+        return true;
+
+    MInstruction* stub = nullptr;
+    switch (actualOp) {
+      case JSOP_NEG:
+      case JSOP_BITNOT:
+        MOZ_ASSERT_IF(op == JSOP_MUL, left->isConstantValue() &&
+                                      left->constantValue().toInt32() == -1);
+        MOZ_ASSERT_IF(op != JSOP_MUL, !left);
+
+        stub = MUnarySharedStub::New(alloc(), right);
+        break;
+      case JSOP_ADD:
+      case JSOP_SUB:
+      case JSOP_MUL:
+      case JSOP_DIV:
+      case JSOP_MOD:
+        stub = MBinarySharedStub::New(alloc(), left, right);
+        break;
+      default:
+        MOZ_CRASH("unsupported arith");
+    }
+
     current->add(stub);
     current->push(stub);
 
     // Decrease type from 'any type' to 'empty type' when one of the operands
     // is 'empty typed'.
     maybeMarkEmpty(stub);
 
     if (!resumeAfter(stub))
@@ -4712,17 +4763,17 @@ IonBuilder::jsop_binary_arith(JSOp op, M
 
         if (!binaryArithTrySpecialized(&emitted, op, left, right) || emitted)
             return emitted;
 
         if (!binaryArithTrySpecializedOnBaselineInspector(&emitted, op, left, right) || emitted)
             return emitted;
     }
 
-    if (!binaryArithTrySharedStub(&emitted, op, left, right) || emitted)
+    if (!arithTrySharedStub(&emitted, op, left, right) || emitted)
         return emitted;
 
     // Not possible to optimize. Do a slow vm call.
     MDefinition::Opcode def_op = JSOpToMDefinition(op);
     MBinaryArithInstruction* ins = MBinaryArithInstruction::New(alloc(), def_op, left, right);
 
     // Decrease type from 'any type' to 'empty type' when one of the operands
     // is 'empty typed'.
@@ -4786,19 +4837,17 @@ IonBuilder::jsop_neg()
 {
     // Since JSOP_NEG does not use a slot, we cannot push the MConstant.
     // The MConstant is therefore passed to JSOP_MUL without slot traffic.
     MConstant* negator = MConstant::New(alloc(), Int32Value(-1));
     current->add(negator);
 
     MDefinition* right = current->pop();
 
-    if (!jsop_binary_arith(JSOP_MUL, negator, right))
-        return false;
-    return true;
+    return jsop_binary_arith(JSOP_MUL, negator, right);
 }
 
 class AutoAccumulateReturns
 {
     MIRGraph& graph_;
     MIRGraphReturns* prev_;
 
   public:
--- a/js/src/jit/IonBuilder.h
+++ b/js/src/jit/IonBuilder.h
@@ -484,17 +484,20 @@ class IonBuilder
                          bool barrier, TemporaryTypeSet* objTypes);
 
     // jsop_binary_arith helpers.
     MBinaryArithInstruction* binaryArithInstruction(JSOp op, MDefinition* left, MDefinition* right);
     bool binaryArithTryConcat(bool* emitted, JSOp op, MDefinition* left, MDefinition* right);
     bool binaryArithTrySpecialized(bool* emitted, JSOp op, MDefinition* left, MDefinition* right);
     bool binaryArithTrySpecializedOnBaselineInspector(bool* emitted, JSOp op, MDefinition* left,
                                                       MDefinition* right);
-    bool binaryArithTrySharedStub(bool* emitted, JSOp op, MDefinition* left, MDefinition* right);
+    bool arithTrySharedStub(bool* emitted, JSOp op, MDefinition* left, MDefinition* right);
+
+    // jsop_bitnot helpers.
+    bool bitnotTrySpecialized(bool* emitted, MDefinition* input);
 
     // binary data lookup helpers.
     TypedObjectPrediction typedObjectPrediction(MDefinition* typedObj);
     TypedObjectPrediction typedObjectPrediction(TemporaryTypeSet* types);
     bool typedObjectHasField(MDefinition* typedObj,
                              PropertyName* name,
                              size_t* fieldOffset,
                              TypedObjectPrediction* fieldTypeReprs,
--- a/js/src/jit/MIR.cpp
+++ b/js/src/jit/MIR.cpp
@@ -1993,25 +1993,16 @@ void
 MCall::addArg(size_t argnum, MDefinition* arg)
 {
     // The operand vector is initialized in reverse order by the IonBuilder.
     // It cannot be checked for consistency until all arguments are added.
     // FixedList doesn't initialize its elements, so do an unchecked init.
     initOperand(argnum + NumNonArgumentOperands, arg);
 }
 
-void
-MBitNot::infer()
-{
-    if (getOperand(0)->mightBeType(MIRType_Object) || getOperand(0)->mightBeType(MIRType_Symbol))
-        specialization_ = MIRType_None;
-    else
-        specialization_ = MIRType_Int32;
-}
-
 static inline bool
 IsConstant(MDefinition* def, double v)
 {
     if (!def->isConstant())
         return false;
 
     return NumbersAreIdentical(def->toConstant()->value().toNumber(), v);
 }
--- a/js/src/jit/MIR.h
+++ b/js/src/jit/MIR.h
@@ -5210,27 +5210,31 @@ class MToObjectOrNull :
 class MBitNot
   : public MUnaryInstruction,
     public BitwisePolicy::Data
 {
   protected:
     explicit MBitNot(MDefinition* input)
       : MUnaryInstruction(input)
     {
+        specialization_ = MIRType_None;
         setResultType(MIRType_Int32);
         setMovable();
     }
 
   public:
     INSTRUCTION_HEADER(BitNot)
     static MBitNot* New(TempAllocator& alloc, MDefinition* input);
     static MBitNot* NewAsmJS(TempAllocator& alloc, MDefinition* input);
 
     MDefinition* foldsTo(TempAllocator& alloc) override;
-    void infer();
+    void setSpecialization(MIRType type) {
+        specialization_ = type;
+        setResultType(type);
+    }
 
     bool congruentTo(const MDefinition* ins) const override {
         return congruentIfOperandsEqual(ins);
     }
     AliasSet getAliasSet() const override {
         if (specialization_ == MIRType_None)
             return AliasSet::Store(AliasSet::Any);
         return AliasSet::None();
--- a/js/src/jit/SharedIC.cpp
+++ b/js/src/jit/SharedIC.cpp
@@ -1,15 +1,17 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  * vim: set ts=8 sts=4 et sw=4 tw=99:
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "jit/SharedIC.h"
+
+#include "mozilla/Casting.h"
 #include "mozilla/SizePrintfMacros.h"
 
 #include "jslibmath.h"
 #include "jstypes.h"
 
 #include "jit/BaselineDebugModeOSR.h"
 #include "jit/BaselineIC.h"
 #include "jit/JitSpewer.h"
@@ -19,16 +21,18 @@
 # include "jit/PerfSpewer.h"
 #endif
 #include "jit/VMFunctions.h"
 #include "vm/Interpreter.h"
 
 #include "jit/MacroAssembler-inl.h"
 #include "vm/Interpreter-inl.h"
 
+using mozilla::BitwiseCast;
+
 namespace js {
 namespace jit {
 
 #ifdef DEBUG
 void
 FallbackICSpew(JSContext* cx, ICFallbackStub* stub, const char* fmt, ...)
 {
     if (JitSpewEnabled(JitSpew_BaselineICFallback)) {
@@ -1430,20 +1434,22 @@ ICBinaryArith_DoubleWithInt32::Compiler:
 //
 // UnaryArith_Fallback
 //
 
 static bool
 DoUnaryArithFallback(JSContext* cx, BaselineFrame* frame, ICUnaryArith_Fallback* stub_,
                      HandleValue val, MutableHandleValue res)
 {
+    ICStubCompiler::Engine engine = SharedStubEngine(frame);
+    RootedScript script(cx, SharedStubScript(frame, stub_));
+
     // This fallback stub may trigger debug mode toggling.
-    DebugModeOSRVolatileStub<ICUnaryArith_Fallback*> stub(frame, stub_);
+    DebugModeOSRVolatileStub<ICUnaryArith_Fallback*> stub(engine, frame, stub_);
 
-    RootedScript script(cx, frame->script());
     jsbytecode* pc = stub->icEntry()->pc(script);
     JSOp op = JSOp(*pc);
     FallbackICSpew(cx, stub, "UnaryArith(%s)", js_CodeName[op]);
 
     switch (op) {
       case JSOP_BITNOT: {
         int32_t result;
         if (!BitNot(cx, val, &result))
@@ -1468,31 +1474,31 @@ DoUnaryArithFallback(JSContext* cx, Base
 
     if (stub->numOptimizedStubs() >= ICUnaryArith_Fallback::MAX_OPTIMIZED_STUBS) {
         // TODO: Discard/replace stubs.
         return true;
     }
 
     if (val.isInt32() && res.isInt32()) {
         JitSpew(JitSpew_BaselineIC, "  Generating %s(Int32 => Int32) stub", js_CodeName[op]);
-        ICUnaryArith_Int32::Compiler compiler(cx, op);
+        ICUnaryArith_Int32::Compiler compiler(cx, op, engine);
         ICStub* int32Stub = compiler.getStub(compiler.getStubSpace(script));
         if (!int32Stub)
             return false;
         stub->addNewStub(int32Stub);
         return true;
     }
 
     if (val.isNumber() && res.isNumber() && cx->runtime()->jitSupportsFloatingPoint) {
         JitSpew(JitSpew_BaselineIC, "  Generating %s(Number => Number) stub", js_CodeName[op]);
 
         // Unlink int32 stubs, the double stub handles both cases and TI specializes for both.
         stub->unlinkStubsWithKind(cx, ICStub::UnaryArith_Int32);
 
-        ICUnaryArith_Double::Compiler compiler(cx, op);
+        ICUnaryArith_Double::Compiler compiler(cx, op, engine);
         ICStub* doubleStub = compiler.getStub(compiler.getStubSpace(script));
         if (!doubleStub)
             return false;
         stub->addNewStub(doubleStub);
         return true;
     }
 
     return true;
@@ -1501,17 +1507,16 @@ DoUnaryArithFallback(JSContext* cx, Base
 typedef bool (*DoUnaryArithFallbackFn)(JSContext*, BaselineFrame*, ICUnaryArith_Fallback*,
                                        HandleValue, MutableHandleValue);
 static const VMFunction DoUnaryArithFallbackInfo =
     FunctionInfo<DoUnaryArithFallbackFn>(DoUnaryArithFallback, TailCall, PopValues(1));
 
 bool
 ICUnaryArith_Fallback::Compiler::generateStubCode(MacroAssembler& masm)
 {
-    MOZ_ASSERT(engine_ == Engine::Baseline);
     MOZ_ASSERT(R0 == JSReturnOperand);
 
     // Restore the tail call register.
     EmitRestoreTailCallReg(masm);
 
     // Ensure stack is fully synced for the expression decompiler.
     masm.pushValue(R0);
 
@@ -1521,18 +1526,16 @@ ICUnaryArith_Fallback::Compiler::generat
     pushFramePtr(masm, R0.scratchReg());
 
     return tailCallVM(DoUnaryArithFallbackInfo, masm);
 }
 
 bool
 ICUnaryArith_Double::Compiler::generateStubCode(MacroAssembler& masm)
 {
-    MOZ_ASSERT(engine_ == Engine::Baseline);
-
     Label failure;
     masm.ensureDouble(R0, FloatReg0, &failure);
 
     MOZ_ASSERT(op == JSOP_NEG || op == JSOP_BITNOT);
 
     if (op == JSOP_NEG) {
         masm.negateDouble(FloatReg0);
         masm.boxDouble(FloatReg0, R0);
--- a/js/src/jit/SharedIC.h
+++ b/js/src/jit/SharedIC.h
@@ -1414,18 +1414,18 @@ class ICUnaryArith_Fallback : public ICF
     }
 
     // Compiler for this stub kind.
     class Compiler : public ICStubCompiler {
       protected:
         bool generateStubCode(MacroAssembler& masm);
 
       public:
-        explicit Compiler(JSContext* cx)
-          : ICStubCompiler(cx, ICStub::UnaryArith_Fallback, Engine::Baseline)
+        explicit Compiler(JSContext* cx, Engine engine)
+          : ICStubCompiler(cx, ICStub::UnaryArith_Fallback, engine)
         {}
 
         ICStub* getStub(ICStubSpace* space) {
             return newStub<ICUnaryArith_Fallback>(space, getStubCode());
         }
     };
 };
 
@@ -1438,18 +1438,18 @@ class ICUnaryArith_Int32 : public ICStub
     {}
 
   public:
     class Compiler : public ICMultiStubCompiler {
       protected:
         bool generateStubCode(MacroAssembler& masm);
 
       public:
-        Compiler(JSContext* cx, JSOp op)
-          : ICMultiStubCompiler(cx, ICStub::UnaryArith_Int32, op, Engine::Baseline)
+        Compiler(JSContext* cx, JSOp op, Engine engine)
+          : ICMultiStubCompiler(cx, ICStub::UnaryArith_Int32, op, engine)
         {}
 
         ICStub* getStub(ICStubSpace* space) {
             return newStub<ICUnaryArith_Int32>(space, getStubCode());
         }
     };
 };
 
@@ -1462,18 +1462,18 @@ class ICUnaryArith_Double : public ICStu
     {}
 
   public:
     class Compiler : public ICMultiStubCompiler {
       protected:
         bool generateStubCode(MacroAssembler& masm);
 
       public:
-        Compiler(JSContext* cx, JSOp op)
-          : ICMultiStubCompiler(cx, ICStub::UnaryArith_Double, op, Engine::Baseline)
+        Compiler(JSContext* cx, JSOp op, Engine engine)
+          : ICMultiStubCompiler(cx, ICStub::UnaryArith_Double, op, engine)
         {}
 
         ICStub* getStub(ICStubSpace* space) {
             return newStub<ICUnaryArith_Double>(space, getStubCode());
         }
     };
 };
 
--- a/js/src/jit/SharedICList.h
+++ b/js/src/jit/SharedICList.h
@@ -15,13 +15,16 @@ namespace jit {
     _(BinaryArith_Fallback)                      \
     _(BinaryArith_Int32)                         \
     _(BinaryArith_Double)                        \
     _(BinaryArith_StringConcat)                  \
     _(BinaryArith_StringObjectConcat)            \
     _(BinaryArith_BooleanWithInt32)              \
     _(BinaryArith_DoubleWithInt32)               \
                                                  \
+    _(UnaryArith_Fallback)                       \
+    _(UnaryArith_Int32)                          \
+    _(UnaryArith_Double)                         \
 
 } // namespace jit
 } // namespace js
 
 #endif /* jit_SharedICList_h */