1958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// Copyright 2014 the V8 project authors. All rights reserved.
2958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// Use of this source code is governed by a BSD-style license that can be
3958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// found in the LICENSE file.
4958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
5014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/runtime/runtime-utils.h"
6958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
7958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#include "src/arguments.h"
8958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#include "src/assembler.h"
9014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/base/utils/random-number-generator.h"
10014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/bootstrapper.h"
11958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#include "src/codegen.h"
1262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#include "src/counters.h"
1362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#include "src/double.h"
1462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#include "src/objects-inl.h"
15958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
16958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniernamespace v8 {
17958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniernamespace internal {
18958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
193b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben MurdochRUNTIME_FUNCTION(Runtime_GenerateRandomNumbers) {
20958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  HandleScope scope(isolate);
2162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK_EQ(0, args.length());
22c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
23c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  Handle<Context> native_context = isolate->native_context();
24c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  DCHECK_EQ(0, native_context->math_random_index()->value());
25c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
26c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  static const int kCacheSize = 64;
27c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  static const int kState0Offset = kCacheSize - 1;
28c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  static const int kState1Offset = kState0Offset - 1;
29c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  // The index is decremented before used to access the cache.
30c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  static const int kInitialIndex = kState1Offset;
31958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
32c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  Handle<FixedDoubleArray> cache;
33c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  uint64_t state0 = 0;
34c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  uint64_t state1 = 0;
35c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  if (native_context->math_random_cache()->IsFixedDoubleArray()) {
36c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    cache = Handle<FixedDoubleArray>(
37c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        FixedDoubleArray::cast(native_context->math_random_cache()), isolate);
38c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    state0 = double_to_uint64(cache->get_scalar(kState0Offset));
39c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    state1 = double_to_uint64(cache->get_scalar(kState1Offset));
40014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
41c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    cache = Handle<FixedDoubleArray>::cast(
42c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        isolate->factory()->NewFixedDoubleArray(kCacheSize, TENURED));
43c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    native_context->set_math_random_cache(*cache);
44c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    // Initialize state if not yet initialized.
45c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    while (state0 == 0 || state1 == 0) {
46c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      isolate->random_number_generator()->NextBytes(&state0, sizeof(state0));
47c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      isolate->random_number_generator()->NextBytes(&state1, sizeof(state1));
48c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    }
49014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
50014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
51014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DisallowHeapAllocation no_gc;
52c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  FixedDoubleArray* raw_cache = *cache;
53014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Create random numbers.
54c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  for (int i = 0; i < kInitialIndex; i++) {
55014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Generate random numbers using xorshift128+.
56014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    base::RandomNumberGenerator::XorShift128(&state0, &state1);
57c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    raw_cache->set(i, base::RandomNumberGenerator::ToDouble(state0, state1));
58014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
59c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
60014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Persist current state.
61c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  raw_cache->set(kState0Offset, uint64_to_double(state0));
62c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  raw_cache->set(kState1Offset, uint64_to_double(state1));
63c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  return Smi::FromInt(kInitialIndex);
64958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
65014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace internal
66014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace v8
67