Index: src/runtime/runtime-maths.cc |
diff --git a/src/runtime/runtime-maths.cc b/src/runtime/runtime-maths.cc |
index 70c587d7454b401fbfe9f2fc61812b039a6a0531..3d8c8aef7ef2d8f609ebc09c91f1c2b695226a73 100644 |
--- a/src/runtime/runtime-maths.cc |
+++ b/src/runtime/runtime-maths.cc |
@@ -7,6 +7,7 @@ |
#include "src/arguments.h" |
#include "src/assembler.h" |
#include "src/base/utils/random-number-generator.h" |
+#include "src/bootstrapper.h" |
#include "src/codegen.h" |
#include "src/third_party/fdlibm/fdlibm.h" |
@@ -247,18 +248,50 @@ RUNTIME_FUNCTION(Runtime_IsMinusZero) { |
} |
-RUNTIME_FUNCTION(Runtime_InitializeRNG) { |
+RUNTIME_FUNCTION(Runtime_GenerateRandomNumbers) { |
HandleScope scope(isolate); |
- DCHECK(args.length() == 0); |
- static const int kSize = 4; |
- Handle<FixedArray> array = isolate->factory()->NewFixedArray(kSize); |
- uint16_t seeds[kSize]; |
- do { |
- isolate->random_number_generator()->NextBytes(seeds, |
- kSize * sizeof(*seeds)); |
- } while (!(seeds[0] && seeds[1] && seeds[2] && seeds[3])); |
- for (int i = 0; i < kSize; i++) array->set(i, Smi::FromInt(seeds[i])); |
- return *isolate->factory()->NewJSArrayWithElements(array); |
+ DCHECK(args.length() == 1); |
+ // Random numbers in the snapshot are not really that random. |
+ DCHECK(!isolate->bootstrapper()->IsActive()); |
+ static const int kState0Offset = 0; |
+ static const int kState1Offset = 1; |
+ static const int kRandomBatchSize = 64; |
+ CONVERT_ARG_HANDLE_CHECKED(Object, maybe_typed_array, 0); |
+ Handle<JSTypedArray> typed_array; |
+ // Allocate typed array if it does not yet exist. |
+ if (maybe_typed_array->IsJSTypedArray()) { |
+ typed_array = Handle<JSTypedArray>::cast(maybe_typed_array); |
+ } else { |
+ static const int kByteLength = kRandomBatchSize * kDoubleSize; |
+ Handle<JSArrayBuffer> buffer = |
+ isolate->factory()->NewJSArrayBuffer(SharedFlag::kNotShared, TENURED); |
+ JSArrayBuffer::SetupAllocatingData(buffer, isolate, kByteLength, true, |
+ SharedFlag::kNotShared); |
+ typed_array = isolate->factory()->NewJSTypedArray( |
+ kExternalFloat64Array, buffer, 0, kRandomBatchSize); |
+ } |
+ |
+ DisallowHeapAllocation no_gc; |
+ double* array = |
+ reinterpret_cast<double*>(typed_array->GetBuffer()->backing_store()); |
+ // Fetch existing state. |
+ uint64_t state0 = double_to_uint64(array[kState0Offset]); |
+ uint64_t state1 = double_to_uint64(array[kState1Offset]); |
+ // Initialize state if not yet initialized. |
+ while (state0 == 0 || state1 == 0) { |
+ isolate->random_number_generator()->NextBytes(&state0, sizeof(state0)); |
+ isolate->random_number_generator()->NextBytes(&state1, sizeof(state1)); |
+ } |
+ // Create random numbers. |
+ for (int i = kState1Offset + 1; i < kRandomBatchSize; i++) { |
+ // Generate random numbers using xorshift128+. |
+ base::RandomNumberGenerator::XorShift128(&state0, &state1); |
+ array[i] = base::RandomNumberGenerator::ToDouble(state0, state1); |
+ } |
+ // Persist current state. |
+ array[kState0Offset] = uint64_to_double(state0); |
+ array[kState1Offset] = uint64_to_double(state1); |
+ return *typed_array; |
} |
} // namespace internal |
} // namespace v8 |