From 503e9d7029a3dffbc9f6c93c503952efbfef0251 Mon Sep 17 00:00:00 2001 From: Sankha Narayan Guria Date: Mon, 7 Jul 2014 15:02:40 +0200 Subject: [PATCH] Bug 1030699 - Sqrt Recover Instruction. r=bbouvier --- .../tests/ion/dce-with-rinstructions.js | 30 +++++++++++++++++ js/src/jit/MIR.h | 5 +++ js/src/jit/Recover.cpp | 33 +++++++++++++++++++ js/src/jit/Recover.h | 16 +++++++++ js/src/jsmath.cpp | 28 +++++++++------- js/src/jsmath.h | 3 ++ 6 files changed, 104 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 88ddd408c26..f0844ec98c6 100644 --- a/js/src/jit-test/tests/ion/dce-with-rinstructions.js +++ b/js/src/jit-test/tests/ion/dce-with-rinstructions.js @@ -510,6 +510,33 @@ function rabs_object(i) { return i; } +var uceFault_sqrt_number = eval(uneval(uceFault).replace('uceFault', 'uceFault_sqrt_number')); +function rsqrt_number(i) { + var x = Math.sqrt(i); + if (uceFault_sqrt_number(i) || uceFault_sqrt_number(i)) + assertEq(x, Math.sqrt(99)); + return i; +} + +var uceFault_sqrt_float = eval(uneval(uceFault).replace('uceFault', 'uceFault_sqrt_float')); +function rsqrt_float(i) { + var x = Math.fround(Math.sqrt(Math.fround(i))); + if (uceFault_sqrt_float(i) || uceFault_sqrt_float(i)) + assertEq(x, Math.fround(Math.sqrt(Math.fround(99)))); /* != 9.9498743710662 (when computed with double sqrt) */ + return i; +} + +var uceFault_sqrt_object = eval(uneval(uceFault).replace('uceFault', 'uceFault_sqrt_object')); +function rsqrt_object(i) { + var t = i; + var o = { valueOf: function () { return t; } }; + var x = Math.sqrt(o); /* computed with t == i, not 1.5 */ + t = 1.5; + if (uceFault_sqrt_object(i) || uceFault_sqrt_object(i)) + assertEq(x, Math.sqrt(99)); + return i; +} + for (i = 0; i < 100; i++) { rbitnot_number(i); rbitnot_object(i); @@ -565,6 +592,9 @@ for (i = 0; i < 100; i++) { rmax_object(i); rabs_number(i); rabs_object(i); + rsqrt_number(i); + rsqrt_float(i); + rsqrt_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 c1ab4192c23..84a614c252e 100644 --- a/js/src/jit/MIR.h +++ b/js/src/jit/MIR.h @@ -4032,6 +4032,11 @@ class MSqrt bool isFloat32Commutative() const { return true; } void trySpecializeFloat32(TempAllocator &alloc); + + bool writeRecoverData(CompactBufferWriter &writer) const; + bool canRecoverOnBailout() const { + return true; + } }; // Inline implementation of atan2 (arctangent of y/x). diff --git a/js/src/jit/Recover.cpp b/js/src/jit/Recover.cpp index f426fefb6fc..153108dee51 100644 --- a/js/src/jit/Recover.cpp +++ b/js/src/jit/Recover.cpp @@ -783,6 +783,39 @@ RAbs::recover(JSContext *cx, SnapshotIterator &iter) const return true; } +bool +MSqrt::writeRecoverData(CompactBufferWriter &writer) const +{ + MOZ_ASSERT(canRecoverOnBailout()); + writer.writeUnsigned(uint32_t(RInstruction::Recover_Sqrt)); + writer.writeByte(type() == MIRType_Float32); + return true; +} + +RSqrt::RSqrt(CompactBufferReader &reader) +{ + isFloatOperation_ = reader.readByte(); +} + +bool +RSqrt::recover(JSContext *cx, SnapshotIterator &iter) const +{ + RootedValue num(cx, iter.read()); + RootedValue result(cx); + + MOZ_ASSERT(num.isNumber()); + if (!math_sqrt_handle(cx, num, &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 MMathFunction::writeRecoverData(CompactBufferWriter &writer) const { diff --git a/js/src/jit/Recover.h b/js/src/jit/Recover.h index 10bdbdf156a..5e7ed983088 100644 --- a/js/src/jit/Recover.h +++ b/js/src/jit/Recover.h @@ -42,6 +42,7 @@ namespace jit { _(PowHalf) \ _(MinMax) \ _(Abs) \ + _(Sqrt) \ _(NewObject) \ _(NewDerivedTypedObject) @@ -415,6 +416,21 @@ class RAbs MOZ_FINAL : public RInstruction bool recover(JSContext *cx, SnapshotIterator &iter) const; }; +class RSqrt MOZ_FINAL : public RInstruction +{ + private: + bool isFloatOperation_; + + public: + RINSTRUCTION_HEADER_(Sqrt) + + virtual uint32_t numOperands() const { + return 1; + } + + 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 6502c4a67a5..cbfa90d1c12 100644 --- a/js/src/jsmath.cpp +++ b/js/src/jsmath.cpp @@ -916,6 +916,22 @@ js::math_sin(JSContext *cx, unsigned argc, Value *vp) return true; } +bool +js::math_sqrt_handle(JSContext *cx, HandleValue number, MutableHandleValue result) +{ + double x; + if (!ToNumber(cx, number, &x)) + return false; + + MathCache *mathCache = cx->runtime()->getMathCache(cx); + if (!mathCache) + return false; + + double z = mathCache->lookup(sqrt, x, MathCache::Sqrt); + result.setDouble(z); + return true; +} + bool js_math_sqrt(JSContext *cx, unsigned argc, Value *vp) { @@ -926,17 +942,7 @@ js_math_sqrt(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 = mathCache->lookup(sqrt, x, MathCache::Sqrt); - args.rval().setDouble(z); - return true; + return math_sqrt_handle(cx, args[0], args.rval()); } double diff --git a/js/src/jsmath.h b/js/src/jsmath.h index ba9b726aa8d..0f98c2c504a 100644 --- a/js/src/jsmath.h +++ b/js/src/jsmath.h @@ -126,6 +126,9 @@ js_minmax_impl(JSContext *cx, bool max, js::HandleValue a, js::HandleValue b, namespace js { +extern bool +math_sqrt_handle(JSContext *cx, js::HandleValue number, js::MutableHandleValue result); + extern bool math_imul(JSContext *cx, unsigned argc, js::Value *vp);