Bug 883748 - Specialize MUrsh as double if needed. r=bhackett, a=lsblakk
authorJan de Mooij <jdemooij@mozilla.com>
Tue, 18 Jun 2013 13:44:01 +0200
changeset 142943 1db75fb7a96892db717fe050a27c54f907902035
parent 142942 7667bef7d81794b71b976da4e976e78429791a94
child 142944 f9f869d1ec535a98cb95a3eb38699b51f00a4f88
push id2579
push userakeybl@mozilla.com
push dateMon, 24 Jun 2013 18:52:47 +0000
treeherdermozilla-beta@b69b7de8a05a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbhackett, lsblakk
bugs883748
milestone23.0a2
Bug 883748 - Specialize MUrsh as double if needed. r=bhackett, a=lsblakk
js/src/ion/BaselineIC.cpp
js/src/ion/BaselineIC.h
js/src/ion/BaselineInspector.cpp
js/src/ion/IonBuilder.cpp
js/src/ion/MIR.cpp
js/src/ion/MIR.h
--- a/js/src/ion/BaselineIC.cpp
+++ b/js/src/ion/BaselineIC.cpp
@@ -2497,19 +2497,20 @@ DoBinaryArithFallback(JSContext *cx, Bas
             stub->addNewStub(doubleStub);
             return true;
           }
           default:
             break;
         }
     }
 
-    // TODO: unlink previous !allowDouble stub.
     if (lhs.isInt32() && rhs.isInt32()) {
         bool allowDouble = ret.isDouble();
+        if (allowDouble)
+            stub->unlinkStubsWithKind(cx, ICStub::BinaryArith_Int32);
         IonSpew(IonSpew_BaselineIC, "  Generating %s(Int32, Int32%s) stub", js_CodeName[op],
                 allowDouble ? " => Double" : "");
         ICBinaryArith_Int32::Compiler compilerInt32(cx, op, allowDouble);
         ICStub *int32Stub = compilerInt32.getStub(compilerInt32.getStubSpace(script));
         if (!int32Stub)
             return false;
         stub->addNewStub(int32Stub);
         return true;
--- a/js/src/ion/BaselineIC.h
+++ b/js/src/ion/BaselineIC.h
@@ -2389,24 +2389,30 @@ class ICBinaryArith_Fallback : public IC
         }
     };
 };
 
 class ICBinaryArith_Int32 : public ICStub
 {
     friend class ICStubSpace;
 
-    ICBinaryArith_Int32(IonCode *stubCode)
-      : ICStub(BinaryArith_Int32, stubCode) {}
+    ICBinaryArith_Int32(IonCode *stubCode, bool allowDouble)
+      : ICStub(BinaryArith_Int32, stubCode)
+    {
+        extra_ = allowDouble;
+    }
 
   public:
-    static inline ICBinaryArith_Int32 *New(ICStubSpace *space, IonCode *code) {
+    static inline ICBinaryArith_Int32 *New(ICStubSpace *space, IonCode *code, bool allowDouble) {
         if (!code)
             return NULL;
-        return space->allocate<ICBinaryArith_Int32>(code);
+        return space->allocate<ICBinaryArith_Int32>(code, allowDouble);
+    }
+    bool allowDouble() const {
+        return extra_;
     }
 
     // Compiler for this stub kind.
     class Compiler : public ICStubCompiler {
       protected:
         JSOp op_;
         bool allowDouble_;
 
@@ -2419,17 +2425,17 @@ class ICBinaryArith_Int32 : public ICStu
         }
 
       public:
         Compiler(JSContext *cx, JSOp op, bool allowDouble)
           : ICStubCompiler(cx, ICStub::BinaryArith_Int32),
             op_(op), allowDouble_(allowDouble) {}
 
         ICStub *getStub(ICStubSpace *space) {
-            return ICBinaryArith_Int32::New(space, getStubCode());
+            return ICBinaryArith_Int32::New(space, getStubCode(), allowDouble_);
         }
     };
 };
 
 class ICBinaryArith_StringConcat : public ICStub
 {
     friend class ICStubSpace;
 
--- a/js/src/ion/BaselineInspector.cpp
+++ b/js/src/ion/BaselineInspector.cpp
@@ -141,16 +141,19 @@ BaselineInspector::expectedResultType(js
     // returning MIRType_None otherwise.
 
     ICStub *stub = monomorphicStub(pc);
     if (!stub)
         return MIRType_None;
 
     switch (stub->kind()) {
       case ICStub::BinaryArith_Int32:
+        if (stub->toBinaryArith_Int32()->allowDouble())
+            return MIRType_Double;
+        return MIRType_Int32;
       case ICStub::BinaryArith_BooleanWithInt32:
       case ICStub::UnaryArith_Int32:
         return MIRType_Int32;
       case ICStub::BinaryArith_Double:
       case ICStub::BinaryArith_DoubleWithInt32:
       case ICStub::UnaryArith_Double:
         return MIRType_Double;
       case ICStub::BinaryArith_StringConcat:
--- a/js/src/ion/IonBuilder.cpp
+++ b/js/src/ion/IonBuilder.cpp
@@ -3212,17 +3212,17 @@ IonBuilder::jsop_bitop(JSOp op)
         break;
 
       default:
         JS_NOT_REACHED("unexpected bitop");
         return false;
     }
 
     current->add(ins);
-    ins->infer();
+    ins->infer(inspector, pc);
 
     current->push(ins);
     if (ins->isEffectful() && !resumeAfter(ins))
         return false;
 
     return true;
 }
 
@@ -6341,17 +6341,17 @@ IonBuilder::convertShiftToMaskForStaticT
     if (!value.isInt32() || uint32_t(value.toInt32()) != TypedArrayShift(viewType))
         return NULL;
 
     // Instead of shifting, mask off the low bits of the index so that
     // a non-scaled access on the typed array can be performed.
     MConstant *mask = MConstant::New(Int32Value(~((1 << value.toInt32()) - 1)));
     MBitAnd *ptr = MBitAnd::New(id->getOperand(0), mask);
 
-    ptr->infer();
+    ptr->infer(NULL, NULL);
     JS_ASSERT(!ptr->isEffectful());
 
     current->add(mask);
     current->add(ptr);
 
     return ptr;
 }
 
--- a/js/src/ion/MIR.cpp
+++ b/js/src/ion/MIR.cpp
@@ -884,17 +884,17 @@ MBinaryBitwiseInstruction::foldUnnecessa
 
     if (EqualValues(false, lhs, rhs))
         return foldIfEqual();
 
     return this;
 }
 
 void
-MBinaryBitwiseInstruction::infer()
+MBinaryBitwiseInstruction::infer(BaselineInspector *, jsbytecode *)
 {
     if (getOperand(0)->mightBeType(MIRType_Object) || getOperand(1)->mightBeType(MIRType_Object)) {
         specialization_ = MIRType_None;
     } else {
         specialization_ = MIRType_Int32;
         setCommutative();
     }
 }
@@ -903,40 +903,41 @@ void
 MBinaryBitwiseInstruction::specializeForAsmJS()
 {
     specialization_ = MIRType_Int32;
     JS_ASSERT(type() == MIRType_Int32);
     setCommutative();
 }
 
 void
-MShiftInstruction::infer()
+MShiftInstruction::infer(BaselineInspector *, jsbytecode *)
 {
     if (getOperand(0)->mightBeType(MIRType_Object) || getOperand(1)->mightBeType(MIRType_Object))
         specialization_ = MIRType_None;
     else
         specialization_ = MIRType_Int32;
 }
 
 void
-MUrsh::infer()
+MUrsh::infer(BaselineInspector *inspector, jsbytecode *pc)
 {
     if (getOperand(0)->mightBeType(MIRType_Object) || getOperand(1)->mightBeType(MIRType_Object)) {
         specialization_ = MIRType_None;
         setResultType(MIRType_Value);
         return;
     }
 
-    if (type() == MIRType_Int32) {
-        specialization_ = MIRType_Int32;
+    if (inspector->expectedResultType(pc) == MIRType_Double) {
+        specialization_ = MIRType_Double;
+        setResultType(MIRType_Double);
         return;
     }
 
-    specialization_ = MIRType_Double;
-    setResultType(MIRType_Double);
+    specialization_ = MIRType_Int32;
+    setResultType(MIRType_Int32);
 }
 
 static inline bool
 NeedNegativeZeroCheck(MDefinition *def)
 {
     // Test if all uses have the same semantics for -0 and 0
     for (MUseIterator use = def->usesBegin(); use != def->usesEnd(); use++) {
         if (use->consumer()->isResumePoint())
--- a/js/src/ion/MIR.h
+++ b/js/src/ion/MIR.h
@@ -2686,17 +2686,17 @@ class MBinaryBitwiseInstruction
         return this;
     }
 
     MDefinition *foldsTo(bool useValueNumbers);
     MDefinition *foldUnnecessaryBitop();
     virtual MDefinition *foldIfZero(size_t operand) = 0;
     virtual MDefinition *foldIfNegOne(size_t operand) = 0;
     virtual MDefinition *foldIfEqual()  = 0;
-    virtual void infer();
+    virtual void infer(BaselineInspector *inspector, jsbytecode *pc);
 
     bool congruentTo(MDefinition *const &ins) const {
         return congruentIfOperandsEqual(ins);
     }
     AliasSet getAliasSet() const {
         if (specialization_ >= MIRType_Object)
             return AliasSet::Store(AliasSet::Any);
         return AliasSet::None();
@@ -2782,17 +2782,17 @@ class MShiftInstruction
 
   public:
     MDefinition *foldIfNegOne(size_t operand) {
         return this;
     }
     MDefinition *foldIfEqual() {
         return this;
     }
-    virtual void infer();
+    virtual void infer(BaselineInspector *inspector, jsbytecode *pc);
 };
 
 class MLsh : public MShiftInstruction
 {
     MLsh(MDefinition *left, MDefinition *right)
       : MShiftInstruction(left, right)
     { }
 
@@ -2846,17 +2846,17 @@ class MUrsh : public MShiftInstruction
     MDefinition *foldIfZero(size_t operand) {
         // 0 >>> x => 0
         if (operand == 0)
             return getOperand(0);
 
         return this;
     }
 
-    void infer();
+    void infer(BaselineInspector *inspector, jsbytecode *pc);
 
     bool canOverflow() {
         // solution is only negative when lhs < 0 and rhs & 0x1f == 0
         MDefinition *lhs = getOperand(0);
         MDefinition *rhs = getOperand(1);
 
         if (lhs->isConstant()) {
             Value lhsv = lhs->toConstant()->value();