| 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
|
|
|