Refactor code so that JIT can parse compiler options.

Currently only the CompilerOptions class. We should also
do it for the CompilerDriver options.

This will fix the flakiness seen on jdwp testing, as the
debuggable flag was not passed to the compiler.

Change-Id: I4218dd5928c9f4fe2d6191ab11e5598e7cf84bcf
diff --git a/compiler/dex/quick/quick_cfi_test.cc b/compiler/dex/quick/quick_cfi_test.cc
index 18c2e55..24daf2f 100644
--- a/compiler/dex/quick/quick_cfi_test.cc
+++ b/compiler/dex/quick/quick_cfi_test.cc
@@ -67,7 +67,6 @@
       false,
       false,
       nullptr,
-      new PassManagerOptions(),
       nullptr,
       false);
     VerificationResults verification_results(&compiler_options);
diff --git a/compiler/dex/quick/x86/quick_assemble_x86_test.cc b/compiler/dex/quick/x86/quick_assemble_x86_test.cc
index d9571c5..e977ebf 100644
--- a/compiler/dex/quick/x86/quick_assemble_x86_test.cc
+++ b/compiler/dex/quick/x86/quick_assemble_x86_test.cc
@@ -50,7 +50,6 @@
         false,
         false,
         nullptr,
-        new PassManagerOptions(),
         nullptr,
         false));
     verification_results_.reset(new VerificationResults(compiler_options_.get()));
diff --git a/compiler/driver/compiler_options.cc b/compiler/driver/compiler_options.cc
index 3f5a1ea..a24c8a3 100644
--- a/compiler/driver/compiler_options.cc
+++ b/compiler/driver/compiler_options.cc
@@ -16,6 +16,8 @@
 
 #include "compiler_options.h"
 
+#include <fstream>
+
 #include "dex/pass_manager.h"
 
 namespace art {
@@ -27,8 +29,8 @@
       small_method_threshold_(kDefaultSmallMethodThreshold),
       tiny_method_threshold_(kDefaultTinyMethodThreshold),
       num_dex_methods_threshold_(kDefaultNumDexMethodsThreshold),
-      inline_depth_limit_(kDefaultInlineDepthLimit),
-      inline_max_code_units_(kDefaultInlineMaxCodeUnits),
+      inline_depth_limit_(kUnsetInlineDepthLimit),
+      inline_max_code_units_(kUnsetInlineMaxCodeUnits),
       include_patch_information_(kDefaultIncludePatchInformation),
       top_k_profile_threshold_(kDefaultTopKProfileThreshold),
       debuggable_(false),
@@ -38,7 +40,7 @@
       implicit_suspend_checks_(false),
       compile_pic_(false),
       verbose_methods_(nullptr),
-      pass_manager_options_(new PassManagerOptions),
+      pass_manager_options_(),
       abort_on_hard_verifier_failure_(false),
       init_failure_output_(nullptr) {
 }
@@ -65,7 +67,6 @@
                                  bool implicit_suspend_checks,
                                  bool compile_pic,
                                  const std::vector<std::string>* verbose_methods,
-                                 PassManagerOptions* pass_manager_options,
                                  std::ostream* init_failure_output,
                                  bool abort_on_hard_verifier_failure
                                  ) :  // NOLINT(whitespace/parens)
@@ -86,9 +87,155 @@
     implicit_suspend_checks_(implicit_suspend_checks),
     compile_pic_(compile_pic),
     verbose_methods_(verbose_methods),
-    pass_manager_options_(pass_manager_options),
+    pass_manager_options_(),
     abort_on_hard_verifier_failure_(abort_on_hard_verifier_failure),
     init_failure_output_(init_failure_output) {
 }
 
+void CompilerOptions::ParseHugeMethodMax(const StringPiece& option, UsageFn Usage) {
+  ParseUintOption(option, "--huge-method-max", &huge_method_threshold_, Usage);
+}
+
+void CompilerOptions::ParseLargeMethodMax(const StringPiece& option, UsageFn Usage) {
+  ParseUintOption(option, "--large-method-max", &large_method_threshold_, Usage);
+}
+
+void CompilerOptions::ParseSmallMethodMax(const StringPiece& option, UsageFn Usage) {
+  ParseUintOption(option, "--small-method-max", &small_method_threshold_, Usage);
+}
+
+void CompilerOptions::ParseTinyMethodMax(const StringPiece& option, UsageFn Usage) {
+  ParseUintOption(option, "--tiny-method-max", &tiny_method_threshold_, Usage);
+}
+
+void CompilerOptions::ParseNumDexMethods(const StringPiece& option, UsageFn Usage) {
+  ParseUintOption(option, "--num-dex-methods", &num_dex_methods_threshold_, Usage);
+}
+
+void CompilerOptions::ParseInlineDepthLimit(const StringPiece& option, UsageFn Usage) {
+  ParseUintOption(option, "--inline-depth-limit", &inline_depth_limit_, Usage);
+}
+
+void CompilerOptions::ParseInlineMaxCodeUnits(const StringPiece& option, UsageFn Usage) {
+  ParseUintOption(option, "--inline-max-code-units=", &inline_max_code_units_, Usage);
+}
+
+void CompilerOptions::ParseDisablePasses(const StringPiece& option,
+                                         UsageFn Usage ATTRIBUTE_UNUSED) {
+  DCHECK(option.starts_with("--disable-passes="));
+  const std::string disable_passes = option.substr(strlen("--disable-passes=")).data();
+  pass_manager_options_.SetDisablePassList(disable_passes);
+}
+
+void CompilerOptions::ParsePrintPasses(const StringPiece& option,
+                                       UsageFn Usage ATTRIBUTE_UNUSED) {
+  DCHECK(option.starts_with("--print-passes="));
+  const std::string print_passes = option.substr(strlen("--print-passes=")).data();
+  pass_manager_options_.SetPrintPassList(print_passes);
+}
+
+void CompilerOptions::ParseDumpCfgPasses(const StringPiece& option,
+                                         UsageFn Usage ATTRIBUTE_UNUSED) {
+  DCHECK(option.starts_with("--dump-cfg-passes="));
+  const std::string dump_passes_string = option.substr(strlen("--dump-cfg-passes=")).data();
+  pass_manager_options_.SetDumpPassList(dump_passes_string);
+}
+
+void CompilerOptions::ParsePassOptions(const StringPiece& option,
+                                       UsageFn Usage ATTRIBUTE_UNUSED) {
+  DCHECK(option.starts_with("--pass-options="));
+  const std::string pass_options = option.substr(strlen("--pass-options=")).data();
+  pass_manager_options_.SetOverriddenPassOptions(pass_options);
+}
+
+void CompilerOptions::ParseDumpInitFailures(const StringPiece& option,
+                                            UsageFn Usage ATTRIBUTE_UNUSED) {
+  DCHECK(option.starts_with("--dump-init-failures="));
+  std::string file_name = option.substr(strlen("--dump-init-failures=")).data();
+  init_failure_output_.reset(new std::ofstream(file_name));
+  if (init_failure_output_.get() == nullptr) {
+    LOG(ERROR) << "Failed to allocate ofstream";
+  } else if (init_failure_output_->fail()) {
+    LOG(ERROR) << "Failed to open " << file_name << " for writing the initialization "
+               << "failures.";
+    init_failure_output_.reset();
+  }
+}
+
+bool CompilerOptions::ParseCompilerOption(const StringPiece& option, UsageFn Usage) {
+  if (option.starts_with("--compiler-filter=")) {
+    const char* compiler_filter_string = option.substr(strlen("--compiler-filter=")).data();
+    if (strcmp(compiler_filter_string, "verify-none") == 0) {
+      compiler_filter_ = CompilerOptions::kVerifyNone;
+    } else if (strcmp(compiler_filter_string, "interpret-only") == 0) {
+      compiler_filter_ = CompilerOptions::kInterpretOnly;
+    } else if (strcmp(compiler_filter_string, "verify-at-runtime") == 0) {
+      compiler_filter_ = CompilerOptions::kVerifyAtRuntime;
+    } else if (strcmp(compiler_filter_string, "space") == 0) {
+      compiler_filter_ = CompilerOptions::kSpace;
+    } else if (strcmp(compiler_filter_string, "balanced") == 0) {
+      compiler_filter_ = CompilerOptions::kBalanced;
+    } else if (strcmp(compiler_filter_string, "speed") == 0) {
+      compiler_filter_ = CompilerOptions::kSpeed;
+    } else if (strcmp(compiler_filter_string, "everything") == 0) {
+      compiler_filter_ = CompilerOptions::kEverything;
+    } else if (strcmp(compiler_filter_string, "time") == 0) {
+      compiler_filter_ = CompilerOptions::kTime;
+    } else {
+      Usage("Unknown --compiler-filter value %s", compiler_filter_string);
+    }
+  } else if (option == "--compile-pic") {
+    compile_pic_ = true;
+  } else if (option.starts_with("--huge-method-max=")) {
+    ParseHugeMethodMax(option, Usage);
+  } else if (option.starts_with("--large-method-max=")) {
+    ParseLargeMethodMax(option, Usage);
+  } else if (option.starts_with("--small-method-max=")) {
+    ParseSmallMethodMax(option, Usage);
+  } else if (option.starts_with("--tiny-method-max=")) {
+    ParseTinyMethodMax(option, Usage);
+  } else if (option.starts_with("--num-dex-methods=")) {
+    ParseNumDexMethods(option, Usage);
+  } else if (option.starts_with("--inline-depth-limit=")) {
+    ParseInlineDepthLimit(option, Usage);
+  } else if (option.starts_with("--inline-max-code-units=")) {
+    ParseInlineMaxCodeUnits(option, Usage);
+  } else if (option == "--generate-debug-info" || option == "-g") {
+    generate_debug_info_ = true;
+  } else if (option == "--no-generate-debug-info") {
+    generate_debug_info_ = false;
+  } else if (option == "--debuggable") {
+    debuggable_ = true;
+    generate_debug_info_ = true;
+  } else if (option.starts_with("--top-k-profile-threshold=")) {
+    ParseDouble(option.data(), '=', 0.0, 100.0, &top_k_profile_threshold_, Usage);
+  } else if (option == "--include-patch-information") {
+    include_patch_information_ = true;
+  } else if (option == "--no-include-patch-information") {
+    include_patch_information_ = false;
+  } else if (option == "--abort-on-hard-verifier-error") {
+    abort_on_hard_verifier_failure_ = true;
+  } else if (option == "--print-pass-names") {
+    pass_manager_options_.SetPrintPassNames(true);
+  } else if (option.starts_with("--disable-passes=")) {
+    ParseDisablePasses(option, Usage);
+  } else if (option.starts_with("--print-passes=")) {
+    ParsePrintPasses(option, Usage);
+  } else if (option == "--print-all-passes") {
+    pass_manager_options_.SetPrintAllPasses();
+  } else if (option.starts_with("--dump-cfg-passes=")) {
+    ParseDumpCfgPasses(option, Usage);
+  } else if (option == "--print-pass-options") {
+    pass_manager_options_.SetPrintPassOptions(true);
+  } else if (option.starts_with("--pass-options=")) {
+    ParsePassOptions(option, Usage);
+  } else if (option.starts_with("--dump-init-failures=")) {
+    ParseDumpInitFailures(option, Usage);
+  } else {
+    // Option not recognized.
+    return false;
+  }
+  return true;
+}
+
 }  // namespace art
diff --git a/compiler/driver/compiler_options.h b/compiler/driver/compiler_options.h
index 18f215d..e6acab4 100644
--- a/compiler/driver/compiler_options.h
+++ b/compiler/driver/compiler_options.h
@@ -22,12 +22,12 @@
 #include <vector>
 
 #include "base/macros.h"
+#include "dex/pass_manager.h"
 #include "globals.h"
+#include "utils.h"
 
 namespace art {
 
-class PassManagerOptions;
-
 class CompilerOptions FINAL {
  public:
   enum CompilerFilter {
@@ -53,6 +53,8 @@
   static const bool kDefaultIncludePatchInformation = false;
   static const size_t kDefaultInlineDepthLimit = 3;
   static const size_t kDefaultInlineMaxCodeUnits = 20;
+  static constexpr size_t kUnsetInlineDepthLimit = -1;
+  static constexpr size_t kUnsetInlineMaxCodeUnits = -1;
 
   // Default inlining settings when the space filter is used.
   static constexpr size_t kSpaceFilterInlineDepthLimit = 3;
@@ -78,7 +80,6 @@
                   bool implicit_suspend_checks,
                   bool compile_pic,
                   const std::vector<std::string>* verbose_methods,
-                  PassManagerOptions* pass_manager_options,
                   std::ostream* init_failure_output,
                   bool abort_on_hard_verifier_failure);
 
@@ -200,47 +201,64 @@
   }
 
   std::ostream* GetInitFailureOutput() const {
-    return init_failure_output_;
+    return init_failure_output_.get();
   }
 
   const PassManagerOptions* GetPassManagerOptions() const {
-    return pass_manager_options_.get();
+    return &pass_manager_options_;
   }
 
   bool AbortOnHardVerifierFailure() const {
     return abort_on_hard_verifier_failure_;
   }
 
+  bool ParseCompilerOption(const StringPiece& option, UsageFn Usage);
+
  private:
+  void ParseDumpInitFailures(const StringPiece& option, UsageFn Usage);
+  void ParsePassOptions(const StringPiece& option, UsageFn Usage);
+  void ParseDumpCfgPasses(const StringPiece& option, UsageFn Usage);
+  void ParsePrintPasses(const StringPiece& option, UsageFn Usage);
+  void ParseDisablePasses(const StringPiece& option, UsageFn Usage);
+  void ParseInlineMaxCodeUnits(const StringPiece& option, UsageFn Usage);
+  void ParseInlineDepthLimit(const StringPiece& option, UsageFn Usage);
+  void ParseNumDexMethods(const StringPiece& option, UsageFn Usage);
+  void ParseTinyMethodMax(const StringPiece& option, UsageFn Usage);
+  void ParseSmallMethodMax(const StringPiece& option, UsageFn Usage);
+  void ParseLargeMethodMax(const StringPiece& option, UsageFn Usage);
+  void ParseHugeMethodMax(const StringPiece& option, UsageFn Usage);
+
   CompilerFilter compiler_filter_;
-  const size_t huge_method_threshold_;
-  const size_t large_method_threshold_;
-  const size_t small_method_threshold_;
-  const size_t tiny_method_threshold_;
-  const size_t num_dex_methods_threshold_;
-  const size_t inline_depth_limit_;
-  const size_t inline_max_code_units_;
-  const bool include_patch_information_;
+  size_t huge_method_threshold_;
+  size_t large_method_threshold_;
+  size_t small_method_threshold_;
+  size_t tiny_method_threshold_;
+  size_t num_dex_methods_threshold_;
+  size_t inline_depth_limit_;
+  size_t inline_max_code_units_;
+  bool include_patch_information_;
   // When using a profile file only the top K% of the profiled samples will be compiled.
-  const double top_k_profile_threshold_;
-  const bool debuggable_;
-  const bool generate_debug_info_;
-  const bool implicit_null_checks_;
-  const bool implicit_so_checks_;
-  const bool implicit_suspend_checks_;
-  const bool compile_pic_;
+  double top_k_profile_threshold_;
+  bool debuggable_;
+  bool generate_debug_info_;
+  bool implicit_null_checks_;
+  bool implicit_so_checks_;
+  bool implicit_suspend_checks_;
+  bool compile_pic_;
 
   // Vector of methods to have verbose output enabled for.
-  const std::vector<std::string>* const verbose_methods_;
+  const std::vector<std::string>* verbose_methods_;
 
-  std::unique_ptr<PassManagerOptions> pass_manager_options_;
+  PassManagerOptions pass_manager_options_;
 
   // Abort compilation with an error if we find a class that fails verification with a hard
   // failure.
-  const bool abort_on_hard_verifier_failure_;
+  bool abort_on_hard_verifier_failure_;
 
   // Log initialization of initialization failures to this stream if not null.
-  std::ostream* const init_failure_output_;
+  std::unique_ptr<std::ostream> init_failure_output_;
+
+  friend class Dex2Oat;
 
   DISALLOW_COPY_AND_ASSIGN(CompilerOptions);
 };
diff --git a/compiler/jit/jit_compiler.cc b/compiler/jit/jit_compiler.cc
index b563c80..c1b87c9 100644
--- a/compiler/jit/jit_compiler.cc
+++ b/compiler/jit/jit_compiler.cc
@@ -63,9 +63,18 @@
   return jit_compiler->CompileMethod(self, method);
 }
 
+// Callers of this method assume it has NO_RETURN.
+NO_RETURN static void Usage(const char* fmt, ...) {
+  va_list ap;
+  va_start(ap, fmt);
+  std::string error;
+  StringAppendV(&error, fmt, ap);
+  LOG(FATAL) << error;
+  va_end(ap);
+  exit(EXIT_FAILURE);
+}
+
 JitCompiler::JitCompiler() : total_time_(0) {
-  auto* pass_manager_options = new PassManagerOptions;
-  pass_manager_options->SetDisablePassList("GVN,DCE,GVNCleanup");
   compiler_options_.reset(new CompilerOptions(
       CompilerOptions::kDefaultCompilerFilter,
       CompilerOptions::kDefaultHugeMethodThreshold,
@@ -84,9 +93,11 @@
       /* implicit_suspend_checks */ false,
       /* pic */ true,  // TODO: Support non-PIC in optimizing.
       /* verbose_methods */ nullptr,
-      pass_manager_options,
       /* init_failure_output */ nullptr,
       /* abort_on_hard_verifier_failure */ false));
+  for (const std::string& argument : Runtime::Current()->GetCompilerOptions()) {
+    compiler_options_->ParseCompilerOption(argument, Usage);
+  }
   const InstructionSet instruction_set = kRuntimeISA;
   for (const StringPiece option : Runtime::Current()->GetCompilerOptions()) {
     VLOG(compiler) << "JIT compiler option " << option;
diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc
index 384b879..85a1bde 100644
--- a/dex2oat/dex2oat.cc
+++ b/dex2oat/dex2oat.cc
@@ -445,38 +445,6 @@
   pthread_t pthread_;
 };
 
-static void ParseStringAfterChar(const std::string& s, char c, std::string* parsed_value) {
-  std::string::size_type colon = s.find(c);
-  if (colon == std::string::npos) {
-    Usage("Missing char %c in option %s\n", c, s.c_str());
-  }
-  // Add one to remove the char we were trimming until.
-  *parsed_value = s.substr(colon + 1);
-}
-
-static void ParseDouble(const std::string& option, char after_char, double min, double max,
-                        double* parsed_value) {
-  std::string substring;
-  ParseStringAfterChar(option, after_char, &substring);
-  bool sane_val = true;
-  double value;
-  if (false) {
-    // TODO: this doesn't seem to work on the emulator.  b/15114595
-    std::stringstream iss(substring);
-    iss >> value;
-    // Ensure that we have a value, there was no cruft after it and it satisfies a sensible range.
-    sane_val = iss.eof() && (value >= min) && (value <= max);
-  } else {
-    char* end = nullptr;
-    value = strtod(substring.c_str(), &end);
-    sane_val = *end == '\0' && value >= min && value <= max;
-  }
-  if (!sane_val) {
-    Usage("Invalid double value %s for option %s\n", substring.c_str(), option.c_str());
-  }
-  *parsed_value = value;
-}
-
 static constexpr size_t kMinDexFilesForSwap = 2;
 static constexpr size_t kMinDexFileCumulativeSizeForSwap = 20 * MB;
 
@@ -555,66 +523,21 @@
   struct ParserOptions {
     std::string oat_symbols;
     std::string boot_image_filename;
-    const char* compiler_filter_string = nullptr;
-    CompilerOptions::CompilerFilter compiler_filter = CompilerOptions::kDefaultCompilerFilter;
-    bool compile_pic = false;
-    int huge_method_threshold = CompilerOptions::kDefaultHugeMethodThreshold;
-    int large_method_threshold = CompilerOptions::kDefaultLargeMethodThreshold;
-    int small_method_threshold = CompilerOptions::kDefaultSmallMethodThreshold;
-    int tiny_method_threshold = CompilerOptions::kDefaultTinyMethodThreshold;
-    int num_dex_methods_threshold = CompilerOptions::kDefaultNumDexMethodsThreshold;
-    static constexpr int kUnsetInlineDepthLimit = -1;
-    int inline_depth_limit = kUnsetInlineDepthLimit;
-    static constexpr int kUnsetInlineMaxCodeUnits = -1;
-    int inline_max_code_units = kUnsetInlineMaxCodeUnits;
-
-    // Profile file to use
-    double top_k_profile_threshold = CompilerOptions::kDefaultTopKProfileThreshold;
-
-    bool debuggable = false;
-    bool include_patch_information = CompilerOptions::kDefaultIncludePatchInformation;
-    bool generate_debug_info = kIsDebugBuild;
     bool watch_dog_enabled = true;
-    bool abort_on_hard_verifier_error = false;
     bool requested_specific_compiler = false;
-
-    bool implicit_null_checks = false;
-    bool implicit_so_checks = false;
-    bool implicit_suspend_checks = false;
-
-    PassManagerOptions pass_manager_options;
-
     std::string error_msg;
   };
 
-  template <typename T>
-  static void ParseUintOption(const StringPiece& option,
-                              const std::string& option_name,
-                              T* out,
-                              bool is_long_option = true) {
-    std::string option_prefix = option_name + (is_long_option ? "=" : "");
-    DCHECK(option.starts_with(option_prefix));
-    const char* value_string = option.substr(option_prefix.size()).data();
-    int64_t parsed_integer_value;
-    if (!ParseInt(value_string, &parsed_integer_value)) {
-      Usage("Failed to parse %s '%s' as an integer", option_name.c_str(), value_string);
-    }
-    if (parsed_integer_value < 0) {
-      Usage("%s passed a negative value %d", option_name.c_str(), parsed_integer_value);
-    }
-    *out = dchecked_integral_cast<T>(parsed_integer_value);
-  }
-
   void ParseZipFd(const StringPiece& option) {
-    ParseUintOption(option, "--zip-fd", &zip_fd_);
+    ParseUintOption(option, "--zip-fd", &zip_fd_, Usage);
   }
 
   void ParseOatFd(const StringPiece& option) {
-    ParseUintOption(option, "--oat-fd", &oat_fd_);
+    ParseUintOption(option, "--oat-fd", &oat_fd_, Usage);
   }
 
   void ParseJ(const StringPiece& option) {
-    ParseUintOption(option, "-j", &thread_count_, /* is_long_option */ false);
+    ParseUintOption(option, "-j", &thread_count_, Usage, /* is_long_option */ false);
   }
 
   void ParseBase(const StringPiece& option) {
@@ -685,80 +608,15 @@
     }
   }
 
-  void ParseHugeMethodMax(const StringPiece& option, ParserOptions* parser_options) {
-    ParseUintOption(option, "--huge-method-max", &parser_options->huge_method_threshold);
-  }
-
-  void ParseLargeMethodMax(const StringPiece& option, ParserOptions* parser_options) {
-    ParseUintOption(option, "--large-method-max", &parser_options->large_method_threshold);
-  }
-
-  void ParseSmallMethodMax(const StringPiece& option, ParserOptions* parser_options) {
-    ParseUintOption(option, "--small-method-max", &parser_options->small_method_threshold);
-  }
-
-  void ParseTinyMethodMax(const StringPiece& option, ParserOptions* parser_options) {
-    ParseUintOption(option, "--tiny-method-max", &parser_options->tiny_method_threshold);
-  }
-
-  void ParseNumDexMethods(const StringPiece& option, ParserOptions* parser_options) {
-    ParseUintOption(option, "--num-dex-methods", &parser_options->num_dex_methods_threshold);
-  }
-
-  void ParseInlineDepthLimit(const StringPiece& option, ParserOptions* parser_options) {
-    ParseUintOption(option, "--inline-depth-limit", &parser_options->inline_depth_limit);
-  }
-
-  void ParseInlineMaxCodeUnits(const StringPiece& option, ParserOptions* parser_options) {
-    ParseUintOption(option, "--inline-max-code-units=", &parser_options->inline_max_code_units);
-  }
-
-  void ParseDisablePasses(const StringPiece& option, ParserOptions* parser_options) {
-    DCHECK(option.starts_with("--disable-passes="));
-    const std::string disable_passes = option.substr(strlen("--disable-passes=")).data();
-    parser_options->pass_manager_options.SetDisablePassList(disable_passes);
-  }
-
-  void ParsePrintPasses(const StringPiece& option, ParserOptions* parser_options) {
-    DCHECK(option.starts_with("--print-passes="));
-    const std::string print_passes = option.substr(strlen("--print-passes=")).data();
-    parser_options->pass_manager_options.SetPrintPassList(print_passes);
-  }
-
-  void ParseDumpCfgPasses(const StringPiece& option, ParserOptions* parser_options) {
-    DCHECK(option.starts_with("--dump-cfg-passes="));
-    const std::string dump_passes_string = option.substr(strlen("--dump-cfg-passes=")).data();
-    parser_options->pass_manager_options.SetDumpPassList(dump_passes_string);
-  }
-
-  void ParsePassOptions(const StringPiece& option, ParserOptions* parser_options) {
-    DCHECK(option.starts_with("--pass-options="));
-    const std::string pass_options = option.substr(strlen("--pass-options=")).data();
-    parser_options->pass_manager_options.SetOverriddenPassOptions(pass_options);
-  }
-
-  void ParseDumpInitFailures(const StringPiece& option) {
-    DCHECK(option.starts_with("--dump-init-failures="));
-    std::string file_name = option.substr(strlen("--dump-init-failures=")).data();
-    init_failure_output_.reset(new std::ofstream(file_name));
-    if (init_failure_output_.get() == nullptr) {
-      LOG(ERROR) << "Failed to allocate ofstream";
-    } else if (init_failure_output_->fail()) {
-      LOG(ERROR) << "Failed to open " << file_name << " for writing the initialization "
-                 << "failures.";
-      init_failure_output_.reset();
-    }
-  }
-
   void ParseSwapFd(const StringPiece& option) {
-    ParseUintOption(option, "--swap-fd", &swap_fd_);
+    ParseUintOption(option, "--swap-fd", &swap_fd_, Usage);
   }
 
   void ProcessOptions(ParserOptions* parser_options) {
     image_ = (!image_filename_.empty());
     if (image_) {
       // We need the boot image to always be debuggable.
-      parser_options->debuggable = true;
+      compiler_options_->debuggable_ = true;
     }
 
     if (oat_filename_.empty() && oat_fd_ == -1) {
@@ -882,44 +740,19 @@
       }
     }
 
-    if (parser_options->compiler_filter_string == nullptr) {
-      parser_options->compiler_filter_string = "speed";
-    }
-
-    CHECK(parser_options->compiler_filter_string != nullptr);
-    if (strcmp(parser_options->compiler_filter_string, "verify-none") == 0) {
-      parser_options->compiler_filter = CompilerOptions::kVerifyNone;
-    } else if (strcmp(parser_options->compiler_filter_string, "interpret-only") == 0) {
-      parser_options->compiler_filter = CompilerOptions::kInterpretOnly;
-    } else if (strcmp(parser_options->compiler_filter_string, "verify-at-runtime") == 0) {
-      parser_options->compiler_filter = CompilerOptions::kVerifyAtRuntime;
-    } else if (strcmp(parser_options->compiler_filter_string, "space") == 0) {
-      parser_options->compiler_filter = CompilerOptions::kSpace;
-    } else if (strcmp(parser_options->compiler_filter_string, "balanced") == 0) {
-      parser_options->compiler_filter = CompilerOptions::kBalanced;
-    } else if (strcmp(parser_options->compiler_filter_string, "speed") == 0) {
-      parser_options->compiler_filter = CompilerOptions::kSpeed;
-    } else if (strcmp(parser_options->compiler_filter_string, "everything") == 0) {
-      parser_options->compiler_filter = CompilerOptions::kEverything;
-    } else if (strcmp(parser_options->compiler_filter_string, "time") == 0) {
-      parser_options->compiler_filter = CompilerOptions::kTime;
-    } else {
-      Usage("Unknown --compiler-filter value %s", parser_options->compiler_filter_string);
-    }
-
     // It they are not set, use default values for inlining settings.
     // TODO: We should rethink the compiler filter. We mostly save
     // time here, which is orthogonal to space.
-    if (parser_options->inline_depth_limit == ParserOptions::kUnsetInlineDepthLimit) {
-      parser_options->inline_depth_limit =
-          (parser_options->compiler_filter == CompilerOptions::kSpace)
+    if (compiler_options_->inline_depth_limit_ == CompilerOptions::kUnsetInlineDepthLimit) {
+      compiler_options_->inline_depth_limit_ =
+          (compiler_options_->compiler_filter_ == CompilerOptions::kSpace)
           // Implementation of the space filter: limit inlining depth.
           ? CompilerOptions::kSpaceFilterInlineDepthLimit
           : CompilerOptions::kDefaultInlineDepthLimit;
     }
-    if (parser_options->inline_max_code_units == ParserOptions::kUnsetInlineMaxCodeUnits) {
-      parser_options->inline_max_code_units =
-          (parser_options->compiler_filter == CompilerOptions::kSpace)
+    if (compiler_options_->inline_max_code_units_ == CompilerOptions::kUnsetInlineMaxCodeUnits) {
+      compiler_options_->inline_max_code_units_ =
+          (compiler_options_->compiler_filter_ == CompilerOptions::kSpace)
           // Implementation of the space filter: limit inlining max code units.
           ? CompilerOptions::kSpaceFilterInlineMaxCodeUnits
           : CompilerOptions::kDefaultInlineMaxCodeUnits;
@@ -935,8 +768,8 @@
       case kX86_64:
       case kMips:
       case kMips64:
-        parser_options->implicit_null_checks = true;
-        parser_options->implicit_so_checks = true;
+        compiler_options_->implicit_null_checks_ = true;
+        compiler_options_->implicit_so_checks_ = true;
         break;
 
       default:
@@ -944,29 +777,7 @@
         break;
     }
 
-    compiler_options_.reset(new CompilerOptions(parser_options->compiler_filter,
-                                                parser_options->huge_method_threshold,
-                                                parser_options->large_method_threshold,
-                                                parser_options->small_method_threshold,
-                                                parser_options->tiny_method_threshold,
-                                                parser_options->num_dex_methods_threshold,
-                                                parser_options->inline_depth_limit,
-                                                parser_options->inline_max_code_units,
-                                                parser_options->include_patch_information,
-                                                parser_options->top_k_profile_threshold,
-                                                parser_options->debuggable,
-                                                parser_options->generate_debug_info,
-                                                parser_options->implicit_null_checks,
-                                                parser_options->implicit_so_checks,
-                                                parser_options->implicit_suspend_checks,
-                                                parser_options->compile_pic,
-                                                verbose_methods_.empty() ?
-                                                    nullptr :
-                                                    &verbose_methods_,
-                                                new PassManagerOptions(
-                                                    parser_options->pass_manager_options),
-                                                init_failure_output_.get(),
-                                                parser_options->abort_on_hard_verifier_error));
+    compiler_options_->verbose_methods_ = verbose_methods_.empty() ? nullptr : &verbose_methods_;
 
     // Done with usage checks, enable watchdog if requested
     if (parser_options->watch_dog_enabled) {
@@ -977,7 +788,7 @@
     key_value_store_.reset(new SafeMap<std::string, std::string>());
   }
 
-  void InsertCompileOptions(int argc, char** argv, ParserOptions* parser_options) {
+  void InsertCompileOptions(int argc, char** argv) {
     std::ostringstream oss;
     for (int i = 0; i < argc; ++i) {
       if (i > 0) {
@@ -991,10 +802,10 @@
     key_value_store_->Put(OatHeader::kDex2OatHostKey, oss.str());
     key_value_store_->Put(
         OatHeader::kPicKey,
-        parser_options->compile_pic ? OatHeader::kTrueValue : OatHeader::kFalseValue);
+        compiler_options_->compile_pic_ ? OatHeader::kTrueValue : OatHeader::kFalseValue);
     key_value_store_->Put(
         OatHeader::kDebuggableKey,
-        parser_options->debuggable ? OatHeader::kTrueValue : OatHeader::kFalseValue);
+        compiler_options_->debuggable_ ? OatHeader::kTrueValue : OatHeader::kFalseValue);
   }
 
   // Parse the arguments from the command line. In case of an unrecognized option or impossible
@@ -1015,6 +826,7 @@
     }
 
     std::unique_ptr<ParserOptions> parser_options(new ParserOptions());
+    compiler_options_.reset(new CompilerOptions());
 
     for (int i = 0; i < argc; i++) {
       const StringPiece option(argv[i]);
@@ -1072,24 +884,11 @@
         ParseInstructionSetFeatures(option, parser_options.get());
       } else if (option.starts_with("--compiler-backend=")) {
         ParseCompilerBackend(option, parser_options.get());
-      } else if (option.starts_with("--compiler-filter=")) {
-        parser_options->compiler_filter_string = option.substr(strlen("--compiler-filter=")).data();
-      } else if (option == "--compile-pic") {
-        parser_options->compile_pic = true;
-      } else if (option.starts_with("--huge-method-max=")) {
-        ParseHugeMethodMax(option, parser_options.get());
-      } else if (option.starts_with("--large-method-max=")) {
-        ParseLargeMethodMax(option, parser_options.get());
-      } else if (option.starts_with("--small-method-max=")) {
-        ParseSmallMethodMax(option, parser_options.get());
-      } else if (option.starts_with("--tiny-method-max=")) {
-        ParseTinyMethodMax(option, parser_options.get());
-      } else if (option.starts_with("--num-dex-methods=")) {
-        ParseNumDexMethods(option, parser_options.get());
-      } else if (option.starts_with("--inline-depth-limit=")) {
-        ParseInlineDepthLimit(option, parser_options.get());
-      } else if (option.starts_with("--inline-max-code-units=")) {
-        ParseInlineMaxCodeUnits(option, parser_options.get());
+      } else if (option.starts_with("--profile-file=")) {
+        profile_file_ = option.substr(strlen("--profile-file=")).data();
+        VLOG(compiler) << "dex2oat: profile file is " << profile_file_;
+      } else if (option == "--no-profile-file") {
+        // No profile
       } else if (option == "--host") {
         is_host_ = true;
       } else if (option == "--runtime-arg") {
@@ -1110,52 +909,16 @@
         dump_cfg_append_ = true;
       } else if (option == "--dump-stats") {
         dump_stats_ = true;
-      } else if (option == "--generate-debug-info" || option == "-g") {
-        parser_options->generate_debug_info = true;
-      } else if (option == "--no-generate-debug-info") {
-        parser_options->generate_debug_info = false;
-      } else if (option == "--debuggable") {
-        parser_options->debuggable = true;
-        parser_options->generate_debug_info = true;
-      } else if (option.starts_with("--profile-file=")) {
-        profile_file_ = option.substr(strlen("--profile-file=")).data();
-        VLOG(compiler) << "dex2oat: profile file is " << profile_file_;
-      } else if (option == "--no-profile-file") {
-        // No profile
-      } else if (option.starts_with("--top-k-profile-threshold=")) {
-        ParseDouble(option.data(), '=', 0.0, 100.0, &parser_options->top_k_profile_threshold);
-      } else if (option == "--print-pass-names") {
-        parser_options->pass_manager_options.SetPrintPassNames(true);
-      } else if (option.starts_with("--disable-passes=")) {
-        ParseDisablePasses(option, parser_options.get());
-      } else if (option.starts_with("--print-passes=")) {
-        ParsePrintPasses(option, parser_options.get());
-      } else if (option == "--print-all-passes") {
-        parser_options->pass_manager_options.SetPrintAllPasses();
-      } else if (option.starts_with("--dump-cfg-passes=")) {
-        ParseDumpCfgPasses(option, parser_options.get());
-      } else if (option == "--print-pass-options") {
-        parser_options->pass_manager_options.SetPrintPassOptions(true);
-      } else if (option.starts_with("--pass-options=")) {
-        ParsePassOptions(option, parser_options.get());
-      } else if (option == "--include-patch-information") {
-        parser_options->include_patch_information = true;
-      } else if (option == "--no-include-patch-information") {
-        parser_options->include_patch_information = false;
+      } else if (option.starts_with("--swap-file=")) {
+        swap_file_name_ = option.substr(strlen("--swap-file=")).data();
+      } else if (option.starts_with("--swap-fd=")) {
+        ParseSwapFd(option);
       } else if (option.starts_with("--verbose-methods=")) {
         // TODO: rather than switch off compiler logging, make all VLOG(compiler) messages
         //       conditional on having verbost methods.
         gLogVerbosity.compiler = false;
         Split(option.substr(strlen("--verbose-methods=")).ToString(), ',', &verbose_methods_);
-      } else if (option.starts_with("--dump-init-failures=")) {
-        ParseDumpInitFailures(option);
-      } else if (option.starts_with("--swap-file=")) {
-        swap_file_name_ = option.substr(strlen("--swap-file=")).data();
-      } else if (option.starts_with("--swap-fd=")) {
-        ParseSwapFd(option);
-      } else if (option == "--abort-on-hard-verifier-error") {
-        parser_options->abort_on_hard_verifier_error = true;
-      } else {
+      } else if (!compiler_options_->ParseCompilerOption(option, Usage)) {
         Usage("Unknown argument %s", option.data());
       }
     }
@@ -1163,7 +926,7 @@
     ProcessOptions(parser_options.get());
 
     // Insert some compiler things.
-    InsertCompileOptions(argc, argv, parser_options.get());
+    InsertCompileOptions(argc, argv);
   }
 
   // Check whether the oat output file is writable, and open it for later. Also open a swap file,
@@ -2005,7 +1768,6 @@
   std::string profile_file_;  // Profile file to use
   TimingLogger* timings_;
   std::unique_ptr<CumulativeLogger> compiler_phases_timings_;
-  std::unique_ptr<std::ostream> init_failure_output_;
 
   DISALLOW_IMPLICIT_CONSTRUCTORS(Dex2Oat);
 };
diff --git a/runtime/utils.cc b/runtime/utils.cc
index dee4f9c..48dce63 100644
--- a/runtime/utils.cc
+++ b/runtime/utils.cc
@@ -1835,4 +1835,43 @@
   os << "Something went wrong, didn't find the method in the class data.";
 }
 
+static void ParseStringAfterChar(const std::string& s,
+                                 char c,
+                                 std::string* parsed_value,
+                                 UsageFn Usage) {
+  std::string::size_type colon = s.find(c);
+  if (colon == std::string::npos) {
+    Usage("Missing char %c in option %s\n", c, s.c_str());
+  }
+  // Add one to remove the char we were trimming until.
+  *parsed_value = s.substr(colon + 1);
+}
+
+void ParseDouble(const std::string& option,
+                 char after_char,
+                 double min,
+                 double max,
+                 double* parsed_value,
+                 UsageFn Usage) {
+  std::string substring;
+  ParseStringAfterChar(option, after_char, &substring, Usage);
+  bool sane_val = true;
+  double value;
+  if ((false)) {
+    // TODO: this doesn't seem to work on the emulator.  b/15114595
+    std::stringstream iss(substring);
+    iss >> value;
+    // Ensure that we have a value, there was no cruft after it and it satisfies a sensible range.
+    sane_val = iss.eof() && (value >= min) && (value <= max);
+  } else {
+    char* end = nullptr;
+    value = strtod(substring.c_str(), &end);
+    sane_val = *end == '\0' && value >= min && value <= max;
+  }
+  if (!sane_val) {
+    Usage("Invalid double value %s for option %s\n", substring.c_str(), option.c_str());
+  }
+  *parsed_value = value;
+}
+
 }  // namespace art
diff --git a/runtime/utils.h b/runtime/utils.h
index bd52b68..5cca296 100644
--- a/runtime/utils.h
+++ b/runtime/utils.h
@@ -26,8 +26,10 @@
 #include <vector>
 
 #include "arch/instruction_set.h"
+#include "base/casts.h"
 #include "base/logging.h"
 #include "base/mutex.h"
+#include "base/stringpiece.h"
 #include "globals.h"
 #include "primitive.h"
 
@@ -35,7 +37,6 @@
 
 namespace art {
 
-class ArtCode;
 class ArtField;
 class ArtMethod;
 class DexFile;
@@ -321,6 +322,34 @@
   return reinterpret_cast<const void*>(code);
 }
 
+using UsageFn = void (*)(const char*, ...);
+
+template <typename T>
+static void ParseUintOption(const StringPiece& option,
+                            const std::string& option_name,
+                            T* out,
+                            UsageFn Usage,
+                            bool is_long_option = true) {
+  std::string option_prefix = option_name + (is_long_option ? "=" : "");
+  DCHECK(option.starts_with(option_prefix));
+  const char* value_string = option.substr(option_prefix.size()).data();
+  int64_t parsed_integer_value;
+  if (!ParseInt(value_string, &parsed_integer_value)) {
+    Usage("Failed to parse %s '%s' as an integer", option_name.c_str(), value_string);
+  }
+  if (parsed_integer_value < 0) {
+    Usage("%s passed a negative value %d", option_name.c_str(), parsed_integer_value);
+  }
+  *out = dchecked_integral_cast<T>(parsed_integer_value);
+}
+
+void ParseDouble(const std::string& option,
+                 char after_char,
+                 double min,
+                 double max,
+                 double* parsed_value,
+                 UsageFn Usage);
+
 }  // namespace art
 
 #endif  // ART_RUNTIME_UTILS_H_