Commit cede9ce5 authored by mvstanton's avatar mvstanton Committed by Commit bot

[builtins] Unify Cosh, Sinh and Tanh as exports from flibm

BUG=v8:5086

Review-Url: https://codereview.chromium.org/2083573002
Cr-Commit-Position: refs/heads/master@{#37424}
parent 483291d2
......@@ -332,7 +332,6 @@ action("js2c") {
"src/js/array.js",
"src/js/string.js",
"src/js/math.js",
"src/third_party/fdlibm/fdlibm.js",
"src/js/regexp.js",
"src/js/arraybuffer.js",
"src/js/typedarray.js",
......
......@@ -1431,6 +1431,11 @@ ExternalReference ExternalReference::ieee754_cos_function(Isolate* isolate) {
Redirect(isolate, FUNCTION_ADDR(base::ieee754::cos), BUILTIN_FP_CALL));
}
ExternalReference ExternalReference::ieee754_cosh_function(Isolate* isolate) {
return ExternalReference(
Redirect(isolate, FUNCTION_ADDR(base::ieee754::cosh), BUILTIN_FP_CALL));
}
ExternalReference ExternalReference::ieee754_exp_function(Isolate* isolate) {
return ExternalReference(
Redirect(isolate, FUNCTION_ADDR(base::ieee754::exp), BUILTIN_FP_CALL));
......@@ -1466,11 +1471,21 @@ ExternalReference ExternalReference::ieee754_sin_function(Isolate* isolate) {
Redirect(isolate, FUNCTION_ADDR(base::ieee754::sin), BUILTIN_FP_CALL));
}
ExternalReference ExternalReference::ieee754_sinh_function(Isolate* isolate) {
return ExternalReference(
Redirect(isolate, FUNCTION_ADDR(base::ieee754::sinh), BUILTIN_FP_CALL));
}
ExternalReference ExternalReference::ieee754_tan_function(Isolate* isolate) {
return ExternalReference(
Redirect(isolate, FUNCTION_ADDR(base::ieee754::tan), BUILTIN_FP_CALL));
}
ExternalReference ExternalReference::ieee754_tanh_function(Isolate* isolate) {
return ExternalReference(
Redirect(isolate, FUNCTION_ADDR(base::ieee754::tanh), BUILTIN_FP_CALL));
}
ExternalReference ExternalReference::page_flags(Page* page) {
return ExternalReference(reinterpret_cast<Address>(page) +
MemoryChunk::kFlagsOffset);
......
......@@ -1004,6 +1004,7 @@ class ExternalReference BASE_EMBEDDED {
static ExternalReference ieee754_atanh_function(Isolate* isolate);
static ExternalReference ieee754_cbrt_function(Isolate* isolate);
static ExternalReference ieee754_cos_function(Isolate* isolate);
static ExternalReference ieee754_cosh_function(Isolate* isolate);
static ExternalReference ieee754_exp_function(Isolate* isolate);
static ExternalReference ieee754_expm1_function(Isolate* isolate);
static ExternalReference ieee754_log_function(Isolate* isolate);
......@@ -1011,7 +1012,9 @@ class ExternalReference BASE_EMBEDDED {
static ExternalReference ieee754_log10_function(Isolate* isolate);
static ExternalReference ieee754_log2_function(Isolate* isolate);
static ExternalReference ieee754_sin_function(Isolate* isolate);
static ExternalReference ieee754_sinh_function(Isolate* isolate);
static ExternalReference ieee754_tan_function(Isolate* isolate);
static ExternalReference ieee754_tanh_function(Isolate* isolate);
static ExternalReference page_flags(Page* page);
......
......@@ -2308,6 +2308,182 @@ double tan(double x) {
}
}
/*
* ES6 draft 09-27-13, section 20.2.2.12.
* Math.cosh
* Method :
* mathematically cosh(x) if defined to be (exp(x)+exp(-x))/2
* 1. Replace x by |x| (cosh(x) = cosh(-x)).
* 2.
* [ exp(x) - 1 ]^2
* 0 <= x <= ln2/2 : cosh(x) := 1 + -------------------
* 2*exp(x)
*
* exp(x) + 1/exp(x)
* ln2/2 <= x <= 22 : cosh(x) := -------------------
* 2
* 22 <= x <= lnovft : cosh(x) := exp(x)/2
* lnovft <= x <= ln2ovft: cosh(x) := exp(x/2)/2 * exp(x/2)
* ln2ovft < x : cosh(x) := huge*huge (overflow)
*
* Special cases:
* cosh(x) is |x| if x is +INF, -INF, or NaN.
* only cosh(0)=1 is exact for finite x.
*/
double cosh(double x) {
static const double KCOSH_OVERFLOW = 710.4758600739439;
static const double one = 1.0, half = 0.5;
static volatile double huge = 1.0e+300;
int32_t ix;
/* High word of |x|. */
GET_HIGH_WORD(ix, x);
ix &= 0x7fffffff;
// |x| in [0,0.5*log2], return 1+expm1(|x|)^2/(2*exp(|x|))
if (ix < 0x3fd62e43) {
double t = expm1(fabs(x));
double w = one + t;
// For |x| < 2^-55, cosh(x) = 1
if (ix < 0x3c800000) return w;
return one + (t * t) / (w + w);
}
// |x| in [0.5*log2, 22], return (exp(|x|)+1/exp(|x|)/2
if (ix < 0x40360000) {
double t = exp(fabs(x));
return half * t + half / t;
}
// |x| in [22, log(maxdouble)], return half*exp(|x|)
if (ix < 0x40862e42) return half * exp(fabs(x));
// |x| in [log(maxdouble), overflowthreshold]
if (fabs(x) <= KCOSH_OVERFLOW) {
double w = exp(half * fabs(x));
double t = half * w;
return t * w;
}
/* x is INF or NaN */
if (ix >= 0x7ff00000) return x * x;
// |x| > overflowthreshold.
return huge * huge;
}
/*
* ES6 draft 09-27-13, section 20.2.2.30.
* Math.sinh
* Method :
* mathematically sinh(x) if defined to be (exp(x)-exp(-x))/2
* 1. Replace x by |x| (sinh(-x) = -sinh(x)).
* 2.
* E + E/(E+1)
* 0 <= x <= 22 : sinh(x) := --------------, E=expm1(x)
* 2
*
* 22 <= x <= lnovft : sinh(x) := exp(x)/2
* lnovft <= x <= ln2ovft: sinh(x) := exp(x/2)/2 * exp(x/2)
* ln2ovft < x : sinh(x) := x*shuge (overflow)
*
* Special cases:
* sinh(x) is |x| if x is +Infinity, -Infinity, or NaN.
* only sinh(0)=0 is exact for finite x.
*/
double sinh(double x) {
static const double KSINH_OVERFLOW = 710.4758600739439,
TWO_M28 =
3.725290298461914e-9, // 2^-28, empty lower half
LOG_MAXD = 709.7822265625; // 0x40862e42 00000000, empty lower half
static const double shuge = 1.0e307;
double h = (x < 0) ? -0.5 : 0.5;
// |x| in [0, 22]. return sign(x)*0.5*(E+E/(E+1))
double ax = fabs(x);
if (ax < 22) {
// For |x| < 2^-28, sinh(x) = x
if (ax < TWO_M28) return x;
double t = expm1(ax);
if (ax < 1) {
return h * (2 * t - t * t / (t + 1));
}
return h * (t + t / (t + 1));
}
// |x| in [22, log(maxdouble)], return 0.5 * exp(|x|)
if (ax < LOG_MAXD) return h * exp(ax);
// |x| in [log(maxdouble), overflowthreshold]
// overflowthreshold = 710.4758600739426
if (ax <= KSINH_OVERFLOW) {
double w = exp(0.5 * ax);
double t = h * w;
return t * w;
}
// |x| > overflowthreshold or is NaN.
// Return Infinity of the appropriate sign or NaN.
return x * shuge;
}
/* Tanh(x)
* Return the Hyperbolic Tangent of x
*
* Method :
* x -x
* e - e
* 0. tanh(x) is defined to be -----------
* x -x
* e + e
* 1. reduce x to non-negative by tanh(-x) = -tanh(x).
* 2. 0 <= x < 2**-28 : tanh(x) := x with inexact if x != 0
* -t
* 2**-28 <= x < 1 : tanh(x) := -----; t = expm1(-2x)
* t + 2
* 2
* 1 <= x < 22 : tanh(x) := 1 - -----; t = expm1(2x)
* t + 2
* 22 <= x <= INF : tanh(x) := 1.
*
* Special cases:
* tanh(NaN) is NaN;
* only tanh(0)=0 is exact for finite argument.
*/
double tanh(double x) {
static const volatile double tiny = 1.0e-300;
static const double one = 1.0, two = 2.0, huge = 1.0e300;
double t, z;
int32_t jx, ix;
GET_HIGH_WORD(jx, x);
ix = jx & 0x7fffffff;
/* x is INF or NaN */
if (ix >= 0x7ff00000) {
if (jx >= 0)
return one / x + one; /* tanh(+-inf)=+-1 */
else
return one / x - one; /* tanh(NaN) = NaN */
}
/* |x| < 22 */
if (ix < 0x40360000) { /* |x|<22 */
if (ix < 0x3e300000) { /* |x|<2**-28 */
if (huge + x > one) return x; /* tanh(tiny) = tiny with inexact */
}
if (ix >= 0x3ff00000) { /* |x|>=1 */
t = expm1(two * fabs(x));
z = one - two / (t + two);
} else {
t = expm1(-two * fabs(x));
z = -t / (t + two);
}
/* |x| >= 22, return +-1 */
} else {
z = one - tiny; /* raise inexact flag */
}
return (jx >= 0) ? z : -z;
}
} // namespace ieee754
} // namespace base
} // namespace v8
......@@ -50,6 +50,15 @@ double sin(double x);
// Returns the tangent of |x|, where |x| is given in radians.
double tan(double x);
// Returns the hyperbolic cosine of |x|, where |x| is given radians.
double cosh(double x);
// Returns the hyperbolic sine of |x|, where |x| is given radians.
double sinh(double x);
// Returns the hyperbolic tangent of |x|, where |x| is given radians.
double tanh(double x);
} // namespace ieee754
} // namespace base
} // namespace v8
......
......@@ -1679,6 +1679,7 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
SimpleInstallFunction(math, "expm1", Builtins::kMathExpm1, 1, true);
SimpleInstallFunction(math, "clz32", Builtins::kMathClz32, 1, true);
SimpleInstallFunction(math, "cos", Builtins::kMathCos, 1, true);
SimpleInstallFunction(math, "cosh", Builtins::kMathCosh, 1, true);
Handle<JSFunction> math_exp =
SimpleInstallFunction(math, "exp", Builtins::kMathExp, 1, true);
native_context()->set_math_exp(*math_exp);
......@@ -1700,10 +1701,12 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
native_context()->set_math_pow(*math_pow);
SimpleInstallFunction(math, "round", Builtins::kMathRound, 1, true);
SimpleInstallFunction(math, "sin", Builtins::kMathSin, 1, true);
SimpleInstallFunction(math, "sinh", Builtins::kMathSinh, 1, true);
Handle<JSFunction> math_sqrt =
SimpleInstallFunction(math, "sqrt", Builtins::kMathSqrt, 1, true);
native_context()->set_math_sqrt(*math_sqrt);
SimpleInstallFunction(math, "tan", Builtins::kMathTan, 1, true);
SimpleInstallFunction(math, "tanh", Builtins::kMathTanh, 1, true);
SimpleInstallFunction(math, "trunc", Builtins::kMathTrunc, 1, true);
// Install math constants.
......@@ -2612,13 +2615,6 @@ void Bootstrapper::ExportFromRuntime(Isolate* isolate,
script_map->AppendDescriptor(&d);
}
{
// TODO(mvstanton): Remove this when MathSinh, MathCosh and MathTanh are
// no longer implemented in fdlibm.js.
SimpleInstallFunction(container, "MathExpm1", Builtins::kMathExpm1, 1,
true);
}
{
PrototypeIterator iter(native_context->sloppy_async_function_map());
Handle<JSObject> async_function_prototype(iter.GetCurrent<JSObject>());
......
......@@ -2457,6 +2457,18 @@ void Builtins::Generate_MathCos(CodeStubAssembler* assembler) {
assembler->Return(result);
}
// ES6 section 20.2.2.13 Math.cosh ( x )
void Builtins::Generate_MathCosh(CodeStubAssembler* assembler) {
using compiler::Node;
Node* x = assembler->Parameter(1);
Node* context = assembler->Parameter(4);
Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
Node* value = assembler->Float64Cosh(x_value);
Node* result = assembler->ChangeFloat64ToTagged(value);
assembler->Return(result);
}
// ES6 section 20.2.2.14 Math.exp ( x )
void Builtins::Generate_MathExp(CodeStubAssembler* assembler) {
using compiler::Node;
......@@ -2587,6 +2599,18 @@ void Builtins::Generate_MathSin(CodeStubAssembler* assembler) {
assembler->Return(result);
}
// ES6 section 20.2.2.31 Math.sinh ( x )
void Builtins::Generate_MathSinh(CodeStubAssembler* assembler) {
using compiler::Node;
Node* x = assembler->Parameter(1);
Node* context = assembler->Parameter(4);
Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
Node* value = assembler->Float64Sinh(x_value);
Node* result = assembler->ChangeFloat64ToTagged(value);
assembler->Return(result);
}
// ES6 section 20.2.2.32 Math.sqrt ( x )
void Builtins::Generate_MathSqrt(CodeStubAssembler* assembler) {
using compiler::Node;
......@@ -2611,6 +2635,18 @@ void Builtins::Generate_MathTan(CodeStubAssembler* assembler) {
assembler->Return(result);
}
// ES6 section 20.2.2.34 Math.tanh ( x )
void Builtins::Generate_MathTanh(CodeStubAssembler* assembler) {
using compiler::Node;
Node* x = assembler->Parameter(1);
Node* context = assembler->Parameter(4);
Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
Node* value = assembler->Float64Tanh(x_value);
Node* result = assembler->ChangeFloat64ToTagged(value);
assembler->Return(result);
}
// ES6 section 20.2.2.35 Math.trunc ( x )
void Builtins::Generate_MathTrunc(CodeStubAssembler* assembler) {
Generate_MathRoundingOperation(assembler, &CodeStubAssembler::Float64Trunc);
......
......@@ -314,6 +314,7 @@ class CodeStubAssembler;
V(MathExpm1, 2) \
V(MathClz32, 2) \
V(MathCos, 2) \
V(MathCosh, 2) \
V(MathExp, 2) \
V(MathFloor, 2) \
V(MathLog, 2) \
......@@ -323,7 +324,9 @@ class CodeStubAssembler;
V(MathRound, 2) \
V(MathPow, 3) \
V(MathSin, 2) \
V(MathSinh, 2) \
V(MathTan, 2) \
V(MathTanh, 2) \
V(MathSqrt, 2) \
V(MathTrunc, 2) \
V(ObjectHasOwnProperty, 2) \
......@@ -644,6 +647,8 @@ class Builtins {
static void Generate_MathClz32(CodeStubAssembler* assembler);
// ES6 section 20.2.2.12 Math.cos ( x )
static void Generate_MathCos(CodeStubAssembler* assembler);
// ES6 section 20.2.2.13 Math.cosh ( x )
static void Generate_MathCosh(CodeStubAssembler* assembler);
// ES6 section 20.2.2.14 Math.exp ( x )
static void Generate_MathExp(CodeStubAssembler* assembler);
// ES6 section 20.2.2.16 Math.floor ( x )
......@@ -672,10 +677,14 @@ class Builtins {
static void Generate_MathRound(CodeStubAssembler* assembler);
// ES6 section 20.2.2.20 Math.sin ( x )
static void Generate_MathSin(CodeStubAssembler* assembler);
// ES6 section 20.2.2.21 Math.sinh ( x )
static void Generate_MathSinh(CodeStubAssembler* assembler);
// ES6 section 20.2.2.32 Math.sqrt ( x )
static void Generate_MathSqrt(CodeStubAssembler* assembler);
// ES6 section 20.2.2.33 Math.sin ( x )
// ES6 section 20.2.2.33 Math.tan ( x )
static void Generate_MathTan(CodeStubAssembler* assembler);
// ES6 section 20.2.2.34 Math.tanh ( x )
static void Generate_MathTanh(CodeStubAssembler* assembler);
// ES6 section 20.2.2.35 Math.trunc ( x )
static void Generate_MathTrunc(CodeStubAssembler* assembler);
......
......@@ -690,6 +690,9 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
case kIeee754Float64Cos:
ASSEMBLE_IEEE754_UNOP(cos);
break;
case kIeee754Float64Cosh:
ASSEMBLE_IEEE754_UNOP(cosh);
break;
case kIeee754Float64Exp:
ASSEMBLE_IEEE754_UNOP(exp);
break;
......@@ -720,9 +723,15 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
case kIeee754Float64Sin:
ASSEMBLE_IEEE754_UNOP(sin);
break;
case kIeee754Float64Sinh:
ASSEMBLE_IEEE754_UNOP(sinh);
break;
case kIeee754Float64Tan:
ASSEMBLE_IEEE754_UNOP(tan);
break;
case kIeee754Float64Tanh:
ASSEMBLE_IEEE754_UNOP(tanh);
break;
case kArmAdd:
__ add(i.OutputRegister(), i.InputRegister(0), i.InputOperand2(1),
i.OutputSBit());
......
......@@ -820,6 +820,9 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
case kIeee754Float64Cos:
ASSEMBLE_IEEE754_UNOP(cos);
break;
case kIeee754Float64Cosh:
ASSEMBLE_IEEE754_UNOP(cosh);
break;
case kIeee754Float64Cbrt:
ASSEMBLE_IEEE754_UNOP(cbrt);
break;
......@@ -852,9 +855,15 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
case kIeee754Float64Sin:
ASSEMBLE_IEEE754_UNOP(sin);
break;
case kIeee754Float64Sinh:
ASSEMBLE_IEEE754_UNOP(sinh);
break;
case kIeee754Float64Tan:
ASSEMBLE_IEEE754_UNOP(tan);
break;
case kIeee754Float64Tanh:
ASSEMBLE_IEEE754_UNOP(tanh);
break;
case kArm64Float32RoundDown:
__ Frintm(i.OutputFloat32Register(), i.InputFloat32Register(0));
break;
......
......@@ -111,6 +111,7 @@ class Schedule;
V(Float64Atan) \
V(Float64Atanh) \
V(Float64Cos) \
V(Float64Cosh) \
V(Float64Exp) \
V(Float64Expm1) \
V(Float64Log) \
......@@ -120,8 +121,10 @@ class Schedule;
V(Float64Cbrt) \
V(Float64Neg) \
V(Float64Sin) \
V(Float64Sinh) \
V(Float64Sqrt) \
V(Float64Tan) \
V(Float64Tanh) \
V(Float64ExtractLowWord32) \
V(Float64ExtractHighWord32) \
V(BitcastWordToTagged) \
......
......@@ -661,6 +661,9 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
case kIeee754Float64Cos:
ASSEMBLE_IEEE754_UNOP(cos);
break;
case kIeee754Float64Cosh:
ASSEMBLE_IEEE754_UNOP(cosh);
break;
case kIeee754Float64Expm1:
ASSEMBLE_IEEE754_UNOP(expm1);
break;
......@@ -700,9 +703,15 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
case kIeee754Float64Sin:
ASSEMBLE_IEEE754_UNOP(sin);
break;
case kIeee754Float64Sinh:
ASSEMBLE_IEEE754_UNOP(sinh);
break;
case kIeee754Float64Tan:
ASSEMBLE_IEEE754_UNOP(tan);
break;
case kIeee754Float64Tanh:
ASSEMBLE_IEEE754_UNOP(tanh);
break;
case kIA32Add:
if (HasImmediateInput(instr, 1)) {
__ add(i.InputOperand(0), i.InputImmediate(1));
......
......@@ -94,6 +94,7 @@ enum class RecordWriteMode { kValueIsMap, kValueIsPointer, kValueIsAny };
V(Ieee754Float64Atanh) \
V(Ieee754Float64Cbrt) \
V(Ieee754Float64Cos) \
V(Ieee754Float64Cosh) \
V(Ieee754Float64Exp) \
V(Ieee754Float64Expm1) \
V(Ieee754Float64Log) \
......@@ -102,7 +103,9 @@ enum class RecordWriteMode { kValueIsMap, kValueIsPointer, kValueIsAny };
V(Ieee754Float64Log2) \
V(Ieee754Float64Pow) \
V(Ieee754Float64Sin) \
V(Ieee754Float64Tan)
V(Ieee754Float64Sinh) \
V(Ieee754Float64Tan) \
V(Ieee754Float64Tanh)
#define ARCH_OPCODE_LIST(V) \
COMMON_ARCH_OPCODE_LIST(V) \
......
......@@ -229,6 +229,7 @@ int InstructionScheduler::GetInstructionFlags(const Instruction* instr) const {
case kIeee754Float64Atanh:
case kIeee754Float64Cbrt:
case kIeee754Float64Cos:
case kIeee754Float64Cosh:
case kIeee754Float64Exp:
case kIeee754Float64Expm1:
case kIeee754Float64Log:
......@@ -237,7 +238,9 @@ int InstructionScheduler::GetInstructionFlags(const Instruction* instr) const {
case kIeee754Float64Log2:
case kIeee754Float64Pow:
case kIeee754Float64Sin:
case kIeee754Float64Sinh:
case kIeee754Float64Tan:
case kIeee754Float64Tanh:
return kNoOpcodeFlags;
case kArchStackPointer:
......
......@@ -1158,6 +1158,8 @@ void InstructionSelector::VisitNode(Node* node) {
return MarkAsFloat64(node), VisitFloat64Cbrt(node);
case IrOpcode::kFloat64Cos:
return MarkAsFloat64(node), VisitFloat64Cos(node);
case IrOpcode::kFloat64Cosh:
return MarkAsFloat64(node), VisitFloat64Cosh(node);
case IrOpcode::kFloat64Exp:
return MarkAsFloat64(node), VisitFloat64Exp(node);
case IrOpcode::kFloat64Expm1:
......@@ -1174,10 +1176,14 @@ void InstructionSelector::VisitNode(Node* node) {
return MarkAsFloat64(node), VisitFloat64Pow(node);
case IrOpcode::kFloat64Sin:
return MarkAsFloat64(node), VisitFloat64Sin(node);
case IrOpcode::kFloat64Sinh:
return MarkAsFloat64(node), VisitFloat64Sinh(node);
case IrOpcode::kFloat64Sqrt:
return MarkAsFloat64(node), VisitFloat64Sqrt(node);
case IrOpcode::kFloat64Tan:
return MarkAsFloat64(node), VisitFloat64Tan(node);
case IrOpcode::kFloat64Tanh:
return MarkAsFloat64(node), VisitFloat64Tanh(node);
case IrOpcode::kFloat64Equal:
return VisitFloat64Equal(node);
case IrOpcode::kFloat64LessThan:
......@@ -1301,6 +1307,10 @@ void InstructionSelector::VisitFloat64Cos(Node* node) {
VisitFloat64Ieee754Unop(node, kIeee754Float64Cos);
}
void InstructionSelector::VisitFloat64Cosh(Node* node) {
VisitFloat64Ieee754Unop(node, kIeee754Float64Cosh);
}
void InstructionSelector::VisitFloat64Exp(Node* node) {
VisitFloat64Ieee754Unop(node, kIeee754Float64Exp);
}
......@@ -1333,10 +1343,18 @@ void InstructionSelector::VisitFloat64Sin(Node* node) {
VisitFloat64Ieee754Unop(node, kIeee754Float64Sin);
}
void InstructionSelector::VisitFloat64Sinh(Node* node) {
VisitFloat64Ieee754Unop(node, kIeee754Float64Sinh);
}
void InstructionSelector::VisitFloat64Tan(Node* node) {
VisitFloat64Ieee754Unop(node, kIeee754Float64Tan);
}
void InstructionSelector::VisitFloat64Tanh(Node* node) {
VisitFloat64Ieee754Unop(node, kIeee754Float64Tanh);
}
void InstructionSelector::EmitTableSwitch(const SwitchInfo& sw,
InstructionOperand& index_operand) {
OperandGenerator g(this);
......
......@@ -177,6 +177,18 @@ Reduction JSBuiltinReducer::ReduceMathCos(Node* node) {
return NoChange();
}
// ES6 section 20.2.2.13 Math.cosh ( x )
Reduction JSBuiltinReducer::ReduceMathCosh(Node* node) {
JSCallReduction r(node);
if (r.InputsMatchOne(Type::PlainPrimitive())) {
// Math.cosh(a:plain-primitive) -> NumberCosh(ToNumber(a))
Node* input = ToNumber(r.GetJSCallInput(0));
Node* value = graph()->NewNode(simplified()->NumberCosh(), input);
return Replace(value);
}
return NoChange();
}
// ES6 section 20.2.2.14 Math.exp ( x )
Reduction JSBuiltinReducer::ReduceMathExp(Node* node) {
JSCallReduction r(node);
......@@ -388,6 +400,18 @@ Reduction JSBuiltinReducer::ReduceMathSin(Node* node) {
return NoChange();
}
// ES6 section 20.2.2.31 Math.sinh ( x )
Reduction JSBuiltinReducer::ReduceMathSinh(Node* node) {
JSCallReduction r(node);
if (r.InputsMatchOne(Type::PlainPrimitive())) {
// Math.sinh(a:plain-primitive) -> NumberSinh(ToNumber(a))
Node* input = ToNumber(r.GetJSCallInput(0));
Node* value = graph()->NewNode(simplified()->NumberSinh(), input);
return Replace(value);
}
return NoChange();
}
// ES6 section 20.2.2.32 Math.sqrt ( x )
Reduction JSBuiltinReducer::ReduceMathSqrt(Node* node) {
JSCallReduction r(node);
......@@ -412,6 +436,18 @@ Reduction JSBuiltinReducer::ReduceMathTan(Node* node) {
return NoChange();
}
// ES6 section 20.2.2.34 Math.tanh ( x )
Reduction JSBuiltinReducer::ReduceMathTanh(Node* node) {
JSCallReduction r(node);
if (r.InputsMatchOne(Type::PlainPrimitive())) {
// Math.tanh(a:plain-primitive) -> NumberTanh(ToNumber(a))
Node* input = ToNumber(r.GetJSCallInput(0));
Node* value = graph()->NewNode(simplified()->NumberTanh(), input);
return Replace(value);
}
return NoChange();
}
// ES6 section 20.2.2.35 Math.trunc ( x )
Reduction JSBuiltinReducer::ReduceMathTrunc(Node* node) {
JSCallReduction r(node);
......@@ -467,6 +503,9 @@ Reduction JSBuiltinReducer::Reduce(Node* node) {
case kMathCos:
reduction = ReduceMathCos(node);
break;
case kMathCosh:
reduction = ReduceMathCosh(node);
break;
case kMathExp:
reduction = ReduceMathExp(node);
break;
......@@ -509,12 +548,18 @@ Reduction JSBuiltinReducer::Reduce(Node* node) {
case kMathSin:
reduction = ReduceMathSin(node);
break;
case kMathSinh:
reduction = ReduceMathSinh(node);
break;
case kMathSqrt:
reduction = ReduceMathSqrt(node);
break;
case kMathTan:
reduction = ReduceMathTan(node);
break;
case kMathTanh:
reduction = ReduceMathTanh(node);
break;
case kMathTrunc:
reduction = ReduceMathTrunc(node);
break;
......
......@@ -37,6 +37,7 @@ class JSBuiltinReducer final : public AdvancedReducer {
Reduction ReduceMathCeil(Node* node);
Reduction ReduceMathClz32(Node* node);
Reduction ReduceMathCos(Node* node);
Reduction ReduceMathCosh(Node* node);
Reduction ReduceMathExp(Node* node);
Reduction ReduceMathExpm1(Node* node);
Reduction ReduceMathFloor(Node* node);
......@@ -51,8 +52,10 @@ class JSBuiltinReducer final : public AdvancedReducer {
Reduction ReduceMathPow(Node* node);
Reduction ReduceMathRound(Node* node);
Reduction ReduceMathSin(Node* node);
Reduction ReduceMathSinh(Node* node);
Reduction ReduceMathSqrt(Node* node);
Reduction ReduceMathTan(Node* node);
Reduction ReduceMathTanh(Node* node);
Reduction ReduceMathTrunc(Node* node);
Reduction ReduceStringFromCharCode(Node* node);
......
......@@ -401,6 +401,11 @@ Reduction MachineOperatorReducer::Reduce(Node* node) {
if (m.HasValue()) return ReplaceFloat64(base::ieee754::cos(m.Value()));
break;
}
case IrOpcode::kFloat64Cosh: {
Float64Matcher m(node->InputAt(0));
if (m.HasValue()) return ReplaceFloat64(base::ieee754::cosh(m.Value()));
break;
}
case IrOpcode::kFloat64Exp: {
Float64Matcher m(node->InputAt(0));
if (m.HasValue()) return ReplaceFloat64(base::ieee754::exp(m.Value()));
......@@ -462,11 +467,21 @@ Reduction MachineOperatorReducer::Reduce(Node* node) {
if (m.HasValue()) return ReplaceFloat64(base::ieee754::sin(m.Value()));
break;
}
case IrOpcode::kFloat64Sinh: {
Float64Matcher m(node->InputAt(0));
if (m.HasValue()) return ReplaceFloat64(base::ieee754::sinh(m.Value()));
break;
}
case IrOpcode::kFloat64Tan: {
Float64Matcher m(node->InputAt(0));
if (m.HasValue()) return ReplaceFloat64(base::ieee754::tan(m.Value()));
break;
}
case IrOpcode::kFloat64Tanh: {
Float64Matcher m(node->InputAt(0));
if (m.HasValue()) return ReplaceFloat64(base::ieee754::tanh(m.Value()));
break;
}
case IrOpcode::kChangeFloat32ToFloat64: {
Float32Matcher m(node->InputAt(0));
if (m.HasValue()) return ReplaceFloat64(m.Value());
......
......@@ -154,6 +154,7 @@ MachineRepresentation AtomicStoreRepresentationOf(Operator const* op) {
V(Float64Atanh, Operator::kNoProperties, 1, 0, 1) \
V(Float64Cbrt, Operator::kNoProperties, 1, 0, 1) \
V(Float64Cos, Operator::kNoProperties, 1, 0, 1) \
V(Float64Cosh, Operator::kNoProperties, 1, 0, 1) \
V(Float64Exp, Operator::kNoProperties, 1, 0, 1) \
V(Float64Expm1, Operator::kNoProperties, 1, 0, 1) \
V(Float64Log, Operator::kNoProperties, 1, 0, 1) \
......@@ -168,8 +169,10 @@ MachineRepresentation AtomicStoreRepresentationOf(Operator const* op) {
V(Float64Mod, Operator::kNoProperties, 2, 0, 1) \
V(Float64Pow, Operator::kNoProperties, 2, 0, 1) \
V(Float64Sin, Operator::kNoProperties, 1, 0, 1) \
V(Float64Sinh, Operator::kNoProperties, 1, 0, 1) \
V(Float64Sqrt, Operator::kNoProperties, 1, 0, 1) \
V(Float64Tan, Operator::kNoProperties, 1, 0, 1) \
V(Float64Tanh, Operator::kNoProperties, 1, 0, 1) \
V(Float32Equal, Operator::kCommutative, 2, 0, 1) \
V(Float32LessThan, Operator::kNoProperties, 2, 0, 1) \
V(Float32LessThanOrEqual, Operator::kNoProperties, 2, 0, 1) \
......
......@@ -375,8 +375,11 @@ class MachineOperatorBuilder final : public ZoneObject {
// Floating point trigonometric functions (double-precision).
const Operator* Float64Cos();
const Operator* Float64Cosh();
const Operator* Float64Sin();
const Operator* Float64Sinh();
const Operator* Float64Tan();
const Operator* Float64Tanh();
// Floating point exponential functions (double-precision).
const Operator* Float64Exp();
......
......@@ -750,6 +750,9 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
case kIeee754Float64Cos:
ASSEMBLE_IEEE754_UNOP(cos);
break;
case kIeee754Float64Cosh:
ASSEMBLE_IEEE754_UNOP(cosh);
break;
case kIeee754Float64Cbrt:
ASSEMBLE_IEEE754_UNOP(cbrt);
break;
......@@ -782,9 +785,15 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
case kIeee754Float64Sin:
ASSEMBLE_IEEE754_UNOP(sin);
break;
case kIeee754Float64Sinh:
ASSEMBLE_IEEE754_UNOP(sinh);
break;
case kIeee754Float64Tan:
ASSEMBLE_IEEE754_UNOP(tan);
break;
case kIeee754Float64Tanh:
ASSEMBLE_IEEE754_UNOP(tanh);
break;
case kMipsAdd:
__ Addu(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1));
break;
......
......@@ -762,6 +762,9 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
case kIeee754Float64Cos:
ASSEMBLE_IEEE754_UNOP(cos);
break;
case kIeee754Float64Cosh:
ASSEMBLE_IEEE754_UNOP(cosh);
break;
case kIeee754Float64Cbrt:
ASSEMBLE_IEEE754_UNOP(cbrt);
break;
......@@ -791,9 +794,15 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
case kIeee754Float64Sin:
ASSEMBLE_IEEE754_UNOP(sin);
break;
case kIeee754Float64Sinh:
ASSEMBLE_IEEE754_UNOP(sinh);
break;
case kIeee754Float64Tan:
ASSEMBLE_IEEE754_UNOP(tan);
break;
case kIeee754Float64Tanh:
ASSEMBLE_IEEE754_UNOP(tanh);
break;
case kMips64Add:
__ Addu(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1));
break;
......
......@@ -224,6 +224,7 @@
V(NumberClz32) \
V(NumberCeil) \
V(NumberCos) \
V(NumberCosh) \
V(NumberFloor) \
V(NumberFround) \
V(NumberAtan) \
......@@ -239,8 +240,10 @@
V(NumberPow) \
V(NumberRound) \
V(NumberSin) \
V(NumberSinh) \
V(NumberSqrt) \
V(NumberTan) \
V(NumberTanh) \
V(NumberTrunc) \
V(NumberToInt32) \
V(NumberToUint32) \
......@@ -398,6 +401,7 @@
V(Float64Atanh) \
V(Float64Cbrt) \
V(Float64Cos) \
V(Float64Cosh) \
V(Float64Exp) \
V(Float64Expm1) \
V(Float64Log) \
......@@ -406,8 +410,10 @@
V(Float64Log2) \
V(Float64Pow) \
V(Float64Sin) \
V(Float64Sinh) \
V(Float64Sqrt) \
V(Float64Tan) \
V(Float64Tanh) \
V(Float64RoundDown) \
V(Float32RoundUp) \
V(Float64RoundUp) \
......
......@@ -467,6 +467,7 @@ class RawMachineAssembler {
Node* Float64Atanh(Node* a) { return AddNode(machine()->Float64Atanh(), a); }
Node* Float64Cbrt(Node* a) { return AddNode(machine()->Float64Cbrt(), a); }
Node* Float64Cos(Node* a) { return AddNode(machine()->Float64Cos(), a); }
Node* Float64Cosh(Node* a) { return AddNode(machine()->Float64Cosh(), a); }
Node* Float64Exp(Node* a) { return AddNode(machine()->Float64Exp(), a); }
Node* Float64Expm1(Node* a) { return AddNode(machine()->Float64Expm1(), a); }
Node* Float64Log(Node* a) { return AddNode(machine()->Float64Log(), a); }
......@@ -477,8 +478,10 @@ class RawMachineAssembler {
return AddNode(machine()->Float64Pow(), a, b);
}
Node* Float64Sin(Node* a) { return AddNode(machine()->Float64Sin(), a); }
Node* Float64Sinh(Node* a) { return AddNode(machine()->Float64Sinh(), a); }
Node* Float64Sqrt(Node* a) { return AddNode(machine()->Float64Sqrt(), a); }
Node* Float64Tan(Node* a) { return AddNode(machine()->Float64Tan(), a); }
Node* Float64Tanh(Node* a) { return AddNode(machine()->Float64Tanh(), a); }
Node* Float64Equal(Node* a, Node* b) {
return AddNode(machine()->Float64Equal(), a, b);
}
......
......@@ -697,6 +697,8 @@ const Operator* RepresentationChanger::Float64OperatorFor(
return machine()->Float64Cbrt();
case IrOpcode::kNumberCos:
return machine()->Float64Cos();
case IrOpcode::kNumberCosh:
return machine()->Float64Cosh();
case IrOpcode::kNumberExp:
return machine()->Float64Exp();
case IrOpcode::kNumberExpm1:
......@@ -717,10 +719,14 @@ const Operator* RepresentationChanger::Float64OperatorFor(
return machine()->Float64Pow();
case IrOpcode::kNumberSin:
return machine()->Float64Sin();
case IrOpcode::kNumberSinh:
return machine()->Float64Sinh();
case IrOpcode::kNumberSqrt:
return machine()->Float64Sqrt();
case IrOpcode::kNumberTan:
return machine()->Float64Tan();
case IrOpcode::kNumberTanh:
return machine()->Float64Tanh();
case IrOpcode::kNumberSilenceNaN:
return machine()->Float64SilenceNaN();
default:
......
......@@ -256,6 +256,7 @@ CompareOperationHints::Hint CompareOperationHintOf(const Operator* op) {
V(NumberAtanh, Operator::kNoProperties, 1) \
V(NumberCbrt, Operator::kNoProperties, 1) \
V(NumberCos, Operator::kNoProperties, 1) \
V(NumberCosh, Operator::kNoProperties, 1) \
V(NumberExp, Operator::kNoProperties, 1) \
V(NumberExpm1, Operator::kNoProperties, 1) \
V(NumberLog, Operator::kNoProperties, 1) \
......@@ -265,8 +266,10 @@ CompareOperationHints::Hint CompareOperationHintOf(const Operator* op) {
V(NumberPow, Operator::kNoProperties, 2) \
V(NumberRound, Operator::kNoProperties, 1) \
V(NumberSin, Operator::kNoProperties, 1) \
V(NumberSinh, Operator::kNoProperties, 1) \
V(NumberSqrt, Operator::kNoProperties, 1) \
V(NumberTan, Operator::kNoProperties, 1) \
V(NumberTanh, Operator::kNoProperties, 1) \
V(NumberTrunc, Operator::kNoProperties, 1) \
V(NumberToInt32, Operator::kNoProperties, 1) \
V(NumberToUint32, Operator::kNoProperties, 1) \
......
......@@ -185,6 +185,7 @@ class SimplifiedOperatorBuilder final : public ZoneObject {
const Operator* NumberAtanh();
const Operator* NumberCbrt();
const Operator* NumberCos();
const Operator* NumberCosh();
const Operator* NumberExp();
const Operator* NumberExpm1();
const Operator* NumberLog();
......@@ -194,8 +195,10 @@ class SimplifiedOperatorBuilder final : public ZoneObject {
const Operator* NumberPow();
const Operator* NumberRound();
const Operator* NumberSin();
const Operator* NumberSinh();
const Operator* NumberSqrt();
const Operator* NumberTan();
const Operator* NumberTanh();
const Operator* NumberTrunc();
const Operator* NumberToInt32();
const Operator* NumberToUint32();
......
......@@ -1651,6 +1651,8 @@ Type* Typer::Visitor::TypeNumberAtanh(Node* node) { return Type::Number(); }
Type* Typer::Visitor::TypeNumberCos(Node* node) { return Type::Number(); }
Type* Typer::Visitor::TypeNumberCosh(Node* node) { return Type::Number(); }
Type* Typer::Visitor::TypeNumberExp(Node* node) {
return Type::Union(Type::PlainNumber(), Type::NaN(), zone());
}
......@@ -1676,10 +1678,14 @@ Type* Typer::Visitor::TypeNumberRound(Node* node) {
Type* Typer::Visitor::TypeNumberSin(Node* node) { return Type::Number(); }
Type* Typer::Visitor::TypeNumberSinh(Node* node) { return Type::Number(); }
Type* Typer::Visitor::TypeNumberSqrt(Node* node) { return Type::Number(); }
Type* Typer::Visitor::TypeNumberTan(Node* node) { return Type::Number(); }
Type* Typer::Visitor::TypeNumberTanh(Node* node) { return Type::Number(); }
Type* Typer::Visitor::TypeNumberTrunc(Node* node) {
return TypeUnaryOp(node, NumberTrunc);
}
......@@ -2331,6 +2337,8 @@ Type* Typer::Visitor::TypeFloat64Cbrt(Node* node) { return Type::Number(); }
Type* Typer::Visitor::TypeFloat64Cos(Node* node) { return Type::Number(); }
Type* Typer::Visitor::TypeFloat64Cosh(Node* node) { return Type::Number(); }
Type* Typer::Visitor::TypeFloat64Exp(Node* node) { return Type::Number(); }
Type* Typer::Visitor::TypeFloat64Expm1(Node* node) { return Type::Number(); }
......@@ -2347,10 +2355,14 @@ Type* Typer::Visitor::TypeFloat64Pow(Node* node) { return Type::Number(); }
Type* Typer::Visitor::TypeFloat64Sin(Node* node) { return Type::Number(); }
Type* Typer::Visitor::TypeFloat64Sinh(Node* node) { return Type::Number(); }
Type* Typer::Visitor::TypeFloat64Sqrt(Node* node) { return Type::Number(); }
Type* Typer::Visitor::TypeFloat64Tan(Node* node) { return Type::Number(); }
Type* Typer::Visitor::TypeFloat64Tanh(Node* node) { return Type::Number(); }
Type* Typer::Visitor::TypeFloat64Equal(Node* node) { return Type::Boolean(); }
......
......@@ -755,6 +755,7 @@ void Verifier::Visitor::Check(Node* node) {
case IrOpcode::kNumberAtan:
case IrOpcode::kNumberAtanh:
case IrOpcode::kNumberCos:
case IrOpcode::kNumberCosh:
case IrOpcode::kNumberExp:
case IrOpcode::kNumberExpm1:
case IrOpcode::kNumberLog:
......@@ -764,8 +765,10 @@ void Verifier::Visitor::Check(Node* node) {
case IrOpcode::kNumberCbrt:
case IrOpcode::kNumberRound:
case IrOpcode::kNumberSin:
case IrOpcode::kNumberSinh:
case IrOpcode::kNumberSqrt:
case IrOpcode::kNumberTan:
case IrOpcode::kNumberTanh:
case IrOpcode::kNumberTrunc:
// Number -> Number
CheckValueInputIs(node, 0, Type::Number());
......@@ -1098,6 +1101,7 @@ void Verifier::Visitor::Check(Node* node) {
case IrOpcode::kFloat64Atanh:
case IrOpcode::kFloat64Cbrt:
case IrOpcode::kFloat64Cos:
case IrOpcode::kFloat64Cosh:
case IrOpcode::kFloat64Exp:
case IrOpcode::kFloat64Expm1:
case IrOpcode::kFloat64Log:
......@@ -1106,8 +1110,10 @@ void Verifier::Visitor::Check(Node* node) {
case IrOpcode::kFloat64Log2:
case IrOpcode::kFloat64Pow:
case IrOpcode::kFloat64Sin:
case IrOpcode::kFloat64Sinh:
case IrOpcode::kFloat64Sqrt:
case IrOpcode::kFloat64Tan:
case IrOpcode::kFloat64Tanh:
case IrOpcode::kFloat32RoundDown:
case IrOpcode::kFloat64RoundDown:
case IrOpcode::kFloat32RoundUp:
......
......@@ -882,6 +882,9 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
case kIeee754Float64Cos:
ASSEMBLE_IEEE754_UNOP(cos);
break;
case kIeee754Float64Cosh:
ASSEMBLE_IEEE754_UNOP(cosh);
break;
case kIeee754Float64Exp:
ASSEMBLE_IEEE754_UNOP(exp);
break;
......@@ -911,9 +914,15 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
case kIeee754Float64Sin:
ASSEMBLE_IEEE754_UNOP(sin);
break;
case kIeee754Float64Sinh:
ASSEMBLE_IEEE754_UNOP(sinh);
break;
case kIeee754Float64Tan:
ASSEMBLE_IEEE754_UNOP(tan);
break;
case kIeee754Float64Tanh:
ASSEMBLE_IEEE754_UNOP(tanh);
break;
case kX64Add32:
ASSEMBLE_BINOP(addl);
break;
......
......@@ -75,6 +75,8 @@ ExternalReferenceTable::ExternalReferenceTable(Isolate* isolate) {
"base::ieee754::cbrt");
Add(ExternalReference::ieee754_cos_function(isolate).address(),
"base::ieee754::cos");
Add(ExternalReference::ieee754_cosh_function(isolate).address(),
"base::ieee754::cosh");
Add(ExternalReference::ieee754_exp_function(isolate).address(),
"base::ieee754::exp");
Add(ExternalReference::ieee754_expm1_function(isolate).address(),
......@@ -89,8 +91,12 @@ ExternalReferenceTable::ExternalReferenceTable(Isolate* isolate) {
"base::ieee754::log2");
Add(ExternalReference::ieee754_sin_function(isolate).address(),
"base::ieee754::sin");
Add(ExternalReference::ieee754_sinh_function(isolate).address(),
"base::ieee754::sinh");
Add(ExternalReference::ieee754_tan_function(isolate).address(),
"base::ieee754::tan");
Add(ExternalReference::ieee754_tanh_function(isolate).address(),
"base::ieee754::tanh");
Add(ExternalReference::store_buffer_top(isolate).address(),
"store_buffer_top");
Add(ExternalReference::address_of_the_hole_nan().address(), "the_hole_nan");
......
......@@ -6724,8 +6724,11 @@ class Script: public Struct {
V(Math, max, MathMax) \
V(Math, min, MathMin) \
V(Math, cos, MathCos) \
V(Math, cosh, MathCosh) \
V(Math, sin, MathSin) \
V(Math, sinh, MathSinh) \
V(Math, tan, MathTan) \
V(Math, tanh, MathTanh) \
V(Math, acos, MathAcos) \
V(Math, asin, MathAsin) \
V(Math, atan, MathAtan) \
......
......@@ -26,178 +26,11 @@
// Imports
var GlobalMath = global.Math;
var MathAbs;
var MathExpm1;
utils.Import(function(from) {
MathAbs = from.MathAbs;
MathExpm1 = from.MathExpm1;
});
// ES6 draft 09-27-13, section 20.2.2.30.
// Math.sinh
// Method :
// mathematically sinh(x) if defined to be (exp(x)-exp(-x))/2
// 1. Replace x by |x| (sinh(-x) = -sinh(x)).
// 2.
// E + E/(E+1)
// 0 <= x <= 22 : sinh(x) := --------------, E=expm1(x)
// 2
//
// 22 <= x <= lnovft : sinh(x) := exp(x)/2
// lnovft <= x <= ln2ovft: sinh(x) := exp(x/2)/2 * exp(x/2)
// ln2ovft < x : sinh(x) := x*shuge (overflow)
//
// Special cases:
// sinh(x) is |x| if x is +Infinity, -Infinity, or NaN.
// only sinh(0)=0 is exact for finite x.
//
define KSINH_OVERFLOW = 710.4758600739439;
define TWO_M28 = 3.725290298461914e-9; // 2^-28, empty lower half
define LOG_MAXD = 709.7822265625; // 0x40862e42 00000000, empty lower half
function MathSinh(x) {
x = x * 1; // Convert to number.
var h = (x < 0) ? -0.5 : 0.5;
// |x| in [0, 22]. return sign(x)*0.5*(E+E/(E+1))
var ax = MathAbs(x);
if (ax < 22) {
// For |x| < 2^-28, sinh(x) = x
if (ax < TWO_M28) return x;
var t = MathExpm1(ax);
if (ax < 1) return h * (2 * t - t * t / (t + 1));
return h * (t + t / (t + 1));
}
// |x| in [22, log(maxdouble)], return 0.5 * exp(|x|)
if (ax < LOG_MAXD) return h * %math_exp(ax);
// |x| in [log(maxdouble), overflowthreshold]
// overflowthreshold = 710.4758600739426
if (ax <= KSINH_OVERFLOW) {
var w = %math_exp(0.5 * ax);
var t = h * w;
return t * w;
}
// |x| > overflowthreshold or is NaN.
// Return Infinity of the appropriate sign or NaN.
return x * INFINITY;
}
// ES6 draft 09-27-13, section 20.2.2.12.
// Math.cosh
// Method :
// mathematically cosh(x) if defined to be (exp(x)+exp(-x))/2
// 1. Replace x by |x| (cosh(x) = cosh(-x)).
// 2.
// [ exp(x) - 1 ]^2
// 0 <= x <= ln2/2 : cosh(x) := 1 + -------------------
// 2*exp(x)
//
// exp(x) + 1/exp(x)
// ln2/2 <= x <= 22 : cosh(x) := -------------------
// 2
// 22 <= x <= lnovft : cosh(x) := exp(x)/2
// lnovft <= x <= ln2ovft: cosh(x) := exp(x/2)/2 * exp(x/2)
// ln2ovft < x : cosh(x) := huge*huge (overflow)
//
// Special cases:
// cosh(x) is |x| if x is +INF, -INF, or NaN.
// only cosh(0)=1 is exact for finite x.
//
define KCOSH_OVERFLOW = 710.4758600739439;
function MathCosh(x) {
x = x * 1; // Convert to number.
var ix = %_DoubleHi(x) & 0x7fffffff;
// |x| in [0,0.5*log2], return 1+expm1(|x|)^2/(2*exp(|x|))
if (ix < 0x3fd62e43) {
var t = MathExpm1(MathAbs(x));
var w = 1 + t;
// For |x| < 2^-55, cosh(x) = 1
if (ix < 0x3c800000) return w;
return 1 + (t * t) / (w + w);
}
// |x| in [0.5*log2, 22], return (exp(|x|)+1/exp(|x|)/2
if (ix < 0x40360000) {
var t = %math_exp(MathAbs(x));
return 0.5 * t + 0.5 / t;
}
// |x| in [22, log(maxdouble)], return half*exp(|x|)
if (ix < 0x40862e42) return 0.5 * %math_exp(MathAbs(x));
// |x| in [log(maxdouble), overflowthreshold]
if (MathAbs(x) <= KCOSH_OVERFLOW) {
var w = %math_exp(0.5 * MathAbs(x));
var t = 0.5 * w;
return t * w;
}
if (NUMBER_IS_NAN(x)) return x;
// |x| > overflowthreshold.
return INFINITY;
}
// ES6 draft 09-27-13, section 20.2.2.33.
// Math.tanh(x)
// Method :
// x -x
// e - e
// 0. tanh(x) is defined to be -----------
// x -x
// e + e
// 1. reduce x to non-negative by tanh(-x) = -tanh(x).
// 2. 0 <= x <= 2**-55 : tanh(x) := x*(one+x)
// -t
// 2**-55 < x <= 1 : tanh(x) := -----; t = expm1(-2x)
// t + 2
// 2
// 1 <= x <= 22.0 : tanh(x) := 1- ----- ; t = expm1(2x)
// t + 2
// 22.0 < x <= INF : tanh(x) := 1.
//
// Special cases:
// tanh(NaN) is NaN;
// only tanh(0) = 0 is exact for finite argument.
//
define TWO_M55 = 2.77555756156289135105e-17; // 2^-55, empty lower half
function MathTanh(x) {
x = x * 1; // Convert to number.
// x is Infinity or NaN
if (!NUMBER_IS_FINITE(x)) {
if (x > 0) return 1;
if (x < 0) return -1;
return x;
}
var ax = MathAbs(x);
var z;
// |x| < 22
if (ax < 22) {
if (ax < TWO_M55) {
// |x| < 2^-55, tanh(small) = small.
return x;
}
if (ax >= 1) {
// |x| >= 1
var t = MathExpm1(2 * ax);
z = 1 - 2 / (t + 2);
} else {
var t = MathExpm1(-2 * ax);
z = -t / (t + 2);
}
} else {
// |x| > 22, return +/- 1
z = 1;
}
return (x >= 0) ? z : -z;
}
utils.Import(function(from) {});
//-------------------------------------------------------------------
utils.InstallFunctions(GlobalMath, DONT_ENUM, [
"sinh", MathSinh,
"cosh", MathCosh,
"tanh", MathTanh
]);
utils.InstallFunctions(GlobalMath, DONT_ENUM, []);
})
......@@ -2066,7 +2066,6 @@
'js/array.js',
'js/string.js',
'js/math.js',
'third_party/fdlibm/fdlibm.js',
'js/regexp.js',
'js/arraybuffer.js',
'js/typedarray.js',
......
......@@ -5537,6 +5537,14 @@ TEST(RunFloat64Cos) {
FOR_FLOAT64_INPUTS(i) { CHECK_DOUBLE_EQ(ieee754::cos(*i), m.Call(*i)); }
}
TEST(RunFloat64Cosh) {
BufferedRawMachineAssemblerTester<double> m(MachineType::Float64());
m.Return(m.Float64Cosh(m.Parameter(0)));
CHECK(std::isnan(m.Call(std::numeric_limits<double>::quiet_NaN())));
CHECK(std::isnan(m.Call(std::numeric_limits<double>::signaling_NaN())));
FOR_FLOAT64_INPUTS(i) { CHECK_DOUBLE_EQ(ieee754::cosh(*i), m.Call(*i)); }
}
TEST(RunFloat64Exp) {
BufferedRawMachineAssemblerTester<double> m(MachineType::Float64());
m.Return(m.Float64Exp(m.Parameter(0)));
......@@ -5639,6 +5647,14 @@ TEST(RunFloat64Sin) {
FOR_FLOAT64_INPUTS(i) { CHECK_DOUBLE_EQ(ieee754::sin(*i), m.Call(*i)); }
}
TEST(RunFloat64Sinh) {
BufferedRawMachineAssemblerTester<double> m(MachineType::Float64());
m.Return(m.Float64Sinh(m.Parameter(0)));
CHECK(std::isnan(m.Call(std::numeric_limits<double>::quiet_NaN())));
CHECK(std::isnan(m.Call(std::numeric_limits<double>::signaling_NaN())));
FOR_FLOAT64_INPUTS(i) { CHECK_DOUBLE_EQ(ieee754::sinh(*i), m.Call(*i)); }
}
TEST(RunFloat64Tan) {
BufferedRawMachineAssemblerTester<double> m(MachineType::Float64());
m.Return(m.Float64Tan(m.Parameter(0)));
......@@ -5647,6 +5663,14 @@ TEST(RunFloat64Tan) {
FOR_FLOAT64_INPUTS(i) { CHECK_DOUBLE_EQ(ieee754::tan(*i), m.Call(*i)); }
}
TEST(RunFloat64Tanh) {
BufferedRawMachineAssemblerTester<double> m(MachineType::Float64());
m.Return(m.Float64Tanh(m.Parameter(0)));
CHECK(std::isnan(m.Call(std::numeric_limits<double>::quiet_NaN())));
CHECK(std::isnan(m.Call(std::numeric_limits<double>::signaling_NaN())));
FOR_FLOAT64_INPUTS(i) { CHECK_DOUBLE_EQ(ieee754::tanh(*i), m.Call(*i)); }
}
static double two_30 = 1 << 30; // 2^30 is a smi boundary.
static double two_52 = two_30 * (1 << 22); // 2^52 is a precision boundary.
static double kValues[] = {0.1,
......
......@@ -791,7 +791,7 @@ bool IsCompiled(const char* name) {
TEST(SnapshotDataBlobWithWarmup) {
DisableTurbofan();
const char* warmup = "Math.tanh(1); Math.sinh = 1;";
const char* warmup = "Math.abs(1); Math.random = 1;";
v8::StartupData cold = v8::V8::CreateSnapshotDataBlob();
v8::StartupData warm = v8::V8::WarmUpSnapshotDataBlob(cold, warmup);
......@@ -810,9 +810,9 @@ TEST(SnapshotDataBlobWithWarmup) {
v8::Context::Scope c_scope(context);
// Running the warmup script has effect on whether functions are
// pre-compiled, but does not pollute the context.
CHECK(IsCompiled("Math.tanh"));
CHECK(!IsCompiled("Math.cosh"));
CHECK(CompileRun("Math.sinh")->IsFunction());
CHECK(IsCompiled("Math.abs"));
CHECK(!IsCompiled("Math.sign"));
CHECK(CompileRun("Math.random")->IsFunction());
}
isolate->Dispose();
}
......@@ -820,9 +820,9 @@ TEST(SnapshotDataBlobWithWarmup) {
TEST(CustomSnapshotDataBlobWithWarmup) {
DisableTurbofan();
const char* source =
"function f() { return Math.sinh(1); }\n"
"function g() { return Math.cosh(1); }\n"
"Math.tanh(1);"
"function f() { return Math.abs(1); }\n"
"function g() { return Math.sign(1); }\n"
"Math.asinh(1);"
"var a = 5";
const char* warmup = "a = f()";
......@@ -844,10 +844,10 @@ TEST(CustomSnapshotDataBlobWithWarmup) {
// Running the warmup script has effect on whether functions are
// pre-compiled, but does not pollute the context.
CHECK(IsCompiled("f"));
CHECK(IsCompiled("Math.sinh"));
CHECK(IsCompiled("Math.abs"));
CHECK(!IsCompiled("g"));
CHECK(!IsCompiled("Math.cosh"));
CHECK(!IsCompiled("Math.tanh"));
CHECK(!IsCompiled("Math.sign"));
CHECK(!IsCompiled("Math.asinh"));
CHECK_EQ(5, CompileRun("a")->Int32Value(context).FromJust());
}
isolate->Dispose();
......
......@@ -117,6 +117,18 @@ TEST(Ieee754, Cos) {
EXPECT_EQ(-0.9258790228548379e0, cos(-kTwo120));
}
TEST(Ieee754, Cosh) {
// Test values mentioned in the EcmaScript spec.
EXPECT_THAT(cosh(std::numeric_limits<double>::quiet_NaN()), IsNaN());
EXPECT_THAT(cosh(std::numeric_limits<double>::signaling_NaN()), IsNaN());
EXPECT_THAT(cosh(std::numeric_limits<double>::infinity()),
std::numeric_limits<double>::infinity());
EXPECT_THAT(cosh(-std::numeric_limits<double>::infinity()),
std::numeric_limits<double>::infinity());
EXPECT_EQ(1, cosh(0.0));
EXPECT_EQ(1, cosh(-0.0));
}
TEST(Ieee754, Exp) {
EXPECT_THAT(exp(std::numeric_limits<double>::quiet_NaN()), IsNaN());
EXPECT_THAT(exp(std::numeric_limits<double>::signaling_NaN()), IsNaN());
......@@ -281,6 +293,18 @@ TEST(Ieee754, Sin) {
EXPECT_EQ(-0.377820109360752e0, sin(-kTwo120));
}
TEST(Ieee754, Sinh) {
// Test values mentioned in the EcmaScript spec.
EXPECT_THAT(sinh(std::numeric_limits<double>::quiet_NaN()), IsNaN());
EXPECT_THAT(sinh(std::numeric_limits<double>::signaling_NaN()), IsNaN());
EXPECT_THAT(sinh(std::numeric_limits<double>::infinity()),
std::numeric_limits<double>::infinity());
EXPECT_THAT(sinh(-std::numeric_limits<double>::infinity()),
-std::numeric_limits<double>::infinity());
EXPECT_EQ(0.0, sinh(0.0));
EXPECT_EQ(-0.0, sinh(-0.0));
}
TEST(Ieee754, Tan) {
// Test values mentioned in the EcmaScript spec.
EXPECT_THAT(tan(std::numeric_limits<double>::quiet_NaN()), IsNaN());
......@@ -318,6 +342,16 @@ TEST(Ieee754, Tan) {
EXPECT_EQ(0.40806638884180424e0, tan(-kTwo120));
}
TEST(Ieee754, Tanh) {
// Test values mentioned in the EcmaScript spec.
EXPECT_THAT(tanh(std::numeric_limits<double>::quiet_NaN()), IsNaN());
EXPECT_THAT(tanh(std::numeric_limits<double>::signaling_NaN()), IsNaN());
EXPECT_THAT(tanh(std::numeric_limits<double>::infinity()), 1);
EXPECT_THAT(tanh(-std::numeric_limits<double>::infinity()), -1);
EXPECT_EQ(0.0, tanh(0.0));
EXPECT_EQ(-0.0, tanh(-0.0));
}
} // namespace ieee754
} // namespace base
} // namespace v8
......@@ -341,6 +341,45 @@ TEST_F(JSBuiltinReducerTest, MathCosWithPlainPrimitive) {
EXPECT_THAT(r.replacement(), IsNumberCos(IsPlainPrimitiveToNumber(p0)));
}
// -----------------------------------------------------------------------------
// Math.cosh
TEST_F(JSBuiltinReducerTest, MathCoshWithNumber) {
Node* function = MathFunction("cosh");
Node* effect = graph()->start();
Node* control = graph()->start();
Node* context = UndefinedConstant();
Node* frame_state = graph()->start();
TRACED_FOREACH(Type*, t0, kNumberTypes) {
Node* p0 = Parameter(t0, 0);
Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
UndefinedConstant(), p0, context, frame_state,
effect, control);
Reduction r = Reduce(call);
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), IsNumberCosh(p0));
}
}
TEST_F(JSBuiltinReducerTest, MathCoshWithPlainPrimitive) {
Node* function = MathFunction("cosh");
Node* effect = graph()->start();
Node* control = graph()->start();
Node* context = UndefinedConstant();
Node* frame_state = graph()->start();
Node* p0 = Parameter(Type::PlainPrimitive(), 0);
Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
UndefinedConstant(), p0, context, frame_state,
effect, control);
Reduction r = Reduce(call);
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), IsNumberCosh(IsPlainPrimitiveToNumber(p0)));
}
// -----------------------------------------------------------------------------
// Math.exp
......@@ -874,6 +913,45 @@ TEST_F(JSBuiltinReducerTest, MathSinWithPlainPrimitive) {
EXPECT_THAT(r.replacement(), IsNumberSin(IsPlainPrimitiveToNumber(p0)));
}
// -----------------------------------------------------------------------------
// Math.sinh
TEST_F(JSBuiltinReducerTest, MathSinhWithNumber) {
Node* function = MathFunction("sinh");
Node* effect = graph()->start();
Node* control = graph()->start();
Node* context = UndefinedConstant();
Node* frame_state = graph()->start();
TRACED_FOREACH(Type*, t0, kNumberTypes) {
Node* p0 = Parameter(t0, 0);
Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
UndefinedConstant(), p0, context, frame_state,
effect, control);
Reduction r = Reduce(call);
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), IsNumberSinh(p0));
}
}
TEST_F(JSBuiltinReducerTest, MathSinhWithPlainPrimitive) {
Node* function = MathFunction("sinh");
Node* effect = graph()->start();
Node* control = graph()->start();
Node* context = UndefinedConstant();
Node* frame_state = graph()->start();
Node* p0 = Parameter(Type::PlainPrimitive(), 0);
Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
UndefinedConstant(), p0, context, frame_state,
effect, control);
Reduction r = Reduce(call);
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), IsNumberSinh(IsPlainPrimitiveToNumber(p0)));
}
// -----------------------------------------------------------------------------
// Math.sqrt
......@@ -952,6 +1030,45 @@ TEST_F(JSBuiltinReducerTest, MathTanWithPlainPrimitive) {
EXPECT_THAT(r.replacement(), IsNumberTan(IsPlainPrimitiveToNumber(p0)));
}
// -----------------------------------------------------------------------------
// Math.tanh
TEST_F(JSBuiltinReducerTest, MathTanhWithNumber) {
Node* function = MathFunction("tanh");
Node* effect = graph()->start();
Node* control = graph()->start();
Node* context = UndefinedConstant();
Node* frame_state = graph()->start();
TRACED_FOREACH(Type*, t0, kNumberTypes) {
Node* p0 = Parameter(t0, 0);
Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
UndefinedConstant(), p0, context, frame_state,
effect, control);
Reduction r = Reduce(call);
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), IsNumberTanh(p0));
}
}
TEST_F(JSBuiltinReducerTest, MathTanhWithPlainPrimitive) {
Node* function = MathFunction("tanh");
Node* effect = graph()->start();
Node* control = graph()->start();
Node* context = UndefinedConstant();
Node* frame_state = graph()->start();
Node* p0 = Parameter(Type::PlainPrimitive(), 0);
Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
UndefinedConstant(), p0, context, frame_state,
effect, control);
Reduction r = Reduce(call);
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), IsNumberTanh(IsPlainPrimitiveToNumber(p0)));
}
// -----------------------------------------------------------------------------
// Math.trunc
......
......@@ -1484,6 +1484,20 @@ TEST_F(MachineOperatorReducerTest, Float64CosWithConstant) {
}
}
// -----------------------------------------------------------------------------
// Float64Cosh
TEST_F(MachineOperatorReducerTest, Float64CoshWithConstant) {
TRACED_FOREACH(double, x, kFloat64Values) {
Reduction const r =
Reduce(graph()->NewNode(machine()->Float64Cosh(), Float64Constant(x)));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(
r.replacement(),
IsFloat64Constant(NanSensitiveDoubleEq(base::ieee754::cosh(x))));
}
}
// -----------------------------------------------------------------------------
// Float64Exp
......@@ -1537,6 +1551,20 @@ TEST_F(MachineOperatorReducerTest, Float64SinWithConstant) {
}
}
// -----------------------------------------------------------------------------
// Float64Sinh
TEST_F(MachineOperatorReducerTest, Float64SinhWithConstant) {
TRACED_FOREACH(double, x, kFloat64Values) {
Reduction const r =
Reduce(graph()->NewNode(machine()->Float64Sinh(), Float64Constant(x)));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(
r.replacement(),
IsFloat64Constant(NanSensitiveDoubleEq(base::ieee754::sinh(x))));
}
}
// -----------------------------------------------------------------------------
// Float64Tan
......@@ -1550,6 +1578,20 @@ TEST_F(MachineOperatorReducerTest, Float64TanWithConstant) {
}
}
// -----------------------------------------------------------------------------
// Float64Tanh
TEST_F(MachineOperatorReducerTest, Float64TanhWithConstant) {
TRACED_FOREACH(double, x, kFloat64Values) {
Reduction const r =
Reduce(graph()->NewNode(machine()->Float64Tanh(), Float64Constant(x)));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(
r.replacement(),
IsFloat64Constant(NanSensitiveDoubleEq(base::ieee754::tanh(x))));
}
}
// -----------------------------------------------------------------------------
// Float64InsertLowWord32
......
......@@ -2285,6 +2285,7 @@ IS_UNOP_MATCHER(NumberCeil)
IS_UNOP_MATCHER(NumberClz32)
IS_UNOP_MATCHER(NumberCbrt)
IS_UNOP_MATCHER(NumberCos)
IS_UNOP_MATCHER(NumberCosh)
IS_UNOP_MATCHER(NumberExp)
IS_UNOP_MATCHER(NumberExpm1)
IS_UNOP_MATCHER(NumberFloor)
......@@ -2295,8 +2296,10 @@ IS_UNOP_MATCHER(NumberLog10)
IS_UNOP_MATCHER(NumberLog2)
IS_UNOP_MATCHER(NumberRound)
IS_UNOP_MATCHER(NumberSin)
IS_UNOP_MATCHER(NumberSinh)
IS_UNOP_MATCHER(NumberSqrt)
IS_UNOP_MATCHER(NumberTan)
IS_UNOP_MATCHER(NumberTanh)
IS_UNOP_MATCHER(NumberTrunc)
IS_UNOP_MATCHER(NumberToInt32)
IS_UNOP_MATCHER(NumberToUint32)
......
......@@ -233,6 +233,7 @@ Matcher<Node*> IsNumberCbrt(const Matcher<Node*>& value_matcher);
Matcher<Node*> IsNumberCeil(const Matcher<Node*>& value_matcher);
Matcher<Node*> IsNumberClz32(const Matcher<Node*>& value_matcher);
Matcher<Node*> IsNumberCos(const Matcher<Node*>& value_matcher);
Matcher<Node*> IsNumberCosh(const Matcher<Node*>& value_matcher);
Matcher<Node*> IsNumberExp(const Matcher<Node*>& value_matcher);
Matcher<Node*> IsNumberExpm1(const Matcher<Node*>& value_matcher);
Matcher<Node*> IsNumberFloor(const Matcher<Node*>& value_matcher);
......@@ -245,8 +246,10 @@ Matcher<Node*> IsNumberRound(const Matcher<Node*>& value_matcher);
Matcher<Node*> IsNumberPow(const Matcher<Node*>& lhs_matcher,
const Matcher<Node*>& rhs_matcher);
Matcher<Node*> IsNumberSin(const Matcher<Node*>& value_matcher);
Matcher<Node*> IsNumberSinh(const Matcher<Node*>& value_matcher);
Matcher<Node*> IsNumberSqrt(const Matcher<Node*>& value_matcher);
Matcher<Node*> IsNumberTan(const Matcher<Node*>& value_matcher);
Matcher<Node*> IsNumberTanh(const Matcher<Node*>& value_matcher);
Matcher<Node*> IsNumberTrunc(const Matcher<Node*>& value_matcher);
Matcher<Node*> IsStringFromCharCode(const Matcher<Node*>& value_matcher);
Matcher<Node*> IsAllocate(const Matcher<Node*>& size_matcher,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment