diff options
author | Mathieu Chartier <mathieuc@google.com> | 2016-03-16 19:08:31 -0700 |
---|---|---|
committer | Mathieu Chartier <mathieuc@google.com> | 2016-03-18 15:21:08 -0700 |
commit | a807780b1d8ee01dfb03923c673621b4c81ac858 (patch) | |
tree | ef7485dca9ad8375559524d74b7c4971d6f088fa | |
parent | 895375bb30716a488bf7b8234e900d1e15de1d21 (diff) | |
download | android_art-a807780b1d8ee01dfb03923c673621b4c81ac858.tar.gz android_art-a807780b1d8ee01dfb03923c673621b4c81ac858.tar.bz2 android_art-a807780b1d8ee01dfb03923c673621b4c81ac858.zip |
Add verify-profile compiler filter
Only verifies and dex2dex compiles classes in the profile. Goal
is to reduce application launch time.
~2x faster than interpret-only for Facebook.
Bug: 27688727
(cherry picked from commit a079e3aa62cceb76c1c1811e6e09bcaf75e20289)
Change-Id: Iad5aa1adee3aa6c2408820e8cbbab2d4412021b8
-rw-r--r-- | compiler/driver/compiler_driver.cc | 28 | ||||
-rw-r--r-- | compiler/driver/compiler_driver.h | 7 | ||||
-rw-r--r-- | compiler/driver/compiler_options.cc | 2 | ||||
-rw-r--r-- | compiler/driver/compiler_options.h | 12 | ||||
-rw-r--r-- | dex2oat/dex2oat.cc | 14 | ||||
-rw-r--r-- | runtime/class_linker.cc | 7 | ||||
-rw-r--r-- | runtime/jit/offline_profiling_info.cc | 12 | ||||
-rw-r--r-- | runtime/jit/offline_profiling_info.h | 3 |
8 files changed, 76 insertions, 9 deletions
diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc index cd9d80fe9b..ea16cb2662 100644 --- a/compiler/driver/compiler_driver.cc +++ b/compiler/driver/compiler_driver.cc @@ -383,6 +383,9 @@ CompilerDriver::CompilerDriver( compiler_->Init(); + if (compiler_options->VerifyOnlyProfile()) { + CHECK(profile_compilation_info_ != nullptr) << "Requires profile"; + } if (boot_image_) { CHECK(image_classes_.get() != nullptr) << "Expected image classes for boot image"; } @@ -830,10 +833,12 @@ void CompilerDriver::PreCompile(jobject class_loader, const bool verification_enabled = compiler_options_->IsVerificationEnabled(); const bool never_verify = compiler_options_->NeverVerify(); + const bool verify_only_profile = compiler_options_->VerifyOnlyProfile(); // We need to resolve for never_verify since it needs to run dex to dex to add the // RETURN_VOID_NO_BARRIER. - if (never_verify || verification_enabled) { + // Let the verifier resolve as needed for the verify_only_profile case. + if ((never_verify || verification_enabled) && !verify_only_profile) { Resolve(class_loader, dex_files, timings); VLOG(compiler) << "Resolve: " << GetMemoryUsageString(false); } @@ -918,6 +923,22 @@ bool CompilerDriver::ShouldCompileBasedOnProfile(const MethodReference& method_r return result; } +bool CompilerDriver::ShouldVerifyClassBasedOnProfile(const DexFile& dex_file, + uint16_t class_idx) const { + if (!compiler_options_->VerifyOnlyProfile()) { + // No profile, verify everything. + return true; + } + DCHECK(profile_compilation_info_ != nullptr); + bool result = profile_compilation_info_->ContainsClass(dex_file, class_idx); + if (kDebugProfileGuidedCompilation) { + LOG(INFO) << "[ProfileGuidedCompilation] " + << (result ? "Verified" : "Skipped") << " method:" + << dex_file.GetClassDescriptor(dex_file.GetClassDef(class_idx)); + } + return result; +} + class ResolveCatchBlockExceptionsClassVisitor : public ClassVisitor { public: ResolveCatchBlockExceptionsClassVisitor( @@ -2197,6 +2218,10 @@ class VerifyClassVisitor : public CompilationVisitor { ATRACE_CALL(); ScopedObjectAccess soa(Thread::Current()); const DexFile& dex_file = *manager_->GetDexFile(); + if (!manager_->GetCompiler()->ShouldVerifyClassBasedOnProfile(dex_file, class_def_index)) { + // Skip verification since the class is not in the profile. + return; + } const DexFile::ClassDef& class_def = dex_file.GetClassDef(class_def_index); const char* descriptor = dex_file.GetClassDescriptor(class_def); ClassLinker* class_linker = manager_->GetClassLinker(); @@ -2665,6 +2690,7 @@ void CompilerDriver::RecordClassStatus(ClassReference ref, mirror::Class::Status case mirror::Class::kStatusRetryVerificationAtRuntime: case mirror::Class::kStatusVerified: case mirror::Class::kStatusInitialized: + case mirror::Class::kStatusResolved: break; // Expected states. default: LOG(FATAL) << "Unexpected class status for class " diff --git a/compiler/driver/compiler_driver.h b/compiler/driver/compiler_driver.h index 4ef26ddd6c..64a06a2f83 100644 --- a/compiler/driver/compiler_driver.h +++ b/compiler/driver/compiler_driver.h @@ -91,7 +91,8 @@ class CompilerDriver { Compiler::Kind compiler_kind, InstructionSet instruction_set, const InstructionSetFeatures* instruction_set_features, - bool boot_image, std::unordered_set<std::string>* image_classes, + bool boot_image, + std::unordered_set<std::string>* image_classes, std::unordered_set<std::string>* compiled_classes, std::unordered_set<std::string>* compiled_methods, size_t thread_count, @@ -435,6 +436,10 @@ class CompilerDriver { // according to the profile file. bool ShouldCompileBasedOnProfile(const MethodReference& method_ref) const; + // Checks whether profile guided verification is enabled and if the method should be verified + // according to the profile file. + bool ShouldVerifyClassBasedOnProfile(const DexFile& dex_file, uint16_t class_idx) const; + void RecordClassStatus(ClassReference ref, mirror::Class::Status status) REQUIRES(!compiled_classes_lock_); diff --git a/compiler/driver/compiler_options.cc b/compiler/driver/compiler_options.cc index 43bdbf3d4d..b4389d3c95 100644 --- a/compiler/driver/compiler_options.cc +++ b/compiler/driver/compiler_options.cc @@ -195,6 +195,8 @@ bool CompilerOptions::ParseCompilerOption(const StringPiece& option, UsageFn Usa compiler_filter_ = CompilerOptions::kEverything; } else if (strcmp(compiler_filter_string, "time") == 0) { compiler_filter_ = CompilerOptions::kTime; + } else if (strcmp(compiler_filter_string, "verify-profile") == 0) { + compiler_filter_ = CompilerOptions::kVerifyProfile; } else { Usage("Unknown --compiler-filter value %s", compiler_filter_string); } diff --git a/compiler/driver/compiler_options.h b/compiler/driver/compiler_options.h index fbfa7c85f1..59698af459 100644 --- a/compiler/driver/compiler_options.h +++ b/compiler/driver/compiler_options.h @@ -39,6 +39,7 @@ class CompilerOptions FINAL { kSpeed, // Maximize runtime performance. kEverything, // Force compilation of everything capable of being compiled. kTime, // Compile methods, but minimize compilation time. + kVerifyProfile, // Verify only the classes in the profile. }; // Guide heuristics to determine whether to compile method if profile data not available. @@ -102,13 +103,14 @@ class CompilerOptions FINAL { bool IsCompilationEnabled() const { return compiler_filter_ != CompilerOptions::kVerifyNone && - compiler_filter_ != CompilerOptions::kInterpretOnly && - compiler_filter_ != CompilerOptions::kVerifyAtRuntime; + compiler_filter_ != CompilerOptions::kInterpretOnly && + compiler_filter_ != CompilerOptions::kVerifyAtRuntime && + compiler_filter_ != CompilerOptions::kVerifyProfile; } bool IsVerificationEnabled() const { return compiler_filter_ != CompilerOptions::kVerifyNone && - compiler_filter_ != CompilerOptions::kVerifyAtRuntime; + compiler_filter_ != CompilerOptions::kVerifyAtRuntime; } bool NeverVerify() const { @@ -119,6 +121,10 @@ class CompilerOptions FINAL { return compiler_filter_ == CompilerOptions::kVerifyAtRuntime; } + bool VerifyOnlyProfile() const { + return compiler_filter_ == CompilerOptions::kVerifyProfile; + } + size_t GetHugeMethodThreshold() const { return huge_method_threshold_; } diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc index 298101115d..c2d5e4dd06 100644 --- a/dex2oat/dex2oat.cc +++ b/dex2oat/dex2oat.cc @@ -256,6 +256,7 @@ NO_RETURN static void Usage(const char* fmt, ...) { UsageError(" --compiler-filter=" "(verify-none" "|verify-at-runtime" + "|verify-profile" "|interpret-only" "|space" "|balanced" @@ -263,6 +264,7 @@ NO_RETURN static void Usage(const char* fmt, ...) { "|everything" "|time):"); UsageError(" select compiler filter."); + UsageError(" verify-profile requires a --profile(-fd) to also be passed in."); UsageError(" Example: --compiler-filter=everything"); UsageError(" Default: speed"); UsageError(""); @@ -805,10 +807,16 @@ class Dex2Oat FINAL { } } - if (!profile_file_.empty() && (profile_file_fd_ != kInvalidFd)) { + const bool have_profile_file = !profile_file_.empty(); + const bool have_profile_fd = profile_file_fd_ != kInvalidFd; + if (have_profile_file && have_profile_fd) { Usage("Profile file should not be specified with both --profile-file-fd and --profile-file"); } + if (compiler_options_->IsVerificationEnabled() && !have_profile_file && !have_profile_fd) { + Usage("verify-profile compiler filter must be used with a profile file or fd"); + } + if (!parser_options->oat_symbols.empty()) { oat_unstripped_ = std::move(parser_options->oat_symbols); } @@ -1450,8 +1458,8 @@ class Dex2Oat FINAL { } /* - * If we're not in interpret-only or verify-none or verify-at-runtime 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 or verify-at-runtime or verify-profile mode, + * go ahead and compile small applications. Don't bother to check if we're doing the image. */ if (!IsBootImage() && compiler_options_->IsCompilationEnabled() && diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc index d8e309d57e..e2ef7ac671 100644 --- a/runtime/class_linker.cc +++ b/runtime/class_linker.cc @@ -3964,7 +3964,12 @@ bool ClassLinker::VerifyClassUsingOatFile(const DexFile& dex_file, oat_file_class_status = oat_dex_file->GetOatClass(class_def_index).GetStatus(); if (oat_file_class_status == mirror::Class::kStatusVerified || oat_file_class_status == mirror::Class::kStatusInitialized) { - return true; + return true; + } + // If we only verified a subset of the classes at compile time, we can end up with classes that + // were resolved by the verifier. + if (oat_file_class_status == mirror::Class::kStatusResolved) { + return false; } if (oat_file_class_status == mirror::Class::kStatusRetryVerificationAtRuntime) { // Compile time verification failed with a soft error. Compile time verification can fail diff --git a/runtime/jit/offline_profiling_info.cc b/runtime/jit/offline_profiling_info.cc index ecf34f57ef..f181ca3467 100644 --- a/runtime/jit/offline_profiling_info.cc +++ b/runtime/jit/offline_profiling_info.cc @@ -367,6 +367,18 @@ bool ProfileCompilationInfo::ContainsMethod(const MethodReference& method_ref) c return false; } +bool ProfileCompilationInfo::ContainsClass(const DexFile& dex_file, uint16_t class_def_idx) const { + auto info_it = info_.find(GetProfileDexFileKey(dex_file.GetLocation())); + if (info_it != info_.end()) { + if (dex_file.GetLocationChecksum() != info_it->second.checksum) { + return false; + } + const std::set<uint16_t>& classes = info_it->second.class_set; + return classes.find(class_def_idx) != classes.end(); + } + return false; +} + uint32_t ProfileCompilationInfo::GetNumberOfMethods() const { uint32_t total = 0; for (const auto& it : info_) { diff --git a/runtime/jit/offline_profiling_info.h b/runtime/jit/offline_profiling_info.h index ee7ce27e4c..df03244779 100644 --- a/runtime/jit/offline_profiling_info.h +++ b/runtime/jit/offline_profiling_info.h @@ -60,6 +60,9 @@ class ProfileCompilationInfo { // Returns true if the method reference is present in the profiling info. bool ContainsMethod(const MethodReference& method_ref) const; + // Returns true if the class is present in the profiling info. + bool ContainsClass(const DexFile& dex_file, uint16_t class_def_idx) const; + // Dumps all the loaded profile info into a string and returns it. // If dex_files is not null then the method indices will be resolved to their // names. |