Index: runtime/vm/isolate.cc |
diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc |
index fcbf9c483775f350396dc4110804f6367429e2d0..064ba77d5b5c1ceb54e1f277534a7532ff47fe71 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); |
@@ -749,6 +751,7 @@ void Isolate::InitOnce() { |
create_callback_ = NULL; |
isolates_list_monitor_ = new Monitor(); |
ASSERT(isolates_list_monitor_ != NULL); |
+ EnableIsolateCreation(); |
} |
@@ -827,8 +830,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; |
} |
@@ -1454,6 +1463,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); |
@@ -1471,7 +1524,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)) { |
@@ -1494,48 +1550,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. |
@@ -1568,7 +1583,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, |
@@ -1917,12 +1932,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; |
} |
@@ -1944,7 +1963,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_); |
} |
@@ -1961,6 +1981,18 @@ void Isolate::CheckForDuplicateThreadState(InterruptableThreadState* state) { |
#endif |
+void Isolate::DisableIsolateCreation() { |
+ MonitorLocker ml(isolates_list_monitor_); |
+ 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()); |
@@ -1969,6 +2001,73 @@ T* Isolate::AllocateReusableHandle() { |
} |
+void Isolate::KillIsolate(Isolate* isolate) { |
+ 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 = isolate->terminate_capability(); |
+ list_values[2] = ∩ |
+ |
+ Dart_CObject imm; |
+ imm.type = Dart_CObject_kInt32; |
+ imm.value.as_int32 = IsolateMessageHandler::kImmediateAction; |
+ list_values[3] = &imm; |
+ |
+ isolate->ScheduleInterrupts(Isolate::kMessageInterrupt); |
+ { |
+ 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(isolate->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::KillIsolate(isolate); |
+ } |
+}; |
+ |
+ |
+void Isolate::KillAllIsolates() { |
+ IsolateKillerVisitor visitor; |
+ VisitIsolates(&visitor); |
+} |
+ |
+ |
static RawInstance* DeserializeObject(Isolate* isolate, |
Zone* zone, |
uint8_t* obj_data, |