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" 222a5c4681ba19411c1cb22e9a7ab446dab910af1cAndreas Gampe#include "debugger.h" 23e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier#include "entrypoints/runtime_asm_entrypoints.h" 24e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier#include "interpreter/interpreter.h" 25e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier#include "jit_code_cache.h" 2631f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle#include "oat_file_manager.h" 27b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray#include "oat_quick_method_header.h" 2831f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle#include "offline_profiling_info.h" 294d77b6a511659f26fdc711e23825ffa6e7feed7aCalin Juravle#include "profile_saver.h" 30e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier#include "runtime.h" 31e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier#include "runtime_options.h" 32b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray#include "stack_map.h" 33bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray#include "thread_list.h" 34e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier#include "utils.h" 35e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier 36e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartiernamespace art { 37e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartiernamespace jit { 38e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier 39d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffraystatic constexpr bool kEnableOnStackReplacement = true; 40bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray// At what priority to schedule jit threads. 9 is the lowest foreground priority on device. 41bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffraystatic constexpr int kJitPoolThreadPthreadPriority = 9; 42e86621386d18a3a7178af6cfc2c05d1b34c3b995Nicolas Geoffray 43ff2376770c1c6d301778c41e5c27c808a38e6968Mathieu Chartier// JIT compiler 44ff2376770c1c6d301778c41e5c27c808a38e6968Mathieu Chartiervoid* Jit::jit_library_handle_= nullptr; 45ff2376770c1c6d301778c41e5c27c808a38e6968Mathieu Chartiervoid* Jit::jit_compiler_handle_ = nullptr; 46ff2376770c1c6d301778c41e5c27c808a38e6968Mathieu Chartiervoid* (*Jit::jit_load_)(bool*) = nullptr; 47ff2376770c1c6d301778c41e5c27c808a38e6968Mathieu Chartiervoid (*Jit::jit_unload_)(void*) = nullptr; 48ff2376770c1c6d301778c41e5c27c808a38e6968Mathieu Chartierbool (*Jit::jit_compile_method_)(void*, ArtMethod*, Thread*, bool) = nullptr; 49ff2376770c1c6d301778c41e5c27c808a38e6968Mathieu Chartiervoid (*Jit::jit_types_loaded_)(void*, mirror::Class**, size_t count) = nullptr; 50ff2376770c1c6d301778c41e5c27c808a38e6968Mathieu Chartierbool Jit::generate_debug_info_ = false; 51ff2376770c1c6d301778c41e5c27c808a38e6968Mathieu Chartier 52e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu ChartierJitOptions* JitOptions::CreateFromRuntimeArguments(const RuntimeArgumentMap& options) { 53e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier auto* jit_options = new JitOptions; 54e5de54cfab5f14ba0b8ff25d8d60901c7021943fCalin Juravle jit_options->use_jit_compilation_ = options.GetOrDefault(RuntimeArgumentMap::UseJitCompilation); 5583f080ac824d0964941c3fbaa957cac874f827b0Nicolas Geoffray 560a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray jit_options->code_cache_initial_capacity_ = 570a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray options.GetOrDefault(RuntimeArgumentMap::JITCodeCacheInitialCapacity); 580a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray jit_options->code_cache_max_capacity_ = 590a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray options.GetOrDefault(RuntimeArgumentMap::JITCodeCacheMaxCapacity); 60a4885cbaafd35fe9c60eb6cd95e41e2c86f54f66Mathieu Chartier jit_options->dump_info_on_shutdown_ = 61a4885cbaafd35fe9c60eb6cd95e41e2c86f54f66Mathieu Chartier options.Exists(RuntimeArgumentMap::DumpJITInfoOnShutdown); 6231f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle jit_options->save_profiling_info_ = 6383f080ac824d0964941c3fbaa957cac874f827b0Nicolas Geoffray options.GetOrDefault(RuntimeArgumentMap::JITSaveProfilingInfo); 6483f080ac824d0964941c3fbaa957cac874f827b0Nicolas Geoffray 6583f080ac824d0964941c3fbaa957cac874f827b0Nicolas Geoffray jit_options->compile_threshold_ = options.GetOrDefault(RuntimeArgumentMap::JITCompileThreshold); 6683f080ac824d0964941c3fbaa957cac874f827b0Nicolas Geoffray if (jit_options->compile_threshold_ > std::numeric_limits<uint16_t>::max()) { 6783f080ac824d0964941c3fbaa957cac874f827b0Nicolas Geoffray LOG(FATAL) << "Method compilation threshold is above its internal limit."; 6883f080ac824d0964941c3fbaa957cac874f827b0Nicolas Geoffray } 6983f080ac824d0964941c3fbaa957cac874f827b0Nicolas Geoffray 7083f080ac824d0964941c3fbaa957cac874f827b0Nicolas Geoffray if (options.Exists(RuntimeArgumentMap::JITWarmupThreshold)) { 7183f080ac824d0964941c3fbaa957cac874f827b0Nicolas Geoffray jit_options->warmup_threshold_ = *options.Get(RuntimeArgumentMap::JITWarmupThreshold); 7283f080ac824d0964941c3fbaa957cac874f827b0Nicolas Geoffray if (jit_options->warmup_threshold_ > std::numeric_limits<uint16_t>::max()) { 7383f080ac824d0964941c3fbaa957cac874f827b0Nicolas Geoffray LOG(FATAL) << "Method warmup threshold is above its internal limit."; 7483f080ac824d0964941c3fbaa957cac874f827b0Nicolas Geoffray } 7583f080ac824d0964941c3fbaa957cac874f827b0Nicolas Geoffray } else { 7683f080ac824d0964941c3fbaa957cac874f827b0Nicolas Geoffray jit_options->warmup_threshold_ = jit_options->compile_threshold_ / 2; 7783f080ac824d0964941c3fbaa957cac874f827b0Nicolas Geoffray } 7883f080ac824d0964941c3fbaa957cac874f827b0Nicolas Geoffray 7983f080ac824d0964941c3fbaa957cac874f827b0Nicolas Geoffray if (options.Exists(RuntimeArgumentMap::JITOsrThreshold)) { 8083f080ac824d0964941c3fbaa957cac874f827b0Nicolas Geoffray jit_options->osr_threshold_ = *options.Get(RuntimeArgumentMap::JITOsrThreshold); 8183f080ac824d0964941c3fbaa957cac874f827b0Nicolas Geoffray if (jit_options->osr_threshold_ > std::numeric_limits<uint16_t>::max()) { 8283f080ac824d0964941c3fbaa957cac874f827b0Nicolas Geoffray LOG(FATAL) << "Method on stack replacement threshold is above its internal limit."; 8383f080ac824d0964941c3fbaa957cac874f827b0Nicolas Geoffray } 8483f080ac824d0964941c3fbaa957cac874f827b0Nicolas Geoffray } else { 8583f080ac824d0964941c3fbaa957cac874f827b0Nicolas Geoffray jit_options->osr_threshold_ = jit_options->compile_threshold_ * 2; 8683f080ac824d0964941c3fbaa957cac874f827b0Nicolas Geoffray if (jit_options->osr_threshold_ > std::numeric_limits<uint16_t>::max()) { 8783f080ac824d0964941c3fbaa957cac874f827b0Nicolas Geoffray jit_options->osr_threshold_ = std::numeric_limits<uint16_t>::max(); 8883f080ac824d0964941c3fbaa957cac874f827b0Nicolas Geoffray } 8983f080ac824d0964941c3fbaa957cac874f827b0Nicolas Geoffray } 9083f080ac824d0964941c3fbaa957cac874f827b0Nicolas Geoffray 91b2771b41a956b50266d4d83fbb067f99faf7b7dcCalin Juravle if (options.Exists(RuntimeArgumentMap::JITPriorityThreadWeight)) { 92b2771b41a956b50266d4d83fbb067f99faf7b7dcCalin Juravle jit_options->priority_thread_weight_ = 93b2771b41a956b50266d4d83fbb067f99faf7b7dcCalin Juravle *options.Get(RuntimeArgumentMap::JITPriorityThreadWeight); 94b2771b41a956b50266d4d83fbb067f99faf7b7dcCalin Juravle if (jit_options->priority_thread_weight_ > jit_options->warmup_threshold_) { 95b2771b41a956b50266d4d83fbb067f99faf7b7dcCalin Juravle LOG(FATAL) << "Priority thread weight is above the warmup threshold."; 96b2771b41a956b50266d4d83fbb067f99faf7b7dcCalin Juravle } else if (jit_options->priority_thread_weight_ == 0) { 97b2771b41a956b50266d4d83fbb067f99faf7b7dcCalin Juravle LOG(FATAL) << "Priority thread weight cannot be 0."; 98b2771b41a956b50266d4d83fbb067f99faf7b7dcCalin Juravle } 99b2771b41a956b50266d4d83fbb067f99faf7b7dcCalin Juravle } else { 100f3f9cf6b65c4bcf9ea44253188d8d910b7cf7e64Nicolas Geoffray jit_options->priority_thread_weight_ = std::max( 101f3f9cf6b65c4bcf9ea44253188d8d910b7cf7e64Nicolas Geoffray jit_options->warmup_threshold_ / Jit::kDefaultPriorityThreadWeightRatio, 102f3f9cf6b65c4bcf9ea44253188d8d910b7cf7e64Nicolas Geoffray static_cast<size_t>(1)); 103b2771b41a956b50266d4d83fbb067f99faf7b7dcCalin Juravle } 104b2771b41a956b50266d4d83fbb067f99faf7b7dcCalin Juravle 1052a894f433d126d6e8694c6235e29e66ef45a31d9Calin Juravle if (options.Exists(RuntimeArgumentMap::JITInvokeTransitionWeight)) { 10695bc2f29ef2e9e6b7a71cd123df0c4a1063be1d7Nicolas Geoffray jit_options->invoke_transition_weight_ = 10795bc2f29ef2e9e6b7a71cd123df0c4a1063be1d7Nicolas Geoffray *options.Get(RuntimeArgumentMap::JITInvokeTransitionWeight); 1082a894f433d126d6e8694c6235e29e66ef45a31d9Calin Juravle if (jit_options->invoke_transition_weight_ > jit_options->warmup_threshold_) { 1092a894f433d126d6e8694c6235e29e66ef45a31d9Calin Juravle LOG(FATAL) << "Invoke transition weight is above the warmup threshold."; 1102a894f433d126d6e8694c6235e29e66ef45a31d9Calin Juravle } else if (jit_options->invoke_transition_weight_ == 0) { 11195bc2f29ef2e9e6b7a71cd123df0c4a1063be1d7Nicolas Geoffray LOG(FATAL) << "Invoke transition weight cannot be 0."; 1122a894f433d126d6e8694c6235e29e66ef45a31d9Calin Juravle } 1132a894f433d126d6e8694c6235e29e66ef45a31d9Calin Juravle } else { 1142a894f433d126d6e8694c6235e29e66ef45a31d9Calin Juravle jit_options->invoke_transition_weight_ = std::max( 1152a894f433d126d6e8694c6235e29e66ef45a31d9Calin Juravle jit_options->warmup_threshold_ / Jit::kDefaultInvokeTransitionWeightRatio, 1162a894f433d126d6e8694c6235e29e66ef45a31d9Calin Juravle static_cast<size_t>(1));; 1172a894f433d126d6e8694c6235e29e66ef45a31d9Calin Juravle } 1182a894f433d126d6e8694c6235e29e66ef45a31d9Calin Juravle 119e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier return jit_options; 120e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier} 121e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier 122b2771b41a956b50266d4d83fbb067f99faf7b7dcCalin Juravlebool Jit::ShouldUsePriorityThreadWeight() { 1238fff24953c78bd58f3a42ac83b340b90e7e7228aCalin Juravle return Runtime::Current()->InJankPerceptibleProcessState() 1248fff24953c78bd58f3a42ac83b340b90e7e7228aCalin Juravle && Thread::Current()->IsJitSensitiveThread(); 125b2771b41a956b50266d4d83fbb067f99faf7b7dcCalin Juravle} 126b2771b41a956b50266d4d83fbb067f99faf7b7dcCalin Juravle 127a4885cbaafd35fe9c60eb6cd95e41e2c86f54f66Mathieu Chartiervoid Jit::DumpInfo(std::ostream& os) { 128bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray code_cache_->Dump(os); 129a4885cbaafd35fe9c60eb6cd95e41e2c86f54f66Mathieu Chartier cumulative_timings_.Dump(os); 130a4f81546373f4cb5fa6dfc135307ee0a1d930872Nicolas Geoffray MutexLock mu(Thread::Current(), lock_); 131a4f81546373f4cb5fa6dfc135307ee0a1d930872Nicolas Geoffray memory_use_.PrintMemoryUse(os); 132a4885cbaafd35fe9c60eb6cd95e41e2c86f54f66Mathieu Chartier} 133a4885cbaafd35fe9c60eb6cd95e41e2c86f54f66Mathieu Chartier 134c19c1c2e1def1f4f5ab5fd9e71b1a6f76d42988fCalin Juravlevoid Jit::DumpForSigQuit(std::ostream& os) { 135c19c1c2e1def1f4f5ab5fd9e71b1a6f76d42988fCalin Juravle DumpInfo(os); 136c19c1c2e1def1f4f5ab5fd9e71b1a6f76d42988fCalin Juravle ProfileSaver::DumpInstanceInfo(os); 137c19c1c2e1def1f4f5ab5fd9e71b1a6f76d42988fCalin Juravle} 138c19c1c2e1def1f4f5ab5fd9e71b1a6f76d42988fCalin Juravle 139a4885cbaafd35fe9c60eb6cd95e41e2c86f54f66Mathieu Chartiervoid Jit::AddTimingLogger(const TimingLogger& logger) { 140a4885cbaafd35fe9c60eb6cd95e41e2c86f54f66Mathieu Chartier cumulative_timings_.AddLogger(logger); 141a4885cbaafd35fe9c60eb6cd95e41e2c86f54f66Mathieu Chartier} 142a4885cbaafd35fe9c60eb6cd95e41e2c86f54f66Mathieu Chartier 143ff2376770c1c6d301778c41e5c27c808a38e6968Mathieu ChartierJit::Jit() : dump_info_on_shutdown_(false), 144a25dce9b452ba17ef7cef768926c884177a3025eNicolas Geoffray cumulative_timings_("JIT timings"), 145a4f81546373f4cb5fa6dfc135307ee0a1d930872Nicolas Geoffray memory_use_("Memory used for compilation", 16), 146a4f81546373f4cb5fa6dfc135307ee0a1d930872Nicolas Geoffray lock_("JIT memory use lock"), 147e5de54cfab5f14ba0b8ff25d8d60901c7021943fCalin Juravle use_jit_compilation_(true), 148ff2376770c1c6d301778c41e5c27c808a38e6968Mathieu Chartier save_profiling_info_(false) {} 149e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier 150e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu ChartierJit* Jit::Create(JitOptions* options, std::string* error_msg) { 151e5de54cfab5f14ba0b8ff25d8d60901c7021943fCalin Juravle DCHECK(options->UseJitCompilation() || options->GetSaveProfilingInfo()); 152e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier std::unique_ptr<Jit> jit(new Jit); 153a4885cbaafd35fe9c60eb6cd95e41e2c86f54f66Mathieu Chartier jit->dump_info_on_shutdown_ = options->DumpJitInfoOnShutdown(); 154ff2376770c1c6d301778c41e5c27c808a38e6968Mathieu Chartier if (jit_compiler_handle_ == nullptr && !LoadCompiler(error_msg)) { 155e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier return nullptr; 156e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier } 1570a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray jit->code_cache_.reset(JitCodeCache::Create( 158a25dce9b452ba17ef7cef768926c884177a3025eNicolas Geoffray options->GetCodeCacheInitialCapacity(), 159a25dce9b452ba17ef7cef768926c884177a3025eNicolas Geoffray options->GetCodeCacheMaxCapacity(), 160a25dce9b452ba17ef7cef768926c884177a3025eNicolas Geoffray jit->generate_debug_info_, 161a25dce9b452ba17ef7cef768926c884177a3025eNicolas Geoffray error_msg)); 162e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier if (jit->GetCodeCache() == nullptr) { 163e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier return nullptr; 164e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier } 165e5de54cfab5f14ba0b8ff25d8d60901c7021943fCalin Juravle jit->use_jit_compilation_ = options->UseJitCompilation(); 1664d77b6a511659f26fdc711e23825ffa6e7feed7aCalin Juravle jit->save_profiling_info_ = options->GetSaveProfilingInfo(); 167bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray VLOG(jit) << "JIT created with initial_capacity=" 1680a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray << PrettySize(options->GetCodeCacheInitialCapacity()) 1690a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray << ", max_capacity=" << PrettySize(options->GetCodeCacheMaxCapacity()) 1704d77b6a511659f26fdc711e23825ffa6e7feed7aCalin Juravle << ", compile_threshold=" << options->GetCompileThreshold() 1714d77b6a511659f26fdc711e23825ffa6e7feed7aCalin Juravle << ", save_profiling_info=" << options->GetSaveProfilingInfo(); 172bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray 173bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray 174bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray jit->hot_method_threshold_ = options->GetCompileThreshold(); 175bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray jit->warm_method_threshold_ = options->GetWarmupThreshold(); 176bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray jit->osr_method_threshold_ = options->GetOsrThreshold(); 177b6a74d8fea21ec53081bfea478d81f42f6184846Nicolas Geoffray jit->priority_thread_weight_ = options->GetPriorityThreadWeight(); 1782a894f433d126d6e8694c6235e29e66ef45a31d9Calin Juravle jit->invoke_transition_weight_ = options->GetInvokeTransitionWeight(); 179bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray 180bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray jit->CreateThreadPool(); 181bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray 182bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray // Notify native debugger about the classes already loaded before the creation of the jit. 183bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray jit->DumpTypeInfoForLoadedTypes(Runtime::Current()->GetClassLinker()); 184e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier return jit.release(); 185e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier} 186e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier 187b10cef442594dd0d6c5f1a5784643931a25cc431Mathieu Chartierbool Jit::LoadCompilerLibrary(std::string* error_msg) { 188e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier jit_library_handle_ = dlopen( 189e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier kIsDebugBuild ? "libartd-compiler.so" : "libart-compiler.so", RTLD_NOW); 190e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier if (jit_library_handle_ == nullptr) { 191e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier std::ostringstream oss; 192e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier oss << "JIT could not load libart-compiler.so: " << dlerror(); 193e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier *error_msg = oss.str(); 194e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier return false; 195e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier } 1965b82d339955d1a0dc23eeb8d2d5659459ff987baNicolas Geoffray jit_load_ = reinterpret_cast<void* (*)(bool*)>(dlsym(jit_library_handle_, "jit_load")); 197e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier if (jit_load_ == nullptr) { 198e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier dlclose(jit_library_handle_); 199e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier *error_msg = "JIT couldn't find jit_load entry point"; 200e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier return false; 201e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier } 202e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier jit_unload_ = reinterpret_cast<void (*)(void*)>( 203e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier dlsym(jit_library_handle_, "jit_unload")); 204e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier if (jit_unload_ == nullptr) { 205e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier dlclose(jit_library_handle_); 206e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier *error_msg = "JIT couldn't find jit_unload entry point"; 207e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier return false; 208e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier } 209b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray jit_compile_method_ = reinterpret_cast<bool (*)(void*, ArtMethod*, Thread*, bool)>( 210e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier dlsym(jit_library_handle_, "jit_compile_method")); 211e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier if (jit_compile_method_ == nullptr) { 212e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier dlclose(jit_library_handle_); 213e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier *error_msg = "JIT couldn't find jit_compile_method entry point"; 214e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier return false; 215e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier } 216fffbee4d158259633ec7b7f712eaf75be86bd4e5Tamas Berghammer jit_types_loaded_ = reinterpret_cast<void (*)(void*, mirror::Class**, size_t)>( 217fffbee4d158259633ec7b7f712eaf75be86bd4e5Tamas Berghammer dlsym(jit_library_handle_, "jit_types_loaded")); 218fffbee4d158259633ec7b7f712eaf75be86bd4e5Tamas Berghammer if (jit_types_loaded_ == nullptr) { 219160e6df5debaf77223eebddb8a4e3f7c5e729ad0Tamas Berghammer dlclose(jit_library_handle_); 220fffbee4d158259633ec7b7f712eaf75be86bd4e5Tamas Berghammer *error_msg = "JIT couldn't find jit_types_loaded entry point"; 221160e6df5debaf77223eebddb8a4e3f7c5e729ad0Tamas Berghammer return false; 222160e6df5debaf77223eebddb8a4e3f7c5e729ad0Tamas Berghammer } 223b10cef442594dd0d6c5f1a5784643931a25cc431Mathieu Chartier return true; 224b10cef442594dd0d6c5f1a5784643931a25cc431Mathieu Chartier} 225b10cef442594dd0d6c5f1a5784643931a25cc431Mathieu Chartier 226b10cef442594dd0d6c5f1a5784643931a25cc431Mathieu Chartierbool Jit::LoadCompiler(std::string* error_msg) { 227b10cef442594dd0d6c5f1a5784643931a25cc431Mathieu Chartier if (jit_library_handle_ == nullptr && !LoadCompilerLibrary(error_msg)) { 228b10cef442594dd0d6c5f1a5784643931a25cc431Mathieu Chartier return false; 229b10cef442594dd0d6c5f1a5784643931a25cc431Mathieu Chartier } 230a25dce9b452ba17ef7cef768926c884177a3025eNicolas Geoffray bool will_generate_debug_symbols = false; 231e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier VLOG(jit) << "Calling JitLoad interpreter_only=" 232e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier << Runtime::Current()->GetInstrumentation()->InterpretOnly(); 2335b82d339955d1a0dc23eeb8d2d5659459ff987baNicolas Geoffray jit_compiler_handle_ = (jit_load_)(&will_generate_debug_symbols); 234e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier if (jit_compiler_handle_ == nullptr) { 235e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier dlclose(jit_library_handle_); 236e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier *error_msg = "JIT couldn't load compiler"; 237e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier return false; 238e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier } 239a25dce9b452ba17ef7cef768926c884177a3025eNicolas Geoffray generate_debug_info_ = will_generate_debug_symbols; 240e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier return true; 241e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier} 242e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier 243b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffraybool Jit::CompileMethod(ArtMethod* method, Thread* self, bool osr) { 244e5de54cfab5f14ba0b8ff25d8d60901c7021943fCalin Juravle DCHECK(Runtime::Current()->UseJitCompilation()); 245e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier DCHECK(!method->IsRuntimeMethod()); 246d9994f069dfeaa32ba929ca78816b5b83e2a4134Nicolas Geoffray 24773be1e8f8609708f6624bb297c9628de44fd8b6fNicolas Geoffray // Don't compile the method if it has breakpoints. 248d8565456d29f4ad05f11cf84d2d2dac488508e06Mathieu Chartier if (Dbg::IsDebuggerActive() && Dbg::MethodHasAnyBreakpoints(method)) { 249d8565456d29f4ad05f11cf84d2d2dac488508e06Mathieu Chartier VLOG(jit) << "JIT not compiling " << PrettyMethod(method) << " due to breakpoint"; 250d8565456d29f4ad05f11cf84d2d2dac488508e06Mathieu Chartier return false; 251d8565456d29f4ad05f11cf84d2d2dac488508e06Mathieu Chartier } 25273be1e8f8609708f6624bb297c9628de44fd8b6fNicolas Geoffray 25373be1e8f8609708f6624bb297c9628de44fd8b6fNicolas Geoffray // Don't compile the method if we are supposed to be deoptimized. 25473be1e8f8609708f6624bb297c9628de44fd8b6fNicolas Geoffray instrumentation::Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation(); 25573be1e8f8609708f6624bb297c9628de44fd8b6fNicolas Geoffray if (instrumentation->AreAllMethodsDeoptimized() || instrumentation->IsDeoptimized(method)) { 256a42363f79832a6e14f348514664dc6dc3edf9da2Nicolas Geoffray VLOG(jit) << "JIT not compiling " << PrettyMethod(method) << " due to deoptimization"; 25773be1e8f8609708f6624bb297c9628de44fd8b6fNicolas Geoffray return false; 25873be1e8f8609708f6624bb297c9628de44fd8b6fNicolas Geoffray } 25973be1e8f8609708f6624bb297c9628de44fd8b6fNicolas Geoffray 260d9994f069dfeaa32ba929ca78816b5b83e2a4134Nicolas Geoffray // If we get a request to compile a proxy method, we pass the actual Java method 261d9994f069dfeaa32ba929ca78816b5b83e2a4134Nicolas Geoffray // of that proxy method, as the compiler does not expect a proxy method. 262d9994f069dfeaa32ba929ca78816b5b83e2a4134Nicolas Geoffray ArtMethod* method_to_compile = method->GetInterfaceMethodIfProxy(sizeof(void*)); 263d9994f069dfeaa32ba929ca78816b5b83e2a4134Nicolas Geoffray if (!code_cache_->NotifyCompilationOf(method_to_compile, self, osr)) { 26473be1e8f8609708f6624bb297c9628de44fd8b6fNicolas Geoffray return false; 26573be1e8f8609708f6624bb297c9628de44fd8b6fNicolas Geoffray } 266f3f9cf6b65c4bcf9ea44253188d8d910b7cf7e64Nicolas Geoffray 267f3f9cf6b65c4bcf9ea44253188d8d910b7cf7e64Nicolas Geoffray VLOG(jit) << "Compiling method " 268f3f9cf6b65c4bcf9ea44253188d8d910b7cf7e64Nicolas Geoffray << PrettyMethod(method_to_compile) 269f3f9cf6b65c4bcf9ea44253188d8d910b7cf7e64Nicolas Geoffray << " osr=" << std::boolalpha << osr; 270d9994f069dfeaa32ba929ca78816b5b83e2a4134Nicolas Geoffray bool success = jit_compile_method_(jit_compiler_handle_, method_to_compile, self, osr); 271454b3b6774fe07765273b917ccc97da2eba776acbuzbee code_cache_->DoneCompiling(method_to_compile, self, osr); 272f3f9cf6b65c4bcf9ea44253188d8d910b7cf7e64Nicolas Geoffray if (!success) { 273f3f9cf6b65c4bcf9ea44253188d8d910b7cf7e64Nicolas Geoffray VLOG(jit) << "Failed to compile method " 274f3f9cf6b65c4bcf9ea44253188d8d910b7cf7e64Nicolas Geoffray << PrettyMethod(method_to_compile) 275f3f9cf6b65c4bcf9ea44253188d8d910b7cf7e64Nicolas Geoffray << " osr=" << std::boolalpha << osr; 276f3f9cf6b65c4bcf9ea44253188d8d910b7cf7e64Nicolas Geoffray } 27773be1e8f8609708f6624bb297c9628de44fd8b6fNicolas Geoffray return success; 278e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier} 279e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier 280e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartiervoid Jit::CreateThreadPool() { 281bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray // There is a DCHECK in the 'AddSamples' method to ensure the tread pool 282bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray // is not null when we instrument. 283bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray thread_pool_.reset(new ThreadPool("Jit thread pool", 1)); 284bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray thread_pool_->SetPthreadPriority(kJitPoolThreadPthreadPriority); 285bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray thread_pool_->StartWorkers(Thread::Current()); 286e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier} 287e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier 288e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartiervoid Jit::DeleteThreadPool() { 289bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray Thread* self = Thread::Current(); 290bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray DCHECK(Runtime::Current()->IsShuttingDown(self)); 291bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray if (thread_pool_ != nullptr) { 292bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray ThreadPool* cache = nullptr; 293bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray { 294bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray ScopedSuspendAll ssa(__FUNCTION__); 295bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray // Clear thread_pool_ field while the threads are suspended. 296bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray // A mutator in the 'AddSamples' method will check against it. 297bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray cache = thread_pool_.release(); 298bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray } 299bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray cache->StopWorkers(self); 300bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray cache->RemoveAllTasks(self); 301bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray // We could just suspend all threads, but we know those threads 302bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray // will finish in a short period, so it's not worth adding a suspend logic 303bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray // here. Besides, this is only done for shutdown. 304bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray cache->Wait(self, false, false); 305bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray delete cache; 306e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier } 307e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier} 308e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier 3094d77b6a511659f26fdc711e23825ffa6e7feed7aCalin Juravlevoid Jit::StartProfileSaver(const std::string& filename, 310c90bc92bc577020ff4d3caced4cee1cdf41fa5deCalin Juravle const std::vector<std::string>& code_paths, 311c90bc92bc577020ff4d3caced4cee1cdf41fa5deCalin Juravle const std::string& foreign_dex_profile_path, 312c90bc92bc577020ff4d3caced4cee1cdf41fa5deCalin Juravle const std::string& app_dir) { 3134d77b6a511659f26fdc711e23825ffa6e7feed7aCalin Juravle if (save_profiling_info_) { 314c90bc92bc577020ff4d3caced4cee1cdf41fa5deCalin Juravle ProfileSaver::Start(filename, code_cache_.get(), code_paths, foreign_dex_profile_path, app_dir); 3154d77b6a511659f26fdc711e23825ffa6e7feed7aCalin Juravle } 3164d77b6a511659f26fdc711e23825ffa6e7feed7aCalin Juravle} 3174d77b6a511659f26fdc711e23825ffa6e7feed7aCalin Juravle 3184d77b6a511659f26fdc711e23825ffa6e7feed7aCalin Juravlevoid Jit::StopProfileSaver() { 3194d77b6a511659f26fdc711e23825ffa6e7feed7aCalin Juravle if (save_profiling_info_ && ProfileSaver::IsStarted()) { 320c19c1c2e1def1f4f5ab5fd9e71b1a6f76d42988fCalin Juravle ProfileSaver::Stop(dump_info_on_shutdown_); 32131f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle } 32231f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle} 32331f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle 32405d241565f36df825cf56a4f1b61bfb7e4dcb056Siva Chandrabool Jit::JitAtFirstUse() { 325bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray return HotMethodThreshold() == 0; 32605d241565f36df825cf56a4f1b61bfb7e4dcb056Siva Chandra} 32705d241565f36df825cf56a4f1b61bfb7e4dcb056Siva Chandra 32835122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffraybool Jit::CanInvokeCompiledCode(ArtMethod* method) { 32935122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray return code_cache_->ContainsPc(method->GetEntryPointFromQuickCompiledCode()); 33035122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray} 33135122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray 332e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu ChartierJit::~Jit() { 3334d77b6a511659f26fdc711e23825ffa6e7feed7aCalin Juravle DCHECK(!save_profiling_info_ || !ProfileSaver::IsStarted()); 334a4885cbaafd35fe9c60eb6cd95e41e2c86f54f66Mathieu Chartier if (dump_info_on_shutdown_) { 335a4885cbaafd35fe9c60eb6cd95e41e2c86f54f66Mathieu Chartier DumpInfo(LOG(INFO)); 336a4885cbaafd35fe9c60eb6cd95e41e2c86f54f66Mathieu Chartier } 337e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier DeleteThreadPool(); 338e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier if (jit_compiler_handle_ != nullptr) { 339e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier jit_unload_(jit_compiler_handle_); 340ff2376770c1c6d301778c41e5c27c808a38e6968Mathieu Chartier jit_compiler_handle_ = nullptr; 341e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier } 342e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier if (jit_library_handle_ != nullptr) { 343e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier dlclose(jit_library_handle_); 344ff2376770c1c6d301778c41e5c27c808a38e6968Mathieu Chartier jit_library_handle_ = nullptr; 345e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier } 346e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier} 347e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier 348160e6df5debaf77223eebddb8a4e3f7c5e729ad0Tamas Berghammervoid Jit::NewTypeLoadedIfUsingJit(mirror::Class* type) { 349e5de54cfab5f14ba0b8ff25d8d60901c7021943fCalin Juravle if (!Runtime::Current()->UseJitCompilation()) { 350e5de54cfab5f14ba0b8ff25d8d60901c7021943fCalin Juravle // No need to notify if we only use the JIT to save profiles. 351e5de54cfab5f14ba0b8ff25d8d60901c7021943fCalin Juravle return; 352e5de54cfab5f14ba0b8ff25d8d60901c7021943fCalin Juravle } 353160e6df5debaf77223eebddb8a4e3f7c5e729ad0Tamas Berghammer jit::Jit* jit = Runtime::Current()->GetJit(); 354e5de54cfab5f14ba0b8ff25d8d60901c7021943fCalin Juravle if (jit->generate_debug_info_) { 355fffbee4d158259633ec7b7f712eaf75be86bd4e5Tamas Berghammer DCHECK(jit->jit_types_loaded_ != nullptr); 356fffbee4d158259633ec7b7f712eaf75be86bd4e5Tamas Berghammer jit->jit_types_loaded_(jit->jit_compiler_handle_, &type, 1); 357fffbee4d158259633ec7b7f712eaf75be86bd4e5Tamas Berghammer } 358fffbee4d158259633ec7b7f712eaf75be86bd4e5Tamas Berghammer} 359fffbee4d158259633ec7b7f712eaf75be86bd4e5Tamas Berghammer 360fffbee4d158259633ec7b7f712eaf75be86bd4e5Tamas Berghammervoid Jit::DumpTypeInfoForLoadedTypes(ClassLinker* linker) { 361fffbee4d158259633ec7b7f712eaf75be86bd4e5Tamas Berghammer struct CollectClasses : public ClassVisitor { 3621aa8ec2ccdd7bedb6d30d91c89f1e94ab23c4439Mathieu Chartier bool operator()(mirror::Class* klass) override { 363fffbee4d158259633ec7b7f712eaf75be86bd4e5Tamas Berghammer classes_.push_back(klass); 364fffbee4d158259633ec7b7f712eaf75be86bd4e5Tamas Berghammer return true; 365fffbee4d158259633ec7b7f712eaf75be86bd4e5Tamas Berghammer } 3669b1c9b761dea9bc48a2994e3d4de46fc10343a25Mathieu Chartier std::vector<mirror::Class*> classes_; 367fffbee4d158259633ec7b7f712eaf75be86bd4e5Tamas Berghammer }; 368fffbee4d158259633ec7b7f712eaf75be86bd4e5Tamas Berghammer 369fffbee4d158259633ec7b7f712eaf75be86bd4e5Tamas Berghammer if (generate_debug_info_) { 370fffbee4d158259633ec7b7f712eaf75be86bd4e5Tamas Berghammer ScopedObjectAccess so(Thread::Current()); 371fffbee4d158259633ec7b7f712eaf75be86bd4e5Tamas Berghammer 372fffbee4d158259633ec7b7f712eaf75be86bd4e5Tamas Berghammer CollectClasses visitor; 373fffbee4d158259633ec7b7f712eaf75be86bd4e5Tamas Berghammer linker->VisitClasses(&visitor); 374fffbee4d158259633ec7b7f712eaf75be86bd4e5Tamas Berghammer jit_types_loaded_(jit_compiler_handle_, visitor.classes_.data(), visitor.classes_.size()); 375160e6df5debaf77223eebddb8a4e3f7c5e729ad0Tamas Berghammer } 376160e6df5debaf77223eebddb8a4e3f7c5e729ad0Tamas Berghammer} 377160e6df5debaf77223eebddb8a4e3f7c5e729ad0Tamas Berghammer 378b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffrayextern "C" void art_quick_osr_stub(void** stack, 379b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray uint32_t stack_size_in_bytes, 380b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray const uint8_t* native_pc, 381b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray JValue* result, 382b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray const char* shorty, 383b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray Thread* self); 384b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray 385b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffraybool Jit::MaybeDoOnStackReplacement(Thread* thread, 386b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray ArtMethod* method, 387b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray uint32_t dex_pc, 388b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray int32_t dex_pc_offset, 389b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray JValue* result) { 390e86621386d18a3a7178af6cfc2c05d1b34c3b995Nicolas Geoffray if (!kEnableOnStackReplacement) { 391e86621386d18a3a7178af6cfc2c05d1b34c3b995Nicolas Geoffray return false; 392e86621386d18a3a7178af6cfc2c05d1b34c3b995Nicolas Geoffray } 393e86621386d18a3a7178af6cfc2c05d1b34c3b995Nicolas Geoffray 394b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray Jit* jit = Runtime::Current()->GetJit(); 395b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray if (jit == nullptr) { 396b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray return false; 397b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray } 398b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray 399b88d59ef4fe611fe47e50a6a19785e03bbd5f93bNicolas Geoffray if (UNLIKELY(__builtin_frame_address(0) < thread->GetStackEnd())) { 400b88d59ef4fe611fe47e50a6a19785e03bbd5f93bNicolas Geoffray // Don't attempt to do an OSR if we are close to the stack limit. Since 401b88d59ef4fe611fe47e50a6a19785e03bbd5f93bNicolas Geoffray // the interpreter frames are still on stack, OSR has the potential 402b88d59ef4fe611fe47e50a6a19785e03bbd5f93bNicolas Geoffray // to stack overflow even for a simple loop. 403b88d59ef4fe611fe47e50a6a19785e03bbd5f93bNicolas Geoffray // b/27094810. 404b88d59ef4fe611fe47e50a6a19785e03bbd5f93bNicolas Geoffray return false; 405b88d59ef4fe611fe47e50a6a19785e03bbd5f93bNicolas Geoffray } 406b88d59ef4fe611fe47e50a6a19785e03bbd5f93bNicolas Geoffray 407d9bc433a89c41a255d1b669d075f802597839bdcNicolas Geoffray // Get the actual Java method if this method is from a proxy class. The compiler 408d9bc433a89c41a255d1b669d075f802597839bdcNicolas Geoffray // and the JIT code cache do not expect methods from proxy classes. 409d9bc433a89c41a255d1b669d075f802597839bdcNicolas Geoffray method = method->GetInterfaceMethodIfProxy(sizeof(void*)); 410d9bc433a89c41a255d1b669d075f802597839bdcNicolas Geoffray 411b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray // Cheap check if the method has been compiled already. That's an indicator that we should 412b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray // osr into it. 413b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray if (!jit->GetCodeCache()->ContainsPc(method->GetEntryPointFromQuickCompiledCode())) { 414b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray return false; 415b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray } 416b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray 417c0b2796ec2056a6ea15c67df1251db250ba7e9a2Nicolas Geoffray // Fetch some data before looking up for an OSR method. We don't want thread 418c0b2796ec2056a6ea15c67df1251db250ba7e9a2Nicolas Geoffray // suspension once we hold an OSR method, as the JIT code cache could delete the OSR 419c0b2796ec2056a6ea15c67df1251db250ba7e9a2Nicolas Geoffray // method while we are being suspended. 420b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray const size_t number_of_vregs = method->GetCodeItem()->registers_size_; 421d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray const char* shorty = method->GetShorty(); 422d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray std::string method_name(VLOG_IS_ON(jit) ? PrettyMethod(method) : ""); 423d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray void** memory = nullptr; 424d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray size_t frame_size = 0; 425d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray ShadowFrame* shadow_frame = nullptr; 426d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray const uint8_t* native_pc = nullptr; 427b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray 428d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray { 429d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray ScopedAssertNoThreadSuspension sts(thread, "Holding OSR method"); 430d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray const OatQuickMethodHeader* osr_method = jit->GetCodeCache()->LookupOsrMethodHeader(method); 431d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray if (osr_method == nullptr) { 432d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray // No osr method yet, just return to the interpreter. 433d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray return false; 434d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray } 435b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray 436d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray CodeInfo code_info = osr_method->GetOptimizedCodeInfo(); 43709ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky CodeInfoEncoding encoding = code_info.ExtractEncoding(); 438b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray 439d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray // Find stack map starting at the target dex_pc. 440d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray StackMap stack_map = code_info.GetOsrStackMapForDexPc(dex_pc + dex_pc_offset, encoding); 441d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray if (!stack_map.IsValid()) { 442d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray // There is no OSR stack map for this dex pc offset. Just return to the interpreter in the 443d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray // hope that the next branch has one. 444d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray return false; 445d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray } 446b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray 4475ecab6e6f523362b3f90358bdbbafdb95b2d037eAart Bik // Before allowing the jump, make sure the debugger is not active to avoid jumping from 4485ecab6e6f523362b3f90358bdbbafdb95b2d037eAart Bik // interpreter to OSR while e.g. single stepping. Note that we could selectively disable 4495ecab6e6f523362b3f90358bdbbafdb95b2d037eAart Bik // OSR when single stepping, but that's currently hard to know at this point. 4505ecab6e6f523362b3f90358bdbbafdb95b2d037eAart Bik if (Dbg::IsDebuggerActive()) { 4515ecab6e6f523362b3f90358bdbbafdb95b2d037eAart Bik return false; 4525ecab6e6f523362b3f90358bdbbafdb95b2d037eAart Bik } 4535ecab6e6f523362b3f90358bdbbafdb95b2d037eAart Bik 454d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray // We found a stack map, now fill the frame with dex register values from the interpreter's 455d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray // shadow frame. 456d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray DexRegisterMap vreg_map = 457d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray code_info.GetDexRegisterMapOf(stack_map, encoding, number_of_vregs); 458d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray 459d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray frame_size = osr_method->GetFrameSizeInBytes(); 460d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray 461d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray // Allocate memory to put shadow frame values. The osr stub will copy that memory to 462d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray // stack. 463d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray // Note that we could pass the shadow frame to the stub, and let it copy the values there, 464d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray // but that is engineering complexity not worth the effort for something like OSR. 465d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray memory = reinterpret_cast<void**>(malloc(frame_size)); 466d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray CHECK(memory != nullptr); 467d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray memset(memory, 0, frame_size); 468d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray 469d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray // Art ABI: ArtMethod is at the bottom of the stack. 470d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray memory[0] = method; 471d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray 472d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray shadow_frame = thread->PopShadowFrame(); 473d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray if (!vreg_map.IsValid()) { 474d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray // If we don't have a dex register map, then there are no live dex registers at 475d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray // this dex pc. 476d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray } else { 477d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray for (uint16_t vreg = 0; vreg < number_of_vregs; ++vreg) { 478d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray DexRegisterLocation::Kind location = 479d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray vreg_map.GetLocationKind(vreg, number_of_vregs, code_info, encoding); 480d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray if (location == DexRegisterLocation::Kind::kNone) { 481c0b2796ec2056a6ea15c67df1251db250ba7e9a2Nicolas Geoffray // Dex register is dead or uninitialized. 482d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray continue; 483d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray } 484d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray 485d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray if (location == DexRegisterLocation::Kind::kConstant) { 486d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray // We skip constants because the compiled code knows how to handle them. 487d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray continue; 488d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray } 489d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray 4907dc11782ff0a5dffcd8108f256f8975f0b3e8076David Srbecky DCHECK_EQ(location, DexRegisterLocation::Kind::kInStack); 491d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray 492d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray int32_t vreg_value = shadow_frame->GetVReg(vreg); 493d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray int32_t slot_offset = vreg_map.GetStackOffsetInBytes(vreg, 494d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray number_of_vregs, 495d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray code_info, 496d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray encoding); 497d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray DCHECK_LT(slot_offset, static_cast<int32_t>(frame_size)); 498d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray DCHECK_GT(slot_offset, 0); 499d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray (reinterpret_cast<int32_t*>(memory))[slot_offset / sizeof(int32_t)] = vreg_value; 500d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray } 501b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray } 502d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray 50309ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky native_pc = stack_map.GetNativePcOffset(encoding.stack_map_encoding) + 50409ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky osr_method->GetEntryPoint(); 505d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray VLOG(jit) << "Jumping to " 506d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray << method_name 507d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray << "@" 508d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray << std::hex << reinterpret_cast<uintptr_t>(native_pc); 509b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray } 510b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray 511b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray { 512b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray ManagedStack fragment; 513b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray thread->PushManagedStackFragment(&fragment); 514b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray (*art_quick_osr_stub)(memory, 515b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray frame_size, 516b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray native_pc, 517b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray result, 518d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray shorty, 519b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray thread); 520d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray 521b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray if (UNLIKELY(thread->GetException() == Thread::GetDeoptimizationException())) { 522b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray thread->DeoptimizeWithDeoptimizationException(result); 523b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray } 524b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray thread->PopManagedStackFragment(fragment); 525b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray } 526b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray free(memory); 527b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray thread->PushShadowFrame(shadow_frame); 528d186dd8ecb1f25d3786d6b27adcd6b0b9ca04ea0Nicolas Geoffray VLOG(jit) << "Done running OSR code for " << method_name; 529b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray return true; 530b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray} 531b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray 532a4f81546373f4cb5fa6dfc135307ee0a1d930872Nicolas Geoffrayvoid Jit::AddMemoryUsage(ArtMethod* method, size_t bytes) { 533a4f81546373f4cb5fa6dfc135307ee0a1d930872Nicolas Geoffray if (bytes > 4 * MB) { 534a4f81546373f4cb5fa6dfc135307ee0a1d930872Nicolas Geoffray LOG(INFO) << "Compiler allocated " 535a4f81546373f4cb5fa6dfc135307ee0a1d930872Nicolas Geoffray << PrettySize(bytes) 536a4f81546373f4cb5fa6dfc135307ee0a1d930872Nicolas Geoffray << " to compile " 537a4f81546373f4cb5fa6dfc135307ee0a1d930872Nicolas Geoffray << PrettyMethod(method); 538a4f81546373f4cb5fa6dfc135307ee0a1d930872Nicolas Geoffray } 539a4f81546373f4cb5fa6dfc135307ee0a1d930872Nicolas Geoffray MutexLock mu(Thread::Current(), lock_); 540a4f81546373f4cb5fa6dfc135307ee0a1d930872Nicolas Geoffray memory_use_.AddValue(bytes); 541a4f81546373f4cb5fa6dfc135307ee0a1d930872Nicolas Geoffray} 542a4f81546373f4cb5fa6dfc135307ee0a1d930872Nicolas Geoffray 543bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffrayclass JitCompileTask FINAL : public Task { 544bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray public: 545bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray enum TaskKind { 546bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray kAllocateProfile, 547bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray kCompile, 548bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray kCompileOsr 549bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray }; 550bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray 551bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray JitCompileTask(ArtMethod* method, TaskKind kind) : method_(method), kind_(kind) { 552bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray ScopedObjectAccess soa(Thread::Current()); 553bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray // Add a global ref to the class to prevent class unloading until compilation is done. 554bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray klass_ = soa.Vm()->AddGlobalRef(soa.Self(), method_->GetDeclaringClass()); 555bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray CHECK(klass_ != nullptr); 556bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray } 557bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray 558bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray ~JitCompileTask() { 559bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray ScopedObjectAccess soa(Thread::Current()); 560bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray soa.Vm()->DeleteGlobalRef(soa.Self(), klass_); 561bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray } 562bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray 563bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray void Run(Thread* self) OVERRIDE { 564bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray ScopedObjectAccess soa(self); 565bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray if (kind_ == kCompile) { 566f3f9cf6b65c4bcf9ea44253188d8d910b7cf7e64Nicolas Geoffray Runtime::Current()->GetJit()->CompileMethod(method_, self, /* osr */ false); 567bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray } else if (kind_ == kCompileOsr) { 568f3f9cf6b65c4bcf9ea44253188d8d910b7cf7e64Nicolas Geoffray Runtime::Current()->GetJit()->CompileMethod(method_, self, /* osr */ true); 569bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray } else { 570bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray DCHECK(kind_ == kAllocateProfile); 571bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray if (ProfilingInfo::Create(self, method_, /* retry_allocation */ true)) { 572bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray VLOG(jit) << "Start profiling " << PrettyMethod(method_); 573bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray } 574bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray } 5755fbb0fe0625a1f76aa33cd78ccf1a17b00d8f6d1Calin Juravle ProfileSaver::NotifyJitActivity(); 576bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray } 577bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray 578bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray void Finalize() OVERRIDE { 579bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray delete this; 580bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray } 581bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray 582bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray private: 583bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray ArtMethod* const method_; 584bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray const TaskKind kind_; 585bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray jobject klass_; 586bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray 587bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray DISALLOW_IMPLICIT_CONSTRUCTORS(JitCompileTask); 588bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray}; 589bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray 590f3f9cf6b65c4bcf9ea44253188d8d910b7cf7e64Nicolas Geoffrayvoid Jit::AddSamples(Thread* self, ArtMethod* method, uint16_t count, bool with_backedges) { 591bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray if (thread_pool_ == nullptr) { 592bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray // Should only see this when shutting down. 593bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray DCHECK(Runtime::Current()->IsShuttingDown(self)); 594bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray return; 595bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray } 596bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray 59762e631a678ef18c80f37862a2dc74004954a8502Nicolas Geoffray if (method->IsClassInitializer() || method->IsNative() || !method->IsCompilable()) { 598bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray // We do not want to compile such methods. 599bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray return; 600bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray } 601bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray DCHECK(thread_pool_ != nullptr); 602bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray DCHECK_GT(warm_method_threshold_, 0); 603bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray DCHECK_GT(hot_method_threshold_, warm_method_threshold_); 604bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray DCHECK_GT(osr_method_threshold_, hot_method_threshold_); 605bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray DCHECK_GE(priority_thread_weight_, 1); 606bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray DCHECK_LE(priority_thread_weight_, hot_method_threshold_); 607bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray 608bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray int32_t starting_count = method->GetCounter(); 609bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray if (Jit::ShouldUsePriorityThreadWeight()) { 610bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray count *= priority_thread_weight_; 611bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray } 612bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray int32_t new_count = starting_count + count; // int32 here to avoid wrap-around; 613bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray if (starting_count < warm_method_threshold_) { 614f3f9cf6b65c4bcf9ea44253188d8d910b7cf7e64Nicolas Geoffray if ((new_count >= warm_method_threshold_) && 615f3f9cf6b65c4bcf9ea44253188d8d910b7cf7e64Nicolas Geoffray (method->GetProfilingInfo(sizeof(void*)) == nullptr)) { 616bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray bool success = ProfilingInfo::Create(self, method, /* retry_allocation */ false); 617bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray if (success) { 618bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray VLOG(jit) << "Start profiling " << PrettyMethod(method); 619bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray } 620bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray 621bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray if (thread_pool_ == nullptr) { 622bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray // Calling ProfilingInfo::Create might put us in a suspended state, which could 623bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray // lead to the thread pool being deleted when we are shutting down. 624bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray DCHECK(Runtime::Current()->IsShuttingDown(self)); 625bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray return; 626bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray } 627bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray 628bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray if (!success) { 629bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray // We failed allocating. Instead of doing the collection on the Java thread, we push 630bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray // an allocation to a compiler thread, that will do the collection. 631bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray thread_pool_->AddTask(self, new JitCompileTask(method, JitCompileTask::kAllocateProfile)); 632bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray } 633bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray } 634bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray // Avoid jumping more than one state at a time. 635bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray new_count = std::min(new_count, hot_method_threshold_ - 1); 636e5de54cfab5f14ba0b8ff25d8d60901c7021943fCalin Juravle } else if (use_jit_compilation_) { 637e5de54cfab5f14ba0b8ff25d8d60901c7021943fCalin Juravle if (starting_count < hot_method_threshold_) { 638e5de54cfab5f14ba0b8ff25d8d60901c7021943fCalin Juravle if ((new_count >= hot_method_threshold_) && 639e5de54cfab5f14ba0b8ff25d8d60901c7021943fCalin Juravle !code_cache_->ContainsPc(method->GetEntryPointFromQuickCompiledCode())) { 640e5de54cfab5f14ba0b8ff25d8d60901c7021943fCalin Juravle DCHECK(thread_pool_ != nullptr); 641e5de54cfab5f14ba0b8ff25d8d60901c7021943fCalin Juravle thread_pool_->AddTask(self, new JitCompileTask(method, JitCompileTask::kCompile)); 642e5de54cfab5f14ba0b8ff25d8d60901c7021943fCalin Juravle } 643e5de54cfab5f14ba0b8ff25d8d60901c7021943fCalin Juravle // Avoid jumping more than one state at a time. 644e5de54cfab5f14ba0b8ff25d8d60901c7021943fCalin Juravle new_count = std::min(new_count, osr_method_threshold_ - 1); 645e5de54cfab5f14ba0b8ff25d8d60901c7021943fCalin Juravle } else if (starting_count < osr_method_threshold_) { 646e5de54cfab5f14ba0b8ff25d8d60901c7021943fCalin Juravle if (!with_backedges) { 647e5de54cfab5f14ba0b8ff25d8d60901c7021943fCalin Juravle // If the samples don't contain any back edge, we don't increment the hotness. 648e5de54cfab5f14ba0b8ff25d8d60901c7021943fCalin Juravle return; 649e5de54cfab5f14ba0b8ff25d8d60901c7021943fCalin Juravle } 650e5de54cfab5f14ba0b8ff25d8d60901c7021943fCalin Juravle if ((new_count >= osr_method_threshold_) && !code_cache_->IsOsrCompiled(method)) { 651e5de54cfab5f14ba0b8ff25d8d60901c7021943fCalin Juravle DCHECK(thread_pool_ != nullptr); 652e5de54cfab5f14ba0b8ff25d8d60901c7021943fCalin Juravle thread_pool_->AddTask(self, new JitCompileTask(method, JitCompileTask::kCompileOsr)); 653e5de54cfab5f14ba0b8ff25d8d60901c7021943fCalin Juravle } 654bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray } 655bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray } 656bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray // Update hotness counter 657bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray method->SetCounter(new_count); 658bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray} 659bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray 660bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffrayvoid Jit::MethodEntered(Thread* thread, ArtMethod* method) { 661e5de54cfab5f14ba0b8ff25d8d60901c7021943fCalin Juravle Runtime* runtime = Runtime::Current(); 662e5de54cfab5f14ba0b8ff25d8d60901c7021943fCalin Juravle if (UNLIKELY(runtime->UseJitCompilation() && runtime->GetJit()->JitAtFirstUse())) { 663bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray // The compiler requires a ProfilingInfo object. 664bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray ProfilingInfo::Create(thread, method, /* retry_allocation */ true); 665bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray JitCompileTask compile_task(method, JitCompileTask::kCompile); 666bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray compile_task.Run(thread); 667bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray return; 668bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray } 669bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray 670bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray ProfilingInfo* profiling_info = method->GetProfilingInfo(sizeof(void*)); 671bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray // Update the entrypoint if the ProfilingInfo has one. The interpreter will call it 672bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray // instead of interpreting the method. 673c8a4f2c632afd44fc558aa37c98b9cf042b4bb5bNicolas Geoffray if ((profiling_info != nullptr) && (profiling_info->GetSavedEntryPoint() != nullptr)) { 674c8a4f2c632afd44fc558aa37c98b9cf042b4bb5bNicolas Geoffray Runtime::Current()->GetInstrumentation()->UpdateMethodsCode( 675c8a4f2c632afd44fc558aa37c98b9cf042b4bb5bNicolas Geoffray method, profiling_info->GetSavedEntryPoint()); 676bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray } else { 677f3f9cf6b65c4bcf9ea44253188d8d910b7cf7e64Nicolas Geoffray AddSamples(thread, method, 1, /* with_backedges */false); 678bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray } 679bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray} 680bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray 681bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffrayvoid Jit::InvokeVirtualOrInterface(Thread* thread, 682bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray mirror::Object* this_object, 683bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray ArtMethod* caller, 684bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray uint32_t dex_pc, 685bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray ArtMethod* callee ATTRIBUTE_UNUSED) { 686bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray ScopedAssertNoThreadSuspension ants(thread, __FUNCTION__); 687bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray DCHECK(this_object != nullptr); 688bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray ProfilingInfo* info = caller->GetProfilingInfo(sizeof(void*)); 689bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray if (info != nullptr) { 690bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray // Since the instrumentation is marked from the declaring class we need to mark the card so 691bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray // that mod-union tables and card rescanning know about the update. 692bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray Runtime::Current()->GetHeap()->WriteBarrierEveryFieldOf(caller->GetDeclaringClass()); 693bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray info->AddInvokeInfo(dex_pc, this_object->GetClass()); 694bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray } 695bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray} 696bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray 697bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffrayvoid Jit::WaitForCompilationToFinish(Thread* self) { 698bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray if (thread_pool_ != nullptr) { 699bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray thread_pool_->Wait(self, false, false); 700bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray } 701bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray} 702bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray 703e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier} // namespace jit 704e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier} // namespace art 705