Notify kernel service of isolate shutdown.

This is needed to clean up compiler associated with the isolate.

Bug: dartbug.com/33428
Change-Id: Ia5c0ac38e30d39a4feb946efca77d197c4e0d7a4
Reviewed-on: https://dart-review.googlesource.com/61113
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Reviewed-by: Alexander Markov <alexmarkov@google.com>
Commit-Queue: Alexander Aprelev <aam@google.com>
diff --git a/pkg/vm/bin/kernel_service.dart b/pkg/vm/bin/kernel_service.dart
index eedfdee..7ec5b51 100644
--- a/pkg/vm/bin/kernel_service.dart
+++ b/pkg/vm/bin/kernel_service.dart
@@ -53,12 +53,14 @@
 //   4 - Compile an individual expression in some context (for debugging
 //       purposes).
 //   5 - List program dependencies (for creating depfiles)
+//   6 - Isolate shutdown that potentially should result in compiler cleanup.
 const int kCompileTag = 0;
 const int kUpdateSourcesTag = 1;
 const int kAcceptTag = 2;
 const int kTrainTag = 3;
 const int kCompileExpressionTag = 4;
 const int kListDependenciesTag = 5;
+const int kNotifyIsolateShutdownTag = 6;
 
 bool allowDartInternalImport = false;
 
@@ -345,6 +347,12 @@
   port.send(result.toResponse());
 }
 
+Future _processIsolateShutdownNotification(request) async {
+  final int isolateId = request[1];
+  isolateCompilers.remove(isolateId);
+  isolateDependencies.remove(isolateId);
+}
+
 Future _processLoadRequest(request) async {
   if (verbose) print("DFE: request: $request");
 
@@ -360,6 +368,11 @@
     return;
   }
 
+  if (tag == kNotifyIsolateShutdownTag) {
+    await _processIsolateShutdownNotification(request);
+    return;
+  }
+
   final SendPort port = request[1];
   final String inputFileUri = request[2];
   final Uri script =
diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc
index af5f2ad..21ab5e0 100644
--- a/runtime/vm/isolate.cc
+++ b/runtime/vm/isolate.cc
@@ -1854,6 +1854,10 @@
           "--check-reloaded is enabled.\n");
     }
   }
+
+  // TODO(33514): Ideally this should be moved to Dart_ShutdownIsolate,
+  // next to ServiceIsolate::SendIsolateShutdownMessage().
+  KernelIsolate::NotifyAboutIsolateShutdown(Isolate::Current());
 #endif  // !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
 
   // Then, proceed with low-level teardown.
diff --git a/runtime/vm/kernel_isolate.cc b/runtime/vm/kernel_isolate.cc
index 0cfc0a0..b5efb44 100644
--- a/runtime/vm/kernel_isolate.cc
+++ b/runtime/vm/kernel_isolate.cc
@@ -54,6 +54,7 @@
 const int KernelIsolate::kTrainTag = 3;
 const int KernelIsolate::kCompileExpressionTag = 4;
 const int KernelIsolate::kListDependenciesTag = 5;
+const int KernelIsolate::kNotifyIsolateShutdown = 6;
 
 Dart_IsolateCreateCallback KernelIsolate::create_callback_ = NULL;
 Monitor* KernelIsolate::monitor_ = new Monitor();
@@ -787,6 +788,34 @@
                                         NULL, 0, source_files_count,
                                         source_files, true, NULL);
 }
+
+void KernelIsolate::NotifyAboutIsolateShutdown(const Isolate* isolate) {
+  if (!KernelIsolate::IsRunning()) {
+    return;
+  }
+  Dart_Port kernel_port = WaitForKernelPort();
+  if (kernel_port == ILLEGAL_PORT) {
+    return;
+  }
+
+  Dart_CObject tag;
+  tag.type = Dart_CObject_kInt32;
+  tag.value.as_int32 = KernelIsolate::kNotifyIsolateShutdown;
+
+  Dart_CObject isolate_id;
+  isolate_id.type = Dart_CObject_kInt64;
+  isolate_id.value.as_int64 =
+      isolate != NULL ? static_cast<int64_t>(isolate->main_port()) : 0;
+
+  Dart_CObject message;
+  message.type = Dart_CObject_kArray;
+  Dart_CObject* message_arr[] = {&tag, &isolate_id};
+  message.value.as_array.values = message_arr;
+  message.value.as_array.length = ARRAY_SIZE(message_arr);
+  // Send the message.
+  Dart_PostCObject(kernel_port, &message);
+}
+
 #endif  // DART_PRECOMPILED_RUNTIME
 
 }  // namespace dart
diff --git a/runtime/vm/kernel_isolate.h b/runtime/vm/kernel_isolate.h
index d888630..5275308 100644
--- a/runtime/vm/kernel_isolate.h
+++ b/runtime/vm/kernel_isolate.h
@@ -27,6 +27,7 @@
   static const int kTrainTag;
   static const int kCompileExpressionTag;
   static const int kListDependenciesTag;
+  static const int kNotifyIsolateShutdown;
 
   static void Run();
 
@@ -61,6 +62,8 @@
 
   static Dart_KernelCompilationResult ListDependencies();
 
+  static void NotifyAboutIsolateShutdown(const Isolate* isolate);
+
  protected:
   static Monitor* monitor_;
   static Dart_IsolateCreateCallback create_callback_;