diff options
-rw-r--r-- | compiler/dex/mir_graph.cc | 6 | ||||
-rw-r--r-- | compiler/dex/mir_graph.h | 3 | ||||
-rw-r--r-- | compiler/dex/pass_driver_me_opts.cc | 2 | ||||
-rw-r--r-- | compiler/dex/pass_driver_me_opts.h | 8 | ||||
-rw-r--r-- | compiler/dex/quick/quick_compiler.cc | 2 | ||||
-rw-r--r-- | compiler/optimizing/optimizing_compiler.cc | 98 |
6 files changed, 78 insertions, 41 deletions
diff --git a/compiler/dex/mir_graph.cc b/compiler/dex/mir_graph.cc index f354a49..3103f96 100644 --- a/compiler/dex/mir_graph.cc +++ b/compiler/dex/mir_graph.cc @@ -2459,11 +2459,9 @@ BasicBlock* MIRGraph::CreateNewBB(BBType block_type) { return res; } -void MIRGraph::CalculateBasicBlockInformation() { - auto* quick_compiler = down_cast<QuickCompiler*>(cu_->compiler_driver->GetCompiler()); - DCHECK(quick_compiler != nullptr); +void MIRGraph::CalculateBasicBlockInformation(const PassManager* const post_opt_pass_manager) { /* Create the pass driver and launch it */ - PassDriverMEPostOpt driver(quick_compiler->GetPostOptPassManager(), cu_); + PassDriverMEPostOpt driver(post_opt_pass_manager, cu_); driver.Launch(); } diff --git a/compiler/dex/mir_graph.h b/compiler/dex/mir_graph.h index 3dae5b4..9da39d1 100644 --- a/compiler/dex/mir_graph.h +++ b/compiler/dex/mir_graph.h @@ -38,6 +38,7 @@ class DexCompilationUnit; class DexFileMethodInliner; class GlobalValueNumbering; class GvnDeadCodeElimination; +class PassManager; // Forward declaration. class MIRGraph; @@ -1201,7 +1202,7 @@ class MIRGraph { void AllocateSSAUseData(MIR *mir, int num_uses); void AllocateSSADefData(MIR *mir, int num_defs); - void CalculateBasicBlockInformation(); + void CalculateBasicBlockInformation(const PassManager* const post_opt); void ComputeDFSOrders(); void ComputeDefBlockMatrix(); void ComputeDominators(); diff --git a/compiler/dex/pass_driver_me_opts.cc b/compiler/dex/pass_driver_me_opts.cc index 320d06a..2e871da 100644 --- a/compiler/dex/pass_driver_me_opts.cc +++ b/compiler/dex/pass_driver_me_opts.cc @@ -66,7 +66,7 @@ void PassDriverMEOpts::ApplyPass(PassDataHolder* data, const Pass* pass) { // Is it dirty at least? if (pass_me_data_holder->dirty == true) { CompilationUnit* c_unit = pass_me_data_holder->c_unit; - c_unit->mir_graph.get()->CalculateBasicBlockInformation(); + c_unit->mir_graph.get()->CalculateBasicBlockInformation(post_opt_pass_manager_); } } } diff --git a/compiler/dex/pass_driver_me_opts.h b/compiler/dex/pass_driver_me_opts.h index b930d02..e94c189 100644 --- a/compiler/dex/pass_driver_me_opts.h +++ b/compiler/dex/pass_driver_me_opts.h @@ -29,8 +29,10 @@ class PassManager; class PassDriverMEOpts : public PassDriverME { public: - explicit PassDriverMEOpts(const PassManager* const manager, CompilationUnit* cu) - : PassDriverME(manager, cu) { + explicit PassDriverMEOpts(const PassManager* const manager, + const PassManager* const post_opt_pass_manager, + CompilationUnit* cu) + : PassDriverME(manager, cu), post_opt_pass_manager_(post_opt_pass_manager) { } ~PassDriverMEOpts() { @@ -45,6 +47,8 @@ class PassDriverMEOpts : public PassDriverME { * @brief Apply a patch: perform start/work/end functions. */ virtual void ApplyPass(PassDataHolder* data, const Pass* pass) OVERRIDE; + + const PassManager* const post_opt_pass_manager_; }; } // namespace art diff --git a/compiler/dex/quick/quick_compiler.cc b/compiler/dex/quick/quick_compiler.cc index 02d74a0..922f2f7 100644 --- a/compiler/dex/quick/quick_compiler.cc +++ b/compiler/dex/quick/quick_compiler.cc @@ -708,7 +708,7 @@ CompiledMethod* QuickCompiler::Compile(const DexFile::CodeItem* code_item, } /* Create the pass driver and launch it */ - PassDriverMEOpts pass_driver(GetPreOptPassManager(), &cu); + PassDriverMEOpts pass_driver(GetPreOptPassManager(), GetPostOptPassManager(), &cu); pass_driver.Launch(); /* For non-leaf methods check if we should skip compilation when the profiler is enabled. */ diff --git a/compiler/optimizing/optimizing_compiler.cc b/compiler/optimizing/optimizing_compiler.cc index e47b4f6..b70f925 100644 --- a/compiler/optimizing/optimizing_compiler.cc +++ b/compiler/optimizing/optimizing_compiler.cc @@ -173,24 +173,40 @@ class OptimizingCompiler FINAL : public Compiler { jobject class_loader, const DexFile& dex_file) const OVERRIDE; + CompiledMethod* TryCompile(const DexFile::CodeItem* code_item, + uint32_t access_flags, + InvokeType invoke_type, + uint16_t class_def_idx, + uint32_t method_idx, + jobject class_loader, + const DexFile& dex_file) const; + CompiledMethod* JniCompile(uint32_t access_flags, uint32_t method_idx, - const DexFile& dex_file) const OVERRIDE; + const DexFile& dex_file) const OVERRIDE { + return ArtQuickJniCompileMethod(GetCompilerDriver(), access_flags, method_idx, dex_file); + } uintptr_t GetEntryPointOf(mirror::ArtMethod* method) const OVERRIDE - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + return reinterpret_cast<uintptr_t>(method->GetEntryPointFromQuickCompiledCodePtrSize( + InstructionSetPointerSize(GetCompilerDriver()->GetInstructionSet()))); + } bool WriteElf(art::File* file, OatWriter* oat_writer, const std::vector<const art::DexFile*>& dex_files, const std::string& android_root, - bool is_host) const OVERRIDE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + bool is_host) const OVERRIDE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + return art::ElfWriterQuick32::Create(file, oat_writer, dex_files, android_root, is_host, + *GetCompilerDriver()); + } - void InitCompilationUnit(CompilationUnit& cu ATTRIBUTE_UNUSED) const OVERRIDE {} + void InitCompilationUnit(CompilationUnit& cu) const OVERRIDE; void Init() OVERRIDE; - void UnInit() const OVERRIDE {} + void UnInit() const OVERRIDE; private: // Whether we should run any optimization or register allocation. If false, will @@ -214,6 +230,9 @@ class OptimizingCompiler FINAL : public Compiler { std::unique_ptr<std::ostream> visualizer_output_; + // Delegate to Quick in case the optimizing compiler cannot compile a method. + std::unique_ptr<Compiler> delegate_; + DISALLOW_COPY_AND_ASSIGN(OptimizingCompiler); }; @@ -224,9 +243,11 @@ OptimizingCompiler::OptimizingCompiler(CompilerDriver* driver) run_optimizations_( (driver->GetCompilerOptions().GetCompilerFilter() != CompilerOptions::kTime) && !driver->GetCompilerOptions().GetDebuggable()), - compilation_stats_() {} + compilation_stats_(), + delegate_(Create(driver, Compiler::Kind::kQuick)) {} void OptimizingCompiler::Init() { + delegate_->Init(); // Enable C1visualizer output. Must be done in Init() because the compiler // driver is not fully initialized when passed to the compiler's constructor. CompilerDriver* driver = GetCompilerDriver(); @@ -239,34 +260,24 @@ void OptimizingCompiler::Init() { } } +void OptimizingCompiler::UnInit() const { + delegate_->UnInit(); +} + OptimizingCompiler::~OptimizingCompiler() { compilation_stats_.Log(); } +void OptimizingCompiler::InitCompilationUnit(CompilationUnit& cu) const { + delegate_->InitCompilationUnit(cu); +} + bool OptimizingCompiler::CanCompileMethod(uint32_t method_idx ATTRIBUTE_UNUSED, const DexFile& dex_file ATTRIBUTE_UNUSED, CompilationUnit* cu ATTRIBUTE_UNUSED) const { return true; } -CompiledMethod* OptimizingCompiler::JniCompile(uint32_t access_flags, - uint32_t method_idx, - const DexFile& dex_file) const { - return ArtQuickJniCompileMethod(GetCompilerDriver(), access_flags, method_idx, dex_file); -} - -uintptr_t OptimizingCompiler::GetEntryPointOf(mirror::ArtMethod* method) const { - return reinterpret_cast<uintptr_t>(method->GetEntryPointFromQuickCompiledCodePtrSize( - InstructionSetPointerSize(GetCompilerDriver()->GetInstructionSet()))); -} - -bool OptimizingCompiler::WriteElf(art::File* file, OatWriter* oat_writer, - const std::vector<const art::DexFile*>& dex_files, - const std::string& android_root, bool is_host) const { - return art::ElfWriterQuick32::Create(file, oat_writer, dex_files, android_root, is_host, - *GetCompilerDriver()); -} - static bool IsInstructionSetSupported(InstructionSet instruction_set) { return instruction_set == kArm64 || (instruction_set == kThumb2 && !kArm32QuickCodeUseSoftFloat) @@ -422,13 +433,13 @@ CompiledMethod* OptimizingCompiler::CompileBaseline( ArrayRef<const uint8_t>()); } -CompiledMethod* OptimizingCompiler::Compile(const DexFile::CodeItem* code_item, - uint32_t access_flags, - InvokeType invoke_type, - uint16_t class_def_idx, - uint32_t method_idx, - jobject class_loader, - const DexFile& dex_file) const { +CompiledMethod* OptimizingCompiler::TryCompile(const DexFile::CodeItem* code_item, + uint32_t access_flags, + InvokeType invoke_type, + uint16_t class_def_idx, + uint32_t method_idx, + jobject class_loader, + const DexFile& dex_file) const { UNUSED(invoke_type); std::string method_name = PrettyMethod(method_idx, dex_file); compilation_stats_.RecordStat(MethodCompilationStat::kAttemptCompilation); @@ -502,6 +513,11 @@ CompiledMethod* OptimizingCompiler::Compile(const DexFile::CodeItem* code_item, bool can_optimize = CanOptimize(*code_item); bool can_allocate_registers = RegisterAllocator::CanAllocateRegistersFor(*graph, instruction_set); + + // `run_optimizations_` is set explicitly (either through a compiler filter + // or the debuggable flag). If it is set, we can run baseline. Otherwise, we fall back + // to Quick. + bool can_use_baseline = !run_optimizations_; if (run_optimizations_ && can_optimize && can_allocate_registers) { VLOG(compiler) << "Optimizing " << method_name; @@ -524,7 +540,7 @@ CompiledMethod* OptimizingCompiler::Compile(const DexFile::CodeItem* code_item, } else if (shouldOptimize && can_allocate_registers) { LOG(FATAL) << "Could not allocate registers in optimizing compiler"; UNREACHABLE(); - } else { + } else if (can_use_baseline) { VLOG(compiler) << "Compile baseline " << method_name; if (!run_optimizations_) { @@ -536,7 +552,25 @@ CompiledMethod* OptimizingCompiler::Compile(const DexFile::CodeItem* code_item, } return CompileBaseline(codegen.get(), compiler_driver, dex_compilation_unit); + } else { + return nullptr; + } +} + +CompiledMethod* OptimizingCompiler::Compile(const DexFile::CodeItem* code_item, + uint32_t access_flags, + InvokeType invoke_type, + uint16_t class_def_idx, + uint32_t method_idx, + jobject class_loader, + const DexFile& dex_file) const { + CompiledMethod* method = TryCompile(code_item, access_flags, invoke_type, class_def_idx, + method_idx, class_loader, dex_file); + if (method != nullptr) { + return method; } + return delegate_->Compile(code_item, access_flags, invoke_type, class_def_idx, method_idx, + class_loader, dex_file); } Compiler* CreateOptimizingCompiler(CompilerDriver* driver) { |