diff options
| author | 2013-07-31 11:26:53 -0700 | |
|---|---|---|
| committer | 2013-07-31 17:36:29 -0700 | |
| commit | 834b394ee759ed31c5371d8093d7cd8cd90014a8 (patch) | |
| tree | f6aa5056f824f7ad81c8eac11d59b54a2e3b8d46 /compiler/driver/compiler_driver.cc | |
| parent | 025218c7e4330a4942b14f9a8f1f68bd3390261c (diff) | |
Merge remote-tracking branch 'goog/dalvik-dev' into merge-art-to-dalvik-dev
Change-Id: I323e9e8c29c3e39d50d9aba93121b26266c52a46
Diffstat (limited to 'compiler/driver/compiler_driver.cc')
| -rw-r--r-- | compiler/driver/compiler_driver.cc | 119 |
1 files changed, 60 insertions, 59 deletions
diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc index 038957e128..38d00a0804 100644 --- a/compiler/driver/compiler_driver.cc +++ b/compiler/driver/compiler_driver.cc @@ -369,7 +369,7 @@ CompilerDriver::CompilerDriver(CompilerBackend compiler_backend, InstructionSet compiler_ = reinterpret_cast<CompilerFn>(ArtQuickCompileMethod); } - dex_to_dex_compiler_ = reinterpret_cast<CompilerFn>(ArtCompileDEX); + dex_to_dex_compiler_ = reinterpret_cast<DexToDexCompilerFn>(ArtCompileDEX); #ifdef ART_SEA_IR_MODE sea_ir_compiler_ = NULL; @@ -495,7 +495,7 @@ const std::vector<uint8_t>* CompilerDriver::CreateInterpreterToQuickEntry() cons void CompilerDriver::CompileAll(jobject class_loader, const std::vector<const DexFile*>& dex_files, - TimingLogger& timings) { + base::TimingLogger& timings) { DCHECK(!Runtime::Current()->IsStarted()); UniquePtr<ThreadPool> thread_pool(new ThreadPool(thread_count_)); PreCompile(class_loader, dex_files, *thread_pool.get(), timings); @@ -505,16 +505,10 @@ void CompilerDriver::CompileAll(jobject class_loader, } } -static bool IsDexToDexCompilationAllowed(mirror::ClassLoader* class_loader, - const DexFile& dex_file, - const DexFile::ClassDef& class_def) +static DexToDexCompilationLevel GetDexToDexCompilationlevel(mirror::ClassLoader* class_loader, + const DexFile& dex_file, + const DexFile::ClassDef& class_def) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - // Do not allow DEX-to-DEX compilation of image classes. This is to prevent the - // verifier from passing on "quick" instruction at compilation time. It must - // only pass on quick instructions at runtime. - if (class_loader == NULL) { - return false; - } const char* descriptor = dex_file.GetClassDescriptor(class_def); ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); mirror::Class* klass = class_linker->FindClass(descriptor, class_loader); @@ -522,13 +516,30 @@ static bool IsDexToDexCompilationAllowed(mirror::ClassLoader* class_loader, Thread* self = Thread::Current(); CHECK(self->IsExceptionPending()); self->ClearException(); - return false; + 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 == NULL); + if (compiling_image_classes) { + return kRequired; + } else if (klass->IsVerified()) { + // Class is verified so we can enable DEX-to-DEX compilation for performance. + return kOptimize; + } else if (klass->IsCompileTimeVerified()) { + // Class verification has soft-failed. Anyway, ensure at least correctness. + DCHECK_EQ(klass->GetStatus(), mirror::Class::kStatusRetryVerificationAtRuntime); + return kRequired; + } else { + // Class verification has failed: do not run DEX-to-DEX compilation. + return kDontDexToDexCompile; } - // DEX-to-DEX compilation is only allowed on preverified classes. - return klass->IsVerified(); } -void CompilerDriver::CompileOne(const mirror::AbstractMethod* method, TimingLogger& timings) { +void CompilerDriver::CompileOne(const mirror::AbstractMethod* method, base::TimingLogger& timings) { DCHECK(!Runtime::Current()->IsStarted()); Thread* self = Thread::Current(); jobject jclass_loader; @@ -556,15 +567,15 @@ void CompilerDriver::CompileOne(const mirror::AbstractMethod* method, TimingLogg uint32_t method_idx = method->GetDexMethodIndex(); const DexFile::CodeItem* code_item = dex_file->GetCodeItem(method->GetCodeItemOffset()); // Can we run DEX-to-DEX compiler on this class ? - bool allow_dex_compilation; + DexToDexCompilationLevel dex_to_dex_compilation_level = kDontDexToDexCompile; { ScopedObjectAccess soa(Thread::Current()); const DexFile::ClassDef& class_def = dex_file->GetClassDef(class_def_idx); mirror::ClassLoader* class_loader = soa.Decode<mirror::ClassLoader*>(jclass_loader); - allow_dex_compilation = IsDexToDexCompilationAllowed(class_loader, *dex_file, class_def); + dex_to_dex_compilation_level = GetDexToDexCompilationlevel(class_loader, *dex_file, class_def); } CompileMethod(code_item, method->GetAccessFlags(), method->GetInvokeType(), - class_def_idx, method_idx, jclass_loader, *dex_file, allow_dex_compilation); + class_def_idx, method_idx, jclass_loader, *dex_file, dex_to_dex_compilation_level); self->GetJniEnv()->DeleteGlobalRef(jclass_loader); @@ -572,7 +583,7 @@ void CompilerDriver::CompileOne(const mirror::AbstractMethod* method, TimingLogg } void CompilerDriver::Resolve(jobject class_loader, const std::vector<const DexFile*>& dex_files, - ThreadPool& thread_pool, TimingLogger& timings) { + ThreadPool& thread_pool, base::TimingLogger& timings) { for (size_t i = 0; i != dex_files.size(); ++i) { const DexFile* dex_file = dex_files[i]; CHECK(dex_file != NULL); @@ -581,7 +592,7 @@ void CompilerDriver::Resolve(jobject class_loader, const std::vector<const DexFi } void CompilerDriver::PreCompile(jobject class_loader, const std::vector<const DexFile*>& dex_files, - ThreadPool& thread_pool, TimingLogger& timings) { + ThreadPool& thread_pool, base::TimingLogger& timings) { LoadImageClasses(timings); Resolve(class_loader, dex_files, thread_pool, timings); @@ -666,12 +677,13 @@ static bool RecordImageClassesVisitor(mirror::Class* klass, void* arg) } // Make a list of descriptors for classes to include in the image -void CompilerDriver::LoadImageClasses(TimingLogger& timings) +void CompilerDriver::LoadImageClasses(base::TimingLogger& timings) LOCKS_EXCLUDED(Locks::mutator_lock_) { if (image_classes_.get() == NULL) { return; } + timings.NewSplit("LoadImageClasses"); // Make a first class to load all classes explicitly listed in the file Thread* self = Thread::Current(); ScopedObjectAccess soa(self); @@ -726,7 +738,6 @@ void CompilerDriver::LoadImageClasses(TimingLogger& timings) class_linker->VisitClasses(RecordImageClassesVisitor, image_classes_.get()); CHECK_NE(image_classes_->size(), 0U); - timings.AddSplit("LoadImageClasses"); } static void MaybeAddToImageClasses(mirror::Class* klass, CompilerDriver::DescriptorSet* image_classes) @@ -758,11 +769,13 @@ void CompilerDriver::FindClinitImageClassesCallback(mirror::Object* object, void MaybeAddToImageClasses(object->GetClass(), compiler_driver->image_classes_.get()); } -void CompilerDriver::UpdateImageClasses(TimingLogger& timings) { +void CompilerDriver::UpdateImageClasses(base::TimingLogger& timings) { if (image_classes_.get() == NULL) { return; } + timings.NewSplit("UpdateImageClasses"); + // Update image_classes_ with classes for objects created by <clinit> methods. Thread* self = Thread::Current(); const char* old_cause = self->StartAssertNoThreadSuspension("ImageWriter"); @@ -772,7 +785,6 @@ void CompilerDriver::UpdateImageClasses(TimingLogger& timings) { heap->FlushAllocStack(); heap->GetLiveBitmap()->Walk(FindClinitImageClassesCallback, this); self->EndAssertNoThreadSuspension(old_cause); - timings.AddSplit("UpdateImageClasses"); } void CompilerDriver::RecordClassStatus(ClassReference ref, CompiledClass* compiled_class) { @@ -1551,22 +1563,22 @@ static void ResolveType(const ParallelCompilationManager* manager, size_t type_i } void CompilerDriver::ResolveDexFile(jobject class_loader, const DexFile& dex_file, - ThreadPool& thread_pool, TimingLogger& timings) { + ThreadPool& thread_pool, base::TimingLogger& timings) { ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); // TODO: we could resolve strings here, although the string table is largely filled with class // and method names. + timings.NewSplit(strdup(("Resolve " + dex_file.GetLocation() + " Types").c_str())); ParallelCompilationManager context(class_linker, class_loader, this, &dex_file, thread_pool); context.ForAll(0, dex_file.NumTypeIds(), ResolveType, thread_count_); - timings.AddSplit("Resolve " + dex_file.GetLocation() + " Types"); + timings.NewSplit(strdup(("Resolve " + dex_file.GetLocation() + " MethodsAndFields").c_str())); context.ForAll(0, dex_file.NumClassDefs(), ResolveClassFieldsAndMethods, thread_count_); - timings.AddSplit("Resolve " + dex_file.GetLocation() + " MethodsAndFields"); } void CompilerDriver::Verify(jobject class_loader, const std::vector<const DexFile*>& dex_files, - ThreadPool& thread_pool, TimingLogger& timings) { + ThreadPool& thread_pool, base::TimingLogger& timings) { for (size_t i = 0; i != dex_files.size(); ++i) { const DexFile* dex_file = dex_files[i]; CHECK(dex_file != NULL); @@ -1620,11 +1632,11 @@ static void VerifyClass(const ParallelCompilationManager* manager, size_t class_ } void CompilerDriver::VerifyDexFile(jobject class_loader, const DexFile& dex_file, - ThreadPool& thread_pool, TimingLogger& timings) { + ThreadPool& thread_pool, base::TimingLogger& timings) { + timings.NewSplit(strdup(("Verify " + dex_file.GetLocation()).c_str())); ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); ParallelCompilationManager context(class_linker, class_loader, this, &dex_file, thread_pool); context.ForAll(0, dex_file.NumClassDefs(), VerifyClass, thread_count_); - timings.AddSplit("Verify " + dex_file.GetLocation()); } static const char* class_initializer_black_list[] = { @@ -2116,7 +2128,8 @@ static void InitializeClass(const ParallelCompilationManager* manager, size_t cl } void CompilerDriver::InitializeClasses(jobject jni_class_loader, const DexFile& dex_file, - ThreadPool& thread_pool, TimingLogger& timings) { + ThreadPool& thread_pool, base::TimingLogger& timings) { + timings.NewSplit(strdup(("InitializeNoClinit " + dex_file.GetLocation()).c_str())); #ifndef NDEBUG for (size_t i = 0; i < arraysize(class_initializer_black_list); ++i) { const char* descriptor = class_initializer_black_list[i]; @@ -2126,12 +2139,11 @@ void CompilerDriver::InitializeClasses(jobject jni_class_loader, const DexFile& ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); ParallelCompilationManager context(class_linker, jni_class_loader, this, &dex_file, thread_pool); context.ForAll(0, dex_file.NumClassDefs(), InitializeClass, thread_count_); - timings.AddSplit("InitializeNoClinit " + dex_file.GetLocation()); } void CompilerDriver::InitializeClasses(jobject class_loader, const std::vector<const DexFile*>& dex_files, - ThreadPool& thread_pool, TimingLogger& timings) { + ThreadPool& thread_pool, base::TimingLogger& timings) { for (size_t i = 0; i != dex_files.size(); ++i) { const DexFile* dex_file = dex_files[i]; CHECK(dex_file != NULL); @@ -2140,7 +2152,7 @@ void CompilerDriver::InitializeClasses(jobject class_loader, } void CompilerDriver::Compile(jobject class_loader, const std::vector<const DexFile*>& dex_files, - ThreadPool& thread_pool, TimingLogger& timings) { + ThreadPool& thread_pool, base::TimingLogger& timings) { for (size_t i = 0; i != dex_files.size(); ++i) { const DexFile* dex_file = dex_files[i]; CHECK(dex_file != NULL); @@ -2170,11 +2182,11 @@ void CompilerDriver::CompileClass(const ParallelCompilationManager* manager, siz return; } // Can we run DEX-to-DEX compiler on this class ? - bool allow_dex_compilation; + DexToDexCompilationLevel dex_to_dex_compilation_level = kDontDexToDexCompile; { ScopedObjectAccess soa(Thread::Current()); mirror::ClassLoader* class_loader = soa.Decode<mirror::ClassLoader*>(jclass_loader); - allow_dex_compilation = IsDexToDexCompilationAllowed(class_loader, dex_file, class_def); + dex_to_dex_compilation_level = GetDexToDexCompilationlevel(class_loader, dex_file, class_def); } ClassDataItemIterator it(dex_file, class_data); // Skip fields @@ -2197,7 +2209,7 @@ void CompilerDriver::CompileClass(const ParallelCompilationManager* manager, siz previous_direct_method_idx = method_idx; manager->GetCompiler()->CompileMethod(it.GetMethodCodeItem(), it.GetMemberAccessFlags(), it.GetMethodInvokeType(class_def), class_def_index, - method_idx, jclass_loader, dex_file, allow_dex_compilation); + method_idx, jclass_loader, dex_file, dex_to_dex_compilation_level); it.Next(); } // Compile virtual methods @@ -2213,24 +2225,24 @@ void CompilerDriver::CompileClass(const ParallelCompilationManager* manager, siz previous_virtual_method_idx = method_idx; manager->GetCompiler()->CompileMethod(it.GetMethodCodeItem(), it.GetMemberAccessFlags(), it.GetMethodInvokeType(class_def), class_def_index, - method_idx, jclass_loader, dex_file, allow_dex_compilation); + method_idx, jclass_loader, dex_file, dex_to_dex_compilation_level); it.Next(); } DCHECK(!it.HasNext()); } void CompilerDriver::CompileDexFile(jobject class_loader, const DexFile& dex_file, - ThreadPool& thread_pool, TimingLogger& timings) { + ThreadPool& thread_pool, base::TimingLogger& timings) { + timings.NewSplit(strdup(("Compile " + dex_file.GetLocation()).c_str())); ParallelCompilationManager context(NULL, class_loader, this, &dex_file, thread_pool); context.ForAll(0, dex_file.NumClassDefs(), CompilerDriver::CompileClass, thread_count_); - timings.AddSplit("Compile " + dex_file.GetLocation()); } void CompilerDriver::CompileMethod(const DexFile::CodeItem* code_item, uint32_t access_flags, InvokeType invoke_type, uint32_t class_def_idx, uint32_t method_idx, jobject class_loader, const DexFile& dex_file, - bool allow_dex_to_dex_compilation) { + DexToDexCompilationLevel dex_to_dex_compilation_level) { CompiledMethod* compiled_method = NULL; uint64_t start_ns = NanoTime(); @@ -2239,18 +2251,8 @@ void CompilerDriver::CompileMethod(const DexFile::CodeItem* code_item, uint32_t CHECK(compiled_method != NULL); } else if ((access_flags & kAccAbstract) != 0) { } else { - // In small mode we only compile image classes. - bool dont_compile = (Runtime::Current()->IsSmallMode() && - ((image_classes_.get() == NULL) || (image_classes_->size() == 0))); - - // Don't compile class initializers, ever. - if (((access_flags & kAccConstructor) != 0) && ((access_flags & kAccStatic) != 0)) { - dont_compile = true; - } else if (code_item->insns_size_in_code_units_ < Runtime::Current()->GetSmallModeMethodDexSizeLimit()) { - // Do compile small methods. - dont_compile = false; - } - if (!dont_compile) { + bool compile = verifier::MethodVerifier::IsCandidateForCompilation(code_item, access_flags); + if (compile) { CompilerFn compiler = compiler_; #ifdef ART_SEA_IR_MODE bool use_sea = Runtime::Current()->IsSeaIRMode(); @@ -2262,13 +2264,12 @@ void CompilerDriver::CompileMethod(const DexFile::CodeItem* code_item, uint32_t compiled_method = (*compiler)(*this, code_item, access_flags, invoke_type, class_def_idx, method_idx, class_loader, dex_file); CHECK(compiled_method != NULL) << PrettyMethod(method_idx, dex_file); - } else if (allow_dex_to_dex_compilation) { + } else if (dex_to_dex_compilation_level != kDontDexToDexCompile) { // TODO: add a mode to disable DEX-to-DEX compilation ? - compiled_method = (*dex_to_dex_compiler_)(*this, code_item, access_flags, - invoke_type, class_def_idx, - method_idx, class_loader, dex_file); - // No native code is generated. - CHECK(compiled_method == NULL) << PrettyMethod(method_idx, dex_file); + (*dex_to_dex_compiler_)(*this, code_item, access_flags, + invoke_type, class_def_idx, + method_idx, class_loader, dex_file, + dex_to_dex_compilation_level); } } uint64_t duration_ns = NanoTime() - start_ns; |