| Index: runtime/vm/isolate.cc | 
| diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc | 
| index 16b70e466c5ecd6054680bbd4b05c90e9340ea08..ec61d1adf6aef53be3019ebb2a4703def9fc2bac 100644 | 
| --- a/runtime/vm/isolate.cc | 
| +++ b/runtime/vm/isolate.cc | 
| @@ -1433,12 +1433,28 @@ void Isolate::Shutdown() { | 
| } | 
| #endif  // DEBUG | 
|  | 
| +  // First, perform higher-level cleanup that may need to allocate. | 
| +  { | 
| +    // Ensure we have a zone and handle scope so that we can call VM functions. | 
| +    StackZone stack_zone(this); | 
| +    HandleScope handle_scope(this); | 
| + | 
| +    // Write out the coverage data if collection has been enabled. | 
| +    CodeCoverage::Write(this); | 
| + | 
| +    if ((timeline_event_recorder_ != NULL) && | 
| +        (FLAG_timeline_trace_dir != NULL)) { | 
| +      timeline_event_recorder_->WriteTo(FLAG_timeline_trace_dir); | 
| +    } | 
| +  } | 
| + | 
| // Remove this isolate from the list *before* we start tearing it down, to | 
| // avoid exposing it in a state of decay. | 
| RemoveIsolateFromList(this); | 
|  | 
| if (heap_ != NULL) { | 
| // Wait for any concurrent GC tasks to finish before shutting down. | 
| +    // TODO(koda): Support faster sweeper shutdown (e.g., after current page). | 
| PageSpace* old_space = heap_->old_space(); | 
| MonitorLocker ml(old_space->tasks_lock()); | 
| while (old_space->tasks() > 0) { | 
| @@ -1446,11 +1462,13 @@ void Isolate::Shutdown() { | 
| } | 
| } | 
|  | 
| -  // Create an area where we do have a zone and a handle scope so that we can | 
| -  // call VM functions while tearing this isolate down. | 
| +  // 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(); | 
| @@ -1474,9 +1492,6 @@ void Isolate::Shutdown() { | 
| // Dump all accumulated timer data for the isolate. | 
| timer_list_.ReportTimers(); | 
|  | 
| -    // Write out the coverage data if collection has been enabled. | 
| -    CodeCoverage::Write(this); | 
| - | 
| // Finalize any weak persistent handles with a non-null referent. | 
| FinalizeWeakPersistentHandlesVisitor visitor; | 
| api_state()->weak_persistent_handles().VisitHandles(&visitor); | 
| @@ -1489,12 +1504,16 @@ void Isolate::Shutdown() { | 
| OS::Print("[-] Stopping isolate:\n" | 
| "\tisolate:    %s\n", name()); | 
| } | 
| +  } | 
|  | 
| -    if ((timeline_event_recorder_ != NULL) && | 
| -        (FLAG_timeline_trace_dir != NULL)) { | 
| -      timeline_event_recorder_->WriteTo(FLAG_timeline_trace_dir); | 
| -    } | 
| +#if defined(DEBUG) | 
| +  // No concurrent sweeper tasks should be running at this point. | 
| +  if (heap_ != NULL) { | 
| +    PageSpace* old_space = heap_->old_space(); | 
| +    MonitorLocker ml(old_space->tasks_lock()); | 
| +    ASSERT(old_space->tasks() == 0); | 
| } | 
| +#endif | 
|  | 
| // TODO(5411455): For now just make sure there are no current isolates | 
| // as we are shutting down the isolate. | 
|  |