Revert 17963, 17962 and 17955: Random number generator in JS changes
authordanno@chromium.org <danno@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Thu, 21 Nov 2013 17:21:00 +0000 (17:21 +0000)
committerdanno@chromium.org <danno@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Thu, 21 Nov 2013 17:21:00 +0000 (17:21 +0000)
Revert 17966, 17965 also as collateral damage: Embed trigonometric lookup table.

Due to Heapcheck and valgrind failures that are not yet fixed.

TBR=svenpanne@chromium.org

Review URL: https://codereview.chromium.org/80513004

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@17981 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

35 files changed:
src/arm/full-codegen-arm.cc
src/arm/lithium-arm.cc
src/arm/lithium-arm.h
src/arm/lithium-codegen-arm.cc
src/assembler.cc
src/assembler.h
src/bootstrapper.cc
src/contexts.h
src/globals.h
src/heap.cc
src/hydrogen-instructions.h
src/hydrogen.cc
src/ia32/full-codegen-ia32.cc
src/ia32/lithium-codegen-ia32.cc
src/ia32/lithium-ia32.cc
src/ia32/lithium-ia32.h
src/math.js
src/mips/full-codegen-mips.cc
src/mips/lithium-codegen-mips.cc
src/mips/lithium-mips.cc
src/mips/lithium-mips.h
src/objects.h
src/runtime.cc
src/runtime.h
src/serialize.cc
src/trig-table.h [deleted file]
src/v8.cc
src/v8.h
src/x64/full-codegen-x64.cc
src/x64/lithium-codegen-x64.cc
src/x64/lithium-x64.cc
src/x64/lithium-x64.h
test/cctest/test-weaktypedarrays.cc
tools/generate-trig-table.py [deleted file]
tools/gyp/v8.gyp

index 4a39970..64a9fdf 100644 (file)
@@ -3347,6 +3347,50 @@ void FullCodeGenerator::EmitLog(CallRuntime* expr) {
 }
 
 
+void FullCodeGenerator::EmitRandomHeapNumber(CallRuntime* expr) {
+  ASSERT(expr->arguments()->length() == 0);
+  Label slow_allocate_heapnumber;
+  Label heapnumber_allocated;
+
+  __ LoadRoot(r6, Heap::kHeapNumberMapRootIndex);
+  __ AllocateHeapNumber(r4, r1, r2, r6, &slow_allocate_heapnumber);
+  __ jmp(&heapnumber_allocated);
+
+  __ bind(&slow_allocate_heapnumber);
+  // Allocate a heap number.
+  __ CallRuntime(Runtime::kNumberAlloc, 0);
+  __ mov(r4, Operand(r0));
+
+  __ bind(&heapnumber_allocated);
+
+  // Convert 32 random bits in r0 to 0.(32 random bits) in a double
+  // by computing:
+  // ( 1.(20 0s)(32 random bits) x 2^20 ) - (1.0 x 2^20)).
+  __ PrepareCallCFunction(1, r0);
+  __ ldr(r0,
+         ContextOperand(context_register(), Context::GLOBAL_OBJECT_INDEX));
+  __ ldr(r0, FieldMemOperand(r0, GlobalObject::kNativeContextOffset));
+  __ CallCFunction(ExternalReference::random_uint32_function(isolate()), 1);
+
+  // 0x41300000 is the top half of 1.0 x 2^20 as a double.
+  // Create this constant using mov/orr to avoid PC relative load.
+  __ mov(r1, Operand(0x41000000));
+  __ orr(r1, r1, Operand(0x300000));
+  // Move 0x41300000xxxxxxxx (x = random bits) to VFP.
+  __ vmov(d7, r0, r1);
+  // Move 0x4130000000000000 to VFP.
+  __ mov(r0, Operand::Zero());
+  __ vmov(d8, r0, r1);
+  // Subtract and store the result in the heap number.
+  __ vsub(d7, d7, d8);
+  __ sub(r0, r4, Operand(kHeapObjectTag));
+  __ vstr(d7, r0, HeapNumber::kValueOffset);
+  __ mov(r0, r4);
+
+  context()->Plug(r0);
+}
+
+
 void FullCodeGenerator::EmitSubString(CallRuntime* expr) {
   // Load the arguments on the stack and call the stub.
   SubStringStub stub;
index eeffc16..a1e892b 100644 (file)
@@ -1720,6 +1720,19 @@ LInstruction* LChunkBuilder::DoPower(HPower* instr) {
 }
 
 
+LInstruction* LChunkBuilder::DoRandom(HRandom* instr) {
+  ASSERT(instr->representation().IsDouble());
+  ASSERT(instr->global_object()->representation().IsTagged());
+  LOperand* global_object = UseTempRegister(instr->global_object());
+  LOperand* scratch = TempRegister();
+  LOperand* scratch2 = TempRegister();
+  LOperand* scratch3 = TempRegister();
+  LRandom* result = new(zone()) LRandom(
+      global_object, scratch, scratch2, scratch3);
+  return DefineFixedDouble(result, d7);
+}
+
+
 LInstruction* LChunkBuilder::DoCompareGeneric(HCompareGeneric* instr) {
   ASSERT(instr->left()->representation().IsTagged());
   ASSERT(instr->right()->representation().IsTagged());
index 72932de..5b9278b 100644 (file)
@@ -155,6 +155,7 @@ class LCodeGen;
   V(Parameter)                                  \
   V(Power)                                      \
   V(PushArgument)                               \
+  V(Random)                                     \
   V(RegExpLiteral)                              \
   V(Return)                                     \
   V(SeqStringGetChar)                           \
@@ -1480,6 +1481,28 @@ class LPower V8_FINAL : public LTemplateInstruction<1, 2, 0> {
 };
 
 
+class LRandom V8_FINAL : public LTemplateInstruction<1, 1, 3> {
+ public:
+  LRandom(LOperand* global_object,
+          LOperand* scratch,
+          LOperand* scratch2,
+          LOperand* scratch3) {
+    inputs_[0] = global_object;
+    temps_[0] = scratch;
+    temps_[1] = scratch2;
+    temps_[2] = scratch3;
+  }
+
+  LOperand* global_object() const { return inputs_[0]; }
+  LOperand* scratch() const { return temps_[0]; }
+  LOperand* scratch2() const { return temps_[1]; }
+  LOperand* scratch3() const { return temps_[2]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(Random, "random")
+  DECLARE_HYDROGEN_ACCESSOR(Random)
+};
+
+
 class LArithmeticD V8_FINAL : public LTemplateInstruction<1, 2, 0> {
  public:
   LArithmeticD(Token::Value op, LOperand* left, LOperand* right)
index cd9c712..0aa8197 100644 (file)
@@ -3934,6 +3934,68 @@ void LCodeGen::DoPower(LPower* instr) {
 }
 
 
+void LCodeGen::DoRandom(LRandom* instr) {
+  // Assert that the register size is indeed the size of each seed.
+  static const int kSeedSize = sizeof(uint32_t);
+  STATIC_ASSERT(kPointerSize == kSeedSize);
+
+  // Load native context
+  Register global_object = ToRegister(instr->global_object());
+  Register native_context = global_object;
+  __ ldr(native_context, FieldMemOperand(
+          global_object, GlobalObject::kNativeContextOffset));
+
+  // Load state (FixedArray of the native context's random seeds)
+  static const int kRandomSeedOffset =
+      FixedArray::kHeaderSize + Context::RANDOM_SEED_INDEX * kPointerSize;
+  Register state = native_context;
+  __ ldr(state, FieldMemOperand(native_context, kRandomSeedOffset));
+
+  // Load state[0].
+  Register state0 = ToRegister(instr->scratch());
+  __ ldr(state0, FieldMemOperand(state, ByteArray::kHeaderSize));
+  // Load state[1].
+  Register state1 = ToRegister(instr->scratch2());
+  __ ldr(state1, FieldMemOperand(state, ByteArray::kHeaderSize + kSeedSize));
+
+  // state[0] = 18273 * (state[0] & 0xFFFF) + (state[0] >> 16)
+  Register scratch3 = ToRegister(instr->scratch3());
+  Register scratch4 = scratch0();
+  __ and_(scratch3, state0, Operand(0xFFFF));
+  __ mov(scratch4, Operand(18273));
+  __ mul(scratch3, scratch3, scratch4);
+  __ add(state0, scratch3, Operand(state0, LSR, 16));
+  // Save state[0].
+  __ str(state0, FieldMemOperand(state, ByteArray::kHeaderSize));
+
+  // state[1] = 36969 * (state[1] & 0xFFFF) + (state[1] >> 16)
+  __ and_(scratch3, state1, Operand(0xFFFF));
+  __ mov(scratch4, Operand(36969));
+  __ mul(scratch3, scratch3, scratch4);
+  __ add(state1, scratch3, Operand(state1, LSR, 16));
+  // Save state[1].
+  __ str(state1, FieldMemOperand(state, ByteArray::kHeaderSize + kSeedSize));
+
+  // Random bit pattern = (state[0] << 14) + (state[1] & 0x3FFFF)
+  Register random = scratch4;
+  __ and_(random, state1, Operand(0x3FFFF));
+  __ add(random, random, Operand(state0, LSL, 14));
+
+  // 0x41300000 is the top half of 1.0 x 2^20 as a double.
+  // Create this constant using mov/orr to avoid PC relative load.
+  __ mov(scratch3, Operand(0x41000000));
+  __ orr(scratch3, scratch3, Operand(0x300000));
+  // Move 0x41300000xxxxxxxx (x = random bits) to VFP.
+  DwVfpRegister result = ToDoubleRegister(instr->result());
+  __ vmov(result, random, scratch3);
+  // Move 0x4130000000000000 to VFP.
+  __ mov(scratch4, Operand::Zero());
+  DwVfpRegister scratch5 = double_scratch0();
+  __ vmov(scratch5, scratch4, scratch3);
+  __ vsub(result, result, scratch5);
+}
+
+
 void LCodeGen::DoMathExp(LMathExp* instr) {
   DwVfpRegister input = ToDoubleRegister(instr->value());
   DwVfpRegister result = ToDoubleRegister(instr->result());
index febae63..fa0b4c3 100644 (file)
@@ -1061,6 +1061,12 @@ ExternalReference ExternalReference::delete_handle_scope_extensions(
 }
 
 
+ExternalReference ExternalReference::random_uint32_function(
+    Isolate* isolate) {
+  return ExternalReference(Redirect(isolate, FUNCTION_ADDR(V8::Random)));
+}
+
+
 ExternalReference ExternalReference::get_date_field_function(
     Isolate* isolate) {
   return ExternalReference(Redirect(isolate, FUNCTION_ADDR(JSDate::GetField)));
index 0c706c4..049fa8c 100644 (file)
@@ -718,6 +718,7 @@ class ExternalReference BASE_EMBEDDED {
       Isolate* isolate);
   static ExternalReference flush_icache_function(Isolate* isolate);
   static ExternalReference perform_gc_function(Isolate* isolate);
+  static ExternalReference random_uint32_function(Isolate* isolate);
   static ExternalReference transcendental_cache_array_address(Isolate* isolate);
   static ExternalReference delete_handle_scope_extensions(Isolate* isolate);
 
index dc64f17..bc52fa8 100644 (file)
@@ -40,7 +40,6 @@
 #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"
@@ -1309,6 +1308,10 @@ void Genesis::InitializeGlobal(Handle<GlobalObject> inner_global,
   // Initialize the embedder data slot.
   Handle<FixedArray> embedder_data = factory->NewFixedArray(2);
   native_context()->set_embedder_data(*embedder_data);
+
+  // Allocate the random seed slot.
+  Handle<ByteArray> random_seed = factory->NewByteArray(kRandomStateSize);
+  native_context()->set_random_seed(*random_seed);
 }
 
 
@@ -2632,71 +2635,13 @@ Genesis::Genesis(Isolate* isolate,
   InitializeExperimentalGlobal();
   if (!InstallExperimentalNatives()) return;
 
-  // We can't (de-)serialize typed arrays currently, but we are lucky: The state
-  // of the random number generator and the trigonometric lookup tables needs no
-  // initialization during snapshot creation time.
-  uint32_t* state = NULL;
-  if (!Serializer::enabled()) {
-    // Initially seed the per-context random number generator using the
-    // per-isolate random number generator.
-    const int num_elems = 2;
-    state = new uint32_t[num_elems];
-    const int num_bytes = num_elems * sizeof(*state);
-
-    do {
-      isolate->random_number_generator()->NextBytes(state, num_bytes);
-    } while (state[0] == 0 || state[1] == 0);
-
-    v8::Local<v8::ArrayBuffer> buffer = v8::ArrayBuffer::New(state, num_bytes);
-    v8::Local<v8::Uint32Array> ta = v8::Uint32Array::New(buffer, 0, num_elems);
-    Handle<JSBuiltinsObject> builtins(native_context()->builtins());
-    ForceSetProperty(builtins,
-                     factory()->InternalizeOneByteString(
-                         STATIC_ASCII_VECTOR("rngstate")),
-                     Utils::OpenHandle(*ta),
-                     NONE);
-
-    // Initialize trigonometric lookup tables and constants.
-    const int table_num_bytes = TrigonometricLookupTable::table_num_bytes();
-    v8::Local<v8::ArrayBuffer> sin_buffer = v8::ArrayBuffer::New(
-        TrigonometricLookupTable::sin_table(), table_num_bytes);
-    v8::Local<v8::ArrayBuffer> cos_buffer = v8::ArrayBuffer::New(
-        TrigonometricLookupTable::cos_x_interval_table(), table_num_bytes);
-    v8::Local<v8::Float64Array> sin_table = v8::Float64Array::New(
-        sin_buffer, 0, TrigonometricLookupTable::table_size());
-    v8::Local<v8::Float64Array> 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);
-  }
-  // TODO(svenpanne) We have to delete the state when the context dies, so we
-  // remember it in the context (encoded as a Smi, our usual technique for
-  // aligned pointers) and do the cleanup in
-  // WeakListVisitor<Context>::VisitPhantomObject(). This hack can go away when
-  // we have a way to allocate the backing store of typed arrays on the heap.
-  ASSERT(reinterpret_cast<Smi*>(state)->IsSmi());
-  native_context()->set_random_state(reinterpret_cast<Smi*>(state));
+  // Initially seed the per-context random number generator
+  // using the per-isolate random number generator.
+  uint32_t* state = reinterpret_cast<uint32_t*>(
+      native_context()->random_seed()->GetDataStartAddress());
+  do {
+    isolate->random_number_generator()->NextBytes(state, kRandomStateSize);
+  } while (state[0] == 0 || state[1] == 0);
 
   result_ = native_context();
 }
index 3817de1..189c215 100644 (file)
@@ -185,7 +185,7 @@ enum BindingFlags {
   V(GENERATOR_OBJECT_PROTOTYPE_MAP_INDEX, Map, \
     generator_object_prototype_map) \
   V(GENERATOR_RESULT_MAP_INDEX, Map, generator_result_map) \
-  V(RANDOM_STATE_INDEX, Smi, random_state)
+  V(RANDOM_SEED_INDEX, ByteArray, random_seed)
 
 // JSFunctions are pairs (context, function code), sometimes also called
 // closures. A Context object is used to represent function contexts and
@@ -332,7 +332,7 @@ class Context: public FixedArray {
     STRICT_MODE_GENERATOR_FUNCTION_MAP_INDEX,
     GENERATOR_OBJECT_PROTOTYPE_MAP_INDEX,
     GENERATOR_RESULT_MAP_INDEX,
-    RANDOM_STATE_INDEX,
+    RANDOM_SEED_INDEX,
 
     // Properties from here are treated as weak references by the full GC.
     // Scavenge treats them as strong references.
index db80a7e..1db48a1 100644 (file)
@@ -251,6 +251,9 @@ const int kFPOnStackSize = kRegisterSize;
 
 const int kDoubleSizeLog2 = 3;
 
+// Size of the state of a the random number generator.
+const int kRandomStateSize = 2 * kIntSize;
+
 #if V8_HOST_ARCH_64_BIT
 const int kPointerSizeLog2 = 3;
 const intptr_t kIntptrSignBit = V8_INT64_C(0x8000000000000000);
index dcab156..b5fe184 100644 (file)
@@ -1765,9 +1765,7 @@ struct WeakListVisitor<Context> {
     }
   }
 
-  static void VisitPhantomObject(Heap*, Context* context) {
-    // A bit of a hack, see the comment at the end of Genesis::Genesis().
-    delete[] reinterpret_cast<uint32_t*>(context->random_state());
+  static void VisitPhantomObject(Heap*, Context*) {
   }
 
   static int WeakNextOffset() {
index f9524bc..73c1d7d 100644 (file)
@@ -155,6 +155,7 @@ class LChunkBuilder;
   V(Parameter)                                 \
   V(Power)                                     \
   V(PushArgument)                              \
+  V(Random)                                    \
   V(RegExpLiteral)                             \
   V(Return)                                    \
   V(Ror)                                       \
@@ -4723,6 +4724,28 @@ class HPower V8_FINAL : public HTemplateInstruction<2> {
 };
 
 
+class HRandom V8_FINAL : public HTemplateInstruction<1> {
+ public:
+  DECLARE_INSTRUCTION_FACTORY_P1(HRandom, HValue*);
+
+  HValue* global_object() { return OperandAt(0); }
+
+  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
+    return Representation::Tagged();
+  }
+
+  DECLARE_CONCRETE_INSTRUCTION(Random)
+
+ private:
+  explicit HRandom(HValue* global_object) {
+    SetOperandAt(0, global_object);
+    set_representation(Representation::Double());
+  }
+
+  virtual bool IsDeletable() const V8_OVERRIDE { return true; }
+};
+
+
 class HAdd V8_FINAL : public HArithmeticBinaryOperation {
  public:
   static HInstruction* New(Zone* zone,
index 9215d0f..f7b3100 100644 (file)
@@ -7489,6 +7489,16 @@ bool HOptimizedGraphBuilder::TryInlineBuiltinMethodCall(
         return true;
       }
       break;
+    case kMathRandom:
+      if (argument_count == 1 && check_type == RECEIVER_MAP_CHECK) {
+        AddCheckConstantFunction(expr->holder(), receiver, receiver_map);
+        Drop(1);  // Receiver.
+        HGlobalObject* global_object = Add<HGlobalObject>();
+        HRandom* result = New<HRandom>(global_object);
+        ast_context()->ReturnInstruction(result, expr->id());
+        return true;
+      }
+      break;
     case kMathMax:
     case kMathMin:
       if (argument_count == 3 && check_type == RECEIVER_MAP_CHECK) {
@@ -9863,6 +9873,14 @@ void HOptimizedGraphBuilder::GenerateLog(CallRuntime* call) {
 }
 
 
+// Fast support for Math.random().
+void HOptimizedGraphBuilder::GenerateRandomHeapNumber(CallRuntime* call) {
+  HGlobalObject* global_object = Add<HGlobalObject>();
+  HRandom* result = New<HRandom>(global_object);
+  return ast_context()->ReturnInstruction(result, call->id());
+}
+
+
 // Fast support for StringAdd.
 void HOptimizedGraphBuilder::GenerateStringAdd(CallRuntime* call) {
   ASSERT_EQ(2, call->arguments()->length());
index e067c90..86c525d 100644 (file)
@@ -3296,6 +3296,57 @@ void FullCodeGenerator::EmitLog(CallRuntime* expr) {
 }
 
 
+void FullCodeGenerator::EmitRandomHeapNumber(CallRuntime* expr) {
+  ASSERT(expr->arguments()->length() == 0);
+
+  Label slow_allocate_heapnumber;
+  Label heapnumber_allocated;
+
+  __ AllocateHeapNumber(edi, ebx, ecx, &slow_allocate_heapnumber);
+  __ jmp(&heapnumber_allocated);
+
+  __ bind(&slow_allocate_heapnumber);
+  // Allocate a heap number.
+  __ CallRuntime(Runtime::kNumberAlloc, 0);
+  __ mov(edi, eax);
+
+  __ bind(&heapnumber_allocated);
+
+  __ PrepareCallCFunction(1, ebx);
+  __ mov(eax, ContextOperand(context_register(), Context::GLOBAL_OBJECT_INDEX));
+  __ mov(eax, FieldOperand(eax, GlobalObject::kNativeContextOffset));
+  __ mov(Operand(esp, 0), eax);
+  __ CallCFunction(ExternalReference::random_uint32_function(isolate()), 1);
+
+  // Convert 32 random bits in eax to 0.(32 random bits) in a double
+  // by computing:
+  // ( 1.(20 0s)(32 random bits) x 2^20 ) - (1.0 x 2^20)).
+  // This is implemented on both SSE2 and FPU.
+  if (CpuFeatures::IsSupported(SSE2)) {
+    CpuFeatureScope fscope(masm(), SSE2);
+    __ mov(ebx, Immediate(0x49800000));  // 1.0 x 2^20 as single.
+    __ movd(xmm1, ebx);
+    __ movd(xmm0, eax);
+    __ cvtss2sd(xmm1, xmm1);
+    __ xorps(xmm0, xmm1);
+    __ subsd(xmm0, xmm1);
+    __ movsd(FieldOperand(edi, HeapNumber::kValueOffset), xmm0);
+  } else {
+    // 0x4130000000000000 is 1.0 x 2^20 as a double.
+    __ mov(FieldOperand(edi, HeapNumber::kExponentOffset),
+           Immediate(0x41300000));
+    __ mov(FieldOperand(edi, HeapNumber::kMantissaOffset), eax);
+    __ fld_d(FieldOperand(edi, HeapNumber::kValueOffset));
+    __ mov(FieldOperand(edi, HeapNumber::kMantissaOffset), Immediate(0));
+    __ fld_d(FieldOperand(edi, HeapNumber::kValueOffset));
+    __ fsubp(1);
+    __ fstp_d(FieldOperand(edi, HeapNumber::kValueOffset));
+  }
+  __ mov(eax, edi);
+  context()->Plug(eax);
+}
+
+
 void FullCodeGenerator::EmitSubString(CallRuntime* expr) {
   // Load the arguments on the stack and call the stub.
   SubStringStub stub;
index 1797d2e..f316e85 100644 (file)
@@ -4167,6 +4167,69 @@ void LCodeGen::DoPower(LPower* instr) {
 }
 
 
+void LCodeGen::DoRandom(LRandom* instr) {
+  CpuFeatureScope scope(masm(), SSE2);
+
+  // Assert that the register size is indeed the size of each seed.
+  static const int kSeedSize = sizeof(uint32_t);
+  STATIC_ASSERT(kPointerSize == kSeedSize);
+
+  // Load native context
+  Register global_object = ToRegister(instr->global_object());
+  Register native_context = global_object;
+  __ mov(native_context, FieldOperand(
+          global_object, GlobalObject::kNativeContextOffset));
+
+  // Load state (FixedArray of the native context's random seeds)
+  static const int kRandomSeedOffset =
+      FixedArray::kHeaderSize + Context::RANDOM_SEED_INDEX * kPointerSize;
+  Register state = native_context;
+  __ mov(state, FieldOperand(native_context, kRandomSeedOffset));
+
+  // Load state[0].
+  Register state0 = ToRegister(instr->scratch());
+  __ mov(state0, FieldOperand(state, ByteArray::kHeaderSize));
+  // Load state[1].
+  Register state1 = ToRegister(instr->scratch2());
+  __ mov(state1, FieldOperand(state, ByteArray::kHeaderSize + kSeedSize));
+
+  // state[0] = 18273 * (state[0] & 0xFFFF) + (state[0] >> 16)
+  Register scratch3 = ToRegister(instr->scratch3());
+  __ movzx_w(scratch3, state0);
+  __ imul(scratch3, scratch3, 18273);
+  __ shr(state0, 16);
+  __ add(state0, scratch3);
+  // Save state[0].
+  __ mov(FieldOperand(state, ByteArray::kHeaderSize), state0);
+
+  // state[1] = 36969 * (state[1] & 0xFFFF) + (state[1] >> 16)
+  __ movzx_w(scratch3, state1);
+  __ imul(scratch3, scratch3, 36969);
+  __ shr(state1, 16);
+  __ add(state1, scratch3);
+  // Save state[1].
+  __ mov(FieldOperand(state, ByteArray::kHeaderSize + kSeedSize), state1);
+
+  // Random bit pattern = (state[0] << 14) + (state[1] & 0x3FFFF)
+  Register random = state0;
+  __ shl(random, 14);
+  __ and_(state1, Immediate(0x3FFFF));
+  __ add(random, state1);
+
+  // Convert 32 random bits in random to 0.(32 random bits) in a double
+  // by computing:
+  // ( 1.(20 0s)(32 random bits) x 2^20 ) - (1.0 x 2^20)).
+  XMMRegister result = ToDoubleRegister(instr->result());
+  XMMRegister scratch4 = double_scratch0();
+  __ mov(scratch3, Immediate(0x49800000));  // 1.0 x 2^20 as single.
+  __ movd(scratch4, scratch3);
+  __ movd(result, random);
+  __ cvtss2sd(scratch4, scratch4);
+  __ xorps(result, scratch4);
+  __ subsd(result, scratch4);
+}
+
+
 void LCodeGen::DoMathLog(LMathLog* instr) {
   CpuFeatureScope scope(masm(), SSE2);
   ASSERT(instr->value()->Equals(instr->result()));
index 5343773..d4c17ab 100644 (file)
@@ -1695,6 +1695,19 @@ LInstruction* LChunkBuilder::DoPower(HPower* instr) {
 }
 
 
+LInstruction* LChunkBuilder::DoRandom(HRandom* instr) {
+  ASSERT(instr->representation().IsDouble());
+  ASSERT(instr->global_object()->representation().IsTagged());
+  LOperand* global_object = UseTempRegister(instr->global_object());
+  LOperand* scratch = TempRegister();
+  LOperand* scratch2 = TempRegister();
+  LOperand* scratch3 = TempRegister();
+  LRandom* result = new(zone()) LRandom(
+      global_object, scratch, scratch2, scratch3);
+  return DefineFixedDouble(result, xmm1);
+}
+
+
 LInstruction* LChunkBuilder::DoCompareGeneric(HCompareGeneric* instr) {
   ASSERT(instr->left()->representation().IsSmiOrTagged());
   ASSERT(instr->right()->representation().IsSmiOrTagged());
index b429120..bc2b71b 100644 (file)
@@ -154,6 +154,7 @@ class LCodeGen;
   V(OuterContext)                               \
   V(Parameter)                                  \
   V(Power)                                      \
+  V(Random)                                     \
   V(PushArgument)                               \
   V(RegExpLiteral)                              \
   V(Return)                                     \
@@ -1461,6 +1462,28 @@ class LPower V8_FINAL : public LTemplateInstruction<1, 2, 0> {
 };
 
 
+class LRandom V8_FINAL : public LTemplateInstruction<1, 1, 3> {
+ public:
+  LRandom(LOperand* global_object,
+          LOperand* scratch,
+          LOperand* scratch2,
+          LOperand* scratch3) {
+    inputs_[0] = global_object;
+    temps_[0] = scratch;
+    temps_[1] = scratch2;
+    temps_[2] = scratch3;
+  }
+
+  LOperand* global_object() const { return inputs_[0]; }
+  LOperand* scratch() const { return temps_[0]; }
+  LOperand* scratch2() const { return temps_[1]; }
+  LOperand* scratch3() const { return temps_[2]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(Random, "random")
+  DECLARE_HYDROGEN_ACCESSOR(Random)
+};
+
+
 class LArithmeticD V8_FINAL : public LTemplateInstruction<1, 2, 0> {
  public:
   LArithmeticD(Token::Value op, LOperand* left, LOperand* right)
index fb7d306..2df0ec2 100644 (file)
@@ -79,8 +79,7 @@ function MathCeil(x) {
 
 // ECMA 262 - 15.8.2.7
 function MathCos(x) {
-  x = MathAbs(x);  // Convert to number and get rid of -0.
-  return TrigonometricInterpolation(x, 1);
+  return MathCosImpl(x);
 }
 
 // ECMA 262 - 15.8.2.8
@@ -169,15 +168,8 @@ function MathPow(x, y) {
 }
 
 // ECMA 262 - 15.8.2.14
-var rngstate;  // Initialized to a Uint32Array during genesis.
 function MathRandom() {
-  var r0 = (MathImul(18273, rngstate[0] & 0xFFFF) + (rngstate[0] >>> 16)) | 0;
-  rngstate[0] = r0;
-  var r1 = (MathImul(36969, rngstate[1] & 0xFFFF) + (rngstate[1] >>> 16)) | 0;
-  rngstate[1] = r1;
-  var x = ((r0 << 16) + (r1 & 0xFFFF)) | 0;
-  // Division by 0x100000000 through multiplication by reciprocal.
-  return (x < 0 ? (x + 0x100000000) : x) * 2.3283064365386962890625e-10;
+  return %_RandomHeapNumber();
 }
 
 // ECMA 262 - 15.8.2.15
@@ -187,9 +179,7 @@ function MathRound(x) {
 
 // ECMA 262 - 15.8.2.16
 function MathSin(x) {
-  x = x * 1;  // Convert to number and deal with -0.
-  if (%_IsMinusZero(x)) return x;
-  return TrigonometricInterpolation(x, 0);
+  return MathSinImpl(x);
 }
 
 // ECMA 262 - 15.8.2.17
@@ -199,7 +189,7 @@ function MathSqrt(x) {
 
 // ECMA 262 - 15.8.2.18
 function MathTan(x) {
-  return MathSin(x) / MathCos(x);
+  return MathSinImpl(x) / MathCosImpl(x);
 }
 
 // Non-standard extension.
@@ -208,73 +198,119 @@ function MathImul(x, y) {
 }
 
 
-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.
-
-// 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 MathSinImpl = function(x) {
+  InitTrigonometricFunctions();
+  return MathSinImpl(x);
+}
+
+
+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;
     }
-    multiple = MathFloor(x * kInversePiHalf);
-    x = x - multiple * kPiHalf1 - multiple * kPiHalf2;
-    phase += multiple;
+    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;
   }
-  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() {
@@ -351,7 +387,6 @@ function SetUpMath() {
   %SetInlineBuiltinFlag(MathSin);
   %SetInlineBuiltinFlag(MathCos);
   %SetInlineBuiltinFlag(MathTan);
-  %SetInlineBuiltinFlag(TrigonometricInterpolation);
 }
 
 SetUpMath();
index 486eb9d..6ef871f 100644 (file)
@@ -3378,6 +3378,48 @@ void FullCodeGenerator::EmitLog(CallRuntime* expr) {
 }
 
 
+void FullCodeGenerator::EmitRandomHeapNumber(CallRuntime* expr) {
+  ASSERT(expr->arguments()->length() == 0);
+  Label slow_allocate_heapnumber;
+  Label heapnumber_allocated;
+
+  // Save the new heap number in callee-saved register s0, since
+  // we call out to external C code below.
+  __ LoadRoot(t6, Heap::kHeapNumberMapRootIndex);
+  __ AllocateHeapNumber(s0, a1, a2, t6, &slow_allocate_heapnumber);
+  __ jmp(&heapnumber_allocated);
+
+  __ bind(&slow_allocate_heapnumber);
+
+  // Allocate a heap number.
+  __ CallRuntime(Runtime::kNumberAlloc, 0);
+  __ mov(s0, v0);   // Save result in s0, so it is saved thru CFunc call.
+
+  __ bind(&heapnumber_allocated);
+
+  // Convert 32 random bits in v0 to 0.(32 random bits) in a double
+  // by computing:
+  // ( 1.(20 0s)(32 random bits) x 2^20 ) - (1.0 x 2^20)).
+  __ PrepareCallCFunction(1, a0);
+  __ lw(a0, ContextOperand(cp, Context::GLOBAL_OBJECT_INDEX));
+  __ lw(a0, FieldMemOperand(a0, GlobalObject::kNativeContextOffset));
+  __ CallCFunction(ExternalReference::random_uint32_function(isolate()), 1);
+
+  // 0x41300000 is the top half of 1.0 x 2^20 as a double.
+  __ li(a1, Operand(0x41300000));
+  // Move 0x41300000xxxxxxxx (x = random bits in v0) to FPU.
+  __ Move(f12, v0, a1);
+  // Move 0x4130000000000000 to FPU.
+  __ Move(f14, zero_reg, a1);
+  // Subtract and store the result in the heap number.
+  __ sub_d(f0, f12, f14);
+  __ sdc1(f0, FieldMemOperand(s0, HeapNumber::kValueOffset));
+  __ mov(v0, s0);
+
+  context()->Plug(v0);
+}
+
+
 void FullCodeGenerator::EmitSubString(CallRuntime* expr) {
   // Load the arguments on the stack and call the stub.
   SubStringStub stub;
index 5a8249e..43d83bd 100644 (file)
@@ -3851,6 +3851,68 @@ void LCodeGen::DoPower(LPower* instr) {
 }
 
 
+void LCodeGen::DoRandom(LRandom* instr) {
+  // Assert that the register size is indeed the size of each seed.
+  static const int kSeedSize = sizeof(uint32_t);
+  STATIC_ASSERT(kPointerSize == kSeedSize);
+
+  // Load native context.
+  Register global_object = ToRegister(instr->global_object());
+  Register native_context = global_object;
+  __ lw(native_context, FieldMemOperand(
+          global_object, GlobalObject::kNativeContextOffset));
+
+  // Load state (FixedArray of the native context's random seeds).
+  static const int kRandomSeedOffset =
+      FixedArray::kHeaderSize + Context::RANDOM_SEED_INDEX * kPointerSize;
+  Register state = native_context;
+  __ lw(state, FieldMemOperand(native_context, kRandomSeedOffset));
+
+  // Load state[0].
+  Register state0 = ToRegister(instr->scratch());
+  __ lw(state0, FieldMemOperand(state, ByteArray::kHeaderSize));
+  // Load state[1].
+  Register state1 = ToRegister(instr->scratch2());
+  __ lw(state1, FieldMemOperand(state, ByteArray::kHeaderSize + kSeedSize));
+
+  // state[0] = 18273 * (state[0] & 0xFFFF) + (state[0] >> 16)
+  Register scratch3 = ToRegister(instr->scratch3());
+  Register scratch4 = scratch0();
+  __ And(scratch3, state0, Operand(0xFFFF));
+  __ li(scratch4, Operand(18273));
+  __ Mul(scratch3, scratch3, scratch4);
+  __ srl(state0, state0, 16);
+  __ Addu(state0, scratch3, state0);
+  // Save state[0].
+  __ sw(state0, FieldMemOperand(state, ByteArray::kHeaderSize));
+
+  // state[1] = 36969 * (state[1] & 0xFFFF) + (state[1] >> 16)
+  __ And(scratch3, state1, Operand(0xFFFF));
+  __ li(scratch4, Operand(36969));
+  __ Mul(scratch3, scratch3, scratch4);
+  __ srl(state1, state1, 16),
+  __ Addu(state1, scratch3, state1);
+  // Save state[1].
+  __ sw(state1, FieldMemOperand(state, ByteArray::kHeaderSize + kSeedSize));
+
+  // Random bit pattern = (state[0] << 14) + (state[1] & 0x3FFFF)
+  Register random = scratch4;
+  __ And(random, state1, Operand(0x3FFFF));
+  __ sll(state0, state0, 14);
+  __ Addu(random, random, state0);
+
+  // 0x41300000 is the top half of 1.0 x 2^20 as a double.
+  __ li(scratch3, Operand(0x41300000));
+  // Move 0x41300000xxxxxxxx (x = random bits in v0) to FPU.
+  DoubleRegister result = ToDoubleRegister(instr->result());
+  __ Move(result, random, scratch3);
+  // Move 0x4130000000000000 to FPU.
+  DoubleRegister scratch5 = double_scratch0();
+  __ Move(scratch5, zero_reg, scratch3);
+  __ sub_d(result, result, scratch5);
+}
+
+
 void LCodeGen::DoMathExp(LMathExp* instr) {
   DoubleRegister input = ToDoubleRegister(instr->value());
   DoubleRegister result = ToDoubleRegister(instr->result());
index 34e5838..5dbef8d 100644 (file)
@@ -1640,6 +1640,19 @@ LInstruction* LChunkBuilder::DoPower(HPower* instr) {
 }
 
 
+LInstruction* LChunkBuilder::DoRandom(HRandom* instr) {
+  ASSERT(instr->representation().IsDouble());
+  ASSERT(instr->global_object()->representation().IsTagged());
+  LOperand* global_object = UseTempRegister(instr->global_object());
+  LOperand* scratch = TempRegister();
+  LOperand* scratch2 = TempRegister();
+  LOperand* scratch3 = TempRegister();
+  LRandom* result = new(zone()) LRandom(
+      global_object, scratch, scratch2, scratch3);
+  return DefineFixedDouble(result, f0);
+}
+
+
 LInstruction* LChunkBuilder::DoCompareGeneric(HCompareGeneric* instr) {
   ASSERT(instr->left()->representation().IsTagged());
   ASSERT(instr->right()->representation().IsTagged());
index 2996c78..452963b 100644 (file)
@@ -154,6 +154,7 @@ class LCodeGen;
   V(Parameter)                                  \
   V(Power)                                      \
   V(PushArgument)                               \
+  V(Random)                                     \
   V(RegExpLiteral)                              \
   V(Return)                                     \
   V(SeqStringGetChar)                           \
@@ -1460,6 +1461,28 @@ class LPower V8_FINAL : public LTemplateInstruction<1, 2, 0> {
 };
 
 
+class LRandom V8_FINAL : public LTemplateInstruction<1, 1, 3> {
+ public:
+  LRandom(LOperand* global_object,
+          LOperand* scratch,
+          LOperand* scratch2,
+          LOperand* scratch3) {
+    inputs_[0] = global_object;
+    temps_[0] = scratch;
+    temps_[1] = scratch2;
+    temps_[2] = scratch3;
+  }
+
+  LOperand* global_object() const { return inputs_[0]; }
+  LOperand* scratch() const { return temps_[0]; }
+  LOperand* scratch2() const { return temps_[1]; }
+  LOperand* scratch3() const { return temps_[2]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(Random, "random")
+  DECLARE_HYDROGEN_ACCESSOR(Random)
+};
+
+
 class LArithmeticD V8_FINAL : public LTemplateInstruction<1, 2, 0> {
  public:
   LArithmeticD(Token::Value op, LOperand* left, LOperand* right)
index 1e26178..a5f5b52 100644 (file)
@@ -6507,6 +6507,7 @@ class Script: public Struct {
   V(Math, exp, MathExp)                             \
   V(Math, sqrt, MathSqrt)                           \
   V(Math, pow, MathPow)                             \
+  V(Math, random, MathRandom)                       \
   V(Math, max, MathMax)                             \
   V(Math, min, MathMin)                             \
   V(Math, imul, MathImul)
index c11a005..f546629 100644 (file)
@@ -7848,6 +7848,35 @@ 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<double*>(
+      JSArrayBuffer::cast(sin_table->buffer())->backing_store());
+  double* cos_buffer = reinterpret_cast<double*>(
+      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);
index 43d4065..4872ab5 100644 (file)
@@ -190,6 +190,7 @@ 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) \
@@ -622,6 +623,7 @@ namespace internal {
   F(OneByteSeqStringSetChar, 3, 1)                                           \
   F(TwoByteSeqStringSetChar, 3, 1)                                           \
   F(ObjectEquals, 2, 1)                                                      \
+  F(RandomHeapNumber, 0, 1)                                                  \
   F(IsObject, 1, 1)                                                          \
   F(IsFunction, 1, 1)                                                        \
   F(IsUndetectableObject, 1, 1)                                              \
index a8df238..36e19c1 100644 (file)
@@ -297,6 +297,10 @@ void ExternalReferenceTable::PopulateTable(Isolate* isolate) {
       RUNTIME_ENTRY,
       1,
       "Runtime::PerformGC");
+  Add(ExternalReference::random_uint32_function(isolate).address(),
+      RUNTIME_ENTRY,
+      3,
+      "V8::Random");
   Add(ExternalReference::delete_handle_scope_extensions(isolate).address(),
       RUNTIME_ENTRY,
       4,
diff --git a/src/trig-table.h b/src/trig-table.h
deleted file mode 100644 (file)
index 081c038..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-// 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<double*>(&kSinTable[0]);
-  }
-
-  static void* cos_x_interval_table() {
-    return const_cast<double*>(&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_
index 0f01818..c56c82a 100644 (file)
--- a/src/v8.cc
+++ b/src/v8.cc
@@ -119,6 +119,25 @@ void V8::SetReturnAddressLocationResolver(
 }
 
 
+// Used by JavaScript APIs
+uint32_t V8::Random(Context* context) {
+  ASSERT(context->IsNativeContext());
+  ByteArray* seed = context->random_seed();
+  uint32_t* state = reinterpret_cast<uint32_t*>(seed->GetDataStartAddress());
+
+  // When we get here, the RNG must have been initialized,
+  // see the Genesis constructor in file bootstrapper.cc.
+  ASSERT_NE(0, state[0]);
+  ASSERT_NE(0, state[1]);
+
+  // Mix the bits.  Never replaces state[i] with 0 if it is nonzero.
+  state[0] = 18273 * (state[0] & 0xFFFF) + (state[0] >> 16);
+  state[1] = 36969 * (state[1] & 0xFFFF) + (state[1] >> 16);
+
+  return (state[0] << 14) + (state[1] & 0x3FFFF);
+}
+
+
 void V8::AddCallCompletedCallback(CallCompletedCallback callback) {
   if (call_completed_callbacks_ == NULL) {  // Lazy init.
     call_completed_callbacks_ = new List<CallCompletedCallback>();
index 8069e8a..6f2633a 100644 (file)
--- a/src/v8.h
+++ b/src/v8.h
@@ -96,6 +96,8 @@ class V8 : public AllStatic {
       ReturnAddressLocationResolver resolver);
   // Support for entry hooking JITed code.
   static void SetFunctionEntryHook(FunctionEntryHook entry_hook);
+  // Random number generation support. Not cryptographically safe.
+  static uint32_t Random(Context* context);
 
   static void AddCallCompletedCallback(CallCompletedCallback callback);
   static void RemoveCallCompletedCallback(CallCompletedCallback callback);
index a62fde0..71b5468 100644 (file)
@@ -3271,6 +3271,47 @@ void FullCodeGenerator::EmitLog(CallRuntime* expr) {
 }
 
 
+void FullCodeGenerator::EmitRandomHeapNumber(CallRuntime* expr) {
+  ASSERT(expr->arguments()->length() == 0);
+
+  Label slow_allocate_heapnumber;
+  Label heapnumber_allocated;
+
+  __ AllocateHeapNumber(rbx, rcx, &slow_allocate_heapnumber);
+  __ jmp(&heapnumber_allocated);
+
+  __ bind(&slow_allocate_heapnumber);
+  // Allocate a heap number.
+  __ CallRuntime(Runtime::kNumberAlloc, 0);
+  __ movq(rbx, rax);
+
+  __ bind(&heapnumber_allocated);
+
+  // Return a random uint32 number in rax.
+  // The fresh HeapNumber is in rbx, which is callee-save on both x64 ABIs.
+  __ PrepareCallCFunction(1);
+  __ movq(arg_reg_1,
+          ContextOperand(context_register(), Context::GLOBAL_OBJECT_INDEX));
+  __ movq(arg_reg_1,
+          FieldOperand(arg_reg_1, GlobalObject::kNativeContextOffset));
+  __ CallCFunction(ExternalReference::random_uint32_function(isolate()), 1);
+
+  // Convert 32 random bits in rax to 0.(32 random bits) in a double
+  // by computing:
+  // ( 1.(20 0s)(32 random bits) x 2^20 ) - (1.0 x 2^20)).
+  __ movl(rcx, Immediate(0x49800000));  // 1.0 x 2^20 as single.
+  __ movd(xmm1, rcx);
+  __ movd(xmm0, rax);
+  __ cvtss2sd(xmm1, xmm1);
+  __ xorps(xmm0, xmm1);
+  __ subsd(xmm0, xmm1);
+  __ movsd(FieldOperand(rbx, HeapNumber::kValueOffset), xmm0);
+
+  __ movq(rax, rbx);
+  context()->Plug(rax);
+}
+
+
 void FullCodeGenerator::EmitSubString(CallRuntime* expr) {
   // Load the arguments on the stack and call the stub.
   SubStringStub stub;
index 241963b..0c95745 100644 (file)
@@ -3698,6 +3698,66 @@ void LCodeGen::DoPower(LPower* instr) {
 }
 
 
+void LCodeGen::DoRandom(LRandom* instr) {
+  // Assert that register size is twice the size of each seed.
+  static const int kSeedSize = sizeof(uint32_t);
+  STATIC_ASSERT(kPointerSize == 2 * kSeedSize);
+
+  // Load native context
+  Register global_object = ToRegister(instr->global_object());
+  Register native_context = global_object;
+  __ movq(native_context, FieldOperand(
+          global_object, GlobalObject::kNativeContextOffset));
+
+  // Load state (FixedArray of the native context's random seeds)
+  static const int kRandomSeedOffset =
+      FixedArray::kHeaderSize + Context::RANDOM_SEED_INDEX * kPointerSize;
+  Register state = native_context;
+  __ movq(state, FieldOperand(native_context, kRandomSeedOffset));
+
+  // Load state[0].
+  Register state0 = ToRegister(instr->scratch());
+  __ movl(state0, FieldOperand(state, ByteArray::kHeaderSize));
+  // Load state[1].
+  Register state1 = ToRegister(instr->scratch2());
+  __ movl(state1, FieldOperand(state, ByteArray::kHeaderSize + kSeedSize));
+
+  // state[0] = 18273 * (state[0] & 0xFFFF) + (state[0] >> 16)
+  Register scratch3 = ToRegister(instr->scratch3());
+  __ movzxwl(scratch3, state0);
+  __ imull(scratch3, scratch3, Immediate(18273));
+  __ shrl(state0, Immediate(16));
+  __ addl(state0, scratch3);
+  // Save state[0].
+  __ movl(FieldOperand(state, ByteArray::kHeaderSize), state0);
+
+  // state[1] = 36969 * (state[1] & 0xFFFF) + (state[1] >> 16)
+  __ movzxwl(scratch3, state1);
+  __ imull(scratch3, scratch3, Immediate(36969));
+  __ shrl(state1, Immediate(16));
+  __ addl(state1, scratch3);
+  // Save state[1].
+  __ movl(FieldOperand(state, ByteArray::kHeaderSize + kSeedSize), state1);
+
+  // Random bit pattern = (state[0] << 14) + (state[1] & 0x3FFFF)
+  Register random = state0;
+  __ shll(random, Immediate(14));
+  __ andl(state1, Immediate(0x3FFFF));
+  __ addl(random, state1);
+
+  // Convert 32 random bits in rax to 0.(32 random bits) in a double
+  // by computing:
+  // ( 1.(20 0s)(32 random bits) x 2^20 ) - (1.0 x 2^20)).
+  XMMRegister result = ToDoubleRegister(instr->result());
+  XMMRegister scratch4 = double_scratch0();
+  __ movq(scratch3, V8_INT64_C(0x4130000000000000));  // 1.0 x 2^20 as double
+  __ movq(scratch4, scratch3);
+  __ movd(result, random);
+  __ xorps(result, scratch4);
+  __ subsd(result, scratch4);
+}
+
+
 void LCodeGen::DoMathExp(LMathExp* instr) {
   XMMRegister input = ToDoubleRegister(instr->value());
   XMMRegister result = ToDoubleRegister(instr->result());
index fa1bdaa..2a73472 100644 (file)
@@ -1601,6 +1601,19 @@ LInstruction* LChunkBuilder::DoPower(HPower* instr) {
 }
 
 
+LInstruction* LChunkBuilder::DoRandom(HRandom* instr) {
+  ASSERT(instr->representation().IsDouble());
+  ASSERT(instr->global_object()->representation().IsTagged());
+  LOperand* global_object = UseTempRegister(instr->global_object());
+  LOperand* scratch = TempRegister();
+  LOperand* scratch2 = TempRegister();
+  LOperand* scratch3 = TempRegister();
+  LRandom* result = new(zone()) LRandom(
+      global_object, scratch, scratch2, scratch3);
+  return DefineFixedDouble(result, xmm1);
+}
+
+
 LInstruction* LChunkBuilder::DoCompareGeneric(HCompareGeneric* instr) {
   ASSERT(instr->left()->representation().IsTagged());
   ASSERT(instr->right()->representation().IsTagged());
index ca7831c..a475d8c 100644 (file)
@@ -153,6 +153,7 @@ class LCodeGen;
   V(Parameter)                                  \
   V(Power)                                      \
   V(PushArgument)                               \
+  V(Random)                                     \
   V(RegExpLiteral)                              \
   V(Return)                                     \
   V(SeqStringGetChar)                           \
@@ -1423,6 +1424,28 @@ class LPower V8_FINAL : public LTemplateInstruction<1, 2, 0> {
 };
 
 
+class LRandom V8_FINAL : public LTemplateInstruction<1, 1, 3> {
+ public:
+  LRandom(LOperand* global_object,
+          LOperand* scratch,
+          LOperand* scratch2,
+          LOperand* scratch3) {
+    inputs_[0] = global_object;
+    temps_[0] = scratch;
+    temps_[1] = scratch2;
+    temps_[2] = scratch3;
+  }
+
+  LOperand* global_object() { return inputs_[0]; }
+  LOperand* scratch() const { return temps_[0]; }
+  LOperand* scratch2() const { return temps_[1]; }
+  LOperand* scratch3() const { return temps_[2]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(Random, "random")
+  DECLARE_HYDROGEN_ACCESSOR(Random)
+};
+
+
 class LArithmeticD V8_FINAL : public LTemplateInstruction<1, 2, 0> {
  public:
   LArithmeticD(Token::Value op, LOperand* left, LOperand* right)
index edfc375..fe1ef04 100644 (file)
@@ -89,7 +89,7 @@ TEST(WeakArrayBuffersFromApi) {
   LocalContext context;
   Isolate* isolate = GetIsolateFrom(&context);
 
-  int start = CountArrayBuffersInWeakList(isolate->heap());
+  CHECK_EQ(0, CountArrayBuffersInWeakList(isolate->heap()));
   {
     v8::HandleScope s1(context->GetIsolate());
     v8::Handle<v8::ArrayBuffer> ab1 = v8::ArrayBuffer::New(256);
@@ -99,12 +99,12 @@ TEST(WeakArrayBuffersFromApi) {
 
       Handle<JSArrayBuffer> iab1 = v8::Utils::OpenHandle(*ab1);
       Handle<JSArrayBuffer> iab2 = v8::Utils::OpenHandle(*ab2);
-      CHECK_EQ(2, CountArrayBuffersInWeakList(isolate->heap()) - start);
+      CHECK_EQ(2, CountArrayBuffersInWeakList(isolate->heap()));
       CHECK(HasArrayBufferInWeakList(isolate->heap(), *iab1));
       CHECK(HasArrayBufferInWeakList(isolate->heap(), *iab2));
     }
     isolate->heap()->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask);
-    CHECK_EQ(1, CountArrayBuffersInWeakList(isolate->heap()) - start);
+    CHECK_EQ(1, CountArrayBuffersInWeakList(isolate->heap()));
     {
       HandleScope scope2(isolate);
       Handle<JSArrayBuffer> iab1 = v8::Utils::OpenHandle(*ab1);
@@ -114,7 +114,7 @@ TEST(WeakArrayBuffersFromApi) {
   }
 
   isolate->heap()->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask);
-  CHECK_EQ(0, CountArrayBuffersInWeakList(isolate->heap()) - start);
+  CHECK_EQ(0, CountArrayBuffersInWeakList(isolate->heap()));
 }
 
 
@@ -122,12 +122,11 @@ TEST(WeakArrayBuffersFromScript) {
   v8::V8::Initialize();
   LocalContext context;
   Isolate* isolate = GetIsolateFrom(&context);
-  int start = CountArrayBuffersInWeakList(isolate->heap());
 
   for (int i = 1; i <= 3; i++) {
     // Create 3 array buffers, make i-th of them garbage,
     // validate correct state of array buffer weak list.
-    CHECK_EQ(0, CountArrayBuffersInWeakList(isolate->heap()) - start);
+    CHECK_EQ(0, CountArrayBuffersInWeakList(isolate->heap()));
     {
       v8::HandleScope scope(context->GetIsolate());
 
@@ -143,7 +142,7 @@ TEST(WeakArrayBuffersFromScript) {
         v8::Handle<v8::ArrayBuffer> ab3 =
             v8::Handle<v8::ArrayBuffer>::Cast(CompileRun("ab3"));
 
-        CHECK_EQ(3, CountArrayBuffersInWeakList(isolate->heap()) - start);
+        CHECK_EQ(3, CountArrayBuffersInWeakList(isolate->heap()));
         CHECK(HasArrayBufferInWeakList(isolate->heap(),
               *v8::Utils::OpenHandle(*ab1)));
         CHECK(HasArrayBufferInWeakList(isolate->heap(),
@@ -157,7 +156,7 @@ TEST(WeakArrayBuffersFromScript) {
       CompileRun(source.start());
       isolate->heap()->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask);
 
-      CHECK_EQ(2, CountArrayBuffersInWeakList(isolate->heap()) - start);
+      CHECK_EQ(2, CountArrayBuffersInWeakList(isolate->heap()));
 
       {
         v8::HandleScope s2(context->GetIsolate());
@@ -175,7 +174,7 @@ TEST(WeakArrayBuffersFromScript) {
     }
 
     isolate->heap()->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask);
-    CHECK_EQ(0, CountArrayBuffersInWeakList(isolate->heap()) - start);
+    CHECK_EQ(0, CountArrayBuffersInWeakList(isolate->heap()));
   }
 }
 
@@ -267,7 +266,6 @@ static void TestTypedArrayFromScript(const char* constructor) {
   LocalContext context;
   Isolate* isolate = GetIsolateFrom(&context);
   v8::HandleScope scope(context->GetIsolate());
-  int start = CountArrayBuffersInWeakList(isolate->heap());
   CompileRun("var ab = new ArrayBuffer(2048);");
   for (int i = 1; i <= 3; i++) {
     // Create 3 typed arrays, make i-th of them garbage,
@@ -275,7 +273,7 @@ static void TestTypedArrayFromScript(const char* constructor) {
     v8::HandleScope s0(context->GetIsolate());
     i::ScopedVector<char> source(2048);
 
-    CHECK_EQ(1, CountArrayBuffersInWeakList(isolate->heap()) - start);
+    CHECK_EQ(1, CountArrayBuffersInWeakList(isolate->heap()));
 
     {
       v8::HandleScope s1(context->GetIsolate());
@@ -294,7 +292,7 @@ static void TestTypedArrayFromScript(const char* constructor) {
           v8::Handle<TypedArray>::Cast(CompileRun("ta2"));
       v8::Handle<TypedArray> ta3 =
           v8::Handle<TypedArray>::Cast(CompileRun("ta3"));
-      CHECK_EQ(1, CountArrayBuffersInWeakList(isolate->heap()) - start);
+      CHECK_EQ(1, CountArrayBuffersInWeakList(isolate->heap()));
       Handle<JSArrayBuffer> iab = v8::Utils::OpenHandle(*ab);
       CHECK_EQ(3, CountViews(*iab));
       CHECK(HasViewInWeakList(*iab, *v8::Utils::OpenHandle(*ta1)));
@@ -306,7 +304,7 @@ static void TestTypedArrayFromScript(const char* constructor) {
     CompileRun(source.start());
     isolate->heap()->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask);
 
-    CHECK_EQ(1, CountArrayBuffersInWeakList(isolate->heap()) - start);
+    CHECK_EQ(1, CountArrayBuffersInWeakList(isolate->heap()));
 
     {
       v8::HandleScope s2(context->GetIsolate());
@@ -326,7 +324,7 @@ static void TestTypedArrayFromScript(const char* constructor) {
     CompileRun("ta1 = null; ta2 = null; ta3 = null;");
     isolate->heap()->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask);
 
-    CHECK_EQ(1, CountArrayBuffersInWeakList(isolate->heap()) - start);
+    CHECK_EQ(1, CountArrayBuffersInWeakList(isolate->heap()));
 
     {
       v8::HandleScope s3(context->GetIsolate());
diff --git a/tools/generate-trig-table.py b/tools/generate-trig-table.py
deleted file mode 100644 (file)
index 14d4472..0000000
+++ /dev/null
@@ -1,84 +0,0 @@
-#!/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()
-
index 65d5fb8..b1b9019 100644 (file)
       'sources': [
         '<(SHARED_INTERMEDIATE_DIR)/libraries.cc',
         '<(SHARED_INTERMEDIATE_DIR)/experimental-libraries.cc',
-        '<(SHARED_INTERMEDIATE_DIR)/trig-table.cc',
         '<(INTERMEDIATE_DIR)/snapshot.cc',
       ],
       'actions': [
       'sources': [
         '<(SHARED_INTERMEDIATE_DIR)/libraries.cc',
         '<(SHARED_INTERMEDIATE_DIR)/experimental-libraries.cc',
-        '<(SHARED_INTERMEDIATE_DIR)/trig-table.cc',
         '../../src/snapshot-empty.cc',
       ],
       'conditions': [
         }],
       ]
     },
-    { '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',
       },