Bug 1011539 - Implement Sub Recover instruction. r=nbp
authorSankha Narayan Guria <sankha93@gmail.com>
Mon, 26 May 2014 21:21:27 +0200
changeset 185245 ca90df6c5130310a1225dbb08c62f841b3e26fe0
parent 185244 9adf12b93052380b8684dcc38c00967184b26660
child 185330 a32b415a167ad4b0571c1a722e5cd0d0704df071
push id44054
push userryanvm@gmail.com
push dateWed, 28 May 2014 12:21:59 +0000
treeherdermozilla-inbound@ca90df6c5130 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnbp
bugs1011539
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 1011539 - Implement Sub 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
@@ -158,16 +158,45 @@ function radd_object(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);
     return i;
 }
 
+var uceFault_sub_number = eval(uneval(uceFault).replace('uceFault', 'uceFault_sub_number'));
+function rsub_number(i) {
+    var x = 1 - i;
+    if (uceFault_sub_number(i) || uceFault_sub_number(i))
+        assertEq(x, -98  /* = 1 - 99 */);
+    return i;
+}
+
+var uceFault_sub_float = eval(uneval(uceFault).replace('uceFault', 'uceFault_sub_float'));
+function rsub_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_sub_float(i) || uceFault_sub_float(i))
+        assertEq(x, -198.3333282470703); /* != -198.33333334326744 (when computed with double subtractions) */
+    return i;
+}
+
+var uceFault_sub_object = eval(uneval(uceFault).replace('uceFault', 'uceFault_sub_object'));
+function rsub_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_sub_object(i) || uceFault_sub_object(i))
+        assertEq(x, 0);
+    return i;
+}
+
 for (i = 0; i < 100; i++) {
     rbitnot_number(i);
     rbitnot_object(i);
     rbitor_number(i);
     rbitor_object(i);
     rbitxor_number(i);
     rbitxor_object(i);
     rlsh_number(i);
@@ -175,16 +204,19 @@ for (i = 0; i < 100; i++) {
     rrsh_number(i);
     rrsh_object(i);
     rursh_number(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);
 }
 
 // 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
@@ -4295,16 +4295,21 @@ class MSub : public MBinaryArithInstruct
     }
 
     bool isFloat32Commutative() const { return true; }
 
     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;
+    }
 };
 
 class MMul : public MBinaryArithInstruction
 {
   public:
     enum Mode {
         Normal,
         Integer
--- a/js/src/jit/Recover.cpp
+++ b/js/src/jit/Recover.cpp
@@ -326,16 +326,50 @@ RAdd::recover(JSContext *cx, SnapshotIte
     if (isFloatOperation_ && !RoundFloat32(cx, result, &result))
         return false;
 
     iter.storeInstructionResult(result);
     return true;
 }
 
 bool
+MSub::writeRecoverData(CompactBufferWriter &writer) const
+{
+    MOZ_ASSERT(canRecoverOnBailout());
+    writer.writeUnsigned(uint32_t(RInstruction::Recover_Sub));
+    writer.writeByte(specialization_ == MIRType_Float32);
+    return true;
+}
+
+RSub::RSub(CompactBufferReader &reader)
+{
+    isFloatOperation_ = reader.readByte();
+}
+
+bool
+RSub::recover(JSContext *cx, SnapshotIterator &iter) const
+{
+    RootedValue lhs(cx, iter.read());
+    RootedValue rhs(cx, iter.read());
+    RootedValue result(cx);
+
+    MOZ_ASSERT(!lhs.isObject() && !rhs.isObject());
+    if (!js::SubValues(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
 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
@@ -20,16 +20,17 @@ namespace jit {
     _(ResumePoint)                              \
     _(BitNot)                                   \
     _(BitOr)                                    \
     _(BitXor)                                   \
     _(Lsh)                                      \
     _(Rsh)                                      \
     _(Ursh)                                     \
     _(Add)                                      \
+    _(Sub)                                      \
     _(NewObject)                                \
     _(NewDerivedTypedObject)
 
 class RResumePoint;
 class SnapshotIterator;
 
 class RInstruction
 {
@@ -176,16 +177,31 @@ class RAdd MOZ_FINAL : public RInstructi
 
     virtual uint32_t numOperands() const {
         return 2;
     }
 
     bool recover(JSContext *cx, SnapshotIterator &iter) const;
 };
 
+class RSub MOZ_FINAL : public RInstruction
+{
+  private:
+    bool isFloatOperation_;
+
+  public:
+    RINSTRUCTION_HEADER_(Sub)
+
+    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)