Chromium Code Reviews| Index: runtime/vm/isolate.cc |
| diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc |
| index 10a157831940c77e053a422ed2e7a342e9aba3cd..0194308bf0ddcce88b2ebda253ccbd9f51ecbfe1 100644 |
| --- a/runtime/vm/isolate.cc |
| +++ b/runtime/vm/isolate.cc |
| @@ -314,6 +314,7 @@ Isolate::Isolate() |
| object_histogram_(NULL), |
| object_id_ring_(NULL), |
| profiler_data_(NULL), |
| + thread_state_(NULL), |
| REUSABLE_HANDLE_LIST(REUSABLE_HANDLE_INITIALIZERS) |
| reusable_handles_() { |
| if (FLAG_print_object_histogram && (Dart::vm_isolate() != NULL)) { |
| @@ -342,12 +343,20 @@ 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) { |
|
siva
2014/02/05 19:09:15
We also need
ASSERT(current->thread_state() == NUL
Cutch
2014/02/05 23:00:31
Done.
|
| +#if defined(DEBUG) |
| + CheckNoIsolateHasThreadData(ThreadInterrupter::GetCurrentThreadState()); |
| +#endif |
| Profiler::BeginExecution(current); |
| + current->set_thread_state(ThreadInterrupter::GetCurrentThreadState()); |
|
siva
2014/02/05 19:09:15
Why not have a local variable
InterruptibleThreadS
Cutch
2014/02/05 23:00:31
Done.
|
| } |
| } |
| @@ -364,6 +373,8 @@ void Isolate::InitOnce() { |
| isolate_key = Thread::CreateThreadLocal(); |
| ASSERT(isolate_key != Thread::kUnsetThreadLocalKey); |
| create_callback_ = NULL; |
| + isolates_monitor_ = new Monitor(); |
| + ASSERT(isolates_monitor_ != NULL); |
| } |
| @@ -374,6 +385,9 @@ Isolate* Isolate::Init(const char* name_prefix) { |
| // Setup for profiling. |
| Profiler::InitProfilingForIsolate(result); |
| + // Add to isolate list. |
| + IsolateCreated(result); |
| + |
| // TODO(5411455): For now just set the recently created isolate as |
| // the current isolate. |
| SetCurrent(result); |
| @@ -748,6 +762,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); |
| + IsolateShutdown(this); |
| Profiler::ShutdownProfilingForIsolate(this); |
| } |
| @@ -765,6 +780,11 @@ Dart_EntropySource Isolate::entropy_source_callback_ = NULL; |
| Dart_IsolateInterruptCallback Isolate::vmstats_callback_ = NULL; |
| Dart_ServiceIsolateCreateCalback Isolate::service_create_callback_ = NULL; |
| +Monitor* Isolate::isolates_monitor_ = NULL; |
| +Isolate** Isolate::isolates_ = NULL; |
| +intptr_t Isolate::isolates_capacity_ = 0; |
| +intptr_t Isolate::isolates_size_ = 0; |
| + |
| void Isolate::VisitObjectPointers(ObjectPointerVisitor* visitor, |
| bool visit_prologue_weak_handles, |
| bool validate_frames) { |
| @@ -865,6 +885,66 @@ void Isolate::PrintToJSONStream(JSONStream* stream) { |
| } |
| +void Isolate::IsolateCreated(Isolate* isolate) { |
| + MonitorLocker ml(isolates_monitor_); |
| + // Not currently registered in the isolates list. |
| + ASSERT(FindIsolateIndex(isolate) < 0); |
| + if (isolates_size_ == isolates_capacity_) { |
| + // Full, grow isolates array. |
| + ResizeIsolates(isolates_capacity_ == 0 ? 16 : isolates_capacity_ * 2); |
| + } |
| + // Add isolate to table. |
| + isolates_[isolates_size_] = isolate; |
| + isolates_size_++; |
| +} |
| + |
| + |
| +void Isolate::IsolateShutdown(Isolate* isolate) { |
| + MonitorLocker ml(isolates_monitor_); |
| + intptr_t index = FindIsolateIndex(isolate); |
| + ASSERT(index >= 0); |
| + intptr_t last = isolates_size_ - 1; |
| + if (index != last) { |
| + isolates_[index] = isolates_[last]; |
| + } |
| + isolates_[last] = NULL; |
| + isolates_size_--; |
| +} |
| + |
| + |
| +void Isolate::ResizeIsolates(intptr_t new_capacity) { |
| + // Must be called with isolates_monitor_ locked. |
| + ASSERT(new_capacity > isolates_capacity_); |
| + isolates_ = reinterpret_cast<Isolate**>( |
| + realloc(isolates_, sizeof(*isolates_) * new_capacity)); |
| + for (intptr_t i = isolates_capacity_; i < new_capacity; i++) { |
| + isolates_[i] = NULL; |
| + } |
| + isolates_capacity_ = new_capacity; |
| +} |
|
siva
2014/02/05 19:09:15
See comment on using a linked list for isolates li
|
| + |
| + |
| +intptr_t Isolate::FindIsolateIndex(Isolate* isolate) { |
| + // Must be called with isolates_monitor_ locked. |
| + for (intptr_t i = 0; i < isolates_size_; i++) { |
| + if (isolates_[i] == isolate) { |
| + return i; |
| + } |
| + } |
| + return -1; |
| +} |
|
siva
2014/02/05 19:09:15
If a singly linked list is used for isolates this
|
| + |
| + |
| +void Isolate::CheckNoIsolateHasThreadData(InterruptableThreadState* state) { |
|
siva
2014/02/05 19:09:15
I would call this CheckForDuplicateThreadState and
Cutch
2014/02/05 23:00:31
Done.
|
| + ASSERT(state != NULL); |
| + MonitorLocker ml(isolates_monitor_); |
| + for (intptr_t i = 0; i < isolates_size_; i++) { |
| + Isolate* isolate = isolates_[i]; |
| + ASSERT(isolate->thread_state() != state); |
| + } |
| +} |
| + |
| + |
| template<class T> |
| T* Isolate::AllocateReusableHandle() { |
| T* handle = reinterpret_cast<T*>(reusable_handles_.AllocateScopedHandle()); |