From 08e9171836db5fde8eb901607f62e0134ef60b34 Mon Sep 17 00:00:00 2001 From: Guillaume Maudoux Date: Sun, 22 Jun 2014 11:13:59 -0700 Subject: [PATCH] Bug 1028556 - IonMonkey: Implement Pow Recover Instruction. r=nbp --- .../tests/ion/dce-with-rinstructions.js | 21 ++++++++++++++ js/src/jit/MIR.h | 4 +++ js/src/jit/Recover.cpp | 26 +++++++++++++++++ js/src/jit/Recover.h | 13 +++++++++ js/src/jsmath.cpp | 28 +++++++++++-------- js/src/jsmath.h | 3 ++ 6 files changed, 84 insertions(+), 11 deletions(-) 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 618985ad9f4..bb695f7dea8 100644 --- a/js/src/jit-test/tests/ion/dce-with-rinstructions.js +++ b/js/src/jit-test/tests/ion/dce-with-rinstructions.js @@ -304,6 +304,25 @@ function rconcat_number(i) { return i; } +var uceFault_pow_number = eval(uneval(uceFault).replace('uceFault', 'uceFault_pow_number')); +function rpow_number(i) { + var x = Math.pow(i, 3.14159); + if (uceFault_pow_number(i) || uceFault_pow_number(i)) + assertEq(x, Math.pow(99, 3.14159)); + return i; +} + +var uceFault_pow_object = eval(uneval(uceFault).replace('uceFault', 'uceFault_pow_object')); +function rpow_object(i) { + var t = i; + var o = { valueOf: function () { return t; } }; + var x = Math.pow(o, 3.14159); /* computed with t == i, not 1.5 */ + t = 1.5; + if (uceFault_bitnot_object(i) || uceFault_bitnot_object(i)) + assertEq(x, Math.pow(99, 3.14159)); + return i; +} + for (i = 0; i < 100; i++) { rbitnot_number(i); rbitnot_object(i); @@ -336,6 +355,8 @@ for (i = 0; i < 100; i++) { rconcat_string(i); rconcat_number(i); rround_number(i); + rpow_number(i); + rpow_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 9a29f726f0e..d33b3b9f7bb 100644 --- a/js/src/jit/MIR.h +++ b/js/src/jit/MIR.h @@ -4158,6 +4158,10 @@ class MPow bool possiblyCalls() const { return true; } + bool writeRecoverData(CompactBufferWriter &writer) const; + bool canRecoverOnBailout() const { + return true; + } }; // Inline implementation of Math.pow(x, 0.5), which subtly differs from Math.sqrt(x). diff --git a/js/src/jit/Recover.cpp b/js/src/jit/Recover.cpp index a01ec5a56ea..d823d261df0 100644 --- a/js/src/jit/Recover.cpp +++ b/js/src/jit/Recover.cpp @@ -534,6 +534,32 @@ RRound::recover(JSContext *cx, SnapshotIterator &iter) const return true; } +bool +MPow::writeRecoverData(CompactBufferWriter &writer) const +{ + MOZ_ASSERT(canRecoverOnBailout()); + writer.writeUnsigned(uint32_t(RInstruction::Recover_Pow)); + return true; +} + +RPow::RPow(CompactBufferReader &reader) +{ } + +bool +RPow::recover(JSContext *cx, SnapshotIterator &iter) const +{ + RootedValue base(cx, iter.read()); + RootedValue power(cx, iter.read()); + RootedValue result(cx); + + MOZ_ASSERT(base.isNumber() && power.isNumber()); + if (!js_math_pow_handle(cx, base, power, &result)) + return false; + + iter.storeInstructionResult(result); + return true; +} + bool MNewObject::writeRecoverData(CompactBufferWriter &writer) const { diff --git a/js/src/jit/Recover.h b/js/src/jit/Recover.h index 5b02dcc19b5..fb9867704ba 100644 --- a/js/src/jit/Recover.h +++ b/js/src/jit/Recover.h @@ -32,6 +32,7 @@ namespace jit { _(Mod) \ _(Concat) \ _(Round) \ + _(Pow) \ _(NewObject) \ _(NewDerivedTypedObject) @@ -281,6 +282,18 @@ class RRound MOZ_FINAL : public RInstruction bool recover(JSContext *cx, SnapshotIterator &iter) const; }; +class RPow MOZ_FINAL : public RInstruction +{ + public: + RINSTRUCTION_HEADER_(Pow) + + virtual uint32_t numOperands() const { + return 2; + } + + bool recover(JSContext *cx, SnapshotIterator &iter) const; +}; + class RNewObject MOZ_FINAL : public RInstruction { private: diff --git a/js/src/jsmath.cpp b/js/src/jsmath.cpp index 4e0de96b31a..d7714ad3fa3 100644 --- a/js/src/jsmath.cpp +++ b/js/src/jsmath.cpp @@ -662,22 +662,28 @@ js::ecmaPow(double x, double y) #if defined(_MSC_VER) # pragma optimize("g", off) #endif +bool +js_math_pow_handle(JSContext *cx, HandleValue base, HandleValue power, MutableHandleValue result) +{ + double x; + if (!ToNumber(cx, base, &x)) + return false; + + double y; + if (!ToNumber(cx, power, &y)) + return false; + + double z = ecmaPow(x, y); + result.setNumber(z); + return true; +} + bool js_math_pow(JSContext *cx, unsigned argc, Value *vp) { CallArgs args = CallArgsFromVp(argc, vp); - double x; - if (!ToNumber(cx, args.get(0), &x)) - return false; - - double y; - if (!ToNumber(cx, args.get(1), &y)) - return false; - - double z = ecmaPow(x, y); - args.rval().setNumber(z); - return true; + return js_math_pow_handle(cx, args.get(0), args.get(1), args.rval()); } #if defined(_MSC_VER) # pragma optimize("", on) diff --git a/js/src/jsmath.h b/js/src/jsmath.h index e192ed8fc9b..c2cca22bbc4 100644 --- a/js/src/jsmath.h +++ b/js/src/jsmath.h @@ -110,6 +110,9 @@ js_math_min(JSContext *cx, unsigned argc, js::Value *vp); extern bool js_math_sqrt(JSContext *cx, unsigned argc, js::Value *vp); +extern bool +js_math_pow_handle(JSContext *cx, js::HandleValue base, js::HandleValue power, js::MutableHandleValue result); + extern bool js_math_pow(JSContext *cx, unsigned argc, js::Value *vp);