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