}
}
- // Parse the arguments from the command line. In case of an unrecognized option or impossible
- // values/combinations, a usage error will be displayed and exit() is called. Thus, if the method
- // returns, arguments have been successfully parsed.
- void ParseArgs(int argc, char** argv) {
- original_argc = argc;
- original_argv = argv;
-
- InitLogging(argv);
-
- // Skip over argv[0].
- argv++;
- argc--;
-
- if (argc == 0) {
- Usage("No arguments specified");
- }
-
+ 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;
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();
+ long long int 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 = parsed_integer_value;
+ }
- for (int i = 0; i < argc; i++) {
- const StringPiece option(argv[i]);
- const bool log_options = false;
- if (log_options) {
- LOG(INFO) << "dex2oat: option[" << i << "]=" << argv[i];
- }
- if (option.starts_with("--dex-file=")) {
- dex_filenames_.push_back(option.substr(strlen("--dex-file=")).data());
- } else if (option.starts_with("--dex-location=")) {
- dex_locations_.push_back(option.substr(strlen("--dex-location=")).data());
- } else if (option.starts_with("--zip-fd=")) {
- const char* zip_fd_str = option.substr(strlen("--zip-fd=")).data();
- if (!ParseInt(zip_fd_str, &zip_fd_)) {
- Usage("Failed to parse --zip-fd argument '%s' as an integer", zip_fd_str);
- }
- if (zip_fd_ < 0) {
- Usage("--zip-fd passed a negative value %d", zip_fd_);
- }
- } else if (option.starts_with("--zip-location=")) {
- zip_location_ = option.substr(strlen("--zip-location=")).data();
- } else if (option.starts_with("--oat-file=")) {
- oat_filename_ = option.substr(strlen("--oat-file=")).data();
- } else if (option.starts_with("--oat-symbols=")) {
- oat_symbols = option.substr(strlen("--oat-symbols=")).data();
- } else if (option.starts_with("--oat-fd=")) {
- const char* oat_fd_str = option.substr(strlen("--oat-fd=")).data();
- if (!ParseInt(oat_fd_str, &oat_fd_)) {
- Usage("Failed to parse --oat-fd argument '%s' as an integer", oat_fd_str);
- }
- if (oat_fd_ < 0) {
- Usage("--oat-fd passed a negative value %d", oat_fd_);
- }
- } else if (option == "--watch-dog") {
- watch_dog_enabled = true;
- } else if (option == "--no-watch-dog") {
- watch_dog_enabled = false;
- } else if (option.starts_with("-j")) {
- const char* thread_count_str = option.substr(strlen("-j")).data();
- if (!ParseUint(thread_count_str, &thread_count_)) {
- Usage("Failed to parse -j argument '%s' as an integer", thread_count_str);
- }
- } else if (option.starts_with("--oat-location=")) {
- oat_location_ = option.substr(strlen("--oat-location=")).data();
- } else if (option.starts_with("--image=")) {
- image_filename_ = option.substr(strlen("--image=")).data();
- } else if (option.starts_with("--image-classes=")) {
- image_classes_filename_ = option.substr(strlen("--image-classes=")).data();
- } else if (option.starts_with("--image-classes-zip=")) {
- image_classes_zip_filename_ = option.substr(strlen("--image-classes-zip=")).data();
- } else if (option.starts_with("--compiled-classes=")) {
- compiled_classes_filename_ = option.substr(strlen("--compiled-classes=")).data();
- } else if (option.starts_with("--compiled-classes-zip=")) {
- compiled_classes_zip_filename_ = option.substr(strlen("--compiled-classes-zip=")).data();
- } else if (option.starts_with("--compiled-methods=")) {
- compiled_methods_filename_ = option.substr(strlen("--compiled-methods=")).data();
- } else if (option.starts_with("--compiled-methods-zip=")) {
- compiled_methods_zip_filename_ = option.substr(strlen("--compiled-methods-zip=")).data();
- } else if (option.starts_with("--base=")) {
- const char* image_base_str = option.substr(strlen("--base=")).data();
- char* end;
- image_base_ = strtoul(image_base_str, &end, 16);
- if (end == image_base_str || *end != '\0') {
- Usage("Failed to parse hexadecimal value for option %s", option.data());
- }
- } else if (option.starts_with("--boot-image=")) {
- boot_image_filename = option.substr(strlen("--boot-image=")).data();
- } else if (option.starts_with("--android-root=")) {
- android_root_ = option.substr(strlen("--android-root=")).data();
- } else if (option.starts_with("--instruction-set=")) {
- StringPiece instruction_set_str = option.substr(strlen("--instruction-set=")).data();
- // StringPiece is not necessarily zero-terminated, so need to make a copy and ensure it.
- std::unique_ptr<char[]> buf(new char[instruction_set_str.length() + 1]);
- strncpy(buf.get(), instruction_set_str.data(), instruction_set_str.length());
- buf.get()[instruction_set_str.length()] = 0;
- instruction_set_ = GetInstructionSetFromString(buf.get());
- // arm actually means thumb2.
- if (instruction_set_ == InstructionSet::kArm) {
- instruction_set_ = InstructionSet::kThumb2;
- }
- } else if (option.starts_with("--instruction-set-variant=")) {
- StringPiece str = option.substr(strlen("--instruction-set-variant=")).data();
- instruction_set_features_.reset(
- InstructionSetFeatures::FromVariant(instruction_set_, str.as_string(), &error_msg));
- if (instruction_set_features_.get() == nullptr) {
- Usage("%s", error_msg.c_str());
- }
- } else if (option.starts_with("--instruction-set-features=")) {
- StringPiece str = option.substr(strlen("--instruction-set-features=")).data();
- if (instruction_set_features_.get() == nullptr) {
- instruction_set_features_.reset(
- InstructionSetFeatures::FromVariant(instruction_set_, "default", &error_msg));
- if (instruction_set_features_.get() == nullptr) {
- Usage("Problem initializing default instruction set features variant: %s",
- error_msg.c_str());
- }
- }
- instruction_set_features_.reset(
- instruction_set_features_->AddFeaturesFromString(str.as_string(), &error_msg));
- if (instruction_set_features_.get() == nullptr) {
- Usage("Error parsing '%s': %s", option.data(), error_msg.c_str());
- }
- } else if (option.starts_with("--compiler-backend=")) {
- requested_specific_compiler = true;
- StringPiece backend_str = option.substr(strlen("--compiler-backend=")).data();
- if (backend_str == "Quick") {
- compiler_kind_ = Compiler::kQuick;
- } else if (backend_str == "Optimizing") {
- compiler_kind_ = Compiler::kOptimizing;
- } else {
- Usage("Unknown compiler backend: %s", backend_str.data());
- }
- } else if (option.starts_with("--compiler-filter=")) {
- compiler_filter_string = option.substr(strlen("--compiler-filter=")).data();
- } else if (option == "--compile-pic") {
- compile_pic = true;
- } else if (option.starts_with("--huge-method-max=")) {
- const char* threshold = option.substr(strlen("--huge-method-max=")).data();
- if (!ParseInt(threshold, &huge_method_threshold)) {
- Usage("Failed to parse --huge-method-max '%s' as an integer", threshold);
- }
- if (huge_method_threshold < 0) {
- Usage("--huge-method-max passed a negative value %s", huge_method_threshold);
- }
- } else if (option.starts_with("--large-method-max=")) {
- const char* threshold = option.substr(strlen("--large-method-max=")).data();
- if (!ParseInt(threshold, &large_method_threshold)) {
- Usage("Failed to parse --large-method-max '%s' as an integer", threshold);
- }
- if (large_method_threshold < 0) {
- Usage("--large-method-max passed a negative value %s", large_method_threshold);
- }
- } else if (option.starts_with("--small-method-max=")) {
- const char* threshold = option.substr(strlen("--small-method-max=")).data();
- if (!ParseInt(threshold, &small_method_threshold)) {
- Usage("Failed to parse --small-method-max '%s' as an integer", threshold);
- }
- if (small_method_threshold < 0) {
- Usage("--small-method-max passed a negative value %s", small_method_threshold);
- }
- } else if (option.starts_with("--tiny-method-max=")) {
- const char* threshold = option.substr(strlen("--tiny-method-max=")).data();
- if (!ParseInt(threshold, &tiny_method_threshold)) {
- Usage("Failed to parse --tiny-method-max '%s' as an integer", threshold);
- }
- if (tiny_method_threshold < 0) {
- Usage("--tiny-method-max passed a negative value %s", tiny_method_threshold);
- }
- } else if (option.starts_with("--num-dex-methods=")) {
- const char* threshold = option.substr(strlen("--num-dex-methods=")).data();
- if (!ParseInt(threshold, &num_dex_methods_threshold)) {
- Usage("Failed to parse --num-dex-methods '%s' as an integer", threshold);
- }
- if (num_dex_methods_threshold < 0) {
- Usage("--num-dex-methods passed a negative value %s", num_dex_methods_threshold);
- }
- } else if (option.starts_with("--inline-depth-limit=")) {
- const char* limit = option.substr(strlen("--inline-depth-limit=")).data();
- if (!ParseInt(limit, &inline_depth_limit)) {
- Usage("Failed to parse --inline-depth-limit '%s' as an integer", limit);
- }
- if (inline_depth_limit < 0) {
- Usage("--inline-depth-limit passed a negative value %s", inline_depth_limit);
- }
- } else if (option.starts_with("--inline-max-code-units=")) {
- const char* code_units = option.substr(strlen("--inline-max-code-units=")).data();
- if (!ParseInt(code_units, &inline_max_code_units)) {
- Usage("Failed to parse --inline-max-code-units '%s' as an integer", code_units);
- }
- if (inline_max_code_units < 0) {
- Usage("--inline-max-code-units passed a negative value %s", inline_max_code_units);
- }
- } else if (option == "--host") {
- is_host_ = true;
- } else if (option == "--runtime-arg") {
- if (++i >= argc) {
- Usage("Missing required argument for --runtime-arg");
- }
- if (log_options) {
- LOG(INFO) << "dex2oat: option[" << i << "]=" << argv[i];
- }
- runtime_args_.push_back(argv[i]);
- } else if (option == "--dump-timing") {
- dump_timing_ = true;
- } else if (option == "--dump-passes") {
- dump_passes_ = true;
- } else if (option.starts_with("--dump-cfg=")) {
- dump_cfg_file_name_ = option.substr(strlen("--dump-cfg=")).data();
- } else if (option == "--dump-stats") {
- dump_stats_ = true;
- } 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("--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, &top_k_profile_threshold);
- } else if (option == "--print-pass-names") {
- pass_manager_options.SetPrintPassNames(true);
- } else if (option.starts_with("--disable-passes=")) {
- const std::string disable_passes = option.substr(strlen("--disable-passes=")).data();
- pass_manager_options.SetDisablePassList(disable_passes);
- } else if (option.starts_with("--print-passes=")) {
- const std::string print_passes = option.substr(strlen("--print-passes=")).data();
- pass_manager_options.SetPrintPassList(print_passes);
- } else if (option == "--print-all-passes") {
- pass_manager_options.SetPrintAllPasses();
- } else if (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);
- } else if (option == "--print-pass-options") {
- pass_manager_options.SetPrintPassOptions(true);
- } else if (option.starts_with("--pass-options=")) {
- const std::string options = option.substr(strlen("--pass-options=")).data();
- pass_manager_options.SetOverriddenPassOptions(options);
- } else if (option == "--include-patch-information") {
- include_patch_information = true;
- } else if (option == "--no-include-patch-information") {
- include_patch_information = false;
- } 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=")) {
- 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();
- }
- } else if (option.starts_with("--swap-file=")) {
- swap_file_name_ = option.substr(strlen("--swap-file=")).data();
- } else if (option.starts_with("--swap-fd=")) {
- const char* swap_fd_str = option.substr(strlen("--swap-fd=")).data();
- if (!ParseInt(swap_fd_str, &swap_fd_)) {
- Usage("Failed to parse --swap-fd argument '%s' as an integer", swap_fd_str);
- }
- if (swap_fd_ < 0) {
- Usage("--swap-fd passed a negative value %d", swap_fd_);
- }
- } else if (option == "--abort-on-hard-verifier-error") {
- abort_on_hard_verifier_error = true;
- } else {
- Usage("Unknown argument %s", option.data());
+ void ParseZipFd(const StringPiece& option) {
+ ParseUintOption(option, "--zip-fd", &zip_fd_);
+ }
+
+ void ParseOatFd(const StringPiece& option) {
+ ParseUintOption(option, "--oat-fd", &oat_fd_);
+ }
+
+ void ParseJ(const StringPiece& option) {
+ ParseUintOption(option, "-j", &thread_count_, /* is_long_option */ false);
+ }
+
+ void ParseBase(const StringPiece& option) {
+ DCHECK(option.starts_with("--base="));
+ const char* image_base_str = option.substr(strlen("--base=")).data();
+ char* end;
+ image_base_ = strtoul(image_base_str, &end, 16);
+ if (end == image_base_str || *end != '\0') {
+ Usage("Failed to parse hexadecimal value for option %s", option.data());
+ }
+ }
+
+ void ParseInstructionSet(const StringPiece& option) {
+ DCHECK(option.starts_with("--instruction-set="));
+ StringPiece instruction_set_str = option.substr(strlen("--instruction-set=")).data();
+ // StringPiece is not necessarily zero-terminated, so need to make a copy and ensure it.
+ std::unique_ptr<char[]> buf(new char[instruction_set_str.length() + 1]);
+ strncpy(buf.get(), instruction_set_str.data(), instruction_set_str.length());
+ buf.get()[instruction_set_str.length()] = 0;
+ instruction_set_ = GetInstructionSetFromString(buf.get());
+ // arm actually means thumb2.
+ if (instruction_set_ == InstructionSet::kArm) {
+ instruction_set_ = InstructionSet::kThumb2;
+ }
+ }
+
+ void ParseInstructionSetVariant(const StringPiece& option, ParserOptions* parser_options) {
+ DCHECK(option.starts_with("--instruction-set-variant="));
+ StringPiece str = option.substr(strlen("--instruction-set-variant=")).data();
+ instruction_set_features_.reset(
+ InstructionSetFeatures::FromVariant(
+ instruction_set_, str.as_string(), &parser_options->error_msg));
+ if (instruction_set_features_.get() == nullptr) {
+ Usage("%s", parser_options->error_msg.c_str());
+ }
+ }
+
+ void ParseInstructionSetFeatures(const StringPiece& option, ParserOptions* parser_options) {
+ DCHECK(option.starts_with("--instruction-set-features="));
+ StringPiece str = option.substr(strlen("--instruction-set-features=")).data();
+ if (instruction_set_features_.get() == nullptr) {
+ instruction_set_features_.reset(
+ InstructionSetFeatures::FromVariant(
+ instruction_set_, "default", &parser_options->error_msg));
+ if (instruction_set_features_.get() == nullptr) {
+ Usage("Problem initializing default instruction set features variant: %s",
+ parser_options->error_msg.c_str());
}
}
+ instruction_set_features_.reset(
+ instruction_set_features_->AddFeaturesFromString(str.as_string(),
+ &parser_options->error_msg));
+ if (instruction_set_features_.get() == nullptr) {
+ Usage("Error parsing '%s': %s", option.data(), parser_options->error_msg.c_str());
+ }
+ }
+
+ void ParseCompilerBackend(const StringPiece& option, ParserOptions* parser_options) {
+ DCHECK(option.starts_with("--compiler-backend="));
+ parser_options->requested_specific_compiler = true;
+ StringPiece backend_str = option.substr(strlen("--compiler-backend=")).data();
+ if (backend_str == "Quick") {
+ compiler_kind_ = Compiler::kQuick;
+ } else if (backend_str == "Optimizing") {
+ compiler_kind_ = Compiler::kOptimizing;
+ } else {
+ Usage("Unknown compiler backend: %s", backend_str.data());
+ }
+ }
+
+ 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_);
+ }
+
+ void ProcessOptions(ParserOptions* parser_options) {
image_ = (!image_filename_.empty());
- if (!requested_specific_compiler && !kUseOptimizingCompiler) {
+ if (!parser_options->requested_specific_compiler && !kUseOptimizingCompiler) {
// If no specific compiler is requested, the current behavior is
// to compile the boot image with Quick, and the rest with Optimizing.
compiler_kind_ = image_ ? Compiler::kQuick : Compiler::kOptimizing;
}
-
if (compiler_kind_ == Compiler::kOptimizing) {
// Optimizing only supports PIC mode.
- compile_pic = true;
+ parser_options->compile_pic = true;
}
if (oat_filename_.empty() && oat_fd_ == -1) {
Usage("--oat-file should not be used with --oat-fd");
}
- if (!oat_symbols.empty() && oat_fd_ != -1) {
+ if (!parser_options->oat_symbols.empty() && oat_fd_ != -1) {
Usage("--oat-symbols should not be used with --oat-fd");
}
- if (!oat_symbols.empty() && is_host_) {
+ if (!parser_options->oat_symbols.empty() && is_host_) {
Usage("--oat-symbols should not be used with --host");
}
android_root_ += android_root_env_var;
}
- if (!image_ && boot_image_filename.empty()) {
- boot_image_filename += android_root_;
- boot_image_filename += "/framework/boot.art";
+ if (!image_ && parser_options->boot_image_filename.empty()) {
+ parser_options->boot_image_filename += android_root_;
+ parser_options->boot_image_filename += "/framework/boot.art";
}
- if (!boot_image_filename.empty()) {
+ if (!parser_options->boot_image_filename.empty()) {
boot_image_option_ += "-Ximage:";
- boot_image_option_ += boot_image_filename;
+ boot_image_option_ += parser_options->boot_image_filename;
}
if (image_classes_filename_ != nullptr && !image_) {
}
oat_stripped_ = oat_filename_;
- if (!oat_symbols.empty()) {
- oat_unstripped_ = oat_symbols;
+ if (!parser_options->oat_symbols.empty()) {
+ oat_unstripped_ = parser_options->oat_symbols;
} else {
oat_unstripped_ = oat_filename_;
}
// instruction set.
if (instruction_set_features_.get() == nullptr) {
instruction_set_features_.reset(
- InstructionSetFeatures::FromVariant(instruction_set_, "default", &error_msg));
+ InstructionSetFeatures::FromVariant(
+ instruction_set_, "default", &parser_options->error_msg));
if (instruction_set_features_.get() == nullptr) {
Usage("Problem initializing default instruction set features variant: %s",
- error_msg.c_str());
+ parser_options->error_msg.c_str());
}
}
}
}
- if (compiler_filter_string == nullptr) {
- compiler_filter_string = "speed";
- }
-
- CHECK(compiler_filter_string != nullptr);
- CompilerOptions::CompilerFilter compiler_filter = CompilerOptions::kDefaultCompilerFilter;
- 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;
+ 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", compiler_filter_string);
+ 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 (inline_depth_limit == kUnsetInlineDepthLimit) {
- inline_depth_limit = (compiler_filter == CompilerOptions::kSpace)
+ if (parser_options->inline_depth_limit == ParserOptions::kUnsetInlineDepthLimit) {
+ parser_options->inline_depth_limit =
+ (parser_options->compiler_filter == CompilerOptions::kSpace)
// Implementation of the space filter: limit inlining depth.
? CompilerOptions::kSpaceFilterInlineDepthLimit
: CompilerOptions::kDefaultInlineDepthLimit;
}
- if (inline_max_code_units == kUnsetInlineMaxCodeUnits) {
- inline_max_code_units = (compiler_filter == CompilerOptions::kSpace)
+ if (parser_options->inline_max_code_units == ParserOptions::kUnsetInlineMaxCodeUnits) {
+ parser_options->inline_max_code_units =
+ (parser_options->compiler_filter == CompilerOptions::kSpace)
// Implementation of the space filter: limit inlining max code units.
? CompilerOptions::kSpaceFilterInlineMaxCodeUnits
: CompilerOptions::kDefaultInlineMaxCodeUnits;
}
// Checks are all explicit until we know the architecture.
- bool implicit_null_checks = false;
- bool implicit_so_checks = false;
- bool implicit_suspend_checks = false;
// Set the compilation target's implicit checks options.
switch (instruction_set_) {
case kArm:
case kX86_64:
case kMips:
case kMips64:
- implicit_null_checks = true;
- implicit_so_checks = true;
+ parser_options->implicit_null_checks = true;
+ parser_options->implicit_so_checks = true;
break;
default:
break;
}
- compiler_options_.reset(new CompilerOptions(compiler_filter,
- huge_method_threshold,
- large_method_threshold,
- small_method_threshold,
- tiny_method_threshold,
- num_dex_methods_threshold,
- inline_depth_limit,
- inline_max_code_units,
- include_patch_information,
- top_k_profile_threshold,
- debuggable,
- generate_debug_info,
- implicit_null_checks,
- implicit_so_checks,
- implicit_suspend_checks,
- compile_pic,
+ 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(pass_manager_options),
+ new PassManagerOptions(
+ parser_options->pass_manager_options),
init_failure_output_.get(),
- abort_on_hard_verifier_error));
+ parser_options->abort_on_hard_verifier_error));
// Done with usage checks, enable watchdog if requested
- if (watch_dog_enabled) {
+ if (parser_options->watch_dog_enabled) {
watchdog_.reset(new WatchDog(true));
}
// Fill some values into the key-value store for the oat header.
key_value_store_.reset(new SafeMap<std::string, std::string>());
+ }
- // Insert some compiler things.
- {
- std::ostringstream oss;
- for (int i = 0; i < argc; ++i) {
- if (i > 0) {
- oss << ' ';
+ void InsertCompileOptions(int argc, char** argv, ParserOptions* parser_options) {
+ std::ostringstream oss;
+ for (int i = 0; i < argc; ++i) {
+ if (i > 0) {
+ oss << ' ';
+ }
+ oss << argv[i];
+ }
+ key_value_store_->Put(OatHeader::kDex2OatCmdLineKey, oss.str());
+ oss.str(""); // Reset.
+ oss << kRuntimeISA;
+ key_value_store_->Put(OatHeader::kDex2OatHostKey, oss.str());
+ key_value_store_->Put(
+ OatHeader::kPicKey,
+ parser_options->compile_pic ? OatHeader::kTrueValue : OatHeader::kFalseValue);
+ key_value_store_->Put(
+ OatHeader::kDebuggableKey,
+ parser_options->debuggable ? OatHeader::kTrueValue : OatHeader::kFalseValue);
+ }
+
+ // Parse the arguments from the command line. In case of an unrecognized option or impossible
+ // values/combinations, a usage error will be displayed and exit() is called. Thus, if the method
+ // returns, arguments have been successfully parsed.
+ void ParseArgs(int argc, char** argv) {
+ original_argc = argc;
+ original_argv = argv;
+
+ InitLogging(argv);
+
+ // Skip over argv[0].
+ argv++;
+ argc--;
+
+ if (argc == 0) {
+ Usage("No arguments specified");
+ }
+
+ std::unique_ptr<ParserOptions> parser_options(new ParserOptions());
+
+ for (int i = 0; i < argc; i++) {
+ const StringPiece option(argv[i]);
+ const bool log_options = false;
+ if (log_options) {
+ LOG(INFO) << "dex2oat: option[" << i << "]=" << argv[i];
+ }
+ if (option.starts_with("--dex-file=")) {
+ dex_filenames_.push_back(option.substr(strlen("--dex-file=")).data());
+ } else if (option.starts_with("--dex-location=")) {
+ dex_locations_.push_back(option.substr(strlen("--dex-location=")).data());
+ } else if (option.starts_with("--zip-fd=")) {
+ ParseZipFd(option);
+ } else if (option.starts_with("--zip-location=")) {
+ zip_location_ = option.substr(strlen("--zip-location=")).data();
+ } else if (option.starts_with("--oat-file=")) {
+ oat_filename_ = option.substr(strlen("--oat-file=")).data();
+ } else if (option.starts_with("--oat-symbols=")) {
+ parser_options->oat_symbols = option.substr(strlen("--oat-symbols=")).data();
+ } else if (option.starts_with("--oat-fd=")) {
+ ParseOatFd(option);
+ } else if (option == "--watch-dog") {
+ parser_options->watch_dog_enabled = true;
+ } else if (option == "--no-watch-dog") {
+ parser_options->watch_dog_enabled = false;
+ } else if (option.starts_with("-j")) {
+ ParseJ(option);
+ } else if (option.starts_with("--oat-location=")) {
+ oat_location_ = option.substr(strlen("--oat-location=")).data();
+ } else if (option.starts_with("--image=")) {
+ image_filename_ = option.substr(strlen("--image=")).data();
+ } else if (option.starts_with("--image-classes=")) {
+ image_classes_filename_ = option.substr(strlen("--image-classes=")).data();
+ } else if (option.starts_with("--image-classes-zip=")) {
+ image_classes_zip_filename_ = option.substr(strlen("--image-classes-zip=")).data();
+ } else if (option.starts_with("--compiled-classes=")) {
+ compiled_classes_filename_ = option.substr(strlen("--compiled-classes=")).data();
+ } else if (option.starts_with("--compiled-classes-zip=")) {
+ compiled_classes_zip_filename_ = option.substr(strlen("--compiled-classes-zip=")).data();
+ } else if (option.starts_with("--compiled-methods=")) {
+ compiled_methods_filename_ = option.substr(strlen("--compiled-methods=")).data();
+ } else if (option.starts_with("--compiled-methods-zip=")) {
+ compiled_methods_zip_filename_ = option.substr(strlen("--compiled-methods-zip=")).data();
+ } else if (option.starts_with("--base=")) {
+ ParseBase(option);
+ } else if (option.starts_with("--boot-image=")) {
+ parser_options->boot_image_filename = option.substr(strlen("--boot-image=")).data();
+ } else if (option.starts_with("--android-root=")) {
+ android_root_ = option.substr(strlen("--android-root=")).data();
+ } else if (option.starts_with("--instruction-set=")) {
+ ParseInstructionSet(option);
+ } else if (option.starts_with("--instruction-set-variant=")) {
+ ParseInstructionSetVariant(option, parser_options.get());
+ } else if (option.starts_with("--instruction-set-features=")) {
+ 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 == "--host") {
+ is_host_ = true;
+ } else if (option == "--runtime-arg") {
+ if (++i >= argc) {
+ Usage("Missing required argument for --runtime-arg");
+ }
+ if (log_options) {
+ LOG(INFO) << "dex2oat: option[" << i << "]=" << argv[i];
}
- oss << argv[i];
+ runtime_args_.push_back(argv[i]);
+ } else if (option == "--dump-timing") {
+ dump_timing_ = true;
+ } else if (option == "--dump-passes") {
+ dump_passes_ = true;
+ } else if (option.starts_with("--dump-cfg=")) {
+ dump_cfg_file_name_ = option.substr(strlen("--dump-cfg=")).data();
+ } 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("--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 {
+ Usage("Unknown argument %s", option.data());
}
- key_value_store_->Put(OatHeader::kDex2OatCmdLineKey, oss.str());
- oss.str(""); // Reset.
- oss << kRuntimeISA;
- key_value_store_->Put(OatHeader::kDex2OatHostKey, oss.str());
- key_value_store_->Put(OatHeader::kPicKey,
- compile_pic ? OatHeader::kTrueValue : OatHeader::kFalseValue);
- key_value_store_->Put(OatHeader::kDebuggableKey,
- debuggable ? OatHeader::kTrueValue : OatHeader::kFalseValue);
}
+
+ ProcessOptions(parser_options.get());
+
+ // Insert some compiler things.
+ InsertCompileOptions(argc, argv, parser_options.get());
}
// Check whether the oat output file is writable, and open it for later. Also open a swap file,