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 =
20 : Handle<FixedDoubleArray>::cast(isolate->factory()->NewFixedDoubleArray(
21 111 : kCacheSize, AllocationType::kOld));
22 14319 : for (int i = 0; i < kCacheSize; i++) cache->set(i, 0);
23 111 : native_context->set_math_random_cache(*cache);
24 : Handle<PodArray<State>> pod =
25 : PodArray<State>::New(isolate, 1, AllocationType::kOld);
26 222 : native_context->set_math_random_state(*pod);
27 111 : ResetContext(*native_context);
28 111 : }
29 :
30 352 : void MathRandom::ResetContext(Context native_context) {
31 352 : native_context->set_math_random_index(Smi::zero());
32 352 : State state = {0, 0};
33 704 : PodArray<State>::cast(native_context->math_random_state())->set(0, state);
34 352 : }
35 :
36 60697 : Address MathRandom::RefillCache(Isolate* isolate, Address raw_native_context) {
37 60697 : Context native_context = Context::cast(Object(raw_native_context));
38 : DisallowHeapAllocation no_gc;
39 : PodArray<State> pod =
40 60697 : PodArray<State>::cast(native_context->math_random_state());
41 60697 : State state = pod->get(0);
42 : // Initialize state if not yet initialized. If a fixed random seed was
43 : // requested, use it to reset our state the first time a script asks for
44 : // random numbers in this context. This ensures the script sees a consistent
45 : // sequence.
46 60697 : if (state.s0 == 0 && state.s1 == 0) {
47 : uint64_t seed;
48 183 : if (FLAG_random_seed != 0) {
49 183 : seed = FLAG_random_seed;
50 : } else {
51 0 : isolate->random_number_generator()->NextBytes(&seed, sizeof(seed));
52 : }
53 183 : state.s0 = base::RandomNumberGenerator::MurmurHash3(seed);
54 183 : state.s1 = base::RandomNumberGenerator::MurmurHash3(~seed);
55 183 : CHECK(state.s0 != 0 || state.s1 != 0);
56 : }
57 :
58 : FixedDoubleArray cache =
59 60697 : FixedDoubleArray::cast(native_context->math_random_cache());
60 : // Create random numbers.
61 7829913 : for (int i = 0; i < kCacheSize; i++) {
62 : // Generate random numbers using xorshift128+.
63 : base::RandomNumberGenerator::XorShift128(&state.s0, &state.s1);
64 3884608 : cache->set(i, base::RandomNumberGenerator::ToDouble(state.s0));
65 : }
66 : pod->set(0, state);
67 :
68 : Smi new_index = Smi::FromInt(kCacheSize);
69 60697 : native_context->set_math_random_index(new_index);
70 60697 : return new_index.ptr();
71 : }
72 :
73 : } // namespace internal
74 122036 : } // namespace v8
|