Index: runtime/vm/isolate.cc |
diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc |
index 614ab37f4b8582ff528e080019e69490951b689b..477459207338229cccf7ae9b2b14b26ce1f5ac80 100644 |
--- a/runtime/vm/isolate.cc |
+++ b/runtime/vm/isolate.cc |
@@ -822,7 +822,7 @@ Isolate::Isolate(const Dart_IsolateFlags& api_flags) |
cha_invalidation_gen_(kInvalidGen), |
field_invalidation_gen_(kInvalidGen), |
prefix_invalidation_gen_(kInvalidGen), |
- boxed_field_list_monitor_(new Monitor()), |
+ boxed_field_list_mutex_(new Mutex()), |
boxed_field_list_(GrowableObjectArray::null()), |
spawn_count_monitor_(new Monitor()), |
spawn_count_(0) { |
@@ -863,8 +863,8 @@ Isolate::~Isolate() { |
object_id_ring_ = NULL; |
delete pause_loop_monitor_; |
pause_loop_monitor_ = NULL; |
- delete boxed_field_list_monitor_; |
- boxed_field_list_monitor_ = NULL; |
+ delete boxed_field_list_mutex_; |
+ boxed_field_list_mutex_ = NULL; |
ASSERT(spawn_count_ == 0); |
delete spawn_count_monitor_; |
if (compiler_stats_ != NULL) { |
@@ -1869,7 +1869,7 @@ void Isolate::VisitObjectPointers(ObjectPointerVisitor* visitor, |
// Visit the boxed_field_list. |
// 'boxed_field_list_' access via mutator and background compilation threads |
// is guarded with a monitor. This means that we can visit it only |
- // when at safepoint or the boxed_field_list_monitor_ lock has been taken. |
+ // when at safepoint or the boxed_field_list_mutex_ lock has been taken. |
visitor->VisitPointer(reinterpret_cast<RawObject**>(&boxed_field_list_)); |
// Visit objects in the debugger. |
@@ -2083,7 +2083,9 @@ void Isolate::set_registered_service_extension_handlers( |
void Isolate::AddDeoptimizingBoxedField(const Field& field) { |
ASSERT(field.IsOriginal()); |
- MonitorLocker ml(boxed_field_list_monitor_); |
+ // The enclosed code allocates objects and can potentially trigger a GC, |
+ // ensure that we account for safepoints when grabbing the lock. |
+ SafepointMutexLocker ml(boxed_field_list_mutex_); |
if (boxed_field_list_ == GrowableObjectArray::null()) { |
boxed_field_list_ = GrowableObjectArray::New(Heap::kOld); |
} |
@@ -2094,7 +2096,7 @@ void Isolate::AddDeoptimizingBoxedField(const Field& field) { |
RawField* Isolate::GetDeoptimizingBoxedField() { |
- MonitorLocker ml(boxed_field_list_monitor_); |
+ MutexLocker ml(boxed_field_list_mutex_); |
if (boxed_field_list_ == GrowableObjectArray::null()) { |
return Field::null(); |
} |
@@ -2317,9 +2319,9 @@ void Isolate::PauseEventHandler() { |
// Handle all available vm service messages, up to a resume |
// request. |
while (!resume && Dart_HasServiceMessages()) { |
- pause_loop_monitor_->Exit(); |
+ ml.Exit(); |
resume = Dart_HandleServiceMessages(); |
- pause_loop_monitor_->Enter(); |
+ ml.Enter(); |
} |
if (resume) { |
break; |
@@ -2338,7 +2340,9 @@ void Isolate::VisitIsolates(IsolateVisitor* visitor) { |
if (visitor == NULL) { |
return; |
} |
- MonitorLocker ml(isolates_list_monitor_); |
+ // The visitor could potentially run code that could safepoint so use |
+ // SafepointMonitorLocker to ensure the lock has safepoint checks. |
+ SafepointMonitorLocker ml(isolates_list_monitor_); |
Isolate* current = isolates_list_head_; |
while (current) { |
visitor->VisitIsolate(current); |
@@ -2528,7 +2532,12 @@ Thread* Isolate::ScheduleThread(bool is_mutator, bool bypass_safepoint) { |
Thread* thread = NULL; |
OSThread* os_thread = OSThread::Current(); |
if (os_thread != NULL) { |
- MonitorLocker ml(threads_lock()); |
+ // We are about to associate the thread with an isolate and it would |
+ // not be possible to correctly track no_safepoint_scope_depth for the |
+ // thread in the constructor/destructor of MonitorLocker, |
+ // so we create a MonitorLocker object which does not do any |
+ // no_safepoint_scope_depth increments/decrements. |
+ MonitorLocker ml(threads_lock(), false); |
// If a safepoint operation is in progress wait for it |
// to finish before scheduling this thread in. |
@@ -2548,6 +2557,7 @@ Thread* Isolate::ScheduleThread(bool is_mutator, bool bypass_safepoint) { |
ASSERT(thread->execution_state() == Thread::kThreadInVM); |
thread->set_safepoint_state(0); |
thread->set_vm_tag(VMTag::kVMTagId); |
+ ASSERT(thread->no_safepoint_scope_depth() == 0); |
os_thread->set_thread(thread); |
if (is_mutator) { |
mutator_thread_ = thread; |
@@ -2564,7 +2574,12 @@ void Isolate::UnscheduleThread(Thread* thread, |
bool bypass_safepoint) { |
// Disassociate the 'Thread' structure and unschedule the thread |
// from this isolate. |
- MonitorLocker ml(threads_lock()); |
+ // We are disassociating the thread from an isolate and it would |
+ // not be possible to correctly track no_safepoint_scope_depth for the |
+ // thread in the constructor/destructor of MonitorLocker, |
+ // so we create a MonitorLocker object which does not do any |
+ // no_safepoint_scope_depth increments/decrements. |
+ MonitorLocker ml(threads_lock(), false); |
if (!bypass_safepoint) { |
// Ensure that the thread reports itself as being at a safepoint. |
thread->EnterSafepoint(); |
@@ -2582,6 +2597,7 @@ void Isolate::UnscheduleThread(Thread* thread, |
thread->set_os_thread(NULL); |
thread->set_execution_state(Thread::kThreadInVM); |
thread->set_safepoint_state(0); |
+ ASSERT(thread->no_safepoint_scope_depth() == 0); |
// Return thread structure. |
thread_registry()->ReturnThreadLocked(is_mutator, thread); |
} |