Bug 1011540 - Implement Mul Recover Instruction. r=nbp
authorSankha Narayan Guria <sankha93@gmail.com>
Fri, 06 Jun 2014 17:29:45 +0200
changeset 206701 9e074affd0a3b6d80bae1905d028c291ccf69fee
parent 206700 650ea68d7ef295ae847d705919d3c494964acd65
child 206702 4fa4ba576464ed135b13b203dec391bdb85ea770
push id3741
push userasasaki@mozilla.com
push dateMon, 21 Jul 2014 20:25:18 +0000
treeherdermozilla-beta@4d6f46f5af68 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnbp
bugs1011540
milestone32.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 1011540 - Implement Mul 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
--- a/js/src/jit-test/tests/ion/dce-with-rinstructions.js
+++ b/js/src/jit-test/tests/ion/dce-with-rinstructions.js
@@ -187,16 +187,45 @@ function rsub_object(i) {
     var o = { valueOf: function () { return t; } };
     var x = o - i; /* computed with t == i, not 1000 */
     t = 1000;
     if (uceFault_sub_object(i) || uceFault_sub_object(i))
         assertEq(x, 0);
     return i;
 }
 
+var uceFault_mul_number = eval(uneval(uceFault).replace('uceFault', 'uceFault_mul_number'));
+function rmul_number(i) {
+    var x = 2 * i;
+    if (uceFault_mul_number(i) || uceFault_mul_number(i))
+        assertEq(x, 198  /* = 1 * 99 */);
+    return i;
+}
+
+var uceFault_mul_float = eval(uneval(uceFault).replace('uceFault', 'uceFault_mul_float'));
+function rmul_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_mul_float(i) || uceFault_mul_float(i))
+        assertEq(x, 363); /* != 363.0000324547301 (when computed with double multiplications) */
+    return i;
+}
+
+var uceFault_mul_object = eval(uneval(uceFault).replace('uceFault', 'uceFault_mul_object'));
+function rmul_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_mul_object(i) || uceFault_mul_object(i))
+        assertEq(x, 9801);
+    return i;
+}
+
 var uceFault_mod_number = eval(uneval(uceFault).replace('uceFault', 'uceFault_mod_number'));
 function rmod_number(i) {
     var x = i % 98;
     if (uceFault_mod_number(i) || uceFault_mod_number(i))
         assertEq(x, 1); /* 99 % 98 = 1 */
     return i;
 }
 
@@ -226,16 +255,19 @@ for (i = 0; i < 100; i++) {
     rursh_object(i);
     radd_number(i);
     radd_float(i);
     radd_string(i);
     radd_object(i);
     rsub_number(i);
     rsub_float(i);
     rsub_object(i);
+    rmul_number(i);
+    rmul_float(i);
+    rmul_object(i);
     rmod_number(i);
     rmod_object(i);
 }
 
 // Test that we can refer multiple time to the same recover instruction, as well
 // as chaining recover instructions.
 
 function alignedAlloc($size, $alignment) {
--- a/js/src/jit/MIR.h
+++ b/js/src/jit/MIR.h
@@ -4338,17 +4338,17 @@ class MSub : public MBinaryArithInstruct
 
     bool fallible() const;
     void computeRange(TempAllocator &alloc);
     bool truncate(TruncateKind kind);
     TruncateKind operandTruncateKind(size_t index) const;
 
     bool writeRecoverData(CompactBufferWriter &writer) const;
     bool canRecoverOnBailout() const {
-        return specialization_ != MIRType_None;
+        return specialization_ < MIRType_Object;
     }
 };
 
 class MMul : public MBinaryArithInstruction
 {
   public:
     enum Mode {
         Normal,
@@ -4435,16 +4435,21 @@ class MMul : public MBinaryArithInstruct
 
     bool isFloat32Commutative() const { return true; }
 
     void computeRange(TempAllocator &alloc);
     bool truncate(TruncateKind kind);
     TruncateKind operandTruncateKind(size_t index) const;
 
     Mode mode() const { return mode_; }
+
+    bool writeRecoverData(CompactBufferWriter &writer) const;
+    bool canRecoverOnBailout() const {
+        return specialization_ < MIRType_Object;
+    }
 };
 
 class MDiv : public MBinaryArithInstruction
 {
     bool canBeNegativeZero_;
     bool canBeNegativeOverflow_;
     bool canBeDivideByZero_;
     bool canBeNegativeDividend_;
--- a/js/src/jit/Recover.cpp
+++ b/js/src/jit/Recover.cpp
@@ -359,16 +359,48 @@ RSub::recover(JSContext *cx, SnapshotIte
     // rounded to a Float32.
     if (isFloatOperation_ && !RoundFloat32(cx, result, &result))
         return false;
 
     iter.storeInstructionResult(result);
     return true;
 }
 
+bool
+MMul::writeRecoverData(CompactBufferWriter &writer) const
+{
+    MOZ_ASSERT(canRecoverOnBailout());
+    writer.writeUnsigned(uint32_t(RInstruction::Recover_Mul));
+    writer.writeByte(specialization_ == MIRType_Float32);
+    return true;
+}
+
+RMul::RMul(CompactBufferReader &reader)
+{
+    isFloatOperation_ = reader.readByte();
+}
+
+bool
+RMul::recover(JSContext *cx, SnapshotIterator &iter) const
+{
+    RootedValue lhs(cx, iter.read());
+    RootedValue rhs(cx, iter.read());
+    RootedValue result(cx);
+
+    if (!js::MulValues(cx, &lhs, &rhs, &result))
+        return false;
+
+    // MIRType_Float32 is a specialization embedding the fact that the result is
+    // rounded to a Float32.
+    if (isFloatOperation_ && !RoundFloat32(cx, result, &result))
+        return false;
+
+    iter.storeInstructionResult(result);
+    return true;
+}
 
 bool
 MMod::writeRecoverData(CompactBufferWriter &writer) const
 {
 	MOZ_ASSERT(canRecoverOnBailout());
 	writer.writeUnsigned(uint32_t(RInstruction::Recover_Mod));
 	return true;
 }
--- a/js/src/jit/Recover.h
+++ b/js/src/jit/Recover.h
@@ -21,16 +21,17 @@ namespace jit {
     _(BitNot)                                   \
     _(BitOr)                                    \
     _(BitXor)                                   \
     _(Lsh)                                      \
     _(Rsh)                                      \
     _(Ursh)                                     \
     _(Add)                                      \
     _(Sub)                                      \
+    _(Mul)                                      \
     _(Mod)                                      \
     _(NewObject)                                \
     _(NewDerivedTypedObject)
 
 class RResumePoint;
 class SnapshotIterator;
 
 class RInstruction
@@ -205,16 +206,31 @@ class RMod MOZ_FINAL : public RInstructi
 
     virtual uint32_t numOperands() const {
         return 2;
     }
 
     bool recover(JSContext *cx, SnapshotIterator &iter) const;
 };
 
+class RMul MOZ_FINAL : public RInstruction
+{
+  private:
+    bool isFloatOperation_;
+
+  public:
+    RINSTRUCTION_HEADER_(Mul)
+
+    virtual uint32_t numOperands() const {
+        return 2;
+    }
+
+    bool recover(JSContext *cx, SnapshotIterator &iter) const;
+};
+
 class RNewObject MOZ_FINAL : public RInstruction
 {
   private:
     bool templateObjectIsClassPrototype_;
 
   public:
     RINSTRUCTION_HEADER_(NewObject)