[vm] Remove Thread::{Enter,Exit}IsolateAsHelper

For every isolate there should be only one mutator with
a unique [Thread] object.

We change existing tests that use this functionality to instead use
`Thread::{Enter,Exit}IsolateGroupAsHelper`. It also results in a net
removal of code.

TEST=ci

Change-Id: Ic326e868a98ddedbab5b8c429252d38ea71bbf04
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/295940
Commit-Queue: Martin Kustermann <kustermann@google.com>
Reviewed-by: Ryan Macnak <rmacnak@google.com>
This commit is contained in:
Martin Kustermann 2023-04-19 09:36:41 +00:00 committed by Commit Queue
parent fb43937e20
commit 779e51efc1
11 changed files with 128 additions and 164 deletions

View file

@ -2653,14 +2653,16 @@ static void TestDirectAccess(Dart_Handle lib,
class BackgroundGCTask : public ThreadPool::Task {
public:
BackgroundGCTask(Isolate* isolate, Monitor* monitor, bool* done)
: isolate_(isolate), monitor_(monitor), done_(done) {}
BackgroundGCTask(IsolateGroup* isolate_group, Monitor* monitor, bool* done)
: isolate_group_(isolate_group), monitor_(monitor), done_(done) {}
virtual void Run() {
Thread::EnterIsolateAsHelper(isolate_, Thread::kUnknownTask);
const bool kBypassSafepoint = false;
Thread::EnterIsolateGroupAsHelper(isolate_group_, Thread::kUnknownTask,
kBypassSafepoint);
for (intptr_t i = 0; i < 10; i++) {
GCTestHelper::CollectAllGarbage();
}
Thread::ExitIsolateAsHelper();
Thread::ExitIsolateGroupAsHelper(kBypassSafepoint);
{
MonitorLocker ml(monitor_);
*done_ = true;
@ -2669,7 +2671,7 @@ class BackgroundGCTask : public ThreadPool::Task {
}
private:
Isolate* isolate_;
IsolateGroup* isolate_group_;
Monitor* monitor_;
bool* done_;
};
@ -2704,7 +2706,7 @@ static void TestTypedDataDirectAccess1() {
Monitor monitor;
bool done = false;
Dart::thread_pool()->Run<BackgroundGCTask>(Isolate::Current(), &monitor,
Dart::thread_pool()->Run<BackgroundGCTask>(IsolateGroup::Current(), &monitor,
&done);
for (intptr_t i = 0; i < 10; i++) {

View file

@ -793,13 +793,17 @@ ISOLATE_UNIT_TEST_CASE(ArrayTruncationRaces) {
class ConcurrentForceGrowthScopeTask : public ThreadPool::Task {
public:
ConcurrentForceGrowthScopeTask(Isolate* isolate,
ConcurrentForceGrowthScopeTask(IsolateGroup* isolate_group,
Monitor* monitor,
intptr_t* done_count)
: isolate_(isolate), monitor_(monitor), done_count_(done_count) {}
: isolate_group_(isolate_group),
monitor_(monitor),
done_count_(done_count) {}
virtual void Run() {
Thread::EnterIsolateAsHelper(isolate_, Thread::kUnknownTask);
const bool kBypassSafepoint = false;
Thread::EnterIsolateGroupAsHelper(isolate_group_, Thread::kUnknownTask,
kBypassSafepoint);
{
Thread* thread = Thread::Current();
StackZone stack_zone(thread);
@ -819,7 +823,7 @@ class ConcurrentForceGrowthScopeTask : public ThreadPool::Task {
accumulate.Add(element);
}
}
Thread::ExitIsolateAsHelper();
Thread::ExitIsolateGroupAsHelper(kBypassSafepoint);
// Notify the main thread that this thread has exited.
{
MonitorLocker ml(monitor_);
@ -829,7 +833,7 @@ class ConcurrentForceGrowthScopeTask : public ThreadPool::Task {
}
private:
Isolate* isolate_;
IsolateGroup* isolate_group_;
Monitor* monitor_;
intptr_t* done_count_;
};
@ -841,7 +845,7 @@ ISOLATE_UNIT_TEST_CASE(ConcurrentForceGrowthScope) {
for (intptr_t i = 0; i < task_count; i++) {
Dart::thread_pool()->Run<ConcurrentForceGrowthScopeTask>(
thread->isolate(), &monitor, &done_count);
thread->isolate_group(), &monitor, &done_count);
}
{

View file

@ -3654,12 +3654,8 @@ Monitor* IsolateGroup::threads_lock() const {
return thread_registry_->threads_lock();
}
Thread* Isolate::ScheduleThread(bool is_mutator,
bool is_nested_reenter,
bool bypass_safepoint) {
if (is_mutator) {
group()->IncreaseMutatorCount(this, is_nested_reenter);
}
Thread* Isolate::ScheduleThread(bool is_nested_reenter) {
group()->IncreaseMutatorCount(this, is_nested_reenter);
// We are about to associate the thread with an isolate group and it would
// not be possible to correctly track no_safepoint_scope_depth for the
@ -3669,7 +3665,7 @@ Thread* Isolate::ScheduleThread(bool is_mutator,
MonitorLocker ml(group()->threads_lock(), false);
// Check to make sure we don't already have a mutator thread.
if (is_mutator && scheduled_mutator_thread_ != nullptr) {
if (scheduled_mutator_thread_ != nullptr) {
return nullptr;
}
@ -3680,7 +3676,7 @@ Thread* Isolate::ScheduleThread(bool is_mutator,
// We lazily create a [Thread] structure for the mutator thread, but we'll
// reuse it until the death of the isolate.
Thread* existing_mutator_thread = is_mutator ? mutator_thread_ : nullptr;
Thread* existing_mutator_thread = mutator_thread_;
if (existing_mutator_thread != nullptr) {
ASSERT(existing_mutator_thread->is_mutator_thread_);
}
@ -3689,23 +3685,19 @@ Thread* Isolate::ScheduleThread(bool is_mutator,
// with it (this is done while we are holding the thread registry lock).
Thread* thread =
group()->ScheduleThreadLocked(&ml, existing_mutator_thread, is_vm_isolate,
is_mutator, bypass_safepoint);
if (is_mutator) {
ASSERT(mutator_thread_ == nullptr || mutator_thread_ == thread);
mutator_thread_ = thread;
scheduled_mutator_thread_ = thread;
thread->is_mutator_thread_ = true;
thread->field_table_values_ = field_table_->table();
}
/*is_mutator=*/true,
/*bypass_safepoint=*/false);
ASSERT(mutator_thread_ == nullptr || mutator_thread_ == thread);
mutator_thread_ = thread;
scheduled_mutator_thread_ = thread;
thread->is_mutator_thread_ = true;
thread->field_table_values_ = field_table_->table();
thread->isolate_ = this;
return thread;
}
void Isolate::UnscheduleThread(Thread* thread,
bool is_mutator,
bool is_nested_exit,
bool bypass_safepoint) {
void Isolate::UnscheduleThread(Thread* thread, bool is_nested_exit) {
{
// Disassociate the 'Thread' structure and unschedule the thread
// from this isolate.
@ -3716,26 +3708,18 @@ void Isolate::UnscheduleThread(Thread* thread,
// no_safepoint_scope_depth increments/decrements.
MonitorLocker ml(group()->threads_lock(), false);
if (is_mutator) {
if (thread->sticky_error() != Error::null()) {
ASSERT(sticky_error_ == Error::null());
sticky_error_ = thread->StealStickyError();
}
ASSERT(mutator_thread_ == thread);
ASSERT(mutator_thread_ == scheduled_mutator_thread_);
scheduled_mutator_thread_ = nullptr;
} else {
// We only reset the isolate pointer for non-mutator threads, since
// mutator threads can still be visited during GC even if unscheduled.
// See also IsolateGroup::UnscheduleThreadLocked`
thread->isolate_ = nullptr;
if (thread->sticky_error() != Error::null()) {
ASSERT(sticky_error_ == Error::null());
sticky_error_ = thread->StealStickyError();
}
ASSERT(mutator_thread_ == thread);
ASSERT(mutator_thread_ == scheduled_mutator_thread_);
scheduled_mutator_thread_ = nullptr;
thread->field_table_values_ = nullptr;
group()->UnscheduleThreadLocked(&ml, thread, is_mutator, bypass_safepoint);
}
if (is_mutator) {
group()->DecreaseMutatorCount(this, is_nested_exit);
group()->UnscheduleThreadLocked(&ml, thread, /*is_mutator=*/true,
/*bypass_safepoint=*/false);
}
group()->DecreaseMutatorCount(this, is_nested_exit);
}
#if !defined(PRODUCT)

View file

@ -1537,13 +1537,8 @@ class Isolate : public BaseIsolate, public IntrusiveDListEntry<Isolate> {
const GrowableObjectArray& value);
#endif // !defined(PRODUCT)
Thread* ScheduleThread(bool is_mutator,
bool is_nested_reenter,
bool bypass_safepoint);
void UnscheduleThread(Thread* thread,
bool is_mutator,
bool is_nested_exit,
bool bypass_safepoint);
Thread* ScheduleThread(bool is_nested_reenter);
void UnscheduleThread(Thread* thread, bool is_nested_exit);
// DEPRECATED: Use Thread's methods instead. During migration, these default
// to using the mutator thread (which must also be the current thread).

View file

@ -113,7 +113,9 @@ class InterruptChecker : public ThreadPool::Task {
: thread_(thread), barrier_(barrier) {}
virtual void Run() {
Thread::EnterIsolateAsHelper(thread_->isolate(), Thread::kUnknownTask);
const bool kBypassSafepoint = false;
Thread::EnterIsolateGroupAsHelper(thread_->isolate_group(),
Thread::kUnknownTask, kBypassSafepoint);
// Tell main thread that we are ready.
barrier_->Sync();
for (intptr_t i = 0; i < kIterations; ++i) {
@ -129,7 +131,7 @@ class InterruptChecker : public ThreadPool::Task {
// Tell main thread that we observed the interrupt.
barrier_->Sync();
}
Thread::ExitIsolateAsHelper();
Thread::ExitIsolateGroupAsHelper(kBypassSafepoint);
barrier_->Sync();
barrier_->Release();
}

View file

@ -300,15 +300,18 @@ DART_EXPORT void* Dart_ExecuteInternalCommand(const char* command, void* arg) {
reinterpret_cast<RunInSafepointAndRWCodeArgs*>(arg);
Isolate* const isolate = args->isolate;
CHECK_ISOLATE(isolate);
Thread::EnterIsolateAsHelper(isolate, Thread::TaskKind::kUnknownTask);
auto isolate_group = isolate->group();
const bool kBypassSafepoint = false;
Thread::EnterIsolateGroupAsHelper(isolate_group, Thread::kUnknownTask,
kBypassSafepoint);
Thread* const thread = Thread::Current();
{
GcSafepointOperationScope scope(thread);
args->isolate->group()->heap()->WriteProtectCode(/*read_only=*/false);
isolate_group->heap()->WriteProtectCode(/*read_only=*/false);
(*args->callback)();
args->isolate->group()->heap()->WriteProtectCode(/*read_only=*/true);
isolate_group->heap()->WriteProtectCode(/*read_only=*/true);
}
Thread::ExitIsolateAsHelper();
Thread::ExitIsolateGroupAsHelper(kBypassSafepoint);
return nullptr;
} else {

View file

@ -1790,9 +1790,9 @@ class StreamableSampleFilter : public SampleFilter {
}
};
void Profiler::ProcessCompletedBlocks(Thread* thread) {
void Profiler::ProcessCompletedBlocks(Isolate* isolate) {
if (!Service::profiler_stream.enabled()) return;
Isolate* isolate = thread->isolate();
auto thread = Thread::Current();
if (Isolate::IsSystemIsolate(isolate)) return;
TIMELINE_DURATION(thread, Isolate, "Profiler::ProcessCompletedBlocks")
@ -1809,7 +1809,7 @@ void Profiler::ProcessCompletedBlocks(Thread* thread) {
void Profiler::IsolateShutdown(Thread* thread) {
FlushSampleBlocks(thread->isolate());
ProcessCompletedBlocks(thread);
ProcessCompletedBlocks(thread->isolate());
}
class SampleBlockProcessorVisitor : public IsolateVisitor {
@ -1819,9 +1819,11 @@ class SampleBlockProcessorVisitor : public IsolateVisitor {
void VisitIsolate(Isolate* isolate) {
if (isolate->TakeHasCompletedBlocks()) {
Thread::EnterIsolateAsHelper(isolate, Thread::kSampleBlockTask);
Profiler::ProcessCompletedBlocks(Thread::Current());
Thread::ExitIsolateAsHelper();
const bool kBypassSafepoint = false;
Thread::EnterIsolateGroupAsHelper(
isolate->group(), Thread::kSampleBlockTask, kBypassSafepoint);
Profiler::ProcessCompletedBlocks(isolate);
Thread::ExitIsolateGroupAsHelper(kBypassSafepoint);
}
}
};

View file

@ -94,7 +94,7 @@ class Profiler : public AllStatic {
}
inline static intptr_t Size();
static void ProcessCompletedBlocks(Thread* thread);
static void ProcessCompletedBlocks(Isolate* isolate);
static void IsolateShutdown(Thread* thread);
private:

View file

@ -272,15 +272,11 @@ const char* Thread::TaskKindToCString(TaskKind kind) {
}
bool Thread::EnterIsolate(Isolate* isolate, bool is_nested_reenter) {
const bool kIsMutatorThread = true;
const bool kBypassSafepoint = false;
is_nested_reenter = is_nested_reenter ||
(isolate->mutator_thread() != nullptr &&
isolate->mutator_thread()->top_exit_frame_info() != 0);
Thread* thread = isolate->ScheduleThread(kIsMutatorThread, is_nested_reenter,
kBypassSafepoint);
Thread* thread = isolate->ScheduleThread(is_nested_reenter);
if (thread != nullptr) {
ASSERT(thread->store_buffer_block_ == nullptr);
ASSERT(thread->isolate() == isolate);
@ -304,48 +300,10 @@ void Thread::ExitIsolate(bool is_nested_exit) {
Isolate* isolate = thread->isolate();
thread->set_vm_tag(isolate->is_runnable() ? VMTag::kIdleTagId
: VMTag::kLoadWaitTagId);
const bool kIsMutatorThread = true;
const bool kBypassSafepoint = false;
is_nested_exit =
is_nested_exit || (isolate->mutator_thread() != nullptr &&
isolate->mutator_thread()->top_exit_frame_info() != 0);
isolate->UnscheduleThread(thread, kIsMutatorThread, is_nested_exit,
kBypassSafepoint);
}
bool Thread::EnterIsolateAsHelper(Isolate* isolate,
TaskKind kind,
bool bypass_safepoint) {
ASSERT(kind != kMutatorTask);
const bool kIsMutatorThread = false;
const bool kIsNestedReenter = false;
Thread* thread = isolate->ScheduleThread(kIsMutatorThread, kIsNestedReenter,
bypass_safepoint);
if (thread != nullptr) {
ASSERT(!thread->IsMutatorThread());
ASSERT(thread->isolate() == isolate);
ASSERT(thread->isolate_group() == isolate->group());
thread->FinishEntering(kind);
return true;
}
return false;
}
void Thread::ExitIsolateAsHelper(bool bypass_safepoint) {
Thread* thread = Thread::Current();
ASSERT(thread != nullptr);
ASSERT(!thread->IsMutatorThread());
ASSERT(thread->isolate() != nullptr);
ASSERT(thread->isolate_group() != nullptr);
thread->PrepareLeaving();
Isolate* isolate = thread->isolate();
ASSERT(isolate != nullptr);
const bool kIsMutatorThread = false;
const bool kIsNestedExit = false;
isolate->UnscheduleThread(thread, kIsMutatorThread, kIsNestedExit,
bypass_safepoint);
isolate->UnscheduleThread(thread, is_nested_exit);
}
bool Thread::EnterIsolateGroupAsHelper(IsolateGroup* isolate_group,
@ -452,7 +410,7 @@ ErrorPtr Thread::HandleInterrupts() {
#if !defined(PRODUCT)
if (isolate()->TakeHasCompletedBlocks()) {
Profiler::ProcessCompletedBlocks(this);
Profiler::ProcessCompletedBlocks(isolate());
}
#endif // !defined(PRODUCT)

View file

@ -362,15 +362,6 @@ class Thread : public ThreadState {
// Makes the current thread exit its isolate.
static void ExitIsolate(bool is_nested_exit = false);
// A VM thread other than the main mutator thread can enter an isolate as a
// "helper" to gain limited concurrent access to the isolate. One example is
// SweeperTask (which uses the class table, which is copy-on-write).
// TODO(koda): Properly synchronize heap access to expand allowed operations.
static bool EnterIsolateAsHelper(Isolate* isolate,
TaskKind kind,
bool bypass_safepoint = false);
static void ExitIsolateAsHelper(bool bypass_safepoint = false);
static bool EnterIsolateGroupAsHelper(IsolateGroup* isolate_group,
TaskKind kind,
bool bypass_safepoint);

View file

@ -112,13 +112,18 @@ class ObjectCounter : public ObjectPointerVisitor {
class TaskWithZoneAllocation : public ThreadPool::Task {
public:
TaskWithZoneAllocation(Isolate* isolate,
TaskWithZoneAllocation(IsolateGroup* isolate_group,
Monitor* monitor,
bool* done,
intptr_t id)
: isolate_(isolate), monitor_(monitor), done_(done), id_(id) {}
: isolate_group_(isolate_group),
monitor_(monitor),
done_(done),
id_(id) {}
virtual void Run() {
Thread::EnterIsolateAsHelper(isolate_, Thread::kUnknownTask);
const bool kBypassSafepoint = false;
Thread::EnterIsolateGroupAsHelper(isolate_group_, Thread::kUnknownTask,
kBypassSafepoint);
{
Thread* thread = Thread::Current();
// Create a zone (which is also a stack resource) and exercise it a bit.
@ -140,7 +145,7 @@ class TaskWithZoneAllocation : public ThreadPool::Task {
EXPECT(smi.Value() == unique_smi);
{
HeapIterationScope iteration(thread);
ObjectCounter counter(isolate_->group(), &smi);
ObjectCounter counter(isolate_group_, &smi);
// Ensure that our particular zone is visited.
iteration.IterateStackPointers(&counter,
ValidationPolicy::kValidateFrames);
@ -157,7 +162,7 @@ class TaskWithZoneAllocation : public ThreadPool::Task {
EXPECT(unique_str.Equals(unique_chars));
{
HeapIterationScope iteration(thread);
ObjectCounter str_counter(isolate_->group(), &unique_str);
ObjectCounter str_counter(isolate_group_, &unique_str);
// Ensure that our particular zone is visited.
iteration.IterateStackPointers(&str_counter,
ValidationPolicy::kValidateFrames);
@ -165,7 +170,7 @@ class TaskWithZoneAllocation : public ThreadPool::Task {
EXPECT_EQ(1, str_counter.count());
}
}
Thread::ExitIsolateAsHelper();
Thread::ExitIsolateGroupAsHelper(kBypassSafepoint);
{
MonitorLocker ml(monitor_);
*done_ = true;
@ -174,7 +179,7 @@ class TaskWithZoneAllocation : public ThreadPool::Task {
}
private:
Isolate* isolate_;
IsolateGroup* isolate_group_;
Monitor* monitor_;
bool* done_;
intptr_t id_;
@ -184,10 +189,11 @@ ISOLATE_UNIT_TEST_CASE(ManyTasksWithZones) {
const int kTaskCount = 100;
Monitor sync[kTaskCount];
bool done[kTaskCount];
Isolate* isolate = thread->isolate();
auto isolate = thread->isolate();
auto isolate_group = thread->isolate_group();
for (int i = 0; i < kTaskCount; i++) {
done[i] = false;
Dart::thread_pool()->Run<TaskWithZoneAllocation>(isolate, &sync[i],
Dart::thread_pool()->Run<TaskWithZoneAllocation>(isolate_group, &sync[i],
&done[i], i);
}
bool in_isolate = true;
@ -220,14 +226,14 @@ ISOLATE_UNIT_TEST_CASE(ManyTasksWithZones) {
class SimpleTaskWithZoneAllocation : public ThreadPool::Task {
public:
SimpleTaskWithZoneAllocation(intptr_t id,
Isolate* isolate,
IsolateGroup* isolate_group,
Thread** thread_ptr,
Monitor* sync,
Monitor* monitor,
intptr_t* done_count,
bool* wait)
: id_(id),
isolate_(isolate),
isolate_group_(isolate_group),
thread_ptr_(thread_ptr),
sync_(sync),
monitor_(monitor),
@ -235,13 +241,15 @@ class SimpleTaskWithZoneAllocation : public ThreadPool::Task {
wait_(wait) {}
virtual void Run() {
Thread::EnterIsolateAsHelper(isolate_, Thread::kUnknownTask);
const bool kBypassSafepoint = false;
Thread::EnterIsolateGroupAsHelper(isolate_group_, Thread::kUnknownTask,
kBypassSafepoint);
{
Thread* thread = Thread::Current();
*thread_ptr_ = thread;
CreateStackZones(id_);
}
Thread::ExitIsolateAsHelper();
Thread::ExitIsolateGroupAsHelper(kBypassSafepoint);
// Notify the main thread that this thread has exited.
{
MonitorLocker ml(monitor_);
@ -288,7 +296,7 @@ class SimpleTaskWithZoneAllocation : public ThreadPool::Task {
}
intptr_t id_;
Isolate* isolate_;
IsolateGroup* isolate_group_;
Thread** thread_ptr_;
Monitor* sync_;
Monitor* monitor_;
@ -301,7 +309,7 @@ ISOLATE_UNIT_TEST_CASE(ManySimpleTasksWithZones) {
Monitor monitor;
Monitor sync;
Thread* threads[kTaskCount];
Isolate* isolate = Thread::Current()->isolate();
auto isolate_group = thread->isolate_group();
intptr_t done_count = 0;
bool wait = true;
@ -311,7 +319,8 @@ ISOLATE_UNIT_TEST_CASE(ManySimpleTasksWithZones) {
for (intptr_t i = 0; i < kTaskCount; i++) {
Dart::thread_pool()->Run<SimpleTaskWithZoneAllocation>(
(i + 1), isolate, &threads[i], &sync, &monitor, &done_count, &wait);
(i + 1), isolate_group, &threads[i], &sync, &monitor, &done_count,
&wait);
}
// Wait until all spawned tasks finish their memory operations.
{
@ -371,12 +380,12 @@ class ICDataTestTask : public ThreadPool::Task {
public:
static constexpr intptr_t kTaskCount = 1;
ICDataTestTask(Isolate* isolate,
ICDataTestTask(IsolateGroup* isolate_group,
const Array& ic_datas,
Monitor* monitor,
intptr_t* exited,
std::atomic<bool>* done)
: isolate_(isolate),
: isolate_group_(isolate_group),
ic_datas_(ic_datas),
len_(ic_datas.Length()),
monitor_(monitor),
@ -384,7 +393,9 @@ class ICDataTestTask : public ThreadPool::Task {
done_(done) {}
virtual void Run() {
Thread::EnterIsolateAsHelper(isolate_, Thread::kUnknownTask);
const bool kBypassSafepoint = false;
Thread::EnterIsolateGroupAsHelper(isolate_group_, Thread::kUnknownTask,
kBypassSafepoint);
Thread* thread = Thread::Current();
@ -414,7 +425,7 @@ class ICDataTestTask : public ThreadPool::Task {
}
}
Thread::ExitIsolateAsHelper();
Thread::ExitIsolateGroupAsHelper(kBypassSafepoint);
{
MonitorLocker ml(monitor_);
++*exited_;
@ -423,7 +434,7 @@ class ICDataTestTask : public ThreadPool::Task {
}
private:
Isolate* isolate_;
IsolateGroup* isolate_group_;
const Array& ic_datas_;
const intptr_t len_;
Monitor* monitor_;
@ -450,8 +461,8 @@ static Function* CreateFunction(const char* name) {
// Test that checks that other threads only see a fully initialized ICData
// whenever ICData is updated.
ISOLATE_UNIT_TEST_CASE(ICDataTest) {
Isolate* isolate = thread->isolate();
USE(isolate);
auto isolate_group = thread->isolate_group();
USE(isolate_group);
Monitor monitor;
intptr_t exited = 0;
std::atomic<bool> done = {false};
@ -472,7 +483,7 @@ ISOLATE_UNIT_TEST_CASE(ICDataTest) {
}
for (int i = 0; i < ICDataTestTask::kTaskCount; i++) {
Dart::thread_pool()->Run<ICDataTestTask>(isolate, ic_datas, &monitor,
Dart::thread_pool()->Run<ICDataTestTask>(isolate_group, ic_datas, &monitor,
&exited, &done);
}
@ -524,7 +535,9 @@ class SafepointTestTask : public ThreadPool::Task {
local_done_(false) {}
virtual void Run() {
Thread::EnterIsolateAsHelper(isolate_, Thread::kUnknownTask);
const bool kBypassSafepoint = false;
Thread::EnterIsolateGroupAsHelper(isolate_->group(), Thread::kUnknownTask,
kBypassSafepoint);
{
MonitorLocker ml(monitor_);
++*expected_count_;
@ -573,7 +586,7 @@ class SafepointTestTask : public ThreadPool::Task {
}
}
}
Thread::ExitIsolateAsHelper();
Thread::ExitIsolateGroupAsHelper(kBypassSafepoint);
{
MonitorLocker ml(monitor_);
++*exited_;
@ -837,20 +850,24 @@ ISOLATE_UNIT_TEST_CASE(RecursiveSafepointTest2) {
class AllocAndGCTask : public ThreadPool::Task {
public:
AllocAndGCTask(Isolate* isolate, Monitor* done_monitor, bool* done)
: isolate_(isolate), done_monitor_(done_monitor), done_(done) {}
AllocAndGCTask(IsolateGroup* isolate_group, Monitor* done_monitor, bool* done)
: isolate_group_(isolate_group),
done_monitor_(done_monitor),
done_(done) {}
virtual void Run() {
Thread::EnterIsolateAsHelper(isolate_, Thread::kUnknownTask);
const bool kBypassSafepoint = false;
Thread::EnterIsolateGroupAsHelper(isolate_group_, Thread::kUnknownTask,
kBypassSafepoint);
{
Thread* thread = Thread::Current();
StackZone stack_zone(thread);
Zone* zone = stack_zone.GetZone();
String& old_str = String::Handle(zone, String::New("old", Heap::kOld));
isolate_->group()->heap()->CollectAllGarbage();
isolate_group_->heap()->CollectAllGarbage();
EXPECT(old_str.Equals("old"));
}
Thread::ExitIsolateAsHelper();
Thread::ExitIsolateGroupAsHelper(kBypassSafepoint);
// Tell main thread that we are ready.
{
MonitorLocker ml(done_monitor_);
@ -861,7 +878,7 @@ class AllocAndGCTask : public ThreadPool::Task {
}
private:
Isolate* isolate_;
IsolateGroup* isolate_group_;
Monitor* done_monitor_;
bool* done_;
};
@ -869,8 +886,8 @@ class AllocAndGCTask : public ThreadPool::Task {
ISOLATE_UNIT_TEST_CASE(HelperAllocAndGC) {
Monitor done_monitor;
bool done = false;
Isolate* isolate = thread->isolate();
Dart::thread_pool()->Run<AllocAndGCTask>(isolate, &done_monitor, &done);
auto isolate_group = thread->isolate_group();
Dart::thread_pool()->Run<AllocAndGCTask>(isolate_group, &done_monitor, &done);
{
while (true) {
TransitionVMToBlocked transition(thread);
@ -884,11 +901,17 @@ ISOLATE_UNIT_TEST_CASE(HelperAllocAndGC) {
class AllocateGlobsOfMemoryTask : public ThreadPool::Task {
public:
AllocateGlobsOfMemoryTask(Isolate* isolate, Monitor* done_monitor, bool* done)
: isolate_(isolate), done_monitor_(done_monitor), done_(done) {}
AllocateGlobsOfMemoryTask(IsolateGroup* isolate_group,
Monitor* done_monitor,
bool* done)
: isolate_group_(isolate_group),
done_monitor_(done_monitor),
done_(done) {}
virtual void Run() {
Thread::EnterIsolateAsHelper(isolate_, Thread::kUnknownTask);
const bool kBypassSafepoint = false;
Thread::EnterIsolateGroupAsHelper(isolate_group_, Thread::kUnknownTask,
kBypassSafepoint);
{
Thread* thread = Thread::Current();
StackZone stack_zone(thread);
@ -898,7 +921,7 @@ class AllocateGlobsOfMemoryTask : public ThreadPool::Task {
String::Handle(zone, String::New("abc"));
}
}
Thread::ExitIsolateAsHelper();
Thread::ExitIsolateGroupAsHelper(kBypassSafepoint);
// Tell main thread that we are ready.
{
MonitorLocker ml(done_monitor_);
@ -909,7 +932,7 @@ class AllocateGlobsOfMemoryTask : public ThreadPool::Task {
}
private:
Isolate* isolate_;
IsolateGroup* isolate_group_;
Monitor* done_monitor_;
bool* done_;
};
@ -918,11 +941,11 @@ ISOLATE_UNIT_TEST_CASE(ExerciseTLABs) {
const int NUMBER_TEST_THREADS = 10;
Monitor done_monitor[NUMBER_TEST_THREADS];
bool done[NUMBER_TEST_THREADS];
Isolate* isolate = thread->isolate();
auto isolate_group = thread->isolate_group();
for (int i = 0; i < NUMBER_TEST_THREADS; i++) {
done[i] = false;
Dart::thread_pool()->Run<AllocateGlobsOfMemoryTask>(
isolate, &done_monitor[i], &done[i]);
isolate_group, &done_monitor[i], &done[i]);
}
for (int i = 0; i < NUMBER_TEST_THREADS; i++) {