Bug 1024896 - IonMonkey: Implement Round Recover Instruction. r=nbp
authorGuillaume Turri <guillaume.turri@gmail.com>
Sun, 22 Jun 2014 11:13:58 -0700
changeset 189962 efaa172c0ee49833d298df1ab6f1af5f779dc236
parent 189961 35c527229cdba117043ea9878c7399773dee8902
child 189963 5bf08ded742621c580c2e0e0922f3b4ba6887f71
push id26999
push userryanvm@gmail.com
push dateMon, 23 Jun 2014 14:42:40 +0000
treeherdermozilla-central@4a7f4ed3f08b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnbp
bugs1024896
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 1024896 - IonMonkey: Implement Round 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
@@ -158,16 +158,24 @@ function radd_float(i) {
     var t = Math.fround(1/3);
     var fi = Math.fround(i);
     var x = Math.fround(Math.fround(Math.fround(Math.fround(t + fi) + t) + fi) + t);
     if (uceFault_add_float(i) || uceFault_add_float(i))
         assertEq(x, 199); /* != 199.00000002980232 (when computed with double additions) */
     return i;
 }
 
+var uceFault_round = eval(uneval(uceFault).replace('uceFault', 'uceFault_round'));
+function rround_number(i) {
+    var x = Math.round(i + 1.4);
+    if (uceFault_round(i) || uceFault_round(i))
+        assertEq(x, 100); /* = i + 1*/
+    return i;
+}
+
 var uceFault_add_object = eval(uneval(uceFault).replace('uceFault', 'uceFault_add_object'));
 function radd_object(i) {
     var t = i;
     var o = { valueOf: function () { return t; } };
     var x = o + i; /* computed with t == i, not 1000 */
     t = 1000;
     if (uceFault_add_object(i) || uceFault_add_object(i))
         assertEq(x, 198);
@@ -322,16 +330,17 @@ for (i = 0; i < 100; i++) {
     rmul_object(i);
     rdiv_number(i);
     rdiv_float(i);
     rdiv_object(i);
     rmod_number(i);
     rmod_object(i);
     rconcat_string(i);
     rconcat_number(i);
+    rround_number(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;
     var $2 = $alignment - 1 | 0;
--- a/js/src/jit/MIR.h
+++ b/js/src/jit/MIR.h
@@ -9018,16 +9018,21 @@ class MRound
 #ifdef DEBUG
     bool isConsistentFloat32Use(MUse *use) const {
         return true;
     }
 #endif
     bool congruentTo(const MDefinition *ins) const {
         return congruentIfOperandsEqual(ins);
     }
+
+    bool writeRecoverData(CompactBufferWriter &writer) const;
+    bool canRecoverOnBailout() const {
+        return true;
+    }
 };
 
 class MIteratorStart
   : public MUnaryInstruction,
     public SingleObjectPolicy
 {
     uint8_t flags_;
 
--- a/js/src/jit/Recover.cpp
+++ b/js/src/jit/Recover.cpp
@@ -505,16 +505,41 @@ RMod::recover(JSContext *cx, SnapshotIte
 	if (!js::ModValues(cx, &lhs, &rhs, &result))
 		return false;
 
 	iter.storeInstructionResult(result);
 	return true;
 }
 
 bool
+MRound::writeRecoverData(CompactBufferWriter &writer) const
+{
+    MOZ_ASSERT(canRecoverOnBailout());
+    writer.writeUnsigned(uint32_t(RInstruction::Recover_Round));
+    return true;
+}
+
+RRound::RRound(CompactBufferReader &reader)
+{}
+
+bool
+RRound::recover(JSContext *cx, SnapshotIterator &iter) const
+{
+    RootedValue arg(cx, iter.read());
+    RootedValue result(cx);
+
+    MOZ_ASSERT(!arg.isObject());
+    if(!js::math_round_handle(cx, arg, &result))
+        return false;
+
+    iter.storeInstructionResult(result);
+    return true;
+}
+
+bool
 MNewObject::writeRecoverData(CompactBufferWriter &writer) const
 {
     MOZ_ASSERT(canRecoverOnBailout());
     writer.writeUnsigned(uint32_t(RInstruction::Recover_NewObject));
     writer.writeByte(templateObjectIsClassPrototype_);
     return true;
 }
 
--- a/js/src/jit/Recover.h
+++ b/js/src/jit/Recover.h
@@ -26,16 +26,17 @@ namespace jit {
     _(Rsh)                                      \
     _(Ursh)                                     \
     _(Add)                                      \
     _(Sub)                                      \
     _(Mul)                                      \
     _(Div)                                      \
     _(Mod)                                      \
     _(Concat)                                   \
+    _(Round)                                    \
     _(NewObject)                                \
     _(NewDerivedTypedObject)
 
 class RResumePoint;
 class SnapshotIterator;
 
 class RInstruction
 {
@@ -263,16 +264,28 @@ class RConcat MOZ_FINAL : public RInstru
 
     virtual uint32_t numOperands() const {
         return 2;
     }
 
     bool recover(JSContext *cx, SnapshotIterator &iter) const;
 };
 
+class RRound MOZ_FINAL : public RInstruction
+{
+  public:
+    RINSTRUCTION_HEADER_(Round)
+
+    virtual uint32_t numOperands() const {
+        return 1;
+    }
+
+    bool recover(JSContext *cx, SnapshotIterator &iter) const;
+};
+
 class RNewObject MOZ_FINAL : public RInstruction
 {
   private:
     bool templateObjectIsClassPrototype_;
 
   public:
     RINSTRUCTION_HEADER_(NewObject)
 
--- a/js/src/jsmath.cpp
+++ b/js/src/jsmath.cpp
@@ -771,16 +771,28 @@ bool
 js_math_random(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     double z = random_nextDouble(cx);
     args.rval().setDouble(z);
     return true;
 }
 
+bool
+js::math_round_handle(JSContext *cx, HandleValue arg, MutableHandleValue res)
+{
+    double d;
+    if (!ToNumber(cx, arg, &d))
+        return false;
+
+    d = math_round_impl(d);
+    res.setNumber(d);
+    return true;
+}
+
 double
 js::math_round_impl(double x)
 {
     int32_t ignored;
     if (NumberIsInt32(x, &ignored))
         return x;
 
     /* Some numbers are so big that adding 0.5 would give the wrong number. */
@@ -809,23 +821,17 @@ js::math_round(JSContext *cx, unsigned a
 {
     CallArgs args = CallArgsFromVp(argc, vp);
 
     if (args.length() == 0) {
         args.rval().setNaN();
         return true;
     }
 
-    double x;
-    if (!ToNumber(cx, args[0], &x))
-        return false;
-
-    double z = math_round_impl(x);
-    args.rval().setNumber(z);
-    return true;
+    return js::math_round_handle(cx, args[0], args.rval());
 }
 
 double
 js::math_sin_impl(MathCache *cache, double x)
 {
     return cache->lookup(sin, x, MathCache::Sin);
 }
 
--- a/js/src/jsmath.h
+++ b/js/src/jsmath.h
@@ -270,16 +270,19 @@ math_clz32(JSContext *cx, unsigned argc,
 
 extern bool
 math_floor(JSContext *cx, unsigned argc, Value *vp);
 
 extern double
 math_floor_impl(double x);
 
 extern bool
+math_round_handle(JSContext *cx, HandleValue arg, MutableHandleValue res);
+
+extern bool
 math_round(JSContext *cx, unsigned argc, Value *vp);
 
 extern double
 math_round_impl(double x);
 
 extern float
 math_roundf_impl(float x);