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