[VM] Use the incremental compiler to compile sources only when the observatory
server is started.

When the incremental compiler is used it accumulates state that
increases the footprint of the process. This state is needed only
when the 'reload' or 'expression evaluation' functionality is used
in the debugger.

Currently in the VM we do not have a good way of detecting when the
debugger will be used as the vm service observatory functionality
can be turned on dynamically after the program has started.

This CL turns on the incremental compiler only when command line options
are used to start the observatory server. We could run into issues with
'expression evaluation' when the observatory is started dynamically after
the program is loaded.

Change-Id: I18c17698622071bca428018f7fdac1a84b0f195e
Reviewed-on: https://dart-review.googlesource.com/64667
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Siva Annamalai <asiva@google.com>
diff --git a/pkg/vm/bin/kernel_service.dart b/pkg/vm/bin/kernel_service.dart
index 4d383d5..84825db 100644
--- a/pkg/vm/bin/kernel_service.dart
+++ b/pkg/vm/bin/kernel_service.dart
@@ -305,18 +305,20 @@
     int isolateId, Component component, String packageConfig) {
   final dependencies = isolateDependencies[isolateId] ??= new List<Uri>();
 
-  for (var lib in component.libraries) {
-    if (lib.importUri.scheme == "dart") continue;
+  if (component != null) {
+    for (var lib in component.libraries) {
+      if (lib.importUri.scheme == "dart") continue;
 
-    dependencies.add(lib.fileUri);
-    for (var part in lib.parts) {
-      final fileUri = lib.fileUri.resolve(part.partUri);
-      if (fileUri.scheme != "" && fileUri.scheme != "file") {
-        // E.g. part 'package:foo/foo.dart';
-        // Maybe the front end should resolve this?
-        continue;
+      dependencies.add(lib.fileUri);
+      for (var part in lib.parts) {
+        final fileUri = lib.fileUri.resolve(part.partUri);
+        if (fileUri.scheme != "" && fileUri.scheme != "file") {
+          // E.g. part 'package:foo/foo.dart';
+          // Maybe the front end should resolve this?
+          continue;
+        }
+        dependencies.add(fileUri);
       }
-      dependencies.add(fileUri);
     }
   }
 
@@ -447,7 +449,7 @@
     FileSystem fileSystem = _buildFileSystem(
         sourceFiles, platformKernel, multirootFilepaths, multirootScheme);
     compiler = new SingleShotCompilerWrapper(fileSystem, platformKernelPath,
-        requireMain: sourceFiles.isEmpty,
+        requireMain: false,
         strongMode: strong,
         suppressWarnings: suppressWarnings,
         syncAsync: syncAsync,
@@ -461,12 +463,17 @@
     }
 
     Component component = await compiler.compile(script);
-    _recordDependencies(isolateId, component, packageConfig);
 
     if (compiler.errors.isNotEmpty) {
-      result = new CompilationResult.errors(compiler.errors,
-          serializeComponent(component, filter: (lib) => !lib.isExternal));
+      if (component != null) {
+        result = new CompilationResult.errors(compiler.errors,
+            serializeComponent(component, filter: (lib) => !lib.isExternal));
+      } else {
+        result = new CompilationResult.errors(compiler.errors, null);
+      }
     } else {
+      // Record dependencies only if compilation was error free.
+      _recordDependencies(isolateId, component, packageConfig);
       // We serialize the component excluding vm_platform.dill because the VM has
       // these sources built-in. Everything loaded as a summary in
       // [kernelForProgram] is marked `external`, so we can use that bit to
diff --git a/runtime/bin/dfe.cc b/runtime/bin/dfe.cc
index 5f1721d..6c0dafb 100644
--- a/runtime/bin/dfe.cc
+++ b/runtime/bin/dfe.cc
@@ -81,6 +81,7 @@
 
 DFE::DFE()
     : use_dfe_(false),
+      use_incremental_compiler_(false),
       frontend_filename_(NULL),
       application_kernel_buffer_(NULL),
       application_kernel_buffer_size_(0) {}
@@ -218,8 +219,8 @@
                                int* exit_code,
                                bool strong,
                                const char* package_config) {
-  Dart_KernelCompilationResult result =
-      CompileScript(script_uri, strong, true, package_config);
+  Dart_KernelCompilationResult result = CompileScript(
+      script_uri, strong, use_incremental_compiler(), package_config);
   switch (result.status) {
     case Dart_KernelCompilationStatus_Ok:
       *kernel_buffer = result.kernel;
diff --git a/runtime/bin/dfe.h b/runtime/bin/dfe.h
index 6efb45c..433550f 100644
--- a/runtime/bin/dfe.h
+++ b/runtime/bin/dfe.h
@@ -34,6 +34,11 @@
   void set_use_dfe(bool value = true) { use_dfe_ = value; }
   bool UseDartFrontend() const { return use_dfe_; }
 
+  void set_use_incremental_compiler(bool value) {
+    use_incremental_compiler_ = value;
+  }
+  bool use_incremental_compiler() const { return use_incremental_compiler_; }
+
   // Returns the platform binary file name if the path to
   // kernel binaries was set using SetKernelBinaries.
   const char* GetPlatformBinaryFilename();
@@ -100,6 +105,7 @@
 
  private:
   bool use_dfe_;
+  bool use_incremental_compiler_;
   char* frontend_filename_;
 
   // Kernel binary specified on the cmd line.
diff --git a/runtime/bin/main_options.cc b/runtime/bin/main_options.cc
index cf88c86..ae4d441 100644
--- a/runtime/bin/main_options.cc
+++ b/runtime/bin/main_options.cc
@@ -296,6 +296,9 @@
         "Use --enable-vm-service[=<port number>[/<bind address>]]\n");
     return false;
   }
+#if !defined(DART_PRECOMPILED_RUNTIME)
+  dfe()->set_use_incremental_compiler(true);
+#endif  // !defined(DART_PRECOMPILED_RUNTIME)
 
   return true;
 }
@@ -320,6 +323,9 @@
   vm_options->AddArgument("--pause-isolates-on-unhandled-exceptions");
   vm_options->AddArgument("--profiler");
   vm_options->AddArgument("--warn-on-pause-with-no-debugger");
+#if !defined(DART_PRECOMPILED_RUNTIME)
+  dfe()->set_use_incremental_compiler(true);
+#endif  // !defined(DART_PRECOMPILED_RUNTIME)
   return true;
 }
 
diff --git a/tests/lib_2/mirrors/dynamic_load_test.dart b/tests/lib_2/mirrors/dynamic_load_test.dart
index 2605b8b..dddb1ac 100644
--- a/tests/lib_2/mirrors/dynamic_load_test.dart
+++ b/tests/lib_2/mirrors/dynamic_load_test.dart
@@ -43,6 +43,7 @@
   }
   print(error);
   Expect.isTrue(error.toString().contains("Cannot open file") ||
+      error.toString().contains("file not found") ||
       error.toString().contains("No such file or directory") ||
       error.toString().contains("The system cannot find the file specified"));
   Expect.isTrue(error.toString().contains("DOES_NOT_EXIST"));
diff --git a/tests/standalone_2/standalone_2_kernel.status b/tests/standalone_2/standalone_2_kernel.status
index 139b619..884f403 100644
--- a/tests/standalone_2/standalone_2_kernel.status
+++ b/tests/standalone_2/standalone_2_kernel.status
@@ -203,5 +203,8 @@
 [ $fasta && !$strong ]
 regress_29350_test/none: MissingCompileTimeError
 
+[ $strong && ($compiler == dartk || $compiler == dartkp) ]
+io/named_pipe_script_test: RuntimeError # Issue 33842
+
 [ !$strong && ($compiler == dartk || $compiler == dartkp || $runtime == dart_precompiled || $runtime == vm) ]
 *: SkipByDesign # standalone_2 is only supported in strong mode.