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