Home | History | Annotate | Download | only in runtime
      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 
     16 namespace v8 {
     17 namespace internal {
     18 
     19 RUNTIME_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