Index: runtime/vm/isolate.cc |
diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc |
index abe9dda1ca83b1fb9e85bee5d6b66a63105de69b..bb493ab7508f0a6fb313db217925e7cd5335cfa7 100644 |
--- a/runtime/vm/isolate.cc |
+++ b/runtime/vm/isolate.cc |
@@ -315,6 +315,8 @@ Isolate::Isolate() |
cha_used_(false), |
object_id_ring_(NULL), |
profiler_data_(NULL), |
+ thread_state_(NULL), |
+ next_(NULL), |
REUSABLE_HANDLE_LIST(REUSABLE_HANDLE_INITIALIZERS) |
reusable_handles_() { |
if (FLAG_print_object_histogram && (Dart::vm_isolate() != NULL)) { |
@@ -343,12 +345,23 @@ Isolate::~Isolate() { |
delete spawn_state_; |
} |
+ |
void Isolate::SetCurrent(Isolate* current) { |
Isolate* old_current = Current(); |
- if (old_current != current) { |
+ if (old_current != NULL) { |
+ old_current->set_thread_state(NULL); |
Profiler::EndExecution(old_current); |
- Thread::SetThreadLocal(isolate_key, reinterpret_cast<uword>(current)); |
+ } |
+ Thread::SetThreadLocal(isolate_key, reinterpret_cast<uword>(current)); |
+ if (current != NULL) { |
+ ASSERT(current->thread_state() == NULL); |
+ InterruptableThreadState* thread_state = |
+ ThreadInterrupter::GetCurrentThreadState(); |
+#if defined(DEBUG) |
+ CheckForDuplicateThreadState(thread_state); |
+#endif |
Profiler::BeginExecution(current); |
+ current->set_thread_state(thread_state); |
} |
} |
@@ -365,6 +378,8 @@ void Isolate::InitOnce() { |
isolate_key = Thread::CreateThreadLocal(); |
ASSERT(isolate_key != Thread::kUnsetThreadLocalKey); |
create_callback_ = NULL; |
+ isolates_list_monitor_ = new Monitor(); |
+ ASSERT(isolates_list_monitor_ != NULL); |
} |
@@ -375,6 +390,9 @@ Isolate* Isolate::Init(const char* name_prefix) { |
// Setup for profiling. |
Profiler::InitProfilingForIsolate(result); |
+ // Add to isolate list. |
+ AddIsolateTolist(result); |
+ |
// TODO(5411455): For now just set the recently created isolate as |
// the current isolate. |
SetCurrent(result); |
@@ -749,6 +767,7 @@ void Isolate::Shutdown() { |
// TODO(5411455): For now just make sure there are no current isolates |
// as we are shutting down the isolate. |
SetCurrent(NULL); |
+ RemoveIsolateFromList(this); |
Profiler::ShutdownProfilingForIsolate(this); |
} |
@@ -766,6 +785,10 @@ Dart_EntropySource Isolate::entropy_source_callback_ = NULL; |
Dart_IsolateInterruptCallback Isolate::vmstats_callback_ = NULL; |
Dart_ServiceIsolateCreateCalback Isolate::service_create_callback_ = NULL; |
+Monitor* Isolate::isolates_list_monitor_ = NULL; |
+Isolate* Isolate::isolates_list_head_ = NULL; |
+ |
+ |
void Isolate::VisitObjectPointers(ObjectPointerVisitor* visitor, |
bool visit_prologue_weak_handles, |
bool validate_frames) { |
@@ -866,6 +889,63 @@ void Isolate::PrintToJSONStream(JSONStream* stream) { |
} |
+void Isolate::VisitIsolates(IsolateVisitor* visitor) { |
+ if (visitor == NULL) { |
+ return; |
+ } |
+ MonitorLocker ml(isolates_list_monitor_); |
+ Isolate* current = isolates_list_head_; |
+ while (current) { |
+ visitor->VisitIsolate(current); |
+ current = current->next_; |
+ } |
+} |
+ |
+ |
+void Isolate::AddIsolateTolist(Isolate* isolate) { |
+ MonitorLocker ml(isolates_list_monitor_); |
+ ASSERT(isolate != NULL); |
+ ASSERT(isolate->next_ == NULL); |
+ isolate->next_ = isolates_list_head_; |
+ isolates_list_head_ = isolate; |
+} |
+ |
+ |
+void Isolate::RemoveIsolateFromList(Isolate* isolate) { |
+ MonitorLocker ml(isolates_list_monitor_); |
+ ASSERT(isolate != NULL); |
+ if (isolate == isolates_list_head_) { |
+ isolates_list_head_ = isolate->next_; |
+ return; |
+ } |
+ Isolate* previous = NULL; |
+ Isolate* current = isolates_list_head_; |
+ while (current) { |
+ if (current == isolate) { |
+ ASSERT(previous != NULL); |
+ previous->next_ = current->next_; |
+ return; |
+ } |
+ previous = current; |
+ current = current->next_; |
+ } |
+ UNREACHABLE(); |
+} |
+ |
+ |
+#if defined(DEBUG) |
+void Isolate::CheckForDuplicateThreadState(InterruptableThreadState* state) { |
+ MonitorLocker ml(isolates_list_monitor_); |
+ ASSERT(state != NULL); |
+ Isolate* current = isolates_list_head_; |
+ while (current) { |
+ ASSERT(current->thread_state() != state); |
+ current = current->next_; |
+ } |
+} |
+#endif |
+ |
+ |
template<class T> |
T* Isolate::AllocateReusableHandle() { |
T* handle = reinterpret_cast<T*>(reusable_handles_.AllocateScopedHandle()); |