runtime-maths.cc 2.62 KB
Newer Older
1 2 3 4
// 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.

5
#include "src/runtime/runtime-utils.h"
6 7 8

#include "src/arguments.h"
#include "src/assembler.h"
9
#include "src/base/utils/random-number-generator.h"
10
#include "src/bootstrapper.h"
11 12 13
#include "src/counters.h"
#include "src/double.h"
#include "src/objects-inl.h"
14 15 16 17

namespace v8 {
namespace internal {

18
RUNTIME_FUNCTION(Runtime_GenerateRandomNumbers) {
19
  HandleScope scope(isolate);
20
  DCHECK_EQ(0, args.length());
21 22 23 24 25 26 27 28 29

  Handle<Context> native_context = isolate->native_context();
  DCHECK_EQ(0, native_context->math_random_index()->value());

  static const int kCacheSize = 64;
  static const int kState0Offset = kCacheSize - 1;
  static const int kState1Offset = kState0Offset - 1;
  // The index is decremented before used to access the cache.
  static const int kInitialIndex = kState1Offset;
30

31 32 33 34 35 36 37 38
  Handle<FixedDoubleArray> cache;
  uint64_t state0 = 0;
  uint64_t state1 = 0;
  if (native_context->math_random_cache()->IsFixedDoubleArray()) {
    cache = Handle<FixedDoubleArray>(
        FixedDoubleArray::cast(native_context->math_random_cache()), isolate);
    state0 = double_to_uint64(cache->get_scalar(kState0Offset));
    state1 = double_to_uint64(cache->get_scalar(kState1Offset));
39
  } else {
40 41 42
    cache = Handle<FixedDoubleArray>::cast(
        isolate->factory()->NewFixedDoubleArray(kCacheSize, TENURED));
    native_context->set_math_random_cache(*cache);
43 44 45 46 47 48 49 50 51 52 53 54
    // Initialize state if not yet initialized. If a fixed random seed was
    // requested, use it to reset our state the first time a script asks for
    // random numbers in this context. This ensures the script sees a consistent
    // sequence.
    if (FLAG_random_seed != 0) {
      state0 = FLAG_random_seed;
      state1 = FLAG_random_seed;
    } else {
      while (state0 == 0 || state1 == 0) {
        isolate->random_number_generator()->NextBytes(&state0, sizeof(state0));
        isolate->random_number_generator()->NextBytes(&state1, sizeof(state1));
      }
55
    }
56 57 58
  }

  DisallowHeapAllocation no_gc;
59
  FixedDoubleArray* raw_cache = *cache;
60
  // Create random numbers.
61
  for (int i = 0; i < kInitialIndex; i++) {
62 63
    // Generate random numbers using xorshift128+.
    base::RandomNumberGenerator::XorShift128(&state0, &state1);
64
    raw_cache->set(i, base::RandomNumberGenerator::ToDouble(state0, state1));
65
  }
66

67
  // Persist current state.
68 69 70
  raw_cache->set(kState0Offset, uint64_to_double(state0));
  raw_cache->set(kState1Offset, uint64_to_double(state1));
  return Smi::FromInt(kInitialIndex);
71
}
72 73
}  // namespace internal
}  // namespace v8