From 1f0542d508af6cc07452432e9376c9576abb91a1 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Thu, 22 Aug 2013 16:33:35 +0200 Subject: [PATCH] Bug 901000: Added uncached variants of Math functions for PJS (r=nmatsakis). --- js/src/jit/CodeGenerator.cpp | 46 +++--- js/src/jit/MIR.h | 2 + js/src/jit/ParallelSafetyAnalysis.cpp | 8 +- js/src/jsmath.cpp | 213 ++++++++++++++++++++++---- js/src/jsmath.h | 66 ++++++++ 5 files changed, 287 insertions(+), 48 deletions(-) diff --git a/js/src/jit/CodeGenerator.cpp b/js/src/jit/CodeGenerator.cpp index 4045fcf2448..8d24ea4adfc 100644 --- a/js/src/jit/CodeGenerator.cpp +++ b/js/src/jit/CodeGenerator.cpp @@ -3628,75 +3628,79 @@ CodeGenerator::visitMathFunctionD(LMathFunctionD *ins) masm.passABIArg(temp); masm.passABIArg(input); +# define MAYBE_CACHED(fcn) (mathCache ? (void*)fcn ## _impl : (void*)fcn ## _uncached) + void *funptr = NULL; switch (ins->mir()->function()) { case MMathFunction::Log: - funptr = JS_FUNC_TO_DATA_PTR(void *, js::math_log_impl); + funptr = JS_FUNC_TO_DATA_PTR(void *, MAYBE_CACHED(js::math_log)); break; case MMathFunction::Sin: - funptr = JS_FUNC_TO_DATA_PTR(void *, js::math_sin_impl); + funptr = JS_FUNC_TO_DATA_PTR(void *, MAYBE_CACHED(js::math_sin)); break; case MMathFunction::Cos: - funptr = JS_FUNC_TO_DATA_PTR(void *, js::math_cos_impl); + funptr = JS_FUNC_TO_DATA_PTR(void *, MAYBE_CACHED(js::math_cos)); break; case MMathFunction::Exp: - funptr = JS_FUNC_TO_DATA_PTR(void *, js::math_exp_impl); + funptr = JS_FUNC_TO_DATA_PTR(void *, MAYBE_CACHED(js::math_exp)); break; case MMathFunction::Tan: - funptr = JS_FUNC_TO_DATA_PTR(void *, js::math_tan_impl); + funptr = JS_FUNC_TO_DATA_PTR(void *, MAYBE_CACHED(js::math_tan)); break; case MMathFunction::ATan: - funptr = JS_FUNC_TO_DATA_PTR(void *, js::math_atan_impl); + funptr = JS_FUNC_TO_DATA_PTR(void *, MAYBE_CACHED(js::math_atan)); break; case MMathFunction::ASin: - funptr = JS_FUNC_TO_DATA_PTR(void *, js::math_asin_impl); + funptr = JS_FUNC_TO_DATA_PTR(void *, MAYBE_CACHED(js::math_asin)); break; case MMathFunction::ACos: - funptr = JS_FUNC_TO_DATA_PTR(void *, js::math_acos_impl); + funptr = JS_FUNC_TO_DATA_PTR(void *, MAYBE_CACHED(js::math_acos)); break; case MMathFunction::Log10: - funptr = JS_FUNC_TO_DATA_PTR(void *, js::math_log10_impl); + funptr = JS_FUNC_TO_DATA_PTR(void *, MAYBE_CACHED(js::math_log10)); break; case MMathFunction::Log2: - funptr = JS_FUNC_TO_DATA_PTR(void *, js::math_log2_impl); + funptr = JS_FUNC_TO_DATA_PTR(void *, MAYBE_CACHED(js::math_log2)); break; case MMathFunction::Log1P: - funptr = JS_FUNC_TO_DATA_PTR(void *, js::math_log1p_impl); + funptr = JS_FUNC_TO_DATA_PTR(void *, MAYBE_CACHED(js::math_log1p)); break; case MMathFunction::ExpM1: - funptr = JS_FUNC_TO_DATA_PTR(void *, js::math_expm1_impl); + funptr = JS_FUNC_TO_DATA_PTR(void *, MAYBE_CACHED(js::math_expm1)); break; case MMathFunction::CosH: - funptr = JS_FUNC_TO_DATA_PTR(void *, js::math_cosh_impl); + funptr = JS_FUNC_TO_DATA_PTR(void *, MAYBE_CACHED(js::math_cosh)); break; case MMathFunction::SinH: - funptr = JS_FUNC_TO_DATA_PTR(void *, js::math_sinh_impl); + funptr = JS_FUNC_TO_DATA_PTR(void *, MAYBE_CACHED(js::math_sinh)); break; case MMathFunction::TanH: - funptr = JS_FUNC_TO_DATA_PTR(void *, js::math_tanh_impl); + funptr = JS_FUNC_TO_DATA_PTR(void *, MAYBE_CACHED(js::math_tanh)); break; case MMathFunction::ACosH: - funptr = JS_FUNC_TO_DATA_PTR(void *, js::math_acosh_impl); + funptr = JS_FUNC_TO_DATA_PTR(void *, MAYBE_CACHED(js::math_acosh)); break; case MMathFunction::ASinH: - funptr = JS_FUNC_TO_DATA_PTR(void *, js::math_asinh_impl); + funptr = JS_FUNC_TO_DATA_PTR(void *, MAYBE_CACHED(js::math_asinh)); break; case MMathFunction::ATanH: - funptr = JS_FUNC_TO_DATA_PTR(void *, js::math_atanh_impl); + funptr = JS_FUNC_TO_DATA_PTR(void *, MAYBE_CACHED(js::math_atanh)); break; case MMathFunction::Sign: - funptr = JS_FUNC_TO_DATA_PTR(void *, js::math_sign_impl); + funptr = JS_FUNC_TO_DATA_PTR(void *, MAYBE_CACHED(js::math_sign)); break; case MMathFunction::Trunc: - funptr = JS_FUNC_TO_DATA_PTR(void *, js::math_trunc_impl); + funptr = JS_FUNC_TO_DATA_PTR(void *, MAYBE_CACHED(js::math_trunc)); break; case MMathFunction::Cbrt: - funptr = JS_FUNC_TO_DATA_PTR(void *, js::math_cbrt_impl); + funptr = JS_FUNC_TO_DATA_PTR(void *, MAYBE_CACHED(js::math_cbrt)); break; default: MOZ_ASSUME_UNREACHABLE("Unknown math function"); } +# undef MAYBE_CACHED + masm.callWithABI(funptr, MacroAssembler::DOUBLE); return true; } diff --git a/js/src/jit/MIR.h b/js/src/jit/MIR.h index 7e60cc031e0..cdd3130ca35 100644 --- a/js/src/jit/MIR.h +++ b/js/src/jit/MIR.h @@ -3402,6 +3402,8 @@ class MMathFunction public: INSTRUCTION_HEADER(MathFunction) + + // A NULL cache means this function will neither access nor update the cache. static MMathFunction *New(MDefinition *input, Function function, MathCache *cache) { return new MMathFunction(input, function, cache); } diff --git a/js/src/jit/ParallelSafetyAnalysis.cpp b/js/src/jit/ParallelSafetyAnalysis.cpp index 50f8cf0f3fc..aaaabe8f952 100644 --- a/js/src/jit/ParallelSafetyAnalysis.cpp +++ b/js/src/jit/ParallelSafetyAnalysis.cpp @@ -147,7 +147,7 @@ class ParallelSafetyVisitor : public MInstructionVisitor SAFE_OP(Abs) SAFE_OP(Sqrt) UNSAFE_OP(Atan2) - SAFE_OP(MathFunction) + CUSTOM_OP(MathFunction) SPECIALIZED_OP(Add, PERMIT_NUMERIC) SPECIALIZED_OP(Sub, PERMIT_NUMERIC) SPECIALIZED_OP(Mul, PERMIT_NUMERIC) @@ -549,6 +549,12 @@ ParallelSafetyVisitor::visitRest(MRest *ins) return replace(ins, MRestPar::New(forkJoinSlice(), ins)); } +bool +ParallelSafetyVisitor::visitMathFunction(MMathFunction *ins) +{ + return replace(ins, MMathFunction::New(ins->input(), ins->function(), NULL)); +} + bool ParallelSafetyVisitor::visitConcat(MConcat *ins) { diff --git a/js/src/jsmath.cpp b/js/src/jsmath.cpp index e8f6d23a709..f1c6e8c0e7d 100644 --- a/js/src/jsmath.cpp +++ b/js/src/jsmath.cpp @@ -132,16 +132,28 @@ js_math_abs(JSContext *cx, unsigned argc, Value *vp) return true; } +#if defined(SOLARIS) && defined(__GNUC__) +#define ACOS_IF_OUT_OF_RANGE(x) if (x < -1 || 1 < x) return js_NaN; +#else +#define ACOS_IF_OUT_OF_RANGE(x) +#endif + double js::math_acos_impl(MathCache *cache, double x) { -#if defined(SOLARIS) && defined(__GNUC__) - if (x < -1 || 1 < x) - return js_NaN; -#endif + ACOS_IF_OUT_OF_RANGE(x); return cache->lookup(acos, x); } +double +js::math_acos_uncached(double x) +{ + ACOS_IF_OUT_OF_RANGE(x); + return acos(x); +} + +#undef ACOS_IF_OUT_OF_RANGE + bool js::math_acos(JSContext *cx, unsigned argc, Value *vp) { @@ -165,16 +177,28 @@ js::math_acos(JSContext *cx, unsigned argc, Value *vp) return true; } +#if defined(SOLARIS) && defined(__GNUC__) +#define ASIN_IF_OUT_OF_RANGE(x) if (x < -1 || 1 < x) return js_NaN; +#else +#define ASIN_IF_OUT_OF_RANGE(x) +#endif + double js::math_asin_impl(MathCache *cache, double x) { -#if defined(SOLARIS) && defined(__GNUC__) - if (x < -1 || 1 < x) - return js_NaN; -#endif + ASIN_IF_OUT_OF_RANGE(x); return cache->lookup(asin, x); } +double +js::math_asin_uncached(double x) +{ + ASIN_IF_OUT_OF_RANGE(x); + return asin(x); +} + +#undef ASIN_IF_OUT_OF_RANGE + bool js::math_asin(JSContext *cx, unsigned argc, Value *vp) { @@ -204,6 +228,12 @@ js::math_atan_impl(MathCache *cache, double x) return cache->lookup(atan, x); } +double +js::math_atan_uncached(double x) +{ + return atan(x); +} + bool js::math_atan(JSContext *cx, unsigned argc, Value *vp) { @@ -311,6 +341,12 @@ js::math_cos_impl(MathCache *cache, double x) return cache->lookup(cos, x); } +double +js::math_cos_uncached(double x) +{ + return cos(x); +} + bool js::math_cos(JSContext *cx, unsigned argc, Value *vp) { @@ -334,20 +370,34 @@ js::math_cos(JSContext *cx, unsigned argc, Value *vp) return true; } +#ifdef _WIN32 +#define EXP_IF_OUT_OF_RANGE(x) \ + if (!IsNaN(x)) { \ + if (x == js_PositiveInfinity) \ + return js_PositiveInfinity; \ + if (x == js_NegativeInfinity) \ + return 0.0; \ + } +#else +#define EXP_IF_OUT_OF_RANGE(x) +#endif + double js::math_exp_impl(MathCache *cache, double x) { -#ifdef _WIN32 - if (!IsNaN(x)) { - if (x == js_PositiveInfinity) - return js_PositiveInfinity; - if (x == js_NegativeInfinity) - return 0.0; - } -#endif + EXP_IF_OUT_OF_RANGE(x); return cache->lookup(exp, x); } +double +js::math_exp_uncached(double x) +{ + EXP_IF_OUT_OF_RANGE(x); + return exp(x); +} + +#undef EXP_IF_OUT_OF_RANGE + bool js::math_exp(JSContext *cx, unsigned argc, Value *vp) { @@ -414,16 +464,28 @@ js::math_imul(JSContext *cx, unsigned argc, Value *vp) return true; } +#if defined(SOLARIS) && defined(__GNUC__) +#define LOG_IF_OUT_OF_RANGE(x) if (x < 0) return js_NaN; +#else +#define LOG_IF_OUT_OF_RANGE(x) +#endif + double js::math_log_impl(MathCache *cache, double x) { -#if defined(SOLARIS) && defined(__GNUC__) - if (x < 0) - return js_NaN; -#endif + LOG_IF_OUT_OF_RANGE(x); return cache->lookup(log, x); } +double +js::math_log_uncached(double x) +{ + LOG_IF_OUT_OF_RANGE(x); + return log(x); +} + +#undef LOG_IF_OUT_OF_RANGE + bool js::math_log(JSContext *cx, unsigned argc, Value *vp) { @@ -724,6 +786,12 @@ js::math_sin_impl(MathCache *cache, double x) return cache->lookup(sin, x); } +double +js::math_sin_uncached(double x) +{ + return sin(x); +} + bool js::math_sin(JSContext *cx, unsigned argc, Value *vp) { @@ -776,6 +844,12 @@ js::math_tan_impl(MathCache *cache, double x) return cache->lookup(tan, x); } +double +js::math_tan_uncached(double x) +{ + return tan(x); +} + bool js::math_tan(JSContext *cx, unsigned argc, Value *vp) { @@ -832,6 +906,12 @@ js::math_log10_impl(MathCache *cache, double x) return cache->lookup(log10, x); } +double +js::math_log10_uncached(double x) +{ + return log10(x); +} + bool js::math_log10(JSContext *cx, unsigned argc, Value *vp) { @@ -851,6 +931,12 @@ js::math_log2_impl(MathCache *cache, double x) return cache->lookup(log2, x); } +double +js::math_log2_uncached(double x) +{ + return log2(x); +} + bool js::math_log2(JSContext *cx, unsigned argc, Value *vp) { @@ -874,18 +960,29 @@ double log1p(double x) } #endif +#ifdef __APPLE__ +// Ensure that log1p(-0) is -0. +#define LOG1P_IF_OUT_OF_RANGE(x) if (x == 0) return x; +#else +#define LOG1P_IF_OUT_OF_RANGE(x) +#endif + double js::math_log1p_impl(MathCache *cache, double x) { -#ifdef __APPLE__ - // Ensure that log1p(-0) is -0. - if (x == 0) - return x; -#endif - + LOG1P_IF_OUT_OF_RANGE(x); return cache->lookup(log1p, x); } +double +js::math_log1p_uncached(double x) +{ + LOG1P_IF_OUT_OF_RANGE(x); + return log1p(x); +} + +#undef LOG1P_IF_OUT_OF_RANGE + bool js::math_log1p(JSContext *cx, unsigned argc, Value *vp) { @@ -919,6 +1016,12 @@ js::math_expm1_impl(MathCache *cache, double x) return cache->lookup(expm1, x); } +double +js::math_expm1_uncached(double x) +{ + return expm1(x); +} + bool js::math_expm1(JSContext *cx, unsigned argc, Value *vp) { @@ -943,6 +1046,12 @@ js::math_cosh_impl(MathCache *cache, double x) return cache->lookup(cosh, x); } +double +js::math_cosh_uncached(double x) +{ + return cosh(x); +} + bool js::math_cosh(JSContext *cx, unsigned argc, Value *vp) { @@ -955,6 +1064,12 @@ js::math_sinh_impl(MathCache *cache, double x) return cache->lookup(sinh, x); } +double +js::math_sinh_uncached(double x) +{ + return sinh(x); +} + bool js::math_sinh(JSContext *cx, unsigned argc, Value *vp) { @@ -967,6 +1082,12 @@ js::math_tanh_impl(MathCache *cache, double x) return cache->lookup(tanh, x); } +double +js::math_tanh_uncached(double x) +{ + return tanh(x); +} + bool js::math_tanh(JSContext *cx, unsigned argc, Value *vp) { @@ -1010,6 +1131,12 @@ js::math_acosh_impl(MathCache *cache, double x) return cache->lookup(acosh, x); } +double +js::math_acosh_uncached(double x) +{ + return acosh(x); +} + bool js::math_acosh(JSContext *cx, unsigned argc, Value *vp) { @@ -1061,6 +1188,16 @@ js::math_asinh_impl(MathCache *cache, double x) #endif } +double +js::math_asinh_uncached(double x) +{ +#ifdef HAVE_ASINH + return asinh(x); +#else + return my_asinh(x); +#endif +} + bool js::math_asinh(JSContext *cx, unsigned argc, Value *vp) { @@ -1101,6 +1238,12 @@ js::math_atanh_impl(MathCache *cache, double x) return cache->lookup(atanh, x); } +double +js::math_atanh_uncached(double x) +{ + return atanh(x); +} + bool js::math_atanh(JSContext *cx, unsigned argc, Value *vp) { @@ -1189,6 +1332,12 @@ js::math_trunc_impl(MathCache *cache, double x) return cache->lookup(trunc, x); } +double +js::math_trunc_uncached(double x) +{ + return trunc(x); +} + bool js::math_trunc(JSContext *cx, unsigned argc, Value *vp) { @@ -1209,6 +1358,12 @@ js::math_sign_impl(MathCache *cache, double x) return cache->lookup(sign, x); } +double +js::math_sign_uncached(double x) +{ + return sign(x); +} + bool js::math_sign(JSContext *cx, unsigned argc, Value *vp) { @@ -1234,6 +1389,12 @@ js::math_cbrt_impl(MathCache *cache, double x) return cache->lookup(cbrt, x); } +double +js::math_cbrt_uncached(double x) +{ + return cbrt(x); +} + bool js::math_cbrt(JSContext *cx, unsigned argc, Value *vp) { diff --git a/js/src/jsmath.h b/js/src/jsmath.h index 8e9ccece422..6f21879853f 100644 --- a/js/src/jsmath.h +++ b/js/src/jsmath.h @@ -105,30 +105,45 @@ math_log(JSContext *cx, unsigned argc, js::Value *vp); extern double math_log_impl(MathCache *cache, double x); +extern double +math_log_uncached(double x); + extern bool math_sin(JSContext *cx, unsigned argc, js::Value *vp); extern double math_sin_impl(MathCache *cache, double x); +extern double +math_sin_uncached(double x); + extern bool math_cos(JSContext *cx, unsigned argc, js::Value *vp); extern double math_cos_impl(MathCache *cache, double x); +extern double +math_cos_uncached(double x); + extern bool math_exp(JSContext *cx, unsigned argc, js::Value *vp); extern double math_exp_impl(MathCache *cache, double x); +extern double +math_exp_uncached(double x); + extern bool math_tan(JSContext *cx, unsigned argc, js::Value *vp); extern double math_tan_impl(MathCache *cache, double x); +extern double +math_tan_uncached(double x); + extern bool math_log10(JSContext *cx, unsigned argc, js::Value *vp); @@ -192,18 +207,27 @@ ecmaAtan2(double x, double y); extern double math_atan_impl(MathCache *cache, double x); +extern double +math_atan_uncached(double x); + extern bool math_atan(JSContext *cx, unsigned argc, js::Value *vp); extern double math_asin_impl(MathCache *cache, double x); +extern double +math_asin_uncached(double x); + extern bool math_asin(JSContext *cx, unsigned argc, js::Value *vp); extern double math_acos_impl(MathCache *cache, double x); +extern double +math_acos_uncached(double x); + extern bool math_acos(JSContext *cx, unsigned argc, js::Value *vp); @@ -219,48 +243,90 @@ math_imul(JSContext *cx, unsigned argc, Value *vp); extern double math_log10_impl(MathCache *cache, double x); +extern double +math_log10_uncached(double x); + extern double math_log2_impl(MathCache *cache, double x); +extern double +math_log2_uncached(double x); + extern double math_log1p_impl(MathCache *cache, double x); +extern double +math_log1p_uncached(double x); + extern double math_expm1_impl(MathCache *cache, double x); +extern double +math_expm1_uncached(double x); + extern double math_cosh_impl(MathCache *cache, double x); +extern double +math_cosh_uncached(double x); + extern double math_sinh_impl(MathCache *cache, double x); +extern double +math_sinh_uncached(double x); + extern double math_tanh_impl(MathCache *cache, double x); +extern double +math_tanh_uncached(double x); + extern double math_acosh_impl(MathCache *cache, double x); +extern double +math_acosh_uncached(double x); + extern double math_asinh_impl(MathCache *cache, double x); +extern double +math_asinh_uncached(double x); + extern double math_atanh_impl(MathCache *cache, double x); +extern double +math_atanh_uncached(double x); + // Math.hypot is disabled pending the resolution of spec issues (bug 896264). #if 0 extern double math_hypot_impl(double x, double y); + +extern double +math_hypot_uncached(double x, double y); #endif extern double math_trunc_impl(MathCache *cache, double x); +extern double +math_trunc_uncached(double x); + extern double math_sign_impl(MathCache *cache, double x); +extern double +math_sign_uncached(double x); + extern double math_cbrt_impl(MathCache *cache, double x); +extern double +math_cbrt_uncached(double x); + } /* namespace js */ #endif /* jsmath_h */