From 6f28d91aab952e3244fbb4e707fa38f85538f374 Mon Sep 17 00:00:00 2001 From: Anwar Ghuloum Date: Wed, 24 Jul 2013 15:02:53 -0700 Subject: Add systrace support to NewTimingLogger, migrate compiler timing logging to NewTimingLogger Rpleaced old TimingLogger by NewTimingLogger, renamed NewTimingLogger to TimingLogger, added systrace support to TimingLogger. Tests passing, phone booting, systrace working. Change-Id: I2aeffb8bcb7f0fd979d8a2a3a8bcfbaa02413679 --- compiler/driver/compiler_driver.h | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) (limited to 'compiler/driver/compiler_driver.h') diff --git a/compiler/driver/compiler_driver.h b/compiler/driver/compiler_driver.h index f3f72dd3c7..a7a47ed876 100644 --- a/compiler/driver/compiler_driver.h +++ b/compiler/driver/compiler_driver.h @@ -78,11 +78,11 @@ class CompilerDriver { ~CompilerDriver(); void CompileAll(jobject class_loader, const std::vector& dex_files, - TimingLogger& timings) + base::TimingLogger& timings) LOCKS_EXCLUDED(Locks::mutator_lock_); // Compile a single Method - void CompileOne(const mirror::AbstractMethod* method, TimingLogger& timings) + void CompileOne(const mirror::AbstractMethod* method, base::TimingLogger& timings) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); InstructionSet GetInstructionSet() const { @@ -284,42 +284,42 @@ class CompilerDriver { SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); void PreCompile(jobject class_loader, const std::vector& dex_files, - ThreadPool& thread_pool, TimingLogger& timings) + ThreadPool& thread_pool, base::TimingLogger& timings) LOCKS_EXCLUDED(Locks::mutator_lock_); - void LoadImageClasses(TimingLogger& timings); + void LoadImageClasses(base::TimingLogger& timings); // Attempt to resolve all type, methods, fields, and strings // referenced from code in the dex file following PathClassLoader // ordering semantics. void Resolve(jobject class_loader, const std::vector& dex_files, - ThreadPool& thread_pool, TimingLogger& timings) + ThreadPool& thread_pool, base::TimingLogger& timings) LOCKS_EXCLUDED(Locks::mutator_lock_); void ResolveDexFile(jobject class_loader, const DexFile& dex_file, - ThreadPool& thread_pool, TimingLogger& timings) + ThreadPool& thread_pool, base::TimingLogger& timings) LOCKS_EXCLUDED(Locks::mutator_lock_); void Verify(jobject class_loader, const std::vector& dex_files, - ThreadPool& thread_pool, TimingLogger& timings); + ThreadPool& thread_pool, base::TimingLogger& timings); void VerifyDexFile(jobject class_loader, const DexFile& dex_file, - ThreadPool& thread_pool, TimingLogger& timings) + ThreadPool& thread_pool, base::TimingLogger& timings) LOCKS_EXCLUDED(Locks::mutator_lock_); void InitializeClasses(jobject class_loader, const std::vector& dex_files, - ThreadPool& thread_pool, TimingLogger& timings) + ThreadPool& thread_pool, base::TimingLogger& timings) LOCKS_EXCLUDED(Locks::mutator_lock_); void InitializeClasses(jobject class_loader, const DexFile& dex_file, - ThreadPool& thread_pool, TimingLogger& timings) + ThreadPool& thread_pool, base::TimingLogger& timings) LOCKS_EXCLUDED(Locks::mutator_lock_, compiled_classes_lock_); - void UpdateImageClasses(TimingLogger& timings); + void UpdateImageClasses(base::TimingLogger& timings); static void FindClinitImageClassesCallback(mirror::Object* object, void* arg) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); void Compile(jobject class_loader, const std::vector& dex_files, - ThreadPool& thread_pool, TimingLogger& timings); + ThreadPool& thread_pool, base::TimingLogger& timings); void CompileDexFile(jobject class_loader, const DexFile& dex_file, - ThreadPool& thread_pool, TimingLogger& timings) + ThreadPool& thread_pool, base::TimingLogger& timings) LOCKS_EXCLUDED(Locks::mutator_lock_); void CompileMethod(const DexFile::CodeItem* code_item, uint32_t access_flags, InvokeType invoke_type, uint32_t class_def_idx, uint32_t method_idx, -- cgit v1.2.3-59-g8ed1b From 75021222d9c03a80fa5c136db0d5fb8d82d04031 Mon Sep 17 00:00:00 2001 From: Sebastien Hertz Date: Tue, 16 Jul 2013 18:34:50 +0200 Subject: Adds a DEX-to-DEX compilation level. This CL adds a DEX-to-DEX compilation level which allows the DEX-to-DEX compiler to ensure correctness on classes with soft-failed verification. Bug: 9307738 Change-Id: If051336bf81370bca55872c8c75ccd573d8ca391 --- compiler/dex/dex_to_dex_compiler.cc | 35 ++++++++++++-------- compiler/driver/compiler_driver.cc | 64 +++++++++++++++++++++---------------- compiler/driver/compiler_driver.h | 17 ++++++++-- 3 files changed, 74 insertions(+), 42 deletions(-) (limited to 'compiler/driver/compiler_driver.h') diff --git a/compiler/dex/dex_to_dex_compiler.cc b/compiler/dex/dex_to_dex_compiler.cc index 3c491ce20f..1ee29cbae1 100644 --- a/compiler/dex/dex_to_dex_compiler.cc +++ b/compiler/dex/dex_to_dex_compiler.cc @@ -36,9 +36,11 @@ const bool kEnableCheckCastEllision = true; class DexCompiler { public: DexCompiler(art::CompilerDriver& compiler, - const DexCompilationUnit& unit) + const DexCompilationUnit& unit, + DexToDexCompilationLevel dex_to_dex_compilation_level) : driver_(compiler), - unit_(unit) {} + unit_(unit), + dex_to_dex_compilation_level_(dex_to_dex_compilation_level) {} ~DexCompiler() {} @@ -55,6 +57,10 @@ class DexCompiler { return *const_cast(unit_.GetDexFile()); } + bool PerformOptimizations() const { + return dex_to_dex_compilation_level_ >= kOptimize; + } + // Compiles a RETURN-VOID into a RETURN-VOID-BARRIER within a constructor where // a barrier is required. void CompileReturnVoid(Instruction* inst, uint32_t dex_pc); @@ -84,6 +90,7 @@ class DexCompiler { CompilerDriver& driver_; const DexCompilationUnit& unit_; + const DexToDexCompilationLevel dex_to_dex_compilation_level_; DISALLOW_COPY_AND_ASSIGN(DexCompiler); }; @@ -138,6 +145,7 @@ class ScopedDexWriteAccess { }; void DexCompiler::Compile() { + DCHECK_GE(dex_to_dex_compilation_level_, kRequired); const DexFile::CodeItem* code_item = unit_.GetCodeItem(); const uint16_t* insns = code_item->insns_; const uint32_t insns_size = code_item->insns_size_in_code_units_; @@ -220,7 +228,7 @@ void DexCompiler::CompileReturnVoid(Instruction* inst, uint32_t dex_pc) { } Instruction* DexCompiler::CompileCheckCast(Instruction* inst, uint32_t dex_pc) { - if (!kEnableCheckCastEllision) { + if (!kEnableCheckCastEllision || !PerformOptimizations()) { return inst; } MethodReference referrer(&GetDexFile(), unit_.GetDexMethodIndex()); @@ -253,7 +261,7 @@ void DexCompiler::CompileInstanceFieldAccess(Instruction* inst, uint32_t dex_pc, Instruction::Code new_opcode, bool is_put) { - if (!kEnableQuickening) { + if (!kEnableQuickening || !PerformOptimizations()) { return; } uint32_t field_idx = inst->VRegC_22c(); @@ -280,7 +288,7 @@ void DexCompiler::CompileInvokeVirtual(Instruction* inst, uint32_t dex_pc, Instruction::Code new_opcode, bool is_range) { - if (!kEnableQuickening) { + if (!kEnableQuickening || !PerformOptimizations()) { return; } uint32_t method_idx = is_range ? inst->VRegB_3rc() : inst->VRegB_35c(); @@ -320,14 +328,15 @@ void DexCompiler::CompileInvokeVirtual(Instruction* inst, } // namespace optimizer } // namespace art -extern "C" art::CompiledMethod* - ArtCompileDEX(art::CompilerDriver& compiler, const art::DexFile::CodeItem* code_item, +extern "C" void ArtCompileDEX(art::CompilerDriver& compiler, const art::DexFile::CodeItem* code_item, uint32_t access_flags, art::InvokeType invoke_type, uint32_t class_def_idx, uint32_t method_idx, jobject class_loader, - const art::DexFile& dex_file) { - art::DexCompilationUnit unit(NULL, class_loader, art::Runtime::Current()->GetClassLinker(), - dex_file, code_item, class_def_idx, method_idx, access_flags); - art::optimizer::DexCompiler dex_compiler(compiler, unit); - dex_compiler.Compile(); - return NULL; + const art::DexFile& dex_file, + art::DexToDexCompilationLevel dex_to_dex_compilation_level) { + if (dex_to_dex_compilation_level != art::kDontDexToDexCompile) { + art::DexCompilationUnit unit(NULL, class_loader, art::Runtime::Current()->GetClassLinker(), + dex_file, code_item, class_def_idx, method_idx, access_flags); + art::optimizer::DexCompiler dex_compiler(compiler, unit, dex_to_dex_compilation_level); + dex_compiler.Compile(); + } } diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc index 49aba4d6a9..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(ArtQuickCompileMethod); } - dex_to_dex_compiler_ = reinterpret_cast(ArtCompileDEX); + dex_to_dex_compiler_ = reinterpret_cast(ArtCompileDEX); #ifdef ART_SEA_IR_MODE sea_ir_compiler_ = NULL; @@ -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,10 +516,27 @@ 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, base::TimingLogger& timings) { @@ -556,15 +567,15 @@ void CompilerDriver::CompileOne(const mirror::AbstractMethod* method, base::Timi 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(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); @@ -2171,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(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 @@ -2198,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 @@ -2214,7 +2225,7 @@ 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()); @@ -2231,7 +2242,7 @@ void CompilerDriver::CompileMethod(const DexFile::CodeItem* code_item, uint32_t 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(); @@ -2253,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; diff --git a/compiler/driver/compiler_driver.h b/compiler/driver/compiler_driver.h index a7a47ed876..18f852dc6f 100644 --- a/compiler/driver/compiler_driver.h +++ b/compiler/driver/compiler_driver.h @@ -48,6 +48,12 @@ enum CompilerBackend { kNoBackend }; +enum DexToDexCompilationLevel { + kDontDexToDexCompile, // Only meaning wrt image time interpretation. + kRequired, // Dex-to-dex compilation required for correctness. + kOptimize // Perform required transformation and peep-hole optimizations. +}; + // Thread-local storage compiler worker threads class CompilerTls { public: @@ -324,7 +330,7 @@ class CompilerDriver { void 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) LOCKS_EXCLUDED(compiled_methods_lock_); static void CompileClass(const ParallelCompilationManager* context, size_t class_def_index) @@ -375,12 +381,19 @@ class CompilerDriver { uint32_t access_flags, InvokeType invoke_type, uint32_t class_dex_idx, uint32_t method_idx, jobject class_loader, const DexFile& dex_file); + + typedef void (*DexToDexCompilerFn)(CompilerDriver& driver, + const DexFile::CodeItem* code_item, + uint32_t access_flags, InvokeType invoke_type, + uint32_t class_dex_idx, uint32_t method_idx, + jobject class_loader, const DexFile& dex_file, + DexToDexCompilationLevel dex_to_dex_compilation_level); CompilerFn compiler_; #ifdef ART_SEA_IR_MODE CompilerFn sea_ir_compiler_; #endif - CompilerFn dex_to_dex_compiler_; + DexToDexCompilerFn dex_to_dex_compiler_; void* compiler_context_; -- cgit v1.2.3-59-g8ed1b