summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Nicolas Geoffray <ngeoffray@google.com> 2015-10-29 18:55:58 +0000
committer Nicolas Geoffray <ngeoffray@google.com> 2015-10-30 11:17:00 +0000
commitabbb0f76b07417f13f712f54d5afddb72e3b9931 (patch)
treebb26eeb28b58aed669ad16af30aa35771eb02be4
parent594c0612519e96bcc1bd42ff4dcbfa2c53b09c5a (diff)
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
-rw-r--r--compiler/dex/quick/quick_cfi_test.cc1
-rw-r--r--compiler/dex/quick/x86/quick_assemble_x86_test.cc1
-rw-r--r--compiler/driver/compiler_options.cc157
-rw-r--r--compiler/driver/compiler_options.h66
-rw-r--r--compiler/jit/jit_compiler.cc17
-rw-r--r--dex2oat/dex2oat.cc296
-rw-r--r--runtime/utils.cc39
-rw-r--r--runtime/utils.h31
8 files changed, 306 insertions, 302 deletions
diff --git a/compiler/dex/quick/quick_cfi_test.cc b/compiler/dex/quick/quick_cfi_test.cc
index 18c2e55700..24daf2f15f 100644
--- a/compiler/dex/quick/quick_cfi_test.cc
+++ b/compiler/dex/quick/quick_cfi_test.cc
@@ -67,7 +67,6 @@ class QuickCFITest : public CFITest {
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 d9571c5f26..e977ebf722 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 @@ class QuickAssembleX86TestBase : public testing::Test {
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 3f5a1eabb6..a24c8a3347 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 @@ CompilerOptions::CompilerOptions()
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 @@ CompilerOptions::CompilerOptions()
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 @@ CompilerOptions::CompilerOptions(CompilerFilter compiler_filter,
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 @@ CompilerOptions::CompilerOptions(CompilerFilter compiler_filter,
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 18f215d165..e6acab42f2 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 @@ class CompilerOptions FINAL {
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 @@ class CompilerOptions FINAL {
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 @@ class CompilerOptions FINAL {
}
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 b563c80f7d..c1b87c9cd0 100644
--- a/compiler/jit/jit_compiler.cc
+++ b/compiler/jit/jit_compiler.cc
@@ -63,9 +63,18 @@ extern "C" bool jit_compile_method(void* handle, ArtMethod* method, Thread* self
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 @@ JitCompiler::JitCompiler() : total_time_(0) {
/* 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 384b8794c1..85a1bdefa6 100644
--- a/dex2oat/dex2oat.cc
+++ b/dex2oat/dex2oat.cc
@@ -445,38 +445,6 @@ class WatchDog {
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 @@ class Dex2Oat FINAL {
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 @@ class Dex2Oat FINAL {
}
}
- 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 @@ class Dex2Oat FINAL {
}
}
- 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 @@ class Dex2Oat FINAL {
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 @@ class Dex2Oat FINAL {
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 @@ class Dex2Oat FINAL {
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 @@ class Dex2Oat FINAL {
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 @@ class Dex2Oat FINAL {
}
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 @@ class Dex2Oat FINAL {
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 @@ class Dex2Oat FINAL {
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 @@ class Dex2Oat FINAL {
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 @@ class Dex2Oat FINAL {
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 dee4f9c891..48dce63f00 100644
--- a/runtime/utils.cc
+++ b/runtime/utils.cc
@@ -1835,4 +1835,43 @@ void DumpMethodCFG(const DexFile* dex_file, uint32_t dex_method_idx, std::ostrea
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 bd52b686fd..5cca2964ce 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 @@ class BacktraceMap;
namespace art {
-class ArtCode;
class ArtField;
class ArtMethod;
class DexFile;
@@ -321,6 +322,34 @@ static inline const void* EntryPointToCodePointer(const void* entry_point) {
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_