Commit 9b152fda authored by skyostil's avatar skyostil Committed by Commit bot

Enable deterministic random number generation

This patch makes Math.random() behave deterministically when a fixed
random seed is provided. This is done by re-seeding the random number
generator the first time a script requests a random number. Doing this
ensures Math.random() returns the same sequence across page loads and
across iframes.

BUG=chromium:696001

Review-Url: https://codereview.chromium.org/2760393002
Cr-Commit-Position: refs/heads/master@{#44076}
parent fb52f5c5
...@@ -41,10 +41,18 @@ RUNTIME_FUNCTION(Runtime_GenerateRandomNumbers) { ...@@ -41,10 +41,18 @@ RUNTIME_FUNCTION(Runtime_GenerateRandomNumbers) {
cache = Handle<FixedDoubleArray>::cast( cache = Handle<FixedDoubleArray>::cast(
isolate->factory()->NewFixedDoubleArray(kCacheSize, TENURED)); isolate->factory()->NewFixedDoubleArray(kCacheSize, TENURED));
native_context->set_math_random_cache(*cache); native_context->set_math_random_cache(*cache);
// Initialize state if not yet initialized. // Initialize state if not yet initialized. If a fixed random seed was
while (state0 == 0 || state1 == 0) { // requested, use it to reset our state the first time a script asks for
isolate->random_number_generator()->NextBytes(&state0, sizeof(state0)); // random numbers in this context. This ensures the script sees a consistent
isolate->random_number_generator()->NextBytes(&state1, sizeof(state1)); // sequence.
if (FLAG_random_seed != 0) {
state0 = FLAG_random_seed;
state1 = FLAG_random_seed;
} else {
while (state0 == 0 || state1 == 0) {
isolate->random_number_generator()->NextBytes(&state0, sizeof(state0));
isolate->random_number_generator()->NextBytes(&state1, sizeof(state1));
}
} }
} }
......
...@@ -26369,3 +26369,28 @@ UNINITIALIZED_TEST(IncreaseHeapLimitForDebugging) { ...@@ -26369,3 +26369,28 @@ UNINITIALIZED_TEST(IncreaseHeapLimitForDebugging) {
} }
isolate->Dispose(); isolate->Dispose();
} }
TEST(DeterministicRandomNumberGeneration) {
v8::HandleScope scope(CcTest::isolate());
int previous_seed = v8::internal::FLAG_random_seed;
v8::internal::FLAG_random_seed = 1234;
double first_value;
double second_value;
{
v8::Local<Context> context = Context::New(CcTest::isolate());
Context::Scope context_scope(context);
v8::Local<Value> result = CompileRun("Math.random();");
first_value = result->ToNumber(context).ToLocalChecked()->Value();
}
{
v8::Local<Context> context = Context::New(CcTest::isolate());
Context::Scope context_scope(context);
v8::Local<Value> result = CompileRun("Math.random();");
second_value = result->ToNumber(context).ToLocalChecked()->Value();
}
CHECK_EQ(first_value, second_value);
v8::internal::FLAG_random_seed = previous_seed;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment