diff options
author | 2016-12-15 13:20:02 +0000 | |
---|---|---|
committer | 2016-12-16 13:35:51 +0000 | |
commit | ade72d6e03e2ca49a8d2691f35fe6e37d88a196d (patch) | |
tree | 8f36d796776c4d18a17215de02d5fdd347d34ae6 | |
parent | 7a8e16c827efc866d01b5cbca835b18fe29a83ab (diff) |
Do not resolve types with vdex.
We don't need to, and it's time expensive.
test: test-art-host, 2x faster vdex compilation time.
bug: 30937355
Change-Id: Ic04ebfee9172ed676fbb38e6901615ed3473352a
-rw-r--r-- | compiler/compiled_class.h | 5 | ||||
-rw-r--r-- | compiler/driver/compiler_driver.cc | 85 | ||||
-rw-r--r-- | compiler/driver/compiler_driver.h | 5 |
3 files changed, 56 insertions, 39 deletions
diff --git a/compiler/compiled_class.h b/compiler/compiled_class.h index b88d613ad5..06ce946942 100644 --- a/compiler/compiled_class.h +++ b/compiler/compiled_class.h @@ -28,8 +28,11 @@ class CompiledClass { mirror::Class::Status GetStatus() const { return status_; } + void SetStatus(mirror::Class::Status status) { + status_ = status; + } private: - const mirror::Class::Status status_; + mirror::Class::Status status_; }; } // namespace art diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc index 1b1de78d90..b6b2575c3a 100644 --- a/compiler/driver/compiler_driver.cc +++ b/compiler/driver/compiler_driver.cc @@ -423,7 +423,7 @@ INTRINSICS_LIST(SETUP_INTRINSICS) // Compile: // 1) Compile all classes and methods enabled for compilation. May fall back to dex-to-dex // compilation. - if (!GetCompilerOptions().VerifyAtRuntime()) { + if (!GetCompilerOptions().VerifyAtRuntime() && !GetCompilerOptions().VerifyOnlyProfile()) { Compile(class_loader, dex_files, timings); } if (dump_stats_) { @@ -492,6 +492,7 @@ void CompilerDriver::CompileAll(jobject class_loader, // TODO: we unquicken unconditionnally, as we don't know // if the boot image has changed. How exactly we'll know is under // experimentation. + TimingLogger::ScopedTiming t("Unquicken", timings); Unquicken(dex_files, vdex_file->GetQuickeningInfo()); Runtime::Current()->GetCompilerCallbacks()->SetVerifierDeps( new verifier::VerifierDeps(dex_files, vdex_file->GetVerifierDepsData())); @@ -983,8 +984,10 @@ void CompilerDriver::PreCompile(jobject class_loader, << "situations. Please check the log."; } - InitializeClasses(class_loader, dex_files, timings); - VLOG(compiler) << "InitializeClasses: " << GetMemoryUsageString(false); + if (!verify_only_profile) { + InitializeClasses(class_loader, dex_files, timings); + VLOG(compiler) << "InitializeClasses: " << GetMemoryUsageString(false); + } UpdateImageClasses(timings); VLOG(compiler) << "UpdateImageClasses: " << GetMemoryUsageString(false); @@ -2060,21 +2063,29 @@ void CompilerDriver::Verify(jobject jclass_loader, std::set<dex::TypeIndex> set(unverified_classes.begin(), unverified_classes.end()); for (uint32_t i = 0; i < dex_file->NumClassDefs(); ++i) { const DexFile::ClassDef& class_def = dex_file->GetClassDef(i); - const char* descriptor = dex_file->GetClassDescriptor(class_def); - cls.Assign(class_linker->FindClass(soa.Self(), descriptor, class_loader)); - if (cls.Get() == nullptr) { - CHECK(soa.Self()->IsExceptionPending()); - soa.Self()->ClearException(); - } else if (set.find(class_def.class_idx_) == set.end()) { - ObjectLock<mirror::Class> lock(soa.Self(), cls); - mirror::Class::SetStatus(cls, mirror::Class::kStatusVerified, soa.Self()); - // Create `VerifiedMethod`s for each methods, the compiler expects one for - // quickening or compiling. - // Note that this means: - // - We're only going to compile methods that did verify. - // - Quickening will not do checkcast ellision. - // TODO(ngeoffray): Reconsider this once we refactor compiler filters. - PopulateVerifiedMethods(*dex_file, i, verification_results_); + if (set.find(class_def.class_idx_) == set.end()) { + if (GetCompilerOptions().VerifyOnlyProfile()) { + // Just update the compiled_classes_ map. The compiler doesn't need to resolve + // the type. + compiled_classes_.Overwrite( + ClassReference(dex_file, i), new CompiledClass(mirror::Class::kStatusVerified)); + } else { + // Resolve the type, so later compilation stages know they don't need to verify + // the class. + const char* descriptor = dex_file->GetClassDescriptor(class_def); + cls.Assign(class_linker->FindClass(soa.Self(), descriptor, class_loader)); + if (cls.Get() != nullptr) { + ObjectLock<mirror::Class> lock(soa.Self(), cls); + mirror::Class::SetStatus(cls, mirror::Class::kStatusVerified, soa.Self()); + } + // Create `VerifiedMethod`s for each methods, the compiler expects one for + // quickening or compiling. + // Note that this means: + // - We're only going to compile methods that did verify. + // - Quickening will not do checkcast ellision. + // TODO(ngeoffray): Reconsider this once we refactor compiler filters. + PopulateVerifiedMethods(*dex_file, i, verification_results_); + } } } } @@ -2675,29 +2686,29 @@ CompiledClass* CompilerDriver::GetCompiledClass(ClassReference ref) const { } void CompilerDriver::RecordClassStatus(ClassReference ref, mirror::Class::Status status) { + switch (status) { + case mirror::Class::kStatusNotReady: + case mirror::Class::kStatusError: + 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 " + << PrettyDescriptor(ref.first->GetClassDescriptor(ref.first->GetClassDef(ref.second))) + << " of " << status; + } + MutexLock mu(Thread::Current(), compiled_classes_lock_); auto it = compiled_classes_.find(ref); - if (it == compiled_classes_.end() || it->second->GetStatus() != status) { - // An entry doesn't exist or the status is lower than the new status. - if (it != compiled_classes_.end()) { - CHECK_GT(status, it->second->GetStatus()); - delete it->second; - } - switch (status) { - case mirror::Class::kStatusNotReady: - case mirror::Class::kStatusError: - 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 " - << PrettyDescriptor(ref.first->GetClassDescriptor(ref.first->GetClassDef(ref.second))) - << " of " << status; - } + if (it == compiled_classes_.end()) { CompiledClass* compiled_class = new CompiledClass(status); compiled_classes_.Overwrite(ref, compiled_class); + } else if (status > it->second->GetStatus()) { + // Update the status if we now have a greater one. This happens with vdex, + // which records a class is verified, but does not resolve it. + it->second->SetStatus(status); } } diff --git a/compiler/driver/compiler_driver.h b/compiler/driver/compiler_driver.h index cc50197140..eb69931f6d 100644 --- a/compiler/driver/compiler_driver.h +++ b/compiler/driver/compiler_driver.h @@ -440,9 +440,12 @@ class CompilerDriver { TimingLogger* timings) REQUIRES(!Locks::mutator_lock_); + // NO_THREAD_SAFETY_ANALYSIS as the method accesses a guarded value in a + // single-threaded way. void Verify(jobject class_loader, const std::vector<const DexFile*>& dex_files, - TimingLogger* timings); + TimingLogger* timings) + NO_THREAD_SAFETY_ANALYSIS; void VerifyDexFile(jobject class_loader, const DexFile& dex_file, |