From 4a200f56b7075309316b04d550c9cc50f8314edd Mon Sep 17 00:00:00 2001 From: Jeff Hao Date: Tue, 1 Apr 2014 14:58:49 -0700 Subject: [PATCH] Add support for -Xverify:none mode. This mode skips all verification and compilation. Public bug: https://code.google.com/p/android/issues/detail?id=67664 Change-Id: Idd00ab8e9e46d129c02988b063c41a507e07bf5b --- Android.mk | 12 ++++++++++++ compiler/dex/frontend.cc | 10 +++------- compiler/dex/mir_analysis.cc | 2 +- compiler/driver/compiler_driver.cc | 7 ++++++- compiler/driver/compiler_options.h | 12 +++++++++++- dex2oat/dex2oat.cc | 21 ++++++++++++--------- runtime/class_linker.cc | 10 ++++++++++ runtime/parsed_options.cc | 13 ++++++++++++- runtime/parsed_options.h | 1 + runtime/runtime.cc | 4 +++- runtime/runtime.h | 7 +++++++ 11 files changed, 78 insertions(+), 21 deletions(-) diff --git a/Android.mk b/Android.mk index 5325abd82..6139cb9ae 100644 --- a/Android.mk +++ b/Android.mk @@ -435,6 +435,18 @@ use-art-interpret-only: adb shell setprop persist.sys.dalvik.vm.lib.1 libart.so adb shell start +.PHONY: use-art-verify-none +use-art-verify-none: + adb root && sleep 3 + adb shell stop + adb shell rm $(ART_DALVIK_CACHE_DIR)/*.dex + adb shell rm $(ART_DALVIK_CACHE_DIR)/*.oat + adb shell rm $(ART_DALVIK_CACHE_DIR)/*.art + adb shell setprop dalvik.vm.dex2oat-flags "--compiler-filter=verify-none" + adb shell setprop dalvik.vm.image-dex2oat-flags "--compiler-filter=verify-none" + adb shell setprop persist.sys.dalvik.vm.lib.1 libart.so + adb shell start + ######################################################################## endif # !art_dont_bother diff --git a/compiler/dex/frontend.cc b/compiler/dex/frontend.cc index 3f122de62..cc616f6ca 100644 --- a/compiler/dex/frontend.cc +++ b/compiler/dex/frontend.cc @@ -145,9 +145,7 @@ static CompiledMethod* CompileMethod(CompilerDriver& driver, return NULL; } - const CompilerOptions& compiler_options = driver.GetCompilerOptions(); - CompilerOptions::CompilerFilter compiler_filter = compiler_options.GetCompilerFilter(); - if (compiler_filter == CompilerOptions::kInterpretOnly) { + if (!driver.GetCompilerOptions().IsCompilationEnabled()) { return nullptr; } @@ -230,10 +228,8 @@ static CompiledMethod* CompileMethod(CompilerDriver& driver, class_loader, dex_file); cu.NewTimingSplit("MIROpt:CheckFilters"); - if (compiler_filter != CompilerOptions::kInterpretOnly) { - if (cu.mir_graph->SkipCompilation()) { - return NULL; - } + if (cu.mir_graph->SkipCompilation()) { + return NULL; } /* Create the pass driver and launch it */ diff --git a/compiler/dex/mir_analysis.cc b/compiler/dex/mir_analysis.cc index b96c40de7..200795e53 100644 --- a/compiler/dex/mir_analysis.cc +++ b/compiler/dex/mir_analysis.cc @@ -1013,7 +1013,7 @@ bool MIRGraph::SkipCompilation() { return true; } - if (compiler_filter == CompilerOptions::kInterpretOnly || compiler_filter == CompilerOptions::kProfiled) { + if (!compiler_options.IsCompilationEnabled() || compiler_filter == CompilerOptions::kProfiled) { return true; } diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc index c10dd8422..a120d054c 100644 --- a/compiler/driver/compiler_driver.cc +++ b/compiler/driver/compiler_driver.cc @@ -598,6 +598,11 @@ void CompilerDriver::PreCompile(jobject class_loader, const std::vectorIsVerificationEnabled()) { + VLOG(compiler) << "Verify none mode specified, skipping pre-compilation"; + return; + } + Resolve(class_loader, dex_files, thread_pool, timings); Verify(class_loader, dex_files, thread_pool, timings); @@ -1872,7 +1877,7 @@ void CompilerDriver::CompileMethod(const DexFile::CodeItem* code_item, uint32_t if ((access_flags & kAccNative) != 0) { // Are we interpreting only and have support for generic JNI down calls? - if ((compiler_options_->GetCompilerFilter() == CompilerOptions::kInterpretOnly) && + if (!compiler_options_->IsCompilationEnabled() && (instruction_set_ == kX86_64 || instruction_set_ == kArm64)) { // Leaving this empty will trigger the generic JNI version } else { diff --git a/compiler/driver/compiler_options.h b/compiler/driver/compiler_options.h index 0cca1e970..20c6bc8e4 100644 --- a/compiler/driver/compiler_options.h +++ b/compiler/driver/compiler_options.h @@ -22,7 +22,8 @@ namespace art { class CompilerOptions { public: enum CompilerFilter { - kInterpretOnly, // Compile nothing. + kVerifyNone, // Skip verification and compile nothing except JNI stubs. + kInterpretOnly, // Compile nothing except JNI stubs. kProfiled, // Compile based on profile. kSpace, // Maximize space savings. kBalanced, // Try to get the best performance return on compilation investment. @@ -86,6 +87,15 @@ class CompilerOptions { compiler_filter_ = compiler_filter; } + bool IsCompilationEnabled() const { + return ((compiler_filter_ != CompilerOptions::kVerifyNone) && + (compiler_filter_ != CompilerOptions::kInterpretOnly)); + } + + bool IsVerificationEnabled() const { + return (compiler_filter_ != CompilerOptions::kVerifyNone); + } + size_t GetHugeMethodThreshold() const { return huge_method_threshold_; } diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc index 552ec89da..f665f5c76 100644 --- a/dex2oat/dex2oat.cc +++ b/dex2oat/dex2oat.cc @@ -153,8 +153,8 @@ static void Usage(const char* fmt, ...) { UsageError(" Example: --compiler-backend=Portable"); UsageError(" Default: Quick"); UsageError(""); - UsageError(" --compiler-filter=(interpret-only|space|balanced|speed|everything): select"); - UsageError(" compiler filter."); + UsageError(" --compiler-filter=(verify-none|interpret-only|space|balanced|speed|everything):"); + UsageError(" select compiler filter."); UsageError(" Example: --compiler-filter=everything"); #if ART_SMALL_MODE UsageError(" Default: interpret-only"); @@ -189,7 +189,8 @@ static void Usage(const char* fmt, ...) { UsageError(""); UsageError(" --num-dex-methods=: threshold size for a small dex file for"); UsageError(" compiler filter tuning. If the input has fewer than this many methods"); - UsageError(" and the filter is not interpret-only, overrides the filter to use speed"); + UsageError(" and the filter is not interpret-only or verify-none, overrides the"); + UsageError(" filter to use speed"); UsageError(" Example: --num-dex-method=%d", CompilerOptions::kDefaultNumDexMethodsThreshold); UsageError(" Default: %d", CompilerOptions::kDefaultNumDexMethodsThreshold); UsageError(""); @@ -201,8 +202,8 @@ static void Usage(const char* fmt, ...) { UsageError(" such as initial heap size, maximum heap size, and verbose output."); UsageError(" Use a separate --runtime-arg switch for each argument."); UsageError(" Example: --runtime-arg -Xms256m"); - UsageError(""); - UsageError(" --profile-file=: specify profiler output file to use for compilation."); + UsageError(""); + UsageError(" --profile-file=: specify profiler output file to use for compilation."); UsageError(""); UsageError(" --print-pass-names: print a list of pass names"); UsageError(""); @@ -1037,7 +1038,9 @@ static int dex2oat(int argc, char** argv) { } CHECK(compiler_filter_string != nullptr); CompilerOptions::CompilerFilter compiler_filter = CompilerOptions::kDefaultCompilerFilter; - if (strcmp(compiler_filter_string, "interpret-only") == 0) { + 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, "space") == 0) { compiler_filter = CompilerOptions::kSpace; @@ -1208,10 +1211,10 @@ static int dex2oat(int argc, char** argv) { } /* - * If we're not in interpret-only mode, go ahead and compile small applications. Don't - * bother to check if we're doing the image. + * If we're not in interpret-only or verify-none mode, go ahead and compile small applications. + * Don't bother to check if we're doing the image. */ - if (!image && (compiler_options.GetCompilerFilter() != CompilerOptions::kInterpretOnly)) { + if (!image && compiler_options.IsCompilationEnabled()) { size_t num_methods = 0; for (size_t i = 0; i != dex_files.size(); ++i) { const DexFile* dex_file = dex_files[i]; diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc index 19cc23c5c..6c5406ec1 100644 --- a/runtime/class_linker.cc +++ b/runtime/class_linker.cc @@ -569,6 +569,10 @@ bool ClassLinker::GenerateOatFile(const char* dex_filename, Runtime::Current()->AddCurrentRuntimeFeaturesAsDex2OatArguments(&argv); + if (!Runtime::Current()->IsVerificationEnabled()) { + argv.push_back("--compiler-filter=verify-none"); + } + if (!kIsTargetBuild) { argv.push_back("--host"); } @@ -2533,6 +2537,12 @@ void ClassLinker::VerifyClass(const SirtRef& klass) { klass->SetStatus(mirror::Class::kStatusVerifyingAtRuntime, self); } + // Skip verification if disabled. + if (!Runtime::Current()->IsVerificationEnabled()) { + klass->SetStatus(mirror::Class::kStatusVerified, self); + return; + } + // Verify super class. SirtRef super(self, klass->GetSuperClass()); if (super.get() != NULL) { diff --git a/runtime/parsed_options.cc b/runtime/parsed_options.cc index e2086f106..08a674fdd 100644 --- a/runtime/parsed_options.cc +++ b/runtime/parsed_options.cc @@ -196,6 +196,8 @@ bool ParsedOptions::Parse(const Runtime::Options& options, bool ignore_unrecogni profile_backoff_coefficient_ = 2.0; profile_clock_source_ = kDefaultProfilerClockSource; + verify_ = true; + // Default to explicit checks. Switch off with -implicit-checks:. // or setprop dalvik.vm.implicit_checks check1,check2,... #ifdef HAVE_ANDROID_OS @@ -569,6 +571,16 @@ bool ParsedOptions::Parse(const Runtime::Options& options, bool ignore_unrecogni return false; } image_compiler_options_.push_back(options[i].first); + } else if (StartsWith(option, "-Xverify:")) { + std::string verify_mode = option.substr(strlen("-Xverify:")); + if (verify_mode == "none") { + verify_ = false; + } else if (verify_mode == "remote" || verify_mode == "all") { + verify_ = true; + } else { + Usage("Unknown -Xverify option %s", verify_mode.c_str()); + return false; + } } else if (StartsWith(option, "-ea:") || StartsWith(option, "-da:") || StartsWith(option, "-enableassertions:") || @@ -578,7 +590,6 @@ bool ParsedOptions::Parse(const Runtime::Options& options, bool ignore_unrecogni (option == "-dsa") || (option == "-enablesystemassertions") || (option == "-disablesystemassertions") || - StartsWith(option, "-Xverify:") || (option == "-Xrs") || StartsWith(option, "-Xint:") || StartsWith(option, "-Xdexopt:") || diff --git a/runtime/parsed_options.h b/runtime/parsed_options.h index d6516a80a..416bc78e6 100644 --- a/runtime/parsed_options.h +++ b/runtime/parsed_options.h @@ -80,6 +80,7 @@ class ParsedOptions { uint32_t profile_interval_us_; double profile_backoff_coefficient_; ProfilerClockSource profile_clock_source_; + bool verify_; static constexpr uint32_t kExplicitNullCheck = 1; static constexpr uint32_t kExplicitSuspendCheck = 2; diff --git a/runtime/runtime.cc b/runtime/runtime.cc index b0a658429..1b3c99615 100644 --- a/runtime/runtime.cc +++ b/runtime/runtime.cc @@ -132,7 +132,8 @@ Runtime::Runtime() preinitialization_transaction_(nullptr), null_pointer_handler_(nullptr), suspend_handler_(nullptr), - stack_overflow_handler_(nullptr) { + stack_overflow_handler_(nullptr), + verify_(false) { for (int i = 0; i < Runtime::kLastCalleeSaveType; i++) { callee_save_methods_[i] = nullptr; } @@ -521,6 +522,7 @@ bool Runtime::Init(const Options& raw_options, bool ignore_unrecognized) { thread_list_ = new ThreadList; intern_table_ = new InternTable; + verify_ = options->verify_; if (options->interpreter_only_) { GetInstrumentation()->ForceInterpretOnly(); diff --git a/runtime/runtime.h b/runtime/runtime.h index 176b71c4e..7b3e04c93 100644 --- a/runtime/runtime.h +++ b/runtime/runtime.h @@ -421,6 +421,10 @@ class Runtime { return stack_overflow_handler_ == nullptr; } + bool IsVerificationEnabled() const { + return verify_; + } + bool RunningOnValgrind() const { return running_on_valgrind_; } @@ -563,6 +567,9 @@ class Runtime { SuspensionHandler* suspend_handler_; StackOverflowHandler* stack_overflow_handler_; + // If false, verification is disabled. True by default. + bool verify_; + DISALLOW_COPY_AND_ASSIGN(Runtime); }; -- 2.11.0