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 |