Bug 1034665 - IonMonkey - Implement RAtan2 recover instruction. r=nbp
authorPaali Tandia <tandiap@gmail.com>
Tue, 15 Jul 2014 23:19:00 +0200
changeset 215362 de68b320435161095234343a626a0176226cdbbe
parent 215361 f41eab62f108ebed6f1edf4813528c8f446ca53e
child 215363 e6d756bc2ba72844536a9adf98796e11a0984dc1
push id3857
push userraliiev@mozilla.com
push dateTue, 02 Sep 2014 16:39:23 +0000
treeherdermozilla-beta@5638b907b505 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnbp
bugs1034665
milestone33.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 1034665 - IonMonkey - Implement RAtan2 recover instruction. r=nbp
js/src/jit-test/tests/ion/dce-with-rinstructions.js
js/src/jit/MIR.h
js/src/jit/Recover.cpp
js/src/jit/Recover.h
js/src/jsmath.cpp
js/src/jsmath.h
--- a/js/src/jit-test/tests/ion/dce-with-rinstructions.js
+++ b/js/src/jit-test/tests/ion/dce-with-rinstructions.js
@@ -532,16 +532,35 @@ function rsqrt_object(i) {
     var o = { valueOf: function () { return t; } };
     var x = Math.sqrt(o); /* computed with t == i, not 1.5 */
     t = 1.5;
     if (uceFault_sqrt_object(i) || uceFault_sqrt_object(i))
         assertEq(x, Math.sqrt(99));
     return i;
 }
 
+var uceFault_atan2_number = eval(uneval(uceFault).replace('uceFault', 'uceFault_atan2_number'));
+function ratan2_number(i) {
+    var x = Math.atan2(i, i+1);
+    if (uceFault_atan2_number(i) || uceFault_atan2_number(i))
+        assertEq(x, Math.atan2(99, 100));
+    return i;
+}
+
+var uceFault_atan2_object = eval(uneval(uceFault).replace('uceFault', 'uceFault_atan2_object'));
+function ratan2_object(i) {
+    var t = i;
+    var o = { valueOf: function () { return t; } };
+    var x = Math.atan2(o, o+1);
+    t = 1000;
+    if (uceFault_atan2_object(i) || uceFault_atan2_object(i))
+        assertEq(x, Math.atan2(i, i+1));
+    return i;
+}
+
 var uceFault_str_split = eval(uneval(uceFault).replace('uceFault', 'uceFault_str_split'))
 function rstr_split(i) {
     var x = "str01234567899876543210rts".split("" + i);
     if (uceFault_str_split(i) || uceFault_str_split(i)) {
         assertEq(x[0], "str012345678");
     }
     return i;
 }
@@ -599,16 +618,18 @@ for (i = 0; i < 100; i++) {
     rmin_object(i);
     rmax_number(i);
     rmax_object(i);
     rabs_number(i);
     rabs_object(i);
     rsqrt_number(i);
     rsqrt_float(i);
     rsqrt_object(i);
+    ratan2_number(i);
+    ratan2_object(i);
     rstr_split(i);
 }
 
 // Test that we can refer multiple time to the same recover instruction, as well
 // as chaining recover instructions.
 
 function alignedAlloc($size, $alignment) {
     var $1 = $size + 4 | 0;
--- a/js/src/jit/MIR.h
+++ b/js/src/jit/MIR.h
@@ -4079,16 +4079,21 @@ class MAtan2
 
     AliasSet getAliasSet() const {
         return AliasSet::None();
     }
 
     bool possiblyCalls() const {
         return true;
     }
+
+    bool writeRecoverData(CompactBufferWriter &writer) const;
+    bool canRecoverOnBailout() const {
+        return true;
+    }
 };
 
 // Inline implementation of Math.hypot().
 class MHypot
   : public MBinaryInstruction,
     public MixPolicy<DoublePolicy<0>, DoublePolicy<1> >
 {
     MHypot(MDefinition *y, MDefinition *x)
--- a/js/src/jit/Recover.cpp
+++ b/js/src/jit/Recover.cpp
@@ -812,16 +812,41 @@ RSqrt::recover(JSContext *cx, SnapshotIt
     if (isFloatOperation_ && !RoundFloat32(cx, result, &result))
         return false;
 
     iter.storeInstructionResult(result);
     return true;
 }
 
 bool
+MAtan2::writeRecoverData(CompactBufferWriter &writer) const
+{
+    MOZ_ASSERT(canRecoverOnBailout());
+    writer.writeUnsigned(uint32_t(RInstruction::Recover_Atan2));
+    return true;
+}
+
+RAtan2::RAtan2(CompactBufferReader &reader)
+{ }
+
+bool
+RAtan2::recover(JSContext *cx, SnapshotIterator &iter) const
+{
+    RootedValue y(cx, iter.read());
+    RootedValue x(cx, iter.read());
+    RootedValue result(cx);
+
+    if(!math_atan2_handle(cx, y, x, &result))
+        return false;
+
+    iter.storeInstructionResult(result);
+    return true;
+}
+
+bool
 MMathFunction::writeRecoverData(CompactBufferWriter &writer) const
 {
     MOZ_ASSERT(canRecoverOnBailout());
     switch (function_) {
       case Round:
         writer.writeUnsigned(uint32_t(RInstruction::Recover_Round));
         return true;
       default:
--- a/js/src/jit/Recover.h
+++ b/js/src/jit/Recover.h
@@ -38,16 +38,17 @@ namespace jit {
     _(Round)                                    \
     _(CharCodeAt)                               \
     _(FromCharCode)                             \
     _(Pow)                                      \
     _(PowHalf)                                  \
     _(MinMax)                                   \
     _(Abs)                                      \
     _(Sqrt)                                     \
+    _(Atan2)                                    \
     _(StringSplit)                              \
     _(NewObject)                                \
     _(NewDerivedTypedObject)
 
 class RResumePoint;
 class SnapshotIterator;
 
 class RInstruction
@@ -427,16 +428,28 @@ class RSqrt MOZ_FINAL : public RInstruct
 
     virtual uint32_t numOperands() const {
         return 1;
     }
 
     bool recover(JSContext *cx, SnapshotIterator &iter) const;
 };
 
+class RAtan2 MOZ_FINAL : public RInstruction
+{
+  public:
+    RINSTRUCTION_HEADER_(Atan2)
+
+    virtual uint32_t numOperands() const {
+        return 2;
+    }
+
+    bool recover(JSContext *cx, SnapshotIterator &iter) const;
+};
+
 class RStringSplit MOZ_FINAL : public RInstruction
 {
   public:
     RINSTRUCTION_HEADER_(StringSplit)
 
     virtual uint32_t numOperands() const {
         return 3;
     }
--- a/js/src/jsmath.cpp
+++ b/js/src/jsmath.cpp
@@ -265,31 +265,37 @@ js::ecmaAtan2(double y, double x)
         if (x == 0)
             return y;
     }
 #endif
     return atan2(y, x);
 }
 
 bool
+js::math_atan2_handle(JSContext *cx, HandleValue y, HandleValue x, MutableHandleValue res)
+{
+    double dy;
+    if (!ToNumber(cx, y, &dy))
+        return false;
+
+    double dx;
+    if (!ToNumber(cx, x, &dx))
+        return false;
+
+    double z = ecmaAtan2(dy, dx);
+    res.setDouble(z);
+    return true;
+}
+
+bool
 js::math_atan2(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
 
-    double y;
-    if (!ToNumber(cx, args.get(0), &y))
-        return false;
-
-    double x;
-    if (!ToNumber(cx, args.get(1), &x))
-        return false;
-
-    double z = ecmaAtan2(y, x);
-    args.rval().setDouble(z);
-    return true;
+    return math_atan2_handle(cx, args.get(0), args.get(1), args.rval());
 }
 
 double
 js::math_ceil_impl(double x)
 {
 #ifdef __APPLE__
     if (x < 0 && x > -1.0)
         return js_copysign(0, -1);
--- a/js/src/jsmath.h
+++ b/js/src/jsmath.h
@@ -236,16 +236,19 @@ math_asin(JSContext *cx, unsigned argc, 
 
 extern bool
 math_acos(JSContext *cx, unsigned argc, Value *vp);
 
 extern bool
 math_atan(JSContext *cx, unsigned argc, Value *vp);
 
 extern bool
+math_atan2_handle(JSContext *cx, HandleValue y, HandleValue x, MutableHandleValue res);
+
+extern bool
 math_atan2(JSContext *cx, unsigned argc, Value *vp);
 
 extern double
 ecmaAtan2(double x, double y);
 
 extern double
 math_atan_impl(MathCache *cache, double x);