Line data Source code
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 1090560 : RUNTIME_FUNCTION(Runtime_GenerateRandomNumbers) {
20 545280 : HandleScope scope(isolate);
21 : DCHECK_EQ(0, args.length());
22 :
23 545280 : 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 545280 : uint64_t state0 = 0;
34 545280 : uint64_t state1 = 0;
35 1090560 : if (native_context->math_random_cache()->IsFixedDoubleArray()) {
36 : cache = Handle<FixedDoubleArray>(
37 544002 : FixedDoubleArray::cast(native_context->math_random_cache()), isolate);
38 544002 : state0 = double_to_uint64(cache->get_scalar(kState0Offset));
39 544002 : state1 = double_to_uint64(cache->get_scalar(kState1Offset));
40 : } else {
41 : cache = Handle<FixedDoubleArray>::cast(
42 1278 : isolate->factory()->NewFixedDoubleArray(kCacheSize, TENURED));
43 1278 : native_context->set_math_random_cache(*cache);
44 : // Initialize state if not yet initialized. If a fixed random seed was
45 : // requested, use it to reset our state the first time a script asks for
46 : // random numbers in this context. This ensures the script sees a consistent
47 : // sequence.
48 1278 : if (FLAG_random_seed != 0) {
49 1278 : state0 = FLAG_random_seed;
50 1278 : state1 = FLAG_random_seed;
51 : } else {
52 0 : while (state0 == 0 || state1 == 0) {
53 0 : isolate->random_number_generator()->NextBytes(&state0, sizeof(state0));
54 0 : isolate->random_number_generator()->NextBytes(&state1, sizeof(state1));
55 : }
56 : }
57 : }
58 :
59 : DisallowHeapAllocation no_gc;
60 : FixedDoubleArray* raw_cache = *cache;
61 : // Create random numbers.
62 33807360 : for (int i = 0; i < kInitialIndex; i++) {
63 : // Generate random numbers using xorshift128+.
64 33807360 : base::RandomNumberGenerator::XorShift128(&state0, &state1);
65 33807360 : raw_cache->set(i, base::RandomNumberGenerator::ToDouble(state0, state1));
66 : }
67 :
68 : // Persist current state.
69 545280 : raw_cache->set(kState0Offset, uint64_to_double(state0));
70 545280 : raw_cache->set(kState1Offset, uint64_to_double(state1));
71 545280 : return Smi::FromInt(kInitialIndex);
72 : }
73 : } // namespace internal
74 : } // namespace v8
|