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