Reland "Do not use FixedDoubleArray to store RNG state"
This is a reland of 33fa357b6f
TBR=mvstanton@chromium.org
Original change's description:
> Do not use FixedDoubleArray to store RNG state
>
> Also:
> - replace runtime call with cheaper C call
> - change state to double conversion
>
> R=mvstanton@chromium.org
>
> Bug: v8:8212
> Cq-Include-Trybots: luci.chromium.try:linux_chromium_rel_ng
> Change-Id: If4bfe0f5fb1864c89f4acd871cb8b74c7cd7ab09
> Reviewed-on: https://chromium-review.googlesource.com/1240116
> Commit-Queue: Yang Guo <yangguo@chromium.org>
> Reviewed-by: Michael Stanton <mvstanton@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#56165}
Bug: v8:8212
Change-Id: Iccc9128034ce7b65801a04a54982219b5a4fe84e
Cq-Include-Trybots: luci.chromium.try:linux_chromium_rel_ng
Reviewed-on: https://chromium-review.googlesource.com/1238551
Reviewed-by: Yang Guo <yangguo@chromium.org>
Commit-Queue: Yang Guo <yangguo@chromium.org>
Cr-Commit-Position: refs/heads/master@{#56175}
This commit is contained in:
parent
62af397b72
commit
ac66c97cfd
3
BUILD.gn
3
BUILD.gn
@ -2164,6 +2164,8 @@ v8_source_set("v8_base") {
|
||||
"src/macro-assembler.h",
|
||||
"src/map-updater.cc",
|
||||
"src/map-updater.h",
|
||||
"src/math-random.cc",
|
||||
"src/math-random.h",
|
||||
"src/maybe-handles-inl.h",
|
||||
"src/maybe-handles.h",
|
||||
"src/messages.cc",
|
||||
@ -2404,7 +2406,6 @@ v8_source_set("v8_base") {
|
||||
"src/runtime/runtime-interpreter.cc",
|
||||
"src/runtime/runtime-intl.cc",
|
||||
"src/runtime/runtime-literals.cc",
|
||||
"src/runtime/runtime-maths.cc",
|
||||
"src/runtime/runtime-module.cc",
|
||||
"src/runtime/runtime-numbers.cc",
|
||||
"src/runtime/runtime-object.cc",
|
||||
|
@ -99,7 +99,7 @@ int RandomNumberGenerator::NextInt(int max) {
|
||||
|
||||
double RandomNumberGenerator::NextDouble() {
|
||||
XorShift128(&state0_, &state1_);
|
||||
return ToDouble(state0_, state1_);
|
||||
return ToDouble(state0_);
|
||||
}
|
||||
|
||||
|
||||
|
@ -108,11 +108,10 @@ class V8_BASE_EXPORT RandomNumberGenerator final {
|
||||
int64_t initial_seed() const { return initial_seed_; }
|
||||
|
||||
// Static and exposed for external use.
|
||||
static inline double ToDouble(uint64_t state0, uint64_t state1) {
|
||||
static inline double ToDouble(uint64_t state0) {
|
||||
// Exponent for double values for [1.0 .. 2.0)
|
||||
static const uint64_t kExponentBits = uint64_t{0x3FF0000000000000};
|
||||
static const uint64_t kMantissaMask = uint64_t{0x000FFFFFFFFFFFFF};
|
||||
uint64_t random = ((state0 + state1) & kMantissaMask) | kExponentBits;
|
||||
uint64_t random = (state0 >> 12) | kExponentBits;
|
||||
return bit_cast<double>(random) - 1;
|
||||
}
|
||||
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "src/extensions/trigger-failure-extension.h"
|
||||
#include "src/heap/heap.h"
|
||||
#include "src/isolate-inl.h"
|
||||
#include "src/math-random.h"
|
||||
#include "src/objects/api-callbacks.h"
|
||||
#include "src/objects/arguments.h"
|
||||
#include "src/objects/hash-table-inl.h"
|
||||
@ -5769,6 +5770,7 @@ Genesis::Genesis(
|
||||
DCHECK_EQ(0u, context_snapshot_index);
|
||||
// We get here if there was no context snapshot.
|
||||
CreateRoots();
|
||||
MathRandom::InitializeContext(isolate, native_context());
|
||||
Handle<JSFunction> empty_function = CreateEmptyFunction();
|
||||
CreateSloppyModeFunctionMaps(empty_function);
|
||||
CreateStrictModeFunctionMaps(empty_function);
|
||||
|
@ -413,7 +413,16 @@ TF_BUILTIN(MathRandom, CodeStubAssembler) {
|
||||
GotoIf(SmiAbove(smi_index.value(), SmiConstant(0)), &if_cached);
|
||||
|
||||
// Cache exhausted, populate the cache. Return value is the new index.
|
||||
smi_index = CAST(CallRuntime(Runtime::kGenerateRandomNumbers, context));
|
||||
Node* const refill_math_random =
|
||||
ExternalConstant(ExternalReference::refill_math_random());
|
||||
Node* const isolate_ptr =
|
||||
ExternalConstant(ExternalReference::isolate_address(isolate()));
|
||||
MachineType type_tagged = MachineType::AnyTagged();
|
||||
MachineType type_ptr = MachineType::Pointer();
|
||||
|
||||
smi_index =
|
||||
CAST(CallCFunction2(type_tagged, type_ptr, type_tagged,
|
||||
refill_math_random, isolate_ptr, native_context));
|
||||
Goto(&if_cached);
|
||||
|
||||
// Compute next index by decrement.
|
||||
|
@ -233,7 +233,8 @@ enum ContextLookupFlags {
|
||||
V(MAP_KEY_VALUE_ITERATOR_MAP_INDEX, Map, map_key_value_iterator_map) \
|
||||
V(MAP_VALUE_ITERATOR_MAP_INDEX, Map, map_value_iterator_map) \
|
||||
V(MATH_RANDOM_INDEX_INDEX, Smi, math_random_index) \
|
||||
V(MATH_RANDOM_CACHE_INDEX, Object, math_random_cache) \
|
||||
V(MATH_RANDOM_STATE_INDEX, ByteArray, math_random_state) \
|
||||
V(MATH_RANDOM_CACHE_INDEX, FixedDoubleArray, math_random_cache) \
|
||||
V(MESSAGE_LISTENERS_INDEX, TemplateList, message_listeners) \
|
||||
V(NATIVES_UTILS_OBJECT_INDEX, Object, natives_utils_object) \
|
||||
V(NORMALIZED_MAP_CACHE_INDEX, Object, normalized_map_cache) \
|
||||
|
@ -308,7 +308,6 @@ bool IntrinsicHasNoSideEffect(Runtime::FunctionId id) {
|
||||
V(ArrayIndexOf) \
|
||||
V(ArrayIsArray) \
|
||||
V(ClassOf) \
|
||||
V(GenerateRandomNumbers) \
|
||||
V(GetFunctionName) \
|
||||
V(GetOwnPropertyDescriptor) \
|
||||
V(GlobalPrint) \
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "src/ic/stub-cache.h"
|
||||
#include "src/interpreter/interpreter.h"
|
||||
#include "src/isolate.h"
|
||||
#include "src/math-random.h"
|
||||
#include "src/objects-inl.h"
|
||||
#include "src/regexp/regexp-stack.h"
|
||||
#include "src/simulator-base.h"
|
||||
@ -719,6 +720,10 @@ ExternalReference ExternalReference::printf_function() {
|
||||
return ExternalReference(Redirect(FUNCTION_ADDR(std::printf)));
|
||||
}
|
||||
|
||||
ExternalReference ExternalReference::refill_math_random() {
|
||||
return ExternalReference(Redirect(FUNCTION_ADDR(MathRandom::RefillCache)));
|
||||
}
|
||||
|
||||
template <typename SubjectChar, typename PatternChar>
|
||||
ExternalReference ExternalReference::search_string_raw() {
|
||||
auto f = SearchStringRaw<SubjectChar, PatternChar>;
|
||||
|
@ -133,6 +133,7 @@ class StatsCounter;
|
||||
V(orderedhashmap_gethash_raw, "orderedhashmap_gethash_raw") \
|
||||
V(power_double_double_function, "power_double_double_function") \
|
||||
V(printf_function, "printf") \
|
||||
V(refill_math_random, "MathRandom::RefillCache") \
|
||||
V(store_buffer_overflow_function, "StoreBuffer::StoreBufferOverflow") \
|
||||
V(search_string_raw_one_one, "search_string_raw_one_one") \
|
||||
V(search_string_raw_one_two, "search_string_raw_one_two") \
|
||||
|
71
src/math-random.cc
Normal file
71
src/math-random.cc
Normal file
@ -0,0 +1,71 @@
|
||||
// Copyright 2018 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "src/math-random.h"
|
||||
|
||||
#include "src/assert-scope.h"
|
||||
#include "src/base/utils/random-number-generator.h"
|
||||
#include "src/contexts-inl.h"
|
||||
#include "src/isolate.h"
|
||||
#include "src/objects/fixed-array.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
|
||||
void MathRandom::InitializeContext(Isolate* isolate,
|
||||
Handle<Context> native_context) {
|
||||
Handle<FixedDoubleArray> cache = Handle<FixedDoubleArray>::cast(
|
||||
isolate->factory()->NewFixedDoubleArray(kCacheSize, TENURED));
|
||||
for (int i = 0; i < kCacheSize; i++) cache->set(i, 0);
|
||||
native_context->set_math_random_cache(*cache);
|
||||
Handle<PodArray<State>> pod = PodArray<State>::New(isolate, 1, TENURED);
|
||||
native_context->set_math_random_state(*pod);
|
||||
ResetContext(*native_context);
|
||||
}
|
||||
|
||||
void MathRandom::ResetContext(Context* native_context) {
|
||||
native_context->set_math_random_index(Smi::kZero);
|
||||
State state = {0, 0};
|
||||
PodArray<State>::cast(native_context->math_random_state())->set(0, state);
|
||||
}
|
||||
|
||||
Smi* MathRandom::RefillCache(Isolate* isolate, Context* native_context) {
|
||||
DisallowHeapAllocation no_gc;
|
||||
PodArray<State>* pod =
|
||||
PodArray<State>::cast(native_context->math_random_state());
|
||||
State state = pod->get(0);
|
||||
// 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 (state.s0 == 0 || state.s1 == 0) {
|
||||
if (FLAG_random_seed != 0) {
|
||||
state.s0 = FLAG_random_seed;
|
||||
state.s1 = FLAG_random_seed;
|
||||
} else {
|
||||
base::RandomNumberGenerator* rng = isolate->random_number_generator();
|
||||
while (state.s0 == 0 || state.s1 == 0) {
|
||||
rng->NextBytes(&state.s0, sizeof(state.s0));
|
||||
rng->NextBytes(&state.s1, sizeof(state.s1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FixedDoubleArray* cache =
|
||||
FixedDoubleArray::cast(native_context->math_random_cache());
|
||||
// Create random numbers.
|
||||
for (int i = 0; i < kCacheSize; i++) {
|
||||
// Generate random numbers using xorshift128+.
|
||||
base::RandomNumberGenerator::XorShift128(&state.s0, &state.s1);
|
||||
cache->set(i, base::RandomNumberGenerator::ToDouble(state.s0));
|
||||
}
|
||||
pod->set(0, state);
|
||||
|
||||
Smi* new_index = Smi::FromInt(kCacheSize);
|
||||
native_context->set_math_random_index(new_index);
|
||||
return new_index;
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace v8
|
33
src/math-random.h
Normal file
33
src/math-random.h
Normal file
@ -0,0 +1,33 @@
|
||||
// Copyright 2018 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef V8_MATH_RANDOM_H_
|
||||
#define V8_MATH_RANDOM_H_
|
||||
|
||||
#include "src/contexts.h"
|
||||
#include "src/globals.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
|
||||
class MathRandom : public AllStatic {
|
||||
public:
|
||||
static void InitializeContext(Isolate* isolate,
|
||||
Handle<Context> native_context);
|
||||
|
||||
static void ResetContext(Context* native_context);
|
||||
static Smi* RefillCache(Isolate* isolate, Context* native_context);
|
||||
|
||||
static const int kCacheSize = 64;
|
||||
static const int kStateSize = 2 * kInt64Size;
|
||||
|
||||
struct State {
|
||||
uint64_t s0;
|
||||
uint64_t s1;
|
||||
};
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
#endif // V8_MATH_RANDOM_H_
|
@ -1,72 +0,0 @@
|
||||
// Copyright 2014 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "src/runtime/runtime-utils.h"
|
||||
|
||||
#include "src/arguments.h"
|
||||
#include "src/base/utils/random-number-generator.h"
|
||||
#include "src/bootstrapper.h"
|
||||
#include "src/counters.h"
|
||||
#include "src/double.h"
|
||||
#include "src/objects-inl.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
|
||||
RUNTIME_FUNCTION(Runtime_GenerateRandomNumbers) {
|
||||
HandleScope scope(isolate);
|
||||
DCHECK_EQ(0, args.length());
|
||||
|
||||
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;
|
||||
|
||||
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 {
|
||||
cache = Handle<FixedDoubleArray>::cast(
|
||||
isolate->factory()->NewFixedDoubleArray(kCacheSize, TENURED));
|
||||
native_context->set_math_random_cache(*cache);
|
||||
// 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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DisallowHeapAllocation no_gc;
|
||||
FixedDoubleArray* raw_cache = *cache;
|
||||
// Create random numbers.
|
||||
for (int i = 0; i < kInitialIndex; i++) {
|
||||
// Generate random numbers using xorshift128+.
|
||||
base::RandomNumberGenerator::XorShift128(&state0, &state1);
|
||||
raw_cache->set(i, base::RandomNumberGenerator::ToDouble(state0, state1));
|
||||
}
|
||||
|
||||
// Persist current state.
|
||||
raw_cache->set(kState0Offset, uint64_to_double(state0));
|
||||
raw_cache->set(kState1Offset, uint64_to_double(state1));
|
||||
return Smi::FromInt(kInitialIndex);
|
||||
}
|
||||
} // namespace internal
|
||||
} // namespace v8
|
@ -256,8 +256,6 @@ namespace internal {
|
||||
F(CreateObjectLiteralWithoutAllocationSite, 2, 1) \
|
||||
F(CreateRegExpLiteral, 4, 1)
|
||||
|
||||
#define FOR_EACH_INTRINSIC_MATHS(F) F(GenerateRandomNumbers, 0, 1)
|
||||
|
||||
#define FOR_EACH_INTRINSIC_MODULE(F) \
|
||||
F(DynamicImportCall, 2, 1) \
|
||||
F(GetImportMetaObject, 0, 1) \
|
||||
@ -581,7 +579,6 @@ namespace internal {
|
||||
FOR_EACH_INTRINSIC_INTERPRETER(F) \
|
||||
FOR_EACH_INTRINSIC_INTL(F) \
|
||||
FOR_EACH_INTRINSIC_LITERALS(F) \
|
||||
FOR_EACH_INTRINSIC_MATHS(F) \
|
||||
FOR_EACH_INTRINSIC_MODULE(F) \
|
||||
FOR_EACH_INTRINSIC_NUMBERS(F) \
|
||||
FOR_EACH_INTRINSIC_OBJECT(F) \
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include "src/snapshot/startup-serializer.h"
|
||||
|
||||
#include "src/api-inl.h"
|
||||
#include "src/math-random.h"
|
||||
#include "src/objects-inl.h"
|
||||
|
||||
namespace v8 {
|
||||
@ -40,8 +41,7 @@ void PartialSerializer::Serialize(Context** o, bool include_global_proxy) {
|
||||
ReadOnlyRoots(isolate()).undefined_value());
|
||||
DCHECK(!context_->global_object()->IsUndefined());
|
||||
// Reset math random cache to get fresh random numbers.
|
||||
context_->set_math_random_index(Smi::kZero);
|
||||
context_->set_math_random_cache(ReadOnlyRoots(isolate()).undefined_value());
|
||||
MathRandom::ResetContext(context_);
|
||||
|
||||
VisitRootPointer(Root::kPartialSnapshotCache, nullptr,
|
||||
reinterpret_cast<Object**>(o));
|
||||
|
Loading…
Reference in New Issue
Block a user