Bug 822265 - BaselineCompiler: JSOP_NEG with double. r=jandem
authorTom Schuster <evilpies@gmail.com>
Sat, 22 Dec 2012 18:45:02 +0100
changeset 116985 38d60bed7b751906a978cca895caea19fc32e222
parent 116984 eb92059c266eb77b683c1209ed6e7a415204ae44
child 116986 d625b8b5e55a926107c72ac863c6d8b151774307
push id1423
push userevilpies@gmail.com
push dateSat, 22 Dec 2012 17:45:48 +0000
reviewersjandem
bugs822265
milestone20.0a1
Bug 822265 - BaselineCompiler: JSOP_NEG with double. r=jandem
js/src/ion/BaselineIC.cpp
js/src/ion/BaselineIC.h
--- a/js/src/ion/BaselineIC.cpp
+++ b/js/src/ion/BaselineIC.cpp
@@ -976,24 +976,37 @@ DoUnaryArithFallback(JSContext *cx, ICUn
         return false;
     }
 
     if (stub->numOptimizedStubs() >= ICUnaryArith_Fallback::MAX_OPTIMIZED_STUBS) {
         // TODO: Discard/replace stubs.
         return true;
     }
 
-    if (!val.isInt32() || !res.isInt32())
+    if (val.isInt32() && res.isInt32()) {
+        ICUnaryArith_Int32::Compiler compiler(cx, op);
+        ICStub *int32Stub = compiler.getStub(ICStubSpace::StubSpaceFor(script));
+        if (!int32Stub)
+            return false;
+        stub->addNewStub(int32Stub);
         return true;
+    }
 
-    ICUnaryArith_Int32::Compiler compiler(cx, op);
-    ICStub *int32Stub = compiler.getStub(ICStubSpace::StubSpaceFor(script));
-    if (!int32Stub)
-        return false;
-    stub->addNewStub(int32Stub);
+    if (val.isNumber() && res.isNumber() && op == JSOP_NEG) {
+        // Unlink int32 stubs, the double stub handles both cases and TI specializes for both.
+        stub->unlinkStubsWithKind(ICStub::UnaryArith_Int32);
+
+        ICUnaryArith_Double::Compiler compiler(cx, op);
+        ICStub *doubleStub = compiler.getStub(ICStubSpace::StubSpaceFor(script));
+        if (!doubleStub)
+            return false;
+        stub->addNewStub(doubleStub);
+        return true;
+    }
+
     return true;
 }
 
 typedef bool (*DoUnaryArithFallbackFn)(JSContext *, ICUnaryArith_Fallback *, HandleValue,
                                        MutableHandleValue);
 static const VMFunction DoUnaryArithFallbackInfo =
     FunctionInfo<DoUnaryArithFallbackFn>(DoUnaryArithFallback);
 
@@ -1006,16 +1019,34 @@ ICUnaryArith_Fallback::Compiler::generat
     EmitRestoreTailCallReg(masm);
 
     masm.pushValue(R0);
     masm.push(BaselineStubReg);
 
     return tailCallVM(DoUnaryArithFallbackInfo, masm);
 }
 
+bool
+ICUnaryArith_Double::Compiler::generateStubCode(MacroAssembler &masm)
+{
+    Label failure;
+    masm.ensureDouble(R0, FloatReg0, &failure);
+
+    JS_ASSERT(op == JSOP_NEG);
+    masm.negateDouble(FloatReg0);
+    masm.boxDouble(FloatReg0, R0);
+
+    EmitReturnFromIC(masm);
+
+    // Failure case - jump to next stub
+    masm.bind(&failure);
+    EmitStubGuardFailure(masm);
+    return true;
+}
+
 //
 // GetElem_Fallback
 //
 
 static bool
 DoGetElemFallback(JSContext *cx, ICGetElem_Fallback *stub, HandleValue lhs, HandleValue rhs, MutableHandleValue res)
 {
     RootedScript script(cx, GetTopIonJSScript(cx));
--- a/js/src/ion/BaselineIC.h
+++ b/js/src/ion/BaselineIC.h
@@ -286,16 +286,17 @@ class ICEntry
     _(ToNumber_Fallback)        \
                                 \
     _(BinaryArith_Fallback)     \
     _(BinaryArith_Int32)        \
     _(BinaryArith_Double)       \
                                 \
     _(UnaryArith_Fallback)      \
     _(UnaryArith_Int32)         \
+    _(UnaryArith_Double)        \
                                 \
     _(Call_Fallback)            \
     _(Call_Scripted)            \
     _(Call_Native)              \
                                 \
     _(GetElem_Fallback)         \
     _(GetElem_Dense)            \
                                 \
@@ -1327,16 +1328,44 @@ class ICBinaryArith_Int32 : public ICStu
             op_(op), allowDouble_(allowDouble) {}
 
         ICStub *getStub(ICStubSpace *space) {
             return ICBinaryArith_Int32::New(space, getStubCode());
         }
     };
 };
 
+class ICBinaryArith_Double : public ICStub
+{
+    friend class ICStubSpace;
+
+    ICBinaryArith_Double(IonCode *stubCode)
+      : ICStub(BinaryArith_Double, stubCode)
+    {}
+
+  public:
+    static inline ICBinaryArith_Double *New(ICStubSpace *space, IonCode *code) {
+        return space->allocate<ICBinaryArith_Double>(code);
+    }
+
+    class Compiler : public ICMultiStubCompiler {
+      protected:
+        bool generateStubCode(MacroAssembler &masm);
+
+      public:
+        Compiler(JSContext *cx, JSOp op)
+          : ICMultiStubCompiler(cx, ICStub::BinaryArith_Double, op)
+        {}
+
+        ICStub *getStub(ICStubSpace *space) {
+            return ICBinaryArith_Double::New(space, getStubCode());
+        }
+    };
+};
+
 // UnaryArith
 //     JSOP_BITNOT
 //     JSOP_NEG
 
 class ICUnaryArith_Fallback : public ICFallbackStub
 {
     friend class ICStubSpace;
 
@@ -1361,44 +1390,16 @@ class ICUnaryArith_Fallback : public ICF
         {}
 
         ICStub *getStub(ICStubSpace *space) {
             return ICUnaryArith_Fallback::New(space, getStubCode());
         }
     };
 };
 
-class ICBinaryArith_Double : public ICStub
-{
-    friend class ICStubSpace;
-
-    ICBinaryArith_Double(IonCode *stubCode)
-      : ICStub(BinaryArith_Double, stubCode)
-    {}
-
-  public:
-    static inline ICBinaryArith_Double *New(ICStubSpace *space, IonCode *code) {
-        return space->allocate<ICBinaryArith_Double>(code);
-    }
-
-    class Compiler : public ICMultiStubCompiler {
-      protected:
-        bool generateStubCode(MacroAssembler &masm);
-
-      public:
-        Compiler(JSContext *cx, JSOp op)
-          : ICMultiStubCompiler(cx, ICStub::BinaryArith_Double, op)
-        {}
-
-        ICStub *getStub(ICStubSpace *space) {
-            return ICBinaryArith_Double::New(space, getStubCode());
-        }
-    };
-};
-
 class ICUnaryArith_Int32 : public ICStub
 {
     friend class ICStubSpace;
 
     ICUnaryArith_Int32(IonCode *stubCode)
       : ICStub(UnaryArith_Int32, stubCode)
     {}
 
@@ -1417,16 +1418,44 @@ class ICUnaryArith_Int32 : public ICStub
         {}
 
         ICStub *getStub(ICStubSpace *space) {
             return ICUnaryArith_Int32::New(space, getStubCode());
         }
     };
 };
 
+class ICUnaryArith_Double : public ICStub
+{
+    friend class ICStubSpace;
+
+    ICUnaryArith_Double(IonCode *stubCode)
+      : ICStub(UnaryArith_Int32, stubCode)
+    {}
+
+  public:
+    static inline ICUnaryArith_Double *New(ICStubSpace *space, IonCode *code) {
+        return space->allocate<ICUnaryArith_Double>(code);
+    }
+
+    class Compiler : public ICMultiStubCompiler {
+      protected:
+        bool generateStubCode(MacroAssembler &masm);
+
+      public:
+        Compiler(JSContext *cx, JSOp op)
+          : ICMultiStubCompiler(cx, ICStub::UnaryArith_Int32, op)
+        {}
+
+        ICStub *getStub(ICStubSpace *space) {
+            return ICUnaryArith_Double::New(space, getStubCode());
+        }
+    };
+};
+
 // GetElem
 //      JSOP_GETELEM
 
 class ICGetElem_Fallback : public ICMonitoredFallbackStub
 {
     friend class ICStubSpace;
 
     ICGetElem_Fallback(IonCode *stubCode)