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