| Index: runtime/vm/isolate.cc
 | 
| diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc
 | 
| index 379287a67b4f94a77a36c0263c45cb0529b70d12..e05790b900e296289170ad7a2ead0cd5794b82da 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);
 | 
| @@ -768,6 +770,7 @@ void Isolate::InitOnce() {
 | 
|    create_callback_ = NULL;
 | 
|    isolates_list_monitor_ = new Monitor();
 | 
|    ASSERT(isolates_list_monitor_ != NULL);
 | 
| +  EnableIsolateCreation();
 | 
|  }
 | 
|  
 | 
|  
 | 
| @@ -846,8 +849,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;
 | 
|  }
 | 
| @@ -1462,6 +1471,70 @@ 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.
 | 
| +  Thread* thread = Thread::Current();
 | 
| +  StackZone stack_zone(thread);
 | 
| +  HandleScope handle_scope(thread);
 | 
| +  NoSafepointScope no_safepoint_scope;
 | 
| +
 | 
| +  if (compiler_stats_ != NULL) {
 | 
| +    OS::Print("%s", compiler_stats()->PrintToZone());
 | 
| +  }
 | 
| +
 | 
| +  // 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();
 | 
| +
 | 
| +  // Before analyzing the isolate's timeline blocks- close all of them.
 | 
| +  CloseAllTimelineBlocks();
 | 
| +
 | 
| +  // Dump all timing data for the isolate.
 | 
| +  if (FLAG_timing) {
 | 
| +    TimelinePauseTrace tpt;
 | 
| +    tpt.Print();
 | 
| +  }
 | 
| +
 | 
| +  // 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();
 | 
| +    MegamorphicCacheTable::PrintSizes(this);
 | 
| +    Symbols::DumpStats();
 | 
| +    OS::Print("[-] Stopping isolate:\n"
 | 
| +              "\tisolate:    %s\n", name());
 | 
| +  }
 | 
| +  if (FLAG_print_metrics) {
 | 
| +    LogBlock lb;
 | 
| +    THR_Print("Printing metrics for %s\n", name());
 | 
| +#define ISOLATE_METRIC_PRINT(type, variable, name, unit)                       \
 | 
| +  THR_Print("%s\n", metric_##variable##_.ToString());
 | 
| +
 | 
| +    ISOLATE_METRIC_LIST(ISOLATE_METRIC_PRINT);
 | 
| +#undef ISOLATE_METRIC_PRINT
 | 
| +    THR_Print("\n");
 | 
| +  }
 | 
| +}
 | 
| +
 | 
| +
 | 
|  void Isolate::Shutdown() {
 | 
|    ASSERT(this == Isolate::Current());
 | 
|    ASSERT(top_resource() == NULL);
 | 
| @@ -1481,7 +1554,10 @@ void Isolate::Shutdown() {
 | 
|      HandleScope handle_scope(thread);
 | 
|  
 | 
|      // Write out the coverage data if collection has been enabled.
 | 
| -    CodeCoverage::Write(this);
 | 
| +    if ((this != Dart::vm_isolate()) &&
 | 
| +        !ServiceIsolate::IsServiceIsolateDescendant(this)) {
 | 
| +      CodeCoverage::Write(this);
 | 
| +    }
 | 
|    }
 | 
|  
 | 
|    // Remove this isolate from the list *before* we start tearing it down, to
 | 
| @@ -1499,66 +1575,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(thread);
 | 
| -    HandleScope handle_scope(thread);
 | 
| -    NoSafepointScope no_safepoint_scope;
 | 
| -
 | 
| -    if (compiler_stats_ != NULL) {
 | 
| -      OS::Print("%s", compiler_stats()->PrintToZone());
 | 
| -    }
 | 
| -
 | 
| -    // 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();
 | 
| -
 | 
| -    // Before analyzing the isolate's timeline blocks- close all of them.
 | 
| -    CloseAllTimelineBlocks();
 | 
| -
 | 
| -    // Dump all timing data for the isolate.
 | 
| -    if (FLAG_timing) {
 | 
| -      TimelinePauseTrace tpt;
 | 
| -      tpt.Print();
 | 
| -    }
 | 
| -
 | 
| -    // 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();
 | 
| -      MegamorphicCacheTable::PrintSizes(this);
 | 
| -      Symbols::DumpStats();
 | 
| -      OS::Print("[-] Stopping isolate:\n"
 | 
| -                "\tisolate:    %s\n", name());
 | 
| -    }
 | 
| -    if (FLAG_print_metrics) {
 | 
| -      LogBlock lb;
 | 
| -      THR_Print("Printing metrics for %s\n", name());
 | 
| -#define ISOLATE_METRIC_PRINT(type, variable, name, unit)                       \
 | 
| -  THR_Print("%s\n", metric_##variable##_.ToString());
 | 
| -  ISOLATE_METRIC_LIST(ISOLATE_METRIC_PRINT);
 | 
| -#undef ISOLATE_METRIC_PRINT
 | 
| -      THR_Print("\n");
 | 
| -    }
 | 
| -  }
 | 
| +  LowLevelShutdown();
 | 
|  
 | 
|  #if defined(DEBUG)
 | 
|    // No concurrent sweeper tasks should be running at this point.
 | 
| @@ -1602,7 +1619,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,
 | 
| @@ -2112,12 +2129,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;
 | 
|  }
 | 
|  
 | 
|  
 | 
| @@ -2126,6 +2147,9 @@ void Isolate::RemoveIsolateFromList(Isolate* isolate) {
 | 
|    ASSERT(isolate != NULL);
 | 
|    if (isolate == isolates_list_head_) {
 | 
|      isolates_list_head_ = isolate->next_;
 | 
| +    if (!creation_enabled_) {
 | 
| +      ml.Notify();
 | 
| +    }
 | 
|      return;
 | 
|    }
 | 
|    Isolate* previous = NULL;
 | 
| @@ -2134,12 +2158,28 @@ void Isolate::RemoveIsolateFromList(Isolate* isolate) {
 | 
|      if (current == isolate) {
 | 
|        ASSERT(previous != NULL);
 | 
|        previous->next_ = current->next_;
 | 
| +      if (!creation_enabled_) {
 | 
| +        ml.Notify();
 | 
| +      }
 | 
|        return;
 | 
|      }
 | 
|      previous = current;
 | 
|      current = current->next_;
 | 
|    }
 | 
| -  UNREACHABLE();
 | 
| +  // If we are shutting down the VM, the isolate may not be in the list.
 | 
| +  ASSERT(!creation_enabled_);
 | 
| +}
 | 
| +
 | 
| +
 | 
| +void Isolate::DisableIsolateCreation() {
 | 
| +  MonitorLocker ml(isolates_list_monitor_);
 | 
| +  creation_enabled_ = false;
 | 
| +}
 | 
| +
 | 
| +
 | 
| +void Isolate::EnableIsolateCreation() {
 | 
| +  MonitorLocker ml(isolates_list_monitor_);
 | 
| +  creation_enabled_ = true;
 | 
|  }
 | 
|  
 | 
|  
 | 
| @@ -2151,6 +2191,93 @@ C* Isolate::AllocateReusableHandle() {
 | 
|  }
 | 
|  
 | 
|  
 | 
| +void Isolate::KillLocked() {
 | 
| +  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() : target_(NULL) {}
 | 
| +
 | 
| +  explicit IsolateKillerVisitor(Isolate* isolate)
 | 
| +      : target_(isolate) {
 | 
| +    ASSERT(isolate != Dart::vm_isolate());
 | 
| +  }
 | 
| +
 | 
| +  virtual ~IsolateKillerVisitor() {}
 | 
| +
 | 
| +  void VisitIsolate(Isolate* isolate) {
 | 
| +    ASSERT(isolate != NULL);
 | 
| +    if (ShouldKill(isolate)) {
 | 
| +      isolate->KillLocked();
 | 
| +    }
 | 
| +  }
 | 
| +
 | 
| + private:
 | 
| +  bool ShouldKill(Isolate* isolate) {
 | 
| +    // If a target_ is specified, then only kill the target_.
 | 
| +    // Otherwise, don't kill the service isolate or vm isolate.
 | 
| +    return (((target_ != NULL) && (isolate == target_)) ||
 | 
| +            ((target_ == NULL) &&
 | 
| +             !ServiceIsolate::IsServiceIsolateDescendant(isolate) &&
 | 
| +             (isolate != Dart::vm_isolate())));
 | 
| +  }
 | 
| +
 | 
| +  Isolate* target_;
 | 
| +};
 | 
| +
 | 
| +
 | 
| +void Isolate::KillAllIsolates() {
 | 
| +  IsolateKillerVisitor visitor;
 | 
| +  VisitIsolates(&visitor);
 | 
| +}
 | 
| +
 | 
| +
 | 
| +void Isolate::KillIfExists(Isolate* isolate) {
 | 
| +  IsolateKillerVisitor visitor(isolate);
 | 
| +  VisitIsolates(&visitor);
 | 
| +}
 | 
| +
 | 
| +
 | 
|  static RawInstance* DeserializeObject(Thread* thread,
 | 
|                                        uint8_t* obj_data,
 | 
|                                        intptr_t obj_len) {
 | 
| 
 |