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:
CodeVectorAllocator(ArenaAllocator * allocator)77   explicit CodeVectorAllocator(ArenaAllocator* allocator)
78       : memory_(allocator->Adapter(kArenaAllocCodeBuffer)),
79         size_(0) {}
80 
Allocate(size_t size)81   virtual uint8_t* Allocate(size_t size) {
82     size_ = size;
83     memory_.resize(size);
84     return &memory_[0];
85   }
86 
GetSize() const87   size_t GetSize() const { return size_; }
GetMemory() const88   const ArenaVector<uint8_t>& GetMemory() const { return memory_; }
GetData()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:
PassObserver(HGraph * graph,CodeGenerator * codegen,std::ostream * visualizer_output,CompilerDriver * compiler_driver,Mutex & dump_mutex)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 
~PassObserver()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 
DumpDisassembly()143   void DumpDisassembly() REQUIRES(!visualizer_dump_mutex_) {
144     if (visualizer_enabled_) {
145       visualizer_.DumpGraphWithDisassembly();
146       FlushVisualizer();
147     }
148   }
149 
SetGraphInBadState()150   void SetGraphInBadState() { graph_in_bad_state_ = true; }
151 
GetMethodName()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:
StartPass(const char * pass_name)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 
FlushVisualizer()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 
EndPass(const char * pass_name)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 
IsVerboseMethod(CompilerDriver * compiler_driver,const char * method_name)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:
PassScope(const char * pass_name,PassObserver * pass_observer)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 
~PassScope()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 
GetEntryPointOf(ArtMethod * method) const282   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:
RunOptimizations(HGraph * graph,CodeGenerator * codegen,const DexCompilationUnit & dex_compilation_unit,PassObserver * pass_observer,VariableSizedHandleScope * handles,const OptimizationDef definitions[],size_t length) const301   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 
RunOptimizations(HGraph * graph,CodeGenerator * codegen,const DexCompilationUnit & dex_compilation_unit,PassObserver * pass_observer,VariableSizedHandleScope * handles,const OptimizationDef (& definitions)[length]) const327   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 
OptimizingCompiler(CompilerDriver * driver)399 OptimizingCompiler::OptimizingCompiler(CompilerDriver* driver)
400     : Compiler(driver, kMaximumCompilationTimeBeforeWarning),
401       dump_mutex_("Visualizer dump lock") {}
402 
Init()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 
UnInit() const418 void OptimizingCompiler::UnInit() const {
419 }
420 
~OptimizingCompiler()421 OptimizingCompiler::~OptimizingCompiler() {
422   if (compilation_stats_.get() != nullptr) {
423     compilation_stats_->Log();
424   }
425 }
426 
CanCompileMethod(uint32_t method_idx ATTRIBUTE_UNUSED,const DexFile & dex_file ATTRIBUTE_UNUSED) const427 bool OptimizingCompiler::CanCompileMethod(uint32_t method_idx ATTRIBUTE_UNUSED,
428                                           const DexFile& dex_file ATTRIBUTE_UNUSED) const {
429   return true;
430 }
431 
IsInstructionSetSupported(InstructionSet instruction_set)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 
MaybeRunInliner(HGraph * graph,CodeGenerator * codegen,const DexCompilationUnit & dex_compilation_unit,PassObserver * pass_observer,VariableSizedHandleScope * handles) const442 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 
RunArchOptimizations(HGraph * graph,CodeGenerator * codegen,const DexCompilationUnit & dex_compilation_unit,PassObserver * pass_observer,VariableSizedHandleScope * handles) const463 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.
AllocateRegisters(HGraph * graph,CodeGenerator * codegen,PassObserver * pass_observer,RegisterAllocator::Strategy strategy,OptimizingCompilerStats * stats)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.
ConvertPassNameToOptimizationName(const std::string & pass_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 
RunOptimizations(HGraph * graph,CodeGenerator * codegen,const DexCompilationUnit & dex_compilation_unit,PassObserver * pass_observer,VariableSizedHandleScope * handles) const607 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 
EmitAndSortLinkerPatches(CodeGenerator * codegen)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 
Emit(ArenaAllocator * allocator,CodeVectorAllocator * code_allocator,CodeGenerator * codegen,const DexFile::CodeItem * code_item_for_osr_check) const703 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 
TryCompile(ArenaAllocator * allocator,ArenaStack * arena_stack,CodeVectorAllocator * code_allocator,const DexCompilationUnit & dex_compilation_unit,ArtMethod * method,bool osr,VariableSizedHandleScope * handles) const737 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 
TryCompileIntrinsic(ArenaAllocator * allocator,ArenaStack * arena_stack,CodeVectorAllocator * code_allocator,const DexCompilationUnit & dex_compilation_unit,ArtMethod * method,VariableSizedHandleScope * handles) const882 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 
Compile(const DexFile::CodeItem * code_item,uint32_t access_flags,InvokeType invoke_type,uint16_t class_def_idx,uint32_t method_idx,Handle<mirror::ClassLoader> jclass_loader,const DexFile & dex_file,Handle<mirror::DexCache> dex_cache) const986 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 
JniCompile(uint32_t access_flags,uint32_t method_idx,const DexFile & dex_file,Handle<mirror::DexCache> dex_cache) const1096 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 
CreateOptimizingCompiler(CompilerDriver * driver)1157 Compiler* CreateOptimizingCompiler(CompilerDriver* driver) {
1158   return new OptimizingCompiler(driver);
1159 }
1160 
IsCompilingWithCoreImage()1161 bool IsCompilingWithCoreImage() {
1162   const std::string& image = Runtime::Current()->GetImageLocation();
1163   return CompilerDriver::IsCoreImageFilename(image);
1164 }
1165 
EncodeArtMethodInInlineInfo(ArtMethod * method ATTRIBUTE_UNUSED)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 
CanEncodeInlinedMethodInStackMap(const DexFile & caller_dex_file,ArtMethod * callee)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 
JitCompile(Thread * self,jit::JitCodeCache * code_cache,ArtMethod * method,bool osr,jit::JitLogger * jit_logger)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 
GenerateJitDebugInfo(ArtMethod * method,debug::MethodDebugInfo info)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