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 460c45e71d1..421205ccf21 100644 --- a/js/src/jit-test/tests/ion/dce-with-rinstructions.js +++ b/js/src/jit-test/tests/ion/dce-with-rinstructions.js @@ -1050,6 +1050,25 @@ function rhypot_object(i) { return i; } +var uceFault_sin_number = eval(uneval(uceFault).replace('uceFault', 'uceFault_sin_number')); +function rsin_number(i) { + var x = Math.sin(i); + if (uceFault_sin_number(i) || uceFault_sin_number(i)) + assertEq(x, Math.sin(i)); + return i; +} + +var uceFault_sin_object = eval(uneval(uceFault).replace('uceFault', 'uceFault_sin_object')); +function rsin_object(i) { + var t = i; + var o = { valueOf: function() { return t; } }; + var x = Math.sin(o); + t = 777; + if (uceFault_sin_object(i) || uceFault_sin_object(i)) + assertEq(x, Math.sin(i)); + return i; +} + for (i = 0; i < 100; i++) { rbitnot_number(i); rbitnot_object(i); @@ -1150,6 +1169,8 @@ for (i = 0; i < 100; i++) { rtofloat32_object(i); rhypot_number(i); rhypot_object(i); + rsin_number(i); + rsin_object(i); } // Test that we can refer multiple time to the same recover instruction, as well diff --git a/js/src/jit/MIR.h b/js/src/jit/MIR.h index 29bb50c4390..443e1b1b3e8 100644 --- a/js/src/jit/MIR.h +++ b/js/src/jit/MIR.h @@ -5590,7 +5590,13 @@ class MMathFunction void computeRange(TempAllocator &alloc); bool writeRecoverData(CompactBufferWriter &writer) const; bool canRecoverOnBailout() const { - return function_ == Round; + switch(function_) { + case Sin: + case Round: + return true; + default: + return false; + } } ALLOW_CLONE(MMathFunction) diff --git a/js/src/jit/Recover.cpp b/js/src/jit/Recover.cpp index 85eea099f1d..9bcadd8a911 100644 --- a/js/src/jit/Recover.cpp +++ b/js/src/jit/Recover.cpp @@ -884,6 +884,34 @@ MMathFunction::writeRecoverData(CompactBufferWriter &writer) const case Round: writer.writeUnsigned(uint32_t(RInstruction::Recover_Round)); return true; + case Sin: + writer.writeUnsigned(uint32_t(RInstruction::Recover_MathFunction)); + writer.writeByte(function_); + return true; + default: + MOZ_CRASH("Unknown math function."); + } +} + +RMathFunction::RMathFunction(CompactBufferReader &reader) +{ + function_ = reader.readByte(); +} + +bool +RMathFunction::recover(JSContext *cx, SnapshotIterator &iter) const +{ + switch (function_) { + case MMathFunction::Sin: { + RootedValue arg(cx, iter.read()); + RootedValue result(cx); + + if (!js::math_sin_handle(cx, arg, &result)) + return false; + + iter.storeInstructionResult(result); + return true; + } default: MOZ_CRASH("Unknown math function."); } diff --git a/js/src/jit/Recover.h b/js/src/jit/Recover.h index 159c1536485..46c80e607b0 100644 --- a/js/src/jit/Recover.h +++ b/js/src/jit/Recover.h @@ -47,6 +47,7 @@ namespace jit { _(Sqrt) \ _(Atan2) \ _(Hypot) \ + _(MathFunction) \ _(StringSplit) \ _(RegExpExec) \ _(RegExpTest) \ @@ -471,6 +472,21 @@ class RHypot MOZ_FINAL : public RInstruction bool recover(JSContext *cx, SnapshotIterator &iter) const; }; +class RMathFunction MOZ_FINAL : public RInstruction +{ + private: + uint8_t function_; + + public: + RINSTRUCTION_HEADER_(MathFunction) + + virtual uint32_t numOperands() const { + return 1; + } + + bool recover(JSContext *cx, SnapshotIterator &iter) const; +}; + class RStringSplit MOZ_FINAL : public RInstruction { public: diff --git a/js/src/jsmath.cpp b/js/src/jsmath.cpp index 377053f4da6..7ed41ee6760 100644 --- a/js/src/jsmath.cpp +++ b/js/src/jsmath.cpp @@ -893,6 +893,22 @@ js::math_sin_uncached(double x) return sin(x); } +bool +js::math_sin_handle(JSContext *cx, HandleValue val, MutableHandleValue res) +{ + double in; + if (!ToNumber(cx, val, &in)) + return false; + + MathCache *mathCache = cx->runtime()->getMathCache(cx); + if (!mathCache) + return false; + + double out = math_sin_impl(mathCache, in); + res.setDouble(out); + return true; +} + bool js::math_sin(JSContext *cx, unsigned argc, Value *vp) { @@ -903,17 +919,7 @@ js::math_sin(JSContext *cx, unsigned argc, Value *vp) return true; } - double x; - if (!ToNumber(cx, args[0], &x)) - return false; - - MathCache *mathCache = cx->runtime()->getMathCache(cx); - if (!mathCache) - return false; - - double z = math_sin_impl(mathCache, x); - args.rval().setDouble(z); - return true; + return math_sin_handle(cx, args[0], args.rval()); } bool diff --git a/js/src/jsmath.h b/js/src/jsmath.h index 5aa427ead37..f22a7d5d7c9 100644 --- a/js/src/jsmath.h +++ b/js/src/jsmath.h @@ -179,6 +179,9 @@ math_sin_impl(MathCache *cache, double x); extern double math_sin_uncached(double x); +extern bool +math_sin_handle(JSContext *cx, HandleValue val, MutableHandleValue res); + extern bool math_cos(JSContext *cx, unsigned argc, js::Value *vp);