1e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier/* 2e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier * Copyright 2014 The Android Open Source Project 3e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier * 4e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier * Licensed under the Apache License, Version 2.0 (the "License"); 5e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier * you may not use this file except in compliance with the License. 6e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier * You may obtain a copy of the License at 7e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier * 8e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier * http://www.apache.org/licenses/LICENSE-2.0 9e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier * 10e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier * Unless required by applicable law or agreed to in writing, software 11e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier * distributed under the License is distributed on an "AS IS" BASIS, 12e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier * See the License for the specific language governing permissions and 14e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier * limitations under the License. 15e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier */ 16e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier 17e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier#include "jit.h" 18e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier 19e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier#include <dlfcn.h> 20e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier 21e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier#include "art_method-inl.h" 22542451cc546779f5c67840e105c51205a1b0a8fdAndreas Gampe#include "base/enums.h" 232a5c4681ba19411c1cb22e9a7ab446dab910af1cAndreas Gampe#include "debugger.h" 24e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier#include "entrypoints/runtime_asm_entrypoints.h" 25e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier#include "interpreter/interpreter.h" 26c15a2f4f45661a7f5f542e406282c146ea1a968dAndreas Gampe#include "java_vm_ext.h" 27e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier#include "jit_code_cache.h" 2831f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle#include "oat_file_manager.h" 29b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray#include "oat_quick_method_header.h" 3033083d626dbf2c8b06badfd73f50e98114483059Calin Juravle#include "profile_compilation_info.h" 314d77b6a511659f26fdc711e23825ffa6e7feed7aCalin Juravle#include "profile_saver.h" 32e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier#include "runtime.h" 33e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier#include "runtime_options.h" 34b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray#include "stack_map.h" 35274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray#include "thread_list.h" 36e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier#include "utils.h" 37e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier 38e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartiernamespace art { 39e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartiernamespace jit { 40e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier 41d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffraystatic constexpr bool kEnableOnStackReplacement = true; 42274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray// At what priority to schedule jit threads. 9 is the lowest foreground priority on device. 43274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffraystatic constexpr int kJitPoolThreadPthreadPriority = 9; 44e86621386d18a3a7178af6cfc2c05d1b34c3b995Nicolas Geoffray 4572918ea854d182ef25b2352bfe1c46c1e916a141Mathieu Chartier// JIT compiler 4672918ea854d182ef25b2352bfe1c46c1e916a141Mathieu Chartiervoid* Jit::jit_library_handle_= nullptr; 4772918ea854d182ef25b2352bfe1c46c1e916a141Mathieu Chartiervoid* Jit::jit_compiler_handle_ = nullptr; 4872918ea854d182ef25b2352bfe1c46c1e916a141Mathieu Chartiervoid* (*Jit::jit_load_)(bool*) = nullptr; 4972918ea854d182ef25b2352bfe1c46c1e916a141Mathieu Chartiervoid (*Jit::jit_unload_)(void*) = nullptr; 5072918ea854d182ef25b2352bfe1c46c1e916a141Mathieu Chartierbool (*Jit::jit_compile_method_)(void*, ArtMethod*, Thread*, bool) = nullptr; 5172918ea854d182ef25b2352bfe1c46c1e916a141Mathieu Chartiervoid (*Jit::jit_types_loaded_)(void*, mirror::Class**, size_t count) = nullptr; 5272918ea854d182ef25b2352bfe1c46c1e916a141Mathieu Chartierbool Jit::generate_debug_info_ = false; 5372918ea854d182ef25b2352bfe1c46c1e916a141Mathieu Chartier 54e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu ChartierJitOptions* JitOptions::CreateFromRuntimeArguments(const RuntimeArgumentMap& options) { 55e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier auto* jit_options = new JitOptions; 56ffc87076dda9878cb2cc098149bae441d38b9268Calin Juravle jit_options->use_jit_compilation_ = options.GetOrDefault(RuntimeArgumentMap::UseJitCompilation); 5783f080ac824d0964941c3fbaa957cac874f827b0Nicolas Geoffray 580a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray jit_options->code_cache_initial_capacity_ = 590a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray options.GetOrDefault(RuntimeArgumentMap::JITCodeCacheInitialCapacity); 600a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray jit_options->code_cache_max_capacity_ = 610a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray options.GetOrDefault(RuntimeArgumentMap::JITCodeCacheMaxCapacity); 62a4885cbaafd35fe9c60eb6cd95e41e2c86f54f66Mathieu Chartier jit_options->dump_info_on_shutdown_ = 63a4885cbaafd35fe9c60eb6cd95e41e2c86f54f66Mathieu Chartier options.Exists(RuntimeArgumentMap::DumpJITInfoOnShutdown); 64138dbff9246c89ac9fbe0b086b54fdab3f4451fbCalin Juravle jit_options->profile_saver_options_ = 65138dbff9246c89ac9fbe0b086b54fdab3f4451fbCalin Juravle options.GetOrDefault(RuntimeArgumentMap::ProfileSaverOpts); 6683f080ac824d0964941c3fbaa957cac874f827b0Nicolas Geoffray 6783f080ac824d0964941c3fbaa957cac874f827b0Nicolas Geoffray jit_options->compile_threshold_ = options.GetOrDefault(RuntimeArgumentMap::JITCompileThreshold); 6883f080ac824d0964941c3fbaa957cac874f827b0Nicolas Geoffray if (jit_options->compile_threshold_ > std::numeric_limits<uint16_t>::max()) { 6983f080ac824d0964941c3fbaa957cac874f827b0Nicolas Geoffray LOG(FATAL) << "Method compilation threshold is above its internal limit."; 7083f080ac824d0964941c3fbaa957cac874f827b0Nicolas Geoffray } 7183f080ac824d0964941c3fbaa957cac874f827b0Nicolas Geoffray 7283f080ac824d0964941c3fbaa957cac874f827b0Nicolas Geoffray if (options.Exists(RuntimeArgumentMap::JITWarmupThreshold)) { 7383f080ac824d0964941c3fbaa957cac874f827b0Nicolas Geoffray jit_options->warmup_threshold_ = *options.Get(RuntimeArgumentMap::JITWarmupThreshold); 7483f080ac824d0964941c3fbaa957cac874f827b0Nicolas Geoffray if (jit_options->warmup_threshold_ > std::numeric_limits<uint16_t>::max()) { 7583f080ac824d0964941c3fbaa957cac874f827b0Nicolas Geoffray LOG(FATAL) << "Method warmup threshold is above its internal limit."; 7683f080ac824d0964941c3fbaa957cac874f827b0Nicolas Geoffray } 7783f080ac824d0964941c3fbaa957cac874f827b0Nicolas Geoffray } else { 7883f080ac824d0964941c3fbaa957cac874f827b0Nicolas Geoffray jit_options->warmup_threshold_ = jit_options->compile_threshold_ / 2; 7983f080ac824d0964941c3fbaa957cac874f827b0Nicolas Geoffray } 8083f080ac824d0964941c3fbaa957cac874f827b0Nicolas Geoffray 8183f080ac824d0964941c3fbaa957cac874f827b0Nicolas Geoffray if (options.Exists(RuntimeArgumentMap::JITOsrThreshold)) { 8283f080ac824d0964941c3fbaa957cac874f827b0Nicolas Geoffray jit_options->osr_threshold_ = *options.Get(RuntimeArgumentMap::JITOsrThreshold); 8383f080ac824d0964941c3fbaa957cac874f827b0Nicolas Geoffray if (jit_options->osr_threshold_ > std::numeric_limits<uint16_t>::max()) { 8483f080ac824d0964941c3fbaa957cac874f827b0Nicolas Geoffray LOG(FATAL) << "Method on stack replacement threshold is above its internal limit."; 8583f080ac824d0964941c3fbaa957cac874f827b0Nicolas Geoffray } 8683f080ac824d0964941c3fbaa957cac874f827b0Nicolas Geoffray } else { 8783f080ac824d0964941c3fbaa957cac874f827b0Nicolas Geoffray jit_options->osr_threshold_ = jit_options->compile_threshold_ * 2; 8883f080ac824d0964941c3fbaa957cac874f827b0Nicolas Geoffray if (jit_options->osr_threshold_ > std::numeric_limits<uint16_t>::max()) { 8983f080ac824d0964941c3fbaa957cac874f827b0Nicolas Geoffray jit_options->osr_threshold_ = std::numeric_limits<uint16_t>::max(); 9083f080ac824d0964941c3fbaa957cac874f827b0Nicolas Geoffray } 9183f080ac824d0964941c3fbaa957cac874f827b0Nicolas Geoffray } 9283f080ac824d0964941c3fbaa957cac874f827b0Nicolas Geoffray 93b2771b41a956b50266d4d83fbb067f99faf7b7dcCalin Juravle if (options.Exists(RuntimeArgumentMap::JITPriorityThreadWeight)) { 94b2771b41a956b50266d4d83fbb067f99faf7b7dcCalin Juravle jit_options->priority_thread_weight_ = 95b2771b41a956b50266d4d83fbb067f99faf7b7dcCalin Juravle *options.Get(RuntimeArgumentMap::JITPriorityThreadWeight); 96b2771b41a956b50266d4d83fbb067f99faf7b7dcCalin Juravle if (jit_options->priority_thread_weight_ > jit_options->warmup_threshold_) { 97b2771b41a956b50266d4d83fbb067f99faf7b7dcCalin Juravle LOG(FATAL) << "Priority thread weight is above the warmup threshold."; 98b2771b41a956b50266d4d83fbb067f99faf7b7dcCalin Juravle } else if (jit_options->priority_thread_weight_ == 0) { 99b2771b41a956b50266d4d83fbb067f99faf7b7dcCalin Juravle LOG(FATAL) << "Priority thread weight cannot be 0."; 100b2771b41a956b50266d4d83fbb067f99faf7b7dcCalin Juravle } 101b2771b41a956b50266d4d83fbb067f99faf7b7dcCalin Juravle } else { 10271cd50fb67fa48667b0ab59aa436a582c04ba43dNicolas Geoffray jit_options->priority_thread_weight_ = std::max( 10371cd50fb67fa48667b0ab59aa436a582c04ba43dNicolas Geoffray jit_options->warmup_threshold_ / Jit::kDefaultPriorityThreadWeightRatio, 10471cd50fb67fa48667b0ab59aa436a582c04ba43dNicolas Geoffray static_cast<size_t>(1)); 105b2771b41a956b50266d4d83fbb067f99faf7b7dcCalin Juravle } 106b2771b41a956b50266d4d83fbb067f99faf7b7dcCalin Juravle 107155ff3d1c59c0f88993559b0b9bd639f7e32f048Calin Juravle if (options.Exists(RuntimeArgumentMap::JITInvokeTransitionWeight)) { 1087c9f3ba7b4f7b9543dbd539ffdc7be818284d922Nicolas Geoffray jit_options->invoke_transition_weight_ = 1097c9f3ba7b4f7b9543dbd539ffdc7be818284d922Nicolas Geoffray *options.Get(RuntimeArgumentMap::JITInvokeTransitionWeight); 110155ff3d1c59c0f88993559b0b9bd639f7e32f048Calin Juravle if (jit_options->invoke_transition_weight_ > jit_options->warmup_threshold_) { 111155ff3d1c59c0f88993559b0b9bd639f7e32f048Calin Juravle LOG(FATAL) << "Invoke transition weight is above the warmup threshold."; 112155ff3d1c59c0f88993559b0b9bd639f7e32f048Calin Juravle } else if (jit_options->invoke_transition_weight_ == 0) { 1137c9f3ba7b4f7b9543dbd539ffdc7be818284d922Nicolas Geoffray LOG(FATAL) << "Invoke transition weight cannot be 0."; 114155ff3d1c59c0f88993559b0b9bd639f7e32f048Calin Juravle } 115155ff3d1c59c0f88993559b0b9bd639f7e32f048Calin Juravle } else { 116155ff3d1c59c0f88993559b0b9bd639f7e32f048Calin Juravle jit_options->invoke_transition_weight_ = std::max( 117155ff3d1c59c0f88993559b0b9bd639f7e32f048Calin Juravle jit_options->warmup_threshold_ / Jit::kDefaultInvokeTransitionWeightRatio, 1186beced4c017826f7c449f12fac7fa42403657f2bMathieu Chartier static_cast<size_t>(1)); 119155ff3d1c59c0f88993559b0b9bd639f7e32f048Calin Juravle } 120155ff3d1c59c0f88993559b0b9bd639f7e32f048Calin Juravle 121e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier return jit_options; 122e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier} 123e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier 124b2771b41a956b50266d4d83fbb067f99faf7b7dcCalin Juravlebool Jit::ShouldUsePriorityThreadWeight() { 12597cbc9206e9adc473a90650ebdb5d620f517ff04Calin Juravle return Runtime::Current()->InJankPerceptibleProcessState() 12697cbc9206e9adc473a90650ebdb5d620f517ff04Calin Juravle && Thread::Current()->IsJitSensitiveThread(); 127b2771b41a956b50266d4d83fbb067f99faf7b7dcCalin Juravle} 128b2771b41a956b50266d4d83fbb067f99faf7b7dcCalin Juravle 129a4885cbaafd35fe9c60eb6cd95e41e2c86f54f66Mathieu Chartiervoid Jit::DumpInfo(std::ostream& os) { 130bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray code_cache_->Dump(os); 131a4885cbaafd35fe9c60eb6cd95e41e2c86f54f66Mathieu Chartier cumulative_timings_.Dump(os); 132a4f81546373f4cb5fa6dfc135307ee0a1d930872Nicolas Geoffray MutexLock mu(Thread::Current(), lock_); 133a4f81546373f4cb5fa6dfc135307ee0a1d930872Nicolas Geoffray memory_use_.PrintMemoryUse(os); 134a4885cbaafd35fe9c60eb6cd95e41e2c86f54f66Mathieu Chartier} 135a4885cbaafd35fe9c60eb6cd95e41e2c86f54f66Mathieu Chartier 136b8e69994d10534e0f4f96878725bc53e531f2c6fCalin Juravlevoid Jit::DumpForSigQuit(std::ostream& os) { 137b8e69994d10534e0f4f96878725bc53e531f2c6fCalin Juravle DumpInfo(os); 138b8e69994d10534e0f4f96878725bc53e531f2c6fCalin Juravle ProfileSaver::DumpInstanceInfo(os); 139b8e69994d10534e0f4f96878725bc53e531f2c6fCalin Juravle} 140b8e69994d10534e0f4f96878725bc53e531f2c6fCalin Juravle 141a4885cbaafd35fe9c60eb6cd95e41e2c86f54f66Mathieu Chartiervoid Jit::AddTimingLogger(const TimingLogger& logger) { 142a4885cbaafd35fe9c60eb6cd95e41e2c86f54f66Mathieu Chartier cumulative_timings_.AddLogger(logger); 143a4885cbaafd35fe9c60eb6cd95e41e2c86f54f66Mathieu Chartier} 144a4885cbaafd35fe9c60eb6cd95e41e2c86f54f66Mathieu Chartier 14572918ea854d182ef25b2352bfe1c46c1e916a141Mathieu ChartierJit::Jit() : dump_info_on_shutdown_(false), 146a25dce9b452ba17ef7cef768926c884177a3025eNicolas Geoffray cumulative_timings_("JIT timings"), 147a4f81546373f4cb5fa6dfc135307ee0a1d930872Nicolas Geoffray memory_use_("Memory used for compilation", 16), 148a4f81546373f4cb5fa6dfc135307ee0a1d930872Nicolas Geoffray lock_("JIT memory use lock"), 1494471e4f7c5874bdaf93762b6047d4a4bebc465dfAndreas Gampe use_jit_compilation_(true), 1504471e4f7c5874bdaf93762b6047d4a4bebc465dfAndreas Gampe hot_method_threshold_(0), 1514471e4f7c5874bdaf93762b6047d4a4bebc465dfAndreas Gampe warm_method_threshold_(0), 1524471e4f7c5874bdaf93762b6047d4a4bebc465dfAndreas Gampe osr_method_threshold_(0), 1534471e4f7c5874bdaf93762b6047d4a4bebc465dfAndreas Gampe priority_thread_weight_(0), 1544471e4f7c5874bdaf93762b6047d4a4bebc465dfAndreas Gampe invoke_transition_weight_(0) {} 155e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier 156e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu ChartierJit* Jit::Create(JitOptions* options, std::string* error_msg) { 157138dbff9246c89ac9fbe0b086b54fdab3f4451fbCalin Juravle DCHECK(options->UseJitCompilation() || options->GetProfileSaverOptions().IsEnabled()); 158e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier std::unique_ptr<Jit> jit(new Jit); 159a4885cbaafd35fe9c60eb6cd95e41e2c86f54f66Mathieu Chartier jit->dump_info_on_shutdown_ = options->DumpJitInfoOnShutdown(); 16072918ea854d182ef25b2352bfe1c46c1e916a141Mathieu Chartier if (jit_compiler_handle_ == nullptr && !LoadCompiler(error_msg)) { 161e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier return nullptr; 162e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier } 1630a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray jit->code_cache_.reset(JitCodeCache::Create( 164a25dce9b452ba17ef7cef768926c884177a3025eNicolas Geoffray options->GetCodeCacheInitialCapacity(), 165a25dce9b452ba17ef7cef768926c884177a3025eNicolas Geoffray options->GetCodeCacheMaxCapacity(), 166a25dce9b452ba17ef7cef768926c884177a3025eNicolas Geoffray jit->generate_debug_info_, 167a25dce9b452ba17ef7cef768926c884177a3025eNicolas Geoffray error_msg)); 168e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier if (jit->GetCodeCache() == nullptr) { 169e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier return nullptr; 170e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier } 171ffc87076dda9878cb2cc098149bae441d38b9268Calin Juravle jit->use_jit_compilation_ = options->UseJitCompilation(); 172138dbff9246c89ac9fbe0b086b54fdab3f4451fbCalin Juravle jit->profile_saver_options_ = options->GetProfileSaverOptions(); 173bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray VLOG(jit) << "JIT created with initial_capacity=" 1740a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray << PrettySize(options->GetCodeCacheInitialCapacity()) 1750a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray << ", max_capacity=" << PrettySize(options->GetCodeCacheMaxCapacity()) 1764d77b6a511659f26fdc711e23825ffa6e7feed7aCalin Juravle << ", compile_threshold=" << options->GetCompileThreshold() 177138dbff9246c89ac9fbe0b086b54fdab3f4451fbCalin Juravle << ", profile_saver_options=" << options->GetProfileSaverOptions(); 178274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray 179274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray 180274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray jit->hot_method_threshold_ = options->GetCompileThreshold(); 181274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray jit->warm_method_threshold_ = options->GetWarmupThreshold(); 182274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray jit->osr_method_threshold_ = options->GetOsrThreshold(); 183ba6aae0b49932a0ae3050d1fc22c6571e51f8180Nicolas Geoffray jit->priority_thread_weight_ = options->GetPriorityThreadWeight(); 184155ff3d1c59c0f88993559b0b9bd639f7e32f048Calin Juravle jit->invoke_transition_weight_ = options->GetInvokeTransitionWeight(); 185274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray 186274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray jit->CreateThreadPool(); 187274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray 188274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray // Notify native debugger about the classes already loaded before the creation of the jit. 189274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray jit->DumpTypeInfoForLoadedTypes(Runtime::Current()->GetClassLinker()); 190e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier return jit.release(); 191e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier} 192e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier 193c1bc4150415686e6240343c7345c49d80e351df3Mathieu Chartierbool Jit::LoadCompilerLibrary(std::string* error_msg) { 194e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier jit_library_handle_ = dlopen( 195e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier kIsDebugBuild ? "libartd-compiler.so" : "libart-compiler.so", RTLD_NOW); 196e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier if (jit_library_handle_ == nullptr) { 197e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier std::ostringstream oss; 198e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier oss << "JIT could not load libart-compiler.so: " << dlerror(); 199e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier *error_msg = oss.str(); 200e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier return false; 201e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier } 2025b82d339955d1a0dc23eeb8d2d5659459ff987baNicolas Geoffray jit_load_ = reinterpret_cast<void* (*)(bool*)>(dlsym(jit_library_handle_, "jit_load")); 203e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier if (jit_load_ == nullptr) { 204e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier dlclose(jit_library_handle_); 205e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier *error_msg = "JIT couldn't find jit_load entry point"; 206e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier return false; 207e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier } 208e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier jit_unload_ = reinterpret_cast<void (*)(void*)>( 209e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier dlsym(jit_library_handle_, "jit_unload")); 210e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier if (jit_unload_ == nullptr) { 211e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier dlclose(jit_library_handle_); 212e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier *error_msg = "JIT couldn't find jit_unload entry point"; 213e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier return false; 214e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier } 215b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray jit_compile_method_ = reinterpret_cast<bool (*)(void*, ArtMethod*, Thread*, bool)>( 216e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier dlsym(jit_library_handle_, "jit_compile_method")); 217e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier if (jit_compile_method_ == nullptr) { 218e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier dlclose(jit_library_handle_); 219e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier *error_msg = "JIT couldn't find jit_compile_method entry point"; 220e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier return false; 221e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier } 222fffbee4d158259633ec7b7f712eaf75be86bd4e5Tamas Berghammer jit_types_loaded_ = reinterpret_cast<void (*)(void*, mirror::Class**, size_t)>( 223fffbee4d158259633ec7b7f712eaf75be86bd4e5Tamas Berghammer dlsym(jit_library_handle_, "jit_types_loaded")); 224fffbee4d158259633ec7b7f712eaf75be86bd4e5Tamas Berghammer if (jit_types_loaded_ == nullptr) { 225160e6df5debaf77223eebddb8a4e3f7c5e729ad0Tamas Berghammer dlclose(jit_library_handle_); 226fffbee4d158259633ec7b7f712eaf75be86bd4e5Tamas Berghammer *error_msg = "JIT couldn't find jit_types_loaded entry point"; 227160e6df5debaf77223eebddb8a4e3f7c5e729ad0Tamas Berghammer return false; 228160e6df5debaf77223eebddb8a4e3f7c5e729ad0Tamas Berghammer } 229c1bc4150415686e6240343c7345c49d80e351df3Mathieu Chartier return true; 230c1bc4150415686e6240343c7345c49d80e351df3Mathieu Chartier} 231c1bc4150415686e6240343c7345c49d80e351df3Mathieu Chartier 232c1bc4150415686e6240343c7345c49d80e351df3Mathieu Chartierbool Jit::LoadCompiler(std::string* error_msg) { 233c1bc4150415686e6240343c7345c49d80e351df3Mathieu Chartier if (jit_library_handle_ == nullptr && !LoadCompilerLibrary(error_msg)) { 234c1bc4150415686e6240343c7345c49d80e351df3Mathieu Chartier return false; 235c1bc4150415686e6240343c7345c49d80e351df3Mathieu Chartier } 236a25dce9b452ba17ef7cef768926c884177a3025eNicolas Geoffray bool will_generate_debug_symbols = false; 237e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier VLOG(jit) << "Calling JitLoad interpreter_only=" 238e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier << Runtime::Current()->GetInstrumentation()->InterpretOnly(); 2395b82d339955d1a0dc23eeb8d2d5659459ff987baNicolas Geoffray jit_compiler_handle_ = (jit_load_)(&will_generate_debug_symbols); 240e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier if (jit_compiler_handle_ == nullptr) { 241e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier dlclose(jit_library_handle_); 242e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier *error_msg = "JIT couldn't load compiler"; 243e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier return false; 244e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier } 245a25dce9b452ba17ef7cef768926c884177a3025eNicolas Geoffray generate_debug_info_ = will_generate_debug_symbols; 246e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier return true; 247e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier} 248e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier 249b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffraybool Jit::CompileMethod(ArtMethod* method, Thread* self, bool osr) { 250ffc87076dda9878cb2cc098149bae441d38b9268Calin Juravle DCHECK(Runtime::Current()->UseJitCompilation()); 251e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier DCHECK(!method->IsRuntimeMethod()); 252d9994f069dfeaa32ba929ca78816b5b83e2a4134Nicolas Geoffray 25373be1e8f8609708f6624bb297c9628de44fd8b6fNicolas Geoffray // Don't compile the method if it has breakpoints. 254d8565456d29f4ad05f11cf84d2d2dac488508e06Mathieu Chartier if (Dbg::IsDebuggerActive() && Dbg::MethodHasAnyBreakpoints(method)) { 255709b070044354d9f47641f273edacaeeb0240ab7David Sehr VLOG(jit) << "JIT not compiling " << method->PrettyMethod() << " due to breakpoint"; 256d8565456d29f4ad05f11cf84d2d2dac488508e06Mathieu Chartier return false; 257d8565456d29f4ad05f11cf84d2d2dac488508e06Mathieu Chartier } 25873be1e8f8609708f6624bb297c9628de44fd8b6fNicolas Geoffray 25973be1e8f8609708f6624bb297c9628de44fd8b6fNicolas Geoffray // Don't compile the method if we are supposed to be deoptimized. 26073be1e8f8609708f6624bb297c9628de44fd8b6fNicolas Geoffray instrumentation::Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation(); 26173be1e8f8609708f6624bb297c9628de44fd8b6fNicolas Geoffray if (instrumentation->AreAllMethodsDeoptimized() || instrumentation->IsDeoptimized(method)) { 262709b070044354d9f47641f273edacaeeb0240ab7David Sehr VLOG(jit) << "JIT not compiling " << method->PrettyMethod() << " due to deoptimization"; 26373be1e8f8609708f6624bb297c9628de44fd8b6fNicolas Geoffray return false; 26473be1e8f8609708f6624bb297c9628de44fd8b6fNicolas Geoffray } 26573be1e8f8609708f6624bb297c9628de44fd8b6fNicolas Geoffray 266d9994f069dfeaa32ba929ca78816b5b83e2a4134Nicolas Geoffray // If we get a request to compile a proxy method, we pass the actual Java method 267d9994f069dfeaa32ba929ca78816b5b83e2a4134Nicolas Geoffray // of that proxy method, as the compiler does not expect a proxy method. 268542451cc546779f5c67840e105c51205a1b0a8fdAndreas Gampe ArtMethod* method_to_compile = method->GetInterfaceMethodIfProxy(kRuntimePointerSize); 269d9994f069dfeaa32ba929ca78816b5b83e2a4134Nicolas Geoffray if (!code_cache_->NotifyCompilationOf(method_to_compile, self, osr)) { 27073be1e8f8609708f6624bb297c9628de44fd8b6fNicolas Geoffray return false; 27173be1e8f8609708f6624bb297c9628de44fd8b6fNicolas Geoffray } 27271cd50fb67fa48667b0ab59aa436a582c04ba43dNicolas Geoffray 27371cd50fb67fa48667b0ab59aa436a582c04ba43dNicolas Geoffray VLOG(jit) << "Compiling method " 274709b070044354d9f47641f273edacaeeb0240ab7David Sehr << ArtMethod::PrettyMethod(method_to_compile) 27571cd50fb67fa48667b0ab59aa436a582c04ba43dNicolas Geoffray << " osr=" << std::boolalpha << osr; 276d9994f069dfeaa32ba929ca78816b5b83e2a4134Nicolas Geoffray bool success = jit_compile_method_(jit_compiler_handle_, method_to_compile, self, osr); 277454b3b6774fe07765273b917ccc97da2eba776acbuzbee code_cache_->DoneCompiling(method_to_compile, self, osr); 27871cd50fb67fa48667b0ab59aa436a582c04ba43dNicolas Geoffray if (!success) { 27971cd50fb67fa48667b0ab59aa436a582c04ba43dNicolas Geoffray VLOG(jit) << "Failed to compile method " 280709b070044354d9f47641f273edacaeeb0240ab7David Sehr << ArtMethod::PrettyMethod(method_to_compile) 28171cd50fb67fa48667b0ab59aa436a582c04ba43dNicolas Geoffray << " osr=" << std::boolalpha << osr; 28271cd50fb67fa48667b0ab59aa436a582c04ba43dNicolas Geoffray } 283320ba91911c840528893e07b0af43d317cd4c9aaAndreas Gampe if (kIsDebugBuild) { 284320ba91911c840528893e07b0af43d317cd4c9aaAndreas Gampe if (self->IsExceptionPending()) { 285320ba91911c840528893e07b0af43d317cd4c9aaAndreas Gampe mirror::Throwable* exception = self->GetException(); 286320ba91911c840528893e07b0af43d317cd4c9aaAndreas Gampe LOG(FATAL) << "No pending exception expected after compiling " 287320ba91911c840528893e07b0af43d317cd4c9aaAndreas Gampe << ArtMethod::PrettyMethod(method) 288320ba91911c840528893e07b0af43d317cd4c9aaAndreas Gampe << ": " 289320ba91911c840528893e07b0af43d317cd4c9aaAndreas Gampe << exception->Dump(); 290320ba91911c840528893e07b0af43d317cd4c9aaAndreas Gampe } 291320ba91911c840528893e07b0af43d317cd4c9aaAndreas Gampe } 29273be1e8f8609708f6624bb297c9628de44fd8b6fNicolas Geoffray return success; 293e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier} 294e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier 295e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartiervoid Jit::CreateThreadPool() { 296274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray // There is a DCHECK in the 'AddSamples' method to ensure the tread pool 297274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray // is not null when we instrument. 2984471e4f7c5874bdaf93762b6047d4a4bebc465dfAndreas Gampe 2994471e4f7c5874bdaf93762b6047d4a4bebc465dfAndreas Gampe // We need peers as we may report the JIT thread, e.g., in the debugger. 3004471e4f7c5874bdaf93762b6047d4a4bebc465dfAndreas Gampe constexpr bool kJitPoolNeedsPeers = true; 3014471e4f7c5874bdaf93762b6047d4a4bebc465dfAndreas Gampe thread_pool_.reset(new ThreadPool("Jit thread pool", 1, kJitPoolNeedsPeers)); 3024471e4f7c5874bdaf93762b6047d4a4bebc465dfAndreas Gampe 303274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray thread_pool_->SetPthreadPriority(kJitPoolThreadPthreadPriority); 304021c5f285550bf1cfa435db6a8bc7e77843e2b7dNicolas Geoffray Start(); 305e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier} 306e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier 307e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartiervoid Jit::DeleteThreadPool() { 308274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray Thread* self = Thread::Current(); 309274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray DCHECK(Runtime::Current()->IsShuttingDown(self)); 310274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray if (thread_pool_ != nullptr) { 311274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray ThreadPool* cache = nullptr; 312274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray { 313274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray ScopedSuspendAll ssa(__FUNCTION__); 314274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray // Clear thread_pool_ field while the threads are suspended. 315274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray // A mutator in the 'AddSamples' method will check against it. 316274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray cache = thread_pool_.release(); 317274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray } 318274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray cache->StopWorkers(self); 319274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray cache->RemoveAllTasks(self); 320274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray // We could just suspend all threads, but we know those threads 321274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray // will finish in a short period, so it's not worth adding a suspend logic 322274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray // here. Besides, this is only done for shutdown. 323274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray cache->Wait(self, false, false); 324274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray delete cache; 325e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier } 326e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier} 327e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier 3284d77b6a511659f26fdc711e23825ffa6e7feed7aCalin Juravlevoid Jit::StartProfileSaver(const std::string& filename, 32977651c4bbd56d502bcf05347e641061bbebca099Calin Juravle const std::vector<std::string>& code_paths) { 330138dbff9246c89ac9fbe0b086b54fdab3f4451fbCalin Juravle if (profile_saver_options_.IsEnabled()) { 331138dbff9246c89ac9fbe0b086b54fdab3f4451fbCalin Juravle ProfileSaver::Start(profile_saver_options_, 332138dbff9246c89ac9fbe0b086b54fdab3f4451fbCalin Juravle filename, 333138dbff9246c89ac9fbe0b086b54fdab3f4451fbCalin Juravle code_cache_.get(), 33477651c4bbd56d502bcf05347e641061bbebca099Calin Juravle code_paths); 3354d77b6a511659f26fdc711e23825ffa6e7feed7aCalin Juravle } 3364d77b6a511659f26fdc711e23825ffa6e7feed7aCalin Juravle} 3374d77b6a511659f26fdc711e23825ffa6e7feed7aCalin Juravle 3384d77b6a511659f26fdc711e23825ffa6e7feed7aCalin Juravlevoid Jit::StopProfileSaver() { 339138dbff9246c89ac9fbe0b086b54fdab3f4451fbCalin Juravle if (profile_saver_options_.IsEnabled() && ProfileSaver::IsStarted()) { 340b8e69994d10534e0f4f96878725bc53e531f2c6fCalin Juravle ProfileSaver::Stop(dump_info_on_shutdown_); 34131f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle } 34231f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle} 34331f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle 34405d241565f36df825cf56a4f1b61bfb7e4dcb056Siva Chandrabool Jit::JitAtFirstUse() { 345274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray return HotMethodThreshold() == 0; 34605d241565f36df825cf56a4f1b61bfb7e4dcb056Siva Chandra} 34705d241565f36df825cf56a4f1b61bfb7e4dcb056Siva Chandra 34835122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffraybool Jit::CanInvokeCompiledCode(ArtMethod* method) { 34935122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray return code_cache_->ContainsPc(method->GetEntryPointFromQuickCompiledCode()); 35035122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray} 35135122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray 352e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu ChartierJit::~Jit() { 353138dbff9246c89ac9fbe0b086b54fdab3f4451fbCalin Juravle DCHECK(!profile_saver_options_.IsEnabled() || !ProfileSaver::IsStarted()); 354a4885cbaafd35fe9c60eb6cd95e41e2c86f54f66Mathieu Chartier if (dump_info_on_shutdown_) { 3553fec9ac0d5af1358d216eb2fdc2000ec0205f3f0Andreas Gampe DumpInfo(LOG_STREAM(INFO)); 35679efadfdd861584f1c47654ade975eae6c43c360Nicolas Geoffray Runtime::Current()->DumpDeoptimizations(LOG_STREAM(INFO)); 357a4885cbaafd35fe9c60eb6cd95e41e2c86f54f66Mathieu Chartier } 358e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier DeleteThreadPool(); 359e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier if (jit_compiler_handle_ != nullptr) { 360e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier jit_unload_(jit_compiler_handle_); 36172918ea854d182ef25b2352bfe1c46c1e916a141Mathieu Chartier jit_compiler_handle_ = nullptr; 362e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier } 363e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier if (jit_library_handle_ != nullptr) { 364e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier dlclose(jit_library_handle_); 36572918ea854d182ef25b2352bfe1c46c1e916a141Mathieu Chartier jit_library_handle_ = nullptr; 366e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier } 367e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier} 368e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier 369160e6df5debaf77223eebddb8a4e3f7c5e729ad0Tamas Berghammervoid Jit::NewTypeLoadedIfUsingJit(mirror::Class* type) { 370ffc87076dda9878cb2cc098149bae441d38b9268Calin Juravle if (!Runtime::Current()->UseJitCompilation()) { 371ffc87076dda9878cb2cc098149bae441d38b9268Calin Juravle // No need to notify if we only use the JIT to save profiles. 372ffc87076dda9878cb2cc098149bae441d38b9268Calin Juravle return; 373ffc87076dda9878cb2cc098149bae441d38b9268Calin Juravle } 374160e6df5debaf77223eebddb8a4e3f7c5e729ad0Tamas Berghammer jit::Jit* jit = Runtime::Current()->GetJit(); 375ffc87076dda9878cb2cc098149bae441d38b9268Calin Juravle if (jit->generate_debug_info_) { 376fffbee4d158259633ec7b7f712eaf75be86bd4e5Tamas Berghammer DCHECK(jit->jit_types_loaded_ != nullptr); 377fffbee4d158259633ec7b7f712eaf75be86bd4e5Tamas Berghammer jit->jit_types_loaded_(jit->jit_compiler_handle_, &type, 1); 378fffbee4d158259633ec7b7f712eaf75be86bd4e5Tamas Berghammer } 379fffbee4d158259633ec7b7f712eaf75be86bd4e5Tamas Berghammer} 380fffbee4d158259633ec7b7f712eaf75be86bd4e5Tamas Berghammer 381fffbee4d158259633ec7b7f712eaf75be86bd4e5Tamas Berghammervoid Jit::DumpTypeInfoForLoadedTypes(ClassLinker* linker) { 382fffbee4d158259633ec7b7f712eaf75be86bd4e5Tamas Berghammer struct CollectClasses : public ClassVisitor { 38328357fab628bd9b91749988b554977398caf9963Mathieu Chartier bool operator()(ObjPtr<mirror::Class> klass) OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_) { 38428357fab628bd9b91749988b554977398caf9963Mathieu Chartier classes_.push_back(klass.Ptr()); 385fffbee4d158259633ec7b7f712eaf75be86bd4e5Tamas Berghammer return true; 386fffbee4d158259633ec7b7f712eaf75be86bd4e5Tamas Berghammer } 3879b1c9b761dea9bc48a2994e3d4de46fc10343a25Mathieu Chartier std::vector<mirror::Class*> classes_; 388fffbee4d158259633ec7b7f712eaf75be86bd4e5Tamas Berghammer }; 389fffbee4d158259633ec7b7f712eaf75be86bd4e5Tamas Berghammer 390fffbee4d158259633ec7b7f712eaf75be86bd4e5Tamas Berghammer if (generate_debug_info_) { 391fffbee4d158259633ec7b7f712eaf75be86bd4e5Tamas Berghammer ScopedObjectAccess so(Thread::Current()); 392fffbee4d158259633ec7b7f712eaf75be86bd4e5Tamas Berghammer 393fffbee4d158259633ec7b7f712eaf75be86bd4e5Tamas Berghammer CollectClasses visitor; 394fffbee4d158259633ec7b7f712eaf75be86bd4e5Tamas Berghammer linker->VisitClasses(&visitor); 395fffbee4d158259633ec7b7f712eaf75be86bd4e5Tamas Berghammer jit_types_loaded_(jit_compiler_handle_, visitor.classes_.data(), visitor.classes_.size()); 396160e6df5debaf77223eebddb8a4e3f7c5e729ad0Tamas Berghammer } 397160e6df5debaf77223eebddb8a4e3f7c5e729ad0Tamas Berghammer} 398160e6df5debaf77223eebddb8a4e3f7c5e729ad0Tamas Berghammer 399b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffrayextern "C" void art_quick_osr_stub(void** stack, 400b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray uint32_t stack_size_in_bytes, 401b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray const uint8_t* native_pc, 402b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray JValue* result, 403b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray const char* shorty, 404b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray Thread* self); 405b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray 406b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffraybool Jit::MaybeDoOnStackReplacement(Thread* thread, 407b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray ArtMethod* method, 408b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray uint32_t dex_pc, 409b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray int32_t dex_pc_offset, 410b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray JValue* result) { 411e86621386d18a3a7178af6cfc2c05d1b34c3b995Nicolas Geoffray if (!kEnableOnStackReplacement) { 412e86621386d18a3a7178af6cfc2c05d1b34c3b995Nicolas Geoffray return false; 413e86621386d18a3a7178af6cfc2c05d1b34c3b995Nicolas Geoffray } 414e86621386d18a3a7178af6cfc2c05d1b34c3b995Nicolas Geoffray 415b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray Jit* jit = Runtime::Current()->GetJit(); 416b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray if (jit == nullptr) { 417b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray return false; 418b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray } 419b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray 420b88d59ef4fe611fe47e50a6a19785e03bbd5f93bNicolas Geoffray if (UNLIKELY(__builtin_frame_address(0) < thread->GetStackEnd())) { 421b88d59ef4fe611fe47e50a6a19785e03bbd5f93bNicolas Geoffray // Don't attempt to do an OSR if we are close to the stack limit. Since 422b88d59ef4fe611fe47e50a6a19785e03bbd5f93bNicolas Geoffray // the interpreter frames are still on stack, OSR has the potential 423b88d59ef4fe611fe47e50a6a19785e03bbd5f93bNicolas Geoffray // to stack overflow even for a simple loop. 424b88d59ef4fe611fe47e50a6a19785e03bbd5f93bNicolas Geoffray // b/27094810. 425b88d59ef4fe611fe47e50a6a19785e03bbd5f93bNicolas Geoffray return false; 426b88d59ef4fe611fe47e50a6a19785e03bbd5f93bNicolas Geoffray } 427b88d59ef4fe611fe47e50a6a19785e03bbd5f93bNicolas Geoffray 428d9bc433a89c41a255d1b669d075f802597839bdcNicolas Geoffray // Get the actual Java method if this method is from a proxy class. The compiler 429d9bc433a89c41a255d1b669d075f802597839bdcNicolas Geoffray // and the JIT code cache do not expect methods from proxy classes. 430542451cc546779f5c67840e105c51205a1b0a8fdAndreas Gampe method = method->GetInterfaceMethodIfProxy(kRuntimePointerSize); 431d9bc433a89c41a255d1b669d075f802597839bdcNicolas Geoffray 432b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray // Cheap check if the method has been compiled already. That's an indicator that we should 433b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray // osr into it. 434b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray if (!jit->GetCodeCache()->ContainsPc(method->GetEntryPointFromQuickCompiledCode())) { 435b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray return false; 436b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray } 437b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray 438c0b2796ec2056a6ea15c67df1251db250ba7e9a2Nicolas Geoffray // Fetch some data before looking up for an OSR method. We don't want thread 439c0b2796ec2056a6ea15c67df1251db250ba7e9a2Nicolas Geoffray // suspension once we hold an OSR method, as the JIT code cache could delete the OSR 440c0b2796ec2056a6ea15c67df1251db250ba7e9a2Nicolas Geoffray // method while we are being suspended. 441b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray const size_t number_of_vregs = method->GetCodeItem()->registers_size_; 442d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray const char* shorty = method->GetShorty(); 443709b070044354d9f47641f273edacaeeb0240ab7David Sehr std::string method_name(VLOG_IS_ON(jit) ? method->PrettyMethod() : ""); 444d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray void** memory = nullptr; 445d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray size_t frame_size = 0; 446d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray ShadowFrame* shadow_frame = nullptr; 447d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray const uint8_t* native_pc = nullptr; 448b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray 449d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray { 450268764da8022cafa5661c5b514eaa343c5257e57Mathieu Chartier ScopedAssertNoThreadSuspension sts("Holding OSR method"); 451d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray const OatQuickMethodHeader* osr_method = jit->GetCodeCache()->LookupOsrMethodHeader(method); 452d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray if (osr_method == nullptr) { 453d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray // No osr method yet, just return to the interpreter. 454d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray return false; 455d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray } 456b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray 457d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray CodeInfo code_info = osr_method->GetOptimizedCodeInfo(); 45809ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky CodeInfoEncoding encoding = code_info.ExtractEncoding(); 459b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray 460d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray // Find stack map starting at the target dex_pc. 461d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray StackMap stack_map = code_info.GetOsrStackMapForDexPc(dex_pc + dex_pc_offset, encoding); 462d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray if (!stack_map.IsValid()) { 463d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray // There is no OSR stack map for this dex pc offset. Just return to the interpreter in the 464d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray // hope that the next branch has one. 465d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray return false; 466d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray } 467b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray 46829bdaeef925f35eed68f3e52d04416daa0a62317Aart Bik // Before allowing the jump, make sure the debugger is not active to avoid jumping from 46929bdaeef925f35eed68f3e52d04416daa0a62317Aart Bik // interpreter to OSR while e.g. single stepping. Note that we could selectively disable 47029bdaeef925f35eed68f3e52d04416daa0a62317Aart Bik // OSR when single stepping, but that's currently hard to know at this point. 47129bdaeef925f35eed68f3e52d04416daa0a62317Aart Bik if (Dbg::IsDebuggerActive()) { 47229bdaeef925f35eed68f3e52d04416daa0a62317Aart Bik return false; 47329bdaeef925f35eed68f3e52d04416daa0a62317Aart Bik } 47429bdaeef925f35eed68f3e52d04416daa0a62317Aart Bik 475d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray // We found a stack map, now fill the frame with dex register values from the interpreter's 476d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray // shadow frame. 477d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray DexRegisterMap vreg_map = 478d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray code_info.GetDexRegisterMapOf(stack_map, encoding, number_of_vregs); 479d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray 480d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray frame_size = osr_method->GetFrameSizeInBytes(); 481d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray 482d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray // Allocate memory to put shadow frame values. The osr stub will copy that memory to 483d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray // stack. 484d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray // Note that we could pass the shadow frame to the stub, and let it copy the values there, 485d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray // but that is engineering complexity not worth the effort for something like OSR. 486d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray memory = reinterpret_cast<void**>(malloc(frame_size)); 487d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray CHECK(memory != nullptr); 488d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray memset(memory, 0, frame_size); 489d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray 490d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray // Art ABI: ArtMethod is at the bottom of the stack. 491d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray memory[0] = method; 492d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray 493d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray shadow_frame = thread->PopShadowFrame(); 494d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray if (!vreg_map.IsValid()) { 495d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray // If we don't have a dex register map, then there are no live dex registers at 496d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray // this dex pc. 497d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray } else { 498d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray for (uint16_t vreg = 0; vreg < number_of_vregs; ++vreg) { 499d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray DexRegisterLocation::Kind location = 500d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray vreg_map.GetLocationKind(vreg, number_of_vregs, code_info, encoding); 501d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray if (location == DexRegisterLocation::Kind::kNone) { 502c0b2796ec2056a6ea15c67df1251db250ba7e9a2Nicolas Geoffray // Dex register is dead or uninitialized. 503d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray continue; 504d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray } 505d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray 506d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray if (location == DexRegisterLocation::Kind::kConstant) { 507d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray // We skip constants because the compiled code knows how to handle them. 508d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray continue; 509d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray } 510d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray 5117dc11782ff0a5dffcd8108f256f8975f0b3e8076David Srbecky DCHECK_EQ(location, DexRegisterLocation::Kind::kInStack); 512d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray 513d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray int32_t vreg_value = shadow_frame->GetVReg(vreg); 514d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray int32_t slot_offset = vreg_map.GetStackOffsetInBytes(vreg, 515d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray number_of_vregs, 516d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray code_info, 517d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray encoding); 518d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray DCHECK_LT(slot_offset, static_cast<int32_t>(frame_size)); 519d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray DCHECK_GT(slot_offset, 0); 520d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray (reinterpret_cast<int32_t*>(memory))[slot_offset / sizeof(int32_t)] = vreg_value; 521d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray } 522b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray } 523d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray 524575d3e60c68b5cf481b615dde4a16283507b19edMathieu Chartier native_pc = stack_map.GetNativePcOffset(encoding.stack_map.encoding, kRuntimeISA) + 52509ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky osr_method->GetEntryPoint(); 526d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray VLOG(jit) << "Jumping to " 527d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray << method_name 528d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray << "@" 529d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray << std::hex << reinterpret_cast<uintptr_t>(native_pc); 530b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray } 531b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray 532b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray { 533b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray ManagedStack fragment; 534b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray thread->PushManagedStackFragment(&fragment); 535b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray (*art_quick_osr_stub)(memory, 536b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray frame_size, 537b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray native_pc, 538b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray result, 539d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray shorty, 540b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray thread); 541d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray 542b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray if (UNLIKELY(thread->GetException() == Thread::GetDeoptimizationException())) { 543b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray thread->DeoptimizeWithDeoptimizationException(result); 544b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray } 545b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray thread->PopManagedStackFragment(fragment); 546b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray } 547b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray free(memory); 548b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray thread->PushShadowFrame(shadow_frame); 549d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray VLOG(jit) << "Done running OSR code for " << method_name; 550b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray return true; 551b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray} 552b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray 553a4f81546373f4cb5fa6dfc135307ee0a1d930872Nicolas Geoffrayvoid Jit::AddMemoryUsage(ArtMethod* method, size_t bytes) { 554a4f81546373f4cb5fa6dfc135307ee0a1d930872Nicolas Geoffray if (bytes > 4 * MB) { 555a4f81546373f4cb5fa6dfc135307ee0a1d930872Nicolas Geoffray LOG(INFO) << "Compiler allocated " 556a4f81546373f4cb5fa6dfc135307ee0a1d930872Nicolas Geoffray << PrettySize(bytes) 557a4f81546373f4cb5fa6dfc135307ee0a1d930872Nicolas Geoffray << " to compile " 558709b070044354d9f47641f273edacaeeb0240ab7David Sehr << ArtMethod::PrettyMethod(method); 559a4f81546373f4cb5fa6dfc135307ee0a1d930872Nicolas Geoffray } 560a4f81546373f4cb5fa6dfc135307ee0a1d930872Nicolas Geoffray MutexLock mu(Thread::Current(), lock_); 561a4f81546373f4cb5fa6dfc135307ee0a1d930872Nicolas Geoffray memory_use_.AddValue(bytes); 562a4f81546373f4cb5fa6dfc135307ee0a1d930872Nicolas Geoffray} 563a4f81546373f4cb5fa6dfc135307ee0a1d930872Nicolas Geoffray 564274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffrayclass JitCompileTask FINAL : public Task { 565274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray public: 566274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray enum TaskKind { 567274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray kAllocateProfile, 568274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray kCompile, 569274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray kCompileOsr 570274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray }; 571274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray 572274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray JitCompileTask(ArtMethod* method, TaskKind kind) : method_(method), kind_(kind) { 573274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray ScopedObjectAccess soa(Thread::Current()); 574274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray // Add a global ref to the class to prevent class unloading until compilation is done. 575274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray klass_ = soa.Vm()->AddGlobalRef(soa.Self(), method_->GetDeclaringClass()); 576274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray CHECK(klass_ != nullptr); 577274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray } 578274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray 579274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray ~JitCompileTask() { 580274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray ScopedObjectAccess soa(Thread::Current()); 581274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray soa.Vm()->DeleteGlobalRef(soa.Self(), klass_); 582274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray } 583274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray 584274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray void Run(Thread* self) OVERRIDE { 585274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray ScopedObjectAccess soa(self); 586274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray if (kind_ == kCompile) { 58771cd50fb67fa48667b0ab59aa436a582c04ba43dNicolas Geoffray Runtime::Current()->GetJit()->CompileMethod(method_, self, /* osr */ false); 588274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray } else if (kind_ == kCompileOsr) { 58971cd50fb67fa48667b0ab59aa436a582c04ba43dNicolas Geoffray Runtime::Current()->GetJit()->CompileMethod(method_, self, /* osr */ true); 590274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray } else { 591274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray DCHECK(kind_ == kAllocateProfile); 592274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray if (ProfilingInfo::Create(self, method_, /* retry_allocation */ true)) { 593709b070044354d9f47641f273edacaeeb0240ab7David Sehr VLOG(jit) << "Start profiling " << ArtMethod::PrettyMethod(method_); 594274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray } 595274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray } 596a26389234ac66a4a5042c7bf7195c6531663d24dCalin Juravle ProfileSaver::NotifyJitActivity(); 597274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray } 598274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray 599274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray void Finalize() OVERRIDE { 600274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray delete this; 601274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray } 602274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray 603274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray private: 604274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray ArtMethod* const method_; 605274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray const TaskKind kind_; 606274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray jobject klass_; 607274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray 608274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray DISALLOW_IMPLICIT_CONSTRUCTORS(JitCompileTask); 609274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray}; 610274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray 61171cd50fb67fa48667b0ab59aa436a582c04ba43dNicolas Geoffrayvoid Jit::AddSamples(Thread* self, ArtMethod* method, uint16_t count, bool with_backedges) { 612274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray if (thread_pool_ == nullptr) { 613274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray // Should only see this when shutting down. 614274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray DCHECK(Runtime::Current()->IsShuttingDown(self)); 615274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray return; 616274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray } 617274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray 618250a378d5a2152662e0fa820f2b38f794ddd3596Nicolas Geoffray if (method->IsClassInitializer() || method->IsNative() || !method->IsCompilable()) { 619274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray // We do not want to compile such methods. 620274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray return; 621274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray } 622274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray DCHECK(thread_pool_ != nullptr); 623274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray DCHECK_GT(warm_method_threshold_, 0); 624274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray DCHECK_GT(hot_method_threshold_, warm_method_threshold_); 625274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray DCHECK_GT(osr_method_threshold_, hot_method_threshold_); 626274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray DCHECK_GE(priority_thread_weight_, 1); 627274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray DCHECK_LE(priority_thread_weight_, hot_method_threshold_); 628274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray 629274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray int32_t starting_count = method->GetCounter(); 630274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray if (Jit::ShouldUsePriorityThreadWeight()) { 631274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray count *= priority_thread_weight_; 632274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray } 633274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray int32_t new_count = starting_count + count; // int32 here to avoid wrap-around; 634274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray if (starting_count < warm_method_threshold_) { 63571cd50fb67fa48667b0ab59aa436a582c04ba43dNicolas Geoffray if ((new_count >= warm_method_threshold_) && 636542451cc546779f5c67840e105c51205a1b0a8fdAndreas Gampe (method->GetProfilingInfo(kRuntimePointerSize) == nullptr)) { 637274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray bool success = ProfilingInfo::Create(self, method, /* retry_allocation */ false); 638274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray if (success) { 639709b070044354d9f47641f273edacaeeb0240ab7David Sehr VLOG(jit) << "Start profiling " << method->PrettyMethod(); 640274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray } 641274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray 642274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray if (thread_pool_ == nullptr) { 643274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray // Calling ProfilingInfo::Create might put us in a suspended state, which could 644274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray // lead to the thread pool being deleted when we are shutting down. 645274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray DCHECK(Runtime::Current()->IsShuttingDown(self)); 646274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray return; 647274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray } 648274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray 649274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray if (!success) { 650274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray // We failed allocating. Instead of doing the collection on the Java thread, we push 651274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray // an allocation to a compiler thread, that will do the collection. 652274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray thread_pool_->AddTask(self, new JitCompileTask(method, JitCompileTask::kAllocateProfile)); 653274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray } 654274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray } 655274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray // Avoid jumping more than one state at a time. 656274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray new_count = std::min(new_count, hot_method_threshold_ - 1); 657ffc87076dda9878cb2cc098149bae441d38b9268Calin Juravle } else if (use_jit_compilation_) { 658ffc87076dda9878cb2cc098149bae441d38b9268Calin Juravle if (starting_count < hot_method_threshold_) { 659ffc87076dda9878cb2cc098149bae441d38b9268Calin Juravle if ((new_count >= hot_method_threshold_) && 660ffc87076dda9878cb2cc098149bae441d38b9268Calin Juravle !code_cache_->ContainsPc(method->GetEntryPointFromQuickCompiledCode())) { 661ffc87076dda9878cb2cc098149bae441d38b9268Calin Juravle DCHECK(thread_pool_ != nullptr); 662ffc87076dda9878cb2cc098149bae441d38b9268Calin Juravle thread_pool_->AddTask(self, new JitCompileTask(method, JitCompileTask::kCompile)); 663ffc87076dda9878cb2cc098149bae441d38b9268Calin Juravle } 664ffc87076dda9878cb2cc098149bae441d38b9268Calin Juravle // Avoid jumping more than one state at a time. 665ffc87076dda9878cb2cc098149bae441d38b9268Calin Juravle new_count = std::min(new_count, osr_method_threshold_ - 1); 666ffc87076dda9878cb2cc098149bae441d38b9268Calin Juravle } else if (starting_count < osr_method_threshold_) { 667ffc87076dda9878cb2cc098149bae441d38b9268Calin Juravle if (!with_backedges) { 668ffc87076dda9878cb2cc098149bae441d38b9268Calin Juravle // If the samples don't contain any back edge, we don't increment the hotness. 669ffc87076dda9878cb2cc098149bae441d38b9268Calin Juravle return; 670ffc87076dda9878cb2cc098149bae441d38b9268Calin Juravle } 671ffc87076dda9878cb2cc098149bae441d38b9268Calin Juravle if ((new_count >= osr_method_threshold_) && !code_cache_->IsOsrCompiled(method)) { 672ffc87076dda9878cb2cc098149bae441d38b9268Calin Juravle DCHECK(thread_pool_ != nullptr); 673ffc87076dda9878cb2cc098149bae441d38b9268Calin Juravle thread_pool_->AddTask(self, new JitCompileTask(method, JitCompileTask::kCompileOsr)); 674ffc87076dda9878cb2cc098149bae441d38b9268Calin Juravle } 675274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray } 676274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray } 677274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray // Update hotness counter 678274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray method->SetCounter(new_count); 679274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray} 680274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray 681274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffrayvoid Jit::MethodEntered(Thread* thread, ArtMethod* method) { 682ffc87076dda9878cb2cc098149bae441d38b9268Calin Juravle Runtime* runtime = Runtime::Current(); 683ffc87076dda9878cb2cc098149bae441d38b9268Calin Juravle if (UNLIKELY(runtime->UseJitCompilation() && runtime->GetJit()->JitAtFirstUse())) { 684274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray // The compiler requires a ProfilingInfo object. 685274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray ProfilingInfo::Create(thread, method, /* retry_allocation */ true); 686274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray JitCompileTask compile_task(method, JitCompileTask::kCompile); 687274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray compile_task.Run(thread); 688274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray return; 689274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray } 690274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray 691542451cc546779f5c67840e105c51205a1b0a8fdAndreas Gampe ProfilingInfo* profiling_info = method->GetProfilingInfo(kRuntimePointerSize); 692274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray // Update the entrypoint if the ProfilingInfo has one. The interpreter will call it 693274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray // instead of interpreting the method. 694480d5108fa62f28cbc2e7072610f974953ff73a8Nicolas Geoffray if ((profiling_info != nullptr) && (profiling_info->GetSavedEntryPoint() != nullptr)) { 695480d5108fa62f28cbc2e7072610f974953ff73a8Nicolas Geoffray Runtime::Current()->GetInstrumentation()->UpdateMethodsCode( 696480d5108fa62f28cbc2e7072610f974953ff73a8Nicolas Geoffray method, profiling_info->GetSavedEntryPoint()); 697274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray } else { 69871cd50fb67fa48667b0ab59aa436a582c04ba43dNicolas Geoffray AddSamples(thread, method, 1, /* with_backedges */false); 699274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray } 700274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray} 701274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray 702ef41db7a3f322a1feb305fdb457410c4cea94d00Mathieu Chartiervoid Jit::InvokeVirtualOrInterface(ObjPtr<mirror::Object> this_object, 703274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray ArtMethod* caller, 704274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray uint32_t dex_pc, 705274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray ArtMethod* callee ATTRIBUTE_UNUSED) { 706268764da8022cafa5661c5b514eaa343c5257e57Mathieu Chartier ScopedAssertNoThreadSuspension ants(__FUNCTION__); 707274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray DCHECK(this_object != nullptr); 708542451cc546779f5c67840e105c51205a1b0a8fdAndreas Gampe ProfilingInfo* info = caller->GetProfilingInfo(kRuntimePointerSize); 709274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray if (info != nullptr) { 710274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray info->AddInvokeInfo(dex_pc, this_object->GetClass()); 711274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray } 712274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray} 713274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray 714274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffrayvoid Jit::WaitForCompilationToFinish(Thread* self) { 715274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray if (thread_pool_ != nullptr) { 716274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray thread_pool_->Wait(self, false, false); 717274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray } 718274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray} 719274fe4adcb0610a9920be7814d9beb9cac6417ceNicolas Geoffray 720021c5f285550bf1cfa435db6a8bc7e77843e2b7dNicolas Geoffrayvoid Jit::Stop() { 721021c5f285550bf1cfa435db6a8bc7e77843e2b7dNicolas Geoffray Thread* self = Thread::Current(); 722021c5f285550bf1cfa435db6a8bc7e77843e2b7dNicolas Geoffray // TODO(ngeoffray): change API to not require calling WaitForCompilationToFinish twice. 723021c5f285550bf1cfa435db6a8bc7e77843e2b7dNicolas Geoffray WaitForCompilationToFinish(self); 724021c5f285550bf1cfa435db6a8bc7e77843e2b7dNicolas Geoffray GetThreadPool()->StopWorkers(self); 725021c5f285550bf1cfa435db6a8bc7e77843e2b7dNicolas Geoffray WaitForCompilationToFinish(self); 726021c5f285550bf1cfa435db6a8bc7e77843e2b7dNicolas Geoffray} 727021c5f285550bf1cfa435db6a8bc7e77843e2b7dNicolas Geoffray 728021c5f285550bf1cfa435db6a8bc7e77843e2b7dNicolas Geoffrayvoid Jit::Start() { 729021c5f285550bf1cfa435db6a8bc7e77843e2b7dNicolas Geoffray GetThreadPool()->StartWorkers(Thread::Current()); 730021c5f285550bf1cfa435db6a8bc7e77843e2b7dNicolas Geoffray} 731021c5f285550bf1cfa435db6a8bc7e77843e2b7dNicolas Geoffray 732f149b3fc6fd315d34244bce709898fdbbddc246fAndreas GampeScopedJitSuspend::ScopedJitSuspend() { 733f149b3fc6fd315d34244bce709898fdbbddc246fAndreas Gampe jit::Jit* jit = Runtime::Current()->GetJit(); 734f149b3fc6fd315d34244bce709898fdbbddc246fAndreas Gampe was_on_ = (jit != nullptr) && (jit->GetThreadPool() != nullptr); 735f149b3fc6fd315d34244bce709898fdbbddc246fAndreas Gampe if (was_on_) { 736021c5f285550bf1cfa435db6a8bc7e77843e2b7dNicolas Geoffray jit->Stop(); 737f149b3fc6fd315d34244bce709898fdbbddc246fAndreas Gampe } 738f149b3fc6fd315d34244bce709898fdbbddc246fAndreas Gampe} 739f149b3fc6fd315d34244bce709898fdbbddc246fAndreas Gampe 740f149b3fc6fd315d34244bce709898fdbbddc246fAndreas GampeScopedJitSuspend::~ScopedJitSuspend() { 741f149b3fc6fd315d34244bce709898fdbbddc246fAndreas Gampe if (was_on_) { 742f149b3fc6fd315d34244bce709898fdbbddc246fAndreas Gampe DCHECK(Runtime::Current()->GetJit() != nullptr); 743f149b3fc6fd315d34244bce709898fdbbddc246fAndreas Gampe DCHECK(Runtime::Current()->GetJit()->GetThreadPool() != nullptr); 744021c5f285550bf1cfa435db6a8bc7e77843e2b7dNicolas Geoffray Runtime::Current()->GetJit()->Start(); 745f149b3fc6fd315d34244bce709898fdbbddc246fAndreas Gampe } 746f149b3fc6fd315d34244bce709898fdbbddc246fAndreas Gampe} 747f149b3fc6fd315d34244bce709898fdbbddc246fAndreas Gampe 748e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier} // namespace jit 749e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier} // namespace art 750