mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-01-11 22:41:02 +00:00
Bug 967709 - SpiderMonkey: Revert the fast_sincos implementation for now. r=me
This commit is contained in:
parent
a9dec9ad29
commit
118e8f6ba8
@ -233,9 +233,9 @@ AddressOf(AsmJSImmKind kind, ExclusiveContext *cx)
|
||||
case AsmJSImm_ModD:
|
||||
return RedirectCall(FuncCast(NumberMod), Args_Double_DoubleDouble);
|
||||
case AsmJSImm_SinD:
|
||||
return RedirectCall(FuncCast<double (double)>(math_sin_impl), Args_Double_Double);
|
||||
return RedirectCall(FuncCast<double (double)>(sin), Args_Double_Double);
|
||||
case AsmJSImm_CosD:
|
||||
return RedirectCall(FuncCast<double (double)>(math_cos_impl), Args_Double_Double);
|
||||
return RedirectCall(FuncCast<double (double)>(cos), Args_Double_Double);
|
||||
case AsmJSImm_TanD:
|
||||
return RedirectCall(FuncCast<double (double)>(tan), Args_Double_Double);
|
||||
case AsmJSImm_ASinD:
|
||||
|
@ -4348,6 +4348,13 @@ CodeGenerator::visitMathFunctionD(LMathFunctionD *ins)
|
||||
|
||||
const MathCache *mathCache = ins->mir()->cache();
|
||||
|
||||
masm.setupUnalignedABICall(mathCache ? 2 : 1, temp);
|
||||
if (mathCache) {
|
||||
masm.movePtr(ImmPtr(mathCache), temp);
|
||||
masm.passABIArg(temp);
|
||||
}
|
||||
masm.passABIArg(input, MoveOp::DOUBLE);
|
||||
|
||||
# define MAYBE_CACHED(fcn) (mathCache ? (void*)fcn ## _impl : (void*)fcn ## _uncached)
|
||||
|
||||
void *funptr = nullptr;
|
||||
@ -4356,12 +4363,10 @@ CodeGenerator::visitMathFunctionD(LMathFunctionD *ins)
|
||||
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);
|
||||
mathCache = nullptr;
|
||||
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);
|
||||
mathCache = nullptr;
|
||||
funptr = JS_FUNC_TO_DATA_PTR(void *, MAYBE_CACHED(js::math_cos));
|
||||
break;
|
||||
case MMathFunction::Exp:
|
||||
funptr = JS_FUNC_TO_DATA_PTR(void *, MAYBE_CACHED(js::math_exp));
|
||||
@ -4419,15 +4424,12 @@ CodeGenerator::visitMathFunctionD(LMathFunctionD *ins)
|
||||
break;
|
||||
case MMathFunction::Floor:
|
||||
funptr = JS_FUNC_TO_DATA_PTR(void *, js::math_floor_impl);
|
||||
mathCache = nullptr;
|
||||
break;
|
||||
case MMathFunction::Ceil:
|
||||
funptr = JS_FUNC_TO_DATA_PTR(void *, js::math_ceil_impl);
|
||||
mathCache = nullptr;
|
||||
break;
|
||||
case MMathFunction::Round:
|
||||
funptr = JS_FUNC_TO_DATA_PTR(void *, js::math_round_impl);
|
||||
mathCache = nullptr;
|
||||
break;
|
||||
default:
|
||||
MOZ_ASSUME_UNREACHABLE("Unknown math function");
|
||||
@ -4435,13 +4437,6 @@ CodeGenerator::visitMathFunctionD(LMathFunctionD *ins)
|
||||
|
||||
# undef MAYBE_CACHED
|
||||
|
||||
masm.setupUnalignedABICall(mathCache ? 2 : 1, temp);
|
||||
if (mathCache) {
|
||||
masm.movePtr(ImmPtr(mathCache), temp);
|
||||
masm.passABIArg(temp);
|
||||
}
|
||||
masm.passABIArg(input, MoveOp::DOUBLE);
|
||||
|
||||
masm.callWithABI(funptr, MoveOp::DOUBLE);
|
||||
return true;
|
||||
}
|
||||
|
@ -332,138 +332,16 @@ js::math_clz32(JSContext *cx, unsigned argc, Value *vp)
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Fast sine and cosine approximation code, based on the sin [0] and cos [1]
|
||||
* implementations [2] in the cephes library [3].
|
||||
* Some of the optimization ideas are inspired by the fast_sincos in VDT [4].
|
||||
*
|
||||
* This implementation satisfies the requirements for sin and cos in JS [5].
|
||||
* However, it does not take the standard's recommendation to use fdlibm [6],
|
||||
* nor does it take advantage of the standard's intent to permit JS to use the
|
||||
* system C math library.
|
||||
*
|
||||
* The code carefully avoids branching, to avoid the cost of mispredictions
|
||||
* either on random input sets or on input sets straddling a boundary condition
|
||||
* in the algorithm. It contains only one branch, which is for testing for
|
||||
* unusual inputs (infinities, NaNs, and extremely large values), and it
|
||||
* should be very predictable.
|
||||
*
|
||||
* This implementation computes both a sin and cos value even when only one
|
||||
* of the two is needed. While creating specialized routines for computing just
|
||||
* sin or just cost would allow them to do less work, the speed benefits would
|
||||
* be expected to be marginal, and not worth the extra code it would take, given
|
||||
* that we'll still want the ability to compute sin and cos together anyway.
|
||||
*
|
||||
* [0] http://netlib.org/cephes/doubldoc.html#sin
|
||||
* [1] http://netlib.org/cephes/doubldoc.html#cos
|
||||
* [2] http://netlib.org/cephes/cmath.tgz
|
||||
* [3] http://netlib.org/cephes/
|
||||
* [4] https://svnweb.cern.ch/trac/vdt
|
||||
* [5] http://www.ecma-international.org/ecma-262/5.1/#sec-15.8.2
|
||||
* [6] http://netlib.org/fdlibm
|
||||
*/
|
||||
|
||||
static double polevl_sin(double z, double zz)
|
||||
double
|
||||
js::math_cos_impl(MathCache *cache, double x)
|
||||
{
|
||||
// Constants generated using Mathematica's GeneralMiniMaxApproximation
|
||||
double ans = 1.59046813973877163292e-10; // 6152825598094877 / exp2(85)
|
||||
ans *= zz;
|
||||
ans += -2.50509001624159785668e-08; // -7571170002733246 / exp2(78)
|
||||
ans *= zz;
|
||||
ans += 2.75573146431678644161e-06; // 6506786951439440 / exp2(71)
|
||||
ans *= zz;
|
||||
ans += -1.98412698327005105692e-04; // -7320136534024805 / exp2(65)
|
||||
ans *= zz;
|
||||
ans += 8.33333333332626768897e-03; // 4803839602524456 / exp2(59)
|
||||
ans *= zz;
|
||||
ans += -1.66666666666666490881e-01; // -6004799503160655 / exp2(55)
|
||||
ans *= zz * z;
|
||||
ans += z;
|
||||
return ans;
|
||||
}
|
||||
|
||||
static double polevl_cos(double zz)
|
||||
{
|
||||
// Constants generated using Mathematica's GeneralMiniMaxApproximation.
|
||||
// This set uses one less coefficient than usual implementations to
|
||||
// increase performance, raising the maximum approximation error to 2 bits.
|
||||
double ans = 2.06467337476762997948e-9;
|
||||
ans *= zz;
|
||||
ans += -2.75555495413759160741e-7;
|
||||
ans *= zz;
|
||||
ans += 2.48015808595638122085e-5;
|
||||
ans *= zz;
|
||||
ans += -1.38888888779622760722e-3;
|
||||
ans *= zz;
|
||||
ans += 4.16666666665987187046e-2;
|
||||
ans *= zz;
|
||||
ans += -4.99999999999999888978e-1;
|
||||
ans *= zz;
|
||||
ans += 1.0;
|
||||
return ans;
|
||||
}
|
||||
|
||||
namespace {
|
||||
struct sincos_result { double s, c; };
|
||||
}
|
||||
|
||||
static sincos_result fast_sincos(double x)
|
||||
{
|
||||
// Make argument non-negative but save the sign.
|
||||
double orig_sign = js_copysign(1.0, x);
|
||||
double absx = fabs(x);
|
||||
|
||||
// The optimized algorithm below doesn't currently support values of x beyond
|
||||
// pow(2, 32) - 2. If x is beyond the range we support, fall back to the libm
|
||||
// implementation. This check also handles the Infinity and NaN input cases.
|
||||
// abs(x) < (221069929647945 / pow(2,16))
|
||||
if (MOZ_UNLIKELY(!(absx < 3.37325942455970764160e9))) {
|
||||
sincos_result result = {
|
||||
sin(x),
|
||||
cos(x)
|
||||
};
|
||||
return result;
|
||||
}
|
||||
|
||||
static const double m_4_pi = 1.27323954473516276487; // 4.0 / M_PI
|
||||
uint32_t i = static_cast<uint32_t>(absx * m_4_pi);
|
||||
|
||||
// Integer and fractional part modulo one octant.
|
||||
uint32_t quad_index = ((i + 1) >> 1) & 3;
|
||||
double y = static_cast<double>(i + (i & 1));
|
||||
|
||||
// Extended precision modular arithmetic
|
||||
double e0 = y * -7.85398006439208984375e-1; // 1647099 / pow(2,21)
|
||||
double e1 = y * -1.56958208208379801363e-7; // 1380619 / pow(2,43)
|
||||
double e2 = y * -3.11168608594830669189e-14; // 4930663418217751 / pow(2,97)
|
||||
double z = absx + e0 + e1 + e2;
|
||||
|
||||
// Compute the sin/cos in quadrant 0.
|
||||
double zz = z * z;
|
||||
double q0_sin = polevl_sin(z, zz);
|
||||
double q0_cos = polevl_cos(zz);
|
||||
|
||||
// Reflect the result into the correct quadrant.
|
||||
const double reflect[4] = {
|
||||
q0_sin, q0_cos, -q0_sin, -q0_cos
|
||||
};
|
||||
|
||||
// Adjust the sine value by the sign of the input.
|
||||
// Missed optimization: C++ doesn't provide convenient access to
|
||||
// floating-point xor; hand-written assembler could change the copysign
|
||||
// above to use 0.0 instead of 1.0, and then just xor the sign with p[0]
|
||||
// here instead of multiplying.
|
||||
sincos_result result = {
|
||||
reflect[quad_index] * orig_sign,
|
||||
reflect[(quad_index + 1) & 3]
|
||||
};
|
||||
return result;
|
||||
return cache->lookup(cos, x);
|
||||
}
|
||||
|
||||
double
|
||||
js::math_cos_impl(double x)
|
||||
js::math_cos_uncached(double x)
|
||||
{
|
||||
return fast_sincos(x).c;
|
||||
return cos(x);
|
||||
}
|
||||
|
||||
bool
|
||||
@ -480,7 +358,11 @@ js::math_cos(JSContext *cx, unsigned argc, Value *vp)
|
||||
if (!ToNumber(cx, args[0], &x))
|
||||
return false;
|
||||
|
||||
double z = math_cos_impl(x);
|
||||
MathCache *mathCache = cx->runtime()->getMathCache(cx);
|
||||
if (!mathCache)
|
||||
return false;
|
||||
|
||||
double z = math_cos_impl(mathCache, x);
|
||||
args.rval().setDouble(z);
|
||||
return true;
|
||||
}
|
||||
@ -931,9 +813,15 @@ js::math_round(JSContext *cx, unsigned argc, Value *vp)
|
||||
}
|
||||
|
||||
double
|
||||
js::math_sin_impl(double x)
|
||||
js::math_sin_impl(MathCache *cache, double x)
|
||||
{
|
||||
return fast_sincos(x).s;
|
||||
return cache->lookup(sin, x);
|
||||
}
|
||||
|
||||
double
|
||||
js::math_sin_uncached(double x)
|
||||
{
|
||||
return sin(x);
|
||||
}
|
||||
|
||||
bool
|
||||
@ -950,7 +838,11 @@ js::math_sin(JSContext *cx, unsigned argc, Value *vp)
|
||||
if (!ToNumber(cx, args[0], &x))
|
||||
return false;
|
||||
|
||||
double z = math_sin_impl(x);
|
||||
MathCache *mathCache = cx->runtime()->getMathCache(cx);
|
||||
if (!mathCache)
|
||||
return false;
|
||||
|
||||
double z = math_sin_impl(mathCache, x);
|
||||
args.rval().setDouble(z);
|
||||
return true;
|
||||
}
|
||||
|
@ -128,13 +128,19 @@ extern bool
|
||||
math_sin(JSContext *cx, unsigned argc, js::Value *vp);
|
||||
|
||||
extern double
|
||||
math_sin_impl(double x);
|
||||
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(double x);
|
||||
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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user