[builtins] Introduce proper Float64Cos and Float64Sin.

Import base::ieee754::cos() and base::ieee754::sin() from fdlibm and
introduce Float64Cos and Float64Sin TurboFan operator based on that,
similar to what we do for Float64Log. Rewrite Math.cos() and Math.sin()
as TurboFan builtins and use those operators to also inline Math.cos()
and Math.sin() into optimized TurboFan functions.

CQ_INCLUDE_TRYBOTS=tryserver.chromium.linux:linux_chromium_rel_ng;tryserver.blink:linux_blink_rel
R=mvstanton@chromium.org
BUG=v8:5086,v8:5118

Review-Url: https://codereview.chromium.org/2073123002
Cr-Commit-Position: refs/heads/master@{#37072}
This commit is contained in:
bmeurer 2016-06-17 08:21:48 -07:00 committed by Commit bot
parent 1298aef51f
commit c781e83194
60 changed files with 1485 additions and 239 deletions

View File

@ -1573,6 +1573,11 @@ ExternalReference ExternalReference::ieee754_atanh_function(Isolate* isolate) {
isolate, FUNCTION_ADDR(base::ieee754::atanh), BUILTIN_FP_FP_CALL));
}
ExternalReference ExternalReference::ieee754_cos_function(Isolate* isolate) {
return ExternalReference(
Redirect(isolate, FUNCTION_ADDR(base::ieee754::cos), BUILTIN_FP_CALL));
}
ExternalReference ExternalReference::ieee754_exp_function(Isolate* isolate) {
return ExternalReference(
Redirect(isolate, FUNCTION_ADDR(base::ieee754::exp), BUILTIN_FP_CALL));
@ -1608,6 +1613,11 @@ ExternalReference ExternalReference::ieee754_expm1_function(Isolate* isolate) {
isolate, FUNCTION_ADDR(base::ieee754::expm1), BUILTIN_FP_FP_CALL));
}
ExternalReference ExternalReference::ieee754_sin_function(Isolate* isolate) {
return ExternalReference(
Redirect(isolate, FUNCTION_ADDR(base::ieee754::sin), BUILTIN_FP_CALL));
}
ExternalReference ExternalReference::page_flags(Page* page) {
return ExternalReference(reinterpret_cast<Address>(page) +
MemoryChunk::kFlagsOffset);

View File

@ -1042,17 +1042,16 @@ class ExternalReference BASE_EMBEDDED {
// IEEE 754 functions.
static ExternalReference ieee754_atan_function(Isolate* isolate);
static ExternalReference ieee754_atan2_function(Isolate* isolate);
static ExternalReference ieee754_exp_function(Isolate* isolate);
static ExternalReference ieee754_log_function(Isolate* isolate);
static ExternalReference ieee754_log1p_function(Isolate* isolate);
static ExternalReference ieee754_log2_function(Isolate* isolate);
static ExternalReference ieee754_log10_function(Isolate* isolate);
static ExternalReference ieee754_atanh_function(Isolate* isolate);
static ExternalReference ieee754_cbrt_function(Isolate* isolate);
static ExternalReference ieee754_cos_function(Isolate* isolate);
static ExternalReference ieee754_exp_function(Isolate* isolate);
static ExternalReference ieee754_expm1_function(Isolate* isolate);
static ExternalReference math_exp_constants(int constant_index);
static ExternalReference math_exp_log_table();
static ExternalReference ieee754_log_function(Isolate* isolate);
static ExternalReference ieee754_log1p_function(Isolate* isolate);
static ExternalReference ieee754_log10_function(Isolate* isolate);
static ExternalReference ieee754_log2_function(Isolate* isolate);
static ExternalReference ieee754_sin_function(Isolate* isolate);
static ExternalReference page_flags(Page* page);

View File

@ -168,6 +168,599 @@ typedef union {
#define STRICT_ASSIGN(type, lval, rval) ((lval) = (rval))
int32_t __ieee754_rem_pio2(double x, double *y) WARN_UNUSED_RESULT;
double __kernel_cos(double x, double y) WARN_UNUSED_RESULT;
int __kernel_rem_pio2(double *x, double *y, int e0, int nx, int prec,
const int32_t *ipio2) WARN_UNUSED_RESULT;
double __kernel_sin(double x, double y, int iy) WARN_UNUSED_RESULT;
/* __ieee754_rem_pio2(x,y)
*
* return the remainder of x rem pi/2 in y[0]+y[1]
* use __kernel_rem_pio2()
*/
int32_t __ieee754_rem_pio2(double x, double *y) {
/*
* Table of constants for 2/pi, 396 Hex digits (476 decimal) of 2/pi
*/
static const int32_t two_over_pi[] = {
0xA2F983, 0x6E4E44, 0x1529FC, 0x2757D1, 0xF534DD, 0xC0DB62, 0x95993C,
0x439041, 0xFE5163, 0xABDEBB, 0xC561B7, 0x246E3A, 0x424DD2, 0xE00649,
0x2EEA09, 0xD1921C, 0xFE1DEB, 0x1CB129, 0xA73EE8, 0x8235F5, 0x2EBB44,
0x84E99C, 0x7026B4, 0x5F7E41, 0x3991D6, 0x398353, 0x39F49C, 0x845F8B,
0xBDF928, 0x3B1FF8, 0x97FFDE, 0x05980F, 0xEF2F11, 0x8B5A0A, 0x6D1F6D,
0x367ECF, 0x27CB09, 0xB74F46, 0x3F669E, 0x5FEA2D, 0x7527BA, 0xC7EBE5,
0xF17B3D, 0x0739F7, 0x8A5292, 0xEA6BFB, 0x5FB11F, 0x8D5D08, 0x560330,
0x46FC7B, 0x6BABF0, 0xCFBC20, 0x9AF436, 0x1DA9E3, 0x91615E, 0xE61B08,
0x659985, 0x5F14A0, 0x68408D, 0xFFD880, 0x4D7327, 0x310606, 0x1556CA,
0x73A8C9, 0x60E27B, 0xC08C6B,
};
static const int32_t npio2_hw[] = {
0x3FF921FB, 0x400921FB, 0x4012D97C, 0x401921FB, 0x401F6A7A, 0x4022D97C,
0x4025FDBB, 0x402921FB, 0x402C463A, 0x402F6A7A, 0x4031475C, 0x4032D97C,
0x40346B9C, 0x4035FDBB, 0x40378FDB, 0x403921FB, 0x403AB41B, 0x403C463A,
0x403DD85A, 0x403F6A7A, 0x40407E4C, 0x4041475C, 0x4042106C, 0x4042D97C,
0x4043A28C, 0x40446B9C, 0x404534AC, 0x4045FDBB, 0x4046C6CB, 0x40478FDB,
0x404858EB, 0x404921FB,
};
/*
* invpio2: 53 bits of 2/pi
* pio2_1: first 33 bit of pi/2
* pio2_1t: pi/2 - pio2_1
* pio2_2: second 33 bit of pi/2
* pio2_2t: pi/2 - (pio2_1+pio2_2)
* pio2_3: third 33 bit of pi/2
* pio2_3t: pi/2 - (pio2_1+pio2_2+pio2_3)
*/
static const double
zero = 0.00000000000000000000e+00, /* 0x00000000, 0x00000000 */
half = 5.00000000000000000000e-01, /* 0x3FE00000, 0x00000000 */
two24 = 1.67772160000000000000e+07, /* 0x41700000, 0x00000000 */
invpio2 = 6.36619772367581382433e-01, /* 0x3FE45F30, 0x6DC9C883 */
pio2_1 = 1.57079632673412561417e+00, /* 0x3FF921FB, 0x54400000 */
pio2_1t = 6.07710050650619224932e-11, /* 0x3DD0B461, 0x1A626331 */
pio2_2 = 6.07710050630396597660e-11, /* 0x3DD0B461, 0x1A600000 */
pio2_2t = 2.02226624879595063154e-21, /* 0x3BA3198A, 0x2E037073 */
pio2_3 = 2.02226624871116645580e-21, /* 0x3BA3198A, 0x2E000000 */
pio2_3t = 8.47842766036889956997e-32; /* 0x397B839A, 0x252049C1 */
double z, w, t, r, fn;
double tx[3];
int32_t e0, i, j, nx, n, ix, hx;
u_int32_t low;
z = 0;
GET_HIGH_WORD(hx, x); /* high word of x */
ix = hx & 0x7fffffff;
if (ix <= 0x3fe921fb) { /* |x| ~<= pi/4 , no need for reduction */
y[0] = x;
y[1] = 0;
return 0;
}
if (ix < 0x4002d97c) { /* |x| < 3pi/4, special case with n=+-1 */
if (hx > 0) {
z = x - pio2_1;
if (ix != 0x3ff921fb) { /* 33+53 bit pi is good enough */
y[0] = z - pio2_1t;
y[1] = (z - y[0]) - pio2_1t;
} else { /* near pi/2, use 33+33+53 bit pi */
z -= pio2_2;
y[0] = z - pio2_2t;
y[1] = (z - y[0]) - pio2_2t;
}
return 1;
} else { /* negative x */
z = x + pio2_1;
if (ix != 0x3ff921fb) { /* 33+53 bit pi is good enough */
y[0] = z + pio2_1t;
y[1] = (z - y[0]) + pio2_1t;
} else { /* near pi/2, use 33+33+53 bit pi */
z += pio2_2;
y[0] = z + pio2_2t;
y[1] = (z - y[0]) + pio2_2t;
}
return -1;
}
}
if (ix <= 0x413921fb) { /* |x| ~<= 2^19*(pi/2), medium size */
t = fabs(x);
n = static_cast<int32_t>(t * invpio2 + half);
fn = static_cast<double>(n);
r = t - fn * pio2_1;
w = fn * pio2_1t; /* 1st round good to 85 bit */
if (n < 32 && ix != npio2_hw[n - 1]) {
y[0] = r - w; /* quick check no cancellation */
} else {
u_int32_t high;
j = ix >> 20;
y[0] = r - w;
GET_HIGH_WORD(high, y[0]);
i = j - ((high >> 20) & 0x7ff);
if (i > 16) { /* 2nd iteration needed, good to 118 */
t = r;
w = fn * pio2_2;
r = t - w;
w = fn * pio2_2t - ((t - r) - w);
y[0] = r - w;
GET_HIGH_WORD(high, y[0]);
i = j - ((high >> 20) & 0x7ff);
if (i > 49) { /* 3rd iteration need, 151 bits acc */
t = r; /* will cover all possible cases */
w = fn * pio2_3;
r = t - w;
w = fn * pio2_3t - ((t - r) - w);
y[0] = r - w;
}
}
}
y[1] = (r - y[0]) - w;
if (hx < 0) {
y[0] = -y[0];
y[1] = -y[1];
return -n;
} else {
return n;
}
}
/*
* all other (large) arguments
*/
if (ix >= 0x7ff00000) { /* x is inf or NaN */
y[0] = y[1] = x - x;
return 0;
}
/* set z = scalbn(|x|,ilogb(x)-23) */
GET_LOW_WORD(low, x);
SET_LOW_WORD(z, low);
e0 = (ix >> 20) - 1046; /* e0 = ilogb(z)-23; */
SET_HIGH_WORD(z, ix - static_cast<int32_t>(e0 << 20));
for (i = 0; i < 2; i++) {
tx[i] = static_cast<double>(static_cast<int32_t>(z));
z = (z - tx[i]) * two24;
}
tx[2] = z;
nx = 3;
while (tx[nx - 1] == zero) nx--; /* skip zero term */
n = __kernel_rem_pio2(tx, y, e0, nx, 2, two_over_pi);
if (hx < 0) {
y[0] = -y[0];
y[1] = -y[1];
return -n;
}
return n;
}
/* __kernel_cos( x, y )
* kernel cos function on [-pi/4, pi/4], pi/4 ~ 0.785398164
* Input x is assumed to be bounded by ~pi/4 in magnitude.
* Input y is the tail of x.
*
* Algorithm
* 1. Since cos(-x) = cos(x), we need only to consider positive x.
* 2. if x < 2^-27 (hx<0x3e400000 0), return 1 with inexact if x!=0.
* 3. cos(x) is approximated by a polynomial of degree 14 on
* [0,pi/4]
* 4 14
* cos(x) ~ 1 - x*x/2 + C1*x + ... + C6*x
* where the remez error is
*
* | 2 4 6 8 10 12 14 | -58
* |cos(x)-(1-.5*x +C1*x +C2*x +C3*x +C4*x +C5*x +C6*x )| <= 2
* | |
*
* 4 6 8 10 12 14
* 4. let r = C1*x +C2*x +C3*x +C4*x +C5*x +C6*x , then
* cos(x) = 1 - x*x/2 + r
* since cos(x+y) ~ cos(x) - sin(x)*y
* ~ cos(x) - x*y,
* a correction term is necessary in cos(x) and hence
* cos(x+y) = 1 - (x*x/2 - (r - x*y))
* For better accuracy when x > 0.3, let qx = |x|/4 with
* the last 32 bits mask off, and if x > 0.78125, let qx = 0.28125.
* Then
* cos(x+y) = (1-qx) - ((x*x/2-qx) - (r-x*y)).
* Note that 1-qx and (x*x/2-qx) is EXACT here, and the
* magnitude of the latter is at least a quarter of x*x/2,
* thus, reducing the rounding error in the subtraction.
*/
V8_INLINE double __kernel_cos(double x, double y) {
static const double
one = 1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */
C1 = 4.16666666666666019037e-02, /* 0x3FA55555, 0x5555554C */
C2 = -1.38888888888741095749e-03, /* 0xBF56C16C, 0x16C15177 */
C3 = 2.48015872894767294178e-05, /* 0x3EFA01A0, 0x19CB1590 */
C4 = -2.75573143513906633035e-07, /* 0xBE927E4F, 0x809C52AD */
C5 = 2.08757232129817482790e-09, /* 0x3E21EE9E, 0xBDB4B1C4 */
C6 = -1.13596475577881948265e-11; /* 0xBDA8FAE9, 0xBE8838D4 */
double a, hz, z, r, qx;
int32_t ix;
GET_HIGH_WORD(ix, x);
ix &= 0x7fffffff; /* ix = |x|'s high word*/
if (ix < 0x3e400000) { /* if x < 2**27 */
if (static_cast<int>(x) == 0) return one; /* generate inexact */
}
z = x * x;
r = z * (C1 + z * (C2 + z * (C3 + z * (C4 + z * (C5 + z * C6)))));
if (ix < 0x3FD33333) { /* if |x| < 0.3 */
return one - (0.5 * z - (z * r - x * y));
} else {
if (ix > 0x3fe90000) { /* x > 0.78125 */
qx = 0.28125;
} else {
INSERT_WORDS(qx, ix - 0x00200000, 0); /* x/4 */
}
hz = 0.5 * z - qx;
a = one - qx;
return a - (hz - (z * r - x * y));
}
}
/* __kernel_rem_pio2(x,y,e0,nx,prec,ipio2)
* double x[],y[]; int e0,nx,prec; int ipio2[];
*
* __kernel_rem_pio2 return the last three digits of N with
* y = x - N*pi/2
* so that |y| < pi/2.
*
* The method is to compute the integer (mod 8) and fraction parts of
* (2/pi)*x without doing the full multiplication. In general we
* skip the part of the product that are known to be a huge integer (
* more accurately, = 0 mod 8 ). Thus the number of operations are
* independent of the exponent of the input.
*
* (2/pi) is represented by an array of 24-bit integers in ipio2[].
*
* Input parameters:
* x[] The input value (must be positive) is broken into nx
* pieces of 24-bit integers in double precision format.
* x[i] will be the i-th 24 bit of x. The scaled exponent
* of x[0] is given in input parameter e0 (i.e., x[0]*2^e0
* match x's up to 24 bits.
*
* Example of breaking a double positive z into x[0]+x[1]+x[2]:
* e0 = ilogb(z)-23
* z = scalbn(z,-e0)
* for i = 0,1,2
* x[i] = floor(z)
* z = (z-x[i])*2**24
*
*
* y[] output result in an array of double precision numbers.
* The dimension of y[] is:
* 24-bit precision 1
* 53-bit precision 2
* 64-bit precision 2
* 113-bit precision 3
* The actual value is the sum of them. Thus for 113-bit
* precison, one may have to do something like:
*
* long double t,w,r_head, r_tail;
* t = (long double)y[2] + (long double)y[1];
* w = (long double)y[0];
* r_head = t+w;
* r_tail = w - (r_head - t);
*
* e0 The exponent of x[0]
*
* nx dimension of x[]
*
* prec an integer indicating the precision:
* 0 24 bits (single)
* 1 53 bits (double)
* 2 64 bits (extended)
* 3 113 bits (quad)
*
* ipio2[]
* integer array, contains the (24*i)-th to (24*i+23)-th
* bit of 2/pi after binary point. The corresponding
* floating value is
*
* ipio2[i] * 2^(-24(i+1)).
*
* External function:
* double scalbn(), floor();
*
*
* Here is the description of some local variables:
*
* jk jk+1 is the initial number of terms of ipio2[] needed
* in the computation. The recommended value is 2,3,4,
* 6 for single, double, extended,and quad.
*
* jz local integer variable indicating the number of
* terms of ipio2[] used.
*
* jx nx - 1
*
* jv index for pointing to the suitable ipio2[] for the
* computation. In general, we want
* ( 2^e0*x[0] * ipio2[jv-1]*2^(-24jv) )/8
* is an integer. Thus
* e0-3-24*jv >= 0 or (e0-3)/24 >= jv
* Hence jv = max(0,(e0-3)/24).
*
* jp jp+1 is the number of terms in PIo2[] needed, jp = jk.
*
* q[] double array with integral value, representing the
* 24-bits chunk of the product of x and 2/pi.
*
* q0 the corresponding exponent of q[0]. Note that the
* exponent for q[i] would be q0-24*i.
*
* PIo2[] double precision array, obtained by cutting pi/2
* into 24 bits chunks.
*
* f[] ipio2[] in floating point
*
* iq[] integer array by breaking up q[] in 24-bits chunk.
*
* fq[] final product of x*(2/pi) in fq[0],..,fq[jk]
*
* ih integer. If >0 it indicates q[] is >= 0.5, hence
* it also indicates the *sign* of the result.
*
*/
int __kernel_rem_pio2(double *x, double *y, int e0, int nx, int prec,
const int32_t *ipio2) {
/* Constants:
* The hexadecimal values are the intended ones for the following
* constants. The decimal values may be used, provided that the
* compiler will convert from decimal to binary accurately enough
* to produce the hexadecimal values shown.
*/
static const int init_jk[] = {2, 3, 4, 6}; /* initial value for jk */
static const double PIo2[] = {
1.57079625129699707031e+00, /* 0x3FF921FB, 0x40000000 */
7.54978941586159635335e-08, /* 0x3E74442D, 0x00000000 */
5.39030252995776476554e-15, /* 0x3CF84698, 0x80000000 */
3.28200341580791294123e-22, /* 0x3B78CC51, 0x60000000 */
1.27065575308067607349e-29, /* 0x39F01B83, 0x80000000 */
1.22933308981111328932e-36, /* 0x387A2520, 0x40000000 */
2.73370053816464559624e-44, /* 0x36E38222, 0x80000000 */
2.16741683877804819444e-51, /* 0x3569F31D, 0x00000000 */
};
static const double
zero = 0.0,
one = 1.0,
two24 = 1.67772160000000000000e+07, /* 0x41700000, 0x00000000 */
twon24 = 5.96046447753906250000e-08; /* 0x3E700000, 0x00000000 */
int32_t jz, jx, jv, jp, jk, carry, n, iq[20], i, j, k, m, q0, ih;
double z, fw, f[20], fq[20], q[20];
/* initialize jk*/
jk = init_jk[prec];
jp = jk;
/* determine jx,jv,q0, note that 3>q0 */
jx = nx - 1;
jv = (e0 - 3) / 24;
if (jv < 0) jv = 0;
q0 = e0 - 24 * (jv + 1);
/* set up f[0] to f[jx+jk] where f[jx+jk] = ipio2[jv+jk] */
j = jv - jx;
m = jx + jk;
for (i = 0; i <= m; i++, j++) {
f[i] = (j < 0) ? zero : static_cast<double>(ipio2[j]);
}
/* compute q[0],q[1],...q[jk] */
for (i = 0; i <= jk; i++) {
for (j = 0, fw = 0.0; j <= jx; j++) fw += x[j] * f[jx + i - j];
q[i] = fw;
}
jz = jk;
recompute:
/* distill q[] into iq[] reversingly */
for (i = 0, j = jz, z = q[jz]; j > 0; i++, j--) {
fw = static_cast<double>(static_cast<int32_t>(twon24 * z));
iq[i] = static_cast<int32_t>(z - two24 * fw);
z = q[j - 1] + fw;
}
/* compute n */
z = scalbn(z, q0); /* actual value of z */
z -= 8.0 * floor(z * 0.125); /* trim off integer >= 8 */
n = static_cast<int32_t>(z);
z -= static_cast<double>(n);
ih = 0;
if (q0 > 0) { /* need iq[jz-1] to determine n */
i = (iq[jz - 1] >> (24 - q0));
n += i;
iq[jz - 1] -= i << (24 - q0);
ih = iq[jz - 1] >> (23 - q0);
} else if (q0 == 0) {
ih = iq[jz - 1] >> 23;
} else if (z >= 0.5) {
ih = 2;
}
if (ih > 0) { /* q > 0.5 */
n += 1;
carry = 0;
for (i = 0; i < jz; i++) { /* compute 1-q */
j = iq[i];
if (carry == 0) {
if (j != 0) {
carry = 1;
iq[i] = 0x1000000 - j;
}
} else {
iq[i] = 0xffffff - j;
}
}
if (q0 > 0) { /* rare case: chance is 1 in 12 */
switch (q0) {
case 1:
iq[jz - 1] &= 0x7fffff;
break;
case 2:
iq[jz - 1] &= 0x3fffff;
break;
}
}
if (ih == 2) {
z = one - z;
if (carry != 0) z -= scalbn(one, q0);
}
}
/* check if recomputation is needed */
if (z == zero) {
j = 0;
for (i = jz - 1; i >= jk; i--) j |= iq[i];
if (j == 0) { /* need recomputation */
for (k = 1; iq[jk - k] == 0; k++) {
/* k = no. of terms needed */
}
for (i = jz + 1; i <= jz + k; i++) { /* add q[jz+1] to q[jz+k] */
f[jx + i] = ipio2[jv + i];
for (j = 0, fw = 0.0; j <= jx; j++) fw += x[j] * f[jx + i - j];
q[i] = fw;
}
jz += k;
goto recompute;
}
}
/* chop off zero terms */
if (z == 0.0) {
jz -= 1;
q0 -= 24;
while (iq[jz] == 0) {
jz--;
q0 -= 24;
}
} else { /* break z into 24-bit if necessary */
z = scalbn(z, -q0);
if (z >= two24) {
fw = static_cast<double>(static_cast<int32_t>(twon24 * z));
iq[jz] = z - two24 * fw;
jz += 1;
q0 += 24;
iq[jz] = fw;
} else {
iq[jz] = z;
}
}
/* convert integer "bit" chunk to floating-point value */
fw = scalbn(one, q0);
for (i = jz; i >= 0; i--) {
q[i] = fw * iq[i];
fw *= twon24;
}
/* compute PIo2[0,...,jp]*q[jz,...,0] */
for (i = jz; i >= 0; i--) {
for (fw = 0.0, k = 0; k <= jp && k <= jz - i; k++) fw += PIo2[k] * q[i + k];
fq[jz - i] = fw;
}
/* compress fq[] into y[] */
switch (prec) {
case 0:
fw = 0.0;
for (i = jz; i >= 0; i--) fw += fq[i];
y[0] = (ih == 0) ? fw : -fw;
break;
case 1:
case 2:
fw = 0.0;
for (i = jz; i >= 0; i--) fw += fq[i];
y[0] = (ih == 0) ? fw : -fw;
fw = fq[0] - fw;
for (i = 1; i <= jz; i++) fw += fq[i];
y[1] = (ih == 0) ? fw : -fw;
break;
case 3: /* painful */
for (i = jz; i > 0; i--) {
fw = fq[i - 1] + fq[i];
fq[i] += fq[i - 1] - fw;
fq[i - 1] = fw;
}
for (i = jz; i > 1; i--) {
fw = fq[i - 1] + fq[i];
fq[i] += fq[i - 1] - fw;
fq[i - 1] = fw;
}
for (fw = 0.0, i = jz; i >= 2; i--) fw += fq[i];
if (ih == 0) {
y[0] = fq[0];
y[1] = fq[1];
y[2] = fw;
} else {
y[0] = -fq[0];
y[1] = -fq[1];
y[2] = -fw;
}
}
return n & 7;
}
/* __kernel_sin( x, y, iy)
* kernel sin function on [-pi/4, pi/4], pi/4 ~ 0.7854
* Input x is assumed to be bounded by ~pi/4 in magnitude.
* Input y is the tail of x.
* Input iy indicates whether y is 0. (if iy=0, y assume to be 0).
*
* Algorithm
* 1. Since sin(-x) = -sin(x), we need only to consider positive x.
* 2. if x < 2^-27 (hx<0x3e400000 0), return x with inexact if x!=0.
* 3. sin(x) is approximated by a polynomial of degree 13 on
* [0,pi/4]
* 3 13
* sin(x) ~ x + S1*x + ... + S6*x
* where
*
* |sin(x) 2 4 6 8 10 12 | -58
* |----- - (1+S1*x +S2*x +S3*x +S4*x +S5*x +S6*x )| <= 2
* | x |
*
* 4. sin(x+y) = sin(x) + sin'(x')*y
* ~ sin(x) + (1-x*x/2)*y
* For better accuracy, let
* 3 2 2 2 2
* r = x *(S2+x *(S3+x *(S4+x *(S5+x *S6))))
* then 3 2
* sin(x) = x + (S1*x + (x *(r-y/2)+y))
*/
V8_INLINE double __kernel_sin(double x, double y, int iy) {
static const double
half = 5.00000000000000000000e-01, /* 0x3FE00000, 0x00000000 */
S1 = -1.66666666666666324348e-01, /* 0xBFC55555, 0x55555549 */
S2 = 8.33333333332248946124e-03, /* 0x3F811111, 0x1110F8A6 */
S3 = -1.98412698298579493134e-04, /* 0xBF2A01A0, 0x19C161D5 */
S4 = 2.75573137070700676789e-06, /* 0x3EC71DE3, 0x57B1FE7D */
S5 = -2.50507602534068634195e-08, /* 0xBE5AE5E6, 0x8A2B9CEB */
S6 = 1.58969099521155010221e-10; /* 0x3DE5D93A, 0x5ACFD57C */
double z, r, v;
int32_t ix;
GET_HIGH_WORD(ix, x);
ix &= 0x7fffffff; /* high word of x */
if (ix < 0x3e400000) { /* |x| < 2**-27 */
if (static_cast<int>(x) == 0) return x;
} /* generate inexact */
z = x * x;
v = z * x;
r = S2 + z * (S3 + z * (S4 + z * (S5 + z * S6)));
if (iy == 0) {
return x + v * (S1 + z * r);
} else {
return x - ((z * (half * y - v * r) - y) - v * S1);
}
}
} // namespace
/* atan(x)
@ -392,6 +985,66 @@ double atan2(double y, double x) {
}
}
/* cos(x)
* Return cosine function of x.
*
* kernel function:
* __kernel_sin ... sine function on [-pi/4,pi/4]
* __kernel_cos ... cosine function on [-pi/4,pi/4]
* __ieee754_rem_pio2 ... argument reduction routine
*
* Method.
* Let S,C and T denote the sin, cos and tan respectively on
* [-PI/4, +PI/4]. Reduce the argument x to y1+y2 = x-k*pi/2
* in [-pi/4 , +pi/4], and let n = k mod 4.
* We have
*
* n sin(x) cos(x) tan(x)
* ----------------------------------------------------------
* 0 S C T
* 1 C -S -1/T
* 2 -S -C T
* 3 -C S -1/T
* ----------------------------------------------------------
*
* Special cases:
* Let trig be any of sin, cos, or tan.
* trig(+-INF) is NaN, with signals;
* trig(NaN) is that NaN;
*
* Accuracy:
* TRIG(x) returns trig(x) nearly rounded
*/
double cos(double x) {
double y[2], z = 0.0;
int32_t n, ix;
/* High word of x. */
GET_HIGH_WORD(ix, x);
/* |x| ~< pi/4 */
ix &= 0x7fffffff;
if (ix <= 0x3fe921fb) {
return __kernel_cos(x, z);
} else if (ix >= 0x7ff00000) {
/* cos(Inf or NaN) is NaN */
return x - x;
} else {
/* argument reduction needed */
n = __ieee754_rem_pio2(x, y);
switch (n & 3) {
case 0:
return __kernel_cos(y[0], y[1]);
case 1:
return -__kernel_sin(y[0], y[1], 1);
case 2:
return -__kernel_cos(y[0], y[1]);
default:
return __kernel_sin(y[0], y[1], 1);
}
}
}
/* exp(x)
* Returns the exponential of x.
*
@ -1410,6 +2063,66 @@ double cbrt(double x) {
return (t);
}
/* sin(x)
* Return sine function of x.
*
* kernel function:
* __kernel_sin ... sine function on [-pi/4,pi/4]
* __kernel_cos ... cose function on [-pi/4,pi/4]
* __ieee754_rem_pio2 ... argument reduction routine
*
* Method.
* Let S,C and T denote the sin, cos and tan respectively on
* [-PI/4, +PI/4]. Reduce the argument x to y1+y2 = x-k*pi/2
* in [-pi/4 , +pi/4], and let n = k mod 4.
* We have
*
* n sin(x) cos(x) tan(x)
* ----------------------------------------------------------
* 0 S C T
* 1 C -S -1/T
* 2 -S -C T
* 3 -C S -1/T
* ----------------------------------------------------------
*
* Special cases:
* Let trig be any of sin, cos, or tan.
* trig(+-INF) is NaN, with signals;
* trig(NaN) is that NaN;
*
* Accuracy:
* TRIG(x) returns trig(x) nearly rounded
*/
double sin(double x) {
double y[2], z = 0.0;
int32_t n, ix;
/* High word of x. */
GET_HIGH_WORD(ix, x);
/* |x| ~< pi/4 */
ix &= 0x7fffffff;
if (ix <= 0x3fe921fb) {
return __kernel_sin(x, z, 0);
} else if (ix >= 0x7ff00000) {
/* sin(Inf or NaN) is NaN */
return x - x;
} else {
/* argument reduction needed */
n = __ieee754_rem_pio2(x, y);
switch (n & 3) {
case 0:
return __kernel_sin(y[0], y[1], 1);
case 1:
return __kernel_cos(y[0], y[1]);
case 2:
return -__kernel_sin(y[0], y[1], 1);
default:
return -__kernel_cos(y[0], y[1]);
}
}
}
} // namespace ieee754
} // namespace base
} // namespace v8

View File

@ -17,6 +17,9 @@ double atan(double x);
// the two arguments to determine the quadrant of the result.
double atan2(double y, double x);
// Returns the cosine of |x|, where |x| is given in radians.
double cos(double x);
// Returns the base-e exponential of |x|.
double exp(double x);
@ -29,18 +32,21 @@ double log(double x);
// accurate even if the value of |x| is near zero.
double log1p(double x);
// Return the base 2 logarithm of |x|.
// Returns the base 2 logarithm of |x|.
double log2(double x);
// Return the base 10 logarithm of |x|.
// Returns the base 10 logarithm of |x|.
double log10(double x);
// Return cube root of |x|.
// Returns the cube root of |x|.
double cbrt(double x);
// Returns exp(x)-1, the exponential of |x| minus 1.
double expm1(double x);
// Returns the sine of |x|, where |x| is given in radians.
double sin(double x);
} // namespace ieee754
} // namespace base
} // namespace v8

View File

@ -1679,6 +1679,7 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
SimpleInstallFunction(math, "cbrt", Builtins::kMathCbrt, 1, true);
SimpleInstallFunction(math, "expm1", Builtins::kMathExpm1, 1, true);
SimpleInstallFunction(math, "clz32", Builtins::kMathClz32, 1, true);
SimpleInstallFunction(math, "cos", Builtins::kMathCos, 1, true);
Handle<JSFunction> math_exp =
SimpleInstallFunction(math, "exp", Builtins::kMathExp, 1, true);
native_context()->set_math_exp(*math_exp);
@ -1696,6 +1697,7 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
SimpleInstallFunction(math, "max", Builtins::kMathMax, 2, false);
SimpleInstallFunction(math, "min", Builtins::kMathMin, 2, false);
SimpleInstallFunction(math, "round", Builtins::kMathRound, 1, true);
SimpleInstallFunction(math, "sin", Builtins::kMathSin, 1, true);
Handle<JSFunction> math_sqrt =
SimpleInstallFunction(math, "sqrt", Builtins::kMathSqrt, 1, true);
native_context()->set_math_sqrt(*math_sqrt);

View File

@ -2421,6 +2421,18 @@ void Builtins::Generate_MathClz32(CodeStubAssembler* assembler) {
}
}
// ES6 section 20.2.2.12 Math.cos ( x )
void Builtins::Generate_MathCos(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->Float64Cos(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;
@ -2525,6 +2537,18 @@ void Builtins::Generate_MathRound(CodeStubAssembler* assembler) {
Generate_MathRoundingOperation(assembler, &CodeStubAssembler::Float64Round);
}
// ES6 section 20.2.2.30 Math.sin ( x )
void Builtins::Generate_MathSin(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->Float64Sin(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;

View File

@ -310,6 +310,7 @@ class CodeStubAssembler;
V(MathCbrt, 2) \
V(MathExpm1, 2) \
V(MathClz32, 2) \
V(MathCos, 2) \
V(MathExp, 2) \
V(MathFloor, 2) \
V(MathLog, 2) \
@ -317,6 +318,7 @@ class CodeStubAssembler;
V(MathLog2, 2) \
V(MathLog10, 2) \
V(MathRound, 2) \
V(MathSin, 2) \
V(MathSqrt, 2) \
V(MathTrunc, 2) \
V(ObjectHasOwnProperty, 2) \
@ -629,6 +631,8 @@ class Builtins {
static void Generate_MathExpm1(CodeStubAssembler* assembler);
// ES6 section 20.2.2.11 Math.clz32 ( x )
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.14 Math.exp ( x )
static void Generate_MathExp(CodeStubAssembler* assembler);
// ES6 section 20.2.2.16 Math.floor ( x )
@ -653,6 +657,8 @@ class Builtins {
}
// ES6 section 20.2.2.28 Math.round ( x )
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.32 Math.sqrt ( x )
static void Generate_MathSqrt(CodeStubAssembler* assembler);
// ES6 section 20.2.2.35 Math.trunc ( x )

View File

@ -709,9 +709,18 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
case kIeee754Float64Atan2:
ASSEMBLE_IEEE754_BINOP(atan2);
break;
case kIeee754Float64Cbrt:
ASSEMBLE_IEEE754_UNOP(cbrt);
break;
case kIeee754Float64Cos:
ASSEMBLE_IEEE754_UNOP(cos);
break;
case kIeee754Float64Exp:
ASSEMBLE_IEEE754_UNOP(exp);
break;
case kIeee754Float64Expm1:
ASSEMBLE_IEEE754_UNOP(expm1);
break;
case kIeee754Float64Atanh:
ASSEMBLE_IEEE754_UNOP(atanh);
break;
@ -727,11 +736,8 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
case kIeee754Float64Log10:
ASSEMBLE_IEEE754_UNOP(log10);
break;
case kIeee754Float64Cbrt:
ASSEMBLE_IEEE754_UNOP(cbrt);
break;
case kIeee754Float64Expm1:
ASSEMBLE_IEEE754_UNOP(expm1);
case kIeee754Float64Sin:
ASSEMBLE_IEEE754_UNOP(sin);
break;
case kArmAdd:
__ add(i.OutputRegister(), i.InputRegister(0), i.InputOperand2(1),

View File

@ -813,9 +813,18 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
case kIeee754Float64Atan2:
ASSEMBLE_IEEE754_BINOP(atan2);
break;
case kIeee754Float64Cos:
ASSEMBLE_IEEE754_UNOP(cos);
break;
case kIeee754Float64Cbrt:
ASSEMBLE_IEEE754_UNOP(cbrt);
break;
case kIeee754Float64Exp:
ASSEMBLE_IEEE754_UNOP(exp);
break;
case kIeee754Float64Expm1:
ASSEMBLE_IEEE754_UNOP(expm1);
break;
case kIeee754Float64Atanh:
ASSEMBLE_IEEE754_UNOP(atanh);
break;
@ -831,11 +840,8 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
case kIeee754Float64Log10:
ASSEMBLE_IEEE754_UNOP(log10);
break;
case kIeee754Float64Cbrt:
ASSEMBLE_IEEE754_UNOP(cbrt);
break;
case kIeee754Float64Expm1:
ASSEMBLE_IEEE754_UNOP(expm1);
case kIeee754Float64Sin:
ASSEMBLE_IEEE754_UNOP(sin);
break;
case kArm64Float32RoundDown:
__ Frintm(i.OutputFloat32Register(), i.InputFloat32Register(0));

View File

@ -109,6 +109,7 @@ class Schedule;
#define CODE_ASSEMBLER_UNARY_OP_LIST(V) \
V(Float64Atan) \
V(Float64Atanh) \
V(Float64Cos) \
V(Float64Exp) \
V(Float64Expm1) \
V(Float64Log) \
@ -117,6 +118,7 @@ class Schedule;
V(Float64Log10) \
V(Float64Cbrt) \
V(Float64Neg) \
V(Float64Sin) \
V(Float64Sqrt) \
V(Float64ExtractLowWord32) \
V(Float64ExtractHighWord32) \

View File

@ -655,6 +655,15 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
case kIeee754Float64Atan2:
ASSEMBLE_IEEE754_BINOP(atan2);
break;
case kIeee754Float64Cbrt:
ASSEMBLE_IEEE754_UNOP(cbrt);
break;
case kIeee754Float64Cos:
ASSEMBLE_IEEE754_UNOP(cos);
break;
case kIeee754Float64Expm1:
ASSEMBLE_IEEE754_UNOP(expm1);
break;
case kIeee754Float64Exp:
ASSEMBLE_IEEE754_UNOP(exp);
break;
@ -673,11 +682,8 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
case kIeee754Float64Log10:
ASSEMBLE_IEEE754_UNOP(log10);
break;
case kIeee754Float64Cbrt:
ASSEMBLE_IEEE754_UNOP(cbrt);
break;
case kIeee754Float64Expm1:
ASSEMBLE_IEEE754_UNOP(expm1);
case kIeee754Float64Sin:
ASSEMBLE_IEEE754_UNOP(sin);
break;
case kIA32Add:
if (HasImmediateInput(instr, 1)) {

View File

@ -92,13 +92,15 @@ enum class RecordWriteMode { kValueIsMap, kValueIsPointer, kValueIsAny };
V(Ieee754Float64Atan) \
V(Ieee754Float64Atan2) \
V(Ieee754Float64Atanh) \
V(Ieee754Float64Cbrt) \
V(Ieee754Float64Cos) \
V(Ieee754Float64Exp) \
V(Ieee754Float64Expm1) \
V(Ieee754Float64Log) \
V(Ieee754Float64Log1p) \
V(Ieee754Float64Log2) \
V(Ieee754Float64Log10) \
V(Ieee754Float64Cbrt)
V(Ieee754Float64Log2) \
V(Ieee754Float64Sin)
#define ARCH_OPCODE_LIST(V) \
COMMON_ARCH_OPCODE_LIST(V) \

View File

@ -227,13 +227,15 @@ int InstructionScheduler::GetInstructionFlags(const Instruction* instr) const {
case kIeee754Float64Atan:
case kIeee754Float64Atan2:
case kIeee754Float64Atanh:
case kIeee754Float64Cbrt:
case kIeee754Float64Cos:
case kIeee754Float64Exp:
case kIeee754Float64Expm1:
case kIeee754Float64Log:
case kIeee754Float64Log1p:
case kIeee754Float64Log2:
case kIeee754Float64Log10:
case kIeee754Float64Cbrt:
case kIeee754Float64Log2:
case kIeee754Float64Sin:
return kNoOpcodeFlags;
case kArchStackPointer:

View File

@ -1140,6 +1140,10 @@ void InstructionSelector::VisitNode(Node* node) {
return MarkAsFloat64(node), VisitFloat64Atan2(node);
case IrOpcode::kFloat64Atanh:
return MarkAsFloat64(node), VisitFloat64Atanh(node);
case IrOpcode::kFloat64Cbrt:
return MarkAsFloat64(node), VisitFloat64Cbrt(node);
case IrOpcode::kFloat64Cos:
return MarkAsFloat64(node), VisitFloat64Cos(node);
case IrOpcode::kFloat64Exp:
return MarkAsFloat64(node), VisitFloat64Exp(node);
case IrOpcode::kFloat64Expm1:
@ -1148,12 +1152,12 @@ void InstructionSelector::VisitNode(Node* node) {
return MarkAsFloat64(node), VisitFloat64Log(node);
case IrOpcode::kFloat64Log1p:
return MarkAsFloat64(node), VisitFloat64Log1p(node);
case IrOpcode::kFloat64Log2:
return MarkAsFloat64(node), VisitFloat64Log2(node);
case IrOpcode::kFloat64Log10:
return MarkAsFloat64(node), VisitFloat64Log10(node);
case IrOpcode::kFloat64Cbrt:
return MarkAsFloat64(node), VisitFloat64Cbrt(node);
case IrOpcode::kFloat64Log2:
return MarkAsFloat64(node), VisitFloat64Log2(node);
case IrOpcode::kFloat64Sin:
return MarkAsFloat64(node), VisitFloat64Sin(node);
case IrOpcode::kFloat64Sqrt:
return MarkAsFloat64(node), VisitFloat64Sqrt(node);
case IrOpcode::kFloat64Equal:
@ -1271,6 +1275,14 @@ void InstructionSelector::VisitFloat64Atanh(Node* node) {
VisitFloat64Ieee754Unop(node, kIeee754Float64Atanh);
}
void InstructionSelector::VisitFloat64Cbrt(Node* node) {
VisitFloat64Ieee754Unop(node, kIeee754Float64Cbrt);
}
void InstructionSelector::VisitFloat64Cos(Node* node) {
VisitFloat64Ieee754Unop(node, kIeee754Float64Cos);
}
void InstructionSelector::VisitFloat64Exp(Node* node) {
VisitFloat64Ieee754Unop(node, kIeee754Float64Exp);
}
@ -1295,8 +1307,8 @@ void InstructionSelector::VisitFloat64Log10(Node* node) {
VisitFloat64Ieee754Unop(node, kIeee754Float64Log10);
}
void InstructionSelector::VisitFloat64Cbrt(Node* node) {
VisitFloat64Ieee754Unop(node, kIeee754Float64Cbrt);
void InstructionSelector::VisitFloat64Sin(Node* node) {
VisitFloat64Ieee754Unop(node, kIeee754Float64Sin);
}
void InstructionSelector::EmitTableSwitch(const SwitchInfo& sw,

View File

@ -153,6 +153,18 @@ Reduction JSBuiltinReducer::ReduceMathClz32(Node* node) {
return NoChange();
}
// ES6 section 20.2.2.12 Math.cos ( x )
Reduction JSBuiltinReducer::ReduceMathCos(Node* node) {
JSCallReduction r(node);
if (r.InputsMatchOne(Type::PlainPrimitive())) {
// Math.cos(a:plain-primitive) -> NumberCos(ToNumber(a))
Node* input = ToNumber(r.GetJSCallInput(0));
Node* value = graph()->NewNode(simplified()->NumberCos(), input);
return Replace(value);
}
return NoChange();
}
// ES6 section 20.2.2.14 Math.exp ( x )
Reduction JSBuiltinReducer::ReduceMathExp(Node* node) {
JSCallReduction r(node);
@ -239,6 +251,28 @@ Reduction JSBuiltinReducer::ReduceMathLog1p(Node* node) {
return NoChange();
}
// ES6 section 20.2.2.22 Math.log10 ( x )
Reduction JSBuiltinReducer::ReduceMathLog10(Node* node) {
JSCallReduction r(node);
if (r.InputsMatchOne(Type::Number())) {
// Math.log10(a:number) -> NumberLog10(a)
Node* value = graph()->NewNode(simplified()->NumberLog10(), r.left());
return Replace(value);
}
return NoChange();
}
// ES6 section 20.2.2.23 Math.log2 ( x )
Reduction JSBuiltinReducer::ReduceMathLog2(Node* node) {
JSCallReduction r(node);
if (r.InputsMatchOne(Type::Number())) {
// Math.log2(a:number) -> NumberLog(a)
Node* value = graph()->NewNode(simplified()->NumberLog2(), r.left());
return Replace(value);
}
return NoChange();
}
// ES6 section 20.2.2.24 Math.max ( value1, value2, ...values )
Reduction JSBuiltinReducer::ReduceMathMax(Node* node) {
JSCallReduction r(node);
@ -293,23 +327,13 @@ Reduction JSBuiltinReducer::ReduceMathMin(Node* node) {
return NoChange();
}
// ES6 section 20.2.2.23 Math.log2 ( x )
Reduction JSBuiltinReducer::ReduceMathLog2(Node* node) {
// ES6 section 20.2.2.28 Math.round ( x )
Reduction JSBuiltinReducer::ReduceMathRound(Node* node) {
JSCallReduction r(node);
if (r.InputsMatchOne(Type::Number())) {
// Math.log2(a:number) -> NumberLog(a)
Node* value = graph()->NewNode(simplified()->NumberLog2(), r.left());
return Replace(value);
}
return NoChange();
}
// ES6 section 20.2.2.22 Math.log10 ( x )
Reduction JSBuiltinReducer::ReduceMathLog10(Node* node) {
JSCallReduction r(node);
if (r.InputsMatchOne(Type::Number())) {
// Math.log10(a:number) -> NumberLog10(a)
Node* value = graph()->NewNode(simplified()->NumberLog10(), r.left());
if (r.InputsMatchOne(Type::PlainPrimitive())) {
// Math.round(a:plain-primitive) -> NumberRound(ToNumber(a))
Node* input = ToNumber(r.GetJSCallInput(0));
Node* value = graph()->NewNode(simplified()->NumberRound(), input);
return Replace(value);
}
return NoChange();
@ -326,13 +350,13 @@ Reduction JSBuiltinReducer::ReduceMathCbrt(Node* node) {
return NoChange();
}
// ES6 section 20.2.2.28 Math.round ( x )
Reduction JSBuiltinReducer::ReduceMathRound(Node* node) {
// ES6 section 20.2.2.30 Math.sin ( x )
Reduction JSBuiltinReducer::ReduceMathSin(Node* node) {
JSCallReduction r(node);
if (r.InputsMatchOne(Type::PlainPrimitive())) {
// Math.round(a:plain-primitive) -> NumberRound(ToNumber(a))
// Math.sin(a:plain-primitive) -> NumberSin(ToNumber(a))
Node* input = ToNumber(r.GetJSCallInput(0));
Node* value = graph()->NewNode(simplified()->NumberRound(), input);
Node* value = graph()->NewNode(simplified()->NumberSin(), input);
return Replace(value);
}
return NoChange();
@ -396,6 +420,9 @@ Reduction JSBuiltinReducer::Reduce(Node* node) {
case kMathCeil:
reduction = ReduceMathCeil(node);
break;
case kMathCos:
reduction = ReduceMathCos(node);
break;
case kMathExp:
reduction = ReduceMathExp(node);
break;
@ -417,12 +444,12 @@ Reduction JSBuiltinReducer::Reduce(Node* node) {
case kMathLog1p:
reduction = ReduceMathLog1p(node);
break;
case kMathLog2:
reduction = ReduceMathLog2(node);
break;
case kMathLog10:
reduction = ReduceMathLog10(node);
break;
case kMathLog2:
reduction = ReduceMathLog2(node);
break;
case kMathMax:
reduction = ReduceMathMax(node);
break;
@ -435,6 +462,9 @@ Reduction JSBuiltinReducer::Reduce(Node* node) {
case kMathRound:
reduction = ReduceMathRound(node);
break;
case kMathSin:
reduction = ReduceMathSin(node);
break;
case kMathSqrt:
reduction = ReduceMathSqrt(node);
break;

View File

@ -34,19 +34,21 @@ class JSBuiltinReducer final : public AdvancedReducer {
Reduction ReduceMathAtanh(Node* node);
Reduction ReduceMathCeil(Node* node);
Reduction ReduceMathClz32(Node* node);
Reduction ReduceMathCos(Node* node);
Reduction ReduceMathExp(Node* node);
Reduction ReduceMathFloor(Node* node);
Reduction ReduceMathFround(Node* node);
Reduction ReduceMathImul(Node* node);
Reduction ReduceMathLog(Node* node);
Reduction ReduceMathLog1p(Node* node);
Reduction ReduceMathLog2(Node* node);
Reduction ReduceMathLog10(Node* node);
Reduction ReduceMathLog2(Node* node);
Reduction ReduceMathMax(Node* node);
Reduction ReduceMathMin(Node* node);
Reduction ReduceMathCbrt(Node* node);
Reduction ReduceMathExpm1(Node* node);
Reduction ReduceMathRound(Node* node);
Reduction ReduceMathSin(Node* node);
Reduction ReduceMathSqrt(Node* node);
Reduction ReduceMathTrunc(Node* node);
Reduction ReduceStringFromCharCode(Node* node);

View File

@ -401,6 +401,11 @@ Reduction MachineOperatorReducer::Reduce(Node* node) {
if (m.HasValue()) return ReplaceFloat64(base::ieee754::atanh(m.Value()));
break;
}
case IrOpcode::kFloat64Cos: {
Float64Matcher m(node->InputAt(0));
if (m.HasValue()) return ReplaceFloat64(base::ieee754::cos(m.Value()));
break;
}
case IrOpcode::kFloat64Exp: {
Float64Matcher m(node->InputAt(0));
if (m.HasValue()) return ReplaceFloat64(base::ieee754::exp(m.Value()));
@ -436,6 +441,11 @@ Reduction MachineOperatorReducer::Reduce(Node* node) {
if (m.HasValue()) return ReplaceFloat64(base::ieee754::cbrt(m.Value()));
break;
}
case IrOpcode::kFloat64Sin: {
Float64Matcher m(node->InputAt(0));
if (m.HasValue()) return ReplaceFloat64(base::ieee754::sin(m.Value()));
break;
}
case IrOpcode::kChangeFloat32ToFloat64: {
Float32Matcher m(node->InputAt(0));
if (m.HasValue()) return ReplaceFloat64(m.Value());

View File

@ -158,19 +158,21 @@ MachineRepresentation AtomicStoreRepresentationOf(Operator const* op) {
V(Float64Atan, Operator::kNoProperties, 1, 0, 1) \
V(Float64Atan2, Operator::kNoProperties, 2, 0, 1) \
V(Float64Atanh, Operator::kNoProperties, 1, 0, 1) \
V(Float64Cbrt, Operator::kNoProperties, 1, 0, 1) \
V(Float64Cos, 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) \
V(Float64Log1p, Operator::kNoProperties, 1, 0, 1) \
V(Float64Log2, Operator::kNoProperties, 1, 0, 1) \
V(Float64Log10, Operator::kNoProperties, 1, 0, 1) \
V(Float64Cbrt, Operator::kNoProperties, 1, 0, 1) \
V(Float64Add, Operator::kCommutative, 2, 0, 1) \
V(Float64Sub, Operator::kNoProperties, 2, 0, 1) \
V(Float64SubPreserveNan, Operator::kNoProperties, 2, 0, 1) \
V(Float64Mul, Operator::kCommutative, 2, 0, 1) \
V(Float64Div, Operator::kNoProperties, 2, 0, 1) \
V(Float64Mod, Operator::kNoProperties, 2, 0, 1) \
V(Float64Sin, Operator::kNoProperties, 1, 0, 1) \
V(Float64Sqrt, Operator::kNoProperties, 1, 0, 1) \
V(Float32Equal, Operator::kCommutative, 2, 0, 1) \
V(Float32LessThan, Operator::kNoProperties, 2, 0, 1) \

View File

@ -373,7 +373,11 @@ class MachineOperatorBuilder final : public ZoneObject {
const Operator* Float64Atan2();
const Operator* Float64Atanh();
// Floating point exponential functions.
// Floating point trigonometric functions (double-precision).
const Operator* Float64Cos();
const Operator* Float64Sin();
// Floating point exponential functions (double-precision).
const Operator* Float64Exp();
// Floating point logarithm (double-precision).

View File

@ -747,29 +747,35 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
case kIeee754Float64Atan2:
ASSEMBLE_IEEE754_BINOP(atan2);
break;
case kIeee754Float64Cos:
ASSEMBLE_IEEE754_UNOP(cos);
break;
case kIeee754Float64Cbrt:
ASSEMBLE_IEEE754_UNOP(cbrt);
break;
case kIeee754Float64Exp:
ASSEMBLE_IEEE754_UNOP(exp);
break;
case kIeee754Float64Expm1:
ASSEMBLE_IEEE754_UNOP(expm1);
break;
case kIeee754Float64Atanh:
ASSEMBLE_IEEE754_UNOP(atanh);
break;
case kIeee754Float64Log:
ASSEMBLE_IEEE754_UNOP(log);
break;
case kIeee754Float64Cbrt:
ASSEMBLE_IEEE754_UNOP(cbrt);
break;
case kIeee754Float64Expm1:
ASSEMBLE_IEEE754_UNOP(expm1);
break;
case kIeee754Float64Log1p:
ASSEMBLE_IEEE754_UNOP(log1p);
break;
case kIeee754Float64Log10:
ASSEMBLE_IEEE754_UNOP(log10);
break;
case kIeee754Float64Log2:
ASSEMBLE_IEEE754_UNOP(log2);
break;
case kIeee754Float64Log10:
ASSEMBLE_IEEE754_UNOP(log10);
case kIeee754Float64Sin:
ASSEMBLE_IEEE754_UNOP(sin);
break;
case kMipsAdd:
__ Addu(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1));

View File

@ -759,6 +759,12 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
case kIeee754Float64Atanh:
ASSEMBLE_IEEE754_UNOP(atanh);
break;
case kIeee754Float64Cos:
ASSEMBLE_IEEE754_UNOP(cos);
break;
case kIeee754Float64Cbrt:
ASSEMBLE_IEEE754_UNOP(cbrt);
break;
case kIeee754Float64Exp:
ASSEMBLE_IEEE754_UNOP(exp);
break;
@ -777,8 +783,8 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
case kIeee754Float64Log10:
ASSEMBLE_IEEE754_UNOP(log10);
break;
case kIeee754Float64Cbrt:
ASSEMBLE_IEEE754_UNOP(cbrt);
case kIeee754Float64Sin:
ASSEMBLE_IEEE754_UNOP(sin);
break;
case kMips64Add:
__ Addu(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1));

View File

@ -199,6 +199,7 @@
V(NumberImul) \
V(NumberClz32) \
V(NumberCeil) \
V(NumberCos) \
V(NumberFloor) \
V(NumberFround) \
V(NumberAtan) \
@ -212,6 +213,7 @@
V(NumberLog10) \
V(NumberCbrt) \
V(NumberRound) \
V(NumberSin) \
V(NumberSqrt) \
V(NumberTrunc) \
V(NumberToInt32) \
@ -376,13 +378,15 @@
V(Float64Atan) \
V(Float64Atan2) \
V(Float64Atanh) \
V(Float64Cbrt) \
V(Float64Cos) \
V(Float64Exp) \
V(Float64Expm1) \
V(Float64Log) \
V(Float64Log1p) \
V(Float64Log2) \
V(Float64Log10) \
V(Float64Cbrt) \
V(Float64Log2) \
V(Float64Sin) \
V(Float64Sqrt) \
V(Float64RoundDown) \
V(Float32RoundUp) \

View File

@ -465,13 +465,15 @@ class RawMachineAssembler {
return AddNode(machine()->Float64Atan2(), a, b);
}
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* 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); }
Node* Float64Log1p(Node* a) { return AddNode(machine()->Float64Log1p(), a); }
Node* Float64Log2(Node* a) { return AddNode(machine()->Float64Log2(), a); }
Node* Float64Log10(Node* a) { return AddNode(machine()->Float64Log10(), a); }
Node* Float64Cbrt(Node* a) { return AddNode(machine()->Float64Cbrt(), a); }
Node* Float64Log2(Node* a) { return AddNode(machine()->Float64Log2(), a); }
Node* Float64Sin(Node* a) { return AddNode(machine()->Float64Sin(), a); }
Node* Float64Sqrt(Node* a) { return AddNode(machine()->Float64Sqrt(), a); }
Node* Float64Equal(Node* a, Node* b) {
return AddNode(machine()->Float64Equal(), a, b);

View File

@ -671,6 +671,8 @@ const Operator* RepresentationChanger::Float64OperatorFor(
return machine()->Float64Atan();
case IrOpcode::kNumberAtan2:
return machine()->Float64Atan2();
case IrOpcode::kNumberCos:
return machine()->Float64Cos();
case IrOpcode::kNumberExp:
return machine()->Float64Exp();
case IrOpcode::kNumberFround:
@ -685,6 +687,8 @@ const Operator* RepresentationChanger::Float64OperatorFor(
return machine()->Float64Log2();
case IrOpcode::kNumberLog10:
return machine()->Float64Log10();
case IrOpcode::kNumberSin:
return machine()->Float64Sin();
case IrOpcode::kNumberSqrt:
return machine()->Float64Sqrt();
case IrOpcode::kNumberCbrt:

View File

@ -1443,13 +1443,15 @@ class RepresentationSelector {
}
case IrOpcode::kNumberAtan:
case IrOpcode::kNumberAtanh:
case IrOpcode::kNumberCos:
case IrOpcode::kNumberExp:
case IrOpcode::kNumberExpm1:
case IrOpcode::kNumberLog:
case IrOpcode::kNumberLog1p:
case IrOpcode::kNumberLog2:
case IrOpcode::kNumberLog10:
case IrOpcode::kNumberCbrt: {
case IrOpcode::kNumberCbrt:
case IrOpcode::kNumberSin: {
VisitUnop(node, UseInfo::TruncatingFloat64(),
MachineRepresentation::kFloat64);
if (lower()) NodeProperties::ChangeOp(node, Float64Op(node));

View File

@ -255,14 +255,16 @@ CompareOperationHints::Hint CompareOperationHintOf(const Operator* op) {
V(NumberAtan, Operator::kNoProperties, 1) \
V(NumberAtan2, Operator::kNoProperties, 2) \
V(NumberAtanh, Operator::kNoProperties, 1) \
V(NumberCbrt, Operator::kNoProperties, 1) \
V(NumberCos, Operator::kNoProperties, 1) \
V(NumberExp, Operator::kNoProperties, 1) \
V(NumberExpm1, Operator::kNoProperties, 1) \
V(NumberLog, Operator::kNoProperties, 1) \
V(NumberLog1p, Operator::kNoProperties, 1) \
V(NumberLog2, Operator::kNoProperties, 1) \
V(NumberLog10, Operator::kNoProperties, 1) \
V(NumberCbrt, Operator::kNoProperties, 1) \
V(NumberLog2, Operator::kNoProperties, 1) \
V(NumberRound, Operator::kNoProperties, 1) \
V(NumberSin, Operator::kNoProperties, 1) \
V(NumberSqrt, Operator::kNoProperties, 1) \
V(NumberTrunc, Operator::kNoProperties, 1) \
V(NumberToInt32, Operator::kNoProperties, 1) \

View File

@ -182,14 +182,16 @@ class SimplifiedOperatorBuilder final : public ZoneObject {
const Operator* NumberAtan();
const Operator* NumberAtan2();
const Operator* NumberAtanh();
const Operator* NumberCbrt();
const Operator* NumberCos();
const Operator* NumberExp();
const Operator* NumberExpm1();
const Operator* NumberLog();
const Operator* NumberLog1p();
const Operator* NumberLog2();
const Operator* NumberLog10();
const Operator* NumberCbrt();
const Operator* NumberLog2();
const Operator* NumberRound();
const Operator* NumberSin();
const Operator* NumberSqrt();
const Operator* NumberTrunc();
const Operator* NumberToInt32();

View File

@ -1803,6 +1803,8 @@ Type* Typer::Visitor::TypeNumberAtan2(Node* node) { return Type::Number(); }
Type* Typer::Visitor::TypeNumberAtanh(Node* node) { return Type::Number(); }
Type* Typer::Visitor::TypeNumberCos(Node* node) { return Type::Number(); }
Type* Typer::Visitor::TypeNumberExp(Node* node) {
return Type::Union(Type::PlainNumber(), Type::NaN(), zone());
}
@ -1824,6 +1826,8 @@ Type* Typer::Visitor::TypeNumberRound(Node* node) {
return TypeUnaryOp(node, NumberRound);
}
Type* Typer::Visitor::TypeNumberSin(Node* node) { return Type::Number(); }
Type* Typer::Visitor::TypeNumberSqrt(Node* node) { return Type::Number(); }
Type* Typer::Visitor::TypeNumberTrunc(Node* node) {
@ -2573,6 +2577,8 @@ Type* Typer::Visitor::TypeFloat64Atan2(Node* node) { return Type::Number(); }
Type* Typer::Visitor::TypeFloat64Atanh(Node* node) { return Type::Number(); }
Type* Typer::Visitor::TypeFloat64Cos(Node* node) { return Type::Number(); }
Type* Typer::Visitor::TypeFloat64Exp(Node* node) { return Type::Number(); }
Type* Typer::Visitor::TypeFloat64Expm1(Node* node) { return Type::Number(); }
@ -2587,6 +2593,8 @@ Type* Typer::Visitor::TypeFloat64Log10(Node* node) { return Type::Number(); }
Type* Typer::Visitor::TypeFloat64Cbrt(Node* node) { return Type::Number(); }
Type* Typer::Visitor::TypeFloat64Sin(Node* node) { return Type::Number(); }
Type* Typer::Visitor::TypeFloat64Sqrt(Node* node) { return Type::Number(); }

View File

@ -754,6 +754,7 @@ void Verifier::Visitor::Check(Node* node) {
case IrOpcode::kNumberFround:
case IrOpcode::kNumberAtan:
case IrOpcode::kNumberAtanh:
case IrOpcode::kNumberCos:
case IrOpcode::kNumberExp:
case IrOpcode::kNumberExpm1:
case IrOpcode::kNumberLog:
@ -762,6 +763,7 @@ void Verifier::Visitor::Check(Node* node) {
case IrOpcode::kNumberLog10:
case IrOpcode::kNumberCbrt:
case IrOpcode::kNumberRound:
case IrOpcode::kNumberSin:
case IrOpcode::kNumberSqrt:
case IrOpcode::kNumberTrunc:
// Number -> Number
@ -1075,6 +1077,7 @@ void Verifier::Visitor::Check(Node* node) {
case IrOpcode::kFloat64Atan:
case IrOpcode::kFloat64Atan2:
case IrOpcode::kFloat64Atanh:
case IrOpcode::kFloat64Cos:
case IrOpcode::kFloat64Exp:
case IrOpcode::kFloat64Expm1:
case IrOpcode::kFloat64Log:
@ -1082,6 +1085,7 @@ void Verifier::Visitor::Check(Node* node) {
case IrOpcode::kFloat64Log2:
case IrOpcode::kFloat64Log10:
case IrOpcode::kFloat64Cbrt:
case IrOpcode::kFloat64Sin:
case IrOpcode::kFloat64Sqrt:
case IrOpcode::kFloat32RoundDown:
case IrOpcode::kFloat64RoundDown:

View File

@ -876,6 +876,12 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
case kIeee754Float64Atanh:
ASSEMBLE_IEEE754_UNOP(atanh);
break;
case kIeee754Float64Cbrt:
ASSEMBLE_IEEE754_UNOP(cbrt);
break;
case kIeee754Float64Cos:
ASSEMBLE_IEEE754_UNOP(cos);
break;
case kIeee754Float64Exp:
ASSEMBLE_IEEE754_UNOP(exp);
break;
@ -894,8 +900,8 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
case kIeee754Float64Log10:
ASSEMBLE_IEEE754_UNOP(log10);
break;
case kIeee754Float64Cbrt:
ASSEMBLE_IEEE754_UNOP(cbrt);
case kIeee754Float64Sin:
ASSEMBLE_IEEE754_UNOP(sin);
break;
case kX64Add32:
ASSEMBLE_BINOP(addl);

View File

@ -1069,6 +1069,10 @@ LInstruction* LChunkBuilder::DoUnaryMathOperation(HUnaryMathOperation* instr) {
return DoMathAbs(instr);
case kMathLog:
return DoMathLog(instr);
case kMathCos:
return DoMathCos(instr);
case kMathSin:
return DoMathSin(instr);
case kMathExp:
return DoMathExp(instr);
case kMathSqrt:
@ -1134,6 +1138,19 @@ LInstruction* LChunkBuilder::DoMathClz32(HUnaryMathOperation* instr) {
return DefineAsRegister(result);
}
LInstruction* LChunkBuilder::DoMathCos(HUnaryMathOperation* instr) {
DCHECK(instr->representation().IsDouble());
DCHECK(instr->value()->representation().IsDouble());
LOperand* input = UseFixedDouble(instr->value(), d0);
return MarkAsCall(DefineFixedDouble(new (zone()) LMathCos(input), d0), instr);
}
LInstruction* LChunkBuilder::DoMathSin(HUnaryMathOperation* instr) {
DCHECK(instr->representation().IsDouble());
DCHECK(instr->value()->representation().IsDouble());
LOperand* input = UseFixedDouble(instr->value(), d0);
return MarkAsCall(DefineFixedDouble(new (zone()) LMathSin(input), d0), instr);
}
LInstruction* LChunkBuilder::DoMathExp(HUnaryMathOperation* instr) {
DCHECK(instr->representation().IsDouble());

View File

@ -98,6 +98,8 @@ class LCodeGen;
V(LoadNamedGeneric) \
V(MathAbs) \
V(MathClz32) \
V(MathCos) \
V(MathSin) \
V(MathExp) \
V(MathFloor) \
V(MathFround) \
@ -905,6 +907,24 @@ class LMathClz32 final : public LTemplateInstruction<1, 1, 0> {
DECLARE_CONCRETE_INSTRUCTION(MathClz32, "math-clz32")
};
class LMathCos final : public LTemplateInstruction<1, 1, 0> {
public:
explicit LMathCos(LOperand* value) { inputs_[0] = value; }
LOperand* value() { return inputs_[0]; }
DECLARE_CONCRETE_INSTRUCTION(MathCos, "math-cos")
};
class LMathSin final : public LTemplateInstruction<1, 1, 0> {
public:
explicit LMathSin(LOperand* value) { inputs_[0] = value; }
LOperand* value() { return inputs_[0]; }
DECLARE_CONCRETE_INSTRUCTION(MathSin, "math-sin")
};
class LMathExp final : public LTemplateInstruction<1, 1, 0> {
public:
explicit LMathExp(LOperand* value) { inputs_[0] = value; }
@ -2532,6 +2552,8 @@ class LChunkBuilder final : public LChunkBuilderBase {
LInstruction* DoMathFround(HUnaryMathOperation* instr);
LInstruction* DoMathAbs(HUnaryMathOperation* instr);
LInstruction* DoMathLog(HUnaryMathOperation* instr);
LInstruction* DoMathCos(HUnaryMathOperation* instr);
LInstruction* DoMathSin(HUnaryMathOperation* instr);
LInstruction* DoMathExp(HUnaryMathOperation* instr);
LInstruction* DoMathSqrt(HUnaryMathOperation* instr);
LInstruction* DoMathPowHalf(HUnaryMathOperation* instr);

View File

@ -3538,6 +3538,19 @@ void LCodeGen::DoPower(LPower* instr) {
}
}
void LCodeGen::DoMathCos(LMathCos* instr) {
__ PrepareCallCFunction(0, 1, scratch0());
__ MovToFloatParameter(ToDoubleRegister(instr->value()));
__ CallCFunction(ExternalReference::ieee754_cos_function(isolate()), 0, 1);
__ MovFromFloatResult(ToDoubleRegister(instr->result()));
}
void LCodeGen::DoMathSin(LMathSin* instr) {
__ PrepareCallCFunction(0, 1, scratch0());
__ MovToFloatParameter(ToDoubleRegister(instr->value()));
__ CallCFunction(ExternalReference::ieee754_sin_function(isolate()), 0, 1);
__ MovFromFloatResult(ToDoubleRegister(instr->result()));
}
void LCodeGen::DoMathExp(LMathExp* instr) {
__ PrepareCallCFunction(0, 1, scratch0());

View File

@ -2459,6 +2459,20 @@ LInstruction* LChunkBuilder::DoUnaryMathOperation(HUnaryMathOperation* instr) {
return result;
}
}
case kMathCos: {
DCHECK(instr->representation().IsDouble());
DCHECK(instr->value()->representation().IsDouble());
LOperand* input = UseFixedDouble(instr->value(), d0);
LMathCos* result = new (zone()) LMathCos(input);
return MarkAsCall(DefineFixedDouble(result, d0), instr);
}
case kMathSin: {
DCHECK(instr->representation().IsDouble());
DCHECK(instr->value()->representation().IsDouble());
LOperand* input = UseFixedDouble(instr->value(), d0);
LMathSin* result = new (zone()) LMathSin(input);
return MarkAsCall(DefineFixedDouble(result, d0), instr);
}
case kMathExp: {
DCHECK(instr->representation().IsDouble());
DCHECK(instr->value()->representation().IsDouble());

View File

@ -104,6 +104,8 @@ class LCodeGen;
V(MathAbs) \
V(MathAbsTagged) \
V(MathClz32) \
V(MathCos) \
V(MathSin) \
V(MathExp) \
V(MathFloorD) \
V(MathFloorI) \
@ -1763,6 +1765,20 @@ class LMathAbsTagged: public LTemplateInstruction<1, 2, 3> {
DECLARE_HYDROGEN_ACCESSOR(UnaryMathOperation)
};
class LMathCos final : public LUnaryMathOperation<0> {
public:
explicit LMathCos(LOperand* value) : LUnaryMathOperation<0>(value) {}
DECLARE_CONCRETE_INSTRUCTION(MathCos, "math-cos")
};
class LMathSin final : public LUnaryMathOperation<0> {
public:
explicit LMathSin(LOperand* value) : LUnaryMathOperation<0>(value) {}
DECLARE_CONCRETE_INSTRUCTION(MathSin, "math-sin")
};
class LMathExp final : public LUnaryMathOperation<0> {
public:
explicit LMathExp(LOperand* value) : LUnaryMathOperation<0>(value) {}

View File

@ -3546,6 +3546,19 @@ void LCodeGen::DoMathAbsTagged(LMathAbsTagged* instr) {
__ Bind(&done);
}
void LCodeGen::DoMathCos(LMathCos* instr) {
DCHECK(instr->IsMarkedAsCall());
DCHECK(ToDoubleRegister(instr->value()).is(d0));
__ CallCFunction(ExternalReference::ieee754_cos_function(isolate()), 0, 1);
DCHECK(ToDoubleRegister(instr->result()).Is(d0));
}
void LCodeGen::DoMathSin(LMathSin* instr) {
DCHECK(instr->IsMarkedAsCall());
DCHECK(ToDoubleRegister(instr->value()).is(d0));
__ CallCFunction(ExternalReference::ieee754_sin_function(isolate()), 0, 1);
DCHECK(ToDoubleRegister(instr->result()).Is(d0));
}
void LCodeGen::DoMathExp(LMathExp* instr) {
DCHECK(instr->IsMarkedAsCall());

View File

@ -1115,10 +1115,14 @@ const char* HUnaryMathOperation::OpName() const {
return "round";
case kMathAbs:
return "abs";
case kMathCos:
return "cos";
case kMathLog:
return "log";
case kMathExp:
return "exp";
case kMathSin:
return "sin";
case kMathSqrt:
return "sqrt";
case kMathPowHalf:
@ -3401,6 +3405,9 @@ HInstruction* HUnaryMathOperation::New(Isolate* isolate, Zone* zone,
}
if (std::isinf(d)) { // +Infinity and -Infinity.
switch (op) {
case kMathCos:
case kMathSin:
return H_CONSTANT_DOUBLE(std::numeric_limits<double>::quiet_NaN());
case kMathExp:
return H_CONSTANT_DOUBLE((d > 0.0) ? d : 0.0);
case kMathLog:
@ -3422,10 +3429,14 @@ HInstruction* HUnaryMathOperation::New(Isolate* isolate, Zone* zone,
}
}
switch (op) {
case kMathCos:
return H_CONSTANT_DOUBLE(base::ieee754::cos(d));
case kMathExp:
return H_CONSTANT_DOUBLE(base::ieee754::exp(d));
case kMathLog:
return H_CONSTANT_DOUBLE(base::ieee754::log(d));
case kMathSin:
return H_CONSTANT_DOUBLE(base::ieee754::sin(d));
case kMathSqrt:
lazily_initialize_fast_sqrt(isolate);
return H_CONSTANT_DOUBLE(fast_sqrt(d, isolate));

View File

@ -2453,9 +2453,11 @@ class HUnaryMathOperation final : public HTemplateInstruction<2> {
return Representation::Tagged();
} else {
switch (op_) {
case kMathCos:
case kMathFloor:
case kMathRound:
case kMathFround:
case kMathSin:
case kMathSqrt:
case kMathPowHalf:
case kMathLog:
@ -2524,9 +2526,11 @@ class HUnaryMathOperation final : public HTemplateInstruction<2> {
// is tagged, and not when it is an unboxed double or unboxed integer.
SetChangesFlag(kNewSpacePromotion);
break;
case kMathCos:
case kMathFround:
case kMathLog:
case kMathExp:
case kMathSin:
case kMathSqrt:
case kMathPowHalf:
set_representation(Representation::Double());

View File

@ -8855,11 +8855,13 @@ bool HOptimizedGraphBuilder::TryInlineBuiltinFunctionCall(Call* expr) {
// We intentionally ignore expr->tail_call_mode() here because builtins
// we inline here do not observe if they were tail called or not.
switch (id) {
case kMathCos:
case kMathExp:
case kMathRound:
case kMathFround:
case kMathFloor:
case kMathAbs:
case kMathSin:
case kMathSqrt:
case kMathLog:
case kMathClz32:
@ -9036,13 +9038,13 @@ bool HOptimizedGraphBuilder::TryInlineBuiltinMethodCall(
return true;
}
break;
case kMathCos:
case kMathExp:
if (!FLAG_fast_math) break;
// Fall through if FLAG_fast_math.
case kMathRound:
case kMathFround:
case kMathFloor:
case kMathAbs:
case kMathSin:
case kMathSqrt:
case kMathLog:
case kMathClz32:

View File

@ -3421,6 +3421,35 @@ void LCodeGen::DoMathClz32(LMathClz32* instr) {
__ Lzcnt(result, input);
}
void LCodeGen::DoMathCos(LMathCos* instr) {
XMMRegister input = ToDoubleRegister(instr->value());
XMMRegister result = ToDoubleRegister(instr->result());
// Pass one double as argument on the stack.
__ PrepareCallCFunction(2, eax);
__ movsd(Operand(esp, 0 * kDoubleSize), input);
__ CallCFunction(ExternalReference::ieee754_cos_function(isolate()), 2);
// Return value is in st(0) on ia32.
// Store it into the result register.
__ sub(esp, Immediate(kDoubleSize));
__ fstp_d(Operand(esp, 0));
__ movsd(result, Operand(esp, 0));
__ add(esp, Immediate(kDoubleSize));
}
void LCodeGen::DoMathSin(LMathSin* instr) {
XMMRegister input = ToDoubleRegister(instr->value());
XMMRegister result = ToDoubleRegister(instr->result());
// Pass one double as argument on the stack.
__ PrepareCallCFunction(2, eax);
__ movsd(Operand(esp, 0 * kDoubleSize), input);
__ CallCFunction(ExternalReference::ieee754_sin_function(isolate()), 2);
// Return value is in st(0) on ia32.
// Store it into the result register.
__ sub(esp, Immediate(kDoubleSize));
__ fstp_d(Operand(esp, 0));
__ movsd(result, Operand(esp, 0));
__ add(esp, Immediate(kDoubleSize));
}
void LCodeGen::DoMathExp(LMathExp* instr) {
XMMRegister input = ToDoubleRegister(instr->value());

View File

@ -1093,6 +1093,8 @@ LInstruction* LChunkBuilder::DoInvokeFunction(HInvokeFunction* instr) {
LInstruction* LChunkBuilder::DoUnaryMathOperation(HUnaryMathOperation* instr) {
switch (instr->op()) {
case kMathCos:
return DoMathCos(instr);
case kMathFloor:
return DoMathFloor(instr);
case kMathRound:
@ -1111,6 +1113,8 @@ LInstruction* LChunkBuilder::DoUnaryMathOperation(HUnaryMathOperation* instr) {
return DoMathPowHalf(instr);
case kMathClz32:
return DoMathClz32(instr);
case kMathSin:
return DoMathSin(instr);
default:
UNREACHABLE();
return NULL;
@ -1177,6 +1181,19 @@ LInstruction* LChunkBuilder::DoMathClz32(HUnaryMathOperation* instr) {
return DefineAsRegister(result);
}
LInstruction* LChunkBuilder::DoMathCos(HUnaryMathOperation* instr) {
DCHECK(instr->representation().IsDouble());
DCHECK(instr->value()->representation().IsDouble());
LOperand* input = UseRegisterAtStart(instr->value());
return MarkAsCall(DefineSameAsFirst(new (zone()) LMathCos(input)), instr);
}
LInstruction* LChunkBuilder::DoMathSin(HUnaryMathOperation* instr) {
DCHECK(instr->representation().IsDouble());
DCHECK(instr->value()->representation().IsDouble());
LOperand* input = UseRegisterAtStart(instr->value());
return MarkAsCall(DefineSameAsFirst(new (zone()) LMathSin(input)), instr);
}
LInstruction* LChunkBuilder::DoMathExp(HUnaryMathOperation* instr) {
DCHECK(instr->representation().IsDouble());

View File

@ -102,6 +102,7 @@ class LCodeGen;
V(LoadRoot) \
V(MathAbs) \
V(MathClz32) \
V(MathCos) \
V(MathExp) \
V(MathFloorD) \
V(MathFloorI) \
@ -111,6 +112,7 @@ class LCodeGen;
V(MathPowHalf) \
V(MathRoundD) \
V(MathRoundI) \
V(MathSin) \
V(MathSqrt) \
V(MaybeGrowElements) \
V(ModByConstI) \
@ -912,6 +914,24 @@ class LMathClz32 final : public LTemplateInstruction<1, 1, 0> {
DECLARE_CONCRETE_INSTRUCTION(MathClz32, "math-clz32")
};
class LMathCos final : public LTemplateInstruction<1, 1, 0> {
public:
explicit LMathCos(LOperand* value) { inputs_[0] = value; }
LOperand* value() { return inputs_[0]; }
DECLARE_CONCRETE_INSTRUCTION(MathCos, "math-cos")
};
class LMathSin final : public LTemplateInstruction<1, 1, 0> {
public:
explicit LMathSin(LOperand* value) { inputs_[0] = value; }
LOperand* value() { return inputs_[0]; }
DECLARE_CONCRETE_INSTRUCTION(MathSin, "math-sin")
};
class LMathExp final : public LTemplateInstruction<1, 1, 0> {
public:
explicit LMathExp(LOperand* value) { inputs_[0] = value; }
@ -2542,6 +2562,8 @@ class LChunkBuilder final : public LChunkBuilderBase {
LInstruction* DoMathFround(HUnaryMathOperation* instr);
LInstruction* DoMathAbs(HUnaryMathOperation* instr);
LInstruction* DoMathLog(HUnaryMathOperation* instr);
LInstruction* DoMathCos(HUnaryMathOperation* instr);
LInstruction* DoMathSin(HUnaryMathOperation* instr);
LInstruction* DoMathExp(HUnaryMathOperation* instr);
LInstruction* DoMathSqrt(HUnaryMathOperation* instr);
LInstruction* DoMathPowHalf(HUnaryMathOperation* instr);

View File

@ -3490,6 +3490,19 @@ void LCodeGen::DoPower(LPower* instr) {
}
}
void LCodeGen::DoMathCos(LMathCos* instr) {
__ PrepareCallCFunction(0, 1, scratch0());
__ MovToFloatParameter(ToDoubleRegister(instr->value()));
__ CallCFunction(ExternalReference::ieee754_cos_function(isolate()), 0, 1);
__ MovFromFloatResult(ToDoubleRegister(instr->result()));
}
void LCodeGen::DoMathSin(LMathSin* instr) {
__ PrepareCallCFunction(0, 1, scratch0());
__ MovToFloatParameter(ToDoubleRegister(instr->value()));
__ CallCFunction(ExternalReference::ieee754_sin_function(isolate()), 0, 1);
__ MovFromFloatResult(ToDoubleRegister(instr->result()));
}
void LCodeGen::DoMathExp(LMathExp* instr) {
__ PrepareCallCFunction(0, 1, scratch0());

View File

@ -1074,6 +1074,10 @@ LInstruction* LChunkBuilder::DoUnaryMathOperation(HUnaryMathOperation* instr) {
return DoMathAbs(instr);
case kMathLog:
return DoMathLog(instr);
case kMathCos:
return DoMathCos(instr);
case kMathSin:
return DoMathSin(instr);
case kMathExp:
return DoMathExp(instr);
case kMathSqrt:
@ -1103,6 +1107,19 @@ LInstruction* LChunkBuilder::DoMathClz32(HUnaryMathOperation* instr) {
return DefineAsRegister(result);
}
LInstruction* LChunkBuilder::DoMathCos(HUnaryMathOperation* instr) {
DCHECK(instr->representation().IsDouble());
DCHECK(instr->value()->representation().IsDouble());
LOperand* input = UseFixedDouble(instr->value(), f4);
return MarkAsCall(DefineFixedDouble(new (zone()) LMathCos(input), f4), instr);
}
LInstruction* LChunkBuilder::DoMathSin(HUnaryMathOperation* instr) {
DCHECK(instr->representation().IsDouble());
DCHECK(instr->value()->representation().IsDouble());
LOperand* input = UseFixedDouble(instr->value(), f4);
return MarkAsCall(DefineFixedDouble(new (zone()) LMathSin(input), f4), instr);
}
LInstruction* LChunkBuilder::DoMathExp(HUnaryMathOperation* instr) {
DCHECK(instr->representation().IsDouble());

View File

@ -97,6 +97,8 @@ class LCodeGen;
V(LoadNamedField) \
V(LoadNamedGeneric) \
V(MathAbs) \
V(MathCos) \
V(MathSin) \
V(MathExp) \
V(MathClz32) \
V(MathFloor) \
@ -882,6 +884,24 @@ class LMathClz32 final : public LTemplateInstruction<1, 1, 0> {
DECLARE_CONCRETE_INSTRUCTION(MathClz32, "math-clz32")
};
class LMathCos final : public LTemplateInstruction<1, 1, 0> {
public:
explicit LMathCos(LOperand* value) { inputs_[0] = value; }
LOperand* value() { return inputs_[0]; }
DECLARE_CONCRETE_INSTRUCTION(MathCos, "math-cos")
};
class LMathSin final : public LTemplateInstruction<1, 1, 0> {
public:
explicit LMathSin(LOperand* value) { inputs_[0] = value; }
LOperand* value() { return inputs_[0]; }
DECLARE_CONCRETE_INSTRUCTION(MathSin, "math-sin")
};
class LMathExp final : public LTemplateInstruction<1, 1, 0> {
public:
explicit LMathExp(LOperand* value) { inputs_[0] = value; }
@ -2490,6 +2510,8 @@ class LChunkBuilder final : public LChunkBuilderBase {
LInstruction* DoMathFround(HUnaryMathOperation* instr);
LInstruction* DoMathAbs(HUnaryMathOperation* instr);
LInstruction* DoMathLog(HUnaryMathOperation* instr);
LInstruction* DoMathCos(HUnaryMathOperation* instr);
LInstruction* DoMathSin(HUnaryMathOperation* instr);
LInstruction* DoMathExp(HUnaryMathOperation* instr);
LInstruction* DoMathSqrt(HUnaryMathOperation* instr);
LInstruction* DoMathPowHalf(HUnaryMathOperation* instr);

View File

@ -3693,6 +3693,19 @@ void LCodeGen::DoPower(LPower* instr) {
}
}
void LCodeGen::DoMathCos(LMathCos* instr) {
__ PrepareCallCFunction(0, 1, scratch0());
__ MovToFloatParameter(ToDoubleRegister(instr->value()));
__ CallCFunction(ExternalReference::ieee754_cos_function(isolate()), 0, 1);
__ MovFromFloatResult(ToDoubleRegister(instr->result()));
}
void LCodeGen::DoMathSin(LMathSin* instr) {
__ PrepareCallCFunction(0, 1, scratch0());
__ MovToFloatParameter(ToDoubleRegister(instr->value()));
__ CallCFunction(ExternalReference::ieee754_sin_function(isolate()), 0, 1);
__ MovFromFloatResult(ToDoubleRegister(instr->result()));
}
void LCodeGen::DoMathExp(LMathExp* instr) {
__ PrepareCallCFunction(0, 1, scratch0());

View File

@ -1074,6 +1074,10 @@ LInstruction* LChunkBuilder::DoUnaryMathOperation(HUnaryMathOperation* instr) {
return DoMathAbs(instr);
case kMathLog:
return DoMathLog(instr);
case kMathCos:
return DoMathCos(instr);
case kMathSin:
return DoMathSin(instr);
case kMathExp:
return DoMathExp(instr);
case kMathSqrt:
@ -1103,6 +1107,19 @@ LInstruction* LChunkBuilder::DoMathClz32(HUnaryMathOperation* instr) {
return DefineAsRegister(result);
}
LInstruction* LChunkBuilder::DoMathCos(HUnaryMathOperation* instr) {
DCHECK(instr->representation().IsDouble());
DCHECK(instr->value()->representation().IsDouble());
LOperand* input = UseFixedDouble(instr->value(), f4);
return MarkAsCall(DefineFixedDouble(new (zone()) LMathCos(input), f4), instr);
}
LInstruction* LChunkBuilder::DoMathSin(HUnaryMathOperation* instr) {
DCHECK(instr->representation().IsDouble());
DCHECK(instr->value()->representation().IsDouble());
LOperand* input = UseFixedDouble(instr->value(), f4);
return MarkAsCall(DefineFixedDouble(new (zone()) LMathSin(input), f4), instr);
}
LInstruction* LChunkBuilder::DoMathExp(HUnaryMathOperation* instr) {
DCHECK(instr->representation().IsDouble());

View File

@ -99,6 +99,8 @@ class LCodeGen;
V(LoadNamedField) \
V(LoadNamedGeneric) \
V(MathAbs) \
V(MathCos) \
V(MathSin) \
V(MathExp) \
V(MathClz32) \
V(MathFloor) \
@ -900,6 +902,24 @@ class LMathClz32 final : public LTemplateInstruction<1, 1, 0> {
DECLARE_CONCRETE_INSTRUCTION(MathClz32, "math-clz32")
};
class LMathCos final : public LTemplateInstruction<1, 1, 0> {
public:
explicit LMathCos(LOperand* value) { inputs_[0] = value; }
LOperand* value() { return inputs_[0]; }
DECLARE_CONCRETE_INSTRUCTION(MathCos, "math-cos")
};
class LMathSin final : public LTemplateInstruction<1, 1, 0> {
public:
explicit LMathSin(LOperand* value) { inputs_[0] = value; }
LOperand* value() { return inputs_[0]; }
DECLARE_CONCRETE_INSTRUCTION(MathSin, "math-sin")
};
class LMathExp final : public LTemplateInstruction<1, 1, 0> {
public:
explicit LMathExp(LOperand* value) { inputs_[0] = value; }
@ -2536,6 +2556,8 @@ class LChunkBuilder final : public LChunkBuilderBase {
LInstruction* DoMathFround(HUnaryMathOperation* instr);
LInstruction* DoMathAbs(HUnaryMathOperation* instr);
LInstruction* DoMathLog(HUnaryMathOperation* instr);
LInstruction* DoMathCos(HUnaryMathOperation* instr);
LInstruction* DoMathSin(HUnaryMathOperation* instr);
LInstruction* DoMathExp(HUnaryMathOperation* instr);
LInstruction* DoMathSqrt(HUnaryMathOperation* instr);
LInstruction* DoMathPowHalf(HUnaryMathOperation* instr);

View File

@ -3598,6 +3598,12 @@ void LCodeGen::DoPower(LPower* instr) {
}
}
void LCodeGen::DoMathCos(LMathCos* instr) {
DCHECK(ToDoubleRegister(instr->value()).is(xmm0));
DCHECK(ToDoubleRegister(instr->result()).is(xmm0));
__ PrepareCallCFunction(1);
__ CallCFunction(ExternalReference::ieee754_cos_function(isolate()), 1);
}
void LCodeGen::DoMathExp(LMathExp* instr) {
DCHECK(ToDoubleRegister(instr->value()).is(xmm0));
@ -3606,6 +3612,12 @@ void LCodeGen::DoMathExp(LMathExp* instr) {
__ CallCFunction(ExternalReference::ieee754_exp_function(isolate()), 1);
}
void LCodeGen::DoMathSin(LMathSin* instr) {
DCHECK(ToDoubleRegister(instr->value()).is(xmm0));
DCHECK(ToDoubleRegister(instr->result()).is(xmm0));
__ PrepareCallCFunction(1);
__ CallCFunction(ExternalReference::ieee754_sin_function(isolate()), 1);
}
void LCodeGen::DoMathLog(LMathLog* instr) {
DCHECK(ToDoubleRegister(instr->value()).is(xmm0));

View File

@ -1090,10 +1090,14 @@ LInstruction* LChunkBuilder::DoUnaryMathOperation(HUnaryMathOperation* instr) {
return DoMathFround(instr);
case kMathAbs:
return DoMathAbs(instr);
case kMathCos:
return DoMathCos(instr);
case kMathLog:
return DoMathLog(instr);
case kMathExp:
return DoMathExp(instr);
case kMathSin:
return DoMathSin(instr);
case kMathSqrt:
return DoMathSqrt(instr);
case kMathPowHalf:
@ -1167,6 +1171,13 @@ LInstruction* LChunkBuilder::DoMathClz32(HUnaryMathOperation* instr) {
return DefineAsRegister(result);
}
LInstruction* LChunkBuilder::DoMathCos(HUnaryMathOperation* instr) {
DCHECK(instr->representation().IsDouble());
DCHECK(instr->value()->representation().IsDouble());
LOperand* input = UseFixedDouble(instr->value(), xmm0);
return MarkAsCall(DefineFixedDouble(new (zone()) LMathCos(input), xmm0),
instr);
}
LInstruction* LChunkBuilder::DoMathExp(HUnaryMathOperation* instr) {
DCHECK(instr->representation().IsDouble());
@ -1176,6 +1187,13 @@ LInstruction* LChunkBuilder::DoMathExp(HUnaryMathOperation* instr) {
instr);
}
LInstruction* LChunkBuilder::DoMathSin(HUnaryMathOperation* instr) {
DCHECK(instr->representation().IsDouble());
DCHECK(instr->value()->representation().IsDouble());
LOperand* input = UseFixedDouble(instr->value(), xmm0);
return MarkAsCall(DefineFixedDouble(new (zone()) LMathSin(input), xmm0),
instr);
}
LInstruction* LChunkBuilder::DoMathSqrt(HUnaryMathOperation* instr) {
LOperand* input = UseAtStart(instr->value());

View File

@ -98,6 +98,7 @@ class LCodeGen;
V(LoadNamedGeneric) \
V(MathAbs) \
V(MathClz32) \
V(MathCos) \
V(MathExp) \
V(MathFloorD) \
V(MathFloorI) \
@ -107,6 +108,7 @@ class LCodeGen;
V(MathPowHalf) \
V(MathRoundD) \
V(MathRoundI) \
V(MathSin) \
V(MathSqrt) \
V(MaybeGrowElements) \
V(ModByConstI) \
@ -909,6 +911,15 @@ class LMathClz32 final : public LTemplateInstruction<1, 1, 0> {
DECLARE_CONCRETE_INSTRUCTION(MathClz32, "math-clz32")
};
class LMathCos final : public LTemplateInstruction<1, 1, 0> {
public:
explicit LMathCos(LOperand* value) { inputs_[0] = value; }
LOperand* value() { return inputs_[0]; }
DECLARE_CONCRETE_INSTRUCTION(MathCos, "math-cos")
};
class LMathExp final : public LTemplateInstruction<1, 1, 0> {
public:
explicit LMathExp(LOperand* value) { inputs_[0] = value; }
@ -918,6 +929,14 @@ class LMathExp final : public LTemplateInstruction<1, 1, 0> {
DECLARE_CONCRETE_INSTRUCTION(MathExp, "math-exp")
};
class LMathSin final : public LTemplateInstruction<1, 1, 0> {
public:
explicit LMathSin(LOperand* value) { inputs_[0] = value; }
LOperand* value() { return inputs_[0]; }
DECLARE_CONCRETE_INSTRUCTION(MathSin, "math-sin")
};
class LMathSqrt final : public LTemplateInstruction<1, 1, 0> {
public:
@ -2531,8 +2550,10 @@ class LChunkBuilder final : public LChunkBuilderBase {
LInstruction* DoMathRound(HUnaryMathOperation* instr);
LInstruction* DoMathFround(HUnaryMathOperation* instr);
LInstruction* DoMathAbs(HUnaryMathOperation* instr);
LInstruction* DoMathCos(HUnaryMathOperation* instr);
LInstruction* DoMathLog(HUnaryMathOperation* instr);
LInstruction* DoMathExp(HUnaryMathOperation* instr);
LInstruction* DoMathSin(HUnaryMathOperation* instr);
LInstruction* DoMathSqrt(HUnaryMathOperation* instr);
LInstruction* DoMathPowHalf(HUnaryMathOperation* instr);
LInstruction* DoMathClz32(HUnaryMathOperation* instr);

View File

@ -73,6 +73,8 @@ ExternalReferenceTable::ExternalReferenceTable(Isolate* isolate) {
"base::ieee754::atan2");
Add(ExternalReference::ieee754_atanh_function(isolate).address(),
"base::ieee754::atanh");
Add(ExternalReference::ieee754_cos_function(isolate).address(),
"base::ieee754::cos");
Add(ExternalReference::ieee754_exp_function(isolate).address(),
"base::ieee754::exp");
Add(ExternalReference::ieee754_expm1_function(isolate).address(),
@ -87,6 +89,8 @@ ExternalReferenceTable::ExternalReferenceTable(Isolate* isolate) {
"base::ieee754::log10");
Add(ExternalReference::ieee754_cbrt_function(isolate).address(),
"base::ieee754::cbrt");
Add(ExternalReference::ieee754_sin_function(isolate).address(),
"base::ieee754::sin");
Add(ExternalReference::store_buffer_top(isolate).address(),
"store_buffer_top");
Add(ExternalReference::address_of_the_hole_nan().address(), "the_hole_nan");

View File

@ -134,103 +134,6 @@ macro REMPIO2(X)
endmacro
// __kernel_sin(X, Y, IY)
// kernel sin function on [-pi/4, pi/4], pi/4 ~ 0.7854
// Input X is assumed to be bounded by ~pi/4 in magnitude.
// Input Y is the tail of X so that x = X + Y.
//
// Algorithm
// 1. Since ieee_sin(-x) = -ieee_sin(x), we need only to consider positive x.
// 2. ieee_sin(x) is approximated by a polynomial of degree 13 on
// [0,pi/4]
// 3 13
// sin(x) ~ x + S1*x + ... + S6*x
// where
//
// |ieee_sin(x) 2 4 6 8 10 12 | -58
// |----- - (1+S1*x +S2*x +S3*x +S4*x +S5*x +S6*x )| <= 2
// | x |
//
// 3. ieee_sin(X+Y) = ieee_sin(X) + sin'(X')*Y
// ~ ieee_sin(X) + (1-X*X/2)*Y
// For better accuracy, let
// 3 2 2 2 2
// r = X *(S2+X *(S3+X *(S4+X *(S5+X *S6))))
// then 3 2
// sin(x) = X + (S1*X + (X *(r-Y/2)+Y))
//
define S1 = -1.66666666666666324348e-01;
define S2 = 8.33333333332248946124e-03;
define S3 = -1.98412698298579493134e-04;
define S4 = 2.75573137070700676789e-06;
define S5 = -2.50507602534068634195e-08;
define S6 = 1.58969099521155010221e-10;
macro RETURN_KERNELSIN(X, Y, SIGN)
var z = X * X;
var v = z * X;
var r = S2 + z * (S3 + z * (S4 + z * (S5 + z * S6)));
return (X - ((z * (0.5 * Y - v * r) - Y) - v * S1)) SIGN;
endmacro
// __kernel_cos(X, Y)
// kernel cos function on [-pi/4, pi/4], pi/4 ~ 0.785398164
// Input X is assumed to be bounded by ~pi/4 in magnitude.
// Input Y is the tail of X so that x = X + Y.
//
// Algorithm
// 1. Since ieee_cos(-x) = ieee_cos(x), we need only to consider positive x.
// 2. ieee_cos(x) is approximated by a polynomial of degree 14 on
// [0,pi/4]
// 4 14
// cos(x) ~ 1 - x*x/2 + C1*x + ... + C6*x
// where the remez error is
//
// | 2 4 6 8 10 12 14 | -58
// |ieee_cos(x)-(1-.5*x +C1*x +C2*x +C3*x +C4*x +C5*x +C6*x )| <= 2
// | |
//
// 4 6 8 10 12 14
// 3. let r = C1*x +C2*x +C3*x +C4*x +C5*x +C6*x , then
// ieee_cos(x) = 1 - x*x/2 + r
// since ieee_cos(X+Y) ~ ieee_cos(X) - ieee_sin(X)*Y
// ~ ieee_cos(X) - X*Y,
// a correction term is necessary in ieee_cos(x) and hence
// cos(X+Y) = 1 - (X*X/2 - (r - X*Y))
// For better accuracy when x > 0.3, let qx = |x|/4 with
// the last 32 bits mask off, and if x > 0.78125, let qx = 0.28125.
// Then
// cos(X+Y) = (1-qx) - ((X*X/2-qx) - (r-X*Y)).
// Note that 1-qx and (X*X/2-qx) is EXACT here, and the
// magnitude of the latter is at least a quarter of X*X/2,
// thus, reducing the rounding error in the subtraction.
//
define C1 = 4.16666666666666019037e-02;
define C2 = -1.38888888888741095749e-03;
define C3 = 2.48015872894767294178e-05;
define C4 = -2.75573143513906633035e-07;
define C5 = 2.08757232129817482790e-09;
define C6 = -1.13596475577881948265e-11;
macro RETURN_KERNELCOS(X, Y, SIGN)
var ix = %_DoubleHi(X) & 0x7fffffff;
var z = X * X;
var r = z * (C1 + z * (C2 + z * (C3 + z * (C4 + z * (C5 + z * C6)))));
if (ix < 0x3fd33333) { // |x| ~< 0.3
return (1 - (0.5 * z - (z * r - X * Y))) SIGN;
} else {
var qx;
if (ix > 0x3fe90000) { // |x| > 0.78125
qx = 0.28125;
} else {
qx = %_ConstructDouble(%_DoubleHi(0.25 * X), 0);
}
var hz = 0.5 * z - qx;
return (1 - qx - (hz - (z * r - X * Y))) SIGN;
}
endmacro
// kernel tan function on [-pi/4, pi/4], pi/4 ~ 0.7854
// Input x is assumed to be bounded by ~pi/4 in magnitude.
// Input y is the tail of x.
@ -345,47 +248,6 @@ function KernelTan(x, y, returnTan) {
}
}
function MathSinSlow(x) {
REMPIO2(x);
var sign = 1 - (n & 2);
if (n & 1) {
RETURN_KERNELCOS(y0, y1, * sign);
} else {
RETURN_KERNELSIN(y0, y1, * sign);
}
}
function MathCosSlow(x) {
REMPIO2(x);
if (n & 1) {
var sign = (n & 2) - 1;
RETURN_KERNELSIN(y0, y1, * sign);
} else {
var sign = 1 - (n & 2);
RETURN_KERNELCOS(y0, y1, * sign);
}
}
// ECMA 262 - 15.8.2.16
function MathSin(x) {
x = +x; // Convert to number.
if ((%_DoubleHi(x) & 0x7fffffff) <= 0x3fe921fb) {
// |x| < pi/4, approximately. No reduction needed.
RETURN_KERNELSIN(x, 0, /* empty */);
}
return +MathSinSlow(x);
}
// ECMA 262 - 15.8.2.7
function MathCos(x) {
x = +x; // Convert to number.
if ((%_DoubleHi(x) & 0x7fffffff) <= 0x3fe921fb) {
// |x| < pi/4, approximately. No reduction needed.
RETURN_KERNELCOS(x, 0, /* empty */);
}
return +MathCosSlow(x);
}
// ECMA 262 - 15.8.2.18
function MathTan(x) {
x = x * 1; // Convert to number.
@ -564,15 +426,10 @@ function MathTanh(x) {
//-------------------------------------------------------------------
utils.InstallFunctions(GlobalMath, DONT_ENUM, [
"cos", MathCos,
"sin", MathSin,
"tan", MathTan,
"sinh", MathSinh,
"cosh", MathCosh,
"tanh", MathTanh
]);
%SetForceInlineFlag(MathSin);
%SetForceInlineFlag(MathCos);
})

View File

@ -5529,6 +5529,14 @@ TEST(RunFloat64Atanh) {
FOR_FLOAT64_INPUTS(i) { CHECK_DOUBLE_EQ(ieee754::atanh(*i), m.Call(*i)); }
}
TEST(RunFloat64Cos) {
BufferedRawMachineAssemblerTester<double> m(MachineType::Float64());
m.Return(m.Float64Cos(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::cos(*i), m.Call(*i)); }
}
TEST(RunFloat64Exp) {
BufferedRawMachineAssemblerTester<double> m(MachineType::Float64());
m.Return(m.Float64Exp(m.Parameter(0)));
@ -5623,6 +5631,14 @@ TEST(RunFloat64Cbrt) {
FOR_FLOAT64_INPUTS(i) { CHECK_DOUBLE_EQ(ieee754::cbrt(*i), m.Call(*i)); }
}
TEST(RunFloat64Sin) {
BufferedRawMachineAssemblerTester<double> m(MachineType::Float64());
m.Return(m.Float64Sin(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::sin(*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,

View File

@ -791,7 +791,7 @@ bool IsCompiled(const char* name) {
TEST(SnapshotDataBlobWithWarmup) {
DisableTurbofan();
const char* warmup = "Math.tan(1); Math.sin = 1;";
const char* warmup = "Math.tanh(1); Math.sinh = 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.tan"));
CHECK(!IsCompiled("Math.cos"));
CHECK(CompileRun("Math.sin")->IsFunction());
CHECK(IsCompiled("Math.tanh"));
CHECK(!IsCompiled("Math.cosh"));
CHECK(CompileRun("Math.sinh")->IsFunction());
}
isolate->Dispose();
}
@ -820,9 +820,9 @@ TEST(SnapshotDataBlobWithWarmup) {
TEST(CustomSnapshotDataBlobWithWarmup) {
DisableTurbofan();
const char* source =
"function f() { return Math.sin(1); }\n"
"function g() { return Math.cos(1); }\n"
"Math.tan(1);"
"function f() { return Math.sinh(1); }\n"
"function g() { return Math.cosh(1); }\n"
"Math.tanh(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.sin"));
CHECK(IsCompiled("Math.sinh"));
CHECK(!IsCompiled("g"));
CHECK(!IsCompiled("Math.cos"));
CHECK(!IsCompiled("Math.tan"));
CHECK(!IsCompiled("Math.cosh"));
CHECK(!IsCompiled("Math.tanh"));
CHECK_EQ(5, CompileRun("a")->Int32Value(context).FromJust());
}
isolate->Dispose();

View File

@ -63,6 +63,48 @@ TEST(Ieee754, Atanh) {
EXPECT_DOUBLE_EQ(0.54930614433405478, atanh(0.5));
}
TEST(Ieee754, Cos) {
// Test values mentioned in the EcmaScript spec.
EXPECT_THAT(cos(std::numeric_limits<double>::quiet_NaN()), IsNaN());
EXPECT_THAT(cos(std::numeric_limits<double>::signaling_NaN()), IsNaN());
EXPECT_THAT(cos(std::numeric_limits<double>::infinity()), IsNaN());
EXPECT_THAT(cos(-std::numeric_limits<double>::infinity()), IsNaN());
// Tests for cos for |x| < pi/4
EXPECT_EQ(1.0, 1 / cos(-0.0));
EXPECT_EQ(1.0, 1 / cos(0.0));
// cos(x) = 1 for |x| < 2^-27
EXPECT_EQ(1, cos(2.3283064365386963e-10));
EXPECT_EQ(1, cos(-2.3283064365386963e-10));
// Test KERNELCOS for |x| < 0.3.
// cos(pi/20) = sqrt(sqrt(2)*sqrt(sqrt(5)+5)+4)/2^(3/2)
EXPECT_EQ(0.9876883405951378, cos(0.15707963267948966));
// Test KERNELCOS for x ~= 0.78125
EXPECT_EQ(0.7100335477927638, cos(0.7812504768371582));
EXPECT_EQ(0.7100338835660797, cos(0.78125));
// Test KERNELCOS for |x| > 0.3.
// cos(pi/8) = sqrt(sqrt(2)+1)/2^(3/4)
EXPECT_EQ(0.9238795325112867, cos(0.39269908169872414));
// Test KERNELTAN for |x| < 0.67434.
EXPECT_EQ(0.9238795325112867, cos(-0.39269908169872414));
// Tests for cos.
EXPECT_EQ(1, cos(3.725290298461914e-9));
// Cover different code paths in KERNELCOS.
EXPECT_EQ(0.9689124217106447, cos(0.25));
EXPECT_EQ(0.8775825618903728, cos(0.5));
EXPECT_EQ(0.7073882691671998, cos(0.785));
// Test that cos(Math.PI/2) != 0 since Math.PI is not exact.
EXPECT_EQ(6.123233995736766e-17, cos(1.5707963267948966));
// Test cos for various phases.
EXPECT_EQ(0.7071067811865474, cos(7.0 / 4 * 3.141592653589793));
EXPECT_EQ(0.7071067811865477, cos(9.0 / 4 * 3.141592653589793));
EXPECT_EQ(-0.7071067811865467, cos(11.0 / 4 * 3.141592653589793));
EXPECT_EQ(-0.7071067811865471, cos(13.0 / 4 * 3.141592653589793));
EXPECT_EQ(0.9367521275331447, cos(1000000.0));
EXPECT_EQ(-3.435757038074824e-12, cos(1048575.0 / 2 * 3.141592653589793));
}
TEST(Ieee754, Exp) {
EXPECT_THAT(exp(std::numeric_limits<double>::quiet_NaN()), IsNaN());
EXPECT_THAT(exp(std::numeric_limits<double>::signaling_NaN()), IsNaN());
@ -170,7 +212,7 @@ TEST(Ieee754, Log10) {
EXPECT_EQ(5.0, log10(100000.0));
}
TEST(Ieee754, cbrt) {
TEST(Ieee754, Cbrt) {
EXPECT_THAT(cbrt(std::numeric_limits<double>::quiet_NaN()), IsNaN());
EXPECT_THAT(cbrt(std::numeric_limits<double>::signaling_NaN()), IsNaN());
EXPECT_EQ(std::numeric_limits<double>::infinity(),
@ -182,6 +224,39 @@ TEST(Ieee754, cbrt) {
EXPECT_EQ(46.415888336127786, cbrt(100000));
}
TEST(Ieee754, Sin) {
// Test values mentioned in the EcmaScript spec.
EXPECT_THAT(sin(std::numeric_limits<double>::quiet_NaN()), IsNaN());
EXPECT_THAT(sin(std::numeric_limits<double>::signaling_NaN()), IsNaN());
EXPECT_THAT(sin(std::numeric_limits<double>::infinity()), IsNaN());
EXPECT_THAT(sin(-std::numeric_limits<double>::infinity()), IsNaN());
// Tests for sin for |x| < pi/4
EXPECT_EQ(-std::numeric_limits<double>::infinity(), 1 / sin(-0.0));
EXPECT_EQ(std::numeric_limits<double>::infinity(), 1 / sin(0.0));
// sin(x) = x for x < 2^-27
EXPECT_EQ(2.3283064365386963e-10, sin(2.3283064365386963e-10));
EXPECT_EQ(-2.3283064365386963e-10, sin(-2.3283064365386963e-10));
// sin(pi/8) = sqrt(sqrt(2)-1)/2^(3/4)
EXPECT_EQ(0.3826834323650898, sin(0.39269908169872414));
EXPECT_EQ(-0.3826834323650898, sin(-0.39269908169872414));
// Tests for sin.
EXPECT_EQ(0.479425538604203, sin(0.5));
EXPECT_EQ(-0.479425538604203, sin(-0.5));
EXPECT_EQ(1, sin(1.5707963267948966));
EXPECT_EQ(-1, sin(-1.5707963267948966));
// Test that sin(Math.PI) != 0 since Math.PI is not exact.
EXPECT_EQ(1.2246467991473532e-16, sin(3.141592653589793));
EXPECT_EQ(-7.047032979958965e-14, sin(2200 * 3.141592653589793));
// Test sin for various phases.
EXPECT_EQ(-0.7071067811865477, sin(7.0 / 4 * 3.141592653589793));
EXPECT_EQ(0.7071067811865474, sin(9.0 / 4 * 3.141592653589793));
EXPECT_EQ(0.7071067811865483, sin(11.0 / 4 * 3.141592653589793));
EXPECT_EQ(-0.7071067811865479, sin(13.0 / 4 * 3.141592653589793));
EXPECT_EQ(-3.2103381051568376e-11, sin(1048576.0 / 4 * 3.141592653589793));
}
} // namespace ieee754
} // namespace base
} // namespace v8

View File

@ -263,6 +263,45 @@ TEST_F(JSBuiltinReducerTest, MathClz32WithPlainPrimitive) {
IsNumberClz32(IsNumberToUint32(IsPlainPrimitiveToNumber(p0))));
}
// -----------------------------------------------------------------------------
// Math.cos
TEST_F(JSBuiltinReducerTest, MathCosWithNumber) {
Node* function = MathFunction("cos");
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(), IsNumberCos(p0));
}
}
TEST_F(JSBuiltinReducerTest, MathCosWithPlainPrimitive) {
Node* function = MathFunction("cos");
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(), IsNumberCos(IsPlainPrimitiveToNumber(p0)));
}
// -----------------------------------------------------------------------------
// Math.exp

View File

@ -1463,6 +1463,19 @@ TEST_F(MachineOperatorReducerTest, Float64Atan2WithNaN) {
}
}
// -----------------------------------------------------------------------------
// Float64Cos
TEST_F(MachineOperatorReducerTest, Float64CosWithConstant) {
TRACED_FOREACH(double, x, kFloat64Values) {
Reduction const r =
Reduce(graph()->NewNode(machine()->Float64Cos(), Float64Constant(x)));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(),
IsFloat64Constant(NanSensitiveDoubleEq(base::ieee754::cos(x))));
}
}
// -----------------------------------------------------------------------------
// Float64Exp
@ -1503,6 +1516,19 @@ TEST_F(MachineOperatorReducerTest, Float64Log1pWithConstant) {
}
}
// -----------------------------------------------------------------------------
// Float64Sin
TEST_F(MachineOperatorReducerTest, Float64SinWithConstant) {
TRACED_FOREACH(double, x, kFloat64Values) {
Reduction const r =
Reduce(graph()->NewNode(machine()->Float64Sin(), Float64Constant(x)));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(),
IsFloat64Constant(NanSensitiveDoubleEq(base::ieee754::sin(x))));
}
}
// -----------------------------------------------------------------------------
// Float64InsertLowWord32

View File

@ -2314,6 +2314,7 @@ IS_UNOP_MATCHER(NumberAtan)
IS_UNOP_MATCHER(NumberAtanh)
IS_UNOP_MATCHER(NumberCeil)
IS_UNOP_MATCHER(NumberClz32)
IS_UNOP_MATCHER(NumberCos)
IS_UNOP_MATCHER(NumberExp)
IS_UNOP_MATCHER(NumberExpm1)
IS_UNOP_MATCHER(NumberFloor)
@ -2323,6 +2324,7 @@ IS_UNOP_MATCHER(NumberLog1p)
IS_UNOP_MATCHER(NumberLog2)
IS_UNOP_MATCHER(NumberLog10)
IS_UNOP_MATCHER(NumberRound)
IS_UNOP_MATCHER(NumberSin)
IS_UNOP_MATCHER(NumberSqrt)
IS_UNOP_MATCHER(NumberCbrt)
IS_UNOP_MATCHER(NumberTrunc)

View File

@ -230,6 +230,7 @@ Matcher<Node*> IsNumberAtan2(const Matcher<Node*>& lhs_matcher,
Matcher<Node*> IsNumberAtanh(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*> IsNumberExp(const Matcher<Node*>& value_matcher);
Matcher<Node*> IsNumberExpm1(const Matcher<Node*>& value_matcher);
Matcher<Node*> IsNumberFloor(const Matcher<Node*>& value_matcher);
@ -240,6 +241,7 @@ Matcher<Node*> IsNumberLog2(const Matcher<Node*>& value_matcher);
Matcher<Node*> IsNumberLog10(const Matcher<Node*>& value_matcher);
Matcher<Node*> IsNumberRound(const Matcher<Node*>& value_matcher);
Matcher<Node*> IsNumberCbrt(const Matcher<Node*>& value_matcher);
Matcher<Node*> IsNumberSin(const Matcher<Node*>& value_matcher);
Matcher<Node*> IsNumberSqrt(const Matcher<Node*>& value_matcher);
Matcher<Node*> IsNumberTrunc(const Matcher<Node*>& value_matcher);
Matcher<Node*> IsStringFromCharCode(const Matcher<Node*>& value_matcher);