diff options
author | Andreas Gampe <agampe@google.com> | 2014-08-28 14:41:02 -0700 |
---|---|---|
committer | Andreas Gampe <agampe@google.com> | 2014-09-15 09:42:50 -0700 |
commit | 2ed8deff799448e094fa7a7cb9cf3b718820f4c6 (patch) | |
tree | b33fa371673d2019b6a8bdb2c928237cd7b3a9d3 /compiler/driver | |
parent | 41bc89598bbfe1037740a6a2e12ce0936dd9ba19 (diff) | |
download | art-2ed8deff799448e094fa7a7cb9cf3b718820f4c6.zip art-2ed8deff799448e094fa7a7cb9cf3b718820f4c6.tar.gz art-2ed8deff799448e094fa7a7cb9cf3b718820f4c6.tar.bz2 |
ART: Allow quickening in the boot image
Update the class linker to accept class status from the boot image
in compiler mode. Update compiler driver to allow quickening for
boot image classes. Update method verifier to accept quickened
instructions in compiler mode when we just want to dump. Update
oatdump to the new verifier API.
Bug: 17316928
(cherry picked from commit 35439baf287b291b67ee406308e17fc6194facbf)
Change-Id: I9ef1bfd78b0d93625b89b3d662131d7d6e5f2903
Diffstat (limited to 'compiler/driver')
-rw-r--r-- | compiler/driver/compiler_driver.cc | 175 | ||||
-rw-r--r-- | compiler/driver/compiler_driver.h | 19 |
2 files changed, 127 insertions, 67 deletions
diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc index 01e0ac4..b993015 100644 --- a/compiler/driver/compiler_driver.cc +++ b/compiler/driver/compiler_driver.cc @@ -350,10 +350,10 @@ CompilerDriver::CompilerDriver(const CompilerOptions* compiler_options, dump_stats_(dump_stats), dump_passes_(dump_passes), timings_logger_(timer), - compiler_library_(NULL), - compiler_context_(NULL), - compiler_enable_auto_elf_loading_(NULL), - compiler_get_method_code_addr_(NULL), + compiler_library_(nullptr), + compiler_context_(nullptr), + compiler_enable_auto_elf_loading_(nullptr), + compiler_get_method_code_addr_(nullptr), support_boot_image_fixup_(instruction_set != kMips), dedupe_code_("dedupe code"), dedupe_src_mapping_table_("dedupe source mapping table"), @@ -365,7 +365,7 @@ CompilerDriver::CompilerDriver(const CompilerOptions* compiler_options, DCHECK(verification_results_ != nullptr); DCHECK(method_inliner_map_ != nullptr); - CHECK_PTHREAD_CALL(pthread_key_create, (&tls_key_, NULL), "compiler tls key"); + CHECK_PTHREAD_CALL(pthread_key_create, (&tls_key_, nullptr), "compiler tls key"); dex_to_dex_compiler_ = reinterpret_cast<DexToDexCompilerFn>(ArtCompileDEX); @@ -445,7 +445,7 @@ CompilerDriver::~CompilerDriver() { CompilerTls* CompilerDriver::GetTls() { // Lazily create thread-local storage CompilerTls* res = static_cast<CompilerTls*>(pthread_getspecific(tls_key_)); - if (res == NULL) { + if (res == nullptr) { res = compiler_->CreateNewCompilerTls(); CHECK_PTHREAD_CALL(pthread_setspecific, (tls_key_, res), "compiler tls"); } @@ -520,20 +520,18 @@ static DexToDexCompilationLevel GetDexToDexCompilationlevel( const char* descriptor = dex_file.GetClassDescriptor(class_def); ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); mirror::Class* klass = class_linker->FindClass(self, descriptor, class_loader); - if (klass == NULL) { + if (klass == nullptr) { CHECK(self->IsExceptionPending()); self->ClearException(); return kDontDexToDexCompile; } - // The verifier can only run on "quick" instructions at runtime (see usage of - // FindAccessedFieldAtDexPc and FindInvokedMethodAtDexPc in ThrowNullPointerExceptionFromDexPC - // function). Since image classes can be verified again while compiling an application, - // we must prevent the DEX-to-DEX compiler from introducing them. - // TODO: find a way to enable "quick" instructions for image classes and remove this check. - bool compiling_image_classes = class_loader.Get() == nullptr; - if (compiling_image_classes) { - return kRequired; - } else if (klass->IsVerified()) { + // DexToDex at the kOptimize level may introduce quickened opcodes, which replace symbolic + // references with actual offsets. We cannot re-verify such instructions. + // + // We store the verification information in the class status in the oat file, which the linker + // can validate (checksums) and use to skip load-time verification. It is thus safe to + // optimize when a class has been fully verified before. + if (klass->IsVerified()) { // Class is verified so we can enable DEX-to-DEX compilation for performance. return kOptimize; } else if (klass->IsCompileTimeVerified()) { @@ -606,13 +604,14 @@ void CompilerDriver::PreCompile(jobject class_loader, const std::vector<const De ThreadPool* thread_pool, TimingLogger* timings) { LoadImageClasses(timings); + Resolve(class_loader, dex_files, thread_pool, timings); + if (!compiler_options_->IsVerificationEnabled()) { - VLOG(compiler) << "Verify none mode specified, skipping pre-compilation"; + VLOG(compiler) << "Verify none mode specified, skipping verification."; + SetVerified(class_loader, dex_files, thread_pool, timings); return; } - Resolve(class_loader, dex_files, thread_pool, timings); - Verify(class_loader, dex_files, thread_pool, timings); InitializeClasses(class_loader, dex_files, thread_pool, timings); @@ -632,7 +631,7 @@ static void ResolveExceptionsForMethod(MethodHelper* mh, std::set<std::pair<uint16_t, const DexFile*>>& exceptions_to_resolve) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { const DexFile::CodeItem* code_item = mh->GetMethod()->GetCodeItem(); - if (code_item == NULL) { + if (code_item == nullptr) { return; // native or abstract method } if (code_item->tries_size_ == 0) { @@ -710,7 +709,7 @@ void CompilerDriver::LoadImageClasses(TimingLogger* timings) StackHandleScope<1> hs(self); Handle<mirror::Class> klass( hs.NewHandle(class_linker->FindSystemClass(self, descriptor.c_str()))); - if (klass.Get() == NULL) { + if (klass.Get() == nullptr) { VLOG(compiler) << "Failed to find class " << descriptor; image_classes_->erase(it++); self->ClearException(); @@ -738,7 +737,7 @@ void CompilerDriver::LoadImageClasses(TimingLogger* timings) Handle<mirror::Class> klass(hs.NewHandle( class_linker->ResolveType(*dex_file, exception_type_idx, dex_cache, NullHandle<mirror::ClassLoader>()))); - if (klass.Get() == NULL) { + if (klass.Get() == nullptr) { const DexFile::TypeId& type_id = dex_file->GetTypeId(exception_type_idx); const char* descriptor = dex_file->GetTypeDescriptor(type_id); LOG(FATAL) << "Failed to resolve class " << descriptor; @@ -785,8 +784,8 @@ static void MaybeAddToImageClasses(Handle<mirror::Class> c, std::set<std::string } void CompilerDriver::FindClinitImageClassesCallback(mirror::Object* object, void* arg) { - DCHECK(object != NULL); - DCHECK(arg != NULL); + DCHECK(object != nullptr); + DCHECK(arg != nullptr); CompilerDriver* compiler_driver = reinterpret_cast<CompilerDriver*>(arg); StackHandleScope<1> hs(Thread::Current()); MaybeAddToImageClasses(hs.NewHandle(object->GetClass()), compiler_driver->image_classes_.get()); @@ -854,29 +853,29 @@ bool CompilerDriver::CanAccessTypeWithoutChecks(uint32_t referrer_idx, const Dex uint32_t type_idx, bool* type_known_final, bool* type_known_abstract, bool* equals_referrers_class) { - if (type_known_final != NULL) { + if (type_known_final != nullptr) { *type_known_final = false; } - if (type_known_abstract != NULL) { + if (type_known_abstract != nullptr) { *type_known_abstract = false; } - if (equals_referrers_class != NULL) { + if (equals_referrers_class != nullptr) { *equals_referrers_class = false; } ScopedObjectAccess soa(Thread::Current()); mirror::DexCache* dex_cache = Runtime::Current()->GetClassLinker()->FindDexCache(dex_file); // Get type from dex cache assuming it was populated by the verifier mirror::Class* resolved_class = dex_cache->GetResolvedType(type_idx); - if (resolved_class == NULL) { + if (resolved_class == nullptr) { stats_->TypeNeedsAccessCheck(); return false; // Unknown class needs access checks. } const DexFile::MethodId& method_id = dex_file.GetMethodId(referrer_idx); - if (equals_referrers_class != NULL) { + if (equals_referrers_class != nullptr) { *equals_referrers_class = (method_id.class_idx_ == type_idx); } mirror::Class* referrer_class = dex_cache->GetResolvedType(method_id.class_idx_); - if (referrer_class == NULL) { + if (referrer_class == nullptr) { stats_->TypeNeedsAccessCheck(); return false; // Incomplete referrer knowledge needs access check. } @@ -885,10 +884,10 @@ bool CompilerDriver::CanAccessTypeWithoutChecks(uint32_t referrer_idx, const Dex bool result = referrer_class->CanAccess(resolved_class); if (result) { stats_->TypeDoesntNeedAccessCheck(); - if (type_known_final != NULL) { + if (type_known_final != nullptr) { *type_known_final = resolved_class->IsFinal() && !resolved_class->IsArrayClass(); } - if (type_known_abstract != NULL) { + if (type_known_abstract != nullptr) { *type_known_abstract = resolved_class->IsAbstract() && !resolved_class->IsArrayClass(); } } else { @@ -904,13 +903,13 @@ bool CompilerDriver::CanAccessInstantiableTypeWithoutChecks(uint32_t referrer_id mirror::DexCache* dex_cache = Runtime::Current()->GetClassLinker()->FindDexCache(dex_file); // Get type from dex cache assuming it was populated by the verifier. mirror::Class* resolved_class = dex_cache->GetResolvedType(type_idx); - if (resolved_class == NULL) { + if (resolved_class == nullptr) { stats_->TypeNeedsAccessCheck(); return false; // Unknown class needs access checks. } const DexFile::MethodId& method_id = dex_file.GetMethodId(referrer_idx); mirror::Class* referrer_class = dex_cache->GetResolvedType(method_id.class_idx_); - if (referrer_class == NULL) { + if (referrer_class == nullptr) { stats_->TypeNeedsAccessCheck(); return false; // Incomplete referrer knowledge needs access check. } @@ -1310,6 +1309,10 @@ const VerifiedMethod* CompilerDriver::GetVerifiedMethod(const DexFile* dex_file, } 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. + return false; + } DCHECK(mUnit->GetVerifiedMethod() != nullptr); bool result = mUnit->GetVerifiedMethod()->IsSafeCast(dex_pc); if (result) { @@ -1410,7 +1413,7 @@ class ParallelCompilationManager { thread_pool_(thread_pool) {} ClassLinker* GetClassLinker() const { - CHECK(class_linker_ != NULL); + CHECK(class_linker_ != nullptr); return class_linker_; } @@ -1419,12 +1422,12 @@ class ParallelCompilationManager { } CompilerDriver* GetCompiler() const { - CHECK(compiler_ != NULL); + CHECK(compiler_ != nullptr); return compiler_; } const DexFile* GetDexFile() const { - CHECK(dex_file_ != NULL); + CHECK(dex_file_ != nullptr); return dex_file_; } @@ -1499,10 +1502,10 @@ class ParallelCompilationManager { // that avoids the expensive FindInClassPath search. static bool SkipClass(jobject class_loader, const DexFile& dex_file, mirror::Class* klass) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - DCHECK(klass != NULL); + DCHECK(klass != nullptr); const DexFile& original_dex_file = *klass->GetDexCache()->GetDexFile(); if (&dex_file != &original_dex_file) { - if (class_loader == NULL) { + if (class_loader == nullptr) { LOG(WARNING) << "Skipping class " << PrettyDescriptor(klass) << " from " << dex_file.GetLocation() << " previously found in " << original_dex_file.GetLocation(); @@ -1587,7 +1590,7 @@ static void ResolveClassFieldsAndMethods(const ParallelCompilationManager* manag // static fields, instance fields, direct methods, and virtual // methods. const byte* class_data = dex_file.GetClassData(class_def); - if (class_data == NULL) { + if (class_data == nullptr) { // Empty class such as a marker interface. requires_constructor_barrier = false; } else { @@ -1596,7 +1599,7 @@ static void ResolveClassFieldsAndMethods(const ParallelCompilationManager* manag if (resolve_fields_and_methods) { mirror::ArtField* field = class_linker->ResolveField(dex_file, it.GetMemberIndex(), dex_cache, class_loader, true); - if (field == NULL) { + if (field == nullptr) { CheckAndClearResolveException(soa.Self()); } } @@ -1611,7 +1614,7 @@ static void ResolveClassFieldsAndMethods(const ParallelCompilationManager* manag if (resolve_fields_and_methods) { mirror::ArtField* field = class_linker->ResolveField(dex_file, it.GetMemberIndex(), dex_cache, class_loader, false); - if (field == NULL) { + if (field == nullptr) { CheckAndClearResolveException(soa.Self()); } } @@ -1623,7 +1626,7 @@ static void ResolveClassFieldsAndMethods(const ParallelCompilationManager* manag dex_cache, class_loader, NullHandle<mirror::ArtMethod>(), it.GetMethodInvokeType(class_def)); - if (method == NULL) { + if (method == nullptr) { CheckAndClearResolveException(soa.Self()); } it.Next(); @@ -1633,7 +1636,7 @@ static void ResolveClassFieldsAndMethods(const ParallelCompilationManager* manag dex_cache, class_loader, NullHandle<mirror::ArtMethod>(), it.GetMethodInvokeType(class_def)); - if (method == NULL) { + if (method == nullptr) { CheckAndClearResolveException(soa.Self()); } it.Next(); @@ -1658,9 +1661,9 @@ static void ResolveType(const ParallelCompilationManager* manager, size_t type_i hs.NewHandle(soa.Decode<mirror::ClassLoader*>(manager->GetClassLoader()))); mirror::Class* klass = class_linker->ResolveType(dex_file, type_idx, dex_cache, class_loader); - if (klass == NULL) { + if (klass == nullptr) { CHECK(soa.Self()->IsExceptionPending()); - mirror::Throwable* exception = soa.Self()->GetException(NULL); + mirror::Throwable* exception = soa.Self()->GetException(nullptr); VLOG(compiler) << "Exception during type resolution: " << exception->Dump(); if (exception->GetClass()->DescriptorEquals("Ljava/lang/OutOfMemoryError;")) { // There's little point continuing compilation if the heap is exhausted. @@ -1691,11 +1694,20 @@ void CompilerDriver::ResolveDexFile(jobject class_loader, const DexFile& dex_fil context.ForAll(0, dex_file.NumClassDefs(), ResolveClassFieldsAndMethods, thread_count_); } +void CompilerDriver::SetVerified(jobject class_loader, const std::vector<const DexFile*>& dex_files, + ThreadPool* thread_pool, TimingLogger* timings) { + for (size_t i = 0; i != dex_files.size(); ++i) { + const DexFile* dex_file = dex_files[i]; + CHECK(dex_file != nullptr); + SetVerifiedDexFile(class_loader, *dex_file, dex_files, thread_pool, timings); + } +} + void CompilerDriver::Verify(jobject class_loader, const std::vector<const DexFile*>& dex_files, ThreadPool* thread_pool, TimingLogger* timings) { for (size_t i = 0; i != dex_files.size(); ++i) { const DexFile* dex_file = dex_files[i]; - CHECK(dex_file != NULL); + CHECK(dex_file != nullptr); VerifyDexFile(class_loader, *dex_file, dex_files, thread_pool, timings); } } @@ -1757,6 +1769,47 @@ void CompilerDriver::VerifyDexFile(jobject class_loader, const DexFile& dex_file context.ForAll(0, dex_file.NumClassDefs(), VerifyClass, thread_count_); } +static void SetVerifiedClass(const ParallelCompilationManager* manager, size_t class_def_index) + LOCKS_EXCLUDED(Locks::mutator_lock_) { + ATRACE_CALL(); + ScopedObjectAccess soa(Thread::Current()); + const DexFile& dex_file = *manager->GetDexFile(); + const DexFile::ClassDef& class_def = dex_file.GetClassDef(class_def_index); + const char* descriptor = dex_file.GetClassDescriptor(class_def); + ClassLinker* class_linker = manager->GetClassLinker(); + jobject jclass_loader = manager->GetClassLoader(); + StackHandleScope<3> hs(soa.Self()); + Handle<mirror::ClassLoader> class_loader( + hs.NewHandle(soa.Decode<mirror::ClassLoader*>(jclass_loader))); + Handle<mirror::Class> klass( + hs.NewHandle(class_linker->FindClass(soa.Self(), descriptor, class_loader))); + // Class might have failed resolution. Then don't set it to verified. + if (klass.Get() != nullptr) { + // Only do this if the class is resolved. If even resolution fails, quickening will go very, + // very wrong. + if (klass->IsResolved()) { + if (klass->GetStatus() < mirror::Class::kStatusVerified) { + ObjectLock<mirror::Class> lock(soa.Self(), klass); + klass->SetStatus(mirror::Class::kStatusVerified, soa.Self()); + } + // Record the final class status if necessary. + ClassReference ref(manager->GetDexFile(), class_def_index); + manager->GetCompiler()->RecordClassStatus(ref, klass->GetStatus()); + } + } + soa.Self()->AssertNoPendingException(); +} + +void CompilerDriver::SetVerifiedDexFile(jobject class_loader, const DexFile& dex_file, + const std::vector<const DexFile*>& dex_files, + ThreadPool* thread_pool, TimingLogger* timings) { + TimingLogger::ScopedTiming t("Verify Dex File", timings); + ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); + ParallelCompilationManager context(class_linker, class_loader, this, &dex_file, dex_files, + thread_pool); + context.ForAll(0, dex_file.NumClassDefs(), SetVerifiedClass, thread_count_); +} + static void InitializeClass(const ParallelCompilationManager* manager, size_t class_def_index) LOCKS_EXCLUDED(Locks::mutator_lock_) { ATRACE_CALL(); @@ -1865,7 +1918,7 @@ void CompilerDriver::InitializeClasses(jobject class_loader, ThreadPool* thread_pool, TimingLogger* timings) { for (size_t i = 0; i != dex_files.size(); ++i) { const DexFile* dex_file = dex_files[i]; - CHECK(dex_file != NULL); + CHECK(dex_file != nullptr); InitializeClasses(class_loader, *dex_file, dex_files, thread_pool, timings); } if (IsImage()) { @@ -1878,7 +1931,7 @@ void CompilerDriver::Compile(jobject class_loader, const std::vector<const DexFi ThreadPool* thread_pool, TimingLogger* timings) { for (size_t i = 0; i != dex_files.size(); ++i) { const DexFile* dex_file = dex_files[i]; - CHECK(dex_file != NULL); + CHECK(dex_file != nullptr); CompileDexFile(class_loader, *dex_file, dex_files, thread_pool, timings); } } @@ -1911,7 +1964,7 @@ void CompilerDriver::CompileClass(const ParallelCompilationManager* manager, siz return; } const byte* class_data = dex_file.GetClassData(class_def); - if (class_data == NULL) { + if (class_data == nullptr) { // empty class, probably a marker interface return; } @@ -1984,7 +2037,7 @@ void CompilerDriver::CompileMethod(const DexFile::CodeItem* code_item, uint32_t uint32_t method_idx, jobject class_loader, const DexFile& dex_file, DexToDexCompilationLevel dex_to_dex_compilation_level) { - CompiledMethod* compiled_method = NULL; + CompiledMethod* compiled_method = nullptr; uint64_t start_ns = kTimeCompileMethod ? NanoTime() : 0; if ((access_flags & kAccNative) != 0) { @@ -1994,14 +2047,14 @@ void CompilerDriver::CompileMethod(const DexFile::CodeItem* code_item, uint32_t // Leaving this empty will trigger the generic JNI version } else { compiled_method = compiler_->JniCompile(access_flags, method_idx, dex_file); - CHECK(compiled_method != NULL); + CHECK(compiled_method != nullptr); } } else if ((access_flags & kAccAbstract) != 0) { } else { MethodReference method_ref(&dex_file, method_idx); bool compile = verification_results_->IsCandidateForCompilation(method_ref, access_flags); if (compile) { - // NOTE: if compiler declines to compile this method, it will return NULL. + // NOTE: if compiler declines to compile this method, it will return nullptr. compiled_method = compiler_->Compile(code_item, access_flags, invoke_type, class_def_idx, method_idx, class_loader, dex_file); } @@ -2022,20 +2075,20 @@ void CompilerDriver::CompileMethod(const DexFile::CodeItem* code_item, uint32_t } Thread* self = Thread::Current(); - if (compiled_method != NULL) { + if (compiled_method != nullptr) { MethodReference ref(&dex_file, method_idx); - DCHECK(GetCompiledMethod(ref) == NULL) << PrettyMethod(method_idx, dex_file); + DCHECK(GetCompiledMethod(ref) == nullptr) << PrettyMethod(method_idx, dex_file); { MutexLock mu(self, compiled_methods_lock_); compiled_methods_.Put(ref, compiled_method); } - DCHECK(GetCompiledMethod(ref) != NULL) << PrettyMethod(method_idx, dex_file); + DCHECK(GetCompiledMethod(ref) != nullptr) << PrettyMethod(method_idx, dex_file); } if (self->IsExceptionPending()) { ScopedObjectAccess soa(self); LOG(FATAL) << "Unexpected exception compiling: " << PrettyMethod(method_idx, dex_file) << "\n" - << self->GetException(NULL)->Dump(); + << self->GetException(nullptr)->Dump(); } } @@ -2043,9 +2096,9 @@ CompiledClass* CompilerDriver::GetCompiledClass(ClassReference ref) const { MutexLock mu(Thread::Current(), compiled_classes_lock_); ClassTable::const_iterator it = compiled_classes_.find(ref); if (it == compiled_classes_.end()) { - return NULL; + return nullptr; } - CHECK(it->second != NULL); + CHECK(it->second != nullptr); return it->second; } @@ -2079,9 +2132,9 @@ CompiledMethod* CompilerDriver::GetCompiledMethod(MethodReference ref) const { MutexLock mu(Thread::Current(), compiled_methods_lock_); MethodTable::const_iterator it = compiled_methods_.find(ref); if (it == compiled_methods_.end()) { - return NULL; + return nullptr; } - CHECK(it->second != NULL); + CHECK(it->second != nullptr); return it->second; } diff --git a/compiler/driver/compiler_driver.h b/compiler/driver/compiler_driver.h index 624947d..3c76098 100644 --- a/compiler/driver/compiler_driver.h +++ b/compiler/driver/compiler_driver.h @@ -81,7 +81,7 @@ class CompilerDriver { // Create a compiler targeting the requested "instruction_set". // "image" should be true if image specific optimizations should be // enabled. "image_classes" lets the compiler know what classes it - // can assume will be in the image, with NULL implying all available + // can assume will be in the image, with nullptr implying all available // classes. explicit CompilerDriver(const CompilerOptions* compiler_options, VerificationResults* verification_results, @@ -183,9 +183,9 @@ class CompilerDriver { // Are runtime access checks necessary in the compiled code? bool CanAccessTypeWithoutChecks(uint32_t referrer_idx, const DexFile& dex_file, - uint32_t type_idx, bool* type_known_final = NULL, - bool* type_known_abstract = NULL, - bool* equals_referrers_class = NULL) + uint32_t type_idx, bool* type_known_final = nullptr, + bool* type_known_abstract = nullptr, + bool* equals_referrers_class = nullptr) LOCKS_EXCLUDED(Locks::mutator_lock_); // Are runtime access and instantiable checks necessary in the code? @@ -436,7 +436,7 @@ class CompilerDriver { referrer_class_def_idx_(referrer_class_def_idx), referrer_method_idx_(referrer_method_idx), literal_offset_(literal_offset) { - CHECK(dex_file_ != NULL); + CHECK(dex_file_ != nullptr); } virtual ~PatchInformation() {} @@ -655,6 +655,13 @@ class CompilerDriver { ThreadPool* thread_pool, TimingLogger* timings) LOCKS_EXCLUDED(Locks::mutator_lock_); + void SetVerified(jobject class_loader, const std::vector<const DexFile*>& dex_files, + ThreadPool* thread_pool, TimingLogger* timings); + void SetVerifiedDexFile(jobject class_loader, const DexFile& dex_file, + const std::vector<const DexFile*>& dex_files, + ThreadPool* thread_pool, TimingLogger* timings) + LOCKS_EXCLUDED(Locks::mutator_lock_); + void InitializeClasses(jobject class_loader, const std::vector<const DexFile*>& dex_files, ThreadPool* thread_pool, TimingLogger* timings) LOCKS_EXCLUDED(Locks::mutator_lock_); @@ -712,7 +719,7 @@ class CompilerDriver { const bool image_; // If image_ is true, specifies the classes that will be included in - // the image. Note if image_classes_ is NULL, all classes are + // the image. Note if image_classes_ is nullptr, all classes are // included in the image. std::unique_ptr<std::set<std::string>> image_classes_; |