Revision: 24476
Author: [email protected]
Date: Thu Oct 9 00:05:16 2014 UTC
Log: Version 3.30.6 (based on bleeding_edge revision r24474)
Update unicode to 7.0.0 (issue 2892).
Classes: Add support for toString (issue 3330).
Don't enable WPO on Win64 and require Server 2003 / x64 for win64 (Chromium
issue 421363).
Performance and stability improvements on all platforms.
https://code.google.com/p/v8/source/detail?r=24476
Added:
/trunk/src/third_party/fdlibm
/trunk/src/third_party/fdlibm/LICENSE
/trunk/src/third_party/fdlibm/README.v8
/trunk/src/third_party/fdlibm/fdlibm.cc
/trunk/src/third_party/fdlibm/fdlibm.h
/trunk/src/third_party/fdlibm/fdlibm.js
/trunk/src/unicode-decoder.cc
/trunk/src/unicode-decoder.h
/trunk/test/mjsunit/asm/float32array-outofbounds.js
/trunk/test/mjsunit/asm/float64array-outofbounds.js
/trunk/test/mjsunit/asm/int16array-outofbounds.js
/trunk/test/mjsunit/asm/int32-div.js
/trunk/test/mjsunit/asm/int32-mod.js
/trunk/test/mjsunit/asm/int32-mul.js
/trunk/test/mjsunit/asm/int32-tmod.js
/trunk/test/mjsunit/asm/int32-udiv.js
/trunk/test/mjsunit/asm/int32-umod.js
/trunk/test/mjsunit/asm/int32array-outofbounds.js
/trunk/test/mjsunit/asm/uint8array-outofbounds.js
/trunk/test/unittests/unicode
/trunk/test/unittests/unicode/unicode-predicates-unittest.cc
Deleted:
/trunk/third_party/fdlibm/LICENSE
/trunk/third_party/fdlibm/README.v8
/trunk/third_party/fdlibm/fdlibm.cc
/trunk/third_party/fdlibm/fdlibm.h
/trunk/third_party/fdlibm/fdlibm.js
Modified:
/trunk/BUILD.gn
/trunk/ChangeLog
/trunk/build/standalone.gypi
/trunk/build/toolchain.gypi
/trunk/include/v8.h
/trunk/src/api.cc
/trunk/src/arm/debug-arm.cc
/trunk/src/arm/full-codegen-arm.cc
/trunk/src/arm64/debug-arm64.cc
/trunk/src/arm64/full-codegen-arm64.cc
/trunk/src/ast.cc
/trunk/src/ast.h
/trunk/src/bootstrapper.cc
/trunk/src/char-predicates.h
/trunk/src/code-stubs.cc
/trunk/src/code-stubs.h
/trunk/src/compiler/code-generator.cc
/trunk/src/compiler/code-generator.h
/trunk/src/compiler/ia32/code-generator-ia32.cc
/trunk/src/compiler/instruction-selector.cc
/trunk/src/compiler/instruction-selector.h
/trunk/src/compiler/instruction.cc
/trunk/src/compiler/instruction.h
/trunk/src/compiler/js-typed-lowering.cc
/trunk/src/compiler/machine-type.h
/trunk/src/compiler/pipeline.cc
/trunk/src/compiler/representation-change.h
/trunk/src/compiler/simplified-lowering.cc
/trunk/src/compiler/simplified-lowering.h
/trunk/src/compiler/typer.cc
/trunk/src/compiler/value-numbering-reducer.cc
/trunk/src/compiler/value-numbering-reducer.h
/trunk/src/contexts.h
/trunk/src/full-codegen.cc
/trunk/src/heap/heap.cc
/trunk/src/heap/heap.h
/trunk/src/heap/incremental-marking.cc
/trunk/src/ia32/builtins-ia32.cc
/trunk/src/ia32/debug-ia32.cc
/trunk/src/ia32/full-codegen-ia32.cc
/trunk/src/ic/ic.cc
/trunk/src/ic/ic.h
/trunk/src/isolate.cc
/trunk/src/isolate.h
/trunk/src/jsregexp.cc
/trunk/src/log.cc
/trunk/src/mips/debug-mips.cc
/trunk/src/mips/full-codegen-mips.cc
/trunk/src/mips64/debug-mips64.cc
/trunk/src/mips64/full-codegen-mips64.cc
/trunk/src/objects.h
/trunk/src/parser.cc
/trunk/src/parser.h
/trunk/src/preparser.h
/trunk/src/runtime/runtime-classes.cc
/trunk/src/runtime/runtime-maths.cc
/trunk/src/runtime/runtime.h
/trunk/src/sampler.cc
/trunk/src/scanner.h
/trunk/src/unicode-inl.h
/trunk/src/unicode.cc
/trunk/src/unicode.h
/trunk/src/v8natives.js
/trunk/src/v8threads.cc
/trunk/src/version.cc
/trunk/src/x64/builtins-x64.cc
/trunk/src/x64/debug-x64.cc
/trunk/src/x64/full-codegen-x64.cc
/trunk/test/cctest/cctest.cc
/trunk/test/cctest/cctest.h
/trunk/test/cctest/compiler/function-tester.h
/trunk/test/cctest/compiler/test-changes-lowering.cc
/trunk/test/cctest/compiler/test-representation-change.cc
/trunk/test/cctest/compiler/test-simplified-lowering.cc
/trunk/test/cctest/test-debug.cc
/trunk/test/cctest/test-lockers.cc
/trunk/test/cctest/test-strings.cc
/trunk/test/mjsunit/harmony/classes.js
/trunk/test/mjsunit/var.js
/trunk/test/unittests/compiler/instruction-selector-unittest.cc
/trunk/test/unittests/compiler/instruction-selector-unittest.h
/trunk/test/unittests/compiler/js-builtin-reducer-unittest.cc
/trunk/test/unittests/compiler/value-numbering-reducer-unittest.cc
/trunk/test/unittests/unittests.gyp
/trunk/tools/gyp/v8.gyp
/trunk/tools/push-to-trunk/test_scripts.py
=======================================
--- /dev/null
+++ /trunk/src/third_party/fdlibm/LICENSE Thu Oct 9 00:05:16 2014 UTC
@@ -0,0 +1,6 @@
+Copyright (C) 1993-2004 by Sun Microsystems, Inc. All rights reserved.
+
+Developed at SunSoft, a Sun Microsystems, Inc. business.
+Permission to use, copy, modify, and distribute this
+software is freely granted, provided that this notice
+is preserved.
=======================================
--- /dev/null
+++ /trunk/src/third_party/fdlibm/README.v8 Thu Oct 9 00:05:16 2014 UTC
@@ -0,0 +1,18 @@
+Name: Freely Distributable LIBM
+Short Name: fdlibm
+URL: http://www.netlib.org/fdlibm/
+Version: 5.3
+License: Freely Distributable.
+License File: LICENSE.
+Security Critical: yes.
+License Android Compatible: yes.
+
+Description:
+This is used to provide a accurate implementation for trigonometric
functions
+used in V8.
+
+Local Modifications:
+For the use in V8, fdlibm has been reduced to include only sine, cosine and
+tangent. To make inlining into generated code possible, a large portion of
+that has been translated to Javascript. The rest remains in C, but has
been
+refactored and reformatted to interoperate with the rest of V8.
=======================================
--- /dev/null
+++ /trunk/src/third_party/fdlibm/fdlibm.cc Thu Oct 9 00:05:16 2014 UTC
@@ -0,0 +1,281 @@
+// The following is adapted from fdlibm (http://www.netlib.org/fdlibm).
+//
+// ====================================================
+// Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+//
+// Developed at SunSoft, a Sun Microsystems, Inc. business.
+// Permission to use, copy, modify, and distribute this
+// software is freely granted, provided that this notice
+// is preserved.
+// ====================================================
+//
+// The original source code covered by the above license above has been
+// modified significantly by Google Inc.
+// Copyright 2014 the V8 project authors. All rights reserved.
+
+#include "src/v8.h"
+
+#include "src/double.h"
+#include "src/third_party/fdlibm/fdlibm.h"
+
+
+namespace v8 {
+namespace fdlibm {
+
+#ifdef _MSC_VER
+inline double scalbn(double x, int y) { return _scalb(x, y); }
+#endif // _MSC_VER
+
+const double MathConstants::constants[] = {
+ 6.36619772367581382433e-01, // invpio2 0
+ 1.57079632673412561417e+00, // pio2_1 1
+ 6.07710050650619224932e-11, // pio2_1t 2
+ 6.07710050630396597660e-11, // pio2_2 3
+ 2.02226624879595063154e-21, // pio2_2t 4
+ 2.02226624871116645580e-21, // pio2_3 5
+ 8.47842766036889956997e-32, // pio2_3t 6
+ -1.66666666666666324348e-01, // S1 7 coefficients for sin
+ 8.33333333332248946124e-03, // 8
+ -1.98412698298579493134e-04, // 9
+ 2.75573137070700676789e-06, // 10
+ -2.50507602534068634195e-08, // 11
+ 1.58969099521155010221e-10, // S6 12
+ 4.16666666666666019037e-02, // C1 13 coefficients for cos
+ -1.38888888888741095749e-03, // 14
+ 2.48015872894767294178e-05, // 15
+ -2.75573143513906633035e-07, // 16
+ 2.08757232129817482790e-09, // 17
+ -1.13596475577881948265e-11, // C6 18
+ 3.33333333333334091986e-01, // T0 19 coefficients for tan
+ 1.33333333333201242699e-01, // 20
+ 5.39682539762260521377e-02, // 21
+ 2.18694882948595424599e-02, // 22
+ 8.86323982359930005737e-03, // 23
+ 3.59207910759131235356e-03, // 24
+ 1.45620945432529025516e-03, // 25
+ 5.88041240820264096874e-04, // 26
+ 2.46463134818469906812e-04, // 27
+ 7.81794442939557092300e-05, // 28
+ 7.14072491382608190305e-05, // 29
+ -1.85586374855275456654e-05, // 30
+ 2.59073051863633712884e-05, // T12 31
+ 7.85398163397448278999e-01, // pio4 32
+ 3.06161699786838301793e-17, // pio4lo 33
+ 6.93147180369123816490e-01, // ln2_hi 34
+ 1.90821492927058770002e-10, // ln2_lo 35
+ 1.80143985094819840000e+16, // 2^54 36
+ 6.666666666666666666e-01, // 2/3 37
+ 6.666666666666735130e-01, // LP1 38 coefficients for log1p
+ 3.999999999940941908e-01, // 39
+ 2.857142874366239149e-01, // 40
+ 2.222219843214978396e-01, // 41
+ 1.818357216161805012e-01, // 42
+ 1.531383769920937332e-01, // 43
+ 1.479819860511658591e-01, // LP7 44
+ 7.09782712893383973096e+02, // 45 overflow threshold for
expm1
+ 1.44269504088896338700e+00, // 1/ln2 46
+ -3.33333333333331316428e-02, // Q1 47 coefficients for expm1
+ 1.58730158725481460165e-03, // 48
+ -7.93650757867487942473e-05, // 49
+ 4.00821782732936239552e-06, // 50
+ -2.01099218183624371326e-07, // Q5 51
+ 710.4758600739439 // 52 overflow threshold sinh,
cosh
+};
+
+
+// Table of constants for 2/pi, 396 Hex digits (476 decimal) of 2/pi
+static const int 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 double zero = 0.0;
+static const double two24 = 1.6777216e+07;
+static const double one = 1.0;
+static const double twon24 = 5.9604644775390625e-08;
+
+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
+};
+
+
+int __kernel_rem_pio2(double* x, double* y, int e0, int nx) {
+ static const int32_t jk = 3;
+ double fw;
+ int32_t jx = nx - 1;
+ int32_t jv = (e0 - 3) / 24;
+ if (jv < 0) jv = 0;
+ int32_t q0 = e0 - 24 * (jv + 1);
+ int32_t m = jx + jk;
+
+ double f[10];
+ for (int i = 0, j = jv - jx; i <= m; i++, j++) {
+ f[i] = (j < 0) ? zero : static_cast<double>(two_over_pi[j]);
+ }
+
+ double q[10];
+ for (int i = 0; i <= jk; i++) {
+ fw = 0.0;
+ for (int j = 0; j <= jx; j++) fw += x[j] * f[jx + i - j];
+ q[i] = fw;
+ }
+
+ int32_t jz = jk;
+
+recompute:
+
+ int32_t iq[10];
+ double z = q[jz];
+ for (int i = 0, j = 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;
+ }
+
+ z = scalbn(z, q0);
+ z -= 8.0 * std::floor(z * 0.125);
+ int32_t n = static_cast<int32_t>(z);
+ z -= static_cast<double>(n);
+ int32_t ih = 0;
+ if (q0 > 0) {
+ int32_t 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) {
+ n += 1;
+ int32_t carry = 0;
+ for (int i = 0; i < jz; i++) {
+ int32_t j = iq[i];
+ if (carry == 0) {
+ if (j != 0) {
+ carry = 1;
+ iq[i] = 0x1000000 - j;
+ }
+ } else {
+ iq[i] = 0xffffff - j;
+ }
+ }
+ if (q0 == 1) {
+ iq[jz - 1] &= 0x7fffff;
+ } else if (q0 == 2) {
+ iq[jz - 1] &= 0x3fffff;
+ }
+ if (ih == 2) {
+ z = one - z;
+ if (carry != 0) z -= scalbn(one, q0);
+ }
+ }
+
+ if (z == zero) {
+ int32_t j = 0;
+ for (int i = jz - 1; i >= jk; i--) j |= iq[i];
+ if (j == 0) {
+ int32_t k = 1;
+ while (iq[jk - k] == 0) k++;
+ for (int i = jz + 1; i <= jz + k; i++) {
+ f[jx + i] = static_cast<double>(two_over_pi[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;
+ }
+ }
+
+ if (z == 0.0) {
+ jz -= 1;
+ q0 -= 24;
+ while (iq[jz] == 0) {
+ jz--;
+ q0 -= 24;
+ }
+ } else {
+ z = scalbn(z, -q0);
+ if (z >= two24) {
+ fw = static_cast<double>(static_cast<int32_t>(twon24 * z));
+ iq[jz] = static_cast<int32_t>(z - two24 * fw);
+ jz += 1;
+ q0 += 24;
+ iq[jz] = static_cast<int32_t>(fw);
+ } else {
+ iq[jz] = static_cast<int32_t>(z);
+ }
+ }
+
+ fw = scalbn(one, q0);
+ for (int i = jz; i >= 0; i--) {
+ q[i] = fw * static_cast<double>(iq[i]);
+ fw *= twon24;
+ }
+
+ double fq[10];
+ for (int i = jz; i >= 0; i--) {
+ fw = 0.0;
+ for (int k = 0; k <= jk && k <= jz - i; k++) fw += PIo2[k] * q[i + k];
+ fq[jz - i] = fw;
+ }
+
+ fw = 0.0;
+ for (int i = jz; i >= 0; i--) fw += fq[i];
+ y[0] = (ih == 0) ? fw : -fw;
+ fw = fq[0] - fw;
+ for (int i = 1; i <= jz; i++) fw += fq[i];
+ y[1] = (ih == 0) ? fw : -fw;
+ return n & 7;
+}
+
+
+int rempio2(double x, double* y) {
+ int32_t hx = static_cast<int32_t>(internal::double_to_uint64(x) >> 32);
+ int32_t ix = hx & 0x7fffffff;
+
+ if (ix >= 0x7ff00000) {
+ *y = base::OS::nan_value();
+ return 0;
+ }
+
+ int32_t e0 = (ix >> 20) - 1046;
+ uint64_t zi = internal::double_to_uint64(x) & 0xFFFFFFFFu;
+ zi |= static_cast<uint64_t>(ix - (e0 << 20)) << 32;
+ double z = internal::uint64_to_double(zi);
+
+ double tx[3];
+ for (int i = 0; i < 2; i++) {
+ tx[i] = static_cast<double>(static_cast<int32_t>(z));
+ z = (z - tx[i]) * two24;
+ }
+ tx[2] = z;
+
+ int nx = 3;
+ while (tx[nx - 1] == zero) nx--;
+ int n = __kernel_rem_pio2(tx, y, e0, nx);
+ if (hx < 0) {
+ y[0] = -y[0];
+ y[1] = -y[1];
+ return -n;
+ }
+ return n;
+}
+}
+} // namespace v8::internal
=======================================
--- /dev/null
+++ /trunk/src/third_party/fdlibm/fdlibm.h Thu Oct 9 00:05:16 2014 UTC
@@ -0,0 +1,31 @@
+// The following is adapted from fdlibm (http://www.netlib.org/fdlibm).
+//
+// ====================================================
+// Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+//
+// Developed at SunSoft, a Sun Microsystems, Inc. business.
+// Permission to use, copy, modify, and distribute this
+// software is freely granted, provided that this notice
+// is preserved.
+// ====================================================
+//
+// The original source code covered by the above license above has been
+// modified significantly by Google Inc.
+// Copyright 2014 the V8 project authors. All rights reserved.
+
+#ifndef V8_FDLIBM_H_
+#define V8_FDLIBM_H_
+
+namespace v8 {
+namespace fdlibm {
+
+int rempio2(double x, double* y);
+
+// Constants to be exposed to builtins via Float64Array.
+struct MathConstants {
+ static const double constants[53];
+};
+}
+} // namespace v8::internal
+
+#endif // V8_FDLIBM_H_
=======================================
--- /dev/null
+++ /trunk/src/third_party/fdlibm/fdlibm.js Thu Oct 9 00:05:16 2014 UTC
@@ -0,0 +1,814 @@
+// The following is adapted from fdlibm (http://www.netlib.org/fdlibm),
+//
+// ====================================================
+// Copyright (C) 1993-2004 by Sun Microsystems, Inc. All rights reserved.
+//
+// Developed at SunSoft, a Sun Microsystems, Inc. business.
+// Permission to use, copy, modify, and distribute this
+// software is freely granted, provided that this notice
+// is preserved.
+// ====================================================
+//
+// The original source code covered by the above license above has been
+// modified significantly by Google Inc.
+// Copyright 2014 the V8 project authors. All rights reserved.
+//
+// The following is a straightforward translation of fdlibm routines
+// by Raymond Toy ([email protected]).
+
+// Double constants that do not have empty lower 32 bits are found in
fdlibm.cc
+// and exposed through kMath as typed array. We assume the compiler to
convert
+// from decimal to binary accurately enough to produce the intended values.
+// kMath is initialized to a Float64Array during genesis and not writable.
+var kMath;
+
+const INVPIO2 = kMath[0];
+const PIO2_1 = kMath[1];
+const PIO2_1T = kMath[2];
+const PIO2_2 = kMath[3];
+const PIO2_2T = kMath[4];
+const PIO2_3 = kMath[5];
+const PIO2_3T = kMath[6];
+const PIO4 = kMath[32];
+const PIO4LO = kMath[33];
+
+// Compute k and r such that x - k*pi/2 = r where |r| < pi/4. For
+// precision, r is returned as two values y0 and y1 such that r = y0 + y1
+// to more than double precision.
+macro REMPIO2(X)
+ var n, y0, y1;
+ var hx = %_DoubleHi(X);
+ var ix = hx & 0x7fffffff;
+
+ if (ix < 0x4002d97c) {
+ // |X| ~< 3*pi/4, special case with n = +/- 1
+ if (hx > 0) {
+ var z = X - PIO2_1;
+ if (ix != 0x3ff921fb) {
+ // 33+53 bit pi is good enough
+ y0 = z - PIO2_1T;
+ y1 = (z - y0) - PIO2_1T;
+ } else {
+ // near pi/2, use 33+33+53 bit pi
+ z -= PIO2_2;
+ y0 = z - PIO2_2T;
+ y1 = (z - y0) - PIO2_2T;
+ }
+ n = 1;
+ } else {
+ // Negative X
+ var z = X + PIO2_1;
+ if (ix != 0x3ff921fb) {
+ // 33+53 bit pi is good enough
+ y0 = z + PIO2_1T;
+ y1 = (z - y0) + PIO2_1T;
+ } else {
+ // near pi/2, use 33+33+53 bit pi
+ z += PIO2_2;
+ y0 = z + PIO2_2T;
+ y1 = (z - y0) + PIO2_2T;
+ }
+ n = -1;
+ }
+ } else if (ix <= 0x413921fb) {
+ // |X| ~<= 2^19*(pi/2), medium size
+ var t = MathAbs(X);
+ n = (t * INVPIO2 + 0.5) | 0;
+ var r = t - n * PIO2_1;
+ var w = n * PIO2_1T;
+ // First round good to 85 bit
+ y0 = r - w;
+ if (ix - (%_DoubleHi(y0) & 0x7ff00000) > 0x1000000) {
+ // 2nd iteration needed, good to 118
+ t = r;
+ w = n * PIO2_2;
+ r = t - w;
+ w = n * PIO2_2T - ((t - r) - w);
+ y0 = r - w;
+ if (ix - (%_DoubleHi(y0) & 0x7ff00000) > 0x3100000) {
+ // 3rd iteration needed. 151 bits accuracy
+ t = r;
+ w = n * PIO2_3;
+ r = t - w;
+ w = n * PIO2_3T - ((t - r) - w);
+ y0 = r - w;
+ }
+ }
+ y1 = (r - y0) - w;
+ if (hx < 0) {
+ n = -n;
+ y0 = -y0;
+ y1 = -y1;
+ }
+ } else {
+ // Need to do full Payne-Hanek reduction here.
+ var r = %RemPiO2(X);
+ n = r[0];
+ y0 = r[1];
+ y1 = r[2];
+ }
+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))
+//
+macro KSIN(x)
+kMath[7+x]
+endmacro
+
+macro RETURN_KERNELSIN(X, Y, SIGN)
+ var z = X * X;
+ var v = z * X;
+ var r = KSIN(1) + z * (KSIN(2) + z * (KSIN(3) +
+ z * (KSIN(4) + z * KSIN(5))));
+ return (X - ((z * (0.5 * Y - v * r) - Y) - v * KSIN(0))) 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.
+//
+macro KCOS(x)
+kMath[13+x]
+endmacro
+
+macro RETURN_KERNELCOS(X, Y, SIGN)
+ var ix = %_DoubleHi(X) & 0x7fffffff;
+ var z = X * X;
+ var r = z * (KCOS(0) + z * (KCOS(1) + z * (KCOS(2)+
+ z * (KCOS(3) + z * (KCOS(4) + z * KCOS(5))))));
+ 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.
+// Input k indicates whether ieee_tan (if k = 1) or -1/tan (if k = -1)
+// is returned.
+//
+// Algorithm
+// 1. Since ieee_tan(-x) = -ieee_tan(x), we need only to consider
positive x.
+// 2. if x < 2^-28 (hx<0x3e300000 0), return x with inexact if x!=0.
+// 3. ieee_tan(x) is approximated by a odd polynomial of degree 27 on
+// [0,0.67434]
+// 3 27
+// tan(x) ~ x + T1*x + ... + T13*x
+// where
+//
+// |ieee_tan(x) 2 4 26 | -59.2
+// |----- - (1+T1*x +T2*x +.... +T13*x )| <= 2
+// | x |
+//
+// Note: ieee_tan(x+y) = ieee_tan(x) + tan'(x)*y
+// ~ ieee_tan(x) + (1+x*x)*y
+// Therefore, for better accuracy in computing ieee_tan(x+y), let
+// 3 2 2 2 2
+// r = x *(T2+x *(T3+x *(...+x *(T12+x *T13))))
+// then
+// 3 2
+// tan(x+y) = x + (T1*x + (x *(r+y)+y))
+//
+// 4. For x in [0.67434,pi/4], let y = pi/4 - x, then
+// tan(x) = ieee_tan(pi/4-y) = (1-ieee_tan(y))/(1+ieee_tan(y))
+// = 1 - 2*(ieee_tan(y) - (ieee_tan(y)^2)/(1+ieee_tan(y)))
+//
+// Set returnTan to 1 for tan; -1 for cot. Anything else is illegal
+// and will cause incorrect results.
+//
+macro KTAN(x)
+kMath[19+x]
+endmacro
+
+function KernelTan(x, y, returnTan) {
+ var z;
+ var w;
+ var hx = %_DoubleHi(x);
+ var ix = hx & 0x7fffffff;
+
+ if (ix < 0x3e300000) { // |x| < 2^-28
+ if (((ix | %_DoubleLo(x)) | (returnTan + 1)) == 0) {
+ // x == 0 && returnTan = -1
+ return 1 / MathAbs(x);
+ } else {
+ if (returnTan == 1) {
+ return x;
+ } else {
+ // Compute -1/(x + y) carefully
+ var w = x + y;
+ var z = %_ConstructDouble(%_DoubleHi(w), 0);
+ var v = y - (z - x);
+ var a = -1 / w;
+ var t = %_ConstructDouble(%_DoubleHi(a), 0);
+ var s = 1 + t * z;
+ return t + a * (s + t * v);
+ }
+ }
+ }
+ if (ix >= 0x3fe59429) { // |x| > .6744
+ if (x < 0) {
+ x = -x;
+ y = -y;
+ }
+ z = PIO4 - x;
+ w = PIO4LO - y;
+ x = z + w;
+ y = 0;
+ }
+ z = x * x;
+ w = z * z;
+
+ // Break x^5 * (T1 + x^2*T2 + ...) into
+ // x^5 * (T1 + x^4*T3 + ... + x^20*T11) +
+ // x^5 * (x^2 * (T2 + x^4*T4 + ... + x^22*T12))
+ var r = KTAN(1) + w * (KTAN(3) + w * (KTAN(5) +
+ w * (KTAN(7) + w * (KTAN(9) + w * KTAN(11)))));
+ var v = z * (KTAN(2) + w * (KTAN(4) + w * (KTAN(6) +
+ w * (KTAN(8) + w * (KTAN(10) + w * KTAN(12))))));
+ var s = z * x;
+ r = y + z * (s * (r + v) + y);
+ r = r + KTAN(0) * s;
+ w = x + r;
+ if (ix >= 0x3fe59428) {
+ return (1 - ((hx >> 30) & 2)) *
+ (returnTan - 2.0 * (x - (w * w / (w + returnTan) - r)));
+ }
+ if (returnTan == 1) {
+ return w;
+ } else {
+ z = %_ConstructDouble(%_DoubleHi(w), 0);
+ v = r - (z - x);
+ var a = -1 / w;
+ var t = %_ConstructDouble(%_DoubleHi(a), 0);
+ s = 1 + t * z;
+ return t + a * (s + t * v);
+ }
+}
+
+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 * 1; // 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 * 1; // 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.
+ if ((%_DoubleHi(x) & 0x7fffffff) <= 0x3fe921fb) {
+ // |x| < pi/4, approximately. No reduction needed.
+ return KernelTan(x, 0, 1);
+ }
+ REMPIO2(x);
+ return KernelTan(y0, y1, (n & 1) ? -1 : 1);
+}
+
+// ES6 draft 09-27-13, section 20.2.2.20.
+// Math.log1p
+//
+// Method :
+// 1. Argument Reduction: find k and f such that
+// 1+x = 2^k * (1+f),
+// where sqrt(2)/2 < 1+f < sqrt(2) .
+//
+// Note. If k=0, then f=x is exact. However, if k!=0, then f
+// may not be representable exactly. In that case, a correction
+// term is need. Let u=1+x rounded. Let c = (1+x)-u, then
+// log(1+x) - log(u) ~ c/u. Thus, we proceed to compute log(u),
+// and add back the correction term c/u.
+// (Note: when x > 2**53, one can simply return log(x))
+//
+// 2. Approximation of log1p(f).
+// Let s = f/(2+f) ; based on log(1+f) = log(1+s) - log(1-s)
+// = 2s + 2/3 s**3 + 2/5 s**5 + .....,
+// = 2s + s*R
+// We use a special Reme algorithm on [0,0.1716] to generate
+// a polynomial of degree 14 to approximate R The maximum error
+// of this polynomial approximation is bounded by 2**-58.45. In
+// other words,
+// 2 4 6 8 10 12 14
+// R(z) ~ Lp1*s +Lp2*s +Lp3*s +Lp4*s +Lp5*s +Lp6*s +Lp7*s
+// (the values of Lp1 to Lp7 are listed in the program)
+// and
+// | 2 14 | -58.45
+// | Lp1*s +...+Lp7*s - R(z) | <= 2
+// | |
+// Note that 2s = f - s*f = f - hfsq + s*hfsq, where hfsq = f*f/2.
+// In order to guarantee error in log below 1ulp, we compute log
+// by
+// log1p(f) = f - (hfsq - s*(hfsq+R)).
+//
+// 3. Finally, log1p(x) = k*ln2 + log1p(f).
+// = k*ln2_hi+(f-(hfsq-(s*(hfsq+R)+k*ln2_lo)))
+// Here ln2 is split into two floating point number:
+// ln2_hi + ln2_lo,
+// where n*ln2_hi is always exact for |n| < 2000.
+//
+// Special cases:
+// log1p(x) is NaN with signal if x < -1 (including -INF) ;
+// log1p(+INF) is +INF; log1p(-1) is -INF with signal;
+// log1p(NaN) is that NaN with no signal.
+//
+// Accuracy:
+// according to an error analysis, the error is always less than
+// 1 ulp (unit in the last place).
+//
+// Constants:
+// Constants are found in fdlibm.cc. We assume the C++ compiler to
convert
+// from decimal to binary accurately enough to produce the intended
values.
+//
+// Note: Assuming log() return accurate answer, the following
+// algorithm can be used to compute log1p(x) to within a few ULP:
+//
+// u = 1+x;
+// if (u==1.0) return x ; else
+// return log(u)*(x/(u-1.0));
+//
+// See HP-15C Advanced Functions Handbook, p.193.
+//
+const LN2_HI = kMath[34];
+const LN2_LO = kMath[35];
+const TWO54 = kMath[36];
+const TWO_THIRD = kMath[37];
+macro KLOG1P(x)
+(kMath[38+x])
+endmacro
+
+function MathLog1p(x) {
+ x = x * 1; // Convert to number.
+ var hx = %_DoubleHi(x);
+ var ax = hx & 0x7fffffff;
+ var k = 1;
+ var f = x;
+ var hu = 1;
+ var c = 0;
+ var u = x;
+
+ if (hx < 0x3fda827a) {
+ // x < 0.41422
+ if (ax >= 0x3ff00000) { // |x| >= 1
+ if (x === -1) {
+ return -INFINITY; // log1p(-1) = -inf
+ } else {
+ return NAN; // log1p(x<-1) = NaN
+ }
+ } else if (ax < 0x3c900000) {
+ // For |x| < 2^-54 we can return x.
+ return x;
+ } else if (ax < 0x3e200000) {
+ // For |x| < 2^-29 we can use a simple two-term Taylor series.
+ return x - x * x * 0.5;
+ }
+
+ if ((hx > 0) || (hx <= -0x402D413D)) { // (int) 0xbfd2bec3 =
-0x402d413d
+ // -.2929 < x < 0.41422
+ k = 0;
+ }
+ }
+
+ // Handle Infinity and NAN
+ if (hx >= 0x7ff00000) return x;
+
+ if (k !== 0) {
+ if (hx < 0x43400000) {
+ // x < 2^53
+ u = 1 + x;
+ hu = %_DoubleHi(u);
+ k = (hu >> 20) - 1023;
+ c = (k > 0) ? 1 - (u - x) : x - (u - 1);
+ c = c / u;
+ } else {
+ hu = %_DoubleHi(u);
+ k = (hu >> 20) - 1023;
+ }
+ hu = hu & 0xfffff;
+ if (hu < 0x6a09e) {
+ u = %_ConstructDouble(hu | 0x3ff00000, %_DoubleLo(u)); // Normalize
u.
+ } else {
+ ++k;
+ u = %_ConstructDouble(hu | 0x3fe00000, %_DoubleLo(u)); // Normalize
u/2.
+ hu = (0x00100000 - hu) >> 2;
+ }
+ f = u - 1;
+ }
+
+ var hfsq = 0.5 * f * f;
+ if (hu === 0) {
+ // |f| < 2^-20;
+ if (f === 0) {
+ if (k === 0) {
+ return 0.0;
+ } else {
+ return k * LN2_HI + (c + k * LN2_LO);
+ }
+ }
+ var R = hfsq * (1 - TWO_THIRD * f);
+ if (k === 0) {
+ return f - R;
+ } else {
+ return k * LN2_HI - ((R - (k * LN2_LO + c)) - f);
+ }
+ }
+
+ var s = f / (2 + f);
+ var z = s * s;
+ var R = z * (KLOG1P(0) + z * (KLOG1P(1) + z *
+ (KLOG1P(2) + z * (KLOG1P(3) + z *
+ (KLOG1P(4) + z * (KLOG1P(5) + z * KLOG1P(6)))))));
+ if (k === 0) {
+ return f - (hfsq - s * (hfsq + R));
+ } else {
+ return k * LN2_HI - ((hfsq - (s * (hfsq + R) + (k * LN2_LO + c))) - f);
+ }
+}
+
+// ES6 draft 09-27-13, section 20.2.2.14.
+// Math.expm1
+// Returns exp(x)-1, the exponential of x minus 1.
+//
+// Method
+// 1. Argument reduction:
+// Given x, find r and integer k such that
+//
+// x = k*ln2 + r, |r| <= 0.5*ln2 ~ 0.34658
+//
+// Here a correction term c will be computed to compensate
+// the error in r when rounded to a floating-point number.
+//
+// 2. Approximating expm1(r) by a special rational function on
+// the interval [0,0.34658]:
+// Since
+// r*(exp(r)+1)/(exp(r)-1) = 2+ r^2/6 - r^4/360 + ...
+// we define R1(r*r) by
+// r*(exp(r)+1)/(exp(r)-1) = 2+ r^2/6 * R1(r*r)
+// That is,
+// R1(r**2) = 6/r *((exp(r)+1)/(exp(r)-1) - 2/r)
+// = 6/r * ( 1 + 2.0*(1/(exp(r)-1) - 1/r))
+// = 1 - r^2/60 + r^4/2520 - r^6/100800 + ...
+// We use a special Remes algorithm on [0,0.347] to generate
+// a polynomial of degree 5 in r*r to approximate R1. The
+// maximum error of this polynomial approximation is bounded
+// by 2**-61. In other words,
+// R1(z) ~ 1.0 + Q1*z + Q2*z**2 + Q3*z**3 + Q4*z**4 + Q5*z**5
+// where Q1 = -1.6666666666666567384E-2,
+// Q2 = 3.9682539681370365873E-4,
+// Q3 = -9.9206344733435987357E-6,
+// Q4 = 2.5051361420808517002E-7,
+// Q5 = -6.2843505682382617102E-9;
+// (where z=r*r, and the values of Q1 to Q5 are listed below)
+// with error bounded by
+// | 5 | -61
+// | 1.0+Q1*z+...+Q5*z - R1(z) | <= 2
+// | |
+//
+// expm1(r) = exp(r)-1 is then computed by the following
+// specific way which minimize the accumulation rounding error:
+// 2 3
+// r r [ 3 - (R1 + R1*r/2) ]
+// expm1(r) = r + --- + --- * [--------------------]
+// 2 2 [ 6 - r*(3 - R1*r/2) ]
+//
+// To compensate the error in the argument reduction, we use
+// expm1(r+c) = expm1(r) + c + expm1(r)*c
+// ~ expm1(r) + c + r*c
+// Thus c+r*c will be added in as the correction terms for
+// expm1(r+c). Now rearrange the term to avoid optimization
+// screw up:
+// ( 2 2 )
+// ({ ( r [ R1 - (3 - R1*r/2) ] ) } r )
+// expm1(r+c)~r - ({r*(--- * [--------------------]-c)-c} - --- )
+// ({ ( 2 [ 6 - r*(3 - R1*r/2) ] ) } 2 )
+// ( )
+//
+// = r - E
+// 3. Scale back to obtain expm1(x):
+// From step 1, we have
+// expm1(x) = either 2^k*[expm1(r)+1] - 1
+// = or 2^k*[expm1(r) + (1-2^-k)]
+// 4. Implementation notes:
+// (A). To save one multiplication, we scale the coefficient Qi
+// to Qi*2^i, and replace z by (x^2)/2.
+// (B). To achieve maximum accuracy, we compute expm1(x) by
+// (i) if x < -56*ln2, return -1.0, (raise inexact if x!=inf)
+// (ii) if k=0, return r-E
+// (iii) if k=-1, return 0.5*(r-E)-0.5
+// (iv) if k=1 if r < -0.25, return 2*((r+0.5)- E)
+// else return 1.0+2.0*(r-E);
+// (v) if (k<-2||k>56) return 2^k(1-(E-r)) - 1 (or exp(x)-1)
+// (vi) if k <= 20, return 2^k((1-2^-k)-(E-r)), else
+// (vii) return 2^k(1-((E+2^-k)-r))
+//
+// Special cases:
+// expm1(INF) is INF, expm1(NaN) is NaN;
+// expm1(-INF) is -1, and
+// for finite argument, only expm1(0)=0 is exact.
+//
+// Accuracy:
+// according to an error analysis, the error is always less than
+// 1 ulp (unit in the last place).
+//
+// Misc. info.
+// For IEEE double
+// if x > 7.09782712893383973096e+02 then expm1(x) overflow
+//
+const KEXPM1_OVERFLOW = kMath[45];
+const INVLN2 = kMath[46];
+macro KEXPM1(x)
+(kMath[47+x])
+endmacro
+
+function MathExpm1(x) {
+ x = x * 1; // Convert to number.
+ var y;
+ var hi;
+ var lo;
+ var k;
+ var t;
+ var c;
+
+ var hx = %_DoubleHi(x);
+ var xsb = hx & 0x80000000; // Sign bit of x
+ var y = (xsb === 0) ? x : -x; // y = |x|
+ hx &= 0x7fffffff; // High word of |x|
+
+ // Filter out huge and non-finite argument
+ if (hx >= 0x4043687a) { // if |x| ~=> 56 * ln2
+ if (hx >= 0x40862e42) { // if |x| >= 709.78
+ if (hx >= 0x7ff00000) {
+ // expm1(inf) = inf; expm1(-inf) = -1; expm1(nan) = nan;
+ return (x === -INFINITY) ? -1 : x;
+ }
+ if (x > KEXPM1_OVERFLOW) return INFINITY; // Overflow
+ }
+ if (xsb != 0) return -1; // x < -56 * ln2, return -1.
+ }
+
+ // Argument reduction
+ if (hx > 0x3fd62e42) { // if |x| > 0.5 * ln2
+ if (hx < 0x3ff0a2b2) { // and |x| < 1.5 * ln2
+ if (xsb === 0) {
+ hi = x - LN2_HI;
+ lo = LN2_LO;
+ k = 1;
+ } else {
+ hi = x + LN2_HI;
+ lo = -LN2_LO;
+ k = -1;
+ }
+ } else {
+ k = (INVLN2 * x + ((xsb === 0) ? 0.5 : -0.5)) | 0;
+ t = k;
+ // t * ln2_hi is exact here.
+ hi = x - t * LN2_HI;
+ lo = t * LN2_LO;
+ }
+ x = hi - lo;
+ c = (hi - x) - lo;
+ } else if (hx < 0x3c900000) {
+ // When |x| < 2^-54, we can return x.
+ return x;
+ } else {
+ // Fall through.
+ k = 0;
+ }
+
+ // x is now in primary range
+ var hfx = 0.5 * x;
+ var hxs = x * hfx;
+ var r1 = 1 + hxs * (KEXPM1(0) + hxs * (KEXPM1(1) + hxs *
+ (KEXPM1(2) + hxs * (KEXPM1(3) + hxs * KEXPM1(4)))));
+ t = 3 - r1 * hfx;
+ var e = hxs * ((r1 - t) / (6 - x * t));
+ if (k === 0) { // c is 0
+ return x - (x*e - hxs);
+ } else {
+ e = (x * (e - c) - c);
+ e -= hxs;
+ if (k === -1) return 0.5 * (x - e) - 0.5;
+ if (k === 1) {
+ if (x < -0.25) return -2 * (e - (x + 0.5));
+ return 1 + 2 * (x - e);
+ }
+
+ if (k <= -2 || k > 56) {
+ // suffice to return exp(x) + 1
+ y = 1 - (e - x);
+ // Add k to y's exponent
+ y = %_ConstructDouble(%_DoubleHi(y) + (k << 20), %_DoubleLo(y));
+ return y - 1;
+ }
+ if (k < 20) {
+ // t = 1 - 2^k
+ t = %_ConstructDouble(0x3ff00000 - (0x200000 >> k), 0);
+ y = t - (e - x);
+ // Add k to y's exponent
+ y = %_ConstructDouble(%_DoubleHi(y) + (k << 20), %_DoubleLo(y));
+ } else {
+ // t = 2^-k
+ t = %_ConstructDouble((0x3ff - k) << 20, 0);
+ y = x - (e + t);
+ y += 1;
+ // Add k to y's exponent
+ y = %_ConstructDouble(%_DoubleHi(y) + (k << 20), %_DoubleLo(y));
+ }
+ }
+ return y;
+}
+
+
+// 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.
+//
+const KSINH_OVERFLOW = kMath[52];
+const TWO_M28 = 3.725290298461914e-9; // 2^-28, empty lower half
+const 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 * MathExp(ax);
+ // |x| in [log(maxdouble), overflowthreshold]
+ // overflowthreshold = 710.4758600739426
+ if (ax <= KSINH_OVERFLOW) {
+ var w = MathExp(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.
+//
+const KCOSH_OVERFLOW = kMath[52];
+
+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 = MathExp(MathAbs(x));
+ return 0.5 * t + 0.5 / t;
+ }
+ // |x| in [22, log(maxdouble)], return half*exp(|x|)
+ if (ix < 0x40862e42) return 0.5 * MathExp(MathAbs(x));
+ // |x| in [log(maxdouble), overflowthreshold]
+ if (MathAbs(x) <= KCOSH_OVERFLOW) {
+ var w = MathExp(0.5 * MathAbs(x));
+ var t = 0.5 * w;
+ return t * w;
+ }
+ if (NUMBER_IS_NAN(x)) return x;
+ // |x| > overflowthreshold.
+ return INFINITY;
+}
=======================================
--- /dev/null
+++ /trunk/src/unicode-decoder.cc Thu Oct 9 00:05:16 2014 UTC
@@ -0,0 +1,78 @@
+// Copyright 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+
+#include "src/unicode-inl.h"
+#include "src/unicode-decoder.h"
+#include <stdio.h>
+#include <stdlib.h>
+
+namespace unibrow {
+
+void Utf8DecoderBase::Reset(uint16_t* buffer, unsigned buffer_length,
+ const uint8_t* stream, unsigned stream_length)
{
+ // Assume everything will fit in the buffer and stream won't be needed.
+ last_byte_of_buffer_unused_ = false;
+ unbuffered_start_ = NULL;
+ bool writing_to_buffer = true;
+ // Loop until stream is read, writing to buffer as long as buffer has
space.
+ unsigned utf16_length = 0;
+ while (stream_length != 0) {
+ unsigned cursor = 0;
+ uint32_t character = Utf8::ValueOf(stream, stream_length, &cursor);
+ DCHECK(cursor > 0 && cursor <= stream_length);
+ stream += cursor;
+ stream_length -= cursor;
+ bool is_two_characters = character > Utf16::kMaxNonSurrogateCharCode;
+ utf16_length += is_two_characters ? 2 : 1;
+ // Don't need to write to the buffer, but still need utf16_length.
+ if (!writing_to_buffer) continue;
+ // Write out the characters to the buffer.
+ // Must check for equality with buffer_length as we've already updated
it.
+ if (utf16_length <= buffer_length) {
+ if (is_two_characters) {
+ *buffer++ = Utf16::LeadSurrogate(character);
+ *buffer++ = Utf16::TrailSurrogate(character);
+ } else {
+ *buffer++ = character;
+ }
+ if (utf16_length == buffer_length) {
+ // Just wrote last character of buffer
+ writing_to_buffer = false;
+ unbuffered_start_ = stream;
+ }
+ continue;
+ }
+ // Have gone over buffer.
+ // Last char of buffer is unused, set cursor back.
+ DCHECK(is_two_characters);
+ writing_to_buffer = false;
+ last_byte_of_buffer_unused_ = true;
+ unbuffered_start_ = stream - cursor;
+ }
+ utf16_length_ = utf16_length;
+}
+
+
+void Utf8DecoderBase::WriteUtf16Slow(const uint8_t* stream, uint16_t* data,
+ unsigned data_length) {
+ while (data_length != 0) {
+ unsigned cursor = 0;
+ uint32_t character = Utf8::ValueOf(stream, Utf8::kMaxEncodedSize,
&cursor);
+ // There's a total lack of bounds checking for stream
+ // as it was already done in Reset.
+ stream += cursor;
+ if (character > unibrow::Utf16::kMaxNonSurrogateCharCode) {
+ *data++ = Utf16::LeadSurrogate(character);
+ *data++ = Utf16::TrailSurrogate(character);
+ DCHECK(data_length > 1);
+ data_length -= 2;
+ } else {
+ *data++ = character;
+ data_length -= 1;
+ }
+ }
+}
+
+} // namespace unibrow
=======================================
--- /dev/null
+++ /trunk/src/unicode-decoder.h Thu Oct 9 00:05:16 2014 UTC
@@ -0,0 +1,121 @@
+// Copyright 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef V8_UNICODE_DECODER_H_
+#define V8_UNICODE_DECODER_H_
+
+#include <sys/types.h>
+#include "src/globals.h"
+
+namespace unibrow {
+
+class Utf8DecoderBase {
+ public:
+ // Initialization done in subclass.
+ inline Utf8DecoderBase();
+ inline Utf8DecoderBase(uint16_t* buffer, unsigned buffer_length,
+ const uint8_t* stream, unsigned stream_length);
+ inline unsigned Utf16Length() const { return utf16_length_; }
+
+ protected:
+ // This reads all characters and sets the utf16_length_.
+ // The first buffer_length utf16 chars are cached in the buffer.
+ void Reset(uint16_t* buffer, unsigned buffer_length, const uint8_t*
stream,
+ unsigned stream_length);
+ static void WriteUtf16Slow(const uint8_t* stream, uint16_t* data,
+ unsigned length);
+ const uint8_t* unbuffered_start_;
+ unsigned utf16_length_;
+ bool last_byte_of_buffer_unused_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(Utf8DecoderBase);
+};
+
+template <unsigned kBufferSize>
+class Utf8Decoder : public Utf8DecoderBase {
+ public:
+ inline Utf8Decoder() {}
+ inline Utf8Decoder(const char* stream, unsigned length);
+ inline void Reset(const char* stream, unsigned length);
+ inline unsigned WriteUtf16(uint16_t* data, unsigned length) const;
+
+ private:
+ uint16_t buffer_[kBufferSize];
+};
+
+
+Utf8DecoderBase::Utf8DecoderBase()
+ : unbuffered_start_(NULL),
+ utf16_length_(0),
+ last_byte_of_buffer_unused_(false) {}
+
+
+Utf8DecoderBase::Utf8DecoderBase(uint16_t* buffer, unsigned buffer_length,
+ const uint8_t* stream,
+ unsigned stream_length) {
+ Reset(buffer, buffer_length, stream, stream_length);
+}
+
+
+template <unsigned kBufferSize>
+Utf8Decoder<kBufferSize>::Utf8Decoder(const char* stream, unsigned length)
+ : Utf8DecoderBase(buffer_, kBufferSize,
+ reinterpret_cast<const uint8_t*>(stream), length) {}
+
+
+template <unsigned kBufferSize>
+void Utf8Decoder<kBufferSize>::Reset(const char* stream, unsigned length) {
+ Utf8DecoderBase::Reset(buffer_, kBufferSize,
+ reinterpret_cast<const uint8_t*>(stream), length);
+}
+
+
+template <unsigned kBufferSize>
+unsigned Utf8Decoder<kBufferSize>::WriteUtf16(uint16_t* data,
+ unsigned length) const {
+ DCHECK(length > 0);
+ if (length > utf16_length_) length = utf16_length_;
+ // memcpy everything in buffer.
+ unsigned buffer_length =
+ last_byte_of_buffer_unused_ ? kBufferSize - 1 : kBufferSize;
+ unsigned memcpy_length = length <= buffer_length ? length :
buffer_length;
+ v8::internal::MemCopy(data, buffer_, memcpy_length * sizeof(uint16_t));
+ if (length <= buffer_length) return length;
+ DCHECK(unbuffered_start_ != NULL);
+ // Copy the rest the slow way.
+ WriteUtf16Slow(unbuffered_start_, data + buffer_length,
+ length - buffer_length);
+ return length;
+}
+
+class Latin1 {
+ public:
+ static const unsigned kMaxChar = 0xff;
+ // Returns 0 if character does not convert to single latin-1 character
+ // or if the character doesn't not convert back to latin-1 via inverse
+ // operation (upper to lower, etc).
+ static inline uint16_t ConvertNonLatin1ToLatin1(uint16_t);
+};
+
+
+uint16_t Latin1::ConvertNonLatin1ToLatin1(uint16_t c) {
+ DCHECK(c > Latin1::kMaxChar);
+ switch (c) {
+ // This are equivalent characters in unicode.
+ case 0x39c:
+ case 0x3bc:
+ return 0xb5;
+ // This is an uppercase of a Latin-1 character
+ // outside of Latin-1.
+ case 0x178:
+ return 0xff;
+ }
+ return 0;
+}
+
+
+} // namespace unibrow
+
+#endif // V8_UNICODE_DECODER_H_
=======================================
--- /dev/null
+++ /trunk/test/mjsunit/asm/float32array-outofbounds.js Thu Oct 9 00:05:16
2014 UTC
@@ -0,0 +1,30 @@
+// Copyright 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+function Module(stdlib, foreign, heap) {
+ "use asm";
+ var MEM32 = new stdlib.Float32Array(heap);
+ function load(i) {
+ i = i|0;
+ i = +MEM32[i >> 2];
+ return i;
+ }
+ function store(i, v) {
+ i = i|0;
+ v = +v;
+ MEM32[i >> 2] = v;
+ }
+ return { load: load, store: store };
+}
+
+var m = Module(this, {}, new ArrayBuffer(4));
+
+m.store(0, 42.0);
+for (var i = 1; i < 64; ++i) {
+ m.store(i * 4 * 32 * 1024, i);
+}
+assertEquals(42.0, m.load(0));
+for (var i = 1; i < 64; ++i) {
+ assertEquals(NaN, m.load(i * 4 * 32 * 1024));
+}
=======================================
--- /dev/null
+++ /trunk/test/mjsunit/asm/float64array-outofbounds.js Thu Oct 9 00:05:16
2014 UTC
@@ -0,0 +1,30 @@
+// Copyright 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+function Module(stdlib, foreign, heap) {
+ "use asm";
+ var MEM64 = new stdlib.Float64Array(heap);
+ function load(i) {
+ i = i|0;
+ i = +MEM64[i >> 3];
+ return i;
+ }
+ function store(i, v) {
+ i = i|0;
+ v = +v;
+ MEM64[i >> 3] = v;
+ }
+ return { load: load, store: store };
+}
+
+var m = Module(this, {}, new ArrayBuffer(8));
+
+m.store(0, 3.12);
+for (var i = 1; i < 64; ++i) {
+ m.store(i * 8 * 32 * 1024, i);
+}
+assertEquals(3.12, m.load(0));
+for (var i = 1; i < 64; ++i) {
+ assertEquals(NaN, m.load(i * 8 * 32 * 1024));
+}
=======================================
--- /dev/null
+++ /trunk/test/mjsunit/asm/int16array-outofbounds.js Thu Oct 9 00:05:16
2014 UTC
@@ -0,0 +1,30 @@
+// Copyright 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+function Module(stdlib, foreign, heap) {
+ "use asm";
+ var MEM16 = new stdlib.Int16Array(heap);
+ function load(i) {
+ i = i|0;
+ i = MEM16[i >> 1] | 0;
+ return i;
+ }
+ function store(i, v) {
+ i = i|0;
+ v = v|0;
+ MEM16[i >> 1] = v;
+ }
+ return { load: load, store: store };
+}
+
+var m = Module(this, {}, new ArrayBuffer(2));
+
+m.store(0, 32767);
+for (var i = 1; i < 64; ++i) {
+ m.store(i * 2 * 32 * 1024, i);
+}
+assertEquals(32767, m.load(0));
+for (var i = 1; i < 64; ++i) {
+ assertEquals(0, m.load(i * 2 * 32 * 1024));
+}
=======================================
--- /dev/null
+++ /trunk/test/mjsunit/asm/int32-div.js Thu Oct 9 00:05:16 2014 UTC
@@ -0,0 +1,33 @@
+// Copyright 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+function Module(stdlib, foreign, heap) {
+ "use asm";
+ function f1(i) {
+ i = i|0;
+ return i / 3 | 0;
+ }
+ function f2(i) {
+ i = i|0;
+ return i / 13 | 0;
+ }
+ function f3(i) {
+ i = i|0;
+ return i / 1024 | 0;
+ }
+ function f4(i) {
+ i = i|0;
+ return i / 3733331 | 0;
+ }
+ return { f1: f1, f2: f2, f3: f3, f4: f4 };
+}
+
+var m = Module(this, {}, new ArrayBuffer(1024));
+
+for (var i = -2147483648; i < 2147483648; i += 3999777) {
+ assertEquals(i / 3 | 0, m.f1(i));
+ assertEquals(i / 13 | 0, m.f2(i));
+ assertEquals(i / 1024 | 0, m.f3(i));
+ assertEquals(i / 3733331 | 0, m.f4(i));
+}
=======================================
--- /dev/null
+++ /trunk/test/mjsunit/asm/int32-mod.js Thu Oct 9 00:05:16 2014 UTC
@@ -0,0 +1,33 @@
+// Copyright 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+function Module(stdlib, foreign, heap) {
+ "use asm";
+ function f1(i) {
+ i = i|0;
+ return i % 3;
+ }
+ function f2(i) {
+ i = i|0;
+ return i % 9;
+ }
+ function f3(i) {
+ i = i|0;
+ return i % 1024;
+ }
+ function f4(i) {
+ i = i|0;
+ return i % 3133335;
+ }
+ return { f1: f1, f2: f2, f3: f3, f4: f4 };
+}
+
+var m = Module(this, {}, new ArrayBuffer(1024));
+
+for (var i = -2147483648; i < 2147483648; i += 3999773) {
+ assertEquals(i % 3, m.f1(i));
+ assertEquals(i % 9, m.f2(i));
+ assertEquals(i % 1024, m.f3(i));
+ assertEquals(i % 3133335, m.f4(i));
+}
=======================================
--- /dev/null
+++ /trunk/test/mjsunit/asm/int32-mul.js Thu Oct 9 00:05:16 2014 UTC
@@ -0,0 +1,33 @@
+// Copyright 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+function Module(stdlib, foreign, heap) {
+ "use asm";
+ function f1(i) {
+ i = i|0;
+ return i * 3 | 0;
+ }
+ function f2(i) {
+ i = i|0;
+ return i * 7 | 0;
+ }
+ function f3(i) {
+ i = i|0;
+ return i * 1024 | 0;
+ }
+ function f4(i) {
+ i = i|0;
+ return i * 3333339 | 0;
+ }
+ return { f1: f1, f2: f2, f3: f3, f4: f4 };
+}
+
+var m = Module(this, {}, new ArrayBuffer(1024));
+
+for (var i = -2147483648; i < 2147483648; i += 3999771) {
+ assertEquals(i * 3 | 0, m.f1(i));
+ assertEquals(i * 7 | 0, m.f2(i));
+ assertEquals(i * 1024 | 0, m.f3(i));
+ assertEquals(i * 3333339 | 0, m.f4(i));
+}
=======================================
--- /dev/null
+++ /trunk/test/mjsunit/asm/int32-tmod.js Thu Oct 9 00:05:16 2014 UTC
@@ -0,0 +1,33 @@
+// Copyright 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+function Module(stdlib, foreign, heap) {
+ "use asm";
+ function f1(i) {
+ i = i|0;
+ return i % 3 | 0;
+ }
+ function f2(i) {
+ i = i|0;
+ return i % 9 | 0;
+ }
+ function f3(i) {
+ i = i|0;
+ return i % 1024 | 0;
+ }
+ function f4(i) {
+ i = i|0;
+ return i % 3333339 | 0;
+ }
+ return { f1: f1, f2: f2, f3: f3, f4: f4 };
+}
+
+var m = Module(this, {}, new ArrayBuffer(1024));
+
+for (var i = -2147483648; i < 2147483648; i += 3999773) {
+ assertEquals(i % 3 | 0, m.f1(i));
+ assertEquals(i % 9 | 0, m.f2(i));
+ assertEquals(i % 1024 | 0, m.f3(i));
+ assertEquals(i % 3333339 | 0, m.f4(i));
+}
=======================================
--- /dev/null
+++ /trunk/test/mjsunit/asm/int32-udiv.js Thu Oct 9 00:05:16 2014 UTC
@@ -0,0 +1,33 @@
+// Copyright 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+function Module(stdlib, foreign, heap) {
+ "use asm";
+ function f1(i) {
+ i = i>>>0;
+ return i / 3 | 0;
+ }
+ function f2(i) {
+ i = i>>>0;
+ return i / 17 | 0;
+ }
+ function f3(i) {
+ i = i>>>0;
+ return i / 1024 | 0;
+ }
+ function f4(i) {
+ i = i>>>0;
+ return i / 3343330 | 0;
+ }
+ return { f1: f1, f2: f2, f3: f3, f4: f4 };
+}
+
+var m = Module(this, {}, new ArrayBuffer(1024));
+
+for (var i = 0; i < 4294967296; i += 3999777) {
+ assertEquals(i / 3 | 0, m.f1(i));
+ assertEquals(i / 17 | 0, m.f2(i));
+ assertEquals(i / 1024 | 0, m.f3(i));
+ assertEquals(i / 3343330 | 0, m.f4(i));
+}
=======================================
--- /dev/null
+++ /trunk/test/mjsunit/asm/int32-umod.js Thu Oct 9 00:05:16 2014 UTC
@@ -0,0 +1,33 @@
+// Copyright 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+function Module(stdlib, foreign, heap) {
+ "use asm";
+ function f1(i) {
+ i = i>>>0;
+ return i % 3;
+ }
+ function f2(i) {
+ i = i>>>0;
+ return i % 11;
+ }
+ function f3(i) {
+ i = i>>>0;
+ return i % 1024;
+ }
+ function f4(i) {
+ i = i>>>0;
+ return i % 3333337;
+ }
+ return { f1: f1, f2: f2, f3: f3, f4: f4 };
+}
+
+var m = Module(this, {}, new ArrayBuffer(1024));
+
+for (var i = 0; i < 4294967296; i += 3999777) {
+ assertEquals(i % 3, m.f1(i));
+ assertEquals(i % 11, m.f2(i));
+ assertEquals(i % 1024, m.f3(i));
+ assertEquals(i % 3333337, m.f4(i));
+}
=======================================
--- /dev/null
+++ /trunk/test/mjsunit/asm/int32array-outofbounds.js Thu Oct 9 00:05:16
2014 UTC
@@ -0,0 +1,30 @@
+// Copyright 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+function Module(stdlib, foreign, heap) {
+ "use asm";
+ var MEM32 = new stdlib.Int32Array(heap);
+ function load(i) {
+ i = i|0;
+ i = MEM32[i >> 2] | 0;
+ return i;
+ }
+ function store(i, v) {
+ i = i|0;
+ v = v|0;
+ MEM32[i >> 2] = v;
+ }
+ return { load: load, store: store };
+}
+
+var m = Module(this, {}, new ArrayBuffer(4));
+
+m.store(0, 0x12345678);
+for (var i = 1; i < 64; ++i) {
+ m.store(i * 4 * 32 * 1024, i);
+}
+assertEquals(0x12345678, m.load(0));
+for (var i = 1; i < 64; ++i) {
+ assertEquals(0, m.load(i * 4 * 32 * 1024));
+}
=======================================
--- /dev/null
+++ /trunk/test/mjsunit/asm/uint8array-outofbounds.js Thu Oct 9 00:05:16
2014 UTC
@@ -0,0 +1,30 @@
+// Copyright 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+function Module(stdlib, foreign, heap) {
+ "use asm";
+ var MEM8 = new stdlib.Uint8Array(heap);
+ function load(i) {
+ i = i|0;
+ i = MEM8[i] | 0;
+ return i;
+ }
+ function store(i, v) {
+ i = i|0;
+ v = v|0;
+ MEM8[i] = v;
+ }
+ return { load: load, store: store };
+}
+
+var m = Module(this, {}, new ArrayBuffer(1));
+
+m.store(0, 255);
+for (var i = 1; i < 64; ++i) {
+ m.store(i * 1 * 32 * 1024, i);
+}
+assertEquals(255, m.load(0));
+for (var i = 1; i < 64; ++i) {
+ assertEquals(0, m.load(i * 1 * 32 * 1024));
+}
=======================================
--- /dev/null
+++ /trunk/test/unittests/unicode/unicode-predicates-unittest.cc Thu Oct 9
00:05:16 2014 UTC
@@ -0,0 +1,90 @@
+// Copyright 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "src/char-predicates.h"
+#include "src/unicode.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace v8 {
+namespace internal {
+
+TEST(UnicodePredicatesTest, WhiteSpace) {
+ // As of Unicode 6.3.0, \u180E is no longer a white space. We still
consider
+ // it to be one though, since JS recognizes all white spaces in Unicode
5.1.
+ EXPECT_TRUE(WhiteSpace::Is(0x0009));
+ EXPECT_TRUE(WhiteSpace::Is(0x000B));
+ EXPECT_TRUE(WhiteSpace::Is(0x000C));
+ EXPECT_TRUE(WhiteSpace::Is(' '));
+ EXPECT_TRUE(WhiteSpace::Is(0x00A0));
+ EXPECT_TRUE(WhiteSpace::Is(0x180E));
+ EXPECT_TRUE(WhiteSpace::Is(0xFEFF));
+}
+
+
+TEST(UnicodePredicatesTest, WhiteSpaceOrLineTerminator) {
+ // As of Unicode 6.3.0, \u180E is no longer a white space. We still
consider
+ // it to be one though, since JS recognizes all white spaces in Unicode
5.1.
+ // White spaces
+ EXPECT_TRUE(WhiteSpaceOrLineTerminator::Is(0x0009));
+ EXPECT_TRUE(WhiteSpaceOrLineTerminator::Is(0x000B));
+ EXPECT_TRUE(WhiteSpaceOrLineTerminator::Is(0x000C));
+ EXPECT_TRUE(WhiteSpaceOrLineTerminator::Is(' '));
+ EXPECT_TRUE(WhiteSpaceOrLineTerminator::Is(0x00A0));
+ EXPECT_TRUE(WhiteSpaceOrLineTerminator::Is(0x180E));
+ EXPECT_TRUE(WhiteSpaceOrLineTerminator::Is(0xFEFF));
+ // Line terminators
+ EXPECT_TRUE(WhiteSpaceOrLineTerminator::Is(0x000A));
+ EXPECT_TRUE(WhiteSpaceOrLineTerminator::Is(0x000D));
+ EXPECT_TRUE(WhiteSpaceOrLineTerminator::Is(0x2028));
+ EXPECT_TRUE(WhiteSpaceOrLineTerminator::Is(0x2029));
+}
+
+
+TEST(UnicodePredicatesTest, IdentifierStart) {
+ EXPECT_TRUE(IdentifierStart::Is('$'));
+ EXPECT_TRUE(IdentifierStart::Is('_'));
+ EXPECT_TRUE(IdentifierStart::Is('\\'));
+
+ // http://www.unicode.org/reports/tr31/
+ // Other_ID_Start
+ EXPECT_TRUE(IdentifierStart::Is(0x2118));
+ EXPECT_TRUE(IdentifierStart::Is(0x212E));
+ EXPECT_TRUE(IdentifierStart::Is(0x309B));
+ EXPECT_TRUE(IdentifierStart::Is(0x309C));
+
+ // Issue 2892:
+ // \u2E2F has the Pattern_Syntax property, excluding it from ID_Start.
+ EXPECT_FALSE(unibrow::ID_Start::Is(0x2E2F));
+}
+
+
+TEST(UnicodePredicatesTest, IdentifierPart) {
+ EXPECT_TRUE(IdentifierPart::Is('$'));
+ EXPECT_TRUE(IdentifierPart::Is('_'));
+ EXPECT_TRUE(IdentifierPart::Is('\\'));
+ EXPECT_TRUE(IdentifierPart::Is(0x200C));
+ EXPECT_TRUE(IdentifierPart::Is(0x200D));
+
+ // http://www.unicode.org/reports/tr31/
+ // Other_ID_Start
+ EXPECT_TRUE(IdentifierPart::Is(0x2118));
+ EXPECT_TRUE(IdentifierPart::Is(0x212E));
+ EXPECT_TRUE(IdentifierPart::Is(0x309B));
+ EXPECT_TRUE(IdentifierPart::Is(0x309C));
+
+ // Other_ID_Continue
+ EXPECT_TRUE(IdentifierPart::Is(0x00B7));
+ EXPECT_TRUE(IdentifierPart::Is(0x0387));
+ EXPECT_TRUE(IdentifierPart::Is(0x1369));
+ EXPECT_TRUE(IdentifierPart::Is(0x1370));
+ EXPECT_TRUE(IdentifierPart::Is(0x1371));
+ EXPECT_TRUE(IdentifierPart::Is(0x19DA));
+
+ // Issue 2892:
+ // \u2E2F has the Pattern_Syntax property, excluding it from ID_Start.
+ EXPECT_FALSE(IdentifierPart::Is(0x2E2F));
+}
+
+} // namespace internal
+} // namespace v8
=======================================
--- /trunk/third_party/fdlibm/LICENSE Thu Aug 21 07:23:04 2014 UTC
+++ /dev/null
@@ -1,6 +0,0 @@
-Copyright (C) 1993-2004 by Sun Microsystems, Inc. All rights reserved.
-
-Developed at SunSoft, a Sun Microsystems, Inc. business.
-Permission to use, copy, modify, and distribute this
-software is freely granted, provided that this notice
-is preserved.
=======================================
--- /trunk/third_party/fdlibm/README.v8 Thu Aug 7 08:39:21 2014 UTC
+++ /dev/null
@@ -1,18 +0,0 @@
-Name: Freely Distributable LIBM
-Short Name: fdlibm
-URL: http://www.netlib.org/fdlibm/
-Version: 5.3
-License: Freely Distributable.
-License File: LICENSE.
-Security Critical: yes.
-License Android Compatible: yes.
-
-Description:
-This is used to provide a accurate implementation for trigonometric
functions
-used in V8.
-
-Local Modifications:
-For the use in V8, fdlibm has been reduced to include only sine, cosine and
-tangent. To make inlining into generated code possible, a large portion of
-that has been translated to Javascript. The rest remains in C, but has
been
-refactored and reformatted to interoperate with the rest of V8.
=======================================
--- /trunk/third_party/fdlibm/fdlibm.cc Tue Sep 2 12:59:15 2014 UTC
+++ /dev/null
@@ -1,281 +0,0 @@
-// The following is adapted from fdlibm (http://www.netlib.org/fdlibm).
-//
-// ====================================================
-// Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
-//
-// Developed at SunSoft, a Sun Microsystems, Inc. business.
-// Permission to use, copy, modify, and distribute this
-// software is freely granted, provided that this notice
-// is preserved.
-// ====================================================
-//
-// The original source code covered by the above license above has been
-// modified significantly by Google Inc.
-// Copyright 2014 the V8 project authors. All rights reserved.
-
-#include "src/v8.h"
-
-#include "src/double.h"
-#include "third_party/fdlibm/fdlibm.h"
-
-
-namespace v8 {
-namespace fdlibm {
-
-#ifdef _MSC_VER
-inline double scalbn(double x, int y) { return _scalb(x, y); }
-#endif // _MSC_VER
-
-const double MathConstants::constants[] = {
- 6.36619772367581382433e-01, // invpio2 0
- 1.57079632673412561417e+00, // pio2_1 1
- 6.07710050650619224932e-11, // pio2_1t 2
- 6.07710050630396597660e-11, // pio2_2 3
- 2.02226624879595063154e-21, // pio2_2t 4
- 2.02226624871116645580e-21, // pio2_3 5
- 8.47842766036889956997e-32, // pio2_3t 6
- -1.66666666666666324348e-01, // S1 7 coefficients for sin
- 8.33333333332248946124e-03, // 8
- -1.98412698298579493134e-04, // 9
- 2.75573137070700676789e-06, // 10
- -2.50507602534068634195e-08, // 11
- 1.58969099521155010221e-10, // S6 12
- 4.16666666666666019037e-02, // C1 13 coefficients for cos
- -1.38888888888741095749e-03, // 14
- 2.48015872894767294178e-05, // 15
- -2.75573143513906633035e-07, // 16
- 2.08757232129817482790e-09, // 17
- -1.13596475577881948265e-11, // C6 18
- 3.33333333333334091986e-01, // T0 19 coefficients for tan
- 1.33333333333201242699e-01, // 20
- 5.39682539762260521377e-02, // 21
- 2.18694882948595424599e-02, // 22
- 8.86323982359930005737e-03, // 23
- 3.59207910759131235356e-03, // 24
- 1.45620945432529025516e-03, // 25
- 5.88041240820264096874e-04, // 26
- 2.46463134818469906812e-04, // 27
- 7.81794442939557092300e-05, // 28
- 7.14072491382608190305e-05, // 29
- -1.85586374855275456654e-05, // 30
- 2.59073051863633712884e-05, // T12 31
- 7.85398163397448278999e-01, // pio4 32
- 3.06161699786838301793e-17, // pio4lo 33
- 6.93147180369123816490e-01, // ln2_hi 34
- 1.90821492927058770002e-10, // ln2_lo 35
- 1.80143985094819840000e+16, // 2^54 36
- 6.666666666666666666e-01, // 2/3 37
- 6.666666666666735130e-01, // LP1 38 coefficients for log1p
- 3.999999999940941908e-01, // 39
- 2.857142874366239149e-01, // 40
- 2.222219843214978396e-01, // 41
- 1.818357216161805012e-01, // 42
- 1.531383769920937332e-01, // 43
- 1.479819860511658591e-01, // LP7 44
- 7.09782712893383973096e+02, // 45 overflow threshold for
expm1
- 1.44269504088896338700e+00, // 1/ln2 46
- -3.33333333333331316428e-02, // Q1 47 coefficients for expm1
- 1.58730158725481460165e-03, // 48
- -7.93650757867487942473e-05, // 49
- 4.00821782732936239552e-06, // 50
- -2.01099218183624371326e-07, // Q5 51
- 710.4758600739439 // 52 overflow threshold sinh,
cosh
-};
-
-
-// Table of constants for 2/pi, 396 Hex digits (476 decimal) of 2/pi
-static const int 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 double zero = 0.0;
-static const double two24 = 1.6777216e+07;
-static const double one = 1.0;
-static const double twon24 = 5.9604644775390625e-08;
-
-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
-};
-
-
-int __kernel_rem_pio2(double* x, double* y, int e0, int nx) {
- static const int32_t jk = 3;
- double fw;
- int32_t jx = nx - 1;
- int32_t jv = (e0 - 3) / 24;
- if (jv < 0) jv = 0;
- int32_t q0 = e0 - 24 * (jv + 1);
- int32_t m = jx + jk;
-
- double f[10];
- for (int i = 0, j = jv - jx; i <= m; i++, j++) {
- f[i] = (j < 0) ? zero : static_cast<double>(two_over_pi[j]);
- }
-
- double q[10];
- for (int i = 0; i <= jk; i++) {
- fw = 0.0;
- for (int j = 0; j <= jx; j++) fw += x[j] * f[jx + i - j];
- q[i] = fw;
- }
-
- int32_t jz = jk;
-
-recompute:
-
- int32_t iq[10];
- double z = q[jz];
- for (int i = 0, j = 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;
- }
-
- z = scalbn(z, q0);
- z -= 8.0 * std::floor(z * 0.125);
- int32_t n = static_cast<int32_t>(z);
- z -= static_cast<double>(n);
- int32_t ih = 0;
- if (q0 > 0) {
- int32_t 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) {
- n += 1;
- int32_t carry = 0;
- for (int i = 0; i < jz; i++) {
- int32_t j = iq[i];
- if (carry == 0) {
- if (j != 0) {
- carry = 1;
- iq[i] = 0x1000000 - j;
- }
- } else {
- iq[i] = 0xffffff - j;
- }
- }
- if (q0 == 1) {
- iq[jz - 1] &= 0x7fffff;
- } else if (q0 == 2) {
- iq[jz - 1] &= 0x3fffff;
- }
- if (ih == 2) {
- z = one - z;
- if (carry != 0) z -= scalbn(one, q0);
- }
- }
-
- if (z == zero) {
- int32_t j = 0;
- for (int i = jz - 1; i >= jk; i--) j |= iq[i];
- if (j == 0) {
- int32_t k = 1;
- while (iq[jk - k] == 0) k++;
- for (int i = jz + 1; i <= jz + k; i++) {
- f[jx + i] = static_cast<double>(two_over_pi[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;
- }
- }
-
- if (z == 0.0) {
- jz -= 1;
- q0 -= 24;
- while (iq[jz] == 0) {
- jz--;
- q0 -= 24;
- }
- } else {
- z = scalbn(z, -q0);
- if (z >= two24) {
- fw = static_cast<double>(static_cast<int32_t>(twon24 * z));
- iq[jz] = static_cast<int32_t>(z - two24 * fw);
- jz += 1;
- q0 += 24;
- iq[jz] = static_cast<int32_t>(fw);
- } else {
- iq[jz] = static_cast<int32_t>(z);
- }
- }
-
- fw = scalbn(one, q0);
- for (int i = jz; i >= 0; i--) {
- q[i] = fw * static_cast<double>(iq[i]);
- fw *= twon24;
- }
-
- double fq[10];
- for (int i = jz; i >= 0; i--) {
- fw = 0.0;
- for (int k = 0; k <= jk && k <= jz - i; k++) fw += PIo2[k] * q[i + k];
- fq[jz - i] = fw;
- }
-
- fw = 0.0;
- for (int i = jz; i >= 0; i--) fw += fq[i];
- y[0] = (ih == 0) ? fw : -fw;
- fw = fq[0] - fw;
- for (int i = 1; i <= jz; i++) fw += fq[i];
- y[1] = (ih == 0) ? fw : -fw;
- return n & 7;
-}
-
-
-int rempio2(double x, double* y) {
- int32_t hx = static_cast<int32_t>(internal::double_to_uint64(x) >> 32);
- int32_t ix = hx & 0x7fffffff;
-
- if (ix >= 0x7ff00000) {
- *y = base::OS::nan_value();
- return 0;
- }
-
- int32_t e0 = (ix >> 20) - 1046;
- uint64_t zi = internal::double_to_uint64(x) & 0xFFFFFFFFu;
- zi |= static_cast<uint64_t>(ix - (e0 << 20)) << 32;
- double z = internal::uint64_to_double(zi);
-
- double tx[3];
- for (int i = 0; i < 2; i++) {
- tx[i] = static_cast<double>(static_cast<int32_t>(z));
- z = (z - tx[i]) * two24;
- }
- tx[2] = z;
-
- int nx = 3;
- while (tx[nx - 1] == zero) nx--;
- int n = __kernel_rem_pio2(tx, y, e0, nx);
- if (hx < 0) {
- y[0] = -y[0];
- y[1] = -y[1];
- return -n;
- }
- return n;
-}
-}
-} // namespace v8::internal
=======================================
--- /trunk/third_party/fdlibm/fdlibm.h Mon Sep 1 00:05:43 2014 UTC
+++ /dev/null
@@ -1,31 +0,0 @@
-// The following is adapted from fdlibm (http://www.netlib.org/fdlibm).
-//
-// ====================================================
-// Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
-//
-// Developed at SunSoft, a Sun Microsystems, Inc. business.
-// Permission to use, copy, modify, and distribute this
-// software is freely granted, provided that this notice
-// is preserved.
-// ====================================================
-//
-// The original source code covered by the above license above has been
-// modified significantly by Google Inc.
-// Copyright 2014 the V8 project authors. All rights reserved.
-
-#ifndef V8_FDLIBM_H_
-#define V8_FDLIBM_H_
-
-namespace v8 {
-namespace fdlibm {
-
-int rempio2(double x, double* y);
-
-// Constants to be exposed to builtins via Float64Array.
-struct MathConstants {
- static const double constants[53];
-};
-}
-} // namespace v8::internal
-
-#endif // V8_FDLIBM_H_
=======================================
--- /trunk/third_party/fdlibm/fdlibm.js Tue Sep 2 12:59:15 2014 UTC
+++ /dev/null
@@ -1,814 +0,0 @@
-// The following is adapted from fdlibm (http://www.netlib.org/fdlibm),
-//
-// ====================================================
-// Copyright (C) 1993-2004 by Sun Microsystems, Inc. All rights reserved.
-//
-// Developed at SunSoft, a Sun Microsystems, Inc. business.
-// Permission to use, copy, modify, and distribute this
-// software is freely granted, provided that this notice
-// is preserved.
-// ====================================================
-//
-// The original source code covered by the above license above has been
-// modified significantly by Google Inc.
-// Copyright 2014 the V8 project authors. All rights reserved.
-//
-// The following is a straightforward translation of fdlibm routines
-// by Raymond Toy ([email protected]).
-
-// Double constants that do not have empty lower 32 bits are found in
fdlibm.cc
-// and exposed through kMath as typed array. We assume the compiler to
convert
-// from decimal to binary accurately enough to produce the intended values.
-// kMath is initialized to a Float64Array during genesis and not writable.
-var kMath;
-
-const INVPIO2 = kMath[0];
-const PIO2_1 = kMath[1];
-const PIO2_1T = kMath[2];
-const PIO2_2 = kMath[3];
-const PIO2_2T = kMath[4];
-const PIO2_3 = kMath[5];
-const PIO2_3T = kMath[6];
-const PIO4 = kMath[32];
-const PIO4LO = kMath[33];
-
-// Compute k and r such that x - k*pi/2 = r where |r| < pi/4. For
-// precision, r is returned as two values y0 and y1 such that r = y0 + y1
-// to more than double precision.
-macro REMPIO2(X)
- var n, y0, y1;
- var hx = %_DoubleHi(X);
- var ix = hx & 0x7fffffff;
-
- if (ix < 0x4002d97c) {
- // |X| ~< 3*pi/4, special case with n = +/- 1
- if (hx > 0) {
- var z = X - PIO2_1;
- if (ix != 0x3ff921fb) {
- // 33+53 bit pi is good enough
- y0 = z - PIO2_1T;
- y1 = (z - y0) - PIO2_1T;
- } else {
- // near pi/2, use 33+33+53 bit pi
- z -= PIO2_2;
- y0 = z - PIO2_2T;
- y1 = (z - y0) - PIO2_2T;
- }
- n = 1;
- } else {
- // Negative X
- var z = X + PIO2_1;
- if (ix != 0x3ff921fb) {
- // 33+53 bit pi is good enough
- y0 = z + PIO2_1T;
- y1 = (z - y0) + PIO2_1T;
- } else {
- // near pi/2, use 33+33+53 bit pi
- z += PIO2_2;
- y0 = z + PIO2_2T;
- y1 = (z - y0) + PIO2_2T;
- }
- n = -1;
- }
- } else if (ix <= 0x413921fb) {
- // |X| ~<= 2^19*(pi/2), medium size
- var t = MathAbs(X);
- n = (t * INVPIO2 + 0.5) | 0;
- var r = t - n * PIO2_1;
- var w = n * PIO2_1T;
- // First round good to 85 bit
- y0 = r - w;
- if (ix - (%_DoubleHi(y0) & 0x7ff00000) > 0x1000000) {
- // 2nd iteration needed, good to 118
- t = r;
- w = n * PIO2_2;
- r = t - w;
- w = n * PIO2_2T - ((t - r) - w);
- y0 = r - w;
- if (ix - (%_DoubleHi(y0) & 0x7ff00000) > 0x3100000) {
- // 3rd iteration needed. 151 bits accuracy
- t = r;
- w = n * PIO2_3;
- r = t - w;
- w = n * PIO2_3T - ((t - r) - w);
- y0 = r - w;
- }
- }
- y1 = (r - y0) - w;
- if (hx < 0) {
- n = -n;
- y0 = -y0;
- y1 = -y1;
- }
- } else {
- // Need to do full Payne-Hanek reduction here.
- var r = %RemPiO2(X);
- n = r[0];
- y0 = r[1];
- y1 = r[2];
- }
-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))
-//
-macro KSIN(x)
-kMath[7+x]
-endmacro
-
-macro RETURN_KERNELSIN(X, Y, SIGN)
- var z = X * X;
- var v = z * X;
- var r = KSIN(1) + z * (KSIN(2) + z * (KSIN(3) +
- z * (KSIN(4) + z * KSIN(5))));
- return (X - ((z * (0.5 * Y - v * r) - Y) - v * KSIN(0))) 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.
-//
-macro KCOS(x)
-kMath[13+x]
-endmacro
-
-macro RETURN_KERNELCOS(X, Y, SIGN)
- var ix = %_DoubleHi(X) & 0x7fffffff;
- var z = X * X;
- var r = z * (KCOS(0) + z * (KCOS(1) + z * (KCOS(2)+
- z * (KCOS(3) + z * (KCOS(4) + z * KCOS(5))))));
- 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.
-// Input k indicates whether ieee_tan (if k = 1) or -1/tan (if k = -1)
-// is returned.
-//
-// Algorithm
-// 1. Since ieee_tan(-x) = -ieee_tan(x), we need only to consider
positive x.
-// 2. if x < 2^-28 (hx<0x3e300000 0), return x with inexact if x!=0.
-// 3. ieee_tan(x) is approximated by a odd polynomial of degree 27 on
-// [0,0.67434]
-// 3 27
-// tan(x) ~ x + T1*x + ... + T13*x
-// where
-//
-// |ieee_tan(x) 2 4 26 | -59.2
-// |----- - (1+T1*x +T2*x +.... +T13*x )| <= 2
-// | x |
-//
-// Note: ieee_tan(x+y) = ieee_tan(x) + tan'(x)*y
-// ~ ieee_tan(x) + (1+x*x)*y
-// Therefore, for better accuracy in computing ieee_tan(x+y), let
-// 3 2 2 2 2
-// r = x *(T2+x *(T3+x *(...+x *(T12+x *T13))))
-// then
-// 3 2
-// tan(x+y) = x + (T1*x + (x *(r+y)+y))
-//
-// 4. For x in [0.67434,pi/4], let y = pi/4 - x, then
-// tan(x) = ieee_tan(pi/4-y) = (1-ieee_tan(y))/(1+ieee_tan(y))
-// = 1 - 2*(ieee_tan(y) - (ieee_tan(y)^2)/(1+ieee_tan(y)))
-//
-// Set returnTan to 1 for tan; -1 for cot. Anything else is illegal
-// and will cause incorrect results.
-//
-macro KTAN(x)
-kMath[19+x]
-endmacro
-
-function KernelTan(x, y, returnTan) {
- var z;
- var w;
- var hx = %_DoubleHi(x);
- var ix = hx & 0x7fffffff;
-
- if (ix < 0x3e300000) { // |x| < 2^-28
- if (((ix | %_DoubleLo(x)) | (returnTan + 1)) == 0) {
- // x == 0 && returnTan = -1
- return 1 / MathAbs(x);
- } else {
- if (returnTan == 1) {
- return x;
- } else {
- // Compute -1/(x + y) carefully
- var w = x + y;
- var z = %_ConstructDouble(%_DoubleHi(w), 0);
- var v = y - (z - x);
- var a = -1 / w;
- var t = %_ConstructDouble(%_DoubleHi(a), 0);
- var s = 1 + t * z;
- return t + a * (s + t * v);
- }
- }
- }
- if (ix >= 0x3fe59429) { // |x| > .6744
- if (x < 0) {
- x = -x;
- y = -y;
- }
- z = PIO4 - x;
- w = PIO4LO - y;
- x = z + w;
- y = 0;
- }
- z = x * x;
- w = z * z;
-
- // Break x^5 * (T1 + x^2*T2 + ...) into
- // x^5 * (T1 + x^4*T3 + ... + x^20*T11) +
- // x^5 * (x^2 * (T2 + x^4*T4 + ... + x^22*T12))
- var r = KTAN(1) + w * (KTAN(3) + w * (KTAN(5) +
- w * (KTAN(7) + w * (KTAN(9) + w * KTAN(11)))));
- var v = z * (KTAN(2) + w * (KTAN(4) + w * (KTAN(6) +
- w * (KTAN(8) + w * (KTAN(10) + w * KTAN(12))))));
- var s = z * x;
- r = y + z * (s * (r + v) + y);
- r = r + KTAN(0) * s;
- w = x + r;
- if (ix >= 0x3fe59428) {
- return (1 - ((hx >> 30) & 2)) *
- (returnTan - 2.0 * (x - (w * w / (w + returnTan) - r)));
- }
- if (returnTan == 1) {
- return w;
- } else {
- z = %_ConstructDouble(%_DoubleHi(w), 0);
- v = r - (z - x);
- var a = -1 / w;
- var t = %_ConstructDouble(%_DoubleHi(a), 0);
- s = 1 + t * z;
- return t + a * (s + t * v);
- }
-}
-
-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 * 1; // 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 * 1; // 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.
- if ((%_DoubleHi(x) & 0x7fffffff) <= 0x3fe921fb) {
- // |x| < pi/4, approximately. No reduction needed.
- return KernelTan(x, 0, 1);
- }
- REMPIO2(x);
- return KernelTan(y0, y1, (n & 1) ? -1 : 1);
-}
-
-// ES6 draft 09-27-13, section 20.2.2.20.
-// Math.log1p
-//
-// Method :
-// 1. Argument Reduction: find k and f such that
-// 1+x = 2^k * (1+f),
-// where sqrt(2)/2 < 1+f < sqrt(2) .
-//
-// Note. If k=0, then f=x is exact. However, if k!=0, then f
-// may not be representable exactly. In that case, a correction
-// term is need. Let u=1+x rounded. Let c = (1+x)-u, then
-// log(1+x) - log(u) ~ c/u. Thus, we proceed to compute log(u),
-// and add back the correction term c/u.
-// (Note: when x > 2**53, one can simply return log(x))
-//
-// 2. Approximation of log1p(f).
-// Let s = f/(2+f) ; based on log(1+f) = log(1+s) - log(1-s)
-// = 2s + 2/3 s**3 + 2/5 s**5 + .....,
-// = 2s + s*R
-// We use a special Reme algorithm on [0,0.1716] to generate
-// a polynomial of degree 14 to approximate R The maximum error
-// of this polynomial approximation is bounded by 2**-58.45. In
-// other words,
-// 2 4 6 8 10 12 14
-// R(z) ~ Lp1*s +Lp2*s +Lp3*s +Lp4*s +Lp5*s +Lp6*s +Lp7*s
-// (the values of Lp1 to Lp7 are listed in the program)
-// and
-// | 2 14 | -58.45
-// | Lp1*s +...+Lp7*s - R(z) | <= 2
-// | |
-// Note that 2s = f - s*f = f - hfsq + s*hfsq, where hfsq = f*f/2.
-// In order to guarantee error in log below 1ulp, we compute log
-// by
-// log1p(f) = f - (hfsq - s*(hfsq+R)).
-//
-// 3. Finally, log1p(x) = k*ln2 + log1p(f).
-// = k*ln2_hi+(f-(hfsq-(s*(hfsq+R)+k*ln2_lo)))
-// Here ln2 is split into two floating point number:
-// ln2_hi + ln2_lo,
-// where n*ln2_hi is always exact for |n| < 2000.
-//
-// Special cases:
-// log1p(x) is NaN with signal if x < -1 (including -INF) ;
-// log1p(+INF) is +INF; log1p(-1) is -INF with signal;
-// log1p(NaN) is that NaN with no signal.
-//
-// Accuracy:
-// according to an error analysis, the error is always less than
-// 1 ulp (unit in the last place).
-//
-// Constants:
-// Constants are found in fdlibm.cc. We assume the C++ compiler to
convert
-// from decimal to binary accurately enough to produce the intended
values.
-//
-// Note: Assuming log() return accurate answer, the following
-// algorithm can be used to compute log1p(x) to within a few ULP:
-//
-// u = 1+x;
-// if (u==1.0) return x ; else
-// return log(u)*(x/(u-1.0));
-//
-// See HP-15C Advanced Functions Handbook, p.193.
-//
-const LN2_HI = kMath[34];
-const LN2_LO = kMath[35];
-const TWO54 = kMath[36];
-const TWO_THIRD = kMath[37];
-macro KLOG1P(x)
-(kMath[38+x])
-endmacro
-
-function MathLog1p(x) {
- x = x * 1; // Convert to number.
- var hx = %_DoubleHi(x);
- var ax = hx & 0x7fffffff;
- var k = 1;
- var f = x;
- var hu = 1;
- var c = 0;
- var u = x;
-
- if (hx < 0x3fda827a) {
- // x < 0.41422
- if (ax >= 0x3ff00000) { // |x| >= 1
- if (x === -1) {
- return -INFINITY; // log1p(-1) = -inf
- } else {
- return NAN; // log1p(x<-1) = NaN
- }
- } else if (ax < 0x3c900000) {
- // For |x| < 2^-54 we can return x.
- return x;
- } else if (ax < 0x3e200000) {
- // For |x| < 2^-29 we can use a simple two-term Taylor series.
- return x - x * x * 0.5;
- }
-
- if ((hx > 0) || (hx <= -0x402D413D)) { // (int) 0xbfd2bec3 =
-0x402d413d
- // -.2929 < x < 0.41422
- k = 0;
- }
- }
-
- // Handle Infinity and NAN
- if (hx >= 0x7ff00000) return x;
-
- if (k !== 0) {
- if (hx < 0x43400000) {
- // x < 2^53
- u = 1 + x;
- hu = %_DoubleHi(u);
- k = (hu >> 20) - 1023;
- c = (k > 0) ? 1 - (u - x) : x - (u - 1);
- c = c / u;
- } else {
- hu = %_DoubleHi(u);
- k = (hu >> 20) - 1023;
- }
- hu = hu & 0xfffff;
- if (hu < 0x6a09e) {
- u = %_ConstructDouble(hu | 0x3ff00000, %_DoubleLo(u)); // Normalize
u.
- } else {
- ++k;
- u = %_ConstructDouble(hu | 0x3fe00000, %_DoubleLo(u)); // Normalize
u/2.
- hu = (0x00100000 - hu) >> 2;
- }
- f = u - 1;
- }
-
- var hfsq = 0.5 * f * f;
- if (hu === 0) {
- // |f| < 2^-20;
- if (f === 0) {
- if (k === 0) {
- return 0.0;
- } else {
- return k * LN2_HI + (c + k * LN2_LO);
- }
- }
- var R = hfsq * (1 - TWO_THIRD * f);
- if (k === 0) {
- return f - R;
- } else {
- return k * LN2_HI - ((R - (k * LN2_LO + c)) - f);
- }
- }
-
- var s = f / (2 + f);
- var z = s * s;
- var R = z * (KLOG1P(0) + z * (KLOG1P(1) + z *
- (KLOG1P(2) + z * (KLOG1P(3) + z *
- (KLOG1P(4) + z * (KLOG1P(5) + z * KLOG1P(6)))))));
- if (k === 0) {
- return f - (hfsq - s * (hfsq + R));
- } else {
- return k * LN2_HI - ((hfsq - (s * (hfsq + R) + (k * LN2_LO + c))) - f);
- }
-}
-
-// ES6 draft 09-27-13, section 20.2.2.14.
-// Math.expm1
-// Returns exp(x)-1, the exponential of x minus 1.
-//
-// Method
-// 1. Argument reduction:
-// Given x, find r and integer k such that
-//
-// x = k*ln2 + r, |r| <= 0.5*ln2 ~ 0.34658
-//
-// Here a correction term c will be computed to compensate
-// the error in r when rounded to a floating-point number.
-//
-// 2. Approximating expm1(r) by a special rational function on
-// the interval [0,0.34658]:
-// Since
-// r*(exp(r)+1)/(exp(r)-1) = 2+ r^2/6 - r^4/360 + ...
-// we define R1(r*r) by
-// r*(exp(r)+1)/(exp(r)-1) = 2+ r^2/6 * R1(r*r)
-// That is,
-// R1(r**2) = 6/r *((exp(r)+1)/(exp(r)-1) - 2/r)
-// = 6/r * ( 1 + 2.0*(1/(exp(r)-1) - 1/r))
-// = 1 - r^2/60 + r^4/2520 - r^6/100800 + ...
-// We use a special Remes algorithm on [0,0.347] to generate
-// a polynomial of degree 5 in r*r to approximate R1. The
-// maximum error of this polynomial approximation is bounded
-// by 2**-61. In other words,
-// R1(z) ~ 1.0 + Q1*z + Q2*z**2 + Q3*z**3 + Q4*z**4 + Q5*z**5
-// where Q1 = -1.6666666666666567384E-2,
-// Q2 = 3.9682539681370365873E-4,
-// Q3 = -9.9206344733435987357E-6,
-// Q4 = 2.5051361420808517002E-7,
-// Q5 = -6.2843505682382617102E-9;
-// (where z=r*r, and the values of Q1 to Q5 are listed below)
-// with error bounded by
-// | 5 | -61
-// | 1.0+Q1*z+...+Q5*z - R1(z) | <= 2
-// | |
-//
-// expm1(r) = exp(r)-1 is then computed by the following
-// specific way which minimize the accumulation rounding error:
-// 2 3
-// r r [ 3 - (R1 + R1*r/2) ]
-// expm1(r) = r + --- + --- * [--------------------]
-// 2 2 [ 6 - r*(3 - R1*r/2) ]
-//
-// To compensate the error in the argument reduction, we use
-// expm1(r+c) = expm1(r) + c + expm1(r)*c
-// ~ expm1(r) + c + r*c
-// Thus c+r*c will be added in as the correction terms for
-// expm1(r+c). Now rearrange the term to avoid optimization
-// screw up:
-// ( 2 2 )
-// ({ ( r [ R1 - (3 - R1*r/2) ] ) } r )
-// expm1(r+c)~r - ({r*(--- * [--------------------]-c)-c} - --- )
-// ({ ( 2 [ 6 - r*(3 - R1*r/2) ] ) } 2 )
-// ( )
-//
-// = r - E
-// 3. Scale back to obtain expm1(x):
-// From step 1, we have
-// expm1(x) = either 2^k*[expm1(r)+1] - 1
-// = or 2^k*[expm1(r) + (1-2^-k)]
-// 4. Implementation notes:
-// (A). To save one multiplication, we scale the coefficient Qi
-// to Qi*2^i, and replace z by (x^2)/2.
-// (B). To achieve maximum accuracy, we compute expm1(x) by
-// (i) if x < -56*ln2, return -1.0, (raise inexact if x!=inf)
-// (ii) if k=0, return r-E
-// (iii) if k=-1, return 0.5*(r-E)-0.5
-// (iv) if k=1 if r < -0.25, return 2*((r+0.5)- E)
-// else return 1.0+2.0*(r-E);
-// (v) if (k<-2||k>56) return 2^k(1-(E-r)) - 1 (or exp(x)-1)
-// (vi) if k <= 20, return 2^k((1-2^-k)-(E-r)), else
-// (vii) return 2^k(1-((E+2^-k)-r))
-//
-// Special cases:
-// expm1(INF) is INF, expm1(NaN) is NaN;
-// expm1(-INF) is -1, and
-// for finite argument, only expm1(0)=0 is exact.
-//
-// Accuracy:
-// according to an error analysis, the error is always less than
-// 1 ulp (unit in the last place).
-//
-// Misc. info.
-// For IEEE double
-// if x > 7.09782712893383973096e+02 then expm1(x) overflow
-//
-const KEXPM1_OVERFLOW = kMath[45];
-const INVLN2 = kMath[46];
-macro KEXPM1(x)
-(kMath[47+x])
-endmacro
-
-function MathExpm1(x) {
- x = x * 1; // Convert to number.
- var y;
- var hi;
- var lo;
- var k;
- var t;
- var c;
-
- var hx = %_DoubleHi(x);
- var xsb = hx & 0x80000000; // Sign bit of x
- var y = (xsb === 0) ? x : -x; // y = |x|
- hx &= 0x7fffffff; // High word of |x|
-
- // Filter out huge and non-finite argument
- if (hx >= 0x4043687a) { // if |x| ~=> 56 * ln2
- if (hx >= 0x40862e42) { // if |x| >= 709.78
- if (hx >= 0x7ff00000) {
- // expm1(inf) = inf; expm1(-inf) = -1; expm1(nan) = nan;
- return (x === -INFINITY) ? -1 : x;
- }
- if (x > KEXPM1_OVERFLOW) return INFINITY; // Overflow
- }
- if (xsb != 0) return -1; // x < -56 * ln2, return -1.
- }
-
- // Argument reduction
- if (hx > 0x3fd62e42) { // if |x| > 0.5 * ln2
- if (hx < 0x3ff0a2b2) { // and |x| < 1.5 * ln2
- if (xsb === 0) {
- hi = x - LN2_HI;
- lo = LN2_LO;
- k = 1;
- } else {
- hi = x + LN2_HI;
- lo = -LN2_LO;
- k = -1;
- }
- } else {
- k = (INVLN2 * x + ((xsb === 0) ? 0.5 : -0.5)) | 0;
- t = k;
- // t * ln2_hi is exact here.
- hi = x - t * LN2_HI;
- lo = t * LN2_LO;
- }
- x = hi - lo;
- c = (hi - x) - lo;
- } else if (hx < 0x3c900000) {
- // When |x| < 2^-54, we can return x.
- return x;
- } else {
- // Fall through.
- k = 0;
- }
-
- // x is now in primary range
- var hfx = 0.5 * x;
- var hxs = x * hfx;
- var r1 = 1 + hxs * (KEXPM1(0) + hxs * (KEXPM1(1) + hxs *
- (KEXPM1(2) + hxs * (KEXPM1(3) + hxs * KEXPM1(4)))));
- t = 3 - r1 * hfx;
- var e = hxs * ((r1 - t) / (6 - x * t));
- if (k === 0) { // c is 0
- return x - (x*e - hxs);
- } else {
- e = (x * (e - c) - c);
- e -= hxs;
- if (k === -1) return 0.5 * (x - e) - 0.5;
- if (k === 1) {
- if (x < -0.25) return -2 * (e - (x + 0.5));
- return 1 + 2 * (x - e);
- }
-
- if (k <= -2 || k > 56) {
- // suffice to return exp(x) + 1
- y = 1 - (e - x);
- // Add k to y's exponent
- y = %_ConstructDouble(%_DoubleHi(y) + (k << 20), %_DoubleLo(y));
- return y - 1;
- }
- if (k < 20) {
- // t = 1 - 2^k
- t = %_ConstructDouble(0x3ff00000 - (0x200000 >> k), 0);
- y = t - (e - x);
- // Add k to y's exponent
- y = %_ConstructDouble(%_DoubleHi(y) + (k << 20), %_DoubleLo(y));
- } else {
- // t = 2^-k
- t = %_ConstructDouble((0x3ff - k) << 20, 0);
- y = x - (e + t);
- y += 1;
- // Add k to y's exponent
- y = %_ConstructDouble(%_DoubleHi(y) + (k << 20), %_DoubleLo(y));
- }
- }
- return y;
-}
-
-
-// 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.
-//
-const KSINH_OVERFLOW = kMath[52];
-const TWO_M28 = 3.725290298461914e-9; // 2^-28, empty lower half
-const 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 * MathExp(ax);
- // |x| in [log(maxdouble), overflowthreshold]
- // overflowthreshold = 710.4758600739426
- if (ax <= KSINH_OVERFLOW) {
- var w = MathExp(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.
-//
-const KCOSH_OVERFLOW = kMath[52];
-
-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 = MathExp(MathAbs(x));
- return 0.5 * t + 0.5 / t;
- }
- // |x| in [22, log(maxdouble)], return half*exp(|x|)
- if (ix < 0x40862e42) return 0.5 * MathExp(MathAbs(x));
- // |x| in [log(maxdouble), overflowthreshold]
- if (MathAbs(x) <= KCOSH_OVERFLOW) {
- var w = MathExp(0.5 * MathAbs(x));
- var t = 0.5 * w;
- return t * w;
- }
- if (NUMBER_IS_NAN(x)) return x;
- // |x| > overflowthreshold.
- return INFINITY;
-}
=======================================
--- /trunk/BUILD.gn Wed Oct 8 00:05:11 2014 UTC
+++ /trunk/BUILD.gn Thu Oct 9 00:05:16 2014 UTC
@@ -182,7 +182,7 @@
"src/array.js",
"src/string.js",
"src/uri.js",
- "third_party/fdlibm/fdlibm.js",
+ "src/third_party/fdlibm/fdlibm.js",
"src/math.js",
"src/apinatives.js",
"src/date.js",
@@ -895,6 +895,8 @@
"src/unicode-inl.h",
"src/unicode.cc",
"src/unicode.h",
+ "src/unicode-decoder.cc",
+ "src/unicode-decoder.h",
"src/unique.h",
"src/uri.h",
"src/utils-inl.h",
@@ -914,8 +916,8 @@
"src/zone-inl.h",
"src/zone.cc",
"src/zone.h",
- "third_party/fdlibm/fdlibm.cc",
- "third_party/fdlibm/fdlibm.h",
+ "src/third_party/fdlibm/fdlibm.cc",
+ "src/third_party/fdlibm/fdlibm.h",
]
if (v8_target_arch == "x86") {
=======================================
--- /trunk/ChangeLog Wed Oct 8 13:44:16 2014 UTC
+++ /trunk/ChangeLog Thu Oct 9 00:05:16 2014 UTC
@@ -1,3 +1,15 @@
+2014-10-09: Version 3.30.6
+
+ Update unicode to 7.0.0 (issue 2892).
+
+ Classes: Add support for toString (issue 3330).
+
+ Don't enable WPO on Win64 and require Server 2003 / x64 for win64
+ (Chromium issue 421363).
+
+ Performance and stability improvements on all platforms.
+
+
2014-10-08: Version 3.30.5
Performance and stability improvements on all platforms.
=======================================
--- /trunk/build/standalone.gypi Fri Sep 5 00:05:05 2014 UTC
+++ /trunk/build/standalone.gypi Thu Oct 9 00:05:16 2014 UTC
@@ -313,9 +313,15 @@
},
'VCLibrarianTool': {
'AdditionalOptions': ['/ignore:4221'],
+ 'conditions': [
+ ['v8_target_arch=="x64"', {
+ 'TargetMachine': '17', # x64
+ }, {
+ 'TargetMachine': '1', # ia32
+ }],
+ ],
},
'VCLinkerTool': {
- 'MinimumRequiredVersion': '5.01', # XP.
'AdditionalDependencies': [
'ws2_32.lib',
],
@@ -340,6 +346,13 @@
'advapi32.lib',
],
}],
+ ['v8_target_arch=="x64"', {
+ 'MinimumRequiredVersion': '5.02', # Server 2003.
+ 'TargetMachine': '17', # x64
+ }, {
+ 'MinimumRequiredVersion': '5.01', # XP.
+ 'TargetMachine': '1', # ia32
+ }],
],
},
},
=======================================
--- /trunk/build/toolchain.gypi Thu Oct 2 00:05:29 2014 UTC
+++ /trunk/build/toolchain.gypi Thu Oct 9 00:05:16 2014 UTC
@@ -790,10 +790,6 @@
}, {
'RuntimeLibrary': '1', #/MTd
}],
- ['v8_target_arch=="x64"', {
- # TODO(2207): remove this option once the bug is fixed.
- 'WholeProgramOptimization': 'true',
- }],
],
},
'VCLinkerTool': {
@@ -963,10 +959,6 @@
}, {
'RuntimeLibrary': '0', #/MT
}],
- ['v8_target_arch=="x64"', {
- # TODO(2207): remove this option once the bug is fixed.
- 'WholeProgramOptimization': 'true',
- }],
],
},
'VCLinkerTool': {
=======================================
--- /trunk/include/v8.h Wed Oct 8 00:05:11 2014 UTC
+++ /trunk/include/v8.h Thu Oct 9 00:05:16 2014 UTC
@@ -5801,8 +5801,6 @@
bool top_level_;
internal::Isolate* isolate_;
- static bool active_;
-
// Disallow copying and assigning.
Locker(const Locker&);
void operator=(const Locker&);
@@ -5911,7 +5909,7 @@
static const int kJSObjectHeaderSize = 3 * kApiPointerSize;
static const int kFixedArrayHeaderSize = 2 * kApiPointerSize;
static const int kContextHeaderSize = 2 * kApiPointerSize;
- static const int kContextEmbedderDataIndex = 95;
+ static const int kContextEmbedderDataIndex = 76;
static const int kFullStringRepresentationMask = 0x07;
static const int kStringEncodingMask = 0x4;
static const int kExternalTwoByteRepresentationTag = 0x02;
=======================================
--- /trunk/src/api.cc Fri Oct 3 00:04:58 2014 UTC
+++ /trunk/src/api.cc Thu Oct 9 00:05:16 2014 UTC
@@ -53,7 +53,6 @@
#define LOG_API(isolate, expr) LOG(isolate, ApiEntryCall(expr))
#define ENTER_V8(isolate) \
- DCHECK((isolate)->IsInitialized()); \
i::VMState<v8::OTHER> __state__((isolate))
namespace v8 {
@@ -194,7 +193,6 @@
static inline bool IsExecutionTerminatingCheck(i::Isolate* isolate) {
- if (!isolate->IsInitialized()) return false;
if (isolate->has_scheduled_exception()) {
return isolate->scheduled_exception() ==
isolate->heap()->termination_exception();
@@ -2690,7 +2688,6 @@
void i::Internals::CheckInitializedImpl(v8::Isolate* external_isolate) {
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(external_isolate);
Utils::ApiCheck(isolate != NULL &&
- isolate->IsInitialized() &&
!isolate->IsDead(),
"v8::internal::Internals::CheckInitialized()",
"Isolate is not initialized or V8 has died");
@@ -5736,7 +5733,6 @@
void v8::Date::DateTimeConfigurationChangeNotification(Isolate* isolate) {
i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
- if (!i_isolate->IsInitialized()) return;
ON_BAILOUT(i_isolate, "v8::Date::DateTimeConfigurationChangeNotification()",
return);
LOG_API(i_isolate, "Date::DateTimeConfigurationChangeNotification");
@@ -6284,7 +6280,6 @@
Local<Number> v8::Number::New(Isolate* isolate, double value) {
i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
- DCHECK(internal_isolate->IsInitialized());
if (std::isnan(value)) {
// Introduce only canonical NaN value into the VM, to avoid signaling
NaNs.
value = base::OS::nan_value();
@@ -6297,7 +6292,6 @@
Local<Integer> v8::Integer::New(Isolate* isolate, int32_t value) {
i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
- DCHECK(internal_isolate->IsInitialized());
if (i::Smi::IsValid(value)) {
return
Utils::IntegerToLocal(i::Handle<i::Object>(i::Smi::FromInt(value),
internal_isolate));
@@ -6310,7 +6304,6 @@
Local<Integer> v8::Integer::NewFromUnsigned(Isolate* isolate, uint32_t
value) {
i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
- DCHECK(internal_isolate->IsInitialized());
bool fits_into_int32_t = (value & (1 << 31)) == 0;
if (fits_into_int32_t) {
return Integer::New(isolate, static_cast<int32_t>(value));
@@ -6598,7 +6591,7 @@
Isolate* Isolate::New(const Isolate::CreateParams& params) {
- i::Isolate* isolate = new i::Isolate();
+ i::Isolate* isolate = new i::Isolate(params.enable_serializer);
Isolate* v8_isolate = reinterpret_cast<Isolate*>(isolate);
if (params.entry_hook) {
isolate->set_function_entry_hook(params.entry_hook);
@@ -6609,9 +6602,6 @@
params.code_event_handler);
}
SetResourceConstraints(isolate, params.constraints);
- if (params.enable_serializer) {
- isolate->enable_serializer();
- }
// TODO(jochen): Once we got rid of Isolate::Current(), we can remove
this.
Isolate::Scope isolate_scope(v8_isolate);
if (params.entry_hook || !i::Snapshot::Initialize(isolate)) {
@@ -6701,14 +6691,6 @@
void Isolate::GetHeapStatistics(HeapStatistics* heap_statistics) {
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
- if (!isolate->IsInitialized()) {
- heap_statistics->total_heap_size_ = 0;
- heap_statistics->total_heap_size_executable_ = 0;
- heap_statistics->total_physical_size_ = 0;
- heap_statistics->used_heap_size_ = 0;
- heap_statistics->heap_size_limit_ = 0;
- return;
- }
i::Heap* heap = isolate->heap();
heap_statistics->total_heap_size_ = heap->CommittedMemory();
heap_statistics->total_heap_size_executable_ =
@@ -7004,7 +6986,6 @@
Local<Value> Debug::Call(v8::Handle<v8::Function> fun,
v8::Handle<v8::Value> data) {
i::Isolate* isolate = i::Isolate::Current();
- if (!isolate->IsInitialized()) return Local<Value>();
ON_BAILOUT(isolate, "v8::Debug::Call()", return Local<Value>());
ENTER_V8(isolate);
i::MaybeHandle<i::Object> maybe_result;
@@ -7025,7 +7006,6 @@
Local<Value> Debug::GetMirror(v8::Handle<v8::Value> obj) {
i::Isolate* isolate = i::Isolate::Current();
- if (!isolate->IsInitialized()) return Local<Value>();
ON_BAILOUT(isolate, "v8::Debug::GetMirror()", return Local<Value>());
ENTER_V8(isolate);
v8::EscapableHandleScope scope(reinterpret_cast<Isolate*>(isolate));
=======================================
--- /trunk/src/arm/debug-arm.cc Thu Sep 4 10:39:50 2014 UTC
+++ /trunk/src/arm/debug-arm.cc Thu Oct 9 00:05:16 2014 UTC
@@ -178,7 +178,11 @@
// Calling convention for IC load (from ic-arm.cc).
Register receiver = LoadDescriptor::ReceiverRegister();
Register name = LoadDescriptor::NameRegister();
- Generate_DebugBreakCallHelper(masm, receiver.bit() | name.bit(), 0);
+ RegList regs = receiver.bit() | name.bit();
+ if (FLAG_vector_ics) {
+ regs |= VectorLoadICTrampolineDescriptor::SlotRegister().bit();
+ }
+ Generate_DebugBreakCallHelper(masm, regs, 0);
}
=======================================
--- /trunk/src/arm/full-codegen-arm.cc Wed Oct 8 00:05:11 2014 UTC
+++ /trunk/src/arm/full-codegen-arm.cc Thu Oct 9 00:05:16 2014 UTC
@@ -1364,7 +1364,13 @@
Handle<Symbol>
home_object_symbol(isolate()->heap()->home_object_symbol());
__ Move(LoadDescriptor::NameRegister(), home_object_symbol);
- CallLoadIC(NOT_CONTEXTUAL, expr->HomeObjectFeedbackId());
+ if (FLAG_vector_ics) {
+ __ mov(VectorLoadICDescriptor::SlotRegister(),
+ Operand(Smi::FromInt(expr->HomeObjectFeedbackSlot())));
+ CallLoadIC(NOT_CONTEXTUAL);
+ } else {
+ CallLoadIC(NOT_CONTEXTUAL, expr->HomeObjectFeedbackId());
+ }
__ cmp(r0, Operand(isolate()->factory()->undefined_value()));
Label done;
=======================================
--- /trunk/src/arm64/debug-arm64.cc Thu Sep 4 10:39:50 2014 UTC
+++ /trunk/src/arm64/debug-arm64.cc Thu Oct 9 00:05:16 2014 UTC
@@ -238,7 +238,11 @@
// Calling convention for IC load (from ic-arm.cc).
Register receiver = LoadDescriptor::ReceiverRegister();
Register name = LoadDescriptor::NameRegister();
- Generate_DebugBreakCallHelper(masm, receiver.Bit() | name.Bit(), 0, x10);
+ RegList regs = receiver.Bit() | name.Bit();
+ if (FLAG_vector_ics) {
+ regs |= VectorLoadICTrampolineDescriptor::SlotRegister().Bit();
+ }
+ Generate_DebugBreakCallHelper(masm, regs, 0, x10);
}
=======================================
--- /trunk/src/arm64/full-codegen-arm64.cc Wed Oct 8 00:05:11 2014 UTC
+++ /trunk/src/arm64/full-codegen-arm64.cc Thu Oct 9 00:05:16 2014 UTC
@@ -1350,7 +1350,13 @@
Handle<Symbol>
home_object_symbol(isolate()->heap()->home_object_symbol());
__ Mov(LoadDescriptor::NameRegister(), Operand(home_object_symbol));
- CallLoadIC(NOT_CONTEXTUAL, expr->HomeObjectFeedbackId());
+ if (FLAG_vector_ics) {
+ __ Mov(VectorLoadICDescriptor::SlotRegister(),
+ Smi::FromInt(expr->HomeObjectFeedbackSlot()));
+ CallLoadIC(NOT_CONTEXTUAL);
+ } else {
+ CallLoadIC(NOT_CONTEXTUAL, expr->HomeObjectFeedbackId());
+ }
__ Mov(x10, Operand(isolate()->factory()->undefined_value()));
__ cmp(x0, x10);
=======================================
--- /trunk/src/ast.cc Wed Oct 8 00:05:11 2014 UTC
+++ /trunk/src/ast.cc Thu Oct 9 00:05:16 2014 UTC
@@ -1026,6 +1026,14 @@
set_dont_turbofan_reason(k##NodeType); \
add_flag(kDontSelfOptimize); \
}
+#define DONT_TURBOFAN_NODE_WITH_FEEDBACK_SLOTS(NodeType) \
+ void AstConstructionVisitor::Visit##NodeType(NodeType* node) { \
+ increase_node_count(); \
+ add_slot_node(node); \
+ set_dont_crankshaft_reason(k##NodeType); \
+ set_dont_turbofan_reason(k##NodeType); \
+ add_flag(kDontSelfOptimize); \
+ }
#define DONT_SELFOPTIMIZE_NODE(NodeType) \
void AstConstructionVisitor::Visit##NodeType(NodeType* node) { \
increase_node_count(); \
@@ -1100,7 +1108,8 @@
DONT_TURBOFAN_NODE(TryCatchStatement)
DONT_TURBOFAN_NODE(TryFinallyStatement)
DONT_TURBOFAN_NODE(ClassLiteral)
-DONT_TURBOFAN_NODE(SuperReference)
+
+DONT_TURBOFAN_NODE_WITH_FEEDBACK_SLOTS(SuperReference)
DONT_SELFOPTIMIZE_NODE(DoWhileStatement)
DONT_SELFOPTIMIZE_NODE(WhileStatement)
=======================================
--- /trunk/src/ast.h Wed Oct 8 00:05:11 2014 UTC
+++ /trunk/src/ast.h Thu Oct 9 00:05:16 2014 UTC
@@ -2536,22 +2536,26 @@
Expression* extends() const { return extends_; }
Expression* constructor() const { return constructor_; }
ZoneList<Property*>* properties() const { return properties_; }
+ int start_position() const { return position(); }
+ int end_position() const { return end_position_; }
protected:
ClassLiteral(Zone* zone, const AstRawString* name, Expression* extends,
Expression* constructor, ZoneList<Property*>* properties,
- int position, IdGen* id_gen)
- : Expression(zone, position, id_gen),
+ int start_position, int end_position, IdGen* id_gen)
+ : Expression(zone, start_position, id_gen),
raw_name_(name),
extends_(extends),
constructor_(constructor),
- properties_(properties) {}
+ properties_(properties),
+ end_position_(end_position) {}
private:
const AstRawString* raw_name_;
Expression* extends_;
Expression* constructor_;
ZoneList<Property*>* properties_;
+ int end_position_;
};
@@ -2591,13 +2595,28 @@
TypeFeedbackId HomeObjectFeedbackId() { return reuse(id()); }
+ // Type feedback information.
+ virtual int ComputeFeedbackSlotCount() { return FLAG_vector_ics ? 1 : 0;
}
+ virtual void SetFirstFeedbackSlot(int slot) {
+ homeobject_feedback_slot_ = slot;
+ }
+
+ int HomeObjectFeedbackSlot() {
+ DCHECK(!FLAG_vector_ics ||
+ homeobject_feedback_slot_ != kInvalidFeedbackSlot);
+ return homeobject_feedback_slot_;
+ }
+
protected:
SuperReference(Zone* zone, VariableProxy* this_var, int pos, IdGen*
id_gen)
- : Expression(zone, pos, id_gen), this_var_(this_var) {
+ : Expression(zone, pos, id_gen),
+ this_var_(this_var),
+ homeobject_feedback_slot_(kInvalidFeedbackSlot) {
DCHECK(this_var->is_this());
}
VariableProxy* this_var_;
+ int homeobject_feedback_slot_;
};
@@ -3535,9 +3554,10 @@
ClassLiteral* NewClassLiteral(const AstRawString* name, Expression*
extends,
Expression* constructor,
ZoneList<ObjectLiteral::Property*>*
properties,
- int position) {
- ClassLiteral* lit = new (zone_) ClassLiteral(
- zone_, name, extends, constructor, properties, position, id_gen_);
+ int start_position, int end_position) {
+ ClassLiteral* lit =
+ new (zone_) ClassLiteral(zone_, name, extends, constructor,
properties,
+ start_position, end_position, id_gen_);
VISIT_AND_RETURN(ClassLiteral, lit)
}
=======================================
--- /trunk/src/bootstrapper.cc Fri Oct 3 00:04:58 2014 UTC
+++ /trunk/src/bootstrapper.cc Thu Oct 9 00:05:16 2014 UTC
@@ -1505,12 +1505,6 @@
.ToHandleChecked();
\
native_context()->set_##var(Type::cast(*var##_native));
-#define INSTALL_NATIVE_MATH(name) \
- { \
- Handle<Object> fun = \
- ResolveBuiltinIdHolder(native_context(), "Math." #name); \
- native_context()->set_math_##name##_fun(JSFunction::cast(*fun)); \
- }
void Genesis::InstallNativeFunctions() {
HandleScope scope(isolate());
@@ -1557,26 +1551,6 @@
INSTALL_NATIVE(Symbol, "symbolIterator", iterator_symbol);
INSTALL_NATIVE(Symbol, "symbolUnscopables", unscopables_symbol);
INSTALL_NATIVE(JSFunction, "ArrayValues", array_values_iterator);
-
- INSTALL_NATIVE_MATH(abs)
- INSTALL_NATIVE_MATH(acos)
- INSTALL_NATIVE_MATH(asin)
- INSTALL_NATIVE_MATH(atan)
- INSTALL_NATIVE_MATH(atan2)
- INSTALL_NATIVE_MATH(ceil)
- INSTALL_NATIVE_MATH(cos)
- INSTALL_NATIVE_MATH(exp)
- INSTALL_NATIVE_MATH(floor)
- INSTALL_NATIVE_MATH(imul)
- INSTALL_NATIVE_MATH(log)
- INSTALL_NATIVE_MATH(max)
- INSTALL_NATIVE_MATH(min)
- INSTALL_NATIVE_MATH(pow)
- INSTALL_NATIVE_MATH(random)
- INSTALL_NATIVE_MATH(round)
- INSTALL_NATIVE_MATH(sin)
- INSTALL_NATIVE_MATH(sqrt)
- INSTALL_NATIVE_MATH(tan)
}
@@ -2590,20 +2564,24 @@
class NoTrackDoubleFieldsForSerializerScope {
public:
explicit NoTrackDoubleFieldsForSerializerScope(Isolate* isolate)
- : flag_(FLAG_track_double_fields) {
+ : flag_(FLAG_track_double_fields), enabled_(false) {
if (isolate->serializer_enabled()) {
// Disable tracking double fields because heap numbers treated as
// immutable by the serializer.
FLAG_track_double_fields = false;
+ enabled_ = true;
}
}
~NoTrackDoubleFieldsForSerializerScope() {
- FLAG_track_double_fields = flag_;
+ if (enabled_) {
+ FLAG_track_double_fields = flag_;
+ }
}
private:
bool flag_;
+ bool enabled_;
};
=======================================
--- /trunk/src/char-predicates.h Wed Jun 4 00:06:13 2014 UTC
+++ /trunk/src/char-predicates.h Thu Oct 9 00:05:16 2014 UTC
@@ -22,42 +22,40 @@
inline bool IsRegExpWord(uc32 c);
inline bool IsRegExpNewline(uc32 c);
+// ES6 draft section 11.6
+// This includes '_', '$' and '\', and ID_Start according to
+// http://www.unicode.org/reports/tr31/, which consists of categories
+// 'Lu', 'Ll', 'Lt', 'Lm', 'Lo', 'Nl', but excluding properties
+// 'Pattern_Syntax' or 'Pattern_White_Space'.
struct IdentifierStart {
- static inline bool Is(uc32 c) {
- switch (c) {
- case '$': case '_': case '\\': return true;
- default: return unibrow::Letter::Is(c);
- }
- }
+ static inline bool Is(uc32 c) { return unibrow::ID_Start::Is(c); }
};
+// ES6 draft section 11.6
+// This includes \u200c and \u200d, and ID_Continue according to
+// http://www.unicode.org/reports/tr31/, which consists of ID_Start,
+// the categories 'Mn', 'Mc', 'Nd', 'Pc', but excluding properties
+// 'Pattern_Syntax' or 'Pattern_White_Space'.
struct IdentifierPart {
static inline bool Is(uc32 c) {
- return IdentifierStart::Is(c)
- || unibrow::Number::Is(c)
- || c == 0x200C // U+200C is Zero-Width Non-Joiner.
- || c == 0x200D // U+200D is Zero-Width Joiner.
- || unibrow::CombiningMark::Is(c)
- || unibrow::ConnectorPunctuation::Is(c);
+ return unibrow::ID_Start::Is(c) || unibrow::ID_Continue::Is(c);
}
};
-// WhiteSpace according to ECMA-262 5.1, 7.2.
+// ES6 draft section 11.2
+// This includes all code points of Unicode category 'Zs'.
+// \u180e stops being one as of Unicode 6.3.0, but ES6 adheres to Unicode
5.1,
+// so it is also included.
+// Further included are \u0009, \u000b, \u0020, \u00a0, \u000c, and \ufeff.
struct WhiteSpace {
- static inline bool Is(uc32 c) {
- return c == 0x0009 || // <TAB>
- c == 0x000B || // <VT>
- c == 0x000C || // <FF>
- c == 0xFEFF || // <BOM>
- // \u0020 and \u00A0 are included in unibrow::WhiteSpace.
- unibrow::WhiteSpace::Is(c);
- }
+ static inline bool Is(uc32 c) { return unibrow::WhiteSpace::Is(c); }
};
-// WhiteSpace and LineTerminator according to ECMA-262 5.1, 7.2 and 7.3.
+// WhiteSpace and LineTerminator according to ES6 draft section 11.2 and
11.3
+// This consists of \000a, \000d, \u2028, and \u2029.
struct WhiteSpaceOrLineTerminator {
static inline bool Is(uc32 c) {
return WhiteSpace::Is(c) || unibrow::LineTerminator::Is(c);
=======================================
--- /trunk/src/code-stubs.cc Fri Oct 3 00:04:58 2014 UTC
+++ /trunk/src/code-stubs.cc Thu Oct 9 00:05:16 2014 UTC
@@ -592,6 +592,9 @@
CallInterfaceDescriptor HandlerStub::GetCallInterfaceDescriptor() {
if (kind() == Code::LOAD_IC || kind() == Code::KEYED_LOAD_IC) {
+ if (FLAG_vector_ics) {
+ return VectorLoadICDescriptor(isolate());
+ }
return LoadDescriptor(isolate());
} else {
DCHECK_EQ(Code::STORE_IC, kind());
@@ -627,14 +630,13 @@
void VectorLoadStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
InitializeVectorLoadStub(isolate(), descriptor,
-
FUNCTION_ADDR(VectorLoadIC_MissFromStubFailure));
+ FUNCTION_ADDR(LoadIC_MissFromStubFailure));
}
void VectorKeyedLoadStub::InitializeDescriptor(CodeStubDescriptor*
descriptor) {
- InitializeVectorLoadStub(
- isolate(), descriptor,
- FUNCTION_ADDR(VectorKeyedLoadIC_MissFromStubFailure));
+ InitializeVectorLoadStub(isolate(), descriptor,
+ FUNCTION_ADDR(KeyedLoadIC_MissFromStubFailure));
}
=======================================
--- /trunk/src/code-stubs.h Wed Oct 1 00:05:35 2014 UTC
+++ /trunk/src/code-stubs.h Thu Oct 9 00:05:16 2014 UTC
@@ -857,7 +857,13 @@
// TODO(mvstanton): only the receiver register is accessed. When this is
// translated to a hydrogen code stub, a new CallInterfaceDescriptor
// should be created that just uses that register for more efficient
code.
- DEFINE_CALL_INTERFACE_DESCRIPTOR(Load);
+ virtual CallInterfaceDescriptor GetCallInterfaceDescriptor() OVERRIDE {
+ if (FLAG_vector_ics) {
+ return VectorLoadICDescriptor(isolate());
+ }
+ return LoadDescriptor(isolate());
+ }
+
DEFINE_PLATFORM_CODE_STUB(FunctionPrototype, PlatformCodeStub);
};
@@ -1819,7 +1825,13 @@
explicit LoadDictionaryElementStub(Isolate* isolate)
: HydrogenCodeStub(isolate) {}
- DEFINE_CALL_INTERFACE_DESCRIPTOR(Load);
+ virtual CallInterfaceDescriptor GetCallInterfaceDescriptor() OVERRIDE {
+ if (FLAG_vector_ics) {
+ return VectorLoadICDescriptor(isolate());
+ }
+ return LoadDescriptor(isolate());
+ }
+
DEFINE_HYDROGEN_CODE_STUB(LoadDictionaryElement, HydrogenCodeStub);
};
@@ -1831,7 +1843,11 @@
virtual Code::Kind GetCodeKind() const { return Code::KEYED_LOAD_IC; }
virtual InlineCacheState GetICState() const { return GENERIC; }
+ // Since KeyedLoadGeneric stub doesn't miss (simply calls runtime), it
+ // doesn't need to use the VectorLoadICDescriptor for the case when
+ // flag --vector-ics is true.
DEFINE_CALL_INTERFACE_DESCRIPTOR(Load);
+
DEFINE_HYDROGEN_CODE_STUB(KeyedLoadGeneric, HydrogenCodeStub);
};
@@ -1845,9 +1861,7 @@
virtual Code::Kind GetCodeKind() const OVERRIDE { return Code::LOAD_IC; }
- virtual InlineCacheState GetICState() const FINAL OVERRIDE {
- return GENERIC;
- }
+ virtual InlineCacheState GetICState() const FINAL OVERRIDE { return
DEFAULT; }
virtual ExtraICState GetExtraICState() const FINAL OVERRIDE {
return static_cast<ExtraICState>(minor_key_);
@@ -1893,7 +1907,13 @@
return static_cast<ExtraICState>(sub_minor_key());
}
- DEFINE_CALL_INTERFACE_DESCRIPTOR(Load);
+ virtual CallInterfaceDescriptor GetCallInterfaceDescriptor() OVERRIDE {
+ if (FLAG_vector_ics) {
+ return VectorLoadICDescriptor(isolate());
+ }
+ return LoadDescriptor(isolate());
+ }
+
DEFINE_HYDROGEN_CODE_STUB(MegamorphicLoad, HydrogenCodeStub);
};
@@ -1907,9 +1927,7 @@
virtual Code::Kind GetCodeKind() const OVERRIDE { return Code::LOAD_IC; }
- virtual InlineCacheState GetICState() const FINAL OVERRIDE {
- return GENERIC;
- }
+ virtual InlineCacheState GetICState() const FINAL OVERRIDE { return
DEFAULT; }
virtual ExtraICState GetExtraICState() const FINAL OVERRIDE {
return static_cast<ExtraICState>(sub_minor_key());
@@ -2003,7 +2021,13 @@
class ElementsKindBits: public BitField<ElementsKind, 0, 8> {};
class IsJSArrayBits: public BitField<bool, 8, 1> {};
- DEFINE_CALL_INTERFACE_DESCRIPTOR(Load);
+ virtual CallInterfaceDescriptor GetCallInterfaceDescriptor() OVERRIDE {
+ if (FLAG_vector_ics) {
+ return VectorLoadICDescriptor(isolate());
+ }
+ return LoadDescriptor(isolate());
+ }
+
DEFINE_HYDROGEN_CODE_STUB(LoadFastElement, HydrogenCodeStub);
};
=======================================
--- /trunk/src/compiler/code-generator.cc Wed Oct 1 00:05:35 2014 UTC
+++ /trunk/src/compiler/code-generator.cc Thu Oct 9 00:05:16 2014 UTC
@@ -270,7 +270,7 @@
// by calls.)
for (size_t i = 0; i < descriptor->GetSize(); i++) {
InstructionOperand* op = instr->InputAt(frame_state_offset + 1 + i);
- CHECK(op->IsStackSlot() || op->IsImmediate());
+ CHECK(op->IsStackSlot() || op->IsDoubleStackSlot() ||
op->IsImmediate());
}
#endif
safepoints()->RecordLazyDeoptimizationIndex(deopt_state_id);
@@ -296,7 +296,15 @@
return code()->GetFrameStateDescriptor(state_id);
}
-static InstructionOperand* OperandForFrameState(
+struct OperandAndType {
+ OperandAndType(InstructionOperand* operand, MachineType type)
+ : operand_(operand), type_(type) {}
+
+ InstructionOperand* operand_;
+ MachineType type_;
+};
+
+static OperandAndType TypedOperandForFrameState(
FrameStateDescriptor* descriptor, Instruction* instr,
size_t frame_state_offset, size_t index, OutputFrameStateCombine
combine) {
DCHECK(index < descriptor->GetSize(combine));
@@ -307,7 +315,8 @@
descriptor->GetSize(OutputFrameStateCombine::Ignore());
// If the index is past the existing stack items, return the output.
if (index >= size_without_output) {
- return instr->OutputAt(index - size_without_output);
+ return OperandAndType(instr->OutputAt(index - size_without_output),
+ kMachAnyTagged);
}
break;
}
@@ -316,11 +325,13 @@
descriptor->GetSize(combine) - 1 - combine.GetOffsetToPokeAt();
if (index >= index_from_top &&
index < index_from_top + instr->OutputCount()) {
- return instr->OutputAt(index - index_from_top);
+ return OperandAndType(instr->OutputAt(index - index_from_top),
+ kMachAnyTagged);
}
break;
}
- return instr->InputAt(frame_state_offset + index);
+ return OperandAndType(instr->InputAt(frame_state_offset + index),
+ descriptor->GetType(index));
}
@@ -356,9 +367,9 @@
frame_state_offset += descriptor->outer_state()->GetTotalSize();
for (size_t i = 0; i < descriptor->GetSize(state_combine); i++) {
- InstructionOperand* op = OperandForFrameState(
+ OperandAndType op = TypedOperandForFrameState(
descriptor, instr, frame_state_offset, i, state_combine);
- AddTranslationForOperand(translation, instr, op);
+ AddTranslationForOperand(translation, instr, op.operand_, op.type_);
}
}
@@ -387,15 +398,36 @@
void CodeGenerator::AddTranslationForOperand(Translation* translation,
Instruction* instr,
- InstructionOperand* op) {
+ InstructionOperand* op,
+ MachineType type) {
if (op->IsStackSlot()) {
- translation->StoreStackSlot(op->index());
+ if (type == kMachBool || type == kMachInt32 || type == kMachInt8 ||
+ type == kMachInt16) {
+ translation->StoreInt32StackSlot(op->index());
+ } else if (type == kMachUint32) {
+ translation->StoreUint32StackSlot(op->index());
+ } else if ((type & kRepMask) == kRepTagged) {
+ translation->StoreStackSlot(op->index());
+ } else {
+ CHECK(false);
+ }
} else if (op->IsDoubleStackSlot()) {
+ DCHECK((type & (kRepFloat32 | kRepFloat64)) != 0);
translation->StoreDoubleStackSlot(op->index());
} else if (op->IsRegister()) {
InstructionOperandConverter converter(this, instr);
- translation->StoreRegister(converter.ToRegister(op));
+ if (type == kMachBool || type == kMachInt32 || type == kMachInt8 ||
+ type == kMachInt16) {
+ translation->StoreInt32Register(converter.ToRegister(op));
+ } else if (type == kMachUint32) {
+ translation->StoreUint32Register(converter.ToRegister(op));
+ } else if ((type & kRepMask) == kRepTagged) {
+ translation->StoreRegister(converter.ToRegister(op));
+ } else {
+ CHECK(false);
+ }
} else if (op->IsDoubleRegister()) {
+ DCHECK((type & (kRepFloat32 | kRepFloat64)) != 0);
InstructionOperandConverter converter(this, instr);
translation->StoreDoubleRegister(converter.ToDoubleRegister(op));
} else if (op->IsImmediate()) {
@@ -404,22 +436,25 @@
Handle<Object> constant_object;
switch (constant.type()) {
case Constant::kInt32:
+ DCHECK(type == kMachInt32 || type == kMachUint32);
constant_object =
isolate()->factory()->NewNumberFromInt(constant.ToInt32());
break;
case Constant::kFloat64:
+ DCHECK(type == kMachFloat64 || type == kMachAnyTagged);
constant_object =
isolate()->factory()->NewNumber(constant.ToFloat64());
break;
case Constant::kHeapObject:
+ DCHECK((type & kRepMask) == kRepTagged);
constant_object = constant.ToHeapObject();
break;
default:
- UNREACHABLE();
+ CHECK(false);
}
int literal_id = DefineDeoptimizationLiteral(constant_object);
translation->StoreLiteral(literal_id);
} else {
- UNREACHABLE();
+ CHECK(false);
}
}
=======================================
--- /trunk/src/compiler/code-generator.h Wed Oct 1 00:05:35 2014 UTC
+++ /trunk/src/compiler/code-generator.h Thu Oct 9 00:05:16 2014 UTC
@@ -96,7 +96,7 @@
Translation* translation, size_t frame_state_offset,
OutputFrameStateCombine state_combine);
void AddTranslationForOperand(Translation* translation, Instruction*
instr,
- InstructionOperand* op);
+ InstructionOperand* op, MachineType type);
void AddNopForSmiCodeInlining();
void EnsureSpaceForLazyDeopt();
void MarkLazyDeoptSite();
=======================================
--- /trunk/src/compiler/ia32/code-generator-ia32.cc Fri Oct 3 00:04:58
2014 UTC
+++ /trunk/src/compiler/ia32/code-generator-ia32.cc Thu Oct 9 00:05:16
2014 UTC
@@ -990,7 +990,7 @@
__ movaps(xmm0, src);
__ movaps(src, dst);
__ movaps(dst, xmm0);
- } else if (source->IsDoubleRegister() && source->IsDoubleStackSlot()) {
+ } else if (source->IsDoubleRegister() &&
destination->IsDoubleStackSlot()) {
// XMM register-memory swap. We rely on having xmm0
// available as a fixed scratch register.
XMMRegister reg = g.ToDoubleRegister(source);
=======================================
--- /trunk/src/compiler/instruction-selector.cc Wed Oct 8 00:05:11 2014 UTC
+++ /trunk/src/compiler/instruction-selector.cc Thu Oct 9 00:05:16 2014 UTC
@@ -438,6 +438,126 @@
break;
}
}
+
+
+MachineType InstructionSelector::GetMachineType(Node* node) {
+ DCHECK_NOT_NULL(schedule()->block(node)); // should only use scheduled
nodes.
+ switch (node->opcode()) {
+ case IrOpcode::kStart:
+ case IrOpcode::kLoop:
+ case IrOpcode::kEnd:
+ case IrOpcode::kBranch:
+ case IrOpcode::kIfTrue:
+ case IrOpcode::kIfFalse:
+ case IrOpcode::kEffectPhi:
+ case IrOpcode::kMerge:
+ // No code needed for these graph artifacts.
+ return kMachNone;
+ case IrOpcode::kFinish:
+ return kMachAnyTagged;
+ case IrOpcode::kParameter:
+ return linkage()->GetParameterType(OpParameter<int>(node));
+ case IrOpcode::kPhi:
+ return OpParameter<MachineType>(node);
+ case IrOpcode::kProjection:
+ // TODO(jarin) Really project from outputs.
+ return kMachAnyTagged;
+ case IrOpcode::kInt32Constant:
+ return kMachInt32;
+ case IrOpcode::kInt64Constant:
+ return kMachInt64;
+ case IrOpcode::kExternalConstant:
+ return kMachPtr;
+ case IrOpcode::kFloat64Constant:
+ return kMachFloat64;
+ case IrOpcode::kHeapConstant:
+ case IrOpcode::kNumberConstant:
+ return kMachAnyTagged;
+ case IrOpcode::kCall:
+ return kMachAnyTagged;
+ case IrOpcode::kFrameState:
+ case IrOpcode::kStateValues:
+ return kMachNone;
+ case IrOpcode::kLoad:
+ return OpParameter<LoadRepresentation>(node);
+ case IrOpcode::kStore:
+ return kMachNone;
+ case IrOpcode::kWord32And:
+ case IrOpcode::kWord32Or:
+ case IrOpcode::kWord32Xor:
+ case IrOpcode::kWord32Shl:
+ case IrOpcode::kWord32Shr:
+ case IrOpcode::kWord32Sar:
+ case IrOpcode::kWord32Ror:
+ return kMachInt32;
+ case IrOpcode::kWord32Equal:
+ return kMachBool;
+ case IrOpcode::kWord64And:
+ case IrOpcode::kWord64Or:
+ case IrOpcode::kWord64Xor:
+ case IrOpcode::kWord64Shl:
+ case IrOpcode::kWord64Shr:
+ case IrOpcode::kWord64Sar:
+ case IrOpcode::kWord64Ror:
+ return kMachInt64;
+ case IrOpcode::kWord64Equal:
+ return kMachBool;
+ case IrOpcode::kInt32Add:
+ case IrOpcode::kInt32AddWithOverflow:
+ case IrOpcode::kInt32Sub:
+ case IrOpcode::kInt32SubWithOverflow:
+ case IrOpcode::kInt32Mul:
+ case IrOpcode::kInt32Div:
+ case IrOpcode::kInt32Mod:
+ return kMachInt32;
+ case IrOpcode::kInt32LessThan:
+ case IrOpcode::kInt32LessThanOrEqual:
+ case IrOpcode::kUint32LessThan:
+ case IrOpcode::kUint32LessThanOrEqual:
+ return kMachBool;
+ case IrOpcode::kInt64Add:
+ case IrOpcode::kInt64Sub:
+ case IrOpcode::kInt64Mul:
+ case IrOpcode::kInt64Div:
+ case IrOpcode::kInt64Mod:
+ return kMachInt64;
+ case IrOpcode::kInt64LessThan:
+ case IrOpcode::kInt64LessThanOrEqual:
+ return kMachBool;
+ case IrOpcode::kChangeFloat32ToFloat64:
+ case IrOpcode::kChangeInt32ToFloat64:
+ case IrOpcode::kChangeUint32ToFloat64:
+ return kMachFloat64;
+ case IrOpcode::kChangeFloat64ToInt32:
+ return kMachInt32;
+ case IrOpcode::kChangeFloat64ToUint32:
+ return kMachUint32;
+ case IrOpcode::kChangeInt32ToInt64:
+ return kMachInt64;
+ case IrOpcode::kChangeUint32ToUint64:
+ return kMachUint64;
+ case IrOpcode::kTruncateFloat64ToFloat32:
+ return kMachFloat32;
+ case IrOpcode::kTruncateFloat64ToInt32:
+ case IrOpcode::kTruncateInt64ToInt32:
+ return kMachInt32;
+ case IrOpcode::kFloat64Add:
+ case IrOpcode::kFloat64Sub:
+ case IrOpcode::kFloat64Mul:
+ case IrOpcode::kFloat64Div:
+ case IrOpcode::kFloat64Mod:
+ case IrOpcode::kFloat64Sqrt:
+ return kMachFloat64;
+ case IrOpcode::kFloat64Equal:
+ case IrOpcode::kFloat64LessThan:
+ case IrOpcode::kFloat64LessThanOrEqual:
+ return kMachBool;
+ default:
+ V8_Fatal(__FILE__, __LINE__, "Unexpected operator #%d:%s @ node #%d",
+ node->opcode(), node->op()->mnemonic(), node->id());
+ }
+ return kMachNone;
+}
void InstructionSelector::VisitNode(Node* node) {
@@ -1008,6 +1128,17 @@
void InstructionSelector::VisitThrow(Node* value) {
UNIMPLEMENTED(); // TODO(titzer)
}
+
+
+void InstructionSelector::FillTypeVectorFromStateValues(
+ ZoneVector<MachineType>* types, Node* state_values) {
+ DCHECK(state_values->opcode() == IrOpcode::kStateValues);
+ int count = OpParameter<int>(state_values);
+ types->reserve(static_cast<size_t>(count));
+ for (int i = 0; i < count; i++) {
+ types->push_back(GetMachineType(state_values->InputAt(i)));
+ }
+}
FrameStateDescriptor* InstructionSelector::GetFrameStateDescriptor(
@@ -1015,6 +1146,7 @@
DCHECK(state->opcode() == IrOpcode::kFrameState);
DCHECK_EQ(5, state->InputCount());
FrameStateCallInfo state_info = OpParameter<FrameStateCallInfo>(state);
+
int parameters = OpParameter<int>(state->InputAt(0));
int locals = OpParameter<int>(state->InputAt(1));
int stack = OpParameter<int>(state->InputAt(2));
@@ -1025,8 +1157,8 @@
outer_state = GetFrameStateDescriptor(outer_node);
}
- return new (instruction_zone())
- FrameStateDescriptor(state_info, parameters, locals, stack,
outer_state);
+ return new (instruction_zone()) FrameStateDescriptor(
+ instruction_zone(), state_info, parameters, locals, stack,
outer_state);
}
@@ -1066,19 +1198,31 @@
DCHECK_EQ(static_cast<int>(descriptor->locals_count()),
locals->InputCount());
DCHECK_EQ(static_cast<int>(descriptor->stack_count()),
stack->InputCount());
+ ZoneVector<MachineType> types(instruction_zone());
+ types.reserve(descriptor->GetSize());
+
OperandGenerator g(this);
+ size_t value_index = 0;
for (int i = 0; i < static_cast<int>(descriptor->parameters_count());
i++) {
- inputs->push_back(UseOrImmediate(&g, parameters->InputAt(i)));
+ Node* input_node = parameters->InputAt(i);
+ inputs->push_back(UseOrImmediate(&g, input_node));
+ descriptor->SetType(value_index++, GetMachineType(input_node));
}
if (descriptor->HasContext()) {
inputs->push_back(UseOrImmediate(&g, context));
+ descriptor->SetType(value_index++, kMachAnyTagged);
}
for (int i = 0; i < static_cast<int>(descriptor->locals_count()); i++) {
- inputs->push_back(UseOrImmediate(&g, locals->InputAt(i)));
+ Node* input_node = locals->InputAt(i);
+ inputs->push_back(UseOrImmediate(&g, input_node));
+ descriptor->SetType(value_index++, GetMachineType(input_node));
}
for (int i = 0; i < static_cast<int>(descriptor->stack_count()); i++) {
- inputs->push_back(UseOrImmediate(&g, stack->InputAt(i)));
+ Node* input_node = stack->InputAt(i);
+ inputs->push_back(UseOrImmediate(&g, input_node));
+ descriptor->SetType(value_index++, GetMachineType(input_node));
}
+ DCHECK(value_index == descriptor->GetSize());
}
=======================================
--- /trunk/src/compiler/instruction-selector.h Fri Sep 26 00:05:23 2014 UTC
+++ /trunk/src/compiler/instruction-selector.h Thu Oct 9 00:05:16 2014 UTC
@@ -145,8 +145,11 @@
bool call_address_immediate);
FrameStateDescriptor* GetFrameStateDescriptor(Node* node);
+ void FillTypeVectorFromStateValues(ZoneVector<MachineType>* parameters,
+ Node* state_values);
void AddFrameStateInputs(Node* state, InstructionOperandVector* inputs,
FrameStateDescriptor* descriptor);
+ MachineType GetMachineType(Node* node);
//
===========================================================================
// ============= Architecture-specific graph covering methods.
===============
=======================================
--- /trunk/src/compiler/instruction.cc Wed Oct 8 00:05:11 2014 UTC
+++ /trunk/src/compiler/instruction.cc Thu Oct 9 00:05:16 2014 UTC
@@ -443,6 +443,78 @@
int InstructionSequence::GetFrameStateDescriptorCount() {
return static_cast<int>(deoptimization_entries_.size());
}
+
+
+FrameStateDescriptor::FrameStateDescriptor(
+ Zone* zone, const FrameStateCallInfo& state_info, size_t
parameters_count,
+ size_t locals_count, size_t stack_count, FrameStateDescriptor*
outer_state)
+ : type_(state_info.type()),
+ bailout_id_(state_info.bailout_id()),
+ frame_state_combine_(state_info.state_combine()),
+ parameters_count_(parameters_count),
+ locals_count_(locals_count),
+ stack_count_(stack_count),
+ types_(zone),
+ outer_state_(outer_state),
+ jsfunction_(state_info.jsfunction()) {
+ types_.resize(GetSize(), kMachNone);
+}
+
+size_t FrameStateDescriptor::GetSize(OutputFrameStateCombine combine)
const {
+ size_t size = parameters_count() + locals_count() + stack_count() +
+ (HasContext() ? 1 : 0);
+ switch (combine.kind()) {
+ case OutputFrameStateCombine::kPushOutput:
+ size += combine.GetPushCount();
+ break;
+ case OutputFrameStateCombine::kPokeAt:
+ break;
+ }
+ return size;
+}
+
+
+size_t FrameStateDescriptor::GetTotalSize() const {
+ size_t total_size = 0;
+ for (const FrameStateDescriptor* iter = this; iter != NULL;
+ iter = iter->outer_state_) {
+ total_size += iter->GetSize();
+ }
+ return total_size;
+}
+
+
+size_t FrameStateDescriptor::GetFrameCount() const {
+ size_t count = 0;
+ for (const FrameStateDescriptor* iter = this; iter != NULL;
+ iter = iter->outer_state_) {
+ ++count;
+ }
+ return count;
+}
+
+
+size_t FrameStateDescriptor::GetJSFrameCount() const {
+ size_t count = 0;
+ for (const FrameStateDescriptor* iter = this; iter != NULL;
+ iter = iter->outer_state_) {
+ if (iter->type_ == JS_FRAME) {
+ ++count;
+ }
+ }
+ return count;
+}
+
+
+MachineType FrameStateDescriptor::GetType(size_t index) const {
+ return types_[index];
+}
+
+
+void FrameStateDescriptor::SetType(size_t index, MachineType type) {
+ DCHECK(index < GetSize());
+ types_[index] = type;
+}
std::ostream& operator<<(std::ostream& os, const InstructionSequence&
code) {
=======================================
--- /trunk/src/compiler/instruction.h Wed Oct 8 00:05:11 2014 UTC
+++ /trunk/src/compiler/instruction.h Thu Oct 9 00:05:16 2014 UTC
@@ -711,18 +711,10 @@
class FrameStateDescriptor : public ZoneObject {
public:
- FrameStateDescriptor(const FrameStateCallInfo& state_info,
+ FrameStateDescriptor(Zone* zone, const FrameStateCallInfo& state_info,
size_t parameters_count, size_t locals_count,
size_t stack_count,
- FrameStateDescriptor* outer_state = NULL)
- : type_(state_info.type()),
- bailout_id_(state_info.bailout_id()),
- frame_state_combine_(state_info.state_combine()),
- parameters_count_(parameters_count),
- locals_count_(locals_count),
- stack_count_(stack_count),
- outer_state_(outer_state),
- jsfunction_(state_info.jsfunction()) {}
+ FrameStateDescriptor* outer_state = NULL);
FrameStateType type() const { return type_; }
BailoutId bailout_id() const { return bailout_id_; }
@@ -732,51 +724,16 @@
size_t stack_count() const { return stack_count_; }
FrameStateDescriptor* outer_state() const { return outer_state_; }
MaybeHandle<JSFunction> jsfunction() const { return jsfunction_; }
+ bool HasContext() const { return type_ == JS_FRAME; }
size_t GetSize(OutputFrameStateCombine combine =
- OutputFrameStateCombine::Ignore()) const {
- size_t size = parameters_count_ + locals_count_ + stack_count_ +
- (HasContext() ? 1 : 0);
- switch (combine.kind()) {
- case OutputFrameStateCombine::kPushOutput:
- size += combine.GetPushCount();
- break;
- case OutputFrameStateCombine::kPokeAt:
- break;
- }
- return size;
- }
+ OutputFrameStateCombine::Ignore()) const;
+ size_t GetTotalSize() const;
+ size_t GetFrameCount() const;
+ size_t GetJSFrameCount() const;
- size_t GetTotalSize() const {
- size_t total_size = 0;
- for (const FrameStateDescriptor* iter = this; iter != NULL;
- iter = iter->outer_state_) {
- total_size += iter->GetSize();
- }
- return total_size;
- }
-
- size_t GetFrameCount() const {
- size_t count = 0;
- for (const FrameStateDescriptor* iter = this; iter != NULL;
- iter = iter->outer_state_) {
- ++count;
- }
- return count;
- }
-
- size_t GetJSFrameCount() const {
- size_t count = 0;
- for (const FrameStateDescriptor* iter = this; iter != NULL;
- iter = iter->outer_state_) {
- if (iter->type_ == JS_FRAME) {
- ++count;
- }
- }
- return count;
- }
-
- bool HasContext() const { return type_ == JS_FRAME; }
+ MachineType GetType(size_t index) const;
+ void SetType(size_t index, MachineType type);
private:
FrameStateType type_;
@@ -785,6 +742,7 @@
size_t parameters_count_;
size_t locals_count_;
size_t stack_count_;
+ ZoneVector<MachineType> types_;
FrameStateDescriptor* outer_state_;
MaybeHandle<JSFunction> jsfunction_;
};
=======================================
--- /trunk/src/compiler/js-typed-lowering.cc Wed Oct 8 00:05:11 2014 UTC
+++ /trunk/src/compiler/js-typed-lowering.cc Thu Oct 9 00:05:16 2014 UTC
@@ -534,7 +534,6 @@
Type* base_type = NodeProperties::GetBounds(base).upper;
// TODO(mstarzinger): This lowering is not correct if:
// a) The typed array or it's buffer is neutered.
- // b) The index is out of bounds.
if (base_type->IsConstant() && key_type->Is(Type::Integral32()) &&
base_type->AsConstant()->Value()->IsJSTypedArray()) {
// JSLoadProperty(typed-array, int32)
=======================================
***Additional files exist in this changeset.***
--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
---
You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.