| Index: src/runtime/runtime-maths.cc
|
| diff --git a/src/runtime/runtime-maths.cc b/src/runtime/runtime-maths.cc
|
| index 47e560d022a4189275604c710bfd5bc5a87ad2bc..404305a150592ee07a8684e1bb55f290f7cea2b5 100644
|
| --- a/src/runtime/runtime-maths.cc
|
| +++ b/src/runtime/runtime-maths.cc
|
| @@ -15,58 +15,49 @@ namespace internal {
|
|
|
| RUNTIME_FUNCTION(Runtime_GenerateRandomNumbers) {
|
| HandleScope scope(isolate);
|
| - DCHECK(args.length() == 1);
|
| - if (isolate->serializer_enabled()) {
|
| - // Random numbers in the snapshot are not really that random. And we cannot
|
| - // return a typed array as it cannot be serialized. To make calling
|
| - // Math.random possible when creating a custom startup snapshot, we simply
|
| - // return a normal array with a single random number.
|
| - Handle<HeapNumber> random_number = isolate->factory()->NewHeapNumber(
|
| - isolate->random_number_generator()->NextDouble());
|
| - Handle<FixedArray> array_backing = isolate->factory()->NewFixedArray(1);
|
| - array_backing->set(0, *random_number);
|
| - return *isolate->factory()->NewJSArrayWithElements(array_backing);
|
| - }
|
| + DCHECK(args.length() == 0);
|
| +
|
| + Handle<Context> native_context = isolate->native_context();
|
| + DCHECK_EQ(0, native_context->math_random_index()->value());
|
| +
|
| + static const int kCacheSize = 64;
|
| + static const int kState0Offset = kCacheSize - 1;
|
| + static const int kState1Offset = kState0Offset - 1;
|
| + // The index is decremented before used to access the cache.
|
| + static const int kInitialIndex = kState1Offset;
|
|
|
| - 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);
|
| + Handle<FixedDoubleArray> cache;
|
| + uint64_t state0 = 0;
|
| + uint64_t state1 = 0;
|
| + if (native_context->math_random_cache()->IsFixedDoubleArray()) {
|
| + cache = Handle<FixedDoubleArray>(
|
| + FixedDoubleArray::cast(native_context->math_random_cache()), isolate);
|
| + state0 = double_to_uint64(cache->get_scalar(kState0Offset));
|
| + state1 = double_to_uint64(cache->get_scalar(kState1Offset));
|
| } 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);
|
| + cache = Handle<FixedDoubleArray>::cast(
|
| + isolate->factory()->NewFixedDoubleArray(kCacheSize, TENURED));
|
| + native_context->set_math_random_cache(*cache);
|
| + // 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));
|
| + }
|
| }
|
|
|
| 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));
|
| - }
|
| + FixedDoubleArray* raw_cache = *cache;
|
| // Create random numbers.
|
| - for (int i = kState1Offset + 1; i < kRandomBatchSize; i++) {
|
| + for (int i = 0; i < kInitialIndex; i++) {
|
| // Generate random numbers using xorshift128+.
|
| base::RandomNumberGenerator::XorShift128(&state0, &state1);
|
| - array[i] = base::RandomNumberGenerator::ToDouble(state0, state1);
|
| + raw_cache->set(i, base::RandomNumberGenerator::ToDouble(state0, state1));
|
| }
|
| +
|
| // Persist current state.
|
| - array[kState0Offset] = uint64_to_double(state0);
|
| - array[kState1Offset] = uint64_to_double(state1);
|
| - return *typed_array;
|
| + raw_cache->set(kState0Offset, uint64_to_double(state0));
|
| + raw_cache->set(kState1Offset, uint64_to_double(state1));
|
| + return Smi::FromInt(kInitialIndex);
|
| }
|
| } // namespace internal
|
| } // namespace v8
|
|
|