1// Copyright 2014 the V8 project authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "src/runtime/runtime-utils.h" 6 7#include "src/arguments.h" 8#include "src/assembler.h" 9#include "src/base/utils/random-number-generator.h" 10#include "src/bootstrapper.h" 11#include "src/codegen.h" 12#include "src/counters.h" 13#include "src/double.h" 14#include "src/objects-inl.h" 15 16namespace v8 { 17namespace internal { 18 19RUNTIME_FUNCTION(Runtime_GenerateRandomNumbers) { 20 HandleScope scope(isolate); 21 DCHECK_EQ(0, args.length()); 22 23 Handle<Context> native_context = isolate->native_context(); 24 DCHECK_EQ(0, native_context->math_random_index()->value()); 25 26 static const int kCacheSize = 64; 27 static const int kState0Offset = kCacheSize - 1; 28 static const int kState1Offset = kState0Offset - 1; 29 // The index is decremented before used to access the cache. 30 static const int kInitialIndex = kState1Offset; 31 32 Handle<FixedDoubleArray> cache; 33 uint64_t state0 = 0; 34 uint64_t state1 = 0; 35 if (native_context->math_random_cache()->IsFixedDoubleArray()) { 36 cache = Handle<FixedDoubleArray>( 37 FixedDoubleArray::cast(native_context->math_random_cache()), isolate); 38 state0 = double_to_uint64(cache->get_scalar(kState0Offset)); 39 state1 = double_to_uint64(cache->get_scalar(kState1Offset)); 40 } else { 41 cache = Handle<FixedDoubleArray>::cast( 42 isolate->factory()->NewFixedDoubleArray(kCacheSize, TENURED)); 43 native_context->set_math_random_cache(*cache); 44 // Initialize state if not yet initialized. 45 while (state0 == 0 || state1 == 0) { 46 isolate->random_number_generator()->NextBytes(&state0, sizeof(state0)); 47 isolate->random_number_generator()->NextBytes(&state1, sizeof(state1)); 48 } 49 } 50 51 DisallowHeapAllocation no_gc; 52 FixedDoubleArray* raw_cache = *cache; 53 // Create random numbers. 54 for (int i = 0; i < kInitialIndex; i++) { 55 // Generate random numbers using xorshift128+. 56 base::RandomNumberGenerator::XorShift128(&state0, &state1); 57 raw_cache->set(i, base::RandomNumberGenerator::ToDouble(state0, state1)); 58 } 59 60 // Persist current state. 61 raw_cache->set(kState0Offset, uint64_to_double(state0)); 62 raw_cache->set(kState1Offset, uint64_to_double(state1)); 63 return Smi::FromInt(kInitialIndex); 64} 65} // namespace internal 66} // namespace v8 67