Chromium Code Reviews| Index: runtime/vm/isolate.cc |
| diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc |
| index 9825341b4d3460dde8b9efe5e0ed59308dea2938..bdd1d7dc544325cec94664e243ed0f20aad6ae6c 100644 |
| --- a/runtime/vm/isolate.cc |
| +++ b/runtime/vm/isolate.cc |
| @@ -5,11 +5,13 @@ |
| #include "vm/isolate.h" |
| #include "include/dart_api.h" |
| +#include "include/dart_native_api.h" |
| #include "platform/assert.h" |
| #include "platform/json.h" |
| #include "vm/code_observers.h" |
| #include "vm/compiler_stats.h" |
| #include "vm/coverage.h" |
| +#include "vm/dart_api_message.h" |
| #include "vm/dart_api_state.h" |
| #include "vm/dart_entry.h" |
| #include "vm/debugger.h" |
| @@ -165,7 +167,6 @@ class IsolateMessageHandler : public MessageHandler { |
| bool IsCurrentIsolate() const; |
| virtual Isolate* isolate() const { return isolate_; } |
| - private: |
| // Keep both these enums in sync with isolate_patch.dart. |
| // The different Isolate API message types. |
| enum { |
| @@ -186,6 +187,7 @@ class IsolateMessageHandler : public MessageHandler { |
| kAsEventAction = 2 |
| }; |
| + private: |
| // A result of false indicates that the isolate should terminate the |
| // processing of further events. |
| bool HandleLibMessage(const Array& message); |
| @@ -752,6 +754,7 @@ void Isolate::InitOnce() { |
| create_callback_ = NULL; |
| isolates_list_monitor_ = new Monitor(); |
| ASSERT(isolates_list_monitor_ != NULL); |
| + EnableIsolateCreation(); |
| } |
| @@ -830,8 +833,14 @@ Isolate* Isolate::Init(const char* name_prefix, |
| result->compiler_stats_ = new CompilerStats(result); |
| } |
| ObjectIdRing::Init(result); |
| - // Add to isolate list. |
| - AddIsolateTolist(result); |
| + |
| + // Add to isolate list. Shutdown and delete the isolate on failure. |
| + if (!AddIsolateToList(result)) { |
| + result->LowLevelShutdown(); |
| + Thread::ExitIsolate(); |
| + delete result; |
| + return NULL; |
| + } |
| return result; |
| } |
| @@ -1458,6 +1467,50 @@ class FinalizeWeakPersistentHandlesVisitor : public HandleVisitor { |
| }; |
| +void Isolate::LowLevelShutdown() { |
| + // Ensure we have a zone and handle scope so that we can call VM functions, |
| + // but we no longer allocate new heap objects. |
| + StackZone stack_zone(this); |
| + HandleScope handle_scope(this); |
| + NoSafepointScope no_safepoint_scope; |
| + |
| + if (compiler_stats_ != NULL) { |
| + compiler_stats()->Print(); |
| + } |
| + |
| + // Notify exit listeners that this isolate is shutting down. |
| + if (object_store() != NULL) { |
| + NotifyExitListeners(); |
| + } |
| + |
| + // Clean up debugger resources. |
| + debugger()->Shutdown(); |
| + |
| + // Close all the ports owned by this isolate. |
| + PortMap::ClosePorts(message_handler()); |
| + |
| + // Fail fast if anybody tries to post any more messsages to this isolate. |
| + delete message_handler(); |
| + set_message_handler(NULL); |
| + |
| + // Dump all accumulated timer data for the isolate. |
| + timer_list_.ReportTimers(); |
| + |
| + // Finalize any weak persistent handles with a non-null referent. |
| + FinalizeWeakPersistentHandlesVisitor visitor; |
| + api_state()->weak_persistent_handles().VisitHandles(&visitor); |
| + api_state()->prologue_weak_persistent_handles().VisitHandles(&visitor); |
| + |
| + if (FLAG_trace_isolates) { |
| + heap()->PrintSizes(); |
| + megamorphic_cache_table()->PrintSizes(); |
| + Symbols::DumpStats(); |
| + OS::Print("[-] Stopping isolate:\n" |
| + "\tisolate: %s\n", name()); |
| + } |
| +} |
| + |
| + |
| void Isolate::Shutdown() { |
| ASSERT(this == Isolate::Current()); |
| ASSERT(top_resource() == NULL); |
| @@ -1475,7 +1528,10 @@ void Isolate::Shutdown() { |
| HandleScope handle_scope(this); |
| // Write out the coverage data if collection has been enabled. |
| - CodeCoverage::Write(this); |
| + if ((this != Dart::vm_isolate()) && |
| + !ServiceIsolate::IsServiceIsolateDescendant(this)) { |
| + CodeCoverage::Write(this); |
| + } |
| if ((timeline_event_recorder_ != NULL) && |
| (FLAG_timeline_trace_dir != NULL)) { |
| @@ -1498,48 +1554,7 @@ void Isolate::Shutdown() { |
| } |
| // Then, proceed with low-level teardown. |
| - { |
| - // Ensure we have a zone and handle scope so that we can call VM functions, |
| - // but we no longer allocate new heap objects. |
| - StackZone stack_zone(this); |
| - HandleScope handle_scope(this); |
| - NoSafepointScope no_safepoint_scope; |
| - |
| - if (compiler_stats_ != NULL) { |
| - compiler_stats()->Print(); |
| - } |
| - |
| - // Notify exit listeners that this isolate is shutting down. |
| - if (object_store() != NULL) { |
| - NotifyExitListeners(); |
| - } |
| - |
| - // Clean up debugger resources. |
| - debugger()->Shutdown(); |
| - |
| - // Close all the ports owned by this isolate. |
| - PortMap::ClosePorts(message_handler()); |
| - |
| - // Fail fast if anybody tries to post any more messsages to this isolate. |
| - delete message_handler(); |
| - set_message_handler(NULL); |
| - |
| - // Dump all accumulated timer data for the isolate. |
| - timer_list_.ReportTimers(); |
| - |
| - // Finalize any weak persistent handles with a non-null referent. |
| - FinalizeWeakPersistentHandlesVisitor visitor; |
| - api_state()->weak_persistent_handles().VisitHandles(&visitor); |
| - api_state()->prologue_weak_persistent_handles().VisitHandles(&visitor); |
| - |
| - if (FLAG_trace_isolates) { |
| - heap()->PrintSizes(); |
| - megamorphic_cache_table()->PrintSizes(); |
| - Symbols::DumpStats(); |
| - OS::Print("[-] Stopping isolate:\n" |
| - "\tisolate: %s\n", name()); |
| - } |
| - } |
| + LowLevelShutdown(); |
| #if defined(DEBUG) |
| // No concurrent sweeper tasks should be running at this point. |
| @@ -1572,7 +1587,7 @@ Dart_EntropySource Isolate::entropy_source_callback_ = NULL; |
| Monitor* Isolate::isolates_list_monitor_ = NULL; |
| Isolate* Isolate::isolates_list_head_ = NULL; |
| - |
| +bool Isolate::creation_enabled_ = false; |
| void Isolate::IterateObjectPointers(ObjectPointerVisitor* visitor, |
| bool visit_prologue_weak_handles, |
| @@ -1913,12 +1928,16 @@ intptr_t Isolate::IsolateListLength() { |
| } |
| -void Isolate::AddIsolateTolist(Isolate* isolate) { |
| +bool Isolate::AddIsolateToList(Isolate* isolate) { |
| MonitorLocker ml(isolates_list_monitor_); |
| + if (!creation_enabled_) { |
| + return false; |
| + } |
| ASSERT(isolate != NULL); |
| ASSERT(isolate->next_ == NULL); |
| isolate->next_ = isolates_list_head_; |
| isolates_list_head_ = isolate; |
| + return true; |
| } |
| @@ -1940,7 +1959,8 @@ void Isolate::RemoveIsolateFromList(Isolate* isolate) { |
| previous = current; |
| current = current->next_; |
| } |
| - UNREACHABLE(); |
| + // If we are shutting down the VM, the isolate may not be in the list. |
| + ASSERT(!creation_enabled_); |
| } |
| @@ -1957,6 +1977,18 @@ void Isolate::CheckForDuplicateThreadState(InterruptableThreadState* state) { |
| #endif |
| +void Isolate::DisableIsolateCreation() { |
| + MonitorLocker ml(isolates_list_monitor_); |
|
Ivan Posva
2015/08/19 08:31:06
We should probably change this to a Mutex. Differe
zra
2015/08/25 18:19:30
Acknowledged.
|
| + creation_enabled_ = false; |
| +} |
| + |
| + |
| +void Isolate::EnableIsolateCreation() { |
| + MonitorLocker ml(isolates_list_monitor_); |
| + creation_enabled_ = true; |
| +} |
| + |
| + |
| template<class T> |
| T* Isolate::AllocateReusableHandle() { |
| T* handle = reinterpret_cast<T*>(reusable_handles_.AllocateScopedHandle()); |
| @@ -1965,6 +1997,72 @@ T* Isolate::AllocateReusableHandle() { |
| } |
| +void Isolate::Kill() { |
| + Dart_CObject kill_msg; |
| + Dart_CObject* list_values[4]; |
| + kill_msg.type = Dart_CObject_kArray; |
| + kill_msg.value.as_array.length = 4; |
| + kill_msg.value.as_array.values = list_values; |
| + |
| + Dart_CObject oob; |
| + oob.type = Dart_CObject_kInt32; |
| + oob.value.as_int32 = Message::kIsolateLibOOBMsg; |
| + list_values[0] = &oob; |
| + |
| + Dart_CObject kill; |
| + kill.type = Dart_CObject_kInt32; |
| + kill.value.as_int32 = IsolateMessageHandler::kKillMsg; |
| + list_values[1] = &kill; |
| + |
| + Dart_CObject cap; |
| + cap.type = Dart_CObject_kCapability; |
| + cap.value.as_capability.id = terminate_capability(); |
| + list_values[2] = ∩ |
| + |
| + Dart_CObject imm; |
| + imm.type = Dart_CObject_kInt32; |
| + imm.value.as_int32 = IsolateMessageHandler::kImmediateAction; |
| + list_values[3] = &imm; |
| + |
| + { |
| + uint8_t* buffer = NULL; |
| + ApiMessageWriter writer(&buffer, allocator); |
| + bool success = writer.WriteCMessage(&kill_msg); |
| + ASSERT(success); |
| + |
| + // Post the message at the given port. |
| + success = PortMap::PostMessage(new Message(main_port(), |
| + buffer, |
| + writer.BytesWritten(), |
| + Message::kOOBPriority)); |
| + ASSERT(success); |
| + } |
| +} |
| + |
| + |
| +class IsolateKillerVisitor : public IsolateVisitor { |
| + public: |
| + IsolateKillerVisitor() {} |
| + |
| + virtual ~IsolateKillerVisitor() {} |
| + |
| + void VisitIsolate(Isolate* isolate) { |
| + ASSERT(isolate != NULL); |
| + if (ServiceIsolate::IsServiceIsolateDescendant(isolate) || |
| + (isolate == Dart::vm_isolate())) { |
| + return; |
| + } |
| + isolate->Kill(); |
| + } |
| +}; |
| + |
| + |
| +void Isolate::KillAllIsolates() { |
| + IsolateKillerVisitor visitor; |
| + VisitIsolates(&visitor); |
| +} |
| + |
| + |
| static RawInstance* DeserializeObject(Isolate* isolate, |
| Zone* zone, |
| uint8_t* obj_data, |