Revert "[dartdev] Use VmInteropHandler for invoking sub commands"

This reverts commit 08252fc9e91cea505d1f65353675206b24ff8b85.

Reason for revert: https://github.com/dart-lang/sdk/issues/59784

Original change's description:
> [dartdev] Use VmInteropHandler for invoking sub commands
>
> Use VmInteropHandler for invoking sub commands instead of running them
> in an isolate. Running sub commands in an isolate causes an increased footprint.
> Changing this to use VmInteropHandler avoids the additional memory footprint.
>
> Commands that need to use an AOT runtime for execution now exec the AOT
> runtime and run the command.
>
> TEST=ci
>
> Change-Id: If7aed1cab2fec9d9940bd562ad5aa9c4e9a6ac7f
> Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/398604
> Reviewed-by: Ben Konyi <bkonyi@google.com>
> Reviewed-by: Brian Quinlan <bquinlan@google.com>
> Commit-Queue: Siva Annamalai <asiva@google.com>

Change-Id: I82a997d49a7d52e1fdaa7d75f509603ebe5e51dd
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/401901
Reviewed-by: Siva Annamalai <asiva@google.com>
Reviewed-by: Sigmund Cherem <sigmund@google.com>
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
diff --git a/pkg/dartdev/lib/src/commands/compile.dart b/pkg/dartdev/lib/src/commands/compile.dart
index 75f113c..54ad454 100644
--- a/pkg/dartdev/lib/src/commands/compile.dart
+++ b/pkg/dartdev/lib/src/commands/compile.dart
@@ -17,7 +17,6 @@
 import '../native_assets.dart';
 import '../sdk.dart';
 import '../utils.dart';
-import '../vm_interop_handler.dart';
 
 const int genericErrorExitCode = 255;
 const int compileErrorExitCode = 254;
@@ -94,18 +93,17 @@
     final args = argResults!;
     var snapshot = sdk.dart2jsAotSnapshot;
     var runtime = sdk.dartAotRuntime;
-    var isAOT = true;
     if (!Sdk.checkArtifactExists(snapshot, logError: false)) {
       // AOT snapshots cannot be generated on IA32, so we need this fallback
       // branch until support for IA32 is dropped (https://dartbug.com/49969).
       snapshot = sdk.dart2jsSnapshot;
+      runtime = sdk.dart;
       if (!Sdk.checkArtifactExists(snapshot)) {
         return genericErrorExitCode;
       }
-      runtime = sdk.dart;
-      isAOT = false;
     }
     final dart2jsCommand = [
+      runtime,
       snapshot,
       '--libraries-spec=${sdk.librariesJson}',
       '--cfe-invocation-modes=compile',
@@ -114,13 +112,8 @@
       if (args.rest.isNotEmpty) ...args.rest.sublist(0),
     ];
     try {
-      VmInteropHandler.run(
-        runtime,
-        dart2jsCommand,
-        packageConfigOverride: null,
-        isAOT : isAOT,
-      );
-      return 0;
+      final exitCode = await runProcessInheritStdio(dart2jsCommand);
+      return exitCode;
     } catch (e, st) {
       log.stderr('Error: JS compilation failed');
       log.stderr(e.toString());
diff --git a/pkg/dartdev/lib/src/vm_interop_handler.dart b/pkg/dartdev/lib/src/vm_interop_handler.dart
index 43bd647..37eed1d 100644
--- a/pkg/dartdev/lib/src/vm_interop_handler.dart
+++ b/pkg/dartdev/lib/src/vm_interop_handler.dart
@@ -18,9 +18,6 @@
   ///
   /// If [markMainIsolateAsSystemIsolate] is given and set to true, the spawned
   /// isolate will run with `--mark-main-isolate-as-system-isolate` enabled.
-  ///
-  /// If [isAOT] is given and set to true, the script is executed by
-  /// execing the dartaotruntime.
   static void run(
     String script,
     List<String> args, {
@@ -30,12 +27,11 @@
     //
     // See https://github.com/dart-lang/sdk/issues/53576
     bool markMainIsolateAsSystemIsolate = false,
-    bool isAOT = false,
   }) {
     final port = _port;
     if (port == null) return;
     final message = <dynamic>[
-      isAOT ? _kResultRunAOT : _kResultRunJIT,
+      _kResultRun,
       script,
       packageConfigOverride,
       markMainIsolateAsSystemIsolate,
@@ -55,9 +51,8 @@
   }
 
   // Note: keep in sync with runtime/bin/dartdev_isolate.h
-  static const int _kResultRunJIT = 1;
-  static const int _kResultRunAOT = 2;
-  static const int _kResultExit = 3;
+  static const int _kResultRun = 1;
+  static const int _kResultExit = 2;
 
   static SendPort? _port;
 }
diff --git a/runtime/bin/dartdev_isolate.cc b/runtime/bin/dartdev_isolate.cc
index 95c9fd5..c7aab45 100644
--- a/runtime/bin/dartdev_isolate.cc
+++ b/runtime/bin/dartdev_isolate.cc
@@ -38,7 +38,6 @@
     DartDevIsolate::DartDevRunner();
 bool DartDevIsolate::should_run_dart_dev_ = false;
 bool DartDevIsolate::print_usage_error_ = false;
-CommandLineOptions* DartDevIsolate::vm_options_ = nullptr;
 Monitor* DartDevIsolate::DartDevRunner::monitor_ = new Monitor();
 DartDevIsolate::DartDev_Result DartDevIsolate::DartDevRunner::result_ =
     DartDevIsolate::DartDev_Result_Unknown;
@@ -139,7 +138,7 @@
   Thread::Start("DartDev Runner", RunCallback, reinterpret_cast<uword>(this));
   monitor_->WaitMicros(Monitor::kNoTimeout);
 
-  if (result_ == DartDevIsolate::DartDev_Result_RunJIT) {
+  if (result_ == DartDevIsolate::DartDev_Result_Run) {
     // Clear the DartDev dart_options and replace them with the processed
     // options provided by DartDev.
     dart_options_->Reset();
@@ -158,8 +157,8 @@
   ASSERT(message->type == Dart_CObject_kArray);
   int32_t type = GetArrayItem(message, 0)->value.as_int32;
   switch (type) {
-    case DartDevIsolate::DartDev_Result_RunJIT: {
-      result_ = DartDevIsolate::DartDev_Result_RunJIT;
+    case DartDevIsolate::DartDev_Result_Run: {
+      result_ = DartDevIsolate::DartDev_Result_Run;
       ASSERT(GetArrayItem(message, 1)->type == Dart_CObject_kString);
       auto item2 = GetArrayItem(message, 2);
 
@@ -205,86 +204,6 @@
       }
       break;
     }
-    case DartDevIsolate::DartDev_Result_RunAOT: {
-      result_ = DartDevIsolate::DartDev_Result_RunAOT;
-      ASSERT(GetArrayItem(message, 1)->type == Dart_CObject_kString);
-      auto item2 = GetArrayItem(message, 2);
-
-      ASSERT(item2->type == Dart_CObject_kString ||
-             item2->type == Dart_CObject_kNull);
-
-      auto item3 = GetArrayItem(message, 3);
-
-      ASSERT(item3->type == Dart_CObject_kBool);
-      const bool mark_main_isolate_as_system_isolate = item3->value.as_bool;
-      if (mark_main_isolate_as_system_isolate) {
-        Options::set_mark_main_isolate_as_system_isolate(true);
-      }
-
-      if (*script_ != nullptr) {
-        free(*script_);
-      }
-      if (*package_config_override_ != nullptr) {
-        free(*package_config_override_);
-        *package_config_override_ = nullptr;
-      }
-      *script_ = Utils::StrDup(GetArrayItem(message, 1)->value.as_string);
-
-      if (item2->type == Dart_CObject_kString) {
-        *package_config_override_ = Utils::StrDup(item2->value.as_string);
-      }
-
-      intptr_t num_vm_options = 0;
-      const char** vm_options = nullptr;
-      ASSERT(GetArrayItem(message, 4)->type == Dart_CObject_kArray);
-      Dart_CObject* args = GetArrayItem(message, 4);
-      intptr_t argc = args->value.as_array.length;
-      Dart_CObject** dart_args = args->value.as_array.values;
-
-      if (vm_options_ != nullptr) {
-        num_vm_options = vm_options_->count();
-        vm_options = vm_options_->arguments();
-      }
-      auto deleter = [](char** args) {
-        for (intptr_t i = 0; i < argc_; ++i) {
-          free(args[i]);
-        }
-        delete[] args;
-      };
-      // Total count of arguments to be passed to the script being execed.
-      argc_ = argc + num_vm_options + 1;
-
-      // Array of arguments to be passed to the script being execed.
-      argv_ = std::unique_ptr<char*[], void (*)(char**)>(new char*[argc_ + 1],
-                                                         deleter);
-
-      intptr_t idx = 0;
-      // Copy in name of the script to run (dartaotruntime).
-      argv_[0] = Utils::StrDup(GetArrayItem(message, 1)->value.as_string);
-      idx += 1;
-      // Copy in any vm options that need to be passed to the execed process.
-      for (intptr_t i = 0; i < num_vm_options; ++i) {
-        argv_[i + idx] = Utils::StrDup(vm_options[i]);
-      }
-      idx += num_vm_options;
-      // Copy in the dart options that need to be passed to the command.
-      for (intptr_t i = 0; i < argc; ++i) {
-        argv_[i + idx] = Utils::StrDup(dart_args[i]->value.as_string);
-      }
-      // Null terminate the argv array.
-      argv_[argc + idx] = nullptr;
-
-      // Exec the script to be run and pass the arguments.
-      char err_msg[256];
-      err_msg[0] = '\0';
-      int ret = Process::Exec(nullptr, *script_,
-                              const_cast<const char**>(argv_.get()), argc_,
-                              nullptr, err_msg, sizeof(err_msg));
-      if (ret != 0) {
-        ProcessError(err_msg, kErrorExitCode);
-      }
-      break;
-    }
     case DartDevIsolate::DartDev_Result_Exit: {
       ASSERT(GetArrayItem(message, 1)->type == Dart_CObject_kInt32);
       int32_t dartdev_exit_code = GetArrayItem(message, 1)->value.as_int32;
@@ -395,9 +314,7 @@
     Dart_IsolateGroupCreateCallback create_isolate,
     char** packages_file,
     char** script,
-    CommandLineOptions* vm_options,
     CommandLineOptions* dart_options) {
-  vm_options_ = vm_options;
   runner_.Run(create_isolate, packages_file, script, dart_options);
   return runner_.result();
 }
diff --git a/runtime/bin/dartdev_isolate.h b/runtime/bin/dartdev_isolate.h
index ed997cc..79566c6 100644
--- a/runtime/bin/dartdev_isolate.h
+++ b/runtime/bin/dartdev_isolate.h
@@ -27,9 +27,8 @@
   // Note: keep in sync with pkg/dartdev/lib/vm_interop_handler.dart
   typedef enum {
     DartDev_Result_Unknown = -1,
-    DartDev_Result_RunJIT = 1,
-    DartDev_Result_RunAOT = 2,
-    DartDev_Result_Exit = 3,
+    DartDev_Result_Run = 1,
+    DartDev_Result_Exit = 2,
   } DartDev_Result;
 
   // Returns true if there does not exist a file at |script_uri| or the URI is
@@ -59,7 +58,6 @@
       Dart_IsolateGroupCreateCallback create_isolate,
       char** packages_file,
       char** script,
-      CommandLineOptions* vm_options,
       CommandLineOptions* dart_options);
 
  protected:
@@ -85,11 +83,11 @@
     static char** package_config_override_;
     static std::unique_ptr<char*[], void (*)(char**)> argv_;
     static intptr_t argc_;
-    static Monitor* monitor_;
 
     Dart_IsolateGroupCreateCallback create_isolate_;
     CommandLineOptions* dart_options_;
     const char* packages_file_;
+    static Monitor* monitor_;
 
     DISALLOW_ALLOCATION();
   };
@@ -100,7 +98,6 @@
   static DartDevRunner runner_;
   static bool should_run_dart_dev_;
   static bool print_usage_error_;
-  static CommandLineOptions* vm_options_;
 
   DISALLOW_ALLOCATION();
   DISALLOW_IMPLICIT_CONSTRUCTORS(DartDevIsolate);
diff --git a/runtime/bin/main_impl.cc b/runtime/bin/main_impl.cc
index cd4fab2..4a26768 100644
--- a/runtime/bin/main_impl.cc
+++ b/runtime/bin/main_impl.cc
@@ -1421,11 +1421,11 @@
       Options::gen_snapshot_kind() == SnapshotKind::kNone) {
     DartDevIsolate::DartDev_Result dartdev_result = DartDevIsolate::RunDartDev(
         CreateIsolateGroupAndSetup, &package_config_override, &script_name,
-        &vm_options, &dart_options);
+        &dart_options);
     ASSERT(dartdev_result != DartDevIsolate::DartDev_Result_Unknown);
     ran_dart_dev = true;
     should_run_user_program =
-        (dartdev_result == DartDevIsolate::DartDev_Result_RunJIT);
+        (dartdev_result == DartDevIsolate::DartDev_Result_Run);
     if (should_run_user_program) {
       try_load_snapshots_lambda();
     }
diff --git a/runtime/bin/process.cc b/runtime/bin/process.cc
index dfb0b77..f990e80 100644
--- a/runtime/bin/process.cc
+++ b/runtime/bin/process.cc
@@ -114,9 +114,9 @@
   const char* path = DartUtils::GetStringValue(path_handle);
   Dart_Handle arguments = Dart_GetNativeArgument(args, 3);
   intptr_t args_length = 0;
-  const char** string_args = const_cast<const char**>(
+  char** string_args =
       ExtractCStringList(arguments, status_handle,
-                         "Arguments must be builtin strings", &args_length));
+                         "Arguments must be builtin strings", &args_length);
   if (string_args == nullptr) {
     Dart_SetBooleanReturnValue(args, false);
     return;
diff --git a/runtime/bin/process.h b/runtime/bin/process.h
index 2aa40cd..9bd547c 100644
--- a/runtime/bin/process.h
+++ b/runtime/bin/process.h
@@ -94,7 +94,7 @@
   // process exit streams.
   static int Start(Namespace* namespc,
                    const char* path,
-                   const char* arguments[],
+                   char* arguments[],
                    intptr_t arguments_length,
                    const char* working_directory,
                    char* environment[],
@@ -114,23 +114,6 @@
                    intptr_t exit_handler,
                    ProcessResult* result);
 
-  // Exec process.
-  // On systems that support 'exec' it will use it to replace
-  // the current process image with the image corresponding to 'path'
-  // On systems that do not support it (Windows) it will start in a
-  // child process in the same group as the parent so that when the parent
-  // is killed the child also dies.
-  // Returns 0 if the process could be execed successfully
-  // Returns -1 if the exec could not be done successfully and 'errmsg'
-  // points to the error message
-  static int Exec(Namespace* namespc,
-                  const char* path,
-                  const char* arguments[],
-                  intptr_t arguments_length,
-                  const char* working_directory,
-                  char* errmsg,
-                  intptr_t errmsg_len);
-
   // Kill a process with a given pid.
   static bool Kill(intptr_t id, int signal);
 
diff --git a/runtime/bin/process_fuchsia.cc b/runtime/bin/process_fuchsia.cc
index 170f074..eed2af0 100644
--- a/runtime/bin/process_fuchsia.cc
+++ b/runtime/bin/process_fuchsia.cc
@@ -838,19 +838,6 @@
   return starter.Start();
 }
 
-// The command line dart utility does not run on Fuchsia, this functionality
-// is not supported on that platform.
-int Process::Exec(Namespace* namespc,
-                  const char* path,
-                  const char** arguments,
-                  const char* working_directory,
-                  char* errmsg,
-                  intptr_t errmsg_len) {
-  snprintf(errmsg, errmsg_len,
-           "Process::Exec is not supported on this platform");
-  return -1;
-}
-
 intptr_t Process::SetSignalHandler(intptr_t signal) {
   errno = ENOSYS;
   return -1;
diff --git a/runtime/bin/process_linux.cc b/runtime/bin/process_linux.cc
index da95e5a..64e74fc 100644
--- a/runtime/bin/process_linux.cc
+++ b/runtime/bin/process_linux.cc
@@ -246,47 +246,11 @@
 bool ExitCodeHandler::terminate_done_ = false;
 Monitor* ExitCodeHandler::monitor_ = nullptr;
 
-// Tries to find path relative to the current namespace unless it should be
-// searched in the PATH environment variable.
-// The path that should be passed to exec is returned in realpath.
-// Returns true on success, and false if there was an error that should
-// be reported to the parent.
-static bool PathInNamespace(char* realpath,
-                            intptr_t realpath_size,
-                            Namespace* namespc,
-                            const char* path) {
-  // Perform a PATH search if there's no slash in the path.
-  if (Namespace::IsDefault(namespc) || strchr(path, '/') == nullptr) {
-    // TODO(zra): If there is a non-default namespace, the entries in PATH
-    // should be treated as relative to the namespace.
-    strncpy(realpath, path, realpath_size);
-    realpath[realpath_size - 1] = '\0';
-    return true;
-  }
-  NamespaceScope ns(namespc, path);
-  const int fd =
-      TEMP_FAILURE_RETRY(openat64(ns.fd(), ns.path(), O_RDONLY | O_CLOEXEC));
-  if (fd == -1) {
-    return false;
-  }
-  char procpath[PATH_MAX];
-  snprintf(procpath, PATH_MAX, "/proc/self/fd/%d", fd);
-  const intptr_t length =
-      TEMP_FAILURE_RETRY(readlink(procpath, realpath, realpath_size));
-  if (length < 0) {
-    FDUtils::SaveErrorAndClose(fd);
-    return false;
-  }
-  realpath[length] = '\0';
-  FDUtils::SaveErrorAndClose(fd);
-  return true;
-}
-
 class ProcessStarter {
  public:
   ProcessStarter(Namespace* namespc,
                  const char* path,
-                 const char* arguments[],
+                 char* arguments[],
                  intptr_t arguments_length,
                  const char* working_directory,
                  char* environment[],
@@ -317,7 +281,7 @@
     exec_control_[0] = -1;
     exec_control_[1] = -1;
 
-    program_arguments_ = reinterpret_cast<const char**>(Dart_ScopeAllocate(
+    program_arguments_ = reinterpret_cast<char**>(Dart_ScopeAllocate(
         (arguments_length + 2) * sizeof(*program_arguments_)));
     program_arguments_[0] = const_cast<char*>(path_);
     for (int i = 0; i < arguments_length; i++) {
@@ -483,7 +447,31 @@
   // Returns true on success, and false if there was an error that should
   // be reported to the parent.
   bool FindPathInNamespace(char* realpath, intptr_t realpath_size) {
-    return PathInNamespace(realpath, realpath_size, namespc_, path_);
+    // Perform a PATH search if there's no slash in the path.
+    if (Namespace::IsDefault(namespc_) || strchr(path_, '/') == nullptr) {
+      // TODO(zra): If there is a non-default namespace, the entries in PATH
+      // should be treated as relative to the namespace.
+      strncpy(realpath, path_, realpath_size);
+      realpath[realpath_size - 1] = '\0';
+      return true;
+    }
+    NamespaceScope ns(namespc_, path_);
+    const int fd =
+        TEMP_FAILURE_RETRY(openat64(ns.fd(), ns.path(), O_RDONLY | O_CLOEXEC));
+    if (fd == -1) {
+      return false;
+    }
+    char procpath[PATH_MAX];
+    snprintf(procpath, PATH_MAX, "/proc/self/fd/%d", fd);
+    const intptr_t length =
+        TEMP_FAILURE_RETRY(readlink(procpath, realpath, realpath_size));
+    if (length < 0) {
+      FDUtils::SaveErrorAndClose(fd);
+      return false;
+    }
+    realpath[length] = '\0';
+    FDUtils::SaveErrorAndClose(fd);
+    return true;
   }
 
   void ExecProcess() {
@@ -784,7 +772,7 @@
   int write_out_[2];     // Pipe for stdin to child process.
   int exec_control_[2];  // Pipe to get the result from exec.
 
-  const char** program_arguments_;
+  char** program_arguments_;
   char** program_environment_;
 
   Namespace* namespc_;
@@ -804,7 +792,7 @@
 
 int Process::Start(Namespace* namespc,
                    const char* path,
-                   const char* arguments[],
+                   char* arguments[],
                    intptr_t arguments_length,
                    const char* working_directory,
                    char* environment[],
@@ -926,31 +914,6 @@
   return true;
 }
 
-int Process::Exec(Namespace* namespc,
-                  const char* path,
-                  const char* arguments[],
-                  intptr_t arguments_length,
-                  const char* working_directory,
-                  char* errmsg,
-                  intptr_t errmsg_len) {
-  if (working_directory != nullptr &&
-      !Directory::SetCurrent(namespc, working_directory)) {
-    Utils::StrError(errno, errmsg, errmsg_len);
-    return -1;
-  }
-
-  char realpath[PATH_MAX];
-  if (!PathInNamespace(realpath, PATH_MAX, namespc, path)) {
-    Utils::StrError(errno, errmsg, errmsg_len);
-    return -1;
-  }
-  // TODO(dart:io) Test for the existence of execveat, and use it instead.
-  execvp(const_cast<const char*>(realpath),
-         const_cast<char* const*>(arguments));
-  Utils::StrError(errno, errmsg, errmsg_len);
-  return -1;
-}
-
 bool Process::Kill(intptr_t id, int signal) {
   return (TEMP_FAILURE_RETRY(kill(id, signal)) != -1);
 }
diff --git a/runtime/bin/process_macos.cc b/runtime/bin/process_macos.cc
index 94568e3..d7eb45e 100644
--- a/runtime/bin/process_macos.cc
+++ b/runtime/bin/process_macos.cc
@@ -249,7 +249,7 @@
 class ProcessStarter {
  public:
   ProcessStarter(const char* path,
-                 const char* arguments[],
+                 char* arguments[],
                  intptr_t arguments_length,
                  const char* working_directory,
                  char* environment[],
@@ -279,7 +279,7 @@
     exec_control_[0] = -1;
     exec_control_[1] = -1;
 
-    program_arguments_ = reinterpret_cast<const char**>(Dart_ScopeAllocate(
+    program_arguments_ = reinterpret_cast<char**>(Dart_ScopeAllocate(
         (arguments_length + 2) * sizeof(*program_arguments_)));
     program_arguments_[0] = const_cast<char*>(path_);
     for (int i = 0; i < arguments_length; i++) {
@@ -740,7 +740,7 @@
   int write_out_[2];     // Pipe for stdin to child process.
   int exec_control_[2];  // Pipe to get the result from exec.
 
-  const char** program_arguments_;
+  char** program_arguments_;
   char** program_environment_;
 
   const char* path_;
@@ -760,7 +760,7 @@
 
 int Process::Start(Namespace* namespc,
                    const char* path,
-                   const char* arguments[],
+                   char* arguments[],
                    intptr_t arguments_length,
                    const char* working_directory,
                    char* environment[],
@@ -898,24 +898,6 @@
 #endif  // defined(DART_HOST_OS_IOS)
 }
 
-int Process::Exec(Namespace* namespc,
-                  const char* path,
-                  const char* arguments[],
-                  intptr_t arguments_length,
-                  const char* working_directory,
-                  char* errmsg,
-                  intptr_t errmsg_len) {
-  if (working_directory != nullptr &&
-      TEMP_FAILURE_RETRY(chdir(working_directory)) == -1) {
-    Utils::StrError(errno, errmsg, errmsg_len);
-    return -1;
-  }
-
-  execvp(const_cast<const char*>(path), const_cast<char* const*>(arguments));
-  Utils::StrError(errno, errmsg, errmsg_len);
-  return -1;
-}
-
 static int SignalMap(intptr_t id) {
   switch (static_cast<ProcessSignals>(id)) {
     case kSighup:
diff --git a/runtime/bin/process_win.cc b/runtime/bin/process_win.cc
index b9949c9..e9a353b 100644
--- a/runtime/bin/process_win.cc
+++ b/runtime/bin/process_win.cc
@@ -20,7 +20,6 @@
 #include "bin/utils.h"
 #include "bin/utils_win.h"
 #include "platform/syslog.h"
-#include "platform/text_buffer.h"
 
 namespace dart {
 namespace bin {
@@ -345,7 +344,7 @@
 class ProcessStarter {
  public:
   ProcessStarter(const char* path,
-                 const char* arguments[],
+                 char* arguments[],
                  intptr_t arguments_length,
                  const char* working_directory,
                  char* environment[],
@@ -374,12 +373,11 @@
     stderr_handles_[kWriteHandle] = INVALID_HANDLE_VALUE;
     exit_handles_[kReadHandle] = INVALID_HANDLE_VALUE;
     exit_handles_[kWriteHandle] = INVALID_HANDLE_VALUE;
-    child_process_handle_ = INVALID_HANDLE_VALUE;
 
     // Transform input strings to system format.
     const wchar_t* system_path = StringUtilsWin::Utf8ToWide(path_);
-    const wchar_t** system_arguments;
-    system_arguments = reinterpret_cast<const wchar_t**>(
+    wchar_t** system_arguments;
+    system_arguments = reinterpret_cast<wchar_t**>(
         Dart_ScopeAllocate(arguments_length * sizeof(*system_arguments)));
     for (int i = 0; i < arguments_length; i++) {
       system_arguments[i] = StringUtilsWin::Utf8ToWide(arguments[i]);
@@ -564,42 +562,7 @@
         *exit_handler_ = reinterpret_cast<intptr_t>(exit_handle);
       }
     }
-    child_process_handle_ = process_info.hProcess;
-    CloseHandle(process_info.hThread);
 
-    // Return process id.
-    *id_ = process_info.dwProcessId;
-    return 0;
-  }
-
-  int StartForExec() {
-    // Setup info
-    STARTUPINFOEXW startup_info;
-    ZeroMemory(&startup_info, sizeof(startup_info));
-    startup_info.StartupInfo.cb = sizeof(startup_info);
-    ASSERT(mode_ == kInheritStdio);
-    ASSERT(Process::ModeIsAttached(mode_));
-    ASSERT(!Process::ModeHasStdio(mode_));
-
-    PROCESS_INFORMATION process_info;
-    ZeroMemory(&process_info, sizeof(process_info));
-
-    // Create process.
-    DWORD creation_flags =
-        EXTENDED_STARTUPINFO_PRESENT | CREATE_UNICODE_ENVIRONMENT;
-    BOOL result = CreateProcessW(
-        nullptr,  // ApplicationName
-        command_line_,
-        nullptr,  // ProcessAttributes
-        nullptr,  // ThreadAttributes
-        TRUE,     // InheritHandles
-        creation_flags, environment_block_, system_working_directory_,
-        reinterpret_cast<STARTUPINFOW*>(&startup_info), &process_info);
-
-    if (result == 0) {
-      return SetOsErrorMessage(os_error_message_);
-    }
-    child_process_handle_ = process_info.hProcess;
     CloseHandle(process_info.hThread);
 
     // Return process id.
@@ -664,7 +627,6 @@
   HANDLE stdout_handles_[2];
   HANDLE stderr_handles_[2];
   HANDLE exit_handles_[2];
-  HANDLE child_process_handle_;
 
   const wchar_t* system_working_directory_;
   wchar_t* command_line_;
@@ -689,7 +651,7 @@
 
 int Process::Start(Namespace* namespc,
                    const char* path,
-                   const char* arguments[],
+                   char* arguments[],
                    intptr_t arguments_length,
                    const char* working_directory,
                    char* environment[],
@@ -918,92 +880,6 @@
   return true;
 }
 
-int Process::Exec(Namespace* namespc,
-                  const char* path,
-                  const char* arguments[],
-                  intptr_t arguments_length,
-                  const char* working_directory,
-                  char* errmsg,
-                  intptr_t errmsg_len) {
-  // Create a Job object with JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE
-  HANDLE hjob = CreateJobObject(nullptr, nullptr);
-  if (hjob == nullptr) {
-    BufferFormatter f(errmsg, errmsg_len);
-    f.Printf("Process::Exec - CreateJobObject failed %d\n", GetLastError());
-    return -1;
-  }
-  JOBOBJECT_EXTENDED_LIMIT_INFORMATION info;
-  DWORD qresult;
-  if (!QueryInformationJobObject(hjob, JobObjectExtendedLimitInformation, &info,
-                                 sizeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION),
-                                 &qresult)) {
-    BufferFormatter f(errmsg, errmsg_len);
-    f.Printf("Process::Exec - QueryInformationJobObject failed %d\n",
-             GetLastError());
-    return -1;
-  }
-  info.BasicLimitInformation.LimitFlags |= JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
-  if (!SetInformationJobObject(hjob, JobObjectExtendedLimitInformation, &info,
-                               sizeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION))) {
-    BufferFormatter f(errmsg, errmsg_len);
-    f.Printf("Process::Exec - SetInformationJobObject failed %d\n",
-             GetLastError());
-    return -1;
-  }
-
-  // Put the current process into the job object (there is a race here
-  // as the process can crash before it is in the Job object, but since
-  // we haven't spawned any children yet this race is harmless)
-  if (!AssignProcessToJobObject(hjob, GetCurrentProcess())) {
-    BufferFormatter f(errmsg, errmsg_len);
-    f.Printf("Process::Exec - AssignProcessToJobObject failed %d\n",
-             GetLastError());
-    return -1;
-  }
-
-  // Spawn the new child process (this child will automatically get
-  // added to the Job object).
-  // If the parent process is killed or it crashes the Job object
-  // will get destroyed and all the child processes will also get killed.
-  // arguments includes the name of the executable to run which is the same
-  // as the value passed in 'path', we strip that off when starting the
-  // process.
-  intptr_t pid = -1;
-  char* os_error_message = nullptr;  // Scope allocated by Process::Start.
-  ProcessStarter starter(path, &(arguments[1]), (arguments_length - 1),
-                         working_directory, nullptr, 0, kInheritStdio, nullptr,
-                         nullptr, nullptr, &pid, nullptr, &os_error_message);
-  int result = starter.StartForExec();
-  if (result != 0) {
-    BufferFormatter f(errmsg, errmsg_len);
-    f.Printf("Process::Exec - %s\n", os_error_message);
-    return -1;
-  }
-
-  // Now wait for this child process to terminate (normal exit or crash).
-  HANDLE child_process = starter.child_process_handle_;
-  ASSERT(child_process != INVALID_HANDLE_VALUE);
-  DWORD wait_result = WaitForSingleObject(child_process, INFINITE);
-  if (wait_result != WAIT_OBJECT_0) {
-    BufferFormatter f(errmsg, errmsg_len);
-    f.Printf("Process::Exec - WaitForSingleObject failed %d\n", GetLastError());
-    CloseHandle(child_process);
-    return -1;
-  }
-  int retval;
-  if (!GetExitCodeProcess(child_process, reinterpret_cast<DWORD*>(&retval))) {
-    BufferFormatter f(errmsg, errmsg_len);
-    f.Printf("Process::Exec - GetExitCodeProcess failed %d\n", GetLastError());
-    CloseHandle(child_process);
-    return -1;
-  }
-  CloseHandle(child_process);
-  // We exit the process here to simulate the same behaviour as exec on systems
-  // that support it.
-  ExitProcess(retval);
-  return 0;
-}
-
 bool Process::Kill(intptr_t id, int signal) {
   USE(signal);  // signal is not used on Windows.
   HANDLE process_handle;