Bug 901000: Added uncached variants of Math functions for PJS (r=nmatsakis).

This commit is contained in:
Felix S. Klock II 2013-08-22 16:33:35 +02:00
parent 37bf16c6ed
commit 1f0542d508
5 changed files with 287 additions and 48 deletions

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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)
{

View File

@ -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)
{

View File

@ -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 */