Line data Source code
1 : // Copyright 2018 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/math-random.h"
6 :
7 : #include "src/assert-scope.h"
8 : #include "src/base/utils/random-number-generator.h"
9 : #include "src/contexts-inl.h"
10 : #include "src/isolate.h"
11 : #include "src/objects/fixed-array.h"
12 : #include "src/objects/smi.h"
13 :
14 : namespace v8 {
15 : namespace internal {
16 :
17 111 : void MathRandom::InitializeContext(Isolate* isolate,
18 : Handle<Context> native_context) {
19 : Handle<FixedDoubleArray> cache = Handle<FixedDoubleArray>::cast(
20 111 : isolate->factory()->NewFixedDoubleArray(kCacheSize, TENURED));
21 7215 : for (int i = 0; i < kCacheSize; i++) cache->set(i, 0);
22 111 : native_context->set_math_random_cache(*cache);
23 111 : Handle<PodArray<State>> pod = PodArray<State>::New(isolate, 1, TENURED);
24 222 : native_context->set_math_random_state(*pod);
25 111 : ResetContext(*native_context);
26 111 : }
27 :
28 342 : void MathRandom::ResetContext(Context native_context) {
29 342 : native_context->set_math_random_index(Smi::zero());
30 342 : State state = {0, 0};
31 684 : PodArray<State>::cast(native_context->math_random_state())->set(0, state);
32 342 : }
33 :
34 62903 : Address MathRandom::RefillCache(Isolate* isolate, Address raw_native_context) {
35 62903 : Context native_context = Context::cast(Object(raw_native_context));
36 : DisallowHeapAllocation no_gc;
37 : PodArray<State> pod =
38 125806 : PodArray<State>::cast(native_context->math_random_state());
39 62903 : State state = pod->get(0);
40 : // Initialize state if not yet initialized. If a fixed random seed was
41 : // requested, use it to reset our state the first time a script asks for
42 : // random numbers in this context. This ensures the script sees a consistent
43 : // sequence.
44 62903 : if (state.s0 == 0 && state.s1 == 0) {
45 : uint64_t seed;
46 174 : if (FLAG_random_seed != 0) {
47 174 : seed = FLAG_random_seed;
48 : } else {
49 0 : isolate->random_number_generator()->NextBytes(&seed, sizeof(seed));
50 : }
51 174 : state.s0 = base::RandomNumberGenerator::MurmurHash3(seed);
52 174 : state.s1 = base::RandomNumberGenerator::MurmurHash3(~seed);
53 174 : CHECK(state.s0 != 0 || state.s1 != 0);
54 : }
55 :
56 : FixedDoubleArray cache =
57 125806 : FixedDoubleArray::cast(native_context->math_random_cache());
58 : // Create random numbers.
59 4088695 : for (int i = 0; i < kCacheSize; i++) {
60 : // Generate random numbers using xorshift128+.
61 : base::RandomNumberGenerator::XorShift128(&state.s0, &state.s1);
62 : cache->set(i, base::RandomNumberGenerator::ToDouble(state.s0));
63 : }
64 : pod->set(0, state);
65 :
66 : Smi new_index = Smi::FromInt(kCacheSize);
67 62903 : native_context->set_math_random_index(new_index);
68 62903 : return new_index.ptr();
69 : }
70 :
71 : } // namespace internal
72 183867 : } // namespace v8
|