diff options
| -rw-r--r-- | compiler/driver/compiler_driver.cc | 85 |
1 files changed, 67 insertions, 18 deletions
diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc index b00d083c28..320304873d 100644 --- a/compiler/driver/compiler_driver.cc +++ b/compiler/driver/compiler_driver.cc @@ -940,6 +940,31 @@ inline void CompilerDriver::CheckThreadPools() { DCHECK(single_thread_pool_ != nullptr); } +static void EnsureVerifiedOrVerifyAtRuntime(jobject jclass_loader, + const std::vector<const DexFile*>& dex_files) { + 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(); + + for (const DexFile* dex_file : dex_files) { + 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) { + soa.Self()->ClearException(); + } else if (&cls->GetDexFile() == dex_file) { + DCHECK(cls->IsErroneous() || cls->IsVerified() || cls->IsCompileTimeVerified()) + << cls->PrettyClass() + << " " << cls->GetStatus(); + } + } + } +} + void CompilerDriver::PreCompile(jobject class_loader, const std::vector<const DexFile*>& dex_files, TimingLogger* timings) { @@ -984,6 +1009,9 @@ void CompilerDriver::PreCompile(jobject class_loader, } if (compiler_options_->IsAnyMethodCompilationEnabled()) { + if (kIsDebugBuild) { + EnsureVerifiedOrVerifyAtRuntime(class_loader, dex_files); + } InitializeClasses(class_loader, dex_files, timings); VLOG(compiler) << "InitializeClasses: " << GetMemoryUsageString(false); } @@ -1949,6 +1977,31 @@ static void PopulateVerifiedMethods(const DexFile& dex_file, DCHECK(!it.HasNext()); } +static void LoadAndUpdateStatus(const DexFile& dex_file, + const DexFile::ClassDef& class_def, + mirror::Class::Status status, + Handle<mirror::ClassLoader> class_loader, + Thread* self) + REQUIRES_SHARED(Locks::mutator_lock_) { + StackHandleScope<1> hs(self); + const char* descriptor = dex_file.GetClassDescriptor(class_def); + ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); + Handle<mirror::Class> cls(hs.NewHandle<mirror::Class>( + class_linker->FindClass(self, descriptor, class_loader))); + if (cls.Get() != nullptr) { + // Check that the class is resolved with the current dex file. We might get + // a boot image class, or a class in a different dex file for multidex, and + // we should not update the status in that case. + if (&cls->GetDexFile() == &dex_file) { + ObjectLock<mirror::Class> lock(self, cls); + mirror::Class::SetStatus(cls, status, self); + } + } else { + DCHECK(self->IsExceptionPending()); + self->ClearException(); + } +} + bool CompilerDriver::FastVerify(jobject jclass_loader, const std::vector<const DexFile*>& dex_files, TimingLogger* timings) { @@ -1963,12 +2016,12 @@ bool CompilerDriver::FastVerify(jobject jclass_loader, 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())) { return false; } + bool compiler_only_verifies = !GetCompilerOptions().IsAnyMethodCompilationEnabled(); + // 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 @@ -1983,28 +2036,16 @@ bool CompilerDriver::FastVerify(jobject jclass_loader, for (uint32_t i = 0; i < dex_file->NumClassDefs(); ++i) { const DexFile::ClassDef& class_def = dex_file->GetClassDef(i); if (set.find(class_def.class_idx_) == set.end()) { - if (!GetCompilerOptions().IsAnyMethodCompilationEnabled()) { + if (compiler_only_verifies) { // 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 + // Update the class status, 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) { - // Check that the class is resolved with the current dex file. We might get - // a boot image class, or a class in a different dex file for multidex, and - // we should not update the status in that case. - if (&cls->GetDexFile() == dex_file) { - ObjectLock<mirror::Class> lock(soa.Self(), cls); - mirror::Class::SetStatus(cls, mirror::Class::kStatusVerified, soa.Self()); - } - } else { - DCHECK(soa.Self()->IsExceptionPending()); - soa.Self()->ClearException(); - } + LoadAndUpdateStatus( + *dex_file, class_def, mirror::Class::kStatusVerified, class_loader, soa.Self()); // Create `VerifiedMethod`s for each methods, the compiler expects one for // quickening or compiling. // Note that this means: @@ -2013,6 +2054,14 @@ bool CompilerDriver::FastVerify(jobject jclass_loader, // TODO(ngeoffray): Reconsider this once we refactor compiler filters. PopulateVerifiedMethods(*dex_file, i, verification_results_); } + } else if (!compiler_only_verifies) { + // Make sure later compilation stages know they should not try to verify + // this class again. + LoadAndUpdateStatus(*dex_file, + class_def, + mirror::Class::kStatusRetryVerificationAtRuntime, + class_loader, + soa.Self()); } } } |