diff options
Diffstat (limited to 'compiler/driver/compiler_driver.cc')
-rw-r--r-- | compiler/driver/compiler_driver.cc | 59 |
1 files changed, 54 insertions, 5 deletions
diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc index 1b87725230..7d045b1d73 100644 --- a/compiler/driver/compiler_driver.cc +++ b/compiler/driver/compiler_driver.cc @@ -39,6 +39,7 @@ #include "compiled_class.h" #include "compiled_method.h" #include "compiler.h" +#include "compiler_callbacks.h" #include "compiler_driver-inl.h" #include "dex_compilation_unit.h" #include "dex_file-inl.h" @@ -393,6 +394,7 @@ static void SetupIntrinsic(Thread* self, void CompilerDriver::CompileAll(jobject class_loader, const std::vector<const DexFile*>& dex_files, + verifier::VerifierDeps* verifier_deps, TimingLogger* timings) { DCHECK(!Runtime::Current()->IsStarted()); @@ -404,7 +406,7 @@ void CompilerDriver::CompileAll(jobject class_loader, // 2) Resolve all classes // 3) Attempt to verify all classes // 4) Attempt to initialize image classes, and trivially initialized classes - PreCompile(class_loader, dex_files, timings); + PreCompile(class_loader, dex_files, verifier_deps, timings); if (GetCompilerOptions().IsBootImage()) { // We don't need to setup the intrinsics for non boot image compilation, as // those compilations will pick up a boot image that have the ArtMethod already @@ -676,7 +678,7 @@ void CompilerDriver::CompileOne(Thread* self, ArtMethod* method, TimingLogger* t InitializeThreadPools(); - PreCompile(jclass_loader, dex_files, timings); + PreCompile(jclass_loader, dex_files, /* verifier_deps */ nullptr, timings); // Can we run DEX-to-DEX compiler on this class ? optimizer::DexToDexCompilationLevel dex_to_dex_compilation_level = @@ -873,6 +875,7 @@ inline void CompilerDriver::CheckThreadPools() { void CompilerDriver::PreCompile(jobject class_loader, const std::vector<const DexFile*>& dex_files, + verifier::VerifierDeps* verifier_deps, TimingLogger* timings) { CheckThreadPools(); @@ -906,7 +909,7 @@ void CompilerDriver::PreCompile(jobject class_loader, VLOG(compiler) << "Resolve const-strings: " << GetMemoryUsageString(false); } - Verify(class_loader, dex_files, timings); + Verify(class_loader, dex_files, verifier_deps, timings); VLOG(compiler) << "Verify: " << GetMemoryUsageString(false); if (had_hard_verifier_failure_ && GetCompilerOptions().AbortOnHardVerifierFailure()) { @@ -1932,15 +1935,61 @@ void CompilerDriver::SetVerified(jobject class_loader, } } -void CompilerDriver::Verify(jobject class_loader, +void CompilerDriver::Verify(jobject jclass_loader, const std::vector<const DexFile*>& dex_files, + verifier::VerifierDeps* verifier_deps, TimingLogger* timings) { + if (verifier_deps != nullptr) { + TimingLogger::ScopedTiming t("Fast Verify", timings); + ScopedObjectAccess soa(Thread::Current()); + StackHandleScope<2> hs(soa.Self()); + Handle<mirror::ClassLoader> class_loader( + hs.NewHandle(soa.Decode<mirror::ClassLoader>(jclass_loader))); + MutableHandle<mirror::Class> cls(hs.NewHandle<mirror::Class>(nullptr)); + ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); + if (verifier_deps->ValidateDependencies(class_loader, soa.Self())) { + // We successfully validated the dependencies, now update class status + // of verified classes. Note that the dependencies also record which classes + // could not be fully verified; we could try again, but that would hurt verification + // time. So instead we assume these classes still need to be verified at + // runtime. + for (const DexFile* dex_file : dex_files) { + // Fetch the list of unverified classes and turn it into a set for faster + // lookups. + const std::vector<uint16_t>& unverified_classes = + verifier_deps->GetUnverifiedClasses(*dex_file); + std::set<uint16_t> 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()); + } + } + } + return; + } + } + + // If there is no passed `verifier_deps` (because of non-existing vdex), or + // the passed `verifier_deps` is not valid anymore, create a new one for + // non boot image compilation. The verifier will need it to record the new dependencies. + // Then dex2oat can update the vdex file with these new dependencies. + if (!GetCompilerOptions().IsBootImage()) { + Runtime::Current()->GetCompilerCallbacks()->SetVerifierDeps( + new verifier::VerifierDeps(dex_files)); + } // Note: verification should not be pulling in classes anymore when compiling the boot image, // as all should have been resolved before. As such, doing this in parallel should still // be deterministic. for (const DexFile* dex_file : dex_files) { CHECK(dex_file != nullptr); - VerifyDexFile(class_loader, + VerifyDexFile(jclass_loader, *dex_file, dex_files, parallel_thread_pool_.get(), |