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) {
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));
// Initialize state if not yet initialized. If a fixed random seed was
// requested, use it to reset our state the first time a script asks for
// random numbers in this context. This ensures the script sees a consistent
// 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) {
}
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