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 "android-base/strings.h"
26 
27 #ifdef ART_ENABLE_CODEGEN_arm
28 #include "dex_cache_array_fixups_arm.h"
29 #endif
30 
31 #ifdef ART_ENABLE_CODEGEN_arm64
32 #include "instruction_simplifier_arm64.h"
33 #endif
34 
35 #ifdef ART_ENABLE_CODEGEN_mips
36 #include "dex_cache_array_fixups_mips.h"
37 #include "pc_relative_fixups_mips.h"
38 #endif
39 
40 #ifdef ART_ENABLE_CODEGEN_x86
41 #include "pc_relative_fixups_x86.h"
42 #endif
43 
44 #if defined(ART_ENABLE_CODEGEN_x86) || defined(ART_ENABLE_CODEGEN_x86_64)
45 #include "x86_memory_gen.h"
46 #endif
47 
48 #include "art_method-inl.h"
49 #include "base/arena_allocator.h"
50 #include "base/arena_containers.h"
51 #include "base/dumpable.h"
52 #include "base/macros.h"
53 #include "base/mutex.h"
54 #include "base/timing_logger.h"
55 #include "bounds_check_elimination.h"
56 #include "builder.h"
57 #include "cha_guard_optimization.h"
58 #include "code_generator.h"
59 #include "code_sinking.h"
60 #include "compiled_method.h"
61 #include "compiler.h"
62 #include "constant_folding.h"
63 #include "dead_code_elimination.h"
64 #include "debug/elf_debug_writer.h"
65 #include "debug/method_debug_info.h"
66 #include "dex/verification_results.h"
67 #include "dex/verified_method.h"
68 #include "dex_file_types.h"
69 #include "driver/compiler_driver-inl.h"
70 #include "driver/compiler_options.h"
71 #include "driver/dex_compilation_unit.h"
72 #include "elf_writer_quick.h"
73 #include "graph_checker.h"
74 #include "graph_visualizer.h"
75 #include "gvn.h"
76 #include "induction_var_analysis.h"
77 #include "inliner.h"
78 #include "instruction_simplifier.h"
79 #include "instruction_simplifier_arm.h"
80 #include "intrinsics.h"
81 #include "jit/debugger_interface.h"
82 #include "jit/jit.h"
83 #include "jit/jit_code_cache.h"
84 #include "jni/quick/jni_compiler.h"
85 #include "licm.h"
86 #include "load_store_elimination.h"
87 #include "loop_optimization.h"
88 #include "nodes.h"
89 #include "oat_quick_method_header.h"
90 #include "prepare_for_register_allocation.h"
91 #include "reference_type_propagation.h"
92 #include "register_allocator_linear_scan.h"
93 #include "select_generator.h"
94 #include "scheduler.h"
95 #include "sharpening.h"
96 #include "side_effects_analysis.h"
97 #include "ssa_builder.h"
98 #include "ssa_liveness_analysis.h"
99 #include "ssa_phi_elimination.h"
100 #include "utils/assembler.h"
101 #include "verifier/verifier_compiler_binding.h"
102 
103 namespace art {
104 
105 static constexpr size_t kArenaAllocatorMemoryReportThreshold = 8 * MB;
106 
107 static constexpr const char* kPassNameSeparator = "$";
108 
109 /**
110  * Used by the code generator, to allocate the code in a vector.
111  */
112 class CodeVectorAllocator FINAL : public CodeAllocator {
113  public:
CodeVectorAllocator(ArenaAllocator * arena)114   explicit CodeVectorAllocator(ArenaAllocator* arena)
115       : memory_(arena->Adapter(kArenaAllocCodeBuffer)),
116         size_(0) {}
117 
Allocate(size_t size)118   virtual uint8_t* Allocate(size_t size) {
119     size_ = size;
120     memory_.resize(size);
121     return &memory_[0];
122   }
123 
GetSize() const124   size_t GetSize() const { return size_; }
GetMemory() const125   const ArenaVector<uint8_t>& GetMemory() const { return memory_; }
GetData()126   uint8_t* GetData() { return memory_.data(); }
127 
128  private:
129   ArenaVector<uint8_t> memory_;
130   size_t size_;
131 
132   DISALLOW_COPY_AND_ASSIGN(CodeVectorAllocator);
133 };
134 
135 /**
136  * Filter to apply to the visualizer. Methods whose name contain that filter will
137  * be dumped.
138  */
139 static constexpr const char kStringFilter[] = "";
140 
141 class PassScope;
142 
143 class PassObserver : public ValueObject {
144  public:
PassObserver(HGraph * graph,CodeGenerator * codegen,std::ostream * visualizer_output,CompilerDriver * compiler_driver,Mutex & dump_mutex)145   PassObserver(HGraph* graph,
146                CodeGenerator* codegen,
147                std::ostream* visualizer_output,
148                CompilerDriver* compiler_driver,
149                Mutex& dump_mutex)
150       : graph_(graph),
151         cached_method_name_(),
152         timing_logger_enabled_(compiler_driver->GetDumpPasses()),
153         timing_logger_(timing_logger_enabled_ ? GetMethodName() : "", true, true),
154         disasm_info_(graph->GetArena()),
155         visualizer_oss_(),
156         visualizer_output_(visualizer_output),
157         visualizer_enabled_(!compiler_driver->GetCompilerOptions().GetDumpCfgFileName().empty()),
158         visualizer_(&visualizer_oss_, graph, *codegen),
159         visualizer_dump_mutex_(dump_mutex),
160         graph_in_bad_state_(false) {
161     if (timing_logger_enabled_ || visualizer_enabled_) {
162       if (!IsVerboseMethod(compiler_driver, GetMethodName())) {
163         timing_logger_enabled_ = visualizer_enabled_ = false;
164       }
165       if (visualizer_enabled_) {
166         visualizer_.PrintHeader(GetMethodName());
167         codegen->SetDisassemblyInformation(&disasm_info_);
168       }
169     }
170   }
171 
~PassObserver()172   ~PassObserver() {
173     if (timing_logger_enabled_) {
174       LOG(INFO) << "TIMINGS " << GetMethodName();
175       LOG(INFO) << Dumpable<TimingLogger>(timing_logger_);
176     }
177     DCHECK(visualizer_oss_.str().empty());
178   }
179 
DumpDisassembly()180   void DumpDisassembly() REQUIRES(!visualizer_dump_mutex_) {
181     if (visualizer_enabled_) {
182       visualizer_.DumpGraphWithDisassembly();
183       FlushVisualizer();
184     }
185   }
186 
SetGraphInBadState()187   void SetGraphInBadState() { graph_in_bad_state_ = true; }
188 
GetMethodName()189   const char* GetMethodName() {
190     // PrettyMethod() is expensive, so we delay calling it until we actually have to.
191     if (cached_method_name_.empty()) {
192       cached_method_name_ = graph_->GetDexFile().PrettyMethod(graph_->GetMethodIdx());
193     }
194     return cached_method_name_.c_str();
195   }
196 
197  private:
StartPass(const char * pass_name)198   void StartPass(const char* pass_name) REQUIRES(!visualizer_dump_mutex_) {
199     VLOG(compiler) << "Starting pass: " << pass_name;
200     // Dump graph first, then start timer.
201     if (visualizer_enabled_) {
202       visualizer_.DumpGraph(pass_name, /* is_after_pass */ false, graph_in_bad_state_);
203       FlushVisualizer();
204     }
205     if (timing_logger_enabled_) {
206       timing_logger_.StartTiming(pass_name);
207     }
208   }
209 
FlushVisualizer()210   void FlushVisualizer() REQUIRES(!visualizer_dump_mutex_) {
211     MutexLock mu(Thread::Current(), visualizer_dump_mutex_);
212     *visualizer_output_ << visualizer_oss_.str();
213     visualizer_output_->flush();
214     visualizer_oss_.str("");
215     visualizer_oss_.clear();
216   }
217 
EndPass(const char * pass_name)218   void EndPass(const char* pass_name) REQUIRES(!visualizer_dump_mutex_) {
219     // Pause timer first, then dump graph.
220     if (timing_logger_enabled_) {
221       timing_logger_.EndTiming();
222     }
223     if (visualizer_enabled_) {
224       visualizer_.DumpGraph(pass_name, /* is_after_pass */ true, graph_in_bad_state_);
225       FlushVisualizer();
226     }
227 
228     // Validate the HGraph if running in debug mode.
229     if (kIsDebugBuild) {
230       if (!graph_in_bad_state_) {
231         GraphChecker checker(graph_);
232         checker.Run();
233         if (!checker.IsValid()) {
234           LOG(FATAL) << "Error after " << pass_name << ": " << Dumpable<GraphChecker>(checker);
235         }
236       }
237     }
238   }
239 
IsVerboseMethod(CompilerDriver * compiler_driver,const char * method_name)240   static bool IsVerboseMethod(CompilerDriver* compiler_driver, const char* method_name) {
241     // Test an exact match to --verbose-methods. If verbose-methods is set, this overrides an
242     // empty kStringFilter matching all methods.
243     if (compiler_driver->GetCompilerOptions().HasVerboseMethods()) {
244       return compiler_driver->GetCompilerOptions().IsVerboseMethod(method_name);
245     }
246 
247     // Test the kStringFilter sub-string. constexpr helper variable to silence unreachable-code
248     // warning when the string is empty.
249     constexpr bool kStringFilterEmpty = arraysize(kStringFilter) <= 1;
250     if (kStringFilterEmpty || strstr(method_name, kStringFilter) != nullptr) {
251       return true;
252     }
253 
254     return false;
255   }
256 
257   HGraph* const graph_;
258 
259   std::string cached_method_name_;
260 
261   bool timing_logger_enabled_;
262   TimingLogger timing_logger_;
263 
264   DisassemblyInformation disasm_info_;
265 
266   std::ostringstream visualizer_oss_;
267   std::ostream* visualizer_output_;
268   bool visualizer_enabled_;
269   HGraphVisualizer visualizer_;
270   Mutex& visualizer_dump_mutex_;
271 
272   // Flag to be set by the compiler if the pass failed and the graph is not
273   // expected to validate.
274   bool graph_in_bad_state_;
275 
276   friend PassScope;
277 
278   DISALLOW_COPY_AND_ASSIGN(PassObserver);
279 };
280 
281 class PassScope : public ValueObject {
282  public:
PassScope(const char * pass_name,PassObserver * pass_observer)283   PassScope(const char *pass_name, PassObserver* pass_observer)
284       : pass_name_(pass_name),
285         pass_observer_(pass_observer) {
286     pass_observer_->StartPass(pass_name_);
287   }
288 
~PassScope()289   ~PassScope() {
290     pass_observer_->EndPass(pass_name_);
291   }
292 
293  private:
294   const char* const pass_name_;
295   PassObserver* const pass_observer_;
296 };
297 
298 class OptimizingCompiler FINAL : public Compiler {
299  public:
300   explicit OptimizingCompiler(CompilerDriver* driver);
301   ~OptimizingCompiler() OVERRIDE;
302 
303   bool CanCompileMethod(uint32_t method_idx, const DexFile& dex_file) const OVERRIDE;
304 
305   CompiledMethod* Compile(const DexFile::CodeItem* code_item,
306                           uint32_t access_flags,
307                           InvokeType invoke_type,
308                           uint16_t class_def_idx,
309                           uint32_t method_idx,
310                           Handle<mirror::ClassLoader> class_loader,
311                           const DexFile& dex_file,
312                           Handle<mirror::DexCache> dex_cache) const OVERRIDE;
313 
JniCompile(uint32_t access_flags,uint32_t method_idx,const DexFile & dex_file,JniOptimizationFlags optimization_flags) const314   CompiledMethod* JniCompile(uint32_t access_flags,
315                              uint32_t method_idx,
316                              const DexFile& dex_file,
317                              JniOptimizationFlags optimization_flags) const OVERRIDE {
318     return ArtQuickJniCompileMethod(GetCompilerDriver(),
319                                     access_flags,
320                                     method_idx,
321                                     dex_file,
322                                     optimization_flags);
323   }
324 
GetEntryPointOf(ArtMethod * method) const325   uintptr_t GetEntryPointOf(ArtMethod* method) const OVERRIDE
326       REQUIRES_SHARED(Locks::mutator_lock_) {
327     return reinterpret_cast<uintptr_t>(method->GetEntryPointFromQuickCompiledCodePtrSize(
328         InstructionSetPointerSize(GetCompilerDriver()->GetInstructionSet())));
329   }
330 
331   void Init() OVERRIDE;
332 
333   void UnInit() const OVERRIDE;
334 
MaybeRecordStat(MethodCompilationStat compilation_stat) const335   void MaybeRecordStat(MethodCompilationStat compilation_stat) const {
336     if (compilation_stats_.get() != nullptr) {
337       compilation_stats_->RecordStat(compilation_stat);
338     }
339   }
340 
341   bool JitCompile(Thread* self, jit::JitCodeCache* code_cache, ArtMethod* method, bool osr)
342       OVERRIDE
343       REQUIRES_SHARED(Locks::mutator_lock_);
344 
345  private:
346   void RunOptimizations(HGraph* graph,
347                         CodeGenerator* codegen,
348                         CompilerDriver* driver,
349                         const DexCompilationUnit& dex_compilation_unit,
350                         PassObserver* pass_observer,
351                         VariableSizedHandleScope* handles) const;
352 
353   void RunOptimizations(HOptimization* optimizations[],
354                         size_t length,
355                         PassObserver* pass_observer) const;
356 
357  private:
358   // Create a 'CompiledMethod' for an optimized graph.
359   CompiledMethod* Emit(ArenaAllocator* arena,
360                        CodeVectorAllocator* code_allocator,
361                        CodeGenerator* codegen,
362                        CompilerDriver* driver,
363                        const DexFile::CodeItem* item) const;
364 
365   // Try compiling a method and return the code generator used for
366   // compiling it.
367   // This method:
368   // 1) Builds the graph. Returns null if it failed to build it.
369   // 2) Transforms the graph to SSA. Returns null if it failed.
370   // 3) Runs optimizations on the graph, including register allocator.
371   // 4) Generates code with the `code_allocator` provided.
372   CodeGenerator* TryCompile(ArenaAllocator* arena,
373                             CodeVectorAllocator* code_allocator,
374                             const DexFile::CodeItem* code_item,
375                             uint32_t access_flags,
376                             InvokeType invoke_type,
377                             uint16_t class_def_idx,
378                             uint32_t method_idx,
379                             Handle<mirror::ClassLoader> class_loader,
380                             const DexFile& dex_file,
381                             Handle<mirror::DexCache> dex_cache,
382                             ArtMethod* method,
383                             bool osr,
384                             VariableSizedHandleScope* handles) const;
385 
386   void MaybeRunInliner(HGraph* graph,
387                        CodeGenerator* codegen,
388                        CompilerDriver* driver,
389                        const DexCompilationUnit& dex_compilation_unit,
390                        PassObserver* pass_observer,
391                        VariableSizedHandleScope* handles) const;
392 
393   void RunArchOptimizations(InstructionSet instruction_set,
394                             HGraph* graph,
395                             CodeGenerator* codegen,
396                             PassObserver* pass_observer) const;
397 
398   std::unique_ptr<OptimizingCompilerStats> compilation_stats_;
399 
400   std::unique_ptr<std::ostream> visualizer_output_;
401 
402   mutable Mutex dump_mutex_;  // To synchronize visualizer writing.
403 
404   DISALLOW_COPY_AND_ASSIGN(OptimizingCompiler);
405 };
406 
407 static const int kMaximumCompilationTimeBeforeWarning = 100; /* ms */
408 
OptimizingCompiler(CompilerDriver * driver)409 OptimizingCompiler::OptimizingCompiler(CompilerDriver* driver)
410     : Compiler(driver, kMaximumCompilationTimeBeforeWarning),
411       dump_mutex_("Visualizer dump lock") {}
412 
Init()413 void OptimizingCompiler::Init() {
414   // Enable C1visualizer output. Must be done in Init() because the compiler
415   // driver is not fully initialized when passed to the compiler's constructor.
416   CompilerDriver* driver = GetCompilerDriver();
417   const std::string cfg_file_name = driver->GetCompilerOptions().GetDumpCfgFileName();
418   if (!cfg_file_name.empty()) {
419     std::ios_base::openmode cfg_file_mode =
420         driver->GetCompilerOptions().GetDumpCfgAppend() ? std::ofstream::app : std::ofstream::out;
421     visualizer_output_.reset(new std::ofstream(cfg_file_name, cfg_file_mode));
422   }
423   if (driver->GetDumpStats()) {
424     compilation_stats_.reset(new OptimizingCompilerStats());
425   }
426 }
427 
UnInit() const428 void OptimizingCompiler::UnInit() const {
429 }
430 
~OptimizingCompiler()431 OptimizingCompiler::~OptimizingCompiler() {
432   if (compilation_stats_.get() != nullptr) {
433     compilation_stats_->Log();
434   }
435 }
436 
CanCompileMethod(uint32_t method_idx ATTRIBUTE_UNUSED,const DexFile & dex_file ATTRIBUTE_UNUSED) const437 bool OptimizingCompiler::CanCompileMethod(uint32_t method_idx ATTRIBUTE_UNUSED,
438                                           const DexFile& dex_file ATTRIBUTE_UNUSED) const {
439   return true;
440 }
441 
IsInstructionSetSupported(InstructionSet instruction_set)442 static bool IsInstructionSetSupported(InstructionSet instruction_set) {
443   return (instruction_set == kArm && !kArm32QuickCodeUseSoftFloat)
444       || instruction_set == kArm64
445       || (instruction_set == kThumb2 && !kArm32QuickCodeUseSoftFloat)
446       || instruction_set == kMips
447       || instruction_set == kMips64
448       || instruction_set == kX86
449       || instruction_set == kX86_64;
450 }
451 
452 // Strip pass name suffix to get optimization name.
ConvertPassNameToOptimizationName(const std::string & pass_name)453 static std::string ConvertPassNameToOptimizationName(const std::string& pass_name) {
454   size_t pos = pass_name.find(kPassNameSeparator);
455   return pos == std::string::npos ? pass_name : pass_name.substr(0, pos);
456 }
457 
BuildOptimization(const std::string & pass_name,ArenaAllocator * arena,HGraph * graph,OptimizingCompilerStats * stats,CodeGenerator * codegen,CompilerDriver * driver,const DexCompilationUnit & dex_compilation_unit,VariableSizedHandleScope * handles,SideEffectsAnalysis * most_recent_side_effects,HInductionVarAnalysis * most_recent_induction)458 static HOptimization* BuildOptimization(
459     const std::string& pass_name,
460     ArenaAllocator* arena,
461     HGraph* graph,
462     OptimizingCompilerStats* stats,
463     CodeGenerator* codegen,
464     CompilerDriver* driver,
465     const DexCompilationUnit& dex_compilation_unit,
466     VariableSizedHandleScope* handles,
467     SideEffectsAnalysis* most_recent_side_effects,
468     HInductionVarAnalysis* most_recent_induction) {
469   std::string opt_name = ConvertPassNameToOptimizationName(pass_name);
470   if (opt_name == BoundsCheckElimination::kBoundsCheckEliminationPassName) {
471     CHECK(most_recent_side_effects != nullptr && most_recent_induction != nullptr);
472     return new (arena) BoundsCheckElimination(graph,
473                                               *most_recent_side_effects,
474                                               most_recent_induction);
475   } else if (opt_name == GVNOptimization::kGlobalValueNumberingPassName) {
476     CHECK(most_recent_side_effects != nullptr);
477     return new (arena) GVNOptimization(graph, *most_recent_side_effects, pass_name.c_str());
478   } else if (opt_name == HConstantFolding::kConstantFoldingPassName) {
479     return new (arena) HConstantFolding(graph, pass_name.c_str());
480   } else if (opt_name == HDeadCodeElimination::kDeadCodeEliminationPassName) {
481     return new (arena) HDeadCodeElimination(graph, stats, pass_name.c_str());
482   } else if (opt_name == HInliner::kInlinerPassName) {
483     size_t number_of_dex_registers = dex_compilation_unit.GetCodeItem()->registers_size_;
484     return new (arena) HInliner(graph,                   // outer_graph
485                                 graph,                   // outermost_graph
486                                 codegen,
487                                 dex_compilation_unit,    // outer_compilation_unit
488                                 dex_compilation_unit,    // outermost_compilation_unit
489                                 driver,
490                                 handles,
491                                 stats,
492                                 number_of_dex_registers,
493                                 /* total_number_of_instructions */ 0,
494                                 /* parent */ nullptr);
495   } else if (opt_name == HSharpening::kSharpeningPassName) {
496     return new (arena) HSharpening(graph, codegen, dex_compilation_unit, driver, handles);
497   } else if (opt_name == HSelectGenerator::kSelectGeneratorPassName) {
498     return new (arena) HSelectGenerator(graph, stats);
499   } else if (opt_name == HInductionVarAnalysis::kInductionPassName) {
500     return new (arena) HInductionVarAnalysis(graph);
501   } else if (opt_name == InstructionSimplifier::kInstructionSimplifierPassName) {
502     return new (arena) InstructionSimplifier(graph, codegen, stats, pass_name.c_str());
503   } else if (opt_name == IntrinsicsRecognizer::kIntrinsicsRecognizerPassName) {
504     return new (arena) IntrinsicsRecognizer(graph, stats);
505   } else if (opt_name == LICM::kLoopInvariantCodeMotionPassName) {
506     CHECK(most_recent_side_effects != nullptr);
507     return new (arena) LICM(graph, *most_recent_side_effects, stats);
508   } else if (opt_name == LoadStoreElimination::kLoadStoreEliminationPassName) {
509     CHECK(most_recent_side_effects != nullptr);
510     return new (arena) LoadStoreElimination(graph, *most_recent_side_effects);
511   } else if (opt_name == SideEffectsAnalysis::kSideEffectsAnalysisPassName) {
512     return new (arena) SideEffectsAnalysis(graph);
513   } else if (opt_name == HLoopOptimization::kLoopOptimizationPassName) {
514     return new (arena) HLoopOptimization(graph, driver, most_recent_induction);
515   } else if (opt_name == CHAGuardOptimization::kCHAGuardOptimizationPassName) {
516     return new (arena) CHAGuardOptimization(graph);
517   } else if (opt_name == CodeSinking::kCodeSinkingPassName) {
518     return new (arena) CodeSinking(graph, stats);
519 #ifdef ART_ENABLE_CODEGEN_arm
520   } else if (opt_name == arm::DexCacheArrayFixups::kDexCacheArrayFixupsArmPassName) {
521     return new (arena) arm::DexCacheArrayFixups(graph, codegen, stats);
522   } else if (opt_name == arm::InstructionSimplifierArm::kInstructionSimplifierArmPassName) {
523     return new (arena) arm::InstructionSimplifierArm(graph, stats);
524 #endif
525 #ifdef ART_ENABLE_CODEGEN_arm64
526   } else if (opt_name == arm64::InstructionSimplifierArm64::kInstructionSimplifierArm64PassName) {
527     return new (arena) arm64::InstructionSimplifierArm64(graph, stats);
528 #endif
529 #ifdef ART_ENABLE_CODEGEN_mips
530   } else if (opt_name == mips::DexCacheArrayFixups::kDexCacheArrayFixupsMipsPassName) {
531     return new (arena) mips::DexCacheArrayFixups(graph, codegen, stats);
532   } else if (opt_name == mips::PcRelativeFixups::kPcRelativeFixupsMipsPassName) {
533     return new (arena) mips::PcRelativeFixups(graph, codegen, stats);
534 #endif
535 #ifdef ART_ENABLE_CODEGEN_x86
536   } else if (opt_name == x86::PcRelativeFixups::kPcRelativeFixupsX86PassName) {
537     return new (arena) x86::PcRelativeFixups(graph, codegen, stats);
538   } else if (opt_name == x86::X86MemoryOperandGeneration::kX86MemoryOperandGenerationPassName) {
539     return new (arena) x86::X86MemoryOperandGeneration(graph, codegen, stats);
540 #endif
541   }
542   return nullptr;
543 }
544 
BuildOptimizations(const std::vector<std::string> & pass_names,ArenaAllocator * arena,HGraph * graph,OptimizingCompilerStats * stats,CodeGenerator * codegen,CompilerDriver * driver,const DexCompilationUnit & dex_compilation_unit,VariableSizedHandleScope * handles)545 static ArenaVector<HOptimization*> BuildOptimizations(
546     const std::vector<std::string>& pass_names,
547     ArenaAllocator* arena,
548     HGraph* graph,
549     OptimizingCompilerStats* stats,
550     CodeGenerator* codegen,
551     CompilerDriver* driver,
552     const DexCompilationUnit& dex_compilation_unit,
553     VariableSizedHandleScope* handles) {
554   // Few HOptimizations constructors require SideEffectsAnalysis or HInductionVarAnalysis
555   // instances. This method assumes that each of them expects the nearest instance preceeding it
556   // in the pass name list.
557   SideEffectsAnalysis* most_recent_side_effects = nullptr;
558   HInductionVarAnalysis* most_recent_induction = nullptr;
559   ArenaVector<HOptimization*> ret(arena->Adapter());
560   for (const std::string& pass_name : pass_names) {
561     HOptimization* opt = BuildOptimization(
562         pass_name,
563         arena,
564         graph,
565         stats,
566         codegen,
567         driver,
568         dex_compilation_unit,
569         handles,
570         most_recent_side_effects,
571         most_recent_induction);
572     CHECK(opt != nullptr) << "Couldn't build optimization: \"" << pass_name << "\"";
573     ret.push_back(opt);
574 
575     std::string opt_name = ConvertPassNameToOptimizationName(pass_name);
576     if (opt_name == SideEffectsAnalysis::kSideEffectsAnalysisPassName) {
577       most_recent_side_effects = down_cast<SideEffectsAnalysis*>(opt);
578     } else if (opt_name == HInductionVarAnalysis::kInductionPassName) {
579       most_recent_induction = down_cast<HInductionVarAnalysis*>(opt);
580     }
581   }
582   return ret;
583 }
584 
RunOptimizations(HOptimization * optimizations[],size_t length,PassObserver * pass_observer) const585 void OptimizingCompiler::RunOptimizations(HOptimization* optimizations[],
586                                           size_t length,
587                                           PassObserver* pass_observer) const {
588   for (size_t i = 0; i < length; ++i) {
589     PassScope scope(optimizations[i]->GetPassName(), pass_observer);
590     optimizations[i]->Run();
591   }
592 }
593 
MaybeRunInliner(HGraph * graph,CodeGenerator * codegen,CompilerDriver * driver,const DexCompilationUnit & dex_compilation_unit,PassObserver * pass_observer,VariableSizedHandleScope * handles) const594 void OptimizingCompiler::MaybeRunInliner(HGraph* graph,
595                                          CodeGenerator* codegen,
596                                          CompilerDriver* driver,
597                                          const DexCompilationUnit& dex_compilation_unit,
598                                          PassObserver* pass_observer,
599                                          VariableSizedHandleScope* handles) const {
600   OptimizingCompilerStats* stats = compilation_stats_.get();
601   const CompilerOptions& compiler_options = driver->GetCompilerOptions();
602   bool should_inline = (compiler_options.GetInlineMaxCodeUnits() > 0);
603   if (!should_inline) {
604     return;
605   }
606   size_t number_of_dex_registers = dex_compilation_unit.GetCodeItem()->registers_size_;
607   HInliner* inliner = new (graph->GetArena()) HInliner(
608       graph,                   // outer_graph
609       graph,                   // outermost_graph
610       codegen,
611       dex_compilation_unit,    // outer_compilation_unit
612       dex_compilation_unit,    // outermost_compilation_unit
613       driver,
614       handles,
615       stats,
616       number_of_dex_registers,
617       /* total_number_of_instructions */ 0,
618       /* parent */ nullptr);
619   HOptimization* optimizations[] = { inliner };
620 
621   RunOptimizations(optimizations, arraysize(optimizations), pass_observer);
622 }
623 
RunArchOptimizations(InstructionSet instruction_set,HGraph * graph,CodeGenerator * codegen,PassObserver * pass_observer) const624 void OptimizingCompiler::RunArchOptimizations(InstructionSet instruction_set,
625                                               HGraph* graph,
626                                               CodeGenerator* codegen,
627                                               PassObserver* pass_observer) const {
628   UNUSED(codegen);  // To avoid compilation error when compiling for svelte
629   OptimizingCompilerStats* stats = compilation_stats_.get();
630   ArenaAllocator* arena = graph->GetArena();
631   switch (instruction_set) {
632 #if defined(ART_ENABLE_CODEGEN_arm)
633     case kThumb2:
634     case kArm: {
635       arm::DexCacheArrayFixups* fixups =
636           new (arena) arm::DexCacheArrayFixups(graph, codegen, stats);
637       arm::InstructionSimplifierArm* simplifier =
638           new (arena) arm::InstructionSimplifierArm(graph, stats);
639       SideEffectsAnalysis* side_effects = new (arena) SideEffectsAnalysis(graph);
640       GVNOptimization* gvn = new (arena) GVNOptimization(graph, *side_effects, "GVN$after_arch");
641       HOptimization* arm_optimizations[] = {
642         simplifier,
643         side_effects,
644         gvn,
645         fixups
646       };
647       RunOptimizations(arm_optimizations, arraysize(arm_optimizations), pass_observer);
648       break;
649     }
650 #endif
651 #ifdef ART_ENABLE_CODEGEN_arm64
652     case kArm64: {
653       arm64::InstructionSimplifierArm64* simplifier =
654           new (arena) arm64::InstructionSimplifierArm64(graph, stats);
655       SideEffectsAnalysis* side_effects = new (arena) SideEffectsAnalysis(graph);
656       GVNOptimization* gvn = new (arena) GVNOptimization(graph, *side_effects, "GVN$after_arch");
657       HInstructionScheduling* scheduling =
658           new (arena) HInstructionScheduling(graph, instruction_set);
659       HOptimization* arm64_optimizations[] = {
660         simplifier,
661         side_effects,
662         gvn,
663         scheduling,
664       };
665       RunOptimizations(arm64_optimizations, arraysize(arm64_optimizations), pass_observer);
666       break;
667     }
668 #endif
669 #ifdef ART_ENABLE_CODEGEN_mips
670     case kMips: {
671       mips::PcRelativeFixups* pc_relative_fixups =
672           new (arena) mips::PcRelativeFixups(graph, codegen, stats);
673       mips::DexCacheArrayFixups* dex_cache_array_fixups =
674           new (arena) mips::DexCacheArrayFixups(graph, codegen, stats);
675       HOptimization* mips_optimizations[] = {
676           pc_relative_fixups,
677           dex_cache_array_fixups
678       };
679       RunOptimizations(mips_optimizations, arraysize(mips_optimizations), pass_observer);
680       break;
681     }
682 #endif
683 #ifdef ART_ENABLE_CODEGEN_x86
684     case kX86: {
685       x86::PcRelativeFixups* pc_relative_fixups =
686           new (arena) x86::PcRelativeFixups(graph, codegen, stats);
687       x86::X86MemoryOperandGeneration* memory_gen =
688           new (arena) x86::X86MemoryOperandGeneration(graph, codegen, stats);
689       HOptimization* x86_optimizations[] = {
690           pc_relative_fixups,
691           memory_gen
692       };
693       RunOptimizations(x86_optimizations, arraysize(x86_optimizations), pass_observer);
694       break;
695     }
696 #endif
697 #ifdef ART_ENABLE_CODEGEN_x86_64
698     case kX86_64: {
699       x86::X86MemoryOperandGeneration* memory_gen =
700           new (arena) x86::X86MemoryOperandGeneration(graph, codegen, stats);
701       HOptimization* x86_64_optimizations[] = {
702           memory_gen
703       };
704       RunOptimizations(x86_64_optimizations, arraysize(x86_64_optimizations), pass_observer);
705       break;
706     }
707 #endif
708     default:
709       break;
710   }
711 }
712 
713 NO_INLINE  // Avoid increasing caller's frame size by large stack-allocated objects.
AllocateRegisters(HGraph * graph,CodeGenerator * codegen,PassObserver * pass_observer,RegisterAllocator::Strategy strategy)714 static void AllocateRegisters(HGraph* graph,
715                               CodeGenerator* codegen,
716                               PassObserver* pass_observer,
717                               RegisterAllocator::Strategy strategy) {
718   {
719     PassScope scope(PrepareForRegisterAllocation::kPrepareForRegisterAllocationPassName,
720                     pass_observer);
721     PrepareForRegisterAllocation(graph).Run();
722   }
723   SsaLivenessAnalysis liveness(graph, codegen);
724   {
725     PassScope scope(SsaLivenessAnalysis::kLivenessPassName, pass_observer);
726     liveness.Analyze();
727   }
728   {
729     PassScope scope(RegisterAllocator::kRegisterAllocatorPassName, pass_observer);
730     RegisterAllocator::Create(graph->GetArena(), codegen, liveness, strategy)->AllocateRegisters();
731   }
732 }
733 
RunOptimizations(HGraph * graph,CodeGenerator * codegen,CompilerDriver * driver,const DexCompilationUnit & dex_compilation_unit,PassObserver * pass_observer,VariableSizedHandleScope * handles) const734 void OptimizingCompiler::RunOptimizations(HGraph* graph,
735                                           CodeGenerator* codegen,
736                                           CompilerDriver* driver,
737                                           const DexCompilationUnit& dex_compilation_unit,
738                                           PassObserver* pass_observer,
739                                           VariableSizedHandleScope* handles) const {
740   OptimizingCompilerStats* stats = compilation_stats_.get();
741   ArenaAllocator* arena = graph->GetArena();
742   if (driver->GetCompilerOptions().GetPassesToRun() != nullptr) {
743     ArenaVector<HOptimization*> optimizations = BuildOptimizations(
744         *driver->GetCompilerOptions().GetPassesToRun(),
745         arena,
746         graph,
747         stats,
748         codegen,
749         driver,
750         dex_compilation_unit,
751         handles);
752     RunOptimizations(&optimizations[0], optimizations.size(), pass_observer);
753     return;
754   }
755 
756   HDeadCodeElimination* dce1 = new (arena) HDeadCodeElimination(
757       graph, stats, "dead_code_elimination$initial");
758   HDeadCodeElimination* dce2 = new (arena) HDeadCodeElimination(
759       graph, stats, "dead_code_elimination$after_inlining");
760   HDeadCodeElimination* dce3 = new (arena) HDeadCodeElimination(
761       graph, stats, "dead_code_elimination$final");
762   HConstantFolding* fold1 = new (arena) HConstantFolding(graph, "constant_folding");
763   InstructionSimplifier* simplify1 = new (arena) InstructionSimplifier(graph, codegen, stats);
764   HSelectGenerator* select_generator = new (arena) HSelectGenerator(graph, stats);
765   HConstantFolding* fold2 = new (arena) HConstantFolding(
766       graph, "constant_folding$after_inlining");
767   HConstantFolding* fold3 = new (arena) HConstantFolding(graph, "constant_folding$after_bce");
768   SideEffectsAnalysis* side_effects1 = new (arena) SideEffectsAnalysis(
769       graph, "side_effects$before_gvn");
770   SideEffectsAnalysis* side_effects2 = new (arena) SideEffectsAnalysis(
771       graph, "side_effects$before_lse");
772   GVNOptimization* gvn = new (arena) GVNOptimization(graph, *side_effects1);
773   LICM* licm = new (arena) LICM(graph, *side_effects1, stats);
774   HInductionVarAnalysis* induction = new (arena) HInductionVarAnalysis(graph);
775   BoundsCheckElimination* bce = new (arena) BoundsCheckElimination(graph, *side_effects1, induction);
776   HLoopOptimization* loop = new (arena) HLoopOptimization(graph, driver, induction);
777   LoadStoreElimination* lse = new (arena) LoadStoreElimination(graph, *side_effects2);
778   HSharpening* sharpening = new (arena) HSharpening(
779       graph, codegen, dex_compilation_unit, driver, handles);
780   InstructionSimplifier* simplify2 = new (arena) InstructionSimplifier(
781       graph, codegen, stats, "instruction_simplifier$after_inlining");
782   InstructionSimplifier* simplify3 = new (arena) InstructionSimplifier(
783       graph, codegen, stats, "instruction_simplifier$after_bce");
784   InstructionSimplifier* simplify4 = new (arena) InstructionSimplifier(
785       graph, codegen, stats, "instruction_simplifier$before_codegen");
786   IntrinsicsRecognizer* intrinsics = new (arena) IntrinsicsRecognizer(graph, stats);
787   CHAGuardOptimization* cha_guard = new (arena) CHAGuardOptimization(graph);
788   CodeSinking* code_sinking = new (arena) CodeSinking(graph, stats);
789 
790   HOptimization* optimizations1[] = {
791     intrinsics,
792     sharpening,
793     fold1,
794     simplify1,
795     dce1,
796   };
797   RunOptimizations(optimizations1, arraysize(optimizations1), pass_observer);
798 
799   MaybeRunInliner(graph, codegen, driver, dex_compilation_unit, pass_observer, handles);
800 
801   HOptimization* optimizations2[] = {
802     // SelectGenerator depends on the InstructionSimplifier removing
803     // redundant suspend checks to recognize empty blocks.
804     select_generator,
805     fold2,  // TODO: if we don't inline we can also skip fold2.
806     simplify2,
807     dce2,
808     side_effects1,
809     gvn,
810     licm,
811     induction,
812     bce,
813     loop,
814     fold3,  // evaluates code generated by dynamic bce
815     simplify3,
816     side_effects2,
817     lse,
818     cha_guard,
819     dce3,
820     code_sinking,
821     // The codegen has a few assumptions that only the instruction simplifier
822     // can satisfy. For example, the code generator does not expect to see a
823     // HTypeConversion from a type to the same type.
824     simplify4,
825   };
826   RunOptimizations(optimizations2, arraysize(optimizations2), pass_observer);
827 
828   RunArchOptimizations(driver->GetInstructionSet(), graph, codegen, pass_observer);
829 }
830 
EmitAndSortLinkerPatches(CodeGenerator * codegen)831 static ArenaVector<LinkerPatch> EmitAndSortLinkerPatches(CodeGenerator* codegen) {
832   ArenaVector<LinkerPatch> linker_patches(codegen->GetGraph()->GetArena()->Adapter());
833   codegen->EmitLinkerPatches(&linker_patches);
834 
835   // Sort patches by literal offset. Required for .oat_patches encoding.
836   std::sort(linker_patches.begin(), linker_patches.end(),
837             [](const LinkerPatch& lhs, const LinkerPatch& rhs) {
838     return lhs.LiteralOffset() < rhs.LiteralOffset();
839   });
840 
841   return linker_patches;
842 }
843 
Emit(ArenaAllocator * arena,CodeVectorAllocator * code_allocator,CodeGenerator * codegen,CompilerDriver * compiler_driver,const DexFile::CodeItem * code_item) const844 CompiledMethod* OptimizingCompiler::Emit(ArenaAllocator* arena,
845                                          CodeVectorAllocator* code_allocator,
846                                          CodeGenerator* codegen,
847                                          CompilerDriver* compiler_driver,
848                                          const DexFile::CodeItem* code_item) const {
849   ArenaVector<LinkerPatch> linker_patches = EmitAndSortLinkerPatches(codegen);
850   ArenaVector<uint8_t> stack_map(arena->Adapter(kArenaAllocStackMaps));
851   ArenaVector<uint8_t> method_info(arena->Adapter(kArenaAllocStackMaps));
852   size_t stack_map_size = 0;
853   size_t method_info_size = 0;
854   codegen->ComputeStackMapAndMethodInfoSize(&stack_map_size, &method_info_size);
855   stack_map.resize(stack_map_size);
856   method_info.resize(method_info_size);
857   codegen->BuildStackMaps(MemoryRegion(stack_map.data(), stack_map.size()),
858                           MemoryRegion(method_info.data(), method_info.size()),
859                           *code_item);
860 
861   CompiledMethod* compiled_method = CompiledMethod::SwapAllocCompiledMethod(
862       compiler_driver,
863       codegen->GetInstructionSet(),
864       ArrayRef<const uint8_t>(code_allocator->GetMemory()),
865       // Follow Quick's behavior and set the frame size to zero if it is
866       // considered "empty" (see the definition of
867       // art::CodeGenerator::HasEmptyFrame).
868       codegen->HasEmptyFrame() ? 0 : codegen->GetFrameSize(),
869       codegen->GetCoreSpillMask(),
870       codegen->GetFpuSpillMask(),
871       ArrayRef<const uint8_t>(method_info),
872       ArrayRef<const uint8_t>(stack_map),
873       ArrayRef<const uint8_t>(*codegen->GetAssembler()->cfi().data()),
874       ArrayRef<const LinkerPatch>(linker_patches));
875 
876   return compiled_method;
877 }
878 
TryCompile(ArenaAllocator * arena,CodeVectorAllocator * code_allocator,const DexFile::CodeItem * code_item,uint32_t access_flags,InvokeType invoke_type,uint16_t class_def_idx,uint32_t method_idx,Handle<mirror::ClassLoader> class_loader,const DexFile & dex_file,Handle<mirror::DexCache> dex_cache,ArtMethod * method,bool osr,VariableSizedHandleScope * handles) const879 CodeGenerator* OptimizingCompiler::TryCompile(ArenaAllocator* arena,
880                                               CodeVectorAllocator* code_allocator,
881                                               const DexFile::CodeItem* code_item,
882                                               uint32_t access_flags,
883                                               InvokeType invoke_type,
884                                               uint16_t class_def_idx,
885                                               uint32_t method_idx,
886                                               Handle<mirror::ClassLoader> class_loader,
887                                               const DexFile& dex_file,
888                                               Handle<mirror::DexCache> dex_cache,
889                                               ArtMethod* method,
890                                               bool osr,
891                                               VariableSizedHandleScope* handles) const {
892   MaybeRecordStat(MethodCompilationStat::kAttemptCompilation);
893   CompilerDriver* compiler_driver = GetCompilerDriver();
894   InstructionSet instruction_set = compiler_driver->GetInstructionSet();
895 
896   // Always use the Thumb-2 assembler: some runtime functionality
897   // (like implicit stack overflow checks) assume Thumb-2.
898   DCHECK_NE(instruction_set, kArm);
899 
900   // Do not attempt to compile on architectures we do not support.
901   if (!IsInstructionSetSupported(instruction_set)) {
902     MaybeRecordStat(MethodCompilationStat::kNotCompiledUnsupportedIsa);
903     return nullptr;
904   }
905 
906   if (Compiler::IsPathologicalCase(*code_item, method_idx, dex_file)) {
907     MaybeRecordStat(MethodCompilationStat::kNotCompiledPathological);
908     return nullptr;
909   }
910 
911   // Implementation of the space filter: do not compile a code item whose size in
912   // code units is bigger than 128.
913   static constexpr size_t kSpaceFilterOptimizingThreshold = 128;
914   const CompilerOptions& compiler_options = compiler_driver->GetCompilerOptions();
915   if ((compiler_options.GetCompilerFilter() == CompilerFilter::kSpace)
916       && (code_item->insns_size_in_code_units_ > kSpaceFilterOptimizingThreshold)) {
917     MaybeRecordStat(MethodCompilationStat::kNotCompiledSpaceFilter);
918     return nullptr;
919   }
920 
921   ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
922   DexCompilationUnit dex_compilation_unit(
923       class_loader,
924       class_linker,
925       dex_file,
926       code_item,
927       class_def_idx,
928       method_idx,
929       access_flags,
930       /* verified_method */ nullptr,
931       dex_cache);
932 
933   HGraph* graph = new (arena) HGraph(
934       arena,
935       dex_file,
936       method_idx,
937       compiler_driver->GetInstructionSet(),
938       kInvalidInvokeType,
939       compiler_driver->GetCompilerOptions().GetDebuggable(),
940       osr);
941 
942   const uint8_t* interpreter_metadata = nullptr;
943   if (method == nullptr) {
944     ScopedObjectAccess soa(Thread::Current());
945     method = compiler_driver->ResolveMethod(
946         soa, dex_cache, class_loader, &dex_compilation_unit, method_idx, invoke_type);
947   }
948   // For AOT compilation, we may not get a method, for example if its class is erroneous.
949   // JIT should always have a method.
950   DCHECK(Runtime::Current()->IsAotCompiler() || method != nullptr);
951   if (method != nullptr) {
952     graph->SetArtMethod(method);
953     ScopedObjectAccess soa(Thread::Current());
954     interpreter_metadata = method->GetQuickenedInfo(class_linker->GetImagePointerSize());
955   }
956 
957   std::unique_ptr<CodeGenerator> codegen(
958       CodeGenerator::Create(graph,
959                             instruction_set,
960                             *compiler_driver->GetInstructionSetFeatures(),
961                             compiler_driver->GetCompilerOptions(),
962                             compilation_stats_.get()));
963   if (codegen.get() == nullptr) {
964     MaybeRecordStat(MethodCompilationStat::kNotCompiledNoCodegen);
965     return nullptr;
966   }
967   codegen->GetAssembler()->cfi().SetEnabled(
968       compiler_driver->GetCompilerOptions().GenerateAnyDebugInfo());
969 
970   PassObserver pass_observer(graph,
971                              codegen.get(),
972                              visualizer_output_.get(),
973                              compiler_driver,
974                              dump_mutex_);
975 
976   {
977     VLOG(compiler) << "Building " << pass_observer.GetMethodName();
978     PassScope scope(HGraphBuilder::kBuilderPassName, &pass_observer);
979     HGraphBuilder builder(graph,
980                           &dex_compilation_unit,
981                           &dex_compilation_unit,
982                           &dex_file,
983                           *code_item,
984                           compiler_driver,
985                           codegen.get(),
986                           compilation_stats_.get(),
987                           interpreter_metadata,
988                           dex_cache,
989                           handles);
990     GraphAnalysisResult result = builder.BuildGraph();
991     if (result != kAnalysisSuccess) {
992       switch (result) {
993         case kAnalysisSkipped:
994           MaybeRecordStat(MethodCompilationStat::kNotCompiledSkipped);
995           break;
996         case kAnalysisInvalidBytecode:
997           MaybeRecordStat(MethodCompilationStat::kNotCompiledInvalidBytecode);
998           break;
999         case kAnalysisFailThrowCatchLoop:
1000           MaybeRecordStat(MethodCompilationStat::kNotCompiledThrowCatchLoop);
1001           break;
1002         case kAnalysisFailAmbiguousArrayOp:
1003           MaybeRecordStat(MethodCompilationStat::kNotCompiledAmbiguousArrayOp);
1004           break;
1005         case kAnalysisSuccess:
1006           UNREACHABLE();
1007       }
1008       pass_observer.SetGraphInBadState();
1009       return nullptr;
1010     }
1011   }
1012 
1013   RunOptimizations(graph,
1014                    codegen.get(),
1015                    compiler_driver,
1016                    dex_compilation_unit,
1017                    &pass_observer,
1018                    handles);
1019 
1020   RegisterAllocator::Strategy regalloc_strategy =
1021     compiler_options.GetRegisterAllocationStrategy();
1022   AllocateRegisters(graph, codegen.get(), &pass_observer, regalloc_strategy);
1023 
1024   codegen->Compile(code_allocator);
1025   pass_observer.DumpDisassembly();
1026 
1027   return codegen.release();
1028 }
1029 
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) const1030 CompiledMethod* OptimizingCompiler::Compile(const DexFile::CodeItem* code_item,
1031                                             uint32_t access_flags,
1032                                             InvokeType invoke_type,
1033                                             uint16_t class_def_idx,
1034                                             uint32_t method_idx,
1035                                             Handle<mirror::ClassLoader> jclass_loader,
1036                                             const DexFile& dex_file,
1037                                             Handle<mirror::DexCache> dex_cache) const {
1038   CompilerDriver* compiler_driver = GetCompilerDriver();
1039   CompiledMethod* method = nullptr;
1040   DCHECK(Runtime::Current()->IsAotCompiler());
1041   const VerifiedMethod* verified_method = compiler_driver->GetVerifiedMethod(&dex_file, method_idx);
1042   DCHECK(!verified_method->HasRuntimeThrow());
1043   if (compiler_driver->IsMethodVerifiedWithoutFailures(method_idx, class_def_idx, dex_file)
1044       || verifier::CanCompilerHandleVerificationFailure(
1045             verified_method->GetEncounteredVerificationFailures())) {
1046     ArenaAllocator arena(Runtime::Current()->GetArenaPool());
1047     CodeVectorAllocator code_allocator(&arena);
1048     std::unique_ptr<CodeGenerator> codegen;
1049     {
1050       ScopedObjectAccess soa(Thread::Current());
1051       VariableSizedHandleScope handles(soa.Self());
1052       // Go to native so that we don't block GC during compilation.
1053       ScopedThreadSuspension sts(soa.Self(), kNative);
1054       codegen.reset(
1055           TryCompile(&arena,
1056                      &code_allocator,
1057                      code_item,
1058                      access_flags,
1059                      invoke_type,
1060                      class_def_idx,
1061                      method_idx,
1062                      jclass_loader,
1063                      dex_file,
1064                      dex_cache,
1065                      nullptr,
1066                      /* osr */ false,
1067                      &handles));
1068     }
1069     if (codegen.get() != nullptr) {
1070       MaybeRecordStat(MethodCompilationStat::kCompiled);
1071       method = Emit(&arena, &code_allocator, codegen.get(), compiler_driver, code_item);
1072 
1073       if (kArenaAllocatorCountAllocations) {
1074         if (arena.BytesAllocated() > kArenaAllocatorMemoryReportThreshold) {
1075           MemStats mem_stats(arena.GetMemStats());
1076           LOG(INFO) << dex_file.PrettyMethod(method_idx) << " " << Dumpable<MemStats>(mem_stats);
1077         }
1078       }
1079     }
1080   } else {
1081     if (compiler_driver->GetCompilerOptions().VerifyAtRuntime()) {
1082       MaybeRecordStat(MethodCompilationStat::kNotCompiledVerifyAtRuntime);
1083     } else {
1084       MaybeRecordStat(MethodCompilationStat::kNotCompiledVerificationError);
1085     }
1086   }
1087 
1088   if (kIsDebugBuild &&
1089       IsCompilingWithCoreImage() &&
1090       IsInstructionSetSupported(compiler_driver->GetInstructionSet())) {
1091     // For testing purposes, we put a special marker on method names
1092     // that should be compiled with this compiler (when the
1093     // instruction set is supported). This makes sure we're not
1094     // regressing.
1095     std::string method_name = dex_file.PrettyMethod(method_idx);
1096     bool shouldCompile = method_name.find("$opt$") != std::string::npos;
1097     DCHECK((method != nullptr) || !shouldCompile) << "Didn't compile " << method_name;
1098   }
1099 
1100   return method;
1101 }
1102 
CreateOptimizingCompiler(CompilerDriver * driver)1103 Compiler* CreateOptimizingCompiler(CompilerDriver* driver) {
1104   return new OptimizingCompiler(driver);
1105 }
1106 
IsCompilingWithCoreImage()1107 bool IsCompilingWithCoreImage() {
1108   const std::string& image = Runtime::Current()->GetImageLocation();
1109   // TODO: This is under-approximating...
1110   if (android::base::EndsWith(image, "core.art") ||
1111       android::base::EndsWith(image, "core-optimizing.art")) {
1112     return true;
1113   }
1114   return false;
1115 }
1116 
EncodeArtMethodInInlineInfo(ArtMethod * method ATTRIBUTE_UNUSED)1117 bool EncodeArtMethodInInlineInfo(ArtMethod* method ATTRIBUTE_UNUSED) {
1118   // Note: the runtime is null only for unit testing.
1119   return Runtime::Current() == nullptr || !Runtime::Current()->IsAotCompiler();
1120 }
1121 
CanEncodeInlinedMethodInStackMap(const DexFile & caller_dex_file,ArtMethod * callee)1122 bool CanEncodeInlinedMethodInStackMap(const DexFile& caller_dex_file, ArtMethod* callee) {
1123   if (!Runtime::Current()->IsAotCompiler()) {
1124     // JIT can always encode methods in stack maps.
1125     return true;
1126   }
1127   if (IsSameDexFile(caller_dex_file, *callee->GetDexFile())) {
1128     return true;
1129   }
1130   // TODO(ngeoffray): Support more AOT cases for inlining:
1131   // - methods in multidex
1132   // - methods in boot image for on-device non-PIC compilation.
1133   return false;
1134 }
1135 
JitCompile(Thread * self,jit::JitCodeCache * code_cache,ArtMethod * method,bool osr)1136 bool OptimizingCompiler::JitCompile(Thread* self,
1137                                     jit::JitCodeCache* code_cache,
1138                                     ArtMethod* method,
1139                                     bool osr) {
1140   StackHandleScope<3> hs(self);
1141   Handle<mirror::ClassLoader> class_loader(hs.NewHandle(
1142       method->GetDeclaringClass()->GetClassLoader()));
1143   Handle<mirror::DexCache> dex_cache(hs.NewHandle(method->GetDexCache()));
1144   DCHECK(method->IsCompilable());
1145 
1146   const DexFile* dex_file = method->GetDexFile();
1147   const uint16_t class_def_idx = method->GetClassDefIndex();
1148   const DexFile::CodeItem* code_item = dex_file->GetCodeItem(method->GetCodeItemOffset());
1149   const uint32_t method_idx = method->GetDexMethodIndex();
1150   const uint32_t access_flags = method->GetAccessFlags();
1151   const InvokeType invoke_type = method->GetInvokeType();
1152 
1153   ArenaAllocator arena(Runtime::Current()->GetJitArenaPool());
1154   CodeVectorAllocator code_allocator(&arena);
1155   VariableSizedHandleScope handles(self);
1156 
1157   std::unique_ptr<CodeGenerator> codegen;
1158   {
1159     // Go to native so that we don't block GC during compilation.
1160     ScopedThreadSuspension sts(self, kNative);
1161     codegen.reset(
1162         TryCompile(&arena,
1163                    &code_allocator,
1164                    code_item,
1165                    access_flags,
1166                    invoke_type,
1167                    class_def_idx,
1168                    method_idx,
1169                    class_loader,
1170                    *dex_file,
1171                    dex_cache,
1172                    method,
1173                    osr,
1174                    &handles));
1175     if (codegen.get() == nullptr) {
1176       return false;
1177     }
1178 
1179     if (kArenaAllocatorCountAllocations) {
1180       if (arena.BytesAllocated() > kArenaAllocatorMemoryReportThreshold) {
1181         MemStats mem_stats(arena.GetMemStats());
1182         LOG(INFO) << dex_file->PrettyMethod(method_idx) << " " << Dumpable<MemStats>(mem_stats);
1183       }
1184     }
1185   }
1186 
1187   size_t stack_map_size = 0;
1188   size_t method_info_size = 0;
1189   codegen->ComputeStackMapAndMethodInfoSize(&stack_map_size, &method_info_size);
1190   size_t number_of_roots = codegen->GetNumberOfJitRoots();
1191   ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
1192   // We allocate an object array to ensure the JIT roots that we will collect in EmitJitRoots
1193   // will be visible by the GC between EmitLiterals and CommitCode. Once CommitCode is
1194   // executed, this array is not needed.
1195   Handle<mirror::ObjectArray<mirror::Object>> roots(
1196       hs.NewHandle(mirror::ObjectArray<mirror::Object>::Alloc(
1197           self, class_linker->GetClassRoot(ClassLinker::kObjectArrayClass), number_of_roots)));
1198   if (roots == nullptr) {
1199     // Out of memory, just clear the exception to avoid any Java exception uncaught problems.
1200     DCHECK(self->IsExceptionPending());
1201     self->ClearException();
1202     return false;
1203   }
1204   uint8_t* stack_map_data = nullptr;
1205   uint8_t* method_info_data = nullptr;
1206   uint8_t* roots_data = nullptr;
1207   uint32_t data_size = code_cache->ReserveData(self,
1208                                                stack_map_size,
1209                                                method_info_size,
1210                                                number_of_roots,
1211                                                method,
1212                                                &stack_map_data,
1213                                                &method_info_data,
1214                                                &roots_data);
1215   if (stack_map_data == nullptr || roots_data == nullptr) {
1216     return false;
1217   }
1218   MaybeRecordStat(MethodCompilationStat::kCompiled);
1219   codegen->BuildStackMaps(MemoryRegion(stack_map_data, stack_map_size),
1220                           MemoryRegion(method_info_data, method_info_size),
1221                           *code_item);
1222   codegen->EmitJitRoots(code_allocator.GetData(), roots, roots_data);
1223 
1224   const void* code = code_cache->CommitCode(
1225       self,
1226       method,
1227       stack_map_data,
1228       method_info_data,
1229       roots_data,
1230       codegen->HasEmptyFrame() ? 0 : codegen->GetFrameSize(),
1231       codegen->GetCoreSpillMask(),
1232       codegen->GetFpuSpillMask(),
1233       code_allocator.GetMemory().data(),
1234       code_allocator.GetSize(),
1235       data_size,
1236       osr,
1237       roots,
1238       codegen->GetGraph()->HasShouldDeoptimizeFlag(),
1239       codegen->GetGraph()->GetCHASingleImplementationList());
1240 
1241   if (code == nullptr) {
1242     code_cache->ClearData(self, stack_map_data, roots_data);
1243     return false;
1244   }
1245 
1246   const CompilerOptions& compiler_options = GetCompilerDriver()->GetCompilerOptions();
1247   if (compiler_options.GetGenerateDebugInfo()) {
1248     const auto* method_header = reinterpret_cast<const OatQuickMethodHeader*>(code);
1249     const uintptr_t code_address = reinterpret_cast<uintptr_t>(method_header->GetCode());
1250     debug::MethodDebugInfo info = debug::MethodDebugInfo();
1251     info.trampoline_name = nullptr;
1252     info.dex_file = dex_file;
1253     info.class_def_index = class_def_idx;
1254     info.dex_method_index = method_idx;
1255     info.access_flags = access_flags;
1256     info.code_item = code_item;
1257     info.isa = codegen->GetInstructionSet();
1258     info.deduped = false;
1259     info.is_native_debuggable = compiler_options.GetNativeDebuggable();
1260     info.is_optimized = true;
1261     info.is_code_address_text_relative = false;
1262     info.code_address = code_address;
1263     info.code_size = code_allocator.GetSize();
1264     info.frame_size_in_bytes = method_header->GetFrameSizeInBytes();
1265     info.code_info = stack_map_size == 0 ? nullptr : stack_map_data;
1266     info.cfi = ArrayRef<const uint8_t>(*codegen->GetAssembler()->cfi().data());
1267     std::vector<uint8_t> elf_file = debug::WriteDebugElfFileForMethods(
1268         GetCompilerDriver()->GetInstructionSet(),
1269         GetCompilerDriver()->GetInstructionSetFeatures(),
1270         ArrayRef<const debug::MethodDebugInfo>(&info, 1));
1271     CreateJITCodeEntryForAddress(code_address, std::move(elf_file));
1272   }
1273 
1274   Runtime::Current()->GetJit()->AddMemoryUsage(method, arena.BytesUsed());
1275 
1276   return true;
1277 }
1278 
1279 }  // namespace art
1280