diff options
23 files changed, 217 insertions, 167 deletions
diff --git a/compiler/common_compiler_test.cc b/compiler/common_compiler_test.cc index 66421e2562..be6da714eb 100644 --- a/compiler/common_compiler_test.cc +++ b/compiler/common_compiler_test.cc @@ -22,6 +22,7 @@ #include "art_field-inl.h" #include "art_method-inl.h" #include "base/callee_save_type.h" +#include "base/casts.h" #include "base/enums.h" #include "base/utils.h" #include "class_linker.h" @@ -152,6 +153,10 @@ void CommonCompilerTest::SetUp() { CreateCompilerDriver(); } + // Note: We cannot use MemMap because some tests tear down the Runtime and destroy + // the gMaps, so when destroying the MemMap, the test would crash. + inaccessible_page_ = mmap(nullptr, kPageSize, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + CHECK(inaccessible_page_ != MAP_FAILED) << strerror(errno); } void CommonCompilerTest::ApplyInstructionSet() { @@ -190,9 +195,7 @@ void CommonCompilerTest::CreateCompilerDriver() { compiler_options_->image_classes_.swap(*GetImageClasses()); compiler_options_->profile_compilation_info_ = GetProfileCompilationInfo(); compiler_driver_.reset(new CompilerDriver(compiler_options_.get(), - verification_results_.get(), compiler_kind_, - &compiler_options_->image_classes_, number_of_threads_, /* swap_fd */ -1)); } @@ -222,6 +225,10 @@ void CommonCompilerTest::TearDown() { verification_results_.reset(); compiler_options_.reset(); image_reservation_.Reset(); + if (inaccessible_page_ != nullptr) { + munmap(inaccessible_page_, kPageSize); + inaccessible_page_ = nullptr; + } CommonRuntimeTest::TearDown(); } @@ -267,8 +274,16 @@ void CommonCompilerTest::CompileMethod(ArtMethod* method) { compiler_driver_->InitializeThreadPools(); - compiler_driver_->PreCompile(class_loader, dex_files, &timings); + compiler_driver_->PreCompile(class_loader, + dex_files, + &timings, + &compiler_options_->image_classes_, + verification_results_.get()); + // Verification results in the `callback_` should not be used during compilation. + down_cast<QuickCompilerCallbacks*>(callbacks_.get())->SetVerificationResults( + reinterpret_cast<VerificationResults*>(inaccessible_page_)); + compiler_options_->verification_results_ = verification_results_.get(); compiler_driver_->CompileOne(self, class_loader, *dex_file, @@ -279,6 +294,9 @@ void CommonCompilerTest::CompileMethod(ArtMethod* method) { code_item, dex_cache, h_class_loader); + compiler_options_->verification_results_ = nullptr; + down_cast<QuickCompilerCallbacks*>(callbacks_.get())->SetVerificationResults( + verification_results_.get()); compiler_driver_->FreeThreadPools(); @@ -334,6 +352,32 @@ void CommonCompilerTest::ReserveImageSpace() { CHECK(image_reservation_.IsValid()) << error_msg; } +void CommonCompilerTest::CompileAll(jobject class_loader, + const std::vector<const DexFile*>& dex_files, + TimingLogger* timings) { + TimingLogger::ScopedTiming t(__FUNCTION__, timings); + SetDexFilesForOatFile(dex_files); + + compiler_driver_->InitializeThreadPools(); + + compiler_driver_->PreCompile(class_loader, + dex_files, + timings, + &compiler_options_->image_classes_, + verification_results_.get()); + + // Verification results in the `callback_` should not be used during compilation. + down_cast<QuickCompilerCallbacks*>(callbacks_.get())->SetVerificationResults( + reinterpret_cast<VerificationResults*>(inaccessible_page_)); + compiler_options_->verification_results_ = verification_results_.get(); + compiler_driver_->CompileAll(class_loader, dex_files, timings); + compiler_options_->verification_results_ = nullptr; + down_cast<QuickCompilerCallbacks*>(callbacks_.get())->SetVerificationResults( + verification_results_.get()); + + compiler_driver_->FreeThreadPools(); +} + void CommonCompilerTest::UnreserveImageSpace() { image_reservation_.Reset(); } diff --git a/compiler/common_compiler_test.h b/compiler/common_compiler_test.h index e6d1564621..a71908e6c8 100644 --- a/compiler/common_compiler_test.h +++ b/compiler/common_compiler_test.h @@ -20,6 +20,8 @@ #include <list> #include <vector> +#include <jni.h> + #include "arch/instruction_set.h" #include "arch/instruction_set_features.h" #include "base/hash_set.h" @@ -37,6 +39,7 @@ class CompilerOptions; class CumulativeLogger; class DexFile; class ProfileCompilationInfo; +class TimingLogger; class VerificationResults; template<class T> class Handle; @@ -88,6 +91,10 @@ class CommonCompilerTest : public CommonRuntimeTest { const char* method_name, const char* signature) REQUIRES_SHARED(Locks::mutator_lock_); + void CompileAll(jobject class_loader, + const std::vector<const DexFile*>& dex_files, + TimingLogger* timings) REQUIRES(!Locks::mutator_lock_); + void ApplyInstructionSet(); void OverrideInstructionSetFeatures(InstructionSet instruction_set, const std::string& variant); @@ -116,6 +123,7 @@ class CommonCompilerTest : public CommonRuntimeTest { private: MemMap image_reservation_; + void* inaccessible_page_; // Chunks must not move their storage after being created - use the node-based std::list. std::list<std::vector<uint8_t>> header_code_and_maps_chunks_; diff --git a/compiler/dex/dex_to_dex_compiler.cc b/compiler/dex/dex_to_dex_compiler.cc index 04ad10c41e..c124ef5dde 100644 --- a/compiler/dex/dex_to_dex_compiler.cc +++ b/compiler/dex/dex_to_dex_compiler.cc @@ -528,7 +528,7 @@ CompiledMethod* DexToDexCompiler::CompileMethod( class_def_idx, method_idx, access_flags, - driver_->GetVerifiedMethod(&dex_file, method_idx), + driver_->GetCompilerOptions().GetVerifiedMethod(&dex_file, method_idx), hs.NewHandle(class_linker->FindDexCache(soa.Self(), dex_file))); std::vector<uint8_t> quicken_data; diff --git a/compiler/dex/dex_to_dex_decompiler_test.cc b/compiler/dex/dex_to_dex_decompiler_test.cc index f61e6c4848..b055416c1e 100644 --- a/compiler/dex/dex_to_dex_decompiler_test.cc +++ b/compiler/dex/dex_to_dex_decompiler_test.cc @@ -39,16 +39,15 @@ namespace art { class DexToDexDecompilerTest : public CommonCompilerTest { public: void CompileAll(jobject class_loader) REQUIRES(!Locks::mutator_lock_) { - TimingLogger timings("CompilerDriverTest::CompileAll", false, false); - TimingLogger::ScopedTiming t(__FUNCTION__, &timings); + TimingLogger timings("DexToDexDecompilerTest::CompileAll", false, false); compiler_options_->image_type_ = CompilerOptions::ImageType::kNone; compiler_options_->SetCompilerFilter(CompilerFilter::kQuicken); // Create the main VerifierDeps, here instead of in the compiler since we want to aggregate // the results for all the dex files, not just the results for the current dex file. down_cast<QuickCompilerCallbacks*>(Runtime::Current()->GetCompilerCallbacks())->SetVerifierDeps( new verifier::VerifierDeps(GetDexFiles(class_loader))); - SetDexFilesForOatFile(GetDexFiles(class_loader)); - compiler_driver_->CompileAll(class_loader, GetDexFiles(class_loader), &timings); + std::vector<const DexFile*> dex_files = GetDexFiles(class_loader); + CommonCompilerTest::CompileAll(class_loader, dex_files, &timings); } void RunTest(const char* dex_name) { diff --git a/compiler/dex/verification_results.cc b/compiler/dex/verification_results.cc index dd947d90b7..5a34efb73c 100644 --- a/compiler/dex/verification_results.cc +++ b/compiler/dex/verification_results.cc @@ -97,7 +97,7 @@ void VerificationResults::ProcessVerifiedMethod(verifier::MethodVerifier* method } } -const VerifiedMethod* VerificationResults::GetVerifiedMethod(MethodReference ref) { +const VerifiedMethod* VerificationResults::GetVerifiedMethod(MethodReference ref) const { const VerifiedMethod* ret = nullptr; if (atomic_verified_methods_.Get(ref, &ret)) { return ret; @@ -129,13 +129,13 @@ void VerificationResults::AddRejectedClass(ClassReference ref) { DCHECK(IsClassRejected(ref)); } -bool VerificationResults::IsClassRejected(ClassReference ref) { +bool VerificationResults::IsClassRejected(ClassReference ref) const { ReaderMutexLock mu(Thread::Current(), rejected_classes_lock_); return (rejected_classes_.find(ref) != rejected_classes_.end()); } bool VerificationResults::IsCandidateForCompilation(MethodReference&, - const uint32_t access_flags) { + const uint32_t access_flags) const { if (!compiler_options_->IsAotCompilationEnabled()) { return false; } diff --git a/compiler/dex/verification_results.h b/compiler/dex/verification_results.h index 56f00309c0..04c4fa65e6 100644 --- a/compiler/dex/verification_results.h +++ b/compiler/dex/verification_results.h @@ -51,13 +51,13 @@ class VerificationResults { void CreateVerifiedMethodFor(MethodReference ref) REQUIRES(!verified_methods_lock_); - const VerifiedMethod* GetVerifiedMethod(MethodReference ref) + const VerifiedMethod* GetVerifiedMethod(MethodReference ref) const REQUIRES(!verified_methods_lock_); void AddRejectedClass(ClassReference ref) REQUIRES(!rejected_classes_lock_); - bool IsClassRejected(ClassReference ref) REQUIRES(!rejected_classes_lock_); + bool IsClassRejected(ClassReference ref) const REQUIRES(!rejected_classes_lock_); - bool IsCandidateForCompilation(MethodReference& method_ref, const uint32_t access_flags); + bool IsCandidateForCompilation(MethodReference& method_ref, const uint32_t access_flags) const; // Add a dex file to enable using the atomic map. void AddDexFile(const DexFile* dex_file) REQUIRES(!verified_methods_lock_); @@ -74,10 +74,12 @@ class VerificationResults { // GetVerifiedMethod. AtomicMap atomic_verified_methods_; - ReaderWriterMutex verified_methods_lock_ DEFAULT_MUTEX_ACQUIRED_AFTER; + // TODO: External locking during CompilerDriver::PreCompile(), no locking during compilation. + mutable ReaderWriterMutex verified_methods_lock_ DEFAULT_MUTEX_ACQUIRED_AFTER; // Rejected classes. - ReaderWriterMutex rejected_classes_lock_ DEFAULT_MUTEX_ACQUIRED_AFTER; + // TODO: External locking during CompilerDriver::PreCompile(), no locking during compilation. + mutable ReaderWriterMutex rejected_classes_lock_ DEFAULT_MUTEX_ACQUIRED_AFTER; std::set<ClassReference> rejected_classes_ GUARDED_BY(rejected_classes_lock_); friend class verifier::VerifierDepsTest; diff --git a/compiler/driver/compiler_driver-inl.h b/compiler/driver/compiler_driver-inl.h index 792f508199..63dcb4664c 100644 --- a/compiler/driver/compiler_driver-inl.h +++ b/compiler/driver/compiler_driver-inl.h @@ -99,11 +99,6 @@ inline std::pair<bool, bool> CompilerDriver::IsFastInstanceField( return std::make_pair(fast_get, fast_put); } -inline VerificationResults* CompilerDriver::GetVerificationResults() const { - DCHECK(Runtime::Current()->IsAotCompiler()); - return verification_results_; -} - } // namespace art #endif // ART_COMPILER_DRIVER_COMPILER_DRIVER_INL_H_ diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc index 67cabef641..18f7105769 100644 --- a/compiler/driver/compiler_driver.cc +++ b/compiler/driver/compiler_driver.cc @@ -245,16 +245,12 @@ class CompilerDriver::AOTCompilationStats { CompilerDriver::CompilerDriver( const CompilerOptions* compiler_options, - VerificationResults* verification_results, Compiler::Kind compiler_kind, - HashSet<std::string>* image_classes, size_t thread_count, int swap_fd) : compiler_options_(compiler_options), - verification_results_(verification_results), compiler_(Compiler::Create(this, compiler_kind)), compiler_kind_(compiler_kind), - image_classes_(std::move(image_classes)), number_of_soft_verifier_failures_(0), had_hard_verifier_failure_(false), parallel_thread_count_(thread_count), @@ -266,10 +262,6 @@ CompilerDriver::CompilerDriver( compiler_->Init(); - if (GetCompilerOptions().IsBootImage()) { - CHECK(image_classes_ != nullptr) << "Expected image classes for boot image"; - } - compiled_method_storage_.SetDedupeEnabled(compiler_options_->DeduplicateCode()); } @@ -325,9 +317,8 @@ void CompilerDriver::CompileAll(jobject class_loader, TimingLogger* timings) { DCHECK(!Runtime::Current()->IsStarted()); - InitializeThreadPools(); + CheckThreadPools(); - PreCompile(class_loader, dex_files, 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 @@ -343,8 +334,6 @@ void CompilerDriver::CompileAll(jobject class_loader, if (GetCompilerOptions().GetDumpStats()) { stats_->Dump(); } - - FreeThreadPools(); } static optimizer::DexToDexCompiler::CompilationLevel GetDexToDexCompilationLevel( @@ -496,7 +485,7 @@ static void CompileMethodDex2Dex( optimizer::DexToDexCompiler* const compiler = &driver->GetDexToDexCompiler(); if (compiler->ShouldCompileMethod(method_ref)) { - VerificationResults* results = driver->GetVerificationResults(); + const VerificationResults* results = driver->GetCompilerOptions().GetVerificationResults(); DCHECK(results != nullptr); const VerifiedMethod* verified_method = results->GetVerifiedMethod(method_ref); // Do not optimize if a VerifiedMethod is missing. SafeCast elision, @@ -574,7 +563,7 @@ static void CompileMethodQuick( } else if ((access_flags & kAccAbstract) != 0) { // Abstract methods don't have code. } else { - VerificationResults* results = driver->GetVerificationResults(); + const VerificationResults* results = driver->GetCompilerOptions().GetVerificationResults(); DCHECK(results != nullptr); const VerifiedMethod* verified_method = results->GetVerifiedMethod(method_ref); bool compile = @@ -881,7 +870,9 @@ static void EnsureVerifiedOrVerifyAtRuntime(jobject jclass_loader, void CompilerDriver::PreCompile(jobject class_loader, const std::vector<const DexFile*>& dex_files, - TimingLogger* timings) { + TimingLogger* timings, + /*inout*/ HashSet<std::string>* image_classes, + /*out*/ VerificationResults* verification_results) { CheckThreadPools(); VLOG(compiler) << "Before precompile " << GetMemoryUsageString(false); @@ -898,7 +889,7 @@ void CompilerDriver::PreCompile(jobject class_loader, // 6) Update the set of image classes. // 7) For deterministic boot image, initialize bitstrings for type checking. - LoadImageClasses(timings); + LoadImageClasses(timings, image_classes); VLOG(compiler) << "LoadImageClasses: " << GetMemoryUsageString(false); if (compiler_options_->IsAnyCompilationEnabled()) { @@ -932,7 +923,7 @@ void CompilerDriver::PreCompile(jobject class_loader, ResolveConstStrings(dex_files, /*only_startup_strings=*/ true, timings); } - Verify(class_loader, dex_files, timings); + Verify(class_loader, dex_files, timings, verification_results); VLOG(compiler) << "Verify: " << GetMemoryUsageString(false); if (had_hard_verifier_failure_ && GetCompilerOptions().AbortOnHardVerifierFailure()) { @@ -957,7 +948,7 @@ void CompilerDriver::PreCompile(jobject class_loader, VLOG(compiler) << "InitializeClasses: " << GetMemoryUsageString(false); } - UpdateImageClasses(timings); + UpdateImageClasses(timings, image_classes); VLOG(compiler) << "UpdateImageClasses: " << GetMemoryUsageString(false); if (kBitstringSubtypeCheckEnabled && @@ -1071,7 +1062,8 @@ class RecordImageClassesVisitor : public ClassVisitor { }; // Make a list of descriptors for classes to include in the image -void CompilerDriver::LoadImageClasses(TimingLogger* timings) { +void CompilerDriver::LoadImageClasses(TimingLogger* timings, + /*inout*/ HashSet<std::string>* image_classes) { CHECK(timings != nullptr); if (!GetCompilerOptions().IsBootImage()) { return; @@ -1082,15 +1074,15 @@ void CompilerDriver::LoadImageClasses(TimingLogger* timings) { Thread* self = Thread::Current(); ScopedObjectAccess soa(self); ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); - CHECK(image_classes_ != nullptr); - for (auto it = image_classes_->begin(), end = image_classes_->end(); it != end;) { + CHECK(image_classes != nullptr); + for (auto it = image_classes->begin(), end = image_classes->end(); it != end;) { const std::string& descriptor(*it); StackHandleScope<1> hs(self); Handle<mirror::Class> klass( hs.NewHandle(class_linker->FindSystemClass(self, descriptor.c_str()))); if (klass == nullptr) { VLOG(compiler) << "Failed to find class " << descriptor; - it = image_classes_->erase(it); + it = image_classes->erase(it); self->ClearException(); } else { ++it; @@ -1140,10 +1132,10 @@ void CompilerDriver::LoadImageClasses(TimingLogger* timings) { // We walk the roots looking for classes so that we'll pick up the // above classes plus any classes them depend on such super // classes, interfaces, and the required ClassLinker roots. - RecordImageClassesVisitor visitor(image_classes_); + RecordImageClassesVisitor visitor(image_classes); class_linker->VisitClasses(&visitor); - CHECK(!image_classes_->empty()); + CHECK(!image_classes->empty()); } static void MaybeAddToImageClasses(Thread* self, @@ -1312,7 +1304,8 @@ class ClinitImageUpdate { DISALLOW_COPY_AND_ASSIGN(ClinitImageUpdate); }; -void CompilerDriver::UpdateImageClasses(TimingLogger* timings) { +void CompilerDriver::UpdateImageClasses(TimingLogger* timings, + /*inout*/ HashSet<std::string>* image_classes) { if (GetCompilerOptions().IsBootImage()) { TimingLogger::ScopedTiming t("UpdateImageClasses", timings); @@ -1324,7 +1317,7 @@ void CompilerDriver::UpdateImageClasses(TimingLogger* timings) { VariableSizedHandleScope hs(Thread::Current()); std::string error_msg; std::unique_ptr<ClinitImageUpdate> update(ClinitImageUpdate::Create(hs, - image_classes_, + image_classes, Thread::Current(), runtime->GetClassLinker())); @@ -1393,12 +1386,6 @@ bool CompilerDriver::ComputeInstanceFieldInfo(uint32_t field_idx, const DexCompi } } -const VerifiedMethod* CompilerDriver::GetVerifiedMethod(const DexFile* dex_file, - uint32_t method_idx) const { - MethodReference ref(dex_file, method_idx); - return verification_results_->GetVerifiedMethod(ref); -} - bool CompilerDriver::IsSafeCast(const DexCompilationUnit* mUnit, uint32_t dex_pc) { if (!compiler_options_->IsVerificationEnabled()) { // If we didn't verify, every cast has to be treated as non-safe. @@ -1764,7 +1751,8 @@ static void LoadAndUpdateStatus(const ClassAccessor& accessor, bool CompilerDriver::FastVerify(jobject jclass_loader, const std::vector<const DexFile*>& dex_files, - TimingLogger* timings) { + TimingLogger* timings, + /*out*/ VerificationResults* verification_results) { verifier::VerifierDeps* verifier_deps = Runtime::Current()->GetCompilerCallbacks()->GetVerifierDeps(); // If there exist VerifierDeps that aren't the ones we just created to output, use them to verify. @@ -1812,7 +1800,7 @@ bool CompilerDriver::FastVerify(jobject jclass_loader, // - Quickening will not do checkcast ellision. // TODO(ngeoffray): Reconsider this once we refactor compiler filters. for (const ClassAccessor::Method& method : accessor.GetMethods()) { - verification_results_->CreateVerifiedMethodFor(method.GetReference()); + verification_results->CreateVerifiedMethodFor(method.GetReference()); } } } else if (!compiler_only_verifies) { @@ -1830,8 +1818,9 @@ bool CompilerDriver::FastVerify(jobject jclass_loader, void CompilerDriver::Verify(jobject jclass_loader, const std::vector<const DexFile*>& dex_files, - TimingLogger* timings) { - if (FastVerify(jclass_loader, dex_files, timings)) { + TimingLogger* timings, + /*out*/ VerificationResults* verification_results) { + if (FastVerify(jclass_loader, dex_files, timings, verification_results)) { return; } @@ -2530,7 +2519,7 @@ void CompilerDriver::InitializeClasses(jobject class_loader, // SetVerificationAttempted so that the access flags are set. If we do not do this they get // changed at runtime resulting in more dirty image pages. // Also create conflict tables. - // Only useful if we are compiling an image (image_classes_ is not null). + // Only useful if we are compiling an image. ScopedObjectAccess soa(Thread::Current()); VariableSizedHandleScope hs(soa.Self()); InitializeArrayClassesAndCreateConflictTablesVisitor visitor(hs); @@ -2569,8 +2558,9 @@ static void CompileDexFile(CompilerDriver* driver, ClassReference ref(&dex_file, class_def_index); const DexFile::ClassDef& class_def = dex_file.GetClassDef(class_def_index); ClassAccessor accessor(dex_file, class_def_index); + CompilerDriver* const driver = context.GetCompiler(); // Skip compiling classes with generic verifier failures since they will still fail at runtime - if (context.GetCompiler()->GetVerificationResults()->IsClassRejected(ref)) { + if (driver->GetCompilerOptions().GetVerificationResults()->IsClassRejected(ref)) { return; } // Use a scoped object access to perform to the quick SkipClass check. @@ -2602,8 +2592,6 @@ static void CompileDexFile(CompilerDriver* driver, // Go to native so that we don't block GC during compilation. ScopedThreadSuspension sts(soa.Self(), kNative); - CompilerDriver* const driver = context.GetCompiler(); - // Can we run DEX-to-DEX compiler on this class ? optimizer::DexToDexCompiler::CompilationLevel dex_to_dex_compilation_level = GetDexToDexCompilationLevel(soa.Self(), *driver, jclass_loader, dex_file, class_def); @@ -2775,31 +2763,6 @@ CompiledMethod* CompilerDriver::GetCompiledMethod(MethodReference ref) const { return compiled_method; } -bool CompilerDriver::IsMethodVerifiedWithoutFailures(uint32_t method_idx, - uint16_t class_def_idx, - const DexFile& dex_file) const { - const VerifiedMethod* verified_method = GetVerifiedMethod(&dex_file, method_idx); - if (verified_method != nullptr) { - return !verified_method->HasVerificationFailures(); - } - - // If we can't find verification metadata, check if this is a system class (we trust that system - // classes have their methods verified). If it's not, be conservative and assume the method - // has not been verified successfully. - - // TODO: When compiling the boot image it should be safe to assume that everything is verified, - // even if methods are not found in the verification cache. - const char* descriptor = dex_file.GetClassDescriptor(dex_file.GetClassDef(class_def_idx)); - ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); - Thread* self = Thread::Current(); - ScopedObjectAccess soa(self); - bool is_system_class = class_linker->FindSystemClass(self, descriptor) != nullptr; - if (!is_system_class) { - self->ClearException(); - } - return is_system_class; -} - std::string CompilerDriver::GetMemoryUsageString(bool extended) const { std::ostringstream oss; const gc::Heap* const heap = Runtime::Current()->GetHeap(); diff --git a/compiler/driver/compiler_driver.h b/compiler/driver/compiler_driver.h index 714b2d1fc8..7c0fc6450f 100644 --- a/compiler/driver/compiler_driver.h +++ b/compiler/driver/compiler_driver.h @@ -76,7 +76,6 @@ template <class Allocator> class SrcMap; class TimingLogger; class VdexFile; class VerificationResults; -class VerifiedMethod; enum EntryPointCallingConvention { // ABI of invocations to a method's interpreter entry point. @@ -95,9 +94,7 @@ class CompilerDriver { // can assume will be in the image, with null implying all available // classes. CompilerDriver(const CompilerOptions* compiler_options, - VerificationResults* verification_results, Compiler::Kind compiler_kind, - HashSet<std::string>* image_classes, size_t thread_count, int swap_fd); @@ -106,6 +103,17 @@ class CompilerDriver { // Set dex files classpath. void SetClasspathDexFiles(const std::vector<const DexFile*>& dex_files); + // Initialize and destroy thread pools. This is exposed because we do not want + // to do this twice, for PreCompile() and CompileAll(). + void InitializeThreadPools(); + void FreeThreadPools(); + + void PreCompile(jobject class_loader, + const std::vector<const DexFile*>& dex_files, + TimingLogger* timings, + /*inout*/ HashSet<std::string>* image_classes, + /*out*/ VerificationResults* verification_results) + REQUIRES(!Locks::mutator_lock_); void CompileAll(jobject class_loader, const std::vector<const DexFile*>& dex_files, TimingLogger* timings) @@ -124,8 +132,6 @@ class CompilerDriver { Handle<mirror::ClassLoader> h_class_loader) REQUIRES(!Locks::mutator_lock_); - VerificationResults* GetVerificationResults() const; - const CompilerOptions& GetCompilerOptions() const { return *compiler_options_; } @@ -194,7 +200,6 @@ class CompilerDriver { REQUIRES_SHARED(Locks::mutator_lock_); - const VerifiedMethod* GetVerifiedMethod(const DexFile* dex_file, uint32_t method_idx) const; bool IsSafeCast(const DexCompilationUnit* mUnit, uint32_t dex_pc); size_t GetThreadCount() const { @@ -219,12 +224,6 @@ class CompilerDriver { void RecordClassStatus(const ClassReference& ref, ClassStatus status); - // Checks if the specified method has been verified without failures. Returns - // false if the method is not in the verification results (GetVerificationResults). - bool IsMethodVerifiedWithoutFailures(uint32_t method_idx, - uint16_t class_def_idx, - const DexFile& dex_file) const; - // Get memory usage during compilation. std::string GetMemoryUsageString(bool extended) const; @@ -265,13 +264,9 @@ class CompilerDriver { } private: - void PreCompile(jobject class_loader, - const std::vector<const DexFile*>& dex_files, - TimingLogger* timings) + void LoadImageClasses(TimingLogger* timings, /*inout*/ HashSet<std::string>* image_classes) REQUIRES(!Locks::mutator_lock_); - void LoadImageClasses(TimingLogger* timings) REQUIRES(!Locks::mutator_lock_); - // Attempt to resolve all type, methods, fields, and strings // referenced from code in the dex file following PathClassLoader // ordering semantics. @@ -291,11 +286,13 @@ class CompilerDriver { // verification was successful. bool FastVerify(jobject class_loader, const std::vector<const DexFile*>& dex_files, - TimingLogger* timings); + TimingLogger* timings, + /*out*/ VerificationResults* verification_results); void Verify(jobject class_loader, const std::vector<const DexFile*>& dex_files, - TimingLogger* timings); + TimingLogger* timings, + /*out*/ VerificationResults* verification_results); void VerifyDexFile(jobject class_loader, const DexFile& dex_file, @@ -326,14 +323,13 @@ class CompilerDriver { TimingLogger* timings) REQUIRES(!Locks::mutator_lock_); - void UpdateImageClasses(TimingLogger* timings) REQUIRES(!Locks::mutator_lock_); + void UpdateImageClasses(TimingLogger* timings, /*inout*/ HashSet<std::string>* image_classes) + REQUIRES(!Locks::mutator_lock_); void Compile(jobject class_loader, const std::vector<const DexFile*>& dex_files, TimingLogger* timings); - void InitializeThreadPools(); - void FreeThreadPools(); void CheckThreadPools(); // Resolve const string literals that are loaded from dex code. If only_startup_strings is @@ -343,7 +339,6 @@ class CompilerDriver { /*inout*/ TimingLogger* timings); const CompilerOptions* const compiler_options_; - VerificationResults* const verification_results_; std::unique_ptr<Compiler> compiler_; Compiler::Kind compiler_kind_; @@ -359,12 +354,6 @@ class CompilerDriver { // All method references that this compiler has compiled. MethodTable compiled_methods_; - // Image classes to be updated by PreCompile(). - // TODO: Remove this member which is a non-const pointer to the CompilerOptions' data. - // Pass this explicitly to the PreCompile() which should be called directly from - // Dex2Oat rather than implicitly by CompileAll(). - HashSet<std::string>* image_classes_; - std::atomic<uint32_t> number_of_soft_verifier_failures_; bool had_hard_verifier_failure_; diff --git a/compiler/driver/compiler_driver_test.cc b/compiler/driver/compiler_driver_test.cc index fe1568da83..b9241292ee 100644 --- a/compiler/driver/compiler_driver_test.cc +++ b/compiler/driver/compiler_driver_test.cc @@ -42,20 +42,18 @@ namespace art { class CompilerDriverTest : public CommonCompilerTest { protected: - void CompileAll(jobject class_loader) REQUIRES(!Locks::mutator_lock_) { - TimingLogger timings("CompilerDriverTest::CompileAll", false, false); - TimingLogger::ScopedTiming t(__FUNCTION__, &timings); + void CompileAllAndMakeExecutable(jobject class_loader) REQUIRES(!Locks::mutator_lock_) { + TimingLogger timings("CompilerDriverTest::CompileAllAndMakeExecutable", false, false); dex_files_ = GetDexFiles(class_loader); - SetDexFilesForOatFile(dex_files_); - compiler_driver_->CompileAll(class_loader, dex_files_, &timings); - t.NewTiming("MakeAllExecutable"); + CompileAll(class_loader, dex_files_, &timings); + TimingLogger::ScopedTiming t("MakeAllExecutable", &timings); MakeAllExecutable(class_loader); } void EnsureCompiled(jobject class_loader, const char* class_name, const char* method, const char* signature, bool is_virtual) REQUIRES(!Locks::mutator_lock_) { - CompileAll(class_loader); + CompileAllAndMakeExecutable(class_loader); Thread::Current()->TransitionFromSuspendedToRunnable(); bool started = runtime_->Start(); CHECK(started); @@ -106,7 +104,7 @@ class CompilerDriverTest : public CommonCompilerTest { // Disabled due to 10 second runtime on host // TODO: Update the test for hash-based dex cache arrays. Bug: 30627598 TEST_F(CompilerDriverTest, DISABLED_LARGE_CompileDexLibCore) { - CompileAll(nullptr); + CompileAllAndMakeExecutable(nullptr); // All libcore references should resolve ScopedObjectAccess soa(Thread::Current()); @@ -266,7 +264,7 @@ TEST_F(CompilerDriverProfileTest, ProfileGuidedCompilation) { ASSERT_TRUE(dex_file->EnableWrite()); } - CompileAll(class_loader); + CompileAllAndMakeExecutable(class_loader); std::unordered_set<std::string> m = GetExpectedMethodsForClass("Main"); std::unordered_set<std::string> s = GetExpectedMethodsForClass("Second"); @@ -310,7 +308,7 @@ TEST_F(CompilerDriverVerifyTest, VerifyCompilation) { } ASSERT_NE(class_loader, nullptr); - CompileAll(class_loader); + CompileAllAndMakeExecutable(class_loader); CheckVerifiedClass(class_loader, "LMain;"); CheckVerifiedClass(class_loader, "LSecond;"); diff --git a/compiler/driver/compiler_options.cc b/compiler/driver/compiler_options.cc index b28c7e0edb..8d1ae3d524 100644 --- a/compiler/driver/compiler_options.cc +++ b/compiler/driver/compiler_options.cc @@ -24,9 +24,14 @@ #include "arch/instruction_set_features.h" #include "base/runtime_debug.h" #include "base/variant_map.h" +#include "class_linker.h" #include "cmdline_parser.h" #include "compiler_options_map-inl.h" +#include "dex/dex_file-inl.h" +#include "dex/verification_results.h" +#include "dex/verified_method.h" #include "runtime.h" +#include "scoped_thread_state_change-inl.h" #include "simple_compiler_options_map.h" namespace art { @@ -44,6 +49,7 @@ CompilerOptions::CompilerOptions() no_inline_from_(), dex_files_for_oat_file_(), image_classes_(), + verification_results_(nullptr), image_type_(ImageType::kNone), compiling_with_core_image_(false), baseline_(false), @@ -141,4 +147,40 @@ bool CompilerOptions::IsImageClass(const char* descriptor) const { return image_classes_.find(StringPiece(descriptor)) != image_classes_.end(); } +const VerificationResults* CompilerOptions::GetVerificationResults() const { + DCHECK(Runtime::Current()->IsAotCompiler()); + return verification_results_; +} + +const VerifiedMethod* CompilerOptions::GetVerifiedMethod(const DexFile* dex_file, + uint32_t method_idx) const { + MethodReference ref(dex_file, method_idx); + return verification_results_->GetVerifiedMethod(ref); +} + +bool CompilerOptions::IsMethodVerifiedWithoutFailures(uint32_t method_idx, + uint16_t class_def_idx, + const DexFile& dex_file) const { + const VerifiedMethod* verified_method = GetVerifiedMethod(&dex_file, method_idx); + if (verified_method != nullptr) { + return !verified_method->HasVerificationFailures(); + } + + // If we can't find verification metadata, check if this is a system class (we trust that system + // classes have their methods verified). If it's not, be conservative and assume the method + // has not been verified successfully. + + // TODO: When compiling the boot image it should be safe to assume that everything is verified, + // even if methods are not found in the verification cache. + const char* descriptor = dex_file.GetClassDescriptor(dex_file.GetClassDef(class_def_idx)); + ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); + Thread* self = Thread::Current(); + ScopedObjectAccess soa(self); + bool is_system_class = class_linker->FindSystemClass(self, descriptor) != nullptr; + if (!is_system_class) { + self->ClearException(); + } + return is_system_class; +} + } // namespace art diff --git a/compiler/driver/compiler_options.h b/compiler/driver/compiler_options.h index a8f246dcab..bd12bf7dda 100644 --- a/compiler/driver/compiler_options.h +++ b/compiler/driver/compiler_options.h @@ -47,6 +47,8 @@ class DexFile; enum class InstructionSet; class InstructionSetFeatures; class ProfileCompilationInfo; +class VerificationResults; +class VerifiedMethod; // Enum for CheckProfileMethodsCompiled. Outside CompilerOptions so it can be forward-declared. enum class ProfileMethodsCheck : uint8_t { @@ -283,6 +285,16 @@ class CompilerOptions final { bool IsImageClass(const char* descriptor) const; + const VerificationResults* GetVerificationResults() const; + + const VerifiedMethod* GetVerifiedMethod(const DexFile* dex_file, uint32_t method_idx) const; + + // Checks if the specified method has been verified without failures. Returns + // false if the method is not in the verification results (GetVerificationResults). + bool IsMethodVerifiedWithoutFailures(uint32_t method_idx, + uint16_t class_def_idx, + const DexFile& dex_file) const; + bool ParseCompilerOptions(const std::vector<std::string>& options, bool ignore_unrecognized, std::string* error_msg); @@ -381,6 +393,9 @@ class CompilerOptions final { // Must not be empty for real boot image, only for tests pretending to compile boot image. HashSet<std::string> image_classes_; + // Results of AOT verification. + const VerificationResults* verification_results_; + ImageType image_type_; bool compiling_with_core_image_; bool baseline_; diff --git a/compiler/jit/jit_compiler.cc b/compiler/jit/jit_compiler.cc index 0eab8356e7..b9fd868f1c 100644 --- a/compiler/jit/jit_compiler.cc +++ b/compiler/jit/jit_compiler.cc @@ -167,9 +167,7 @@ JitCompiler::JitCompiler() { compiler_driver_.reset(new CompilerDriver( compiler_options_.get(), - /* verification_results */ nullptr, Compiler::kOptimizing, - /* image_classes */ nullptr, /* thread_count */ 1, /* swap_fd */ -1)); // Disable dedupe so we can remove compiled methods. diff --git a/compiler/optimizing/inliner.cc b/compiler/optimizing/inliner.cc index ec9322270a..417d794264 100644 --- a/compiler/optimizing/inliner.cc +++ b/compiler/optimizing/inliner.cc @@ -28,7 +28,6 @@ #include "dex/inline_method_analyser.h" #include "dex/verification_results.h" #include "dex/verified_method.h" -#include "driver/compiler_driver-inl.h" #include "driver/compiler_options.h" #include "driver/dex_compilation_unit.h" #include "instruction_simplifier.h" @@ -408,7 +407,7 @@ ArtMethod* HInliner::TryCHADevirtualization(ArtMethod* resolved_method) { return single_impl; } -static bool IsMethodUnverified(CompilerDriver* const compiler_driver, ArtMethod* method) +static bool IsMethodUnverified(const CompilerOptions& compiler_options, ArtMethod* method) REQUIRES_SHARED(Locks::mutator_lock_) { if (!method->GetDeclaringClass()->IsVerified()) { if (Runtime::Current()->UseJitCompilation()) { @@ -417,8 +416,9 @@ static bool IsMethodUnverified(CompilerDriver* const compiler_driver, ArtMethod* return true; } uint16_t class_def_idx = method->GetDeclaringClass()->GetDexClassDefIndex(); - if (!compiler_driver->IsMethodVerifiedWithoutFailures( - method->GetDexMethodIndex(), class_def_idx, *method->GetDexFile())) { + if (!compiler_options.IsMethodVerifiedWithoutFailures(method->GetDexMethodIndex(), + class_def_idx, + *method->GetDexFile())) { // Method has soft or hard failures, don't analyze. return true; } @@ -426,11 +426,11 @@ static bool IsMethodUnverified(CompilerDriver* const compiler_driver, ArtMethod* return false; } -static bool AlwaysThrows(CompilerDriver* const compiler_driver, ArtMethod* method) +static bool AlwaysThrows(const CompilerOptions& compiler_options, ArtMethod* method) REQUIRES_SHARED(Locks::mutator_lock_) { DCHECK(method != nullptr); // Skip non-compilable and unverified methods. - if (!method->IsCompilable() || IsMethodUnverified(compiler_driver, method)) { + if (!method->IsCompilable() || IsMethodUnverified(compiler_options, method)) { return false; } // Skip native methods, methods with try blocks, and methods that are too large. @@ -518,7 +518,7 @@ bool HInliner::TryInline(HInvoke* invoke_instruction) { MaybeRecordStat(stats_, MethodCompilationStat::kInlinedInvokeVirtualOrInterface); } } - } else if (!cha_devirtualize && AlwaysThrows(compiler_driver_, actual_method)) { + } else if (!cha_devirtualize && AlwaysThrows(codegen_->GetCompilerOptions(), actual_method)) { // Set always throws property for non-inlined method call with single target // (unless it was obtained through CHA, because that would imply we have // to add the CHA dependency, which seems not worth it). @@ -1500,7 +1500,7 @@ bool HInliner::TryBuildAndInline(HInvoke* invoke_instruction, return false; } - if (IsMethodUnverified(compiler_driver_, method)) { + if (IsMethodUnverified(codegen_->GetCompilerOptions(), method)) { LOG_FAIL(stats_, MethodCompilationStat::kNotInlinedNotVerified) << "Method " << method->PrettyMethod() << " couldn't be verified, so it cannot be inlined"; @@ -2069,7 +2069,6 @@ void HInliner::RunOptimizations(HGraph* callee_graph, codegen_, outer_compilation_unit_, dex_compilation_unit, - compiler_driver_, handles_, inline_stats_, total_number_of_dex_registers_ + accessor.RegistersSize(), diff --git a/compiler/optimizing/inliner.h b/compiler/optimizing/inliner.h index 6fd0c204b2..8ac2163a94 100644 --- a/compiler/optimizing/inliner.h +++ b/compiler/optimizing/inliner.h @@ -38,7 +38,6 @@ class HInliner : public HOptimization { CodeGenerator* codegen, const DexCompilationUnit& outer_compilation_unit, const DexCompilationUnit& caller_compilation_unit, - CompilerDriver* compiler_driver, VariableSizedHandleScope* handles, OptimizingCompilerStats* stats, size_t total_number_of_dex_registers, @@ -51,7 +50,6 @@ class HInliner : public HOptimization { outer_compilation_unit_(outer_compilation_unit), caller_compilation_unit_(caller_compilation_unit), codegen_(codegen), - compiler_driver_(compiler_driver), total_number_of_dex_registers_(total_number_of_dex_registers), total_number_of_instructions_(total_number_of_instructions), parent_(parent), @@ -280,7 +278,6 @@ class HInliner : public HOptimization { const DexCompilationUnit& outer_compilation_unit_; const DexCompilationUnit& caller_compilation_unit_; CodeGenerator* const codegen_; - CompilerDriver* const compiler_driver_; const size_t total_number_of_dex_registers_; size_t total_number_of_instructions_; diff --git a/compiler/optimizing/optimization.cc b/compiler/optimizing/optimization.cc index 0f971e100e..b75afad4c8 100644 --- a/compiler/optimizing/optimization.cc +++ b/compiler/optimizing/optimization.cc @@ -181,7 +181,6 @@ ArenaVector<HOptimization*> ConstructOptimizations( HGraph* graph, OptimizingCompilerStats* stats, CodeGenerator* codegen, - CompilerDriver* driver, const DexCompilationUnit& dex_compilation_unit, VariableSizedHandleScope* handles) { ArenaVector<HOptimization*> optimizations(allocator->Adapter()); @@ -258,7 +257,6 @@ ArenaVector<HOptimization*> ConstructOptimizations( codegen, dex_compilation_unit, // outer_compilation_unit dex_compilation_unit, // outermost_compilation_unit - driver, handles, stats, accessor.RegistersSize(), diff --git a/compiler/optimizing/optimization.h b/compiler/optimizing/optimization.h index 490007d9d9..ce44b5f81a 100644 --- a/compiler/optimizing/optimization.h +++ b/compiler/optimizing/optimization.h @@ -147,7 +147,6 @@ ArenaVector<HOptimization*> ConstructOptimizations( HGraph* graph, OptimizingCompilerStats* stats, CodeGenerator* codegen, - CompilerDriver* driver, const DexCompilationUnit& dex_compilation_unit, VariableSizedHandleScope* handles); diff --git a/compiler/optimizing/optimizing_compiler.cc b/compiler/optimizing/optimizing_compiler.cc index 641368b87a..92aaa19121 100644 --- a/compiler/optimizing/optimizing_compiler.cc +++ b/compiler/optimizing/optimizing_compiler.cc @@ -321,7 +321,6 @@ class OptimizingCompiler final : public Compiler { graph, compilation_stats_.get(), codegen, - GetCompilerDriver(), dex_compilation_unit, handles); DCHECK_EQ(length, optimizations.size()); @@ -962,9 +961,9 @@ CodeGenerator* OptimizingCompiler::TryCompileIntrinsic( arena_stack, dex_file, method_idx, - compiler_driver->GetCompilerOptions().GetInstructionSet(), + compiler_options.GetInstructionSet(), kInvalidInvokeType, - compiler_driver->GetCompilerOptions().GetDebuggable(), + compiler_options.GetDebuggable(), /* osr */ false); DCHECK(Runtime::Current()->IsAotCompiler()); @@ -1043,12 +1042,13 @@ CompiledMethod* OptimizingCompiler::Compile(const DexFile::CodeItem* code_item, const DexFile& dex_file, Handle<mirror::DexCache> dex_cache) const { CompilerDriver* compiler_driver = GetCompilerDriver(); + const CompilerOptions& compiler_options = compiler_driver->GetCompilerOptions(); CompiledMethod* compiled_method = nullptr; Runtime* runtime = Runtime::Current(); DCHECK(runtime->IsAotCompiler()); - const VerifiedMethod* verified_method = compiler_driver->GetVerifiedMethod(&dex_file, method_idx); + const VerifiedMethod* verified_method = compiler_options.GetVerifiedMethod(&dex_file, method_idx); DCHECK(!verified_method->HasRuntimeThrow()); - if (compiler_driver->IsMethodVerifiedWithoutFailures(method_idx, class_def_idx, dex_file) || + if (compiler_options.IsMethodVerifiedWithoutFailures(method_idx, class_def_idx, dex_file) || verifier::CanCompilerHandleVerificationFailure( verified_method->GetEncounteredVerificationFailures())) { ArenaAllocator allocator(runtime->GetArenaPool()); @@ -1080,7 +1080,7 @@ CompiledMethod* OptimizingCompiler::Compile(const DexFile::CodeItem* code_item, // Go to native so that we don't block GC during compilation. ScopedThreadSuspension sts(soa.Self(), kNative); if (method != nullptr && UNLIKELY(method->IsIntrinsic())) { - DCHECK(compiler_driver->GetCompilerOptions().IsBootImage()); + DCHECK(compiler_options.IsBootImage()); codegen.reset( TryCompileIntrinsic(&allocator, &arena_stack, @@ -1099,7 +1099,7 @@ CompiledMethod* OptimizingCompiler::Compile(const DexFile::CodeItem* code_item, &code_allocator, dex_compilation_unit, method, - compiler_driver->GetCompilerOptions().IsBaseline(), + compiler_options.IsBaseline(), /* osr= */ false, &handles)); } @@ -1128,7 +1128,7 @@ CompiledMethod* OptimizingCompiler::Compile(const DexFile::CodeItem* code_item, } } else { MethodCompilationStat method_stat; - if (compiler_driver->GetCompilerOptions().VerifyAtRuntime()) { + if (compiler_options.VerifyAtRuntime()) { method_stat = MethodCompilationStat::kNotCompiledVerifyAtRuntime; } else { method_stat = MethodCompilationStat::kNotCompiledVerificationError; @@ -1137,8 +1137,8 @@ CompiledMethod* OptimizingCompiler::Compile(const DexFile::CodeItem* code_item, } if (kIsDebugBuild && - compiler_driver->GetCompilerOptions().CompilingWithCoreImage() && - IsInstructionSetSupported(compiler_driver->GetCompilerOptions().GetInstructionSet())) { + compiler_options.CompilingWithCoreImage() && + IsInstructionSetSupported(compiler_options.GetInstructionSet())) { // For testing purposes, we put a special marker on method names // that should be compiled with this compiler (when the // instruction set is supported). This makes sure we're not diff --git a/compiler/verifier_deps_test.cc b/compiler/verifier_deps_test.cc index eb44dd7f1d..8c90aa7e37 100644 --- a/compiler/verifier_deps_test.cc +++ b/compiler/verifier_deps_test.cc @@ -93,12 +93,12 @@ class VerifierDepsTest : public CommonCompilerTest { verifier_deps_.reset(deps); } callbacks_->SetVerifierDeps(deps); - compiler_driver_->Verify(class_loader_, dex_files_, &timings); + compiler_driver_->Verify(class_loader_, dex_files_, &timings, verification_results_.get()); callbacks_->SetVerifierDeps(nullptr); // Clear entries in the verification results to avoid hitting a DCHECK that // we always succeed inserting a new entry after verifying. AtomicDexRefMap<MethodReference, const VerifiedMethod*>* map = - &compiler_driver_->GetVerificationResults()->atomic_verified_methods_; + &verification_results_->atomic_verified_methods_; map->Visit([](const DexFileReference& ref ATTRIBUTE_UNUSED, const VerifiedMethod* method) { delete method; }); @@ -126,7 +126,7 @@ class VerifierDepsTest : public CommonCompilerTest { class_linker_->RegisterDexFile(*dex_file, loader.Get()); } for (const DexFile* dex_file : dex_files_) { - compiler_driver_->GetVerificationResults()->AddDexFile(dex_file); + verification_results_->AddDexFile(dex_file); } SetDexFilesForOatFile(dex_files_); } diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc index 9e0e61df6c..a5bba9bb97 100644 --- a/dex2oat/dex2oat.cc +++ b/dex2oat/dex2oat.cc @@ -631,6 +631,7 @@ class Dex2Oat final { thread_count_(sysconf(_SC_NPROCESSORS_CONF)), start_ns_(NanoTime()), start_cputime_ns_(ProcessCpuNanoTime()), + strip_(false), oat_fd_(-1), input_vdex_fd_(-1), output_vdex_fd_(-1), @@ -1718,9 +1719,7 @@ class Dex2Oat final { compiler_options_->profile_compilation_info_ = profile_compilation_info_.get(); driver_.reset(new CompilerDriver(compiler_options_.get(), - verification_results_.get(), compiler_kind_, - &compiler_options_->image_classes_, thread_count_, swap_fd_)); if (!IsBootImage()) { @@ -1792,7 +1791,16 @@ class Dex2Oat final { << soa.Self()->GetException()->Dump(); } } + driver_->InitializeThreadPools(); + driver_->PreCompile(class_loader, + dex_files, + timings_, + &compiler_options_->image_classes_, + verification_results_.get()); + callbacks_->SetVerificationResults(nullptr); // Should not be needed anymore. + compiler_options_->verification_results_ = verification_results_.get(); driver_->CompileAll(class_loader, dex_files, timings_); + driver_->FreeThreadPools(); return class_loader; } diff --git a/dex2oat/linker/image_test.h b/dex2oat/linker/image_test.h index 41108448c4..bd8cf5ad56 100644 --- a/dex2oat/linker/image_test.h +++ b/dex2oat/linker/image_test.h @@ -219,11 +219,9 @@ inline void ImageTest::DoCompile(ImageHeader::StorageMode storage_mode, { jobject class_loader = nullptr; TimingLogger timings("ImageTest::WriteRead", false, false); - TimingLogger::ScopedTiming t("CompileAll", &timings); - SetDexFilesForOatFile(class_path); - driver->CompileAll(class_loader, class_path, &timings); + CompileAll(class_loader, class_path, &timings); - t.NewTiming("WriteElf"); + TimingLogger::ScopedTiming t("WriteElf", &timings); SafeMap<std::string, std::string> key_value_store; key_value_store.Put(OatHeader::kBootClassPathKey, android::base::Join(out_helper.dex_file_locations, ':')); diff --git a/dex2oat/linker/oat_writer.cc b/dex2oat/linker/oat_writer.cc index 6b17ef6e87..d045698d07 100644 --- a/dex2oat/linker/oat_writer.cc +++ b/dex2oat/linker/oat_writer.cc @@ -968,7 +968,7 @@ class OatWriter::InitOatClassesMethodVisitor : public DexMethodVisitor { ClassStatus status; bool found = writer_->compiler_driver_->GetCompiledClass(class_ref, &status); if (!found) { - VerificationResults* results = writer_->compiler_driver_->GetVerificationResults(); + const VerificationResults* results = writer_->compiler_options_.GetVerificationResults(); if (results != nullptr && results->IsClassRejected(class_ref)) { // The oat class status is used only for verification of resolved classes, // so use ClassStatus::kErrorResolved whether the class was resolved or unresolved diff --git a/dex2oat/linker/oat_writer_test.cc b/dex2oat/linker/oat_writer_test.cc index 598a0f846b..5de1540839 100644 --- a/dex2oat/linker/oat_writer_test.cc +++ b/dex2oat/linker/oat_writer_test.cc @@ -391,8 +391,7 @@ TEST_F(OatTest, WriteRead) { jobject class_loader = nullptr; if (kCompile) { TimingLogger timings2("OatTest::WriteRead", false, false); - SetDexFilesForOatFile(class_linker->GetBootClassPath()); - compiler_driver_->CompileAll(class_loader, class_linker->GetBootClassPath(), &timings2); + CompileAll(class_loader, class_linker->GetBootClassPath(), &timings2); } ScratchFile tmp_base, tmp_oat(tmp_base, ".oat"), tmp_vdex(tmp_base, ".vdex"); @@ -405,7 +404,7 @@ TEST_F(OatTest, WriteRead) { ASSERT_TRUE(success); if (kCompile) { // OatWriter strips the code, regenerate to compare - compiler_driver_->CompileAll(class_loader, class_linker->GetBootClassPath(), &timings); + CompileAll(class_loader, class_linker->GetBootClassPath(), &timings); } std::unique_ptr<OatFile> oat_file(OatFile::Open(/*zip_fd=*/ -1, tmp_oat.GetFilename(), @@ -513,8 +512,7 @@ TEST_F(OatTest, EmptyTextSection) { ScopedObjectAccess soa(Thread::Current()); class_linker->RegisterDexFile(*dex_file, soa.Decode<mirror::ClassLoader>(class_loader)); } - SetDexFilesForOatFile(dex_files); - compiler_driver_->CompileAll(class_loader, dex_files, &timings); + CompileAll(class_loader, dex_files, &timings); ScratchFile tmp_base, tmp_oat(tmp_base, ".oat"), tmp_vdex(tmp_base, ".vdex"); SafeMap<std::string, std::string> key_value_store; |