Home | History | Annotate | Download | only in optimizing
      1 /*
      2  * Copyright (C) 2014 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include "optimizing_compiler.h"
     18 
     19 #include <fstream>
     20 #include <memory>
     21 #include <sstream>
     22 
     23 #include <stdint.h>
     24 
     25 #include "art_method-inl.h"
     26 #include "base/arena_allocator.h"
     27 #include "base/arena_containers.h"
     28 #include "base/dumpable.h"
     29 #include "base/macros.h"
     30 #include "base/mutex.h"
     31 #include "base/scoped_arena_allocator.h"
     32 #include "base/timing_logger.h"
     33 #include "builder.h"
     34 #include "code_generator.h"
     35 #include "compiled_method.h"
     36 #include "compiler.h"
     37 #include "debug/elf_debug_writer.h"
     38 #include "debug/method_debug_info.h"
     39 #include "dex/dex_file_types.h"
     40 #include "dex/verification_results.h"
     41 #include "dex/verified_method.h"
     42 #include "driver/compiler_driver-inl.h"
     43 #include "driver/compiler_options.h"
     44 #include "driver/dex_compilation_unit.h"
     45 #include "graph_checker.h"
     46 #include "graph_visualizer.h"
     47 #include "inliner.h"
     48 #include "jit/debugger_interface.h"
     49 #include "jit/jit.h"
     50 #include "jit/jit_code_cache.h"
     51 #include "jit/jit_logger.h"
     52 #include "jni/quick/jni_compiler.h"
     53 #include "linker/linker_patch.h"
     54 #include "nodes.h"
     55 #include "oat_quick_method_header.h"
     56 #include "prepare_for_register_allocation.h"
     57 #include "reference_type_propagation.h"
     58 #include "register_allocator_linear_scan.h"
     59 #include "select_generator.h"
     60 #include "ssa_builder.h"
     61 #include "ssa_liveness_analysis.h"
     62 #include "ssa_phi_elimination.h"
     63 #include "utils/assembler.h"
     64 #include "verifier/verifier_compiler_binding.h"
     65 
     66 namespace art {
     67 
     68 static constexpr size_t kArenaAllocatorMemoryReportThreshold = 8 * MB;
     69 
     70 static constexpr const char* kPassNameSeparator = "$";
     71 
     72 /**
     73  * Used by the code generator, to allocate the code in a vector.
     74  */
     75 class CodeVectorAllocator FINAL : public CodeAllocator {
     76  public:
     77   explicit CodeVectorAllocator(ArenaAllocator* allocator)
     78       : memory_(allocator->Adapter(kArenaAllocCodeBuffer)),
     79         size_(0) {}
     80 
     81   virtual uint8_t* Allocate(size_t size) {
     82     size_ = size;
     83     memory_.resize(size);
     84     return &memory_[0];
     85   }
     86 
     87   size_t GetSize() const { return size_; }
     88   const ArenaVector<uint8_t>& GetMemory() const { return memory_; }
     89   uint8_t* GetData() { return memory_.data(); }
     90 
     91  private:
     92   ArenaVector<uint8_t> memory_;
     93   size_t size_;
     94 
     95   DISALLOW_COPY_AND_ASSIGN(CodeVectorAllocator);
     96 };
     97 
     98 /**
     99  * Filter to apply to the visualizer. Methods whose name contain that filter will
    100  * be dumped.
    101  */
    102 static constexpr const char kStringFilter[] = "";
    103 
    104 class PassScope;
    105 
    106 class PassObserver : public ValueObject {
    107  public:
    108   PassObserver(HGraph* graph,
    109                CodeGenerator* codegen,
    110                std::ostream* visualizer_output,
    111                CompilerDriver* compiler_driver,
    112                Mutex& dump_mutex)
    113       : graph_(graph),
    114         cached_method_name_(),
    115         timing_logger_enabled_(compiler_driver->GetCompilerOptions().GetDumpTimings()),
    116         timing_logger_(timing_logger_enabled_ ? GetMethodName() : "", true, true),
    117         disasm_info_(graph->GetAllocator()),
    118         visualizer_oss_(),
    119         visualizer_output_(visualizer_output),
    120         visualizer_enabled_(!compiler_driver->GetCompilerOptions().GetDumpCfgFileName().empty()),
    121         visualizer_(&visualizer_oss_, graph, *codegen),
    122         visualizer_dump_mutex_(dump_mutex),
    123         graph_in_bad_state_(false) {
    124     if (timing_logger_enabled_ || visualizer_enabled_) {
    125       if (!IsVerboseMethod(compiler_driver, GetMethodName())) {
    126         timing_logger_enabled_ = visualizer_enabled_ = false;
    127       }
    128       if (visualizer_enabled_) {
    129         visualizer_.PrintHeader(GetMethodName());
    130         codegen->SetDisassemblyInformation(&disasm_info_);
    131       }
    132     }
    133   }
    134 
    135   ~PassObserver() {
    136     if (timing_logger_enabled_) {
    137       LOG(INFO) << "TIMINGS " << GetMethodName();
    138       LOG(INFO) << Dumpable<TimingLogger>(timing_logger_);
    139     }
    140     DCHECK(visualizer_oss_.str().empty());
    141   }
    142 
    143   void DumpDisassembly() REQUIRES(!visualizer_dump_mutex_) {
    144     if (visualizer_enabled_) {
    145       visualizer_.DumpGraphWithDisassembly();
    146       FlushVisualizer();
    147     }
    148   }
    149 
    150   void SetGraphInBadState() { graph_in_bad_state_ = true; }
    151 
    152   const char* GetMethodName() {
    153     // PrettyMethod() is expensive, so we delay calling it until we actually have to.
    154     if (cached_method_name_.empty()) {
    155       cached_method_name_ = graph_->GetDexFile().PrettyMethod(graph_->GetMethodIdx());
    156     }
    157     return cached_method_name_.c_str();
    158   }
    159 
    160  private:
    161   void StartPass(const char* pass_name) REQUIRES(!visualizer_dump_mutex_) {
    162     VLOG(compiler) << "Starting pass: " << pass_name;
    163     // Dump graph first, then start timer.
    164     if (visualizer_enabled_) {
    165       visualizer_.DumpGraph(pass_name, /* is_after_pass */ false, graph_in_bad_state_);
    166       FlushVisualizer();
    167     }
    168     if (timing_logger_enabled_) {
    169       timing_logger_.StartTiming(pass_name);
    170     }
    171   }
    172 
    173   void FlushVisualizer() REQUIRES(!visualizer_dump_mutex_) {
    174     MutexLock mu(Thread::Current(), visualizer_dump_mutex_);
    175     *visualizer_output_ << visualizer_oss_.str();
    176     visualizer_output_->flush();
    177     visualizer_oss_.str("");
    178     visualizer_oss_.clear();
    179   }
    180 
    181   void EndPass(const char* pass_name) REQUIRES(!visualizer_dump_mutex_) {
    182     // Pause timer first, then dump graph.
    183     if (timing_logger_enabled_) {
    184       timing_logger_.EndTiming();
    185     }
    186     if (visualizer_enabled_) {
    187       visualizer_.DumpGraph(pass_name, /* is_after_pass */ true, graph_in_bad_state_);
    188       FlushVisualizer();
    189     }
    190 
    191     // Validate the HGraph if running in debug mode.
    192     if (kIsDebugBuild) {
    193       if (!graph_in_bad_state_) {
    194         GraphChecker checker(graph_);
    195         checker.Run();
    196         if (!checker.IsValid()) {
    197           LOG(FATAL) << "Error after " << pass_name << ": " << Dumpable<GraphChecker>(checker);
    198         }
    199       }
    200     }
    201   }
    202 
    203   static bool IsVerboseMethod(CompilerDriver* compiler_driver, const char* method_name) {
    204     // Test an exact match to --verbose-methods. If verbose-methods is set, this overrides an
    205     // empty kStringFilter matching all methods.
    206     if (compiler_driver->GetCompilerOptions().HasVerboseMethods()) {
    207       return compiler_driver->GetCompilerOptions().IsVerboseMethod(method_name);
    208     }
    209 
    210     // Test the kStringFilter sub-string. constexpr helper variable to silence unreachable-code
    211     // warning when the string is empty.
    212     constexpr bool kStringFilterEmpty = arraysize(kStringFilter) <= 1;
    213     if (kStringFilterEmpty || strstr(method_name, kStringFilter) != nullptr) {
    214       return true;
    215     }
    216 
    217     return false;
    218   }
    219 
    220   HGraph* const graph_;
    221 
    222   std::string cached_method_name_;
    223 
    224   bool timing_logger_enabled_;
    225   TimingLogger timing_logger_;
    226 
    227   DisassemblyInformation disasm_info_;
    228 
    229   std::ostringstream visualizer_oss_;
    230   std::ostream* visualizer_output_;
    231   bool visualizer_enabled_;
    232   HGraphVisualizer visualizer_;
    233   Mutex& visualizer_dump_mutex_;
    234 
    235   // Flag to be set by the compiler if the pass failed and the graph is not
    236   // expected to validate.
    237   bool graph_in_bad_state_;
    238 
    239   friend PassScope;
    240 
    241   DISALLOW_COPY_AND_ASSIGN(PassObserver);
    242 };
    243 
    244 class PassScope : public ValueObject {
    245  public:
    246   PassScope(const char *pass_name, PassObserver* pass_observer)
    247       : pass_name_(pass_name),
    248         pass_observer_(pass_observer) {
    249     pass_observer_->StartPass(pass_name_);
    250   }
    251 
    252   ~PassScope() {
    253     pass_observer_->EndPass(pass_name_);
    254   }
    255 
    256  private:
    257   const char* const pass_name_;
    258   PassObserver* const pass_observer_;
    259 };
    260 
    261 class OptimizingCompiler FINAL : public Compiler {
    262  public:
    263   explicit OptimizingCompiler(CompilerDriver* driver);
    264   ~OptimizingCompiler() OVERRIDE;
    265 
    266   bool CanCompileMethod(uint32_t method_idx, const DexFile& dex_file) const OVERRIDE;
    267 
    268   CompiledMethod* Compile(const DexFile::CodeItem* code_item,
    269                           uint32_t access_flags,
    270                           InvokeType invoke_type,
    271                           uint16_t class_def_idx,
    272                           uint32_t method_idx,
    273                           Handle<mirror::ClassLoader> class_loader,
    274                           const DexFile& dex_file,
    275                           Handle<mirror::DexCache> dex_cache) const OVERRIDE;
    276 
    277   CompiledMethod* JniCompile(uint32_t access_flags,
    278                              uint32_t method_idx,
    279                              const DexFile& dex_file,
    280                              Handle<mirror::DexCache> dex_cache) const OVERRIDE;
    281 
    282   uintptr_t GetEntryPointOf(ArtMethod* method) const OVERRIDE
    283       REQUIRES_SHARED(Locks::mutator_lock_) {
    284     return reinterpret_cast<uintptr_t>(method->GetEntryPointFromQuickCompiledCodePtrSize(
    285         InstructionSetPointerSize(GetCompilerDriver()->GetInstructionSet())));
    286   }
    287 
    288   void Init() OVERRIDE;
    289 
    290   void UnInit() const OVERRIDE;
    291 
    292   bool JitCompile(Thread* self,
    293                   jit::JitCodeCache* code_cache,
    294                   ArtMethod* method,
    295                   bool osr,
    296                   jit::JitLogger* jit_logger)
    297       OVERRIDE
    298       REQUIRES_SHARED(Locks::mutator_lock_);
    299 
    300  private:
    301   void RunOptimizations(HGraph* graph,
    302                         CodeGenerator* codegen,
    303                         const DexCompilationUnit& dex_compilation_unit,
    304                         PassObserver* pass_observer,
    305                         VariableSizedHandleScope* handles,
    306                         const OptimizationDef definitions[],
    307                         size_t length) const {
    308     // Convert definitions to optimization passes.
    309     ArenaVector<HOptimization*> optimizations = ConstructOptimizations(
    310         definitions,
    311         length,
    312         graph->GetAllocator(),
    313         graph,
    314         compilation_stats_.get(),
    315         codegen,
    316         GetCompilerDriver(),
    317         dex_compilation_unit,
    318         handles);
    319     DCHECK_EQ(length, optimizations.size());
    320     // Run the optimization passes one by one.
    321     for (size_t i = 0; i < length; ++i) {
    322       PassScope scope(optimizations[i]->GetPassName(), pass_observer);
    323       optimizations[i]->Run();
    324     }
    325   }
    326 
    327   template <size_t length> void RunOptimizations(
    328       HGraph* graph,
    329       CodeGenerator* codegen,
    330       const DexCompilationUnit& dex_compilation_unit,
    331       PassObserver* pass_observer,
    332       VariableSizedHandleScope* handles,
    333       const OptimizationDef (&definitions)[length]) const {
    334     RunOptimizations(
    335         graph, codegen, dex_compilation_unit, pass_observer, handles, definitions, length);
    336   }
    337 
    338   void RunOptimizations(HGraph* graph,
    339                         CodeGenerator* codegen,
    340                         const DexCompilationUnit& dex_compilation_unit,
    341                         PassObserver* pass_observer,
    342                         VariableSizedHandleScope* handles) const;
    343 
    344  private:
    345   // Create a 'CompiledMethod' for an optimized graph.
    346   CompiledMethod* Emit(ArenaAllocator* allocator,
    347                        CodeVectorAllocator* code_allocator,
    348                        CodeGenerator* codegen,
    349                        const DexFile::CodeItem* item) const;
    350 
    351   // Try compiling a method and return the code generator used for
    352   // compiling it.
    353   // This method:
    354   // 1) Builds the graph. Returns null if it failed to build it.
    355   // 2) Transforms the graph to SSA. Returns null if it failed.
    356   // 3) Runs optimizations on the graph, including register allocator.
    357   // 4) Generates code with the `code_allocator` provided.
    358   CodeGenerator* TryCompile(ArenaAllocator* allocator,
    359                             ArenaStack* arena_stack,
    360                             CodeVectorAllocator* code_allocator,
    361                             const DexCompilationUnit& dex_compilation_unit,
    362                             ArtMethod* method,
    363                             bool osr,
    364                             VariableSizedHandleScope* handles) const;
    365 
    366   CodeGenerator* TryCompileIntrinsic(ArenaAllocator* allocator,
    367                                      ArenaStack* arena_stack,
    368                                      CodeVectorAllocator* code_allocator,
    369                                      const DexCompilationUnit& dex_compilation_unit,
    370                                      ArtMethod* method,
    371                                      VariableSizedHandleScope* handles) const;
    372 
    373   void MaybeRunInliner(HGraph* graph,
    374                        CodeGenerator* codegen,
    375                        const DexCompilationUnit& dex_compilation_unit,
    376                        PassObserver* pass_observer,
    377                        VariableSizedHandleScope* handles) const;
    378 
    379   void RunArchOptimizations(HGraph* graph,
    380                             CodeGenerator* codegen,
    381                             const DexCompilationUnit& dex_compilation_unit,
    382                             PassObserver* pass_observer,
    383                             VariableSizedHandleScope* handles) const;
    384 
    385   void GenerateJitDebugInfo(ArtMethod* method, debug::MethodDebugInfo method_debug_info)
    386       REQUIRES_SHARED(Locks::mutator_lock_);
    387 
    388   std::unique_ptr<OptimizingCompilerStats> compilation_stats_;
    389 
    390   std::unique_ptr<std::ostream> visualizer_output_;
    391 
    392   mutable Mutex dump_mutex_;  // To synchronize visualizer writing.
    393 
    394   DISALLOW_COPY_AND_ASSIGN(OptimizingCompiler);
    395 };
    396 
    397 static const int kMaximumCompilationTimeBeforeWarning = 100; /* ms */
    398 
    399 OptimizingCompiler::OptimizingCompiler(CompilerDriver* driver)
    400     : Compiler(driver, kMaximumCompilationTimeBeforeWarning),
    401       dump_mutex_("Visualizer dump lock") {}
    402 
    403 void OptimizingCompiler::Init() {
    404   // Enable C1visualizer output. Must be done in Init() because the compiler
    405   // driver is not fully initialized when passed to the compiler's constructor.
    406   CompilerDriver* driver = GetCompilerDriver();
    407   const std::string cfg_file_name = driver->GetCompilerOptions().GetDumpCfgFileName();
    408   if (!cfg_file_name.empty()) {
    409     std::ios_base::openmode cfg_file_mode =
    410         driver->GetCompilerOptions().GetDumpCfgAppend() ? std::ofstream::app : std::ofstream::out;
    411     visualizer_output_.reset(new std::ofstream(cfg_file_name, cfg_file_mode));
    412   }
    413   if (driver->GetCompilerOptions().GetDumpStats()) {
    414     compilation_stats_.reset(new OptimizingCompilerStats());
    415   }
    416 }
    417 
    418 void OptimizingCompiler::UnInit() const {
    419 }
    420 
    421 OptimizingCompiler::~OptimizingCompiler() {
    422   if (compilation_stats_.get() != nullptr) {
    423     compilation_stats_->Log();
    424   }
    425 }
    426 
    427 bool OptimizingCompiler::CanCompileMethod(uint32_t method_idx ATTRIBUTE_UNUSED,
    428                                           const DexFile& dex_file ATTRIBUTE_UNUSED) const {
    429   return true;
    430 }
    431 
    432 static bool IsInstructionSetSupported(InstructionSet instruction_set) {
    433   return instruction_set == InstructionSet::kArm
    434       || instruction_set == InstructionSet::kArm64
    435       || instruction_set == InstructionSet::kThumb2
    436       || instruction_set == InstructionSet::kMips
    437       || instruction_set == InstructionSet::kMips64
    438       || instruction_set == InstructionSet::kX86
    439       || instruction_set == InstructionSet::kX86_64;
    440 }
    441 
    442 void OptimizingCompiler::MaybeRunInliner(HGraph* graph,
    443                                          CodeGenerator* codegen,
    444                                          const DexCompilationUnit& dex_compilation_unit,
    445                                          PassObserver* pass_observer,
    446                                          VariableSizedHandleScope* handles) const {
    447   const CompilerOptions& compiler_options = GetCompilerDriver()->GetCompilerOptions();
    448   bool should_inline = (compiler_options.GetInlineMaxCodeUnits() > 0);
    449   if (!should_inline) {
    450     return;
    451   }
    452   OptimizationDef optimizations[] = {
    453     OptDef(OptimizationPass::kInliner)
    454   };
    455   RunOptimizations(graph,
    456                    codegen,
    457                    dex_compilation_unit,
    458                    pass_observer,
    459                    handles,
    460                    optimizations);
    461 }
    462 
    463 void OptimizingCompiler::RunArchOptimizations(HGraph* graph,
    464                                               CodeGenerator* codegen,
    465                                               const DexCompilationUnit& dex_compilation_unit,
    466                                               PassObserver* pass_observer,
    467                                               VariableSizedHandleScope* handles) const {
    468   switch (GetCompilerDriver()->GetInstructionSet()) {
    469 #if defined(ART_ENABLE_CODEGEN_arm)
    470     case InstructionSet::kThumb2:
    471     case InstructionSet::kArm: {
    472       OptimizationDef arm_optimizations[] = {
    473         OptDef(OptimizationPass::kInstructionSimplifierArm),
    474         OptDef(OptimizationPass::kSideEffectsAnalysis),
    475         OptDef(OptimizationPass::kGlobalValueNumbering, "GVN$after_arch"),
    476         OptDef(OptimizationPass::kScheduling)
    477       };
    478       RunOptimizations(graph,
    479                        codegen,
    480                        dex_compilation_unit,
    481                        pass_observer,
    482                        handles,
    483                        arm_optimizations);
    484       break;
    485     }
    486 #endif
    487 #ifdef ART_ENABLE_CODEGEN_arm64
    488     case InstructionSet::kArm64: {
    489       OptimizationDef arm64_optimizations[] = {
    490         OptDef(OptimizationPass::kInstructionSimplifierArm64),
    491         OptDef(OptimizationPass::kSideEffectsAnalysis),
    492         OptDef(OptimizationPass::kGlobalValueNumbering, "GVN$after_arch"),
    493         OptDef(OptimizationPass::kScheduling)
    494       };
    495       RunOptimizations(graph,
    496                        codegen,
    497                        dex_compilation_unit,
    498                        pass_observer,
    499                        handles,
    500                        arm64_optimizations);
    501       break;
    502     }
    503 #endif
    504 #ifdef ART_ENABLE_CODEGEN_mips
    505     case InstructionSet::kMips: {
    506       OptimizationDef mips_optimizations[] = {
    507         OptDef(OptimizationPass::kInstructionSimplifierMips),
    508         OptDef(OptimizationPass::kSideEffectsAnalysis),
    509         OptDef(OptimizationPass::kGlobalValueNumbering, "GVN$after_arch"),
    510         OptDef(OptimizationPass::kPcRelativeFixupsMips)
    511       };
    512       RunOptimizations(graph,
    513                        codegen,
    514                        dex_compilation_unit,
    515                        pass_observer,
    516                        handles,
    517                        mips_optimizations);
    518       break;
    519     }
    520 #endif
    521 #ifdef ART_ENABLE_CODEGEN_mips64
    522     case InstructionSet::kMips64: {
    523       OptimizationDef mips64_optimizations[] = {
    524         OptDef(OptimizationPass::kSideEffectsAnalysis),
    525         OptDef(OptimizationPass::kGlobalValueNumbering, "GVN$after_arch")
    526       };
    527       RunOptimizations(graph,
    528                        codegen,
    529                        dex_compilation_unit,
    530                        pass_observer,
    531                        handles,
    532                        mips64_optimizations);
    533       break;
    534     }
    535 #endif
    536 #ifdef ART_ENABLE_CODEGEN_x86
    537     case InstructionSet::kX86: {
    538       OptimizationDef x86_optimizations[] = {
    539         OptDef(OptimizationPass::kSideEffectsAnalysis),
    540         OptDef(OptimizationPass::kGlobalValueNumbering, "GVN$after_arch"),
    541         OptDef(OptimizationPass::kPcRelativeFixupsX86),
    542         OptDef(OptimizationPass::kX86MemoryOperandGeneration)
    543       };
    544       RunOptimizations(graph,
    545                        codegen,
    546                        dex_compilation_unit,
    547                        pass_observer,
    548                        handles,
    549                        x86_optimizations);
    550       break;
    551     }
    552 #endif
    553 #ifdef ART_ENABLE_CODEGEN_x86_64
    554     case InstructionSet::kX86_64: {
    555       OptimizationDef x86_64_optimizations[] = {
    556         OptDef(OptimizationPass::kSideEffectsAnalysis),
    557         OptDef(OptimizationPass::kGlobalValueNumbering, "GVN$after_arch"),
    558         OptDef(OptimizationPass::kX86MemoryOperandGeneration)
    559       };
    560       RunOptimizations(graph,
    561                        codegen,
    562                        dex_compilation_unit,
    563                        pass_observer,
    564                        handles,
    565                        x86_64_optimizations);
    566       break;
    567     }
    568 #endif
    569     default:
    570       break;
    571   }
    572 }
    573 
    574 NO_INLINE  // Avoid increasing caller's frame size by large stack-allocated objects.
    575 static void AllocateRegisters(HGraph* graph,
    576                               CodeGenerator* codegen,
    577                               PassObserver* pass_observer,
    578                               RegisterAllocator::Strategy strategy,
    579                               OptimizingCompilerStats* stats) {
    580   {
    581     PassScope scope(PrepareForRegisterAllocation::kPrepareForRegisterAllocationPassName,
    582                     pass_observer);
    583     PrepareForRegisterAllocation(graph, stats).Run();
    584   }
    585   // Use local allocator shared by SSA liveness analysis and register allocator.
    586   // (Register allocator creates new objects in the liveness data.)
    587   ScopedArenaAllocator local_allocator(graph->GetArenaStack());
    588   SsaLivenessAnalysis liveness(graph, codegen, &local_allocator);
    589   {
    590     PassScope scope(SsaLivenessAnalysis::kLivenessPassName, pass_observer);
    591     liveness.Analyze();
    592   }
    593   {
    594     PassScope scope(RegisterAllocator::kRegisterAllocatorPassName, pass_observer);
    595     std::unique_ptr<RegisterAllocator> register_allocator =
    596         RegisterAllocator::Create(&local_allocator, codegen, liveness, strategy);
    597     register_allocator->AllocateRegisters();
    598   }
    599 }
    600 
    601 // Strip pass name suffix to get optimization name.
    602 static std::string ConvertPassNameToOptimizationName(const std::string& pass_name) {
    603   size_t pos = pass_name.find(kPassNameSeparator);
    604   return pos == std::string::npos ? pass_name : pass_name.substr(0, pos);
    605 }
    606 
    607 void OptimizingCompiler::RunOptimizations(HGraph* graph,
    608                                           CodeGenerator* codegen,
    609                                           const DexCompilationUnit& dex_compilation_unit,
    610                                           PassObserver* pass_observer,
    611                                           VariableSizedHandleScope* handles) const {
    612   const std::vector<std::string>* pass_names =
    613       GetCompilerDriver()->GetCompilerOptions().GetPassesToRun();
    614   if (pass_names != nullptr) {
    615     // If passes were defined on command-line, build the optimization
    616     // passes and run these instead of the built-in optimizations.
    617     const size_t length = pass_names->size();
    618     std::vector<OptimizationDef> optimizations;
    619     for (const std::string& pass_name : *pass_names) {
    620       std::string opt_name = ConvertPassNameToOptimizationName(pass_name);
    621       optimizations.push_back(OptDef(OptimizationPassByName(opt_name.c_str()), pass_name.c_str()));
    622     }
    623     RunOptimizations(graph,
    624                      codegen,
    625                      dex_compilation_unit,
    626                      pass_observer,
    627                      handles,
    628                      optimizations.data(),
    629                      length);
    630     return;
    631   }
    632 
    633   OptimizationDef optimizations1[] = {
    634     OptDef(OptimizationPass::kIntrinsicsRecognizer),
    635     OptDef(OptimizationPass::kSharpening),
    636     OptDef(OptimizationPass::kConstantFolding),
    637     OptDef(OptimizationPass::kInstructionSimplifier),
    638     OptDef(OptimizationPass::kDeadCodeElimination, "dead_code_elimination$initial")
    639   };
    640   RunOptimizations(graph,
    641                    codegen,
    642                    dex_compilation_unit,
    643                    pass_observer,
    644                    handles,
    645                    optimizations1);
    646 
    647   MaybeRunInliner(graph, codegen, dex_compilation_unit, pass_observer, handles);
    648 
    649   OptimizationDef optimizations2[] = {
    650     // SelectGenerator depends on the InstructionSimplifier removing
    651     // redundant suspend checks to recognize empty blocks.
    652     OptDef(OptimizationPass::kSelectGenerator),
    653     // TODO: if we don't inline we can also skip fold2.
    654     OptDef(OptimizationPass::kConstantFolding,       "constant_folding$after_inlining"),
    655     OptDef(OptimizationPass::kInstructionSimplifier, "instruction_simplifier$after_inlining"),
    656     OptDef(OptimizationPass::kDeadCodeElimination,   "dead_code_elimination$after_inlining"),
    657     OptDef(OptimizationPass::kSideEffectsAnalysis,   "side_effects$before_gvn"),
    658     OptDef(OptimizationPass::kGlobalValueNumbering),
    659     OptDef(OptimizationPass::kInvariantCodeMotion),
    660     OptDef(OptimizationPass::kInductionVarAnalysis),
    661     OptDef(OptimizationPass::kBoundsCheckElimination),
    662     OptDef(OptimizationPass::kLoopOptimization),
    663     // Evaluates code generated by dynamic bce.
    664     OptDef(OptimizationPass::kConstantFolding,       "constant_folding$after_bce"),
    665     OptDef(OptimizationPass::kInstructionSimplifier, "instruction_simplifier$after_bce"),
    666     OptDef(OptimizationPass::kSideEffectsAnalysis,   "side_effects$before_lse"),
    667     OptDef(OptimizationPass::kLoadStoreAnalysis),
    668     OptDef(OptimizationPass::kLoadStoreElimination),
    669     OptDef(OptimizationPass::kCHAGuardOptimization),
    670     OptDef(OptimizationPass::kDeadCodeElimination,   "dead_code_elimination$final"),
    671     OptDef(OptimizationPass::kCodeSinking),
    672     // The codegen has a few assumptions that only the instruction simplifier
    673     // can satisfy. For example, the code generator does not expect to see a
    674     // HTypeConversion from a type to the same type.
    675     OptDef(OptimizationPass::kInstructionSimplifier, "instruction_simplifier$before_codegen"),
    676     // Eliminate constructor fences after code sinking to avoid
    677     // complicated sinking logic to split a fence with many inputs.
    678     OptDef(OptimizationPass::kConstructorFenceRedundancyElimination)
    679   };
    680   RunOptimizations(graph,
    681                    codegen,
    682                    dex_compilation_unit,
    683                    pass_observer,
    684                    handles,
    685                    optimizations2);
    686 
    687   RunArchOptimizations(graph, codegen, dex_compilation_unit, pass_observer, handles);
    688 }
    689 
    690 static ArenaVector<linker::LinkerPatch> EmitAndSortLinkerPatches(CodeGenerator* codegen) {
    691   ArenaVector<linker::LinkerPatch> linker_patches(codegen->GetGraph()->GetAllocator()->Adapter());
    692   codegen->EmitLinkerPatches(&linker_patches);
    693 
    694   // Sort patches by literal offset. Required for .oat_patches encoding.
    695   std::sort(linker_patches.begin(), linker_patches.end(),
    696             [](const linker::LinkerPatch& lhs, const linker::LinkerPatch& rhs) {
    697     return lhs.LiteralOffset() < rhs.LiteralOffset();
    698   });
    699 
    700   return linker_patches;
    701 }
    702 
    703 CompiledMethod* OptimizingCompiler::Emit(ArenaAllocator* allocator,
    704                                          CodeVectorAllocator* code_allocator,
    705                                          CodeGenerator* codegen,
    706                                          const DexFile::CodeItem* code_item_for_osr_check) const {
    707   ArenaVector<linker::LinkerPatch> linker_patches = EmitAndSortLinkerPatches(codegen);
    708   ArenaVector<uint8_t> stack_map(allocator->Adapter(kArenaAllocStackMaps));
    709   ArenaVector<uint8_t> method_info(allocator->Adapter(kArenaAllocStackMaps));
    710   size_t stack_map_size = 0;
    711   size_t method_info_size = 0;
    712   codegen->ComputeStackMapAndMethodInfoSize(&stack_map_size, &method_info_size);
    713   stack_map.resize(stack_map_size);
    714   method_info.resize(method_info_size);
    715   codegen->BuildStackMaps(MemoryRegion(stack_map.data(), stack_map.size()),
    716                           MemoryRegion(method_info.data(), method_info.size()),
    717                           code_item_for_osr_check);
    718 
    719   CompiledMethod* compiled_method = CompiledMethod::SwapAllocCompiledMethod(
    720       GetCompilerDriver(),
    721       codegen->GetInstructionSet(),
    722       ArrayRef<const uint8_t>(code_allocator->GetMemory()),
    723       // Follow Quick's behavior and set the frame size to zero if it is
    724       // considered "empty" (see the definition of
    725       // art::CodeGenerator::HasEmptyFrame).
    726       codegen->HasEmptyFrame() ? 0 : codegen->GetFrameSize(),
    727       codegen->GetCoreSpillMask(),
    728       codegen->GetFpuSpillMask(),
    729       ArrayRef<const uint8_t>(method_info),
    730       ArrayRef<const uint8_t>(stack_map),
    731       ArrayRef<const uint8_t>(*codegen->GetAssembler()->cfi().data()),
    732       ArrayRef<const linker::LinkerPatch>(linker_patches));
    733 
    734   return compiled_method;
    735 }
    736 
    737 CodeGenerator* OptimizingCompiler::TryCompile(ArenaAllocator* allocator,
    738                                               ArenaStack* arena_stack,
    739                                               CodeVectorAllocator* code_allocator,
    740                                               const DexCompilationUnit& dex_compilation_unit,
    741                                               ArtMethod* method,
    742                                               bool osr,
    743                                               VariableSizedHandleScope* handles) const {
    744   MaybeRecordStat(compilation_stats_.get(), MethodCompilationStat::kAttemptBytecodeCompilation);
    745   CompilerDriver* compiler_driver = GetCompilerDriver();
    746   InstructionSet instruction_set = compiler_driver->GetInstructionSet();
    747   const DexFile& dex_file = *dex_compilation_unit.GetDexFile();
    748   uint32_t method_idx = dex_compilation_unit.GetDexMethodIndex();
    749   const DexFile::CodeItem* code_item = dex_compilation_unit.GetCodeItem();
    750 
    751   // Always use the Thumb-2 assembler: some runtime functionality
    752   // (like implicit stack overflow checks) assume Thumb-2.
    753   DCHECK_NE(instruction_set, InstructionSet::kArm);
    754 
    755   // Do not attempt to compile on architectures we do not support.
    756   if (!IsInstructionSetSupported(instruction_set)) {
    757     MaybeRecordStat(compilation_stats_.get(),
    758                     MethodCompilationStat::kNotCompiledUnsupportedIsa);
    759     return nullptr;
    760   }
    761 
    762   if (Compiler::IsPathologicalCase(*code_item, method_idx, dex_file)) {
    763     MaybeRecordStat(compilation_stats_.get(), MethodCompilationStat::kNotCompiledPathological);
    764     return nullptr;
    765   }
    766 
    767   // Implementation of the space filter: do not compile a code item whose size in
    768   // code units is bigger than 128.
    769   static constexpr size_t kSpaceFilterOptimizingThreshold = 128;
    770   const CompilerOptions& compiler_options = compiler_driver->GetCompilerOptions();
    771   if ((compiler_options.GetCompilerFilter() == CompilerFilter::kSpace)
    772       && (CodeItemInstructionAccessor(dex_file, code_item).InsnsSizeInCodeUnits() >
    773           kSpaceFilterOptimizingThreshold)) {
    774     MaybeRecordStat(compilation_stats_.get(), MethodCompilationStat::kNotCompiledSpaceFilter);
    775     return nullptr;
    776   }
    777 
    778   CodeItemDebugInfoAccessor code_item_accessor(dex_file, code_item, method_idx);
    779   HGraph* graph = new (allocator) HGraph(
    780       allocator,
    781       arena_stack,
    782       dex_file,
    783       method_idx,
    784       compiler_driver->GetInstructionSet(),
    785       kInvalidInvokeType,
    786       compiler_driver->GetCompilerOptions().GetDebuggable(),
    787       osr);
    788 
    789   ArrayRef<const uint8_t> interpreter_metadata;
    790   // For AOT compilation, we may not get a method, for example if its class is erroneous.
    791   // JIT should always have a method.
    792   DCHECK(Runtime::Current()->IsAotCompiler() || method != nullptr);
    793   if (method != nullptr) {
    794     graph->SetArtMethod(method);
    795     ScopedObjectAccess soa(Thread::Current());
    796     interpreter_metadata = method->GetQuickenedInfo();
    797   }
    798 
    799   std::unique_ptr<CodeGenerator> codegen(
    800       CodeGenerator::Create(graph,
    801                             instruction_set,
    802                             *compiler_driver->GetInstructionSetFeatures(),
    803                             compiler_driver->GetCompilerOptions(),
    804                             compilation_stats_.get()));
    805   if (codegen.get() == nullptr) {
    806     MaybeRecordStat(compilation_stats_.get(), MethodCompilationStat::kNotCompiledNoCodegen);
    807     return nullptr;
    808   }
    809   codegen->GetAssembler()->cfi().SetEnabled(
    810       compiler_driver->GetCompilerOptions().GenerateAnyDebugInfo());
    811 
    812   PassObserver pass_observer(graph,
    813                              codegen.get(),
    814                              visualizer_output_.get(),
    815                              compiler_driver,
    816                              dump_mutex_);
    817 
    818   {
    819     VLOG(compiler) << "Building " << pass_observer.GetMethodName();
    820     PassScope scope(HGraphBuilder::kBuilderPassName, &pass_observer);
    821     HGraphBuilder builder(graph,
    822                           code_item_accessor,
    823                           &dex_compilation_unit,
    824                           &dex_compilation_unit,
    825                           compiler_driver,
    826                           codegen.get(),
    827                           compilation_stats_.get(),
    828                           interpreter_metadata,
    829                           handles);
    830     GraphAnalysisResult result = builder.BuildGraph();
    831     if (result != kAnalysisSuccess) {
    832       switch (result) {
    833         case kAnalysisSkipped: {
    834           MaybeRecordStat(compilation_stats_.get(),
    835                           MethodCompilationStat::kNotCompiledSkipped);
    836         }
    837           break;
    838         case kAnalysisInvalidBytecode: {
    839           MaybeRecordStat(compilation_stats_.get(),
    840                           MethodCompilationStat::kNotCompiledInvalidBytecode);
    841         }
    842           break;
    843         case kAnalysisFailThrowCatchLoop: {
    844           MaybeRecordStat(compilation_stats_.get(),
    845                           MethodCompilationStat::kNotCompiledThrowCatchLoop);
    846         }
    847           break;
    848         case kAnalysisFailAmbiguousArrayOp: {
    849           MaybeRecordStat(compilation_stats_.get(),
    850                           MethodCompilationStat::kNotCompiledAmbiguousArrayOp);
    851         }
    852           break;
    853         case kAnalysisSuccess:
    854           UNREACHABLE();
    855       }
    856       pass_observer.SetGraphInBadState();
    857       return nullptr;
    858     }
    859   }
    860 
    861   RunOptimizations(graph,
    862                    codegen.get(),
    863                    dex_compilation_unit,
    864                    &pass_observer,
    865                    handles);
    866 
    867   RegisterAllocator::Strategy regalloc_strategy =
    868     compiler_options.GetRegisterAllocationStrategy();
    869   AllocateRegisters(graph,
    870                     codegen.get(),
    871                     &pass_observer,
    872                     regalloc_strategy,
    873                     compilation_stats_.get());
    874 
    875   codegen->Compile(code_allocator);
    876   pass_observer.DumpDisassembly();
    877 
    878   MaybeRecordStat(compilation_stats_.get(), MethodCompilationStat::kCompiledBytecode);
    879   return codegen.release();
    880 }
    881 
    882 CodeGenerator* OptimizingCompiler::TryCompileIntrinsic(
    883     ArenaAllocator* allocator,
    884     ArenaStack* arena_stack,
    885     CodeVectorAllocator* code_allocator,
    886     const DexCompilationUnit& dex_compilation_unit,
    887     ArtMethod* method,
    888     VariableSizedHandleScope* handles) const {
    889   MaybeRecordStat(compilation_stats_.get(), MethodCompilationStat::kAttemptIntrinsicCompilation);
    890   CompilerDriver* compiler_driver = GetCompilerDriver();
    891   InstructionSet instruction_set = compiler_driver->GetInstructionSet();
    892   const DexFile& dex_file = *dex_compilation_unit.GetDexFile();
    893   uint32_t method_idx = dex_compilation_unit.GetDexMethodIndex();
    894 
    895   // Always use the Thumb-2 assembler: some runtime functionality
    896   // (like implicit stack overflow checks) assume Thumb-2.
    897   DCHECK_NE(instruction_set, InstructionSet::kArm);
    898 
    899   // Do not attempt to compile on architectures we do not support.
    900   if (!IsInstructionSetSupported(instruction_set)) {
    901     return nullptr;
    902   }
    903 
    904   HGraph* graph = new (allocator) HGraph(
    905       allocator,
    906       arena_stack,
    907       dex_file,
    908       method_idx,
    909       compiler_driver->GetInstructionSet(),
    910       kInvalidInvokeType,
    911       compiler_driver->GetCompilerOptions().GetDebuggable(),
    912       /* osr */ false);
    913 
    914   DCHECK(Runtime::Current()->IsAotCompiler());
    915   DCHECK(method != nullptr);
    916   graph->SetArtMethod(method);
    917 
    918   std::unique_ptr<CodeGenerator> codegen(
    919       CodeGenerator::Create(graph,
    920                             instruction_set,
    921                             *compiler_driver->GetInstructionSetFeatures(),
    922                             compiler_driver->GetCompilerOptions(),
    923                             compilation_stats_.get()));
    924   if (codegen.get() == nullptr) {
    925     return nullptr;
    926   }
    927   codegen->GetAssembler()->cfi().SetEnabled(
    928       compiler_driver->GetCompilerOptions().GenerateAnyDebugInfo());
    929 
    930   PassObserver pass_observer(graph,
    931                              codegen.get(),
    932                              visualizer_output_.get(),
    933                              compiler_driver,
    934                              dump_mutex_);
    935 
    936   {
    937     VLOG(compiler) << "Building intrinsic graph " << pass_observer.GetMethodName();
    938     PassScope scope(HGraphBuilder::kBuilderPassName, &pass_observer);
    939     HGraphBuilder builder(graph,
    940                           CodeItemDebugInfoAccessor(),  // Null code item.
    941                           &dex_compilation_unit,
    942                           &dex_compilation_unit,
    943                           compiler_driver,
    944                           codegen.get(),
    945                           compilation_stats_.get(),
    946                           /* interpreter_metadata */ ArrayRef<const uint8_t>(),
    947                           handles);
    948     builder.BuildIntrinsicGraph(method);
    949   }
    950 
    951   OptimizationDef optimizations[] = {
    952     OptDef(OptimizationPass::kIntrinsicsRecognizer),
    953     // Some intrinsics are converted to HIR by the simplifier and the codegen also
    954     // has a few assumptions that only the instruction simplifier can satisfy.
    955     OptDef(OptimizationPass::kInstructionSimplifier),
    956   };
    957   RunOptimizations(graph,
    958                    codegen.get(),
    959                    dex_compilation_unit,
    960                    &pass_observer,
    961                    handles,
    962                    optimizations);
    963 
    964   RunArchOptimizations(graph, codegen.get(), dex_compilation_unit, &pass_observer, handles);
    965 
    966   AllocateRegisters(graph,
    967                     codegen.get(),
    968                     &pass_observer,
    969                     compiler_driver->GetCompilerOptions().GetRegisterAllocationStrategy(),
    970                     compilation_stats_.get());
    971   if (!codegen->IsLeafMethod()) {
    972     VLOG(compiler) << "Intrinsic method is not leaf: " << method->GetIntrinsic()
    973         << " " << graph->PrettyMethod();
    974     return nullptr;
    975   }
    976 
    977   codegen->Compile(code_allocator);
    978   pass_observer.DumpDisassembly();
    979 
    980   VLOG(compiler) << "Compiled intrinsic: " << method->GetIntrinsic()
    981       << " " << graph->PrettyMethod();
    982   MaybeRecordStat(compilation_stats_.get(), MethodCompilationStat::kCompiledIntrinsic);
    983   return codegen.release();
    984 }
    985 
    986 CompiledMethod* OptimizingCompiler::Compile(const DexFile::CodeItem* code_item,
    987                                             uint32_t access_flags,
    988                                             InvokeType invoke_type,
    989                                             uint16_t class_def_idx,
    990                                             uint32_t method_idx,
    991                                             Handle<mirror::ClassLoader> jclass_loader,
    992                                             const DexFile& dex_file,
    993                                             Handle<mirror::DexCache> dex_cache) const {
    994   CompilerDriver* compiler_driver = GetCompilerDriver();
    995   CompiledMethod* compiled_method = nullptr;
    996   Runtime* runtime = Runtime::Current();
    997   DCHECK(runtime->IsAotCompiler());
    998   const VerifiedMethod* verified_method = compiler_driver->GetVerifiedMethod(&dex_file, method_idx);
    999   DCHECK(!verified_method->HasRuntimeThrow());
   1000   if (compiler_driver->IsMethodVerifiedWithoutFailures(method_idx, class_def_idx, dex_file) ||
   1001       verifier::CanCompilerHandleVerificationFailure(
   1002           verified_method->GetEncounteredVerificationFailures())) {
   1003     ArenaAllocator allocator(runtime->GetArenaPool());
   1004     ArenaStack arena_stack(runtime->GetArenaPool());
   1005     CodeVectorAllocator code_allocator(&allocator);
   1006     std::unique_ptr<CodeGenerator> codegen;
   1007     bool compiled_intrinsic = false;
   1008     {
   1009       DexCompilationUnit dex_compilation_unit(
   1010           jclass_loader,
   1011           runtime->GetClassLinker(),
   1012           dex_file,
   1013           code_item,
   1014           class_def_idx,
   1015           method_idx,
   1016           access_flags,
   1017           /* verified_method */ nullptr,  // Not needed by the Optimizing compiler.
   1018           dex_cache);
   1019       ScopedObjectAccess soa(Thread::Current());
   1020       ArtMethod* method = compiler_driver->ResolveMethod(
   1021             soa, dex_cache, jclass_loader, &dex_compilation_unit, method_idx, invoke_type);
   1022       VariableSizedHandleScope handles(soa.Self());
   1023       // Go to native so that we don't block GC during compilation.
   1024       ScopedThreadSuspension sts(soa.Self(), kNative);
   1025       if (method != nullptr && UNLIKELY(method->IsIntrinsic())) {
   1026         DCHECK(compiler_driver->GetCompilerOptions().IsBootImage());
   1027         codegen.reset(
   1028             TryCompileIntrinsic(&allocator,
   1029                                 &arena_stack,
   1030                                 &code_allocator,
   1031                                 dex_compilation_unit,
   1032                                 method,
   1033                                 &handles));
   1034         if (codegen != nullptr) {
   1035           compiled_intrinsic = true;
   1036         }
   1037       }
   1038       if (codegen == nullptr) {
   1039         codegen.reset(
   1040             TryCompile(&allocator,
   1041                        &arena_stack,
   1042                        &code_allocator,
   1043                        dex_compilation_unit,
   1044                        method,
   1045                        /* osr */ false,
   1046                        &handles));
   1047       }
   1048     }
   1049     if (codegen.get() != nullptr) {
   1050       compiled_method = Emit(&allocator,
   1051                              &code_allocator,
   1052                              codegen.get(),
   1053                              compiled_intrinsic ? nullptr : code_item);
   1054       if (compiled_intrinsic) {
   1055         compiled_method->MarkAsIntrinsic();
   1056       }
   1057 
   1058       if (kArenaAllocatorCountAllocations) {
   1059         codegen.reset();  // Release codegen's ScopedArenaAllocator for memory accounting.
   1060         size_t total_allocated = allocator.BytesAllocated() + arena_stack.PeakBytesAllocated();
   1061         if (total_allocated > kArenaAllocatorMemoryReportThreshold) {
   1062           MemStats mem_stats(allocator.GetMemStats());
   1063           MemStats peak_stats(arena_stack.GetPeakStats());
   1064           LOG(INFO) << "Used " << total_allocated << " bytes of arena memory for compiling "
   1065                     << dex_file.PrettyMethod(method_idx)
   1066                     << "\n" << Dumpable<MemStats>(mem_stats)
   1067                     << "\n" << Dumpable<MemStats>(peak_stats);
   1068         }
   1069       }
   1070     }
   1071   } else {
   1072     MethodCompilationStat method_stat;
   1073     if (compiler_driver->GetCompilerOptions().VerifyAtRuntime()) {
   1074       method_stat = MethodCompilationStat::kNotCompiledVerifyAtRuntime;
   1075     } else {
   1076       method_stat = MethodCompilationStat::kNotCompiledVerificationError;
   1077     }
   1078     MaybeRecordStat(compilation_stats_.get(), method_stat);
   1079   }
   1080 
   1081   if (kIsDebugBuild &&
   1082       IsCompilingWithCoreImage() &&
   1083       IsInstructionSetSupported(compiler_driver->GetInstructionSet())) {
   1084     // For testing purposes, we put a special marker on method names
   1085     // that should be compiled with this compiler (when the
   1086     // instruction set is supported). This makes sure we're not
   1087     // regressing.
   1088     std::string method_name = dex_file.PrettyMethod(method_idx);
   1089     bool shouldCompile = method_name.find("$opt$") != std::string::npos;
   1090     DCHECK((compiled_method != nullptr) || !shouldCompile) << "Didn't compile " << method_name;
   1091   }
   1092 
   1093   return compiled_method;
   1094 }
   1095 
   1096 CompiledMethod* OptimizingCompiler::JniCompile(uint32_t access_flags,
   1097                                                uint32_t method_idx,
   1098                                                const DexFile& dex_file,
   1099                                                Handle<mirror::DexCache> dex_cache) const {
   1100   if (GetCompilerDriver()->GetCompilerOptions().IsBootImage()) {
   1101     ScopedObjectAccess soa(Thread::Current());
   1102     Runtime* runtime = Runtime::Current();
   1103     ArtMethod* method = runtime->GetClassLinker()->LookupResolvedMethod(
   1104         method_idx, dex_cache.Get(), /* class_loader */ nullptr);
   1105     if (method != nullptr && UNLIKELY(method->IsIntrinsic())) {
   1106       ScopedNullHandle<mirror::ClassLoader> class_loader;  // null means boot class path loader.
   1107       DexCompilationUnit dex_compilation_unit(
   1108           class_loader,
   1109           runtime->GetClassLinker(),
   1110           dex_file,
   1111           /* code_item */ nullptr,
   1112           /* class_def_idx */ DexFile::kDexNoIndex16,
   1113           method_idx,
   1114           access_flags,
   1115           /* verified_method */ nullptr,
   1116           dex_cache);
   1117       ArenaAllocator allocator(runtime->GetArenaPool());
   1118       ArenaStack arena_stack(runtime->GetArenaPool());
   1119       CodeVectorAllocator code_allocator(&allocator);
   1120       VariableSizedHandleScope handles(soa.Self());
   1121       // Go to native so that we don't block GC during compilation.
   1122       ScopedThreadSuspension sts(soa.Self(), kNative);
   1123       std::unique_ptr<CodeGenerator> codegen(
   1124           TryCompileIntrinsic(&allocator,
   1125                               &arena_stack,
   1126                               &code_allocator,
   1127                               dex_compilation_unit,
   1128                               method,
   1129                               &handles));
   1130       if (codegen != nullptr) {
   1131         CompiledMethod* compiled_method = Emit(&allocator,
   1132                                                &code_allocator,
   1133                                                codegen.get(),
   1134                                                /* code_item_for_osr_check */ nullptr);
   1135         compiled_method->MarkAsIntrinsic();
   1136         return compiled_method;
   1137       }
   1138     }
   1139   }
   1140 
   1141   JniCompiledMethod jni_compiled_method = ArtQuickJniCompileMethod(
   1142       GetCompilerDriver(), access_flags, method_idx, dex_file);
   1143   MaybeRecordStat(compilation_stats_.get(), MethodCompilationStat::kCompiledNativeStub);
   1144   return CompiledMethod::SwapAllocCompiledMethod(
   1145       GetCompilerDriver(),
   1146       jni_compiled_method.GetInstructionSet(),
   1147       jni_compiled_method.GetCode(),
   1148       jni_compiled_method.GetFrameSize(),
   1149       jni_compiled_method.GetCoreSpillMask(),
   1150       jni_compiled_method.GetFpSpillMask(),
   1151       /* method_info */ ArrayRef<const uint8_t>(),
   1152       /* vmap_table */ ArrayRef<const uint8_t>(),
   1153       jni_compiled_method.GetCfi(),
   1154       /* patches */ ArrayRef<const linker::LinkerPatch>());
   1155 }
   1156 
   1157 Compiler* CreateOptimizingCompiler(CompilerDriver* driver) {
   1158   return new OptimizingCompiler(driver);
   1159 }
   1160 
   1161 bool IsCompilingWithCoreImage() {
   1162   const std::string& image = Runtime::Current()->GetImageLocation();
   1163   return CompilerDriver::IsCoreImageFilename(image);
   1164 }
   1165 
   1166 bool EncodeArtMethodInInlineInfo(ArtMethod* method ATTRIBUTE_UNUSED) {
   1167   // Note: the runtime is null only for unit testing.
   1168   return Runtime::Current() == nullptr || !Runtime::Current()->IsAotCompiler();
   1169 }
   1170 
   1171 bool CanEncodeInlinedMethodInStackMap(const DexFile& caller_dex_file, ArtMethod* callee) {
   1172   if (!Runtime::Current()->IsAotCompiler()) {
   1173     // JIT can always encode methods in stack maps.
   1174     return true;
   1175   }
   1176   if (IsSameDexFile(caller_dex_file, *callee->GetDexFile())) {
   1177     return true;
   1178   }
   1179   // TODO(ngeoffray): Support more AOT cases for inlining:
   1180   // - methods in multidex
   1181   // - methods in boot image for on-device non-PIC compilation.
   1182   return false;
   1183 }
   1184 
   1185 bool OptimizingCompiler::JitCompile(Thread* self,
   1186                                     jit::JitCodeCache* code_cache,
   1187                                     ArtMethod* method,
   1188                                     bool osr,
   1189                                     jit::JitLogger* jit_logger) {
   1190   StackHandleScope<3> hs(self);
   1191   Handle<mirror::ClassLoader> class_loader(hs.NewHandle(
   1192       method->GetDeclaringClass()->GetClassLoader()));
   1193   Handle<mirror::DexCache> dex_cache(hs.NewHandle(method->GetDexCache()));
   1194   DCHECK(method->IsCompilable());
   1195 
   1196   const DexFile* dex_file = method->GetDexFile();
   1197   const uint16_t class_def_idx = method->GetClassDefIndex();
   1198   const DexFile::CodeItem* code_item = dex_file->GetCodeItem(method->GetCodeItemOffset());
   1199   const uint32_t method_idx = method->GetDexMethodIndex();
   1200   const uint32_t access_flags = method->GetAccessFlags();
   1201 
   1202   Runtime* runtime = Runtime::Current();
   1203   ArenaAllocator allocator(runtime->GetJitArenaPool());
   1204 
   1205   if (UNLIKELY(method->IsNative())) {
   1206     JniCompiledMethod jni_compiled_method = ArtQuickJniCompileMethod(
   1207         GetCompilerDriver(), access_flags, method_idx, *dex_file);
   1208     ScopedNullHandle<mirror::ObjectArray<mirror::Object>> roots;
   1209     ArenaSet<ArtMethod*, std::less<ArtMethod*>> cha_single_implementation_list(
   1210         allocator.Adapter(kArenaAllocCHA));
   1211     const void* code = code_cache->CommitCode(
   1212         self,
   1213         method,
   1214         /* stack_map_data */ nullptr,
   1215         /* method_info_data */ nullptr,
   1216         /* roots_data */ nullptr,
   1217         jni_compiled_method.GetFrameSize(),
   1218         jni_compiled_method.GetCoreSpillMask(),
   1219         jni_compiled_method.GetFpSpillMask(),
   1220         jni_compiled_method.GetCode().data(),
   1221         jni_compiled_method.GetCode().size(),
   1222         /* data_size */ 0u,
   1223         osr,
   1224         roots,
   1225         /* has_should_deoptimize_flag */ false,
   1226         cha_single_implementation_list);
   1227     if (code == nullptr) {
   1228       return false;
   1229     }
   1230 
   1231     const CompilerOptions& compiler_options = GetCompilerDriver()->GetCompilerOptions();
   1232     if (compiler_options.GenerateAnyDebugInfo()) {
   1233       const auto* method_header = reinterpret_cast<const OatQuickMethodHeader*>(code);
   1234       const uintptr_t code_address = reinterpret_cast<uintptr_t>(method_header->GetCode());
   1235       debug::MethodDebugInfo info = {};
   1236       DCHECK(info.custom_name.empty());
   1237       info.dex_file = dex_file;
   1238       info.class_def_index = class_def_idx;
   1239       info.dex_method_index = method_idx;
   1240       info.access_flags = access_flags;
   1241       info.code_item = code_item;
   1242       info.isa = jni_compiled_method.GetInstructionSet();
   1243       info.deduped = false;
   1244       info.is_native_debuggable = compiler_options.GetNativeDebuggable();
   1245       info.is_optimized = true;
   1246       info.is_code_address_text_relative = false;
   1247       info.code_address = code_address;
   1248       info.code_size = jni_compiled_method.GetCode().size();
   1249       info.frame_size_in_bytes = method_header->GetFrameSizeInBytes();
   1250       info.code_info = nullptr;
   1251       info.cfi = jni_compiled_method.GetCfi();
   1252       GenerateJitDebugInfo(method, info);
   1253     }
   1254 
   1255     Runtime::Current()->GetJit()->AddMemoryUsage(method, allocator.BytesUsed());
   1256     if (jit_logger != nullptr) {
   1257       jit_logger->WriteLog(code, jni_compiled_method.GetCode().size(), method);
   1258     }
   1259     return true;
   1260   }
   1261 
   1262   ArenaStack arena_stack(runtime->GetJitArenaPool());
   1263   CodeVectorAllocator code_allocator(&allocator);
   1264   VariableSizedHandleScope handles(self);
   1265 
   1266   std::unique_ptr<CodeGenerator> codegen;
   1267   {
   1268     DexCompilationUnit dex_compilation_unit(
   1269         class_loader,
   1270         runtime->GetClassLinker(),
   1271         *dex_file,
   1272         code_item,
   1273         class_def_idx,
   1274         method_idx,
   1275         access_flags,
   1276         /* verified_method */ nullptr,
   1277         dex_cache);
   1278 
   1279     // Go to native so that we don't block GC during compilation.
   1280     ScopedThreadSuspension sts(self, kNative);
   1281     codegen.reset(
   1282         TryCompile(&allocator,
   1283                    &arena_stack,
   1284                    &code_allocator,
   1285                    dex_compilation_unit,
   1286                    method,
   1287                    osr,
   1288                    &handles));
   1289     if (codegen.get() == nullptr) {
   1290       return false;
   1291     }
   1292   }
   1293 
   1294   size_t stack_map_size = 0;
   1295   size_t method_info_size = 0;
   1296   codegen->ComputeStackMapAndMethodInfoSize(&stack_map_size, &method_info_size);
   1297   size_t number_of_roots = codegen->GetNumberOfJitRoots();
   1298   ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
   1299   // We allocate an object array to ensure the JIT roots that we will collect in EmitJitRoots
   1300   // will be visible by the GC between EmitLiterals and CommitCode. Once CommitCode is
   1301   // executed, this array is not needed.
   1302   Handle<mirror::ObjectArray<mirror::Object>> roots(
   1303       hs.NewHandle(mirror::ObjectArray<mirror::Object>::Alloc(
   1304           self, class_linker->GetClassRoot(ClassLinker::kObjectArrayClass), number_of_roots)));
   1305   if (roots == nullptr) {
   1306     // Out of memory, just clear the exception to avoid any Java exception uncaught problems.
   1307     MaybeRecordStat(compilation_stats_.get(), MethodCompilationStat::kJitOutOfMemoryForCommit);
   1308     DCHECK(self->IsExceptionPending());
   1309     self->ClearException();
   1310     return false;
   1311   }
   1312   uint8_t* stack_map_data = nullptr;
   1313   uint8_t* method_info_data = nullptr;
   1314   uint8_t* roots_data = nullptr;
   1315   uint32_t data_size = code_cache->ReserveData(self,
   1316                                                stack_map_size,
   1317                                                method_info_size,
   1318                                                number_of_roots,
   1319                                                method,
   1320                                                &stack_map_data,
   1321                                                &method_info_data,
   1322                                                &roots_data);
   1323   if (stack_map_data == nullptr || roots_data == nullptr) {
   1324     MaybeRecordStat(compilation_stats_.get(), MethodCompilationStat::kJitOutOfMemoryForCommit);
   1325     return false;
   1326   }
   1327   codegen->BuildStackMaps(MemoryRegion(stack_map_data, stack_map_size),
   1328                           MemoryRegion(method_info_data, method_info_size),
   1329                           code_item);
   1330   codegen->EmitJitRoots(code_allocator.GetData(), roots, roots_data);
   1331 
   1332   const void* code = code_cache->CommitCode(
   1333       self,
   1334       method,
   1335       stack_map_data,
   1336       method_info_data,
   1337       roots_data,
   1338       codegen->HasEmptyFrame() ? 0 : codegen->GetFrameSize(),
   1339       codegen->GetCoreSpillMask(),
   1340       codegen->GetFpuSpillMask(),
   1341       code_allocator.GetMemory().data(),
   1342       code_allocator.GetSize(),
   1343       data_size,
   1344       osr,
   1345       roots,
   1346       codegen->GetGraph()->HasShouldDeoptimizeFlag(),
   1347       codegen->GetGraph()->GetCHASingleImplementationList());
   1348 
   1349   if (code == nullptr) {
   1350     MaybeRecordStat(compilation_stats_.get(), MethodCompilationStat::kJitOutOfMemoryForCommit);
   1351     code_cache->ClearData(self, stack_map_data, roots_data);
   1352     return false;
   1353   }
   1354 
   1355   const CompilerOptions& compiler_options = GetCompilerDriver()->GetCompilerOptions();
   1356   if (compiler_options.GenerateAnyDebugInfo()) {
   1357     const auto* method_header = reinterpret_cast<const OatQuickMethodHeader*>(code);
   1358     const uintptr_t code_address = reinterpret_cast<uintptr_t>(method_header->GetCode());
   1359     debug::MethodDebugInfo info = {};
   1360     DCHECK(info.custom_name.empty());
   1361     info.dex_file = dex_file;
   1362     info.class_def_index = class_def_idx;
   1363     info.dex_method_index = method_idx;
   1364     info.access_flags = access_flags;
   1365     info.code_item = code_item;
   1366     info.isa = codegen->GetInstructionSet();
   1367     info.deduped = false;
   1368     info.is_native_debuggable = compiler_options.GetNativeDebuggable();
   1369     info.is_optimized = true;
   1370     info.is_code_address_text_relative = false;
   1371     info.code_address = code_address;
   1372     info.code_size = code_allocator.GetSize();
   1373     info.frame_size_in_bytes = method_header->GetFrameSizeInBytes();
   1374     info.code_info = stack_map_size == 0 ? nullptr : stack_map_data;
   1375     info.cfi = ArrayRef<const uint8_t>(*codegen->GetAssembler()->cfi().data());
   1376     GenerateJitDebugInfo(method, info);
   1377   }
   1378 
   1379   Runtime::Current()->GetJit()->AddMemoryUsage(method, allocator.BytesUsed());
   1380   if (jit_logger != nullptr) {
   1381     jit_logger->WriteLog(code, code_allocator.GetSize(), method);
   1382   }
   1383 
   1384   if (kArenaAllocatorCountAllocations) {
   1385     codegen.reset();  // Release codegen's ScopedArenaAllocator for memory accounting.
   1386     size_t total_allocated = allocator.BytesAllocated() + arena_stack.PeakBytesAllocated();
   1387     if (total_allocated > kArenaAllocatorMemoryReportThreshold) {
   1388       MemStats mem_stats(allocator.GetMemStats());
   1389       MemStats peak_stats(arena_stack.GetPeakStats());
   1390       LOG(INFO) << "Used " << total_allocated << " bytes of arena memory for compiling "
   1391                 << dex_file->PrettyMethod(method_idx)
   1392                 << "\n" << Dumpable<MemStats>(mem_stats)
   1393                 << "\n" << Dumpable<MemStats>(peak_stats);
   1394     }
   1395   }
   1396 
   1397   return true;
   1398 }
   1399 
   1400 void OptimizingCompiler::GenerateJitDebugInfo(ArtMethod* method, debug::MethodDebugInfo info) {
   1401   const CompilerOptions& compiler_options = GetCompilerDriver()->GetCompilerOptions();
   1402   DCHECK(compiler_options.GenerateAnyDebugInfo());
   1403 
   1404   // If both flags are passed, generate full debug info.
   1405   const bool mini_debug_info = !compiler_options.GetGenerateDebugInfo();
   1406 
   1407   // Create entry for the single method that we just compiled.
   1408   std::vector<uint8_t> elf_file = debug::MakeElfFileForJIT(
   1409       GetCompilerDriver()->GetInstructionSet(),
   1410       GetCompilerDriver()->GetInstructionSetFeatures(),
   1411       mini_debug_info,
   1412       ArrayRef<const debug::MethodDebugInfo>(&info, 1));
   1413   MutexLock mu(Thread::Current(), *Locks::native_debug_interface_lock_);
   1414   AddNativeDebugInfoForJit(reinterpret_cast<const void*>(info.code_address), elf_file);
   1415 
   1416   VLOG(jit)
   1417       << "JIT mini-debug-info added for " << ArtMethod::PrettyMethod(method)
   1418       << " size=" << PrettySize(elf_file.size())
   1419       << " total_size=" << PrettySize(GetJitNativeDebugInfoMemUsage());
   1420 }
   1421 
   1422 }  // namespace art
   1423