ART: Implicit checks in the compiler are independent from Runtime
When cross-compiling, those flags are independent. This is an
initial CL that helps bypass fatal failures when cross-compiling,
as not all architectures support (and have turned on) implicit
checks.
The actual transport for the target architecture when it is
different from the runtime needs to be implemented in a follow-up
CL.
Bug: 15703710
Change-Id: Idc881a9a4abfd38643b862a491a5af9b8841f693
diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc
index c3f2082..d7b34dc 100644
--- a/dex2oat/dex2oat.cc
+++ b/dex2oat/dex2oat.cc
@@ -744,6 +744,19 @@
*parsed_value = value;
}
+void CheckExplicitCheckOptions(InstructionSet isa, bool* explicit_null_checks,
+ bool* explicit_so_checks, bool* explicit_suspend_checks) {
+ switch (isa) {
+ case kArm:
+ break; // All checks implemented, leave as is.
+
+ default: // No checks implemented, reset all to explicit checks.
+ *explicit_null_checks = true;
+ *explicit_so_checks = true;
+ *explicit_suspend_checks = true;
+ }
+}
+
static int dex2oat(int argc, char** argv) {
#if defined(__linux__) && defined(__arm__)
int major, minor;
@@ -825,6 +838,11 @@
bool watch_dog_enabled = !kIsTargetBuild;
bool generate_gdb_information = kIsDebugBuild;
+ bool explicit_null_checks = true;
+ bool explicit_so_checks = true;
+ bool explicit_suspend_checks = true;
+ bool has_explicit_checks_options = false;
+
for (int i = 0; i < argc; i++) {
const StringPiece option(argv[i]);
const bool log_options = false;
@@ -998,6 +1016,31 @@
} else if (option.starts_with("--dump-cfg-passes=")) {
std::string dump_passes = option.substr(strlen("--dump-cfg-passes=")).data();
PassDriverMEOpts::SetDumpPassList(dump_passes);
+ } else if (option.starts_with("--implicit-checks=")) {
+ std::string checks = option.substr(strlen("--implicit-checks=")).data();
+ std::vector<std::string> checkvec;
+ Split(checks, ',', checkvec);
+ for (auto& str : checkvec) {
+ std::string val = Trim(str);
+ if (val == "none") {
+ explicit_null_checks = true;
+ explicit_so_checks = true;
+ explicit_suspend_checks = true;
+ } else if (val == "null") {
+ explicit_null_checks = false;
+ } else if (val == "suspend") {
+ explicit_suspend_checks = false;
+ } else if (val == "stack") {
+ explicit_so_checks = false;
+ } else if (val == "all") {
+ explicit_null_checks = false;
+ explicit_so_checks = false;
+ explicit_suspend_checks = false;
+ } else {
+ Usage("--implicit-checks passed non-recognized value %s", val.c_str());
+ }
+ has_explicit_checks_options = true;
+ }
} else {
Usage("Unknown argument %s", option.data());
}
@@ -1126,6 +1169,9 @@
Usage("Unknown --compiler-filter value %s", compiler_filter_string);
}
+ CheckExplicitCheckOptions(instruction_set, &explicit_null_checks, &explicit_so_checks,
+ &explicit_suspend_checks);
+
CompilerOptions compiler_options(compiler_filter,
huge_method_threshold,
large_method_threshold,
@@ -1134,7 +1180,10 @@
num_dex_methods_threshold,
generate_gdb_information,
top_k_profile_threshold,
- include_debug_symbols
+ include_debug_symbols,
+ explicit_null_checks,
+ explicit_so_checks,
+ explicit_suspend_checks
#ifdef ART_SEA_IR_MODE
, compiler_options.sea_ir_ = true;
#endif
@@ -1205,6 +1254,18 @@
return EXIT_FAILURE;
}
std::unique_ptr<Dex2Oat> dex2oat(p_dex2oat);
+
+ // TODO: Not sure whether it's a good idea to allow anything else but the runtime option in
+ // this case at all, as we'll have to throw away produced code for a mismatch.
+ if (!has_explicit_checks_options) {
+ if (instruction_set == kRuntimeISA) {
+ Runtime* runtime = Runtime::Current();
+ compiler_options.SetExplicitNullChecks(runtime->ExplicitNullChecks());
+ compiler_options.SetExplicitStackOverflowChecks(runtime->ExplicitStackOverflowChecks());
+ compiler_options.SetExplicitSuspendChecks(runtime->ExplicitSuspendChecks());
+ }
+ }
+
// Runtime::Create acquired the mutator_lock_ that is normally given away when we Runtime::Start,
// give it away now so that we don't starve GC.
Thread* self = Thread::Current();