From a7d38f7a4184eb4917559f26b2b15062d00fc6f1 Mon Sep 17 00:00:00 2001 From: "yangguo@chromium.org" Date: Fri, 22 Nov 2013 08:25:50 +0000 Subject: [PATCH] Reland: Embed trigonometric lookup table. R=danno@chromium.org Review URL: https://codereview.chromium.org/78263005 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@17988 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/bootstrapper.cc | 39 ++++++ src/math.js | 178 +++++++++++----------------- src/runtime.cc | 29 ----- src/runtime.h | 1 - src/trig-table.h | 61 ++++++++++ test/cctest/test-weaktypedarrays.cc | 8 +- tools/generate-trig-table.py | 84 +++++++++++++ tools/gyp/v8.gyp | 31 +++++ 8 files changed, 287 insertions(+), 144 deletions(-) create mode 100644 src/trig-table.h create mode 100644 tools/generate-trig-table.py diff --git a/src/bootstrapper.cc b/src/bootstrapper.cc index bc52fa858f..322df912f9 100644 --- a/src/bootstrapper.cc +++ b/src/bootstrapper.cc @@ -40,6 +40,7 @@ #include "objects-visiting.h" #include "platform.h" #include "snapshot.h" +#include "trig-table.h" #include "extensions/externalize-string-extension.h" #include "extensions/gc-extension.h" #include "extensions/statistics-extension.h" @@ -2635,6 +2636,44 @@ Genesis::Genesis(Isolate* isolate, InitializeExperimentalGlobal(); if (!InstallExperimentalNatives()) return; + if (!Serializer::enabled()) { + Handle builtins(native_context()->builtins()); + // Initialize trigonometric lookup tables and constants. + // The snapshot cannot contain typed arrays, and we don't need it to. + const int table_num_bytes = TrigonometricLookupTable::table_num_bytes(); + v8::Local sin_buffer = v8::ArrayBuffer::New( + TrigonometricLookupTable::sin_table(), table_num_bytes); + v8::Local cos_buffer = v8::ArrayBuffer::New( + TrigonometricLookupTable::cos_x_interval_table(), table_num_bytes); + v8::Local sin_table = v8::Float64Array::New( + sin_buffer, 0, TrigonometricLookupTable::table_size()); + v8::Local cos_table = v8::Float64Array::New( + cos_buffer, 0, TrigonometricLookupTable::table_size()); + + ForceSetProperty(builtins, + factory()->InternalizeOneByteString( + STATIC_ASCII_VECTOR("kSinTable")), + Utils::OpenHandle(*sin_table), + NONE); + ForceSetProperty(builtins, + factory()->InternalizeOneByteString( + STATIC_ASCII_VECTOR("kCosXIntervalTable")), + Utils::OpenHandle(*cos_table), + NONE); + ForceSetProperty(builtins, + factory()->InternalizeOneByteString( + STATIC_ASCII_VECTOR("kSamples")), + factory()->NewHeapNumber( + TrigonometricLookupTable::samples()), + NONE); + ForceSetProperty(builtins, + factory()->InternalizeOneByteString( + STATIC_ASCII_VECTOR("kIndexConvert")), + factory()->NewHeapNumber( + TrigonometricLookupTable::samples_over_pi_half()), + NONE); + } + // Initially seed the per-context random number generator // using the per-isolate random number generator. uint32_t* state = reinterpret_cast( diff --git a/src/math.js b/src/math.js index 2df0ec2a5f..c163d9a46f 100644 --- a/src/math.js +++ b/src/math.js @@ -79,7 +79,8 @@ function MathCeil(x) { // ECMA 262 - 15.8.2.7 function MathCos(x) { - return MathCosImpl(x); + x = MathAbs(x); // Convert to number and get rid of -0. + return TrigonometricInterpolation(x, 1); } // ECMA 262 - 15.8.2.8 @@ -179,7 +180,9 @@ function MathRound(x) { // ECMA 262 - 15.8.2.16 function MathSin(x) { - return MathSinImpl(x); + x = x * 1; // Convert to number and deal with -0. + if (%_IsMinusZero(x)) return x; + return TrigonometricInterpolation(x, 0); } // ECMA 262 - 15.8.2.17 @@ -189,7 +192,7 @@ function MathSqrt(x) { // ECMA 262 - 15.8.2.18 function MathTan(x) { - return MathSinImpl(x) / MathCosImpl(x); + return MathSin(x) / MathCos(x); } // Non-standard extension. @@ -198,119 +201,73 @@ function MathImul(x, y) { } -var MathSinImpl = function(x) { - InitTrigonometricFunctions(); - return MathSinImpl(x); -} +var kInversePiHalf = 0.636619772367581343; // 2 / pi +var kInversePiHalfS26 = 9.48637384723993156e-9; // 2 / pi / (2^26) +var kS26 = 1 << 26; +var kTwoStepThreshold = 1 << 27; +// pi / 2 rounded up +var kPiHalf = 1.570796326794896780; // 0x192d4454fb21f93f +// We use two parts for pi/2 to emulate a higher precision. +// pi_half_1 only has 26 significant bits for mantissa. +// Note that pi_half > pi_half_1 + pi_half_2 +var kPiHalf1 = 1.570796325802803040; // 0x00000054fb21f93f +var kPiHalf2 = 9.920935796805404252e-10; // 0x3326a611460b113e +var kSamples; // Initialized to a number during genesis. +var kIndexConvert; // Initialized to kSamples / (pi/2) during genesis. +var kSinTable; // Initialized to a Float64Array during genesis. +var kCosXIntervalTable; // Initialized to a Float64Array during genesis. -var MathCosImpl = function(x) { - InitTrigonometricFunctions(); - return MathCosImpl(x); -} - - -var InitTrigonometricFunctions; - - -// Define constants and interpolation functions. -// Also define the initialization function that populates the lookup table -// and then wires up the function definitions. -function SetupTrigonometricFunctions() { - var samples = 1800; // Table size. Do not change arbitrarily. - var inverse_pi_half = 0.636619772367581343; // 2 / pi - var inverse_pi_half_s_26 = 9.48637384723993156e-9; // 2 / pi / (2^26) - var s_26 = 1 << 26; - var two_step_threshold = 1 << 27; - var index_convert = 1145.915590261646418; // samples / (pi / 2) - // pi / 2 rounded up - var pi_half = 1.570796326794896780; // 0x192d4454fb21f93f - // We use two parts for pi/2 to emulate a higher precision. - // pi_half_1 only has 26 significant bits for mantissa. - // Note that pi_half > pi_half_1 + pi_half_2 - var pi_half_1 = 1.570796325802803040; // 0x00000054fb21f93f - var pi_half_2 = 9.920935796805404252e-10; // 0x3326a611460b113e - var table_sin; - var table_cos_interval; - - // This implements sine using the following algorithm. - // 1) Multiplication takes care of to-number conversion. - // 2) Reduce x to the first quadrant [0, pi/2]. - // Conveniently enough, in case of +/-Infinity, we get NaN. - // Note that we try to use only 26 instead of 52 significant bits for - // mantissa to avoid rounding errors when multiplying. For very large - // input we therefore have additional steps. - // 3) Replace x by (pi/2-x) if x was in the 2nd or 4th quadrant. - // 4) Do a table lookup for the closest samples to the left and right of x. - // 5) Find the derivatives at those sampling points by table lookup: - // dsin(x)/dx = cos(x) = sin(pi/2-x) for x in [0, pi/2]. - // 6) Use cubic spline interpolation to approximate sin(x). - // 7) Negate the result if x was in the 3rd or 4th quadrant. - // 8) Get rid of -0 by adding 0. - var Interpolation = function(x, phase) { - if (x < 0 || x > pi_half) { - var multiple; - while (x < -two_step_threshold || x > two_step_threshold) { - // Let's assume this loop does not terminate. - // All numbers x in each loop forms a set S. - // (1) abs(x) > 2^27 for all x in S. - // (2) abs(multiple) != 0 since (2^27 * inverse_pi_half_s26) > 1 - // (3) multiple is rounded down in 2^26 steps, so the rounding error is - // at most max(ulp, 2^26). - // (4) so for x > 2^27, we subtract at most (1+pi/4)x and at least - // (1-pi/4)x - // (5) The subtraction results in x' so that abs(x') <= abs(x)*pi/4. - // Note that this difference cannot be simply rounded off. - // Set S cannot exist since (5) violates (1). Loop must terminate. - multiple = MathFloor(x * inverse_pi_half_s_26) * s_26; - x = x - multiple * pi_half_1 - multiple * pi_half_2; - } - multiple = MathFloor(x * inverse_pi_half); - x = x - multiple * pi_half_1 - multiple * pi_half_2; - phase += multiple; +// This implements sine using the following algorithm. +// 1) Multiplication takes care of to-number conversion. +// 2) Reduce x to the first quadrant [0, pi/2]. +// Conveniently enough, in case of +/-Infinity, we get NaN. +// Note that we try to use only 26 instead of 52 significant bits for +// mantissa to avoid rounding errors when multiplying. For very large +// input we therefore have additional steps. +// 3) Replace x by (pi/2-x) if x was in the 2nd or 4th quadrant. +// 4) Do a table lookup for the closest samples to the left and right of x. +// 5) Find the derivatives at those sampling points by table lookup: +// dsin(x)/dx = cos(x) = sin(pi/2-x) for x in [0, pi/2]. +// 6) Use cubic spline interpolation to approximate sin(x). +// 7) Negate the result if x was in the 3rd or 4th quadrant. +// 8) Get rid of -0 by adding 0. +function TrigonometricInterpolation(x, phase) { + if (x < 0 || x > kPiHalf) { + var multiple; + while (x < -kTwoStepThreshold || x > kTwoStepThreshold) { + // Let's assume this loop does not terminate. + // All numbers x in each loop forms a set S. + // (1) abs(x) > 2^27 for all x in S. + // (2) abs(multiple) != 0 since (2^27 * inverse_pi_half_s26) > 1 + // (3) multiple is rounded down in 2^26 steps, so the rounding error is + // at most max(ulp, 2^26). + // (4) so for x > 2^27, we subtract at most (1+pi/4)x and at least + // (1-pi/4)x + // (5) The subtraction results in x' so that abs(x') <= abs(x)*pi/4. + // Note that this difference cannot be simply rounded off. + // Set S cannot exist since (5) violates (1). Loop must terminate. + multiple = MathFloor(x * kInversePiHalfS26) * kS26; + x = x - multiple * kPiHalf1 - multiple * kPiHalf2; } - var double_index = x * index_convert; - if (phase & 1) double_index = samples - double_index; - var index = double_index | 0; - var t1 = double_index - index; - var t2 = 1 - t1; - var y1 = table_sin[index]; - var y2 = table_sin[index + 1]; - var dy = y2 - y1; - return (t2 * y1 + t1 * y2 + - t1 * t2 * ((table_cos_interval[index] - dy) * t2 + - (dy - table_cos_interval[index + 1]) * t1)) - * (1 - (phase & 2)) + 0; - } - - var MathSinInterpolation = function(x) { - x = x * 1; // Convert to number and deal with -0. - if (%_IsMinusZero(x)) return x; - return Interpolation(x, 0); - } - - // Cosine is sine with a phase offset. - var MathCosInterpolation = function(x) { - x = MathAbs(x); // Convert to number and get rid of -0. - return Interpolation(x, 1); - }; - - %SetInlineBuiltinFlag(Interpolation); - %SetInlineBuiltinFlag(MathSinInterpolation); - %SetInlineBuiltinFlag(MathCosInterpolation); - - InitTrigonometricFunctions = function() { - table_sin = new global.Float64Array(samples + 2); - table_cos_interval = new global.Float64Array(samples + 2); - %PopulateTrigonometricTable(table_sin, table_cos_interval, samples); - MathSinImpl = MathSinInterpolation; - MathCosImpl = MathCosInterpolation; + multiple = MathFloor(x * kInversePiHalf); + x = x - multiple * kPiHalf1 - multiple * kPiHalf2; + phase += multiple; } + var double_index = x * kIndexConvert; + if (phase & 1) double_index = kSamples - double_index; + var index = double_index | 0; + var t1 = double_index - index; + var t2 = 1 - t1; + var y1 = kSinTable[index]; + var y2 = kSinTable[index + 1]; + var dy = y2 - y1; + return (t2 * y1 + t1 * y2 + + t1 * t2 * ((kCosXIntervalTable[index] - dy) * t2 + + (dy - kCosXIntervalTable[index + 1]) * t1)) + * (1 - (phase & 2)) + 0; } -SetupTrigonometricFunctions(); - - // ------------------------------------------------------------------- function SetUpMath() { @@ -387,6 +344,7 @@ function SetUpMath() { %SetInlineBuiltinFlag(MathSin); %SetInlineBuiltinFlag(MathCos); %SetInlineBuiltinFlag(MathTan); + %SetInlineBuiltinFlag(TrigonometricInterpolation); } SetUpMath(); diff --git a/src/runtime.cc b/src/runtime.cc index f546629df5..c11a00528d 100644 --- a/src/runtime.cc +++ b/src/runtime.cc @@ -7848,35 +7848,6 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_tan) { } -RUNTIME_FUNCTION(MaybeObject*, Runtime_PopulateTrigonometricTable) { - HandleScope scope(isolate); - ASSERT(args.length() == 3); - CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, sin_table, 0); - CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, cos_table, 1); - CONVERT_SMI_ARG_CHECKED(samples, 2); - RUNTIME_ASSERT(sin_table->type() == kExternalDoubleArray); - RUNTIME_ASSERT(cos_table->type() == kExternalDoubleArray); - double* sin_buffer = reinterpret_cast( - JSArrayBuffer::cast(sin_table->buffer())->backing_store()); - double* cos_buffer = reinterpret_cast( - JSArrayBuffer::cast(cos_table->buffer())->backing_store()); - - static const double pi_half = 3.1415926535897932 / 2; - double interval = pi_half / samples; - for (int i = 0; i < samples + 1; i++) { - double sample = sin(i * interval); - sin_buffer[i] = sample; - cos_buffer[samples - i] = sample * interval; - } - - // Fill this to catch out of bound accesses when calculating Math.sin(pi/2). - sin_buffer[samples + 1] = sin(pi_half + interval); - cos_buffer[samples + 1] = cos(pi_half + interval) * interval; - - return isolate->heap()->undefined_value(); -} - - RUNTIME_FUNCTION(MaybeObject*, Runtime_DateMakeDay) { SealHandleScope shs(isolate); ASSERT(args.length() == 2); diff --git a/src/runtime.h b/src/runtime.h index 4872ab51cc..0e09200218 100644 --- a/src/runtime.h +++ b/src/runtime.h @@ -190,7 +190,6 @@ namespace internal { F(Math_sin, 1, 1) \ F(Math_sqrt, 1, 1) \ F(Math_tan, 1, 1) \ - F(PopulateTrigonometricTable, 3, 1) \ \ /* Regular expressions */ \ F(RegExpCompile, 3, 1) \ diff --git a/src/trig-table.h b/src/trig-table.h new file mode 100644 index 0000000000..081c0389ae --- /dev/null +++ b/src/trig-table.h @@ -0,0 +1,61 @@ +// Copyright 2013 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef V8_TRIG_TABLE_H_ +#define V8_TRIG_TABLE_H_ + + +namespace v8 { +namespace internal { + +class TrigonometricLookupTable : public AllStatic { + public: + // Casting away const-ness to use as argument for typed array constructor. + static void* sin_table() { + return const_cast(&kSinTable[0]); + } + + static void* cos_x_interval_table() { + return const_cast(&kCosXIntervalTable[0]); + } + + static double samples_over_pi_half() { return kSamplesOverPiHalf; } + static int samples() { return kSamples; } + static int table_num_bytes() { return kTableSize * sizeof(*kSinTable); } + static int table_size() { return kTableSize; } + + private: + static const double kSinTable[]; + static const double kCosXIntervalTable[]; + static const int kSamples; + static const int kTableSize; + static const double kSamplesOverPiHalf; +}; + +} } // namespace v8::internal + +#endif // V8_TRIG_TABLE_H_ diff --git a/test/cctest/test-weaktypedarrays.cc b/test/cctest/test-weaktypedarrays.cc index fe1ef04940..26b214190a 100644 --- a/test/cctest/test-weaktypedarrays.cc +++ b/test/cctest/test-weaktypedarrays.cc @@ -89,7 +89,7 @@ TEST(WeakArrayBuffersFromApi) { LocalContext context; Isolate* isolate = GetIsolateFrom(&context); - CHECK_EQ(0, CountArrayBuffersInWeakList(isolate->heap())); + int start = CountArrayBuffersInWeakList(isolate->heap()); { v8::HandleScope s1(context->GetIsolate()); v8::Handle ab1 = v8::ArrayBuffer::New(256); @@ -99,12 +99,12 @@ TEST(WeakArrayBuffersFromApi) { Handle iab1 = v8::Utils::OpenHandle(*ab1); Handle iab2 = v8::Utils::OpenHandle(*ab2); - CHECK_EQ(2, CountArrayBuffersInWeakList(isolate->heap())); + CHECK_EQ(2, CountArrayBuffersInWeakList(isolate->heap()) - start); CHECK(HasArrayBufferInWeakList(isolate->heap(), *iab1)); CHECK(HasArrayBufferInWeakList(isolate->heap(), *iab2)); } isolate->heap()->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask); - CHECK_EQ(1, CountArrayBuffersInWeakList(isolate->heap())); + CHECK_EQ(1, CountArrayBuffersInWeakList(isolate->heap()) - start); { HandleScope scope2(isolate); Handle iab1 = v8::Utils::OpenHandle(*ab1); @@ -114,7 +114,7 @@ TEST(WeakArrayBuffersFromApi) { } isolate->heap()->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask); - CHECK_EQ(0, CountArrayBuffersInWeakList(isolate->heap())); + CHECK_EQ(start, CountArrayBuffersInWeakList(isolate->heap())); } diff --git a/tools/generate-trig-table.py b/tools/generate-trig-table.py new file mode 100644 index 0000000000..14d4472aad --- /dev/null +++ b/tools/generate-trig-table.py @@ -0,0 +1,84 @@ +#!/usr/bin/env python +# +# Copyright 2013 the V8 project authors. All rights reserved. +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following +# disclaimer in the documentation and/or other materials provided +# with the distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# This is a utility for populating the lookup table for the +# approximation of trigonometric functions. + +import sys, math + +SAMPLES = 1800 + +TEMPLATE = """\ +// Copyright 2013 Google Inc. All Rights Reserved. + +// This file was generated from a python script. + +#include "v8.h" +#include "trig-table.h" + +namespace v8 { +namespace internal { + + const double TrigonometricLookupTable::kSinTable[] = + { %(sine_table)s }; + const double TrigonometricLookupTable::kCosXIntervalTable[] = + { %(cosine_table)s }; + const int TrigonometricLookupTable::kSamples = %(samples)i; + const int TrigonometricLookupTable::kTableSize = %(table_size)i; + const double TrigonometricLookupTable::kSamplesOverPiHalf = + %(samples_over_pi_half)s; + +} } // v8::internal +""" + +def main(): + pi_half = math.pi / 2 + interval = pi_half / SAMPLES + sin = [] + cos_times_interval = [] + table_size = SAMPLES + 2 + + for i in range(0, table_size): + sample = i * interval + sin.append(repr(math.sin(sample))) + cos_times_interval.append(repr(math.cos(sample) * interval)) + + output_file = sys.argv[1] + output = open(str(output_file), "w") + output.write(TEMPLATE % { + 'sine_table': ','.join(sin), + 'cosine_table': ','.join(cos_times_interval), + 'samples': SAMPLES, + 'table_size': table_size, + 'samples_over_pi_half': repr(SAMPLES / pi_half) + }) + +if __name__ == "__main__": + main() + diff --git a/tools/gyp/v8.gyp b/tools/gyp/v8.gyp index b1b9019e16..65d5fb89a9 100644 --- a/tools/gyp/v8.gyp +++ b/tools/gyp/v8.gyp @@ -140,6 +140,7 @@ 'sources': [ '<(SHARED_INTERMEDIATE_DIR)/libraries.cc', '<(SHARED_INTERMEDIATE_DIR)/experimental-libraries.cc', + '<(SHARED_INTERMEDIATE_DIR)/trig-table.cc', '<(INTERMEDIATE_DIR)/snapshot.cc', ], 'actions': [ @@ -182,6 +183,7 @@ 'sources': [ '<(SHARED_INTERMEDIATE_DIR)/libraries.cc', '<(SHARED_INTERMEDIATE_DIR)/experimental-libraries.cc', + '<(SHARED_INTERMEDIATE_DIR)/trig-table.cc', '../../src/snapshot-empty.cc', ], 'conditions': [ @@ -200,9 +202,38 @@ }], ] }, + { 'target_name': 'generate_trig_table', + 'type': 'none', + 'conditions': [ + ['want_separate_host_toolset==1', { + 'toolsets': ['host', 'target'], + }, { + 'toolsets': ['target'], + }], + ], + 'actions': [ + { + 'action_name': 'generate', + 'inputs': [ + '../../tools/generate-trig-table.py', + ], + 'outputs': [ + '<(SHARED_INTERMEDIATE_DIR)/trig-table.cc', + ], + 'action': [ + 'python', + '../../tools/generate-trig-table.py', + '<@(_outputs)', + ], + }, + ] + }, { 'target_name': 'v8_base.<(v8_target_arch)', 'type': 'static_library', + 'dependencies': [ + 'generate_trig_table', + ], 'variables': { 'optimize': 'max', },