diff --git a/js/src/jit-test/tests/ion/dce-with-rinstructions.js b/js/src/jit-test/tests/ion/dce-with-rinstructions.js index fd1a1bc4da9..7e96cabaa19 100644 --- a/js/src/jit-test/tests/ion/dce-with-rinstructions.js +++ b/js/src/jit-test/tests/ion/dce-with-rinstructions.js @@ -192,6 +192,35 @@ function rsub_object(i) { 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; @@ -231,6 +260,9 @@ for (i = 0; i < 100; 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); } diff --git a/js/src/jit/MIR.h b/js/src/jit/MIR.h index 771b5274838..54b14d1a7b4 100644 --- a/js/src/jit/MIR.h +++ b/js/src/jit/MIR.h @@ -4343,7 +4343,7 @@ class MSub : public MBinaryArithInstruction bool writeRecoverData(CompactBufferWriter &writer) const; bool canRecoverOnBailout() const { - return specialization_ != MIRType_None; + return specialization_ < MIRType_Object; } }; @@ -4440,6 +4440,11 @@ class MMul : public MBinaryArithInstruction 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 diff --git a/js/src/jit/Recover.cpp b/js/src/jit/Recover.cpp index 7c331794ee6..4061b0db39e 100644 --- a/js/src/jit/Recover.cpp +++ b/js/src/jit/Recover.cpp @@ -364,6 +364,38 @@ RSub::recover(JSContext *cx, SnapshotIterator &iter) const 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 diff --git a/js/src/jit/Recover.h b/js/src/jit/Recover.h index 79b46e96192..c5354a0e032 100644 --- a/js/src/jit/Recover.h +++ b/js/src/jit/Recover.h @@ -26,6 +26,7 @@ namespace jit { _(Ursh) \ _(Add) \ _(Sub) \ + _(Mul) \ _(Mod) \ _(NewObject) \ _(NewDerivedTypedObject) @@ -210,6 +211,21 @@ class RMod MOZ_FINAL : public RInstruction 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: