[vm] Remove Isolate, IsolateGroup and global Random.

The per Thread instance is sufficient.

TEST=ci
Change-Id: Iff2c4279937637089f7ae4194cb1097b5e6eef67
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/452881
Commit-Queue: Ryan Macnak <rmacnak@google.com>
Reviewed-by: Alexander Aprelev <aam@google.com>
This commit is contained in:
Ryan Macnak
2025-10-07 15:13:14 -07:00
committed by Commit Queue
parent a0b625075d
commit f1aa58931d
13 changed files with 25 additions and 71 deletions
+1 -1
View File
@@ -685,7 +685,7 @@ void main() {
expect(result.stderr, isEmpty);
// This value should be consistent as long as --random_seed is processed.
expect(result.stdout, contains('64'));
expect(result.stdout, contains('21'));
expect(result.exitCode, 0);
}, skip: isRunningOnIA32);
+1 -1
View File
@@ -38,7 +38,7 @@ DEFINE_NATIVE_ENTRY(Capability_factory, 0, 1) {
// protocol can process it properly.
//
// See https://github.com/dart-lang/sdk/issues/53081.
uint64_t id = isolate->random()->NextJSInt();
uint64_t id = thread->random()->NextJSInt();
return Capability::New(id);
}
+1 -4
View File
@@ -14,10 +14,7 @@
namespace dart {
DEFINE_NATIVE_ENTRY(Random_initialSeed, 0, 0) {
Random* rnd = isolate->random();
uint64_t seed = rnd->NextUInt32();
seed |= (static_cast<uint64_t>(rnd->NextUInt32()) << 32);
return Integer::New(seed);
return Integer::New(thread->random()->NextUInt64());
}
DEFINE_NATIVE_ENTRY(SecureRandom_getBytes, 0, 1) {
+1 -1
View File
@@ -245,7 +245,7 @@ bool HasIntegerValue(const dart::Object& object, int64_t* value) {
}
int32_t CreateJitCookie() {
return static_cast<int32_t>(IsolateGroup::Current()->random()->NextUInt32());
return static_cast<int32_t>(Thread::Current()->random()->NextUInt32());
}
word TypedDataElementSizeInBytes(classid_t cid) {
-2
View File
@@ -365,7 +365,6 @@ char* Dart::DartInit(const Dart_InitializeParams* params) {
#endif
OSThread::Init();
Random::Init();
Zone::Init();
#if defined(SUPPORT_TIMELINE)
Timeline::Init();
@@ -800,7 +799,6 @@ char* Dart::Cleanup() {
#endif
NOT_IN_PRODUCT(MicrotaskMirrorQueues::CleanUp());
Zone::Cleanup();
Random::Cleanup();
// Delete the current thread's TLS and set it's TLS to null.
// If it is the last thread then the destructor would call
// OSThread::Cleanup.
+1 -1
View File
@@ -539,7 +539,7 @@ class StressTask : public StateMachineTask {
virtual void RunInternal() {
data_->WaitUntil(kStart);
Random random(thread_->isolate_group()->random()->NextUInt64());
Random random(thread_->random()->NextUInt64());
while (!data()->IsIn(kPleaseExit)) {
const auto us = random.NextUInt32() % 3;
switch (random.NextUInt32() % 5) {
+1 -1
View File
@@ -295,7 +295,7 @@ void HeapProfileSampler::SampleOldSpaceAllocation(intptr_t allocation_size) {
// Determines the next sampling interval by sampling from a poisson
intptr_t HeapProfileSampler::GetNextSamplingIntervalLocked() {
ASSERT(thread_->isolate_group() != nullptr);
double u = thread_->isolate_group()->random()->NextDouble();
double u = thread_->random()->NextDouble();
ASSERT(u >= 0.0 && u <= 1.0);
// Approximate sampling from a poisson distribution using an exponential
// distribution. We take the sample by feeding in a random uniform value in
+2 -4
View File
@@ -323,7 +323,6 @@ IsolateGroup::IsolateGroup(std::shared_ptr<IsolateGroupSource> source,
mutators_(),
start_time_micros_(OS::GetCurrentMonotonicMicros()),
is_system_isolate_group_(source->flags.is_system_isolate),
random_(),
#if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
last_reload_timestamp_(OS::GetCurrentTimeMillis()),
reload_every_n_stack_overflow_checks_(FLAG_reload_every),
@@ -1855,7 +1854,6 @@ Isolate::Isolate(IsolateGroup* isolate_group,
message_notify_callback_(nullptr),
on_shutdown_callback_(Isolate::ShutdownCallback()),
on_cleanup_callback_(Isolate::CleanupCallback()),
random_(),
mutex_(),
owner_thread_(OSThread::kInvalidThreadId),
sticky_error_(Error::null()),
@@ -1958,8 +1956,8 @@ Isolate* Isolate::InitIsolate(const char* name_prefix,
// protocol can process it properly.
//
// See https://github.com/dart-lang/sdk/issues/53081.
result->set_pause_capability(result->random()->NextJSInt());
result->set_terminate_capability(result->random()->NextJSInt());
result->set_pause_capability(Thread::Current()->random()->NextJSInt());
result->set_terminate_capability(Thread::Current()->random()->NextJSInt());
#if !defined(PRODUCT)
result->debugger_ = new Debugger(result);
-6
View File
@@ -461,8 +461,6 @@ class IsolateGroup : public IntrusiveDListEntry<IsolateGroup> {
void set_obfuscation_map(const char** map) { obfuscation_map_ = map; }
const char** obfuscation_map() const { return obfuscation_map_; }
Random* random() { return &random_; }
bool is_system_isolate_group() const { return is_system_isolate_group_; }
// IsolateGroup-specific flag handling.
@@ -918,7 +916,6 @@ class IsolateGroup : public IntrusiveDListEntry<IsolateGroup> {
Dart_DeferredLoadHandler deferred_load_handler_ = nullptr;
int64_t start_time_micros_;
bool is_system_isolate_group_;
Random random_;
#if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
int64_t last_reload_timestamp_;
@@ -1273,8 +1270,6 @@ class Isolate : public IntrusiveDListEntry<Isolate> {
isolate_flags_.UpdateBool<ErrorsFatalBit>(value);
}
Random* random() { return &random_; }
Simulator* simulator() const { return simulator_; }
void set_simulator(Simulator* value) { simulator_ = value; }
@@ -1695,7 +1690,6 @@ class Isolate : public IntrusiveDListEntry<Isolate> {
uint64_t terminate_capability_ = 0;
void* init_callback_data_ = nullptr;
Dart_EnvironmentCallback environment_callback_ = nullptr;
Random random_;
Simulator* simulator_ = nullptr;
Mutex mutex_; // Protects compiler stats.
IsolateMessageHandler* message_handler_ = nullptr;
+6 -38
View File
@@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
#include "vm/random.h"
#include "vm/dart.h"
#include "vm/flags.h"
#include "vm/os.h"
@@ -35,7 +36,7 @@ Random::Random() {
void Random::Initialize(uint64_t seed) {
ASSERT(seed != 0);
// Crank the next state a couple of times.
_state = seed;
state_ = seed;
NextState();
NextState();
NextState();
@@ -46,10 +47,6 @@ Random::Random(uint64_t seed) {
Initialize(seed);
}
Random::~Random() {
// Nothing to be done here.
}
// The algorithm used here is Multiply with Carry (MWC) with a Base b = 2^32.
// http://en.wikipedia.org/wiki/Multiply-with-carry
// The constant A is selected from "Numerical Recipes 3rd Edition" p.348 B1.
@@ -57,17 +54,10 @@ uint64_t Random::NextState() {
const uint64_t MASK_32 = 0xffffffff;
const uint64_t A = 0xffffda61;
uint64_t old_state = _state;
while (true) {
const uint64_t state_lo = old_state & MASK_32;
const uint64_t state_hi = (old_state >> 32) & MASK_32;
const uint64_t new_state = (A * state_lo) + state_hi;
if (_state.compare_exchange_weak(old_state, new_state,
std::memory_order_relaxed,
std::memory_order_relaxed)) {
return new_state;
}
}
uint64_t state_lo = state_ & MASK_32;
uint64_t state_hi = (state_ >> 32) & MASK_32;
state_ = (A * state_lo) + state_hi;
return state_;
}
uint32_t Random::NextUInt32() {
@@ -75,28 +65,6 @@ uint32_t Random::NextUInt32() {
return static_cast<uint32_t>(NextState() & MASK_32);
}
static Random* global_random = nullptr;
static Mutex* global_random_mutex = nullptr;
void Random::Init() {
ASSERT(global_random_mutex == nullptr);
global_random_mutex = new Mutex();
ASSERT(global_random == nullptr);
global_random = new Random();
}
void Random::Cleanup() {
delete global_random_mutex;
global_random_mutex = nullptr;
delete global_random;
global_random = nullptr;
}
uint64_t Random::GlobalNextUInt64() {
MutexLocker locker(global_random_mutex);
return global_random->NextUInt64();
}
double Random::NextDouble() {
uint64_t mantissa = NextUInt64() & 0xFFFFFFFFFFFFF;
// The exponent value 0 in biased form.
+2 -8
View File
@@ -5,8 +5,6 @@
#ifndef RUNTIME_VM_RANDOM_H_
#define RUNTIME_VM_RANDOM_H_
#include <atomic>
#include "vm/allocation.h"
#include "vm/flags.h"
#include "vm/globals.h"
@@ -20,7 +18,7 @@ class Random {
Random();
// Seed must be non-zero.
explicit Random(uint64_t seed);
~Random();
~Random() {}
uint32_t NextUInt32();
uint64_t NextUInt64() {
@@ -40,10 +38,6 @@ class Random {
return NextUInt64() & kMaxJsInt;
}
static uint64_t GlobalNextUInt64();
static void Init();
static void Cleanup();
// Generates a uniform random variable in the range [0,1].
double NextDouble();
@@ -51,7 +45,7 @@ class Random {
uint64_t NextState();
void Initialize(uint64_t seed);
std::atomic<uint64_t> _state;
uint64_t state_;
DISALLOW_COPY_AND_ASSIGN(Random);
};
+6 -1
View File
@@ -83,6 +83,7 @@ Thread::Thread(bool is_vm_isolate)
api_top_scope_(nullptr),
double_truncate_round_supported_(
TargetCPUFeatures::double_truncate_round_supported() ? 1 : 0),
random_(),
tsan_utils_(DO_IF_TSAN(new TsanUtils()) DO_IF_NOT_TSAN(nullptr)),
current_tag_(UserTag::null()),
default_tag_(UserTag::null()),
@@ -143,10 +144,14 @@ Thread::Thread(bool is_vm_isolate)
InitVMConstants();
}
// For os_signposts, we need task ids that are the unique at least
// process-wide. Each thread will be allocating ids sequentially and we hope
// the random seed will keep each thread's run of ids from overlapping the
// runs of other threads.
#if defined(DART_HOST_OS_FUCHSIA)
next_task_id_ = trace_generate_nonce();
#else
next_task_id_ = Random::GlobalNextUInt64();
next_task_id_ = random_.NextUInt64();
#endif
memset(&unboxed_runtime_arg_, 0, sizeof(simd128_value_t));
+3 -3
View File
@@ -1292,8 +1292,8 @@ class Thread : public ThreadState, public IntrusiveDListEntry<Thread> {
static intptr_t next_task_id_offset() {
return OFFSET_OF(Thread, next_task_id_);
}
Random* random() { return &thread_random_; }
static intptr_t random_offset() { return OFFSET_OF(Thread, thread_random_); }
Random* random() { return &random_; }
static intptr_t random_offset() { return OFFSET_OF(Thread, random_); }
#ifndef PRODUCT
void PrintJSON(JSONStream* stream) const;
@@ -1521,7 +1521,7 @@ class Thread : public ThreadState, public IntrusiveDListEntry<Thread> {
// could be passed as arguments.
ALIGN8 simd128_value_t unboxed_runtime_arg_;
ALIGN8 int64_t next_task_id_;
ALIGN8 Random thread_random_;
ALIGN8 Random random_;
TsanUtils* tsan_utils_ = nullptr;