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_code_cache.h" 18e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier 19e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier#include <sstream> 20e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier 21e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier#include "art_method-inl.h" 2266f55237679db90cb0a0a265043a787932b466f8Calin Juravle#include "base/stl_util.h" 2332ce2adefb8a3d0eda59a29f5e87c1eb43eef796Mathieu Chartier#include "base/systrace.h" 2431f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle#include "base/time_utils.h" 255cc349f3dd578e974f78314c50b6a0267c23e591David Srbecky#include "debugger_interface.h" 261dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray#include "entrypoints/runtime_asm_entrypoints.h" 271dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray#include "gc/accounting/bitmap-inl.h" 2899c959f3868512bb95432cf02a1f0ad3971698bfNicolas Geoffray#include "gc/scoped_gc_critical_section.h" 29bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray#include "jit/jit.h" 3026705e2b1245b65989a0341b24c5dbf2658d4bb6Nicolas Geoffray#include "jit/profiling_info.h" 311dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray#include "linear_alloc.h" 32e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier#include "mem_map.h" 33e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier#include "oat_file-inl.h" 3462623401fe994ff2f2719faf3cdb3c23b92ccd96Nicolas Geoffray#include "scoped_thread_state_change.h" 351dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray#include "thread_list.h" 36e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier 37e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartiernamespace art { 38e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartiernamespace jit { 39e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier 400c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffraystatic constexpr int kProtAll = PROT_READ | PROT_WRITE | PROT_EXEC; 410c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffraystatic constexpr int kProtData = PROT_READ | PROT_WRITE; 420c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffraystatic constexpr int kProtCode = PROT_READ | PROT_EXEC; 430c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray 44933330a192d43d7c7304120999907857a89c2f96Nicolas Geoffraystatic constexpr size_t kCodeSizeLogThreshold = 50 * KB; 45933330a192d43d7c7304120999907857a89c2f96Nicolas Geoffraystatic constexpr size_t kStackMapSizeLogThreshold = 50 * KB; 46933330a192d43d7c7304120999907857a89c2f96Nicolas Geoffray 470c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray#define CHECKED_MPROTECT(memory, size, prot) \ 480c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray do { \ 490c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray int rc = mprotect(memory, size, prot); \ 500c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray if (UNLIKELY(rc != 0)) { \ 510c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray errno = rc; \ 520c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray PLOG(FATAL) << "Failed to mprotect jit code cache"; \ 530c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray } \ 540c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray } while (false) \ 550c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray 560a3be1620a3560253cfa789cb9819013293c5654Nicolas GeoffrayJitCodeCache* JitCodeCache::Create(size_t initial_capacity, 570a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray size_t max_capacity, 58a25dce9b452ba17ef7cef768926c884177a3025eNicolas Geoffray bool generate_debug_info, 590a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray std::string* error_msg) { 6032ce2adefb8a3d0eda59a29f5e87c1eb43eef796Mathieu Chartier ScopedTrace trace(__PRETTY_FUNCTION__); 610a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray CHECK_GE(max_capacity, initial_capacity); 62a25dce9b452ba17ef7cef768926c884177a3025eNicolas Geoffray 63a25dce9b452ba17ef7cef768926c884177a3025eNicolas Geoffray // Generating debug information is mostly for using the 'perf' tool, which does 64a25dce9b452ba17ef7cef768926c884177a3025eNicolas Geoffray // not work with ashmem. 65a25dce9b452ba17ef7cef768926c884177a3025eNicolas Geoffray bool use_ashmem = !generate_debug_info; 66a25dce9b452ba17ef7cef768926c884177a3025eNicolas Geoffray // With 'perf', we want a 1-1 mapping between an address and a method. 67a25dce9b452ba17ef7cef768926c884177a3025eNicolas Geoffray bool garbage_collect_code = !generate_debug_info; 68a25dce9b452ba17ef7cef768926c884177a3025eNicolas Geoffray 690a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray // We need to have 32 bit offsets from method headers in code cache which point to things 700a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray // in the data cache. If the maps are more than 4G apart, having multiple maps wouldn't work. 710a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray // Ensure we're below 1 GB to be safe. 720a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray if (max_capacity > 1 * GB) { 730a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray std::ostringstream oss; 740a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray oss << "Maxium code cache capacity is limited to 1 GB, " 750a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray << PrettySize(max_capacity) << " is too big"; 760a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray *error_msg = oss.str(); 770a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray return nullptr; 780a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray } 790a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray 80e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier std::string error_str; 81e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier // Map name specific for android_os_Debug.cpp accounting. 820c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray MemMap* data_map = MemMap::MapAnonymous( 83a25dce9b452ba17ef7cef768926c884177a3025eNicolas Geoffray "data-code-cache", nullptr, max_capacity, kProtAll, false, false, &error_str, use_ashmem); 840c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray if (data_map == nullptr) { 850c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray std::ostringstream oss; 860a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray oss << "Failed to create read write execute cache: " << error_str << " size=" << max_capacity; 870c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray *error_msg = oss.str(); 880c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray return nullptr; 890c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray } 900c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray 910a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray // Align both capacities to page size, as that's the unit mspaces use. 920a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray initial_capacity = RoundDown(initial_capacity, 2 * kPageSize); 930a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray max_capacity = RoundDown(max_capacity, 2 * kPageSize); 940a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray 954e915fbc2be5fc43c782389bbbb7306cd76a523aNicolas Geoffray // Data cache is 1 / 2 of the map. 960c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray // TODO: Make this variable? 970a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray size_t data_size = max_capacity / 2; 980a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray size_t code_size = max_capacity - data_size; 990a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray DCHECK_EQ(code_size + data_size, max_capacity); 1000c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray uint8_t* divider = data_map->Begin() + data_size; 1010c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray 102a25dce9b452ba17ef7cef768926c884177a3025eNicolas Geoffray MemMap* code_map = 103a25dce9b452ba17ef7cef768926c884177a3025eNicolas Geoffray data_map->RemapAtEnd(divider, "jit-code-cache", kProtAll, &error_str, use_ashmem); 1040c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray if (code_map == nullptr) { 105e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier std::ostringstream oss; 1060a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray oss << "Failed to create read write execute cache: " << error_str << " size=" << max_capacity; 107e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier *error_msg = oss.str(); 108e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier return nullptr; 109e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier } 1100c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray DCHECK_EQ(code_map->Begin(), divider); 1110a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray data_size = initial_capacity / 2; 1120a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray code_size = initial_capacity - data_size; 1130a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray DCHECK_EQ(code_size + data_size, initial_capacity); 114a25dce9b452ba17ef7cef768926c884177a3025eNicolas Geoffray return new JitCodeCache( 115c3fec4c4ca01055d4d5920f363620b5726ebbbefNicolas Geoffray code_map, data_map, code_size, data_size, max_capacity, garbage_collect_code); 116e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier} 117e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier 1180a3be1620a3560253cfa789cb9819013293c5654Nicolas GeoffrayJitCodeCache::JitCodeCache(MemMap* code_map, 1190a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray MemMap* data_map, 1200a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray size_t initial_code_capacity, 1210a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray size_t initial_data_capacity, 122a25dce9b452ba17ef7cef768926c884177a3025eNicolas Geoffray size_t max_capacity, 123a25dce9b452ba17ef7cef768926c884177a3025eNicolas Geoffray bool garbage_collect_code) 1240c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray : lock_("Jit code cache", kJitCodeCacheLock), 1251dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray lock_cond_("Jit code cache variable", lock_), 1261dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray collection_in_progress_(false), 1270c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray code_map_(code_map), 1280a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray data_map_(data_map), 1290a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray max_capacity_(max_capacity), 1300a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray current_capacity_(initial_code_capacity + initial_data_capacity), 1310a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray code_end_(initial_code_capacity), 1320a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray data_end_(initial_data_capacity), 13335122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray last_collection_increased_code_cache_(false), 134a25dce9b452ba17ef7cef768926c884177a3025eNicolas Geoffray last_update_time_ns_(0), 1350a52223d9173315aeaca05217b8c792b3088ea7dNicolas Geoffray garbage_collect_code_(garbage_collect_code), 136b0d220835f2ddc03510f17fcc4fb4c64b426a0f5Nicolas Geoffray used_memory_for_data_(0), 137b0d220835f2ddc03510f17fcc4fb4c64b426a0f5Nicolas Geoffray used_memory_for_code_(0), 138fcdd72941810f03460a8efca0c6255439be80c35Nicolas Geoffray number_of_compilations_(0), 139bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray number_of_osr_compilations_(0), 140bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray number_of_deoptimizations_(0), 141933330a192d43d7c7304120999907857a89c2f96Nicolas Geoffray number_of_collections_(0), 142933330a192d43d7c7304120999907857a89c2f96Nicolas Geoffray histogram_stack_map_memory_use_("Memory used for stack maps", 16), 143933330a192d43d7c7304120999907857a89c2f96Nicolas Geoffray histogram_code_memory_use_("Memory used for compiled code", 16), 144933330a192d43d7c7304120999907857a89c2f96Nicolas Geoffray histogram_profiling_info_memory_use_("Memory used for profiling info", 16) { 1450c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray 146c3fec4c4ca01055d4d5920f363620b5726ebbbefNicolas Geoffray DCHECK_GE(max_capacity, initial_code_capacity + initial_data_capacity); 1470a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray code_mspace_ = create_mspace_with_base(code_map_->Begin(), code_end_, false /*locked*/); 1480a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray data_mspace_ = create_mspace_with_base(data_map_->Begin(), data_end_, false /*locked*/); 1490c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray 1500c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray if (code_mspace_ == nullptr || data_mspace_ == nullptr) { 1510c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray PLOG(FATAL) << "create_mspace_with_base failed"; 1520c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray } 1530c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray 1540a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray SetFootprintLimit(current_capacity_); 1550c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray 1560c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray CHECKED_MPROTECT(code_map_->Begin(), code_map_->Size(), kProtCode); 1570c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray CHECKED_MPROTECT(data_map_->Begin(), data_map_->Size(), kProtData); 158e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier 1590a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray VLOG(jit) << "Created jit code cache: initial data size=" 1600a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray << PrettySize(initial_data_capacity) 1610a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray << ", initial code size=" 1620a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray << PrettySize(initial_code_capacity); 163e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier} 164e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier 1651dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffraybool JitCodeCache::ContainsPc(const void* ptr) const { 1660c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray return code_map_->Begin() <= ptr && ptr < code_map_->End(); 167e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier} 168e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier 169a5891e81a2fb833307cf7c7e7267070dc0223dc8Nicolas Geoffraybool JitCodeCache::ContainsMethod(ArtMethod* method) { 170a5891e81a2fb833307cf7c7e7267070dc0223dc8Nicolas Geoffray MutexLock mu(Thread::Current(), lock_); 171a5891e81a2fb833307cf7c7e7267070dc0223dc8Nicolas Geoffray for (auto& it : method_code_map_) { 172a5891e81a2fb833307cf7c7e7267070dc0223dc8Nicolas Geoffray if (it.second == method) { 173a5891e81a2fb833307cf7c7e7267070dc0223dc8Nicolas Geoffray return true; 174a5891e81a2fb833307cf7c7e7267070dc0223dc8Nicolas Geoffray } 175a5891e81a2fb833307cf7c7e7267070dc0223dc8Nicolas Geoffray } 176a5891e81a2fb833307cf7c7e7267070dc0223dc8Nicolas Geoffray return false; 177a5891e81a2fb833307cf7c7e7267070dc0223dc8Nicolas Geoffray} 178a5891e81a2fb833307cf7c7e7267070dc0223dc8Nicolas Geoffray 17933fbf37feb959293b10d0b6e26d5e8ee7dff786cMathieu Chartierclass ScopedCodeCacheWrite : ScopedTrace { 1800c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray public: 18133fbf37feb959293b10d0b6e26d5e8ee7dff786cMathieu Chartier explicit ScopedCodeCacheWrite(MemMap* code_map) 18233fbf37feb959293b10d0b6e26d5e8ee7dff786cMathieu Chartier : ScopedTrace("ScopedCodeCacheWrite"), 18333fbf37feb959293b10d0b6e26d5e8ee7dff786cMathieu Chartier code_map_(code_map) { 18433fbf37feb959293b10d0b6e26d5e8ee7dff786cMathieu Chartier ScopedTrace trace("mprotect all"); 1850c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray CHECKED_MPROTECT(code_map_->Begin(), code_map_->Size(), kProtAll); 1860c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray } 1870c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray ~ScopedCodeCacheWrite() { 18833fbf37feb959293b10d0b6e26d5e8ee7dff786cMathieu Chartier ScopedTrace trace("mprotect code"); 1890c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray CHECKED_MPROTECT(code_map_->Begin(), code_map_->Size(), kProtCode); 1900c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray } 1910c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray private: 1920c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray MemMap* const code_map_; 1930c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray 1940c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray DISALLOW_COPY_AND_ASSIGN(ScopedCodeCacheWrite); 1950c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray}; 1960c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray 1970c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffrayuint8_t* JitCodeCache::CommitCode(Thread* self, 1981dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray ArtMethod* method, 1990c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray const uint8_t* vmap_table, 2000c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray size_t frame_size_in_bytes, 2010c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray size_t core_spill_mask, 2020c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray size_t fp_spill_mask, 2030c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray const uint8_t* code, 204b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray size_t code_size, 205b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray bool osr) { 2061dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray uint8_t* result = CommitCodeInternal(self, 2071dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray method, 2081dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray vmap_table, 2091dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray frame_size_in_bytes, 2101dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray core_spill_mask, 2111dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray fp_spill_mask, 2121dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray code, 213b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray code_size, 214b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray osr); 2151dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray if (result == nullptr) { 2161dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray // Retry. 2171dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray GarbageCollectCache(self); 2181dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray result = CommitCodeInternal(self, 2191dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray method, 2201dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray vmap_table, 2211dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray frame_size_in_bytes, 2221dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray core_spill_mask, 2231dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray fp_spill_mask, 2241dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray code, 225b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray code_size, 226b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray osr); 2271dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray } 2281dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray return result; 2291dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray} 2301dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray 2311dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffraybool JitCodeCache::WaitForPotentialCollectionToComplete(Thread* self) { 2321dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray bool in_collection = false; 2331dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray while (collection_in_progress_) { 2341dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray in_collection = true; 2351dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray lock_cond_.Wait(self); 2361dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray } 2371dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray return in_collection; 2381dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray} 2391dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray 2401dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffraystatic uintptr_t FromCodeToAllocation(const void* code) { 2411dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray size_t alignment = GetInstructionSetAlignment(kRuntimeISA); 2421dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray return reinterpret_cast<uintptr_t>(code) - RoundUp(sizeof(OatQuickMethodHeader), alignment); 2431dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray} 2441dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray 2451dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffrayvoid JitCodeCache::FreeCode(const void* code_ptr, ArtMethod* method ATTRIBUTE_UNUSED) { 2461dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray uintptr_t allocation = FromCodeToAllocation(code_ptr); 2471dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray const OatQuickMethodHeader* method_header = OatQuickMethodHeader::FromCodePointer(code_ptr); 2485cc349f3dd578e974f78314c50b6a0267c23e591David Srbecky // Notify native debugger that we are about to remove the code. 2495cc349f3dd578e974f78314c50b6a0267c23e591David Srbecky // It does nothing if we are not using native debugger. 2505cc349f3dd578e974f78314c50b6a0267c23e591David Srbecky DeleteJITCodeEntryForAddress(reinterpret_cast<uintptr_t>(code_ptr)); 25138ea9bd50debc63ceb77ec1e65036d8e2070ec7dNicolas Geoffray 2521dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray // Use the offset directly to prevent sanity check that the method is 2531dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray // compiled with optimizing. 2541dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray // TODO(ngeoffray): Clean up. 2551dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray if (method_header->vmap_table_offset_ != 0) { 25638ea9bd50debc63ceb77ec1e65036d8e2070ec7dNicolas Geoffray const uint8_t* data = method_header->code_ - method_header->vmap_table_offset_; 25738ea9bd50debc63ceb77ec1e65036d8e2070ec7dNicolas Geoffray FreeData(const_cast<uint8_t*>(data)); 2581dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray } 25938ea9bd50debc63ceb77ec1e65036d8e2070ec7dNicolas Geoffray FreeCode(reinterpret_cast<uint8_t*>(allocation)); 2601dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray} 2611dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray 2621dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffrayvoid JitCodeCache::RemoveMethodsIn(Thread* self, const LinearAlloc& alloc) { 26332ce2adefb8a3d0eda59a29f5e87c1eb43eef796Mathieu Chartier ScopedTrace trace(__PRETTY_FUNCTION__); 2641dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray MutexLock mu(self, lock_); 2651dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray // We do not check if a code cache GC is in progress, as this method comes 2661dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray // with the classlinker_classes_lock_ held, and suspending ourselves could 2671dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray // lead to a deadlock. 26826705e2b1245b65989a0341b24c5dbf2658d4bb6Nicolas Geoffray { 26926705e2b1245b65989a0341b24c5dbf2658d4bb6Nicolas Geoffray ScopedCodeCacheWrite scc(code_map_.get()); 27026705e2b1245b65989a0341b24c5dbf2658d4bb6Nicolas Geoffray for (auto it = method_code_map_.begin(); it != method_code_map_.end();) { 27126705e2b1245b65989a0341b24c5dbf2658d4bb6Nicolas Geoffray if (alloc.ContainsUnsafe(it->second)) { 27226705e2b1245b65989a0341b24c5dbf2658d4bb6Nicolas Geoffray FreeCode(it->first, it->second); 27326705e2b1245b65989a0341b24c5dbf2658d4bb6Nicolas Geoffray it = method_code_map_.erase(it); 27426705e2b1245b65989a0341b24c5dbf2658d4bb6Nicolas Geoffray } else { 27526705e2b1245b65989a0341b24c5dbf2658d4bb6Nicolas Geoffray ++it; 27626705e2b1245b65989a0341b24c5dbf2658d4bb6Nicolas Geoffray } 27726705e2b1245b65989a0341b24c5dbf2658d4bb6Nicolas Geoffray } 27826705e2b1245b65989a0341b24c5dbf2658d4bb6Nicolas Geoffray } 279a9b91313cee629d81d4784798d03419fc7fa9e11Nicolas Geoffray for (auto it = osr_code_map_.begin(); it != osr_code_map_.end();) { 280a9b91313cee629d81d4784798d03419fc7fa9e11Nicolas Geoffray if (alloc.ContainsUnsafe(it->first)) { 281a9b91313cee629d81d4784798d03419fc7fa9e11Nicolas Geoffray // Note that the code has already been removed in the loop above. 282a9b91313cee629d81d4784798d03419fc7fa9e11Nicolas Geoffray it = osr_code_map_.erase(it); 283a9b91313cee629d81d4784798d03419fc7fa9e11Nicolas Geoffray } else { 284a9b91313cee629d81d4784798d03419fc7fa9e11Nicolas Geoffray ++it; 285a9b91313cee629d81d4784798d03419fc7fa9e11Nicolas Geoffray } 286a9b91313cee629d81d4784798d03419fc7fa9e11Nicolas Geoffray } 28726705e2b1245b65989a0341b24c5dbf2658d4bb6Nicolas Geoffray for (auto it = profiling_infos_.begin(); it != profiling_infos_.end();) { 28826705e2b1245b65989a0341b24c5dbf2658d4bb6Nicolas Geoffray ProfilingInfo* info = *it; 28926705e2b1245b65989a0341b24c5dbf2658d4bb6Nicolas Geoffray if (alloc.ContainsUnsafe(info->GetMethod())) { 29026705e2b1245b65989a0341b24c5dbf2658d4bb6Nicolas Geoffray info->GetMethod()->SetProfilingInfo(nullptr); 29138ea9bd50debc63ceb77ec1e65036d8e2070ec7dNicolas Geoffray FreeData(reinterpret_cast<uint8_t*>(info)); 29226705e2b1245b65989a0341b24c5dbf2658d4bb6Nicolas Geoffray it = profiling_infos_.erase(it); 2931dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray } else { 2941dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray ++it; 2951dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray } 2961dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray } 2971dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray} 2981dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray 299b6e20ae17d0881a66c22532e4152ce6779454a92Nicolas Geoffrayvoid JitCodeCache::ClearGcRootsInInlineCaches(Thread* self) { 300b6e20ae17d0881a66c22532e4152ce6779454a92Nicolas Geoffray MutexLock mu(self, lock_); 301b6e20ae17d0881a66c22532e4152ce6779454a92Nicolas Geoffray for (ProfilingInfo* info : profiling_infos_) { 302b6e20ae17d0881a66c22532e4152ce6779454a92Nicolas Geoffray if (!info->IsInUseByCompiler()) { 303b6e20ae17d0881a66c22532e4152ce6779454a92Nicolas Geoffray info->ClearGcRootsInInlineCaches(); 304b6e20ae17d0881a66c22532e4152ce6779454a92Nicolas Geoffray } 305b6e20ae17d0881a66c22532e4152ce6779454a92Nicolas Geoffray } 306b6e20ae17d0881a66c22532e4152ce6779454a92Nicolas Geoffray} 307b6e20ae17d0881a66c22532e4152ce6779454a92Nicolas Geoffray 3081dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffrayuint8_t* JitCodeCache::CommitCodeInternal(Thread* self, 3091dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray ArtMethod* method, 3101dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray const uint8_t* vmap_table, 3111dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray size_t frame_size_in_bytes, 3121dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray size_t core_spill_mask, 3131dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray size_t fp_spill_mask, 3141dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray const uint8_t* code, 315b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray size_t code_size, 316b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray bool osr) { 3171e7de6cfcabc87ebd36bf6f2c9ed466152d21d4eNicolas Geoffray size_t alignment = GetInstructionSetAlignment(kRuntimeISA); 3181e7de6cfcabc87ebd36bf6f2c9ed466152d21d4eNicolas Geoffray // Ensure the header ends up at expected instruction alignment. 3191e7de6cfcabc87ebd36bf6f2c9ed466152d21d4eNicolas Geoffray size_t header_size = RoundUp(sizeof(OatQuickMethodHeader), alignment); 3201e7de6cfcabc87ebd36bf6f2c9ed466152d21d4eNicolas Geoffray size_t total_size = header_size + code_size; 3211e7de6cfcabc87ebd36bf6f2c9ed466152d21d4eNicolas Geoffray 3220c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray OatQuickMethodHeader* method_header = nullptr; 3231e7de6cfcabc87ebd36bf6f2c9ed466152d21d4eNicolas Geoffray uint8_t* code_ptr = nullptr; 32438ea9bd50debc63ceb77ec1e65036d8e2070ec7dNicolas Geoffray uint8_t* memory = nullptr; 3250c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray { 326d28b969c273ab777ca9b147b87fcef671b4f695fNicolas Geoffray ScopedThreadSuspension sts(self, kSuspended); 327d28b969c273ab777ca9b147b87fcef671b4f695fNicolas Geoffray MutexLock mu(self, lock_); 328d28b969c273ab777ca9b147b87fcef671b4f695fNicolas Geoffray WaitForPotentialCollectionToComplete(self); 329d28b969c273ab777ca9b147b87fcef671b4f695fNicolas Geoffray { 330d28b969c273ab777ca9b147b87fcef671b4f695fNicolas Geoffray ScopedCodeCacheWrite scc(code_map_.get()); 33138ea9bd50debc63ceb77ec1e65036d8e2070ec7dNicolas Geoffray memory = AllocateCode(total_size); 33238ea9bd50debc63ceb77ec1e65036d8e2070ec7dNicolas Geoffray if (memory == nullptr) { 333d28b969c273ab777ca9b147b87fcef671b4f695fNicolas Geoffray return nullptr; 334d28b969c273ab777ca9b147b87fcef671b4f695fNicolas Geoffray } 33538ea9bd50debc63ceb77ec1e65036d8e2070ec7dNicolas Geoffray code_ptr = memory + header_size; 336d28b969c273ab777ca9b147b87fcef671b4f695fNicolas Geoffray 337d28b969c273ab777ca9b147b87fcef671b4f695fNicolas Geoffray std::copy(code, code + code_size, code_ptr); 338d28b969c273ab777ca9b147b87fcef671b4f695fNicolas Geoffray method_header = OatQuickMethodHeader::FromCodePointer(code_ptr); 339d28b969c273ab777ca9b147b87fcef671b4f695fNicolas Geoffray new (method_header) OatQuickMethodHeader( 340d28b969c273ab777ca9b147b87fcef671b4f695fNicolas Geoffray (vmap_table == nullptr) ? 0 : code_ptr - vmap_table, 341d28b969c273ab777ca9b147b87fcef671b4f695fNicolas Geoffray frame_size_in_bytes, 342d28b969c273ab777ca9b147b87fcef671b4f695fNicolas Geoffray core_spill_mask, 343d28b969c273ab777ca9b147b87fcef671b4f695fNicolas Geoffray fp_spill_mask, 344d28b969c273ab777ca9b147b87fcef671b4f695fNicolas Geoffray code_size); 3450c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray } 346d28b969c273ab777ca9b147b87fcef671b4f695fNicolas Geoffray 347324302696c0a93511fef1310d309a54ebfb25a46Roland Levillain FlushInstructionCache(reinterpret_cast<char*>(code_ptr), 348324302696c0a93511fef1310d309a54ebfb25a46Roland Levillain reinterpret_cast<char*>(code_ptr + code_size)); 3490a52223d9173315aeaca05217b8c792b3088ea7dNicolas Geoffray number_of_compilations_++; 350a5891e81a2fb833307cf7c7e7267070dc0223dc8Nicolas Geoffray } 351a5891e81a2fb833307cf7c7e7267070dc0223dc8Nicolas Geoffray // We need to update the entry point in the runnable state for the instrumentation. 352a5891e81a2fb833307cf7c7e7267070dc0223dc8Nicolas Geoffray { 353a5891e81a2fb833307cf7c7e7267070dc0223dc8Nicolas Geoffray MutexLock mu(self, lock_); 354d28b969c273ab777ca9b147b87fcef671b4f695fNicolas Geoffray method_code_map_.Put(code_ptr, method); 355b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray if (osr) { 356fcdd72941810f03460a8efca0c6255439be80c35Nicolas Geoffray number_of_osr_compilations_++; 357b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray osr_code_map_.Put(method, code_ptr); 358c8a4f2c632afd44fc558aa37c98b9cf042b4bb5bNicolas Geoffray } else { 359b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray Runtime::Current()->GetInstrumentation()->UpdateMethodsCode( 360b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray method, method_header->GetEntryPoint()); 361b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray } 362a5891e81a2fb833307cf7c7e7267070dc0223dc8Nicolas Geoffray if (collection_in_progress_) { 363a5891e81a2fb833307cf7c7e7267070dc0223dc8Nicolas Geoffray // We need to update the live bitmap if there is a GC to ensure it sees this new 364a5891e81a2fb833307cf7c7e7267070dc0223dc8Nicolas Geoffray // code. 365a5891e81a2fb833307cf7c7e7267070dc0223dc8Nicolas Geoffray GetLiveBitmap()->AtomicTestAndSet(FromCodeToAllocation(code_ptr)); 366a5891e81a2fb833307cf7c7e7267070dc0223dc8Nicolas Geoffray } 3674d77b6a511659f26fdc711e23825ffa6e7feed7aCalin Juravle last_update_time_ns_.StoreRelease(NanoTime()); 368a5891e81a2fb833307cf7c7e7267070dc0223dc8Nicolas Geoffray VLOG(jit) 369f3f9cf6b65c4bcf9ea44253188d8d910b7cf7e64Nicolas Geoffray << "JIT added (osr=" << std::boolalpha << osr << std::noboolalpha << ") " 370a5891e81a2fb833307cf7c7e7267070dc0223dc8Nicolas Geoffray << PrettyMethod(method) << "@" << method 371a5891e81a2fb833307cf7c7e7267070dc0223dc8Nicolas Geoffray << " ccache_size=" << PrettySize(CodeCacheSizeLocked()) << ": " 372a5891e81a2fb833307cf7c7e7267070dc0223dc8Nicolas Geoffray << " dcache_size=" << PrettySize(DataCacheSizeLocked()) << ": " 373a5891e81a2fb833307cf7c7e7267070dc0223dc8Nicolas Geoffray << reinterpret_cast<const void*>(method_header->GetEntryPoint()) << "," 374a5891e81a2fb833307cf7c7e7267070dc0223dc8Nicolas Geoffray << reinterpret_cast<const void*>(method_header->GetEntryPoint() + method_header->code_size_); 375933330a192d43d7c7304120999907857a89c2f96Nicolas Geoffray histogram_code_memory_use_.AddValue(code_size); 376933330a192d43d7c7304120999907857a89c2f96Nicolas Geoffray if (code_size > kCodeSizeLogThreshold) { 377933330a192d43d7c7304120999907857a89c2f96Nicolas Geoffray LOG(INFO) << "JIT allocated " 378933330a192d43d7c7304120999907857a89c2f96Nicolas Geoffray << PrettySize(code_size) 379933330a192d43d7c7304120999907857a89c2f96Nicolas Geoffray << " for compiled code of " 380933330a192d43d7c7304120999907857a89c2f96Nicolas Geoffray << PrettyMethod(method); 381933330a192d43d7c7304120999907857a89c2f96Nicolas Geoffray } 382e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier } 3830c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray 3840c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray return reinterpret_cast<uint8_t*>(method_header); 3850c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray} 3860c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray 3870c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffraysize_t JitCodeCache::CodeCacheSize() { 3880c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray MutexLock mu(Thread::Current(), lock_); 389a5891e81a2fb833307cf7c7e7267070dc0223dc8Nicolas Geoffray return CodeCacheSizeLocked(); 390a5891e81a2fb833307cf7c7e7267070dc0223dc8Nicolas Geoffray} 391a5891e81a2fb833307cf7c7e7267070dc0223dc8Nicolas Geoffray 392a5891e81a2fb833307cf7c7e7267070dc0223dc8Nicolas Geoffraysize_t JitCodeCache::CodeCacheSizeLocked() { 39338ea9bd50debc63ceb77ec1e65036d8e2070ec7dNicolas Geoffray return used_memory_for_code_; 3940c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray} 3950c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray 3960c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffraysize_t JitCodeCache::DataCacheSize() { 3970c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray MutexLock mu(Thread::Current(), lock_); 398a5891e81a2fb833307cf7c7e7267070dc0223dc8Nicolas Geoffray return DataCacheSizeLocked(); 399a5891e81a2fb833307cf7c7e7267070dc0223dc8Nicolas Geoffray} 400a5891e81a2fb833307cf7c7e7267070dc0223dc8Nicolas Geoffray 401a5891e81a2fb833307cf7c7e7267070dc0223dc8Nicolas Geoffraysize_t JitCodeCache::DataCacheSizeLocked() { 40238ea9bd50debc63ceb77ec1e65036d8e2070ec7dNicolas Geoffray return used_memory_for_data_; 403e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier} 404e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier 405d28b969c273ab777ca9b147b87fcef671b4f695fNicolas Geoffrayvoid JitCodeCache::ClearData(Thread* self, void* data) { 406d28b969c273ab777ca9b147b87fcef671b4f695fNicolas Geoffray MutexLock mu(self, lock_); 40738ea9bd50debc63ceb77ec1e65036d8e2070ec7dNicolas Geoffray FreeData(reinterpret_cast<uint8_t*>(data)); 408d28b969c273ab777ca9b147b87fcef671b4f695fNicolas Geoffray} 409d28b969c273ab777ca9b147b87fcef671b4f695fNicolas Geoffray 410933330a192d43d7c7304120999907857a89c2f96Nicolas Geoffrayuint8_t* JitCodeCache::ReserveData(Thread* self, size_t size, ArtMethod* method) { 4115550ca8bcc742b109d77e62f3a0877c667d894d3Nicolas Geoffray size = RoundUp(size, sizeof(void*)); 4121dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray uint8_t* result = nullptr; 4131dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray 4141dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray { 4151dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray ScopedThreadSuspension sts(self, kSuspended); 4161dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray MutexLock mu(self, lock_); 4171dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray WaitForPotentialCollectionToComplete(self); 41838ea9bd50debc63ceb77ec1e65036d8e2070ec7dNicolas Geoffray result = AllocateData(size); 4191dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray } 4201dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray 4211dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray if (result == nullptr) { 4221dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray // Retry. 4231dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray GarbageCollectCache(self); 4241dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray ScopedThreadSuspension sts(self, kSuspended); 4251dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray MutexLock mu(self, lock_); 4261dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray WaitForPotentialCollectionToComplete(self); 42738ea9bd50debc63ceb77ec1e65036d8e2070ec7dNicolas Geoffray result = AllocateData(size); 4281dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray } 4291dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray 430933330a192d43d7c7304120999907857a89c2f96Nicolas Geoffray MutexLock mu(self, lock_); 431933330a192d43d7c7304120999907857a89c2f96Nicolas Geoffray histogram_stack_map_memory_use_.AddValue(size); 432933330a192d43d7c7304120999907857a89c2f96Nicolas Geoffray if (size > kStackMapSizeLogThreshold) { 433933330a192d43d7c7304120999907857a89c2f96Nicolas Geoffray LOG(INFO) << "JIT allocated " 434933330a192d43d7c7304120999907857a89c2f96Nicolas Geoffray << PrettySize(size) 435933330a192d43d7c7304120999907857a89c2f96Nicolas Geoffray << " for stack maps of " 436933330a192d43d7c7304120999907857a89c2f96Nicolas Geoffray << PrettyMethod(method); 437e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier } 4380c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray return result; 439e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier} 440e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier 4411dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffrayclass MarkCodeVisitor FINAL : public StackVisitor { 4421dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray public: 4431dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray MarkCodeVisitor(Thread* thread_in, JitCodeCache* code_cache_in) 4441dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray : StackVisitor(thread_in, nullptr, StackVisitor::StackWalkKind::kSkipInlinedFrames), 4451dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray code_cache_(code_cache_in), 4461dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray bitmap_(code_cache_->GetLiveBitmap()) {} 4471dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray 4481dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray bool VisitFrame() OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_) { 4491dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray const OatQuickMethodHeader* method_header = GetCurrentOatQuickMethodHeader(); 4501dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray if (method_header == nullptr) { 4511dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray return true; 4521dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray } 4531dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray const void* code = method_header->GetCode(); 4541dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray if (code_cache_->ContainsPc(code)) { 4551dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray // Use the atomic set version, as multiple threads are executing this code. 4561dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray bitmap_->AtomicTestAndSet(FromCodeToAllocation(code)); 4571dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray } 4581dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray return true; 459e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier } 4601dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray 4611dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray private: 4621dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray JitCodeCache* const code_cache_; 4631dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray CodeCacheBitmap* const bitmap_; 4641dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray}; 4651dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray 4661dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffrayclass MarkCodeClosure FINAL : public Closure { 4671dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray public: 4681dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray MarkCodeClosure(JitCodeCache* code_cache, Barrier* barrier) 4691dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray : code_cache_(code_cache), barrier_(barrier) {} 4701dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray 4711dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray void Run(Thread* thread) OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_) { 47232ce2adefb8a3d0eda59a29f5e87c1eb43eef796Mathieu Chartier ScopedTrace trace(__PRETTY_FUNCTION__); 4731dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray DCHECK(thread == Thread::Current() || thread->IsSuspended()); 4741dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray MarkCodeVisitor visitor(thread, code_cache_); 4751dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray visitor.WalkStack(); 4765a23d2ea6e0d89112ff11ec765e676c03818b7c2Nicolas Geoffray if (kIsDebugBuild) { 4775a23d2ea6e0d89112ff11ec765e676c03818b7c2Nicolas Geoffray // The stack walking code queries the side instrumentation stack if it 4785a23d2ea6e0d89112ff11ec765e676c03818b7c2Nicolas Geoffray // sees an instrumentation exit pc, so the JIT code of methods in that stack 4795a23d2ea6e0d89112ff11ec765e676c03818b7c2Nicolas Geoffray // must have been seen. We sanity check this below. 4805a23d2ea6e0d89112ff11ec765e676c03818b7c2Nicolas Geoffray for (const instrumentation::InstrumentationStackFrame& frame 4815a23d2ea6e0d89112ff11ec765e676c03818b7c2Nicolas Geoffray : *thread->GetInstrumentationStack()) { 4825a23d2ea6e0d89112ff11ec765e676c03818b7c2Nicolas Geoffray // The 'method_' in InstrumentationStackFrame is the one that has return_pc_ in 4835a23d2ea6e0d89112ff11ec765e676c03818b7c2Nicolas Geoffray // its stack frame, it is not the method owning return_pc_. We just pass null to 4845a23d2ea6e0d89112ff11ec765e676c03818b7c2Nicolas Geoffray // LookupMethodHeader: the method is only checked against in debug builds. 4855a23d2ea6e0d89112ff11ec765e676c03818b7c2Nicolas Geoffray OatQuickMethodHeader* method_header = 4865a23d2ea6e0d89112ff11ec765e676c03818b7c2Nicolas Geoffray code_cache_->LookupMethodHeader(frame.return_pc_, nullptr); 4875a23d2ea6e0d89112ff11ec765e676c03818b7c2Nicolas Geoffray if (method_header != nullptr) { 4885a23d2ea6e0d89112ff11ec765e676c03818b7c2Nicolas Geoffray const void* code = method_header->GetCode(); 4895a23d2ea6e0d89112ff11ec765e676c03818b7c2Nicolas Geoffray CHECK(code_cache_->GetLiveBitmap()->Test(FromCodeToAllocation(code))); 4905a23d2ea6e0d89112ff11ec765e676c03818b7c2Nicolas Geoffray } 4915a23d2ea6e0d89112ff11ec765e676c03818b7c2Nicolas Geoffray } 4925a23d2ea6e0d89112ff11ec765e676c03818b7c2Nicolas Geoffray } 49310d2508b105427ef1bcaf0c222873bae7acc66d3Mathieu Chartier barrier_->Pass(Thread::Current()); 4941dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray } 4951dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray 4961dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray private: 4971dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray JitCodeCache* const code_cache_; 4981dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray Barrier* const barrier_; 4991dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray}; 5001dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray 5010a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffrayvoid JitCodeCache::NotifyCollectionDone(Thread* self) { 5020a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray collection_in_progress_ = false; 5030a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray lock_cond_.Broadcast(self); 5040a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray} 5050a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray 5060a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffrayvoid JitCodeCache::SetFootprintLimit(size_t new_footprint) { 5070a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray size_t per_space_footprint = new_footprint / 2; 5080a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray DCHECK(IsAlignedParam(per_space_footprint, kPageSize)); 5090a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray DCHECK_EQ(per_space_footprint * 2, new_footprint); 5100a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray mspace_set_footprint_limit(data_mspace_, per_space_footprint); 5110a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray { 5120a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray ScopedCodeCacheWrite scc(code_map_.get()); 5130a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray mspace_set_footprint_limit(code_mspace_, per_space_footprint); 5140a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray } 5150a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray} 5160a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray 5170a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffraybool JitCodeCache::IncreaseCodeCacheCapacity() { 5180a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray if (current_capacity_ == max_capacity_) { 5190a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray return false; 5200a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray } 5210a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray 5220a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray // Double the capacity if we're below 1MB, or increase it by 1MB if 5230a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray // we're above. 5240a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray if (current_capacity_ < 1 * MB) { 5250a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray current_capacity_ *= 2; 5260a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray } else { 5270a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray current_capacity_ += 1 * MB; 5280a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray } 5290a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray if (current_capacity_ > max_capacity_) { 5300a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray current_capacity_ = max_capacity_; 5310a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray } 5320a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray 5331dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray if (!kIsDebugBuild || VLOG_IS_ON(jit)) { 5340a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray LOG(INFO) << "Increasing code cache capacity to " << PrettySize(current_capacity_); 5351dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray } 5361dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray 5370a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray SetFootprintLimit(current_capacity_); 5380a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray 5390a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray return true; 5400a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray} 5410a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray 5428d37250f7b9a7839b11488f45a1842b025026f94Nicolas Geoffrayvoid JitCodeCache::MarkCompiledCodeOnThreadStacks(Thread* self) { 5438d37250f7b9a7839b11488f45a1842b025026f94Nicolas Geoffray Barrier barrier(0); 5448d37250f7b9a7839b11488f45a1842b025026f94Nicolas Geoffray size_t threads_running_checkpoint = 0; 5458d37250f7b9a7839b11488f45a1842b025026f94Nicolas Geoffray MarkCodeClosure closure(this, &barrier); 5468d37250f7b9a7839b11488f45a1842b025026f94Nicolas Geoffray threads_running_checkpoint = Runtime::Current()->GetThreadList()->RunCheckpoint(&closure); 5478d37250f7b9a7839b11488f45a1842b025026f94Nicolas Geoffray // Now that we have run our checkpoint, move to a suspended state and wait 5488d37250f7b9a7839b11488f45a1842b025026f94Nicolas Geoffray // for other threads to run the checkpoint. 5498d37250f7b9a7839b11488f45a1842b025026f94Nicolas Geoffray ScopedThreadSuspension sts(self, kSuspended); 5508d37250f7b9a7839b11488f45a1842b025026f94Nicolas Geoffray if (threads_running_checkpoint != 0) { 5518d37250f7b9a7839b11488f45a1842b025026f94Nicolas Geoffray barrier.Increment(self, threads_running_checkpoint); 5528d37250f7b9a7839b11488f45a1842b025026f94Nicolas Geoffray } 5538d37250f7b9a7839b11488f45a1842b025026f94Nicolas Geoffray} 5548d37250f7b9a7839b11488f45a1842b025026f94Nicolas Geoffray 55535122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffraybool JitCodeCache::ShouldDoFullCollection() { 55635122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray if (current_capacity_ == max_capacity_) { 55735122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray // Always do a full collection when the code cache is full. 55835122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray return true; 55935122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray } else if (current_capacity_ < kReservedCapacity) { 56035122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray // Always do partial collection when the code cache size is below the reserved 56135122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray // capacity. 56235122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray return false; 56335122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray } else if (last_collection_increased_code_cache_) { 56435122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray // This time do a full collection. 56535122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray return true; 56635122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray } else { 56735122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray // This time do a partial collection. 56835122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray return false; 5698d37250f7b9a7839b11488f45a1842b025026f94Nicolas Geoffray } 5708d37250f7b9a7839b11488f45a1842b025026f94Nicolas Geoffray} 5718d37250f7b9a7839b11488f45a1842b025026f94Nicolas Geoffray 5720a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffrayvoid JitCodeCache::GarbageCollectCache(Thread* self) { 57332ce2adefb8a3d0eda59a29f5e87c1eb43eef796Mathieu Chartier ScopedTrace trace(__FUNCTION__); 5748d37250f7b9a7839b11488f45a1842b025026f94Nicolas Geoffray if (!garbage_collect_code_) { 5758d37250f7b9a7839b11488f45a1842b025026f94Nicolas Geoffray MutexLock mu(self, lock_); 5768d37250f7b9a7839b11488f45a1842b025026f94Nicolas Geoffray IncreaseCodeCacheCapacity(); 5778d37250f7b9a7839b11488f45a1842b025026f94Nicolas Geoffray return; 5788d37250f7b9a7839b11488f45a1842b025026f94Nicolas Geoffray } 5791dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray 580a5891e81a2fb833307cf7c7e7267070dc0223dc8Nicolas Geoffray // Wait for an existing collection, or let everyone know we are starting one. 5811dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray { 582a5891e81a2fb833307cf7c7e7267070dc0223dc8Nicolas Geoffray ScopedThreadSuspension sts(self, kSuspended); 5831dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray MutexLock mu(self, lock_); 5841dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray if (WaitForPotentialCollectionToComplete(self)) { 5851dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray return; 586a5891e81a2fb833307cf7c7e7267070dc0223dc8Nicolas Geoffray } else { 587bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray number_of_collections_++; 5888d37250f7b9a7839b11488f45a1842b025026f94Nicolas Geoffray live_bitmap_.reset(CodeCacheBitmap::Create( 5898d37250f7b9a7839b11488f45a1842b025026f94Nicolas Geoffray "code-cache-bitmap", 5908d37250f7b9a7839b11488f45a1842b025026f94Nicolas Geoffray reinterpret_cast<uintptr_t>(code_map_->Begin()), 5918d37250f7b9a7839b11488f45a1842b025026f94Nicolas Geoffray reinterpret_cast<uintptr_t>(code_map_->Begin() + current_capacity_ / 2))); 592a5891e81a2fb833307cf7c7e7267070dc0223dc8Nicolas Geoffray collection_in_progress_ = true; 5931dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray } 594a5891e81a2fb833307cf7c7e7267070dc0223dc8Nicolas Geoffray } 5950a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray 596bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray TimingLogger logger("JIT code cache timing logger", true, VLOG_IS_ON(jit)); 5978d37250f7b9a7839b11488f45a1842b025026f94Nicolas Geoffray { 598bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray TimingLogger::ScopedTiming st("Code cache collection", &logger); 5998d37250f7b9a7839b11488f45a1842b025026f94Nicolas Geoffray 600bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray bool do_full_collection = false; 601bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray { 602bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray MutexLock mu(self, lock_); 603bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray do_full_collection = ShouldDoFullCollection(); 604bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray } 60535122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray 606bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray if (!kIsDebugBuild || VLOG_IS_ON(jit)) { 607bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray LOG(INFO) << "Do " 608bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray << (do_full_collection ? "full" : "partial") 609bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray << " code cache collection, code=" 610bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray << PrettySize(CodeCacheSize()) 611bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray << ", data=" << PrettySize(DataCacheSize()); 612bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray } 6138d37250f7b9a7839b11488f45a1842b025026f94Nicolas Geoffray 614bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray DoCollection(self, /* collect_profiling_info */ do_full_collection); 61535122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray 616bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray if (!kIsDebugBuild || VLOG_IS_ON(jit)) { 617bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray LOG(INFO) << "After code cache collection, code=" 618bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray << PrettySize(CodeCacheSize()) 619bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray << ", data=" << PrettySize(DataCacheSize()); 62035122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray } 62135122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray 622bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray { 623bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray MutexLock mu(self, lock_); 624bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray 625bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray // Increase the code cache only when we do partial collections. 626bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray // TODO: base this strategy on how full the code cache is? 627bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray if (do_full_collection) { 628bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray last_collection_increased_code_cache_ = false; 629bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray } else { 630bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray last_collection_increased_code_cache_ = true; 631bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray IncreaseCodeCacheCapacity(); 632bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray } 63335122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray 634bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray bool next_collection_will_be_full = ShouldDoFullCollection(); 635bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray 636bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray // Start polling the liveness of compiled code to prepare for the next full collection. 637c8a4f2c632afd44fc558aa37c98b9cf042b4bb5bNicolas Geoffray if (next_collection_will_be_full) { 638bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray // Save the entry point of methods we have compiled, and update the entry 639bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray // point of those methods to the interpreter. If the method is invoked, the 640bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray // interpreter will update its entry point to the compiled code and call it. 641bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray for (ProfilingInfo* info : profiling_infos_) { 642bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray const void* entry_point = info->GetMethod()->GetEntryPointFromQuickCompiledCode(); 643bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray if (ContainsPc(entry_point)) { 644bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray info->SetSavedEntryPoint(entry_point); 645c8a4f2c632afd44fc558aa37c98b9cf042b4bb5bNicolas Geoffray Runtime::Current()->GetInstrumentation()->UpdateMethodsCode( 646c8a4f2c632afd44fc558aa37c98b9cf042b4bb5bNicolas Geoffray info->GetMethod(), GetQuickToInterpreterBridge()); 647bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray } 64835122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray } 64935122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray 650bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray DCHECK(CheckLiveCompiledCodeHasProfilingInfo()); 651bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray } 652bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray live_bitmap_.reset(nullptr); 653bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray NotifyCollectionDone(self); 6540a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray } 6550a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray } 656bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray Runtime::Current()->GetJit()->AddTimingLogger(logger); 65735122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray} 6580a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray 6599abb2978f09643227664ab70c0677744b8f6e946Nicolas Geoffrayvoid JitCodeCache::RemoveUnmarkedCode(Thread* self) { 66032ce2adefb8a3d0eda59a29f5e87c1eb43eef796Mathieu Chartier ScopedTrace trace(__FUNCTION__); 66135122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray MutexLock mu(self, lock_); 66235122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray ScopedCodeCacheWrite scc(code_map_.get()); 6639abb2978f09643227664ab70c0677744b8f6e946Nicolas Geoffray // Iterate over all compiled code and remove entries that are not marked. 66435122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray for (auto it = method_code_map_.begin(); it != method_code_map_.end();) { 66535122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray const void* code_ptr = it->first; 66635122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray ArtMethod* method = it->second; 66735122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray uintptr_t allocation = FromCodeToAllocation(code_ptr); 6689abb2978f09643227664ab70c0677744b8f6e946Nicolas Geoffray if (GetLiveBitmap()->Test(allocation)) { 66935122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray ++it; 67035122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray } else { 67135122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray FreeCode(code_ptr, method); 67235122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray it = method_code_map_.erase(it); 67335122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray } 6740a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray } 6758d37250f7b9a7839b11488f45a1842b025026f94Nicolas Geoffray} 6768d37250f7b9a7839b11488f45a1842b025026f94Nicolas Geoffray 67735122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffrayvoid JitCodeCache::DoCollection(Thread* self, bool collect_profiling_info) { 67832ce2adefb8a3d0eda59a29f5e87c1eb43eef796Mathieu Chartier ScopedTrace trace(__FUNCTION__); 679a5891e81a2fb833307cf7c7e7267070dc0223dc8Nicolas Geoffray { 680a5891e81a2fb833307cf7c7e7267070dc0223dc8Nicolas Geoffray MutexLock mu(self, lock_); 68135122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray if (collect_profiling_info) { 68235122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray // Clear the profiling info of methods that do not have compiled code as entrypoint. 68335122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray // Also remove the saved entry point from the ProfilingInfo objects. 68435122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray for (ProfilingInfo* info : profiling_infos_) { 68535122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray const void* ptr = info->GetMethod()->GetEntryPointFromQuickCompiledCode(); 686b6e20ae17d0881a66c22532e4152ce6779454a92Nicolas Geoffray if (!ContainsPc(ptr) && !info->IsInUseByCompiler()) { 68735122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray info->GetMethod()->SetProfilingInfo(nullptr); 68835122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray } 689b9a639df2f21dd67b9f4379f31b7ccc5dd48ebd6Nicolas Geoffray 690b9a639df2f21dd67b9f4379f31b7ccc5dd48ebd6Nicolas Geoffray if (info->GetSavedEntryPoint() != nullptr) { 691b9a639df2f21dd67b9f4379f31b7ccc5dd48ebd6Nicolas Geoffray info->SetSavedEntryPoint(nullptr); 692b9a639df2f21dd67b9f4379f31b7ccc5dd48ebd6Nicolas Geoffray // We are going to move this method back to interpreter. Clear the counter now to 693b9a639df2f21dd67b9f4379f31b7ccc5dd48ebd6Nicolas Geoffray // give it a chance to be hot again. 694b9a639df2f21dd67b9f4379f31b7ccc5dd48ebd6Nicolas Geoffray info->GetMethod()->ClearCounter(); 695b9a639df2f21dd67b9f4379f31b7ccc5dd48ebd6Nicolas Geoffray } 69635122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray } 69735122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray } else if (kIsDebugBuild) { 69835122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray // Sanity check that the profiling infos do not have a dangling entry point. 69935122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray for (ProfilingInfo* info : profiling_infos_) { 70035122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray DCHECK(info->GetSavedEntryPoint() == nullptr); 70173be1e8f8609708f6624bb297c9628de44fd8b6fNicolas Geoffray } 70226705e2b1245b65989a0341b24c5dbf2658d4bb6Nicolas Geoffray } 703b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray 7049abb2978f09643227664ab70c0677744b8f6e946Nicolas Geoffray // Mark compiled code that are entrypoints of ArtMethods. Compiled code that is not 7059abb2978f09643227664ab70c0677744b8f6e946Nicolas Geoffray // an entry point is either: 7069abb2978f09643227664ab70c0677744b8f6e946Nicolas Geoffray // - an osr compiled code, that will be removed if not in a thread call stack. 7079abb2978f09643227664ab70c0677744b8f6e946Nicolas Geoffray // - discarded compiled code, that will be removed if not in a thread call stack. 7089abb2978f09643227664ab70c0677744b8f6e946Nicolas Geoffray for (const auto& it : method_code_map_) { 7099abb2978f09643227664ab70c0677744b8f6e946Nicolas Geoffray ArtMethod* method = it.second; 7109abb2978f09643227664ab70c0677744b8f6e946Nicolas Geoffray const void* code_ptr = it.first; 7119abb2978f09643227664ab70c0677744b8f6e946Nicolas Geoffray const OatQuickMethodHeader* method_header = OatQuickMethodHeader::FromCodePointer(code_ptr); 7129abb2978f09643227664ab70c0677744b8f6e946Nicolas Geoffray if (method_header->GetEntryPoint() == method->GetEntryPointFromQuickCompiledCode()) { 7139abb2978f09643227664ab70c0677744b8f6e946Nicolas Geoffray GetLiveBitmap()->AtomicTestAndSet(FromCodeToAllocation(code_ptr)); 7149abb2978f09643227664ab70c0677744b8f6e946Nicolas Geoffray } 7159abb2978f09643227664ab70c0677744b8f6e946Nicolas Geoffray } 7169abb2978f09643227664ab70c0677744b8f6e946Nicolas Geoffray 717d9994f069dfeaa32ba929ca78816b5b83e2a4134Nicolas Geoffray // Empty osr method map, as osr compiled code will be deleted (except the ones 718b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray // on thread stacks). 719b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray osr_code_map_.clear(); 7201dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray } 7211dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray 7221dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray // Run a checkpoint on all threads to mark the JIT compiled code they are running. 7238d37250f7b9a7839b11488f45a1842b025026f94Nicolas Geoffray MarkCompiledCodeOnThreadStacks(self); 7241dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray 7259abb2978f09643227664ab70c0677744b8f6e946Nicolas Geoffray // At this point, mutator threads are still running, and entrypoints of methods can 7269abb2978f09643227664ab70c0677744b8f6e946Nicolas Geoffray // change. We do know they cannot change to a code cache entry that is not marked, 7279abb2978f09643227664ab70c0677744b8f6e946Nicolas Geoffray // therefore we can safely remove those entries. 7289abb2978f09643227664ab70c0677744b8f6e946Nicolas Geoffray RemoveUnmarkedCode(self); 729a96917a6983a5abbe973255a3846fda549fb1657Nicolas Geoffray 73035122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray if (collect_profiling_info) { 73199c959f3868512bb95432cf02a1f0ad3971698bfNicolas Geoffray ScopedThreadSuspension sts(self, kSuspended); 73299c959f3868512bb95432cf02a1f0ad3971698bfNicolas Geoffray gc::ScopedGCCriticalSection gcs( 73399c959f3868512bb95432cf02a1f0ad3971698bfNicolas Geoffray self, gc::kGcCauseJitCodeCache, gc::kCollectorTypeJitCodeCache); 73435122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray MutexLock mu(self, lock_); 73535122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray // Free all profiling infos of methods not compiled nor being compiled. 73673be1e8f8609708f6624bb297c9628de44fd8b6fNicolas Geoffray auto profiling_kept_end = std::remove_if(profiling_infos_.begin(), profiling_infos_.end(), 73738ea9bd50debc63ceb77ec1e65036d8e2070ec7dNicolas Geoffray [this] (ProfilingInfo* info) NO_THREAD_SAFETY_ANALYSIS { 73835122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray const void* ptr = info->GetMethod()->GetEntryPointFromQuickCompiledCode(); 739511e41b4ec2d378a5c434598ebd0b3d6136fff9dNicolas Geoffray // We have previously cleared the ProfilingInfo pointer in the ArtMethod in the hope 740511e41b4ec2d378a5c434598ebd0b3d6136fff9dNicolas Geoffray // that the compiled code would not get revived. As mutator threads run concurrently, 741511e41b4ec2d378a5c434598ebd0b3d6136fff9dNicolas Geoffray // they may have revived the compiled code, and now we are in the situation where 742511e41b4ec2d378a5c434598ebd0b3d6136fff9dNicolas Geoffray // a method has compiled code but no ProfilingInfo. 743511e41b4ec2d378a5c434598ebd0b3d6136fff9dNicolas Geoffray // We make sure compiled methods have a ProfilingInfo object. It is needed for 744511e41b4ec2d378a5c434598ebd0b3d6136fff9dNicolas Geoffray // code cache collection. 74535122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray if (ContainsPc(ptr) && info->GetMethod()->GetProfilingInfo(sizeof(void*)) == nullptr) { 746511e41b4ec2d378a5c434598ebd0b3d6136fff9dNicolas Geoffray // We clear the inline caches as classes in it might be stalled. 747b6e20ae17d0881a66c22532e4152ce6779454a92Nicolas Geoffray info->ClearGcRootsInInlineCaches(); 748511e41b4ec2d378a5c434598ebd0b3d6136fff9dNicolas Geoffray // Do a fence to make sure the clearing is seen before attaching to the method. 749511e41b4ec2d378a5c434598ebd0b3d6136fff9dNicolas Geoffray QuasiAtomic::ThreadFenceRelease(); 75035122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray info->GetMethod()->SetProfilingInfo(info); 75135122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray } else if (info->GetMethod()->GetProfilingInfo(sizeof(void*)) != info) { 75235122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray // No need for this ProfilingInfo object anymore. 75338ea9bd50debc63ceb77ec1e65036d8e2070ec7dNicolas Geoffray FreeData(reinterpret_cast<uint8_t*>(info)); 75473be1e8f8609708f6624bb297c9628de44fd8b6fNicolas Geoffray return true; 75573be1e8f8609708f6624bb297c9628de44fd8b6fNicolas Geoffray } 75673be1e8f8609708f6624bb297c9628de44fd8b6fNicolas Geoffray return false; 75773be1e8f8609708f6624bb297c9628de44fd8b6fNicolas Geoffray }); 75873be1e8f8609708f6624bb297c9628de44fd8b6fNicolas Geoffray profiling_infos_.erase(profiling_kept_end, profiling_infos_.end()); 75935122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray DCHECK(CheckLiveCompiledCodeHasProfilingInfo()); 760e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier } 761e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier} 762e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier 76335122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffraybool JitCodeCache::CheckLiveCompiledCodeHasProfilingInfo() { 76432ce2adefb8a3d0eda59a29f5e87c1eb43eef796Mathieu Chartier ScopedTrace trace(__FUNCTION__); 76535122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray // Check that methods we have compiled do have a ProfilingInfo object. We would 76635122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray // have memory leaks of compiled code otherwise. 76735122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray for (const auto& it : method_code_map_) { 76835122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray ArtMethod* method = it.second; 76935122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray if (method->GetProfilingInfo(sizeof(void*)) == nullptr) { 77035122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray const void* code_ptr = it.first; 77135122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray const OatQuickMethodHeader* method_header = OatQuickMethodHeader::FromCodePointer(code_ptr); 77235122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray if (method_header->GetEntryPoint() == method->GetEntryPointFromQuickCompiledCode()) { 77335122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray // If the code is not dead, then we have a problem. Note that this can even 77435122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray // happen just after a collection, as mutator threads are running in parallel 77535122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray // and could deoptimize an existing compiled code. 77635122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray return false; 77735122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray } 77835122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray } 77935122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray } 78035122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray return true; 78135122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray} 7821dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray 7831dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas GeoffrayOatQuickMethodHeader* JitCodeCache::LookupMethodHeader(uintptr_t pc, ArtMethod* method) { 7841dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray static_assert(kRuntimeISA != kThumb2, "kThumb2 cannot be a runtime ISA"); 7851dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray if (kRuntimeISA == kArm) { 7861dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray // On Thumb-2, the pc is offset by one. 7871dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray --pc; 7881dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray } 7891dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray if (!ContainsPc(reinterpret_cast<const void*>(pc))) { 7901dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray return nullptr; 7911dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray } 7921dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray 793e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier MutexLock mu(Thread::Current(), lock_); 7941dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray if (method_code_map_.empty()) { 7951dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray return nullptr; 7961dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray } 7971dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray auto it = method_code_map_.lower_bound(reinterpret_cast<const void*>(pc)); 7981dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray --it; 7991dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray 8001dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray const void* code_ptr = it->first; 8011dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray OatQuickMethodHeader* method_header = OatQuickMethodHeader::FromCodePointer(code_ptr); 8021dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray if (!method_header->Contains(pc)) { 8031dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray return nullptr; 804e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier } 8055a23d2ea6e0d89112ff11ec765e676c03818b7c2Nicolas Geoffray if (kIsDebugBuild && method != nullptr) { 8065a23d2ea6e0d89112ff11ec765e676c03818b7c2Nicolas Geoffray DCHECK_EQ(it->second, method) 8075a23d2ea6e0d89112ff11ec765e676c03818b7c2Nicolas Geoffray << PrettyMethod(method) << " " << PrettyMethod(it->second) << " " << std::hex << pc; 8085a23d2ea6e0d89112ff11ec765e676c03818b7c2Nicolas Geoffray } 8091dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray return method_header; 810e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier} 811e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier 812b331febbab8e916680faba722cc84b66b84218a3Nicolas GeoffrayOatQuickMethodHeader* JitCodeCache::LookupOsrMethodHeader(ArtMethod* method) { 813b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray MutexLock mu(Thread::Current(), lock_); 814b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray auto it = osr_code_map_.find(method); 815b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray if (it == osr_code_map_.end()) { 816b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray return nullptr; 817b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray } 818b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray return OatQuickMethodHeader::FromCodePointer(it->second); 819b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray} 820b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray 82126705e2b1245b65989a0341b24c5dbf2658d4bb6Nicolas GeoffrayProfilingInfo* JitCodeCache::AddProfilingInfo(Thread* self, 82226705e2b1245b65989a0341b24c5dbf2658d4bb6Nicolas Geoffray ArtMethod* method, 82326705e2b1245b65989a0341b24c5dbf2658d4bb6Nicolas Geoffray const std::vector<uint32_t>& entries, 8241e7da9bd04bdd2664a4196f1d7e285c010f8881fNicolas Geoffray bool retry_allocation) 8251e7da9bd04bdd2664a4196f1d7e285c010f8881fNicolas Geoffray // No thread safety analysis as we are using TryLock/Unlock explicitly. 8261e7da9bd04bdd2664a4196f1d7e285c010f8881fNicolas Geoffray NO_THREAD_SAFETY_ANALYSIS { 8271e7da9bd04bdd2664a4196f1d7e285c010f8881fNicolas Geoffray ProfilingInfo* info = nullptr; 8281e7da9bd04bdd2664a4196f1d7e285c010f8881fNicolas Geoffray if (!retry_allocation) { 8291e7da9bd04bdd2664a4196f1d7e285c010f8881fNicolas Geoffray // If we are allocating for the interpreter, just try to lock, to avoid 8301e7da9bd04bdd2664a4196f1d7e285c010f8881fNicolas Geoffray // lock contention with the JIT. 8311e7da9bd04bdd2664a4196f1d7e285c010f8881fNicolas Geoffray if (lock_.ExclusiveTryLock(self)) { 8321e7da9bd04bdd2664a4196f1d7e285c010f8881fNicolas Geoffray info = AddProfilingInfoInternal(self, method, entries); 8331e7da9bd04bdd2664a4196f1d7e285c010f8881fNicolas Geoffray lock_.ExclusiveUnlock(self); 8341e7da9bd04bdd2664a4196f1d7e285c010f8881fNicolas Geoffray } 8351e7da9bd04bdd2664a4196f1d7e285c010f8881fNicolas Geoffray } else { 8361e7da9bd04bdd2664a4196f1d7e285c010f8881fNicolas Geoffray { 8371e7da9bd04bdd2664a4196f1d7e285c010f8881fNicolas Geoffray MutexLock mu(self, lock_); 8381e7da9bd04bdd2664a4196f1d7e285c010f8881fNicolas Geoffray info = AddProfilingInfoInternal(self, method, entries); 8391e7da9bd04bdd2664a4196f1d7e285c010f8881fNicolas Geoffray } 84026705e2b1245b65989a0341b24c5dbf2658d4bb6Nicolas Geoffray 8411e7da9bd04bdd2664a4196f1d7e285c010f8881fNicolas Geoffray if (info == nullptr) { 8421e7da9bd04bdd2664a4196f1d7e285c010f8881fNicolas Geoffray GarbageCollectCache(self); 8431e7da9bd04bdd2664a4196f1d7e285c010f8881fNicolas Geoffray MutexLock mu(self, lock_); 8441e7da9bd04bdd2664a4196f1d7e285c010f8881fNicolas Geoffray info = AddProfilingInfoInternal(self, method, entries); 8451e7da9bd04bdd2664a4196f1d7e285c010f8881fNicolas Geoffray } 84626705e2b1245b65989a0341b24c5dbf2658d4bb6Nicolas Geoffray } 84726705e2b1245b65989a0341b24c5dbf2658d4bb6Nicolas Geoffray return info; 84826705e2b1245b65989a0341b24c5dbf2658d4bb6Nicolas Geoffray} 84926705e2b1245b65989a0341b24c5dbf2658d4bb6Nicolas Geoffray 8501e7da9bd04bdd2664a4196f1d7e285c010f8881fNicolas GeoffrayProfilingInfo* JitCodeCache::AddProfilingInfoInternal(Thread* self ATTRIBUTE_UNUSED, 85126705e2b1245b65989a0341b24c5dbf2658d4bb6Nicolas Geoffray ArtMethod* method, 85226705e2b1245b65989a0341b24c5dbf2658d4bb6Nicolas Geoffray const std::vector<uint32_t>& entries) { 85326705e2b1245b65989a0341b24c5dbf2658d4bb6Nicolas Geoffray size_t profile_info_size = RoundUp( 85473be1e8f8609708f6624bb297c9628de44fd8b6fNicolas Geoffray sizeof(ProfilingInfo) + sizeof(InlineCache) * entries.size(), 85526705e2b1245b65989a0341b24c5dbf2658d4bb6Nicolas Geoffray sizeof(void*)); 85626705e2b1245b65989a0341b24c5dbf2658d4bb6Nicolas Geoffray 85726705e2b1245b65989a0341b24c5dbf2658d4bb6Nicolas Geoffray // Check whether some other thread has concurrently created it. 85826705e2b1245b65989a0341b24c5dbf2658d4bb6Nicolas Geoffray ProfilingInfo* info = method->GetProfilingInfo(sizeof(void*)); 85926705e2b1245b65989a0341b24c5dbf2658d4bb6Nicolas Geoffray if (info != nullptr) { 86026705e2b1245b65989a0341b24c5dbf2658d4bb6Nicolas Geoffray return info; 86126705e2b1245b65989a0341b24c5dbf2658d4bb6Nicolas Geoffray } 86226705e2b1245b65989a0341b24c5dbf2658d4bb6Nicolas Geoffray 86338ea9bd50debc63ceb77ec1e65036d8e2070ec7dNicolas Geoffray uint8_t* data = AllocateData(profile_info_size); 86426705e2b1245b65989a0341b24c5dbf2658d4bb6Nicolas Geoffray if (data == nullptr) { 86526705e2b1245b65989a0341b24c5dbf2658d4bb6Nicolas Geoffray return nullptr; 86626705e2b1245b65989a0341b24c5dbf2658d4bb6Nicolas Geoffray } 86726705e2b1245b65989a0341b24c5dbf2658d4bb6Nicolas Geoffray info = new (data) ProfilingInfo(method, entries); 86807f3564d73550495a937bc667d03721106315400Nicolas Geoffray 86907f3564d73550495a937bc667d03721106315400Nicolas Geoffray // Make sure other threads see the data in the profiling info object before the 87007f3564d73550495a937bc667d03721106315400Nicolas Geoffray // store in the ArtMethod's ProfilingInfo pointer. 87107f3564d73550495a937bc667d03721106315400Nicolas Geoffray QuasiAtomic::ThreadFenceRelease(); 87207f3564d73550495a937bc667d03721106315400Nicolas Geoffray 87326705e2b1245b65989a0341b24c5dbf2658d4bb6Nicolas Geoffray method->SetProfilingInfo(info); 87426705e2b1245b65989a0341b24c5dbf2658d4bb6Nicolas Geoffray profiling_infos_.push_back(info); 875933330a192d43d7c7304120999907857a89c2f96Nicolas Geoffray histogram_profiling_info_memory_use_.AddValue(profile_info_size); 87626705e2b1245b65989a0341b24c5dbf2658d4bb6Nicolas Geoffray return info; 87726705e2b1245b65989a0341b24c5dbf2658d4bb6Nicolas Geoffray} 87826705e2b1245b65989a0341b24c5dbf2658d4bb6Nicolas Geoffray 8790a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray// NO_THREAD_SAFETY_ANALYSIS as this is called from mspace code, at which point the lock 8800a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray// is already held. 8810a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffrayvoid* JitCodeCache::MoreCore(const void* mspace, intptr_t increment) NO_THREAD_SAFETY_ANALYSIS { 8820a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray if (code_mspace_ == mspace) { 8830a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray size_t result = code_end_; 8840a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray code_end_ += increment; 8850a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray return reinterpret_cast<void*>(result + code_map_->Begin()); 8860a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray } else { 8870a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray DCHECK_EQ(data_mspace_, mspace); 8880a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray size_t result = data_end_; 8890a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray data_end_ += increment; 8900a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray return reinterpret_cast<void*>(result + data_map_->Begin()); 8910a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray } 8920a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray} 8930a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray 894e2d066d0337b7c81d47e4806e6025b70d83fcd56Calin Juravlevoid JitCodeCache::GetProfiledMethods(const std::set<std::string>& dex_base_locations, 895e2d066d0337b7c81d47e4806e6025b70d83fcd56Calin Juravle std::vector<MethodReference>& methods) { 89632ce2adefb8a3d0eda59a29f5e87c1eb43eef796Mathieu Chartier ScopedTrace trace(__FUNCTION__); 89731f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle MutexLock mu(Thread::Current(), lock_); 898e2d066d0337b7c81d47e4806e6025b70d83fcd56Calin Juravle for (const ProfilingInfo* info : profiling_infos_) { 899e2d066d0337b7c81d47e4806e6025b70d83fcd56Calin Juravle ArtMethod* method = info->GetMethod(); 900e2d066d0337b7c81d47e4806e6025b70d83fcd56Calin Juravle const DexFile* dex_file = method->GetDexFile(); 901e2d066d0337b7c81d47e4806e6025b70d83fcd56Calin Juravle if (ContainsElement(dex_base_locations, dex_file->GetBaseLocation())) { 902e2d066d0337b7c81d47e4806e6025b70d83fcd56Calin Juravle methods.emplace_back(dex_file, method->GetDexMethodIndex()); 90331f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle } 90431f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle } 90531f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle} 90631f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle 9074d77b6a511659f26fdc711e23825ffa6e7feed7aCalin Juravleuint64_t JitCodeCache::GetLastUpdateTimeNs() const { 9084d77b6a511659f26fdc711e23825ffa6e7feed7aCalin Juravle return last_update_time_ns_.LoadAcquire(); 90931f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle} 91073be1e8f8609708f6624bb297c9628de44fd8b6fNicolas Geoffray 911f3f9cf6b65c4bcf9ea44253188d8d910b7cf7e64Nicolas Geoffraybool JitCodeCache::IsOsrCompiled(ArtMethod* method) { 912f3f9cf6b65c4bcf9ea44253188d8d910b7cf7e64Nicolas Geoffray MutexLock mu(Thread::Current(), lock_); 913f3f9cf6b65c4bcf9ea44253188d8d910b7cf7e64Nicolas Geoffray return osr_code_map_.find(method) != osr_code_map_.end(); 914f3f9cf6b65c4bcf9ea44253188d8d910b7cf7e64Nicolas Geoffray} 915f3f9cf6b65c4bcf9ea44253188d8d910b7cf7e64Nicolas Geoffray 916b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffraybool JitCodeCache::NotifyCompilationOf(ArtMethod* method, Thread* self, bool osr) { 917b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray if (!osr && ContainsPc(method->GetEntryPointFromQuickCompiledCode())) { 91873be1e8f8609708f6624bb297c9628de44fd8b6fNicolas Geoffray return false; 91973be1e8f8609708f6624bb297c9628de44fd8b6fNicolas Geoffray } 920a42363f79832a6e14f348514664dc6dc3edf9da2Nicolas Geoffray 921a42363f79832a6e14f348514664dc6dc3edf9da2Nicolas Geoffray MutexLock mu(self, lock_); 922b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray if (osr && (osr_code_map_.find(method) != osr_code_map_.end())) { 923b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray return false; 924b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray } 925bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray 926c26f1288aaf9141ac4b2150869f0c594d52dbf36Nicolas Geoffray ProfilingInfo* info = method->GetProfilingInfo(sizeof(void*)); 927bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray if (info == nullptr) { 928bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray VLOG(jit) << PrettyMethod(method) << " needs a ProfilingInfo to be compiled"; 929b9a639df2f21dd67b9f4379f31b7ccc5dd48ebd6Nicolas Geoffray // Because the counter is not atomic, there are some rare cases where we may not 930b9a639df2f21dd67b9f4379f31b7ccc5dd48ebd6Nicolas Geoffray // hit the threshold for creating the ProfilingInfo. Reset the counter now to 931b9a639df2f21dd67b9f4379f31b7ccc5dd48ebd6Nicolas Geoffray // "correct" this. 932b9a639df2f21dd67b9f4379f31b7ccc5dd48ebd6Nicolas Geoffray method->ClearCounter(); 933bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray return false; 934bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray } 935bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray 936454b3b6774fe07765273b917ccc97da2eba776acbuzbee if (info->IsMethodBeingCompiled(osr)) { 93773be1e8f8609708f6624bb297c9628de44fd8b6fNicolas Geoffray return false; 93873be1e8f8609708f6624bb297c9628de44fd8b6fNicolas Geoffray } 939bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray 940454b3b6774fe07765273b917ccc97da2eba776acbuzbee info->SetIsMethodBeingCompiled(true, osr); 94173be1e8f8609708f6624bb297c9628de44fd8b6fNicolas Geoffray return true; 94273be1e8f8609708f6624bb297c9628de44fd8b6fNicolas Geoffray} 94373be1e8f8609708f6624bb297c9628de44fd8b6fNicolas Geoffray 94407e3ca9a46801990d662c48d0fddedc63c4c053cNicolas GeoffrayProfilingInfo* JitCodeCache::NotifyCompilerUse(ArtMethod* method, Thread* self) { 945b6e20ae17d0881a66c22532e4152ce6779454a92Nicolas Geoffray MutexLock mu(self, lock_); 946b6e20ae17d0881a66c22532e4152ce6779454a92Nicolas Geoffray ProfilingInfo* info = method->GetProfilingInfo(sizeof(void*)); 947b6e20ae17d0881a66c22532e4152ce6779454a92Nicolas Geoffray if (info != nullptr) { 948b6e20ae17d0881a66c22532e4152ce6779454a92Nicolas Geoffray info->IncrementInlineUse(); 949b6e20ae17d0881a66c22532e4152ce6779454a92Nicolas Geoffray } 95007e3ca9a46801990d662c48d0fddedc63c4c053cNicolas Geoffray return info; 951b6e20ae17d0881a66c22532e4152ce6779454a92Nicolas Geoffray} 952b6e20ae17d0881a66c22532e4152ce6779454a92Nicolas Geoffray 95307e3ca9a46801990d662c48d0fddedc63c4c053cNicolas Geoffrayvoid JitCodeCache::DoneCompilerUse(ArtMethod* method, Thread* self) { 954b6e20ae17d0881a66c22532e4152ce6779454a92Nicolas Geoffray MutexLock mu(self, lock_); 955b6e20ae17d0881a66c22532e4152ce6779454a92Nicolas Geoffray ProfilingInfo* info = method->GetProfilingInfo(sizeof(void*)); 95607e3ca9a46801990d662c48d0fddedc63c4c053cNicolas Geoffray DCHECK(info != nullptr); 95707e3ca9a46801990d662c48d0fddedc63c4c053cNicolas Geoffray info->DecrementInlineUse(); 958b6e20ae17d0881a66c22532e4152ce6779454a92Nicolas Geoffray} 959b6e20ae17d0881a66c22532e4152ce6779454a92Nicolas Geoffray 960454b3b6774fe07765273b917ccc97da2eba776acbuzbeevoid JitCodeCache::DoneCompiling(ArtMethod* method, Thread* self ATTRIBUTE_UNUSED, bool osr) { 96173be1e8f8609708f6624bb297c9628de44fd8b6fNicolas Geoffray ProfilingInfo* info = method->GetProfilingInfo(sizeof(void*)); 962454b3b6774fe07765273b917ccc97da2eba776acbuzbee DCHECK(info->IsMethodBeingCompiled(osr)); 963454b3b6774fe07765273b917ccc97da2eba776acbuzbee info->SetIsMethodBeingCompiled(false, osr); 96473be1e8f8609708f6624bb297c9628de44fd8b6fNicolas Geoffray} 96573be1e8f8609708f6624bb297c9628de44fd8b6fNicolas Geoffray 966a25dce9b452ba17ef7cef768926c884177a3025eNicolas Geoffraysize_t JitCodeCache::GetMemorySizeOfCodePointer(const void* ptr) { 967a25dce9b452ba17ef7cef768926c884177a3025eNicolas Geoffray MutexLock mu(Thread::Current(), lock_); 968a25dce9b452ba17ef7cef768926c884177a3025eNicolas Geoffray return mspace_usable_size(reinterpret_cast<const void*>(FromCodeToAllocation(ptr))); 969a25dce9b452ba17ef7cef768926c884177a3025eNicolas Geoffray} 970a25dce9b452ba17ef7cef768926c884177a3025eNicolas Geoffray 971b88d59ef4fe611fe47e50a6a19785e03bbd5f93bNicolas Geoffrayvoid JitCodeCache::InvalidateCompiledCodeFor(ArtMethod* method, 972b88d59ef4fe611fe47e50a6a19785e03bbd5f93bNicolas Geoffray const OatQuickMethodHeader* header) { 97335122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray ProfilingInfo* profiling_info = method->GetProfilingInfo(sizeof(void*)); 97435122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray if ((profiling_info != nullptr) && 97535122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray (profiling_info->GetSavedEntryPoint() == header->GetEntryPoint())) { 97635122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray // Prevent future uses of the compiled code. 97735122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray profiling_info->SetSavedEntryPoint(nullptr); 97835122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray } 97935122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray 980b88d59ef4fe611fe47e50a6a19785e03bbd5f93bNicolas Geoffray if (method->GetEntryPointFromQuickCompiledCode() == header->GetEntryPoint()) { 981b88d59ef4fe611fe47e50a6a19785e03bbd5f93bNicolas Geoffray // The entrypoint is the one to invalidate, so we just update 982b88d59ef4fe611fe47e50a6a19785e03bbd5f93bNicolas Geoffray // it to the interpreter entry point and clear the counter to get the method 983b88d59ef4fe611fe47e50a6a19785e03bbd5f93bNicolas Geoffray // Jitted again. 984b88d59ef4fe611fe47e50a6a19785e03bbd5f93bNicolas Geoffray Runtime::Current()->GetInstrumentation()->UpdateMethodsCode( 985b88d59ef4fe611fe47e50a6a19785e03bbd5f93bNicolas Geoffray method, GetQuickToInterpreterBridge()); 986b88d59ef4fe611fe47e50a6a19785e03bbd5f93bNicolas Geoffray method->ClearCounter(); 987b88d59ef4fe611fe47e50a6a19785e03bbd5f93bNicolas Geoffray } else { 988b88d59ef4fe611fe47e50a6a19785e03bbd5f93bNicolas Geoffray MutexLock mu(Thread::Current(), lock_); 989b88d59ef4fe611fe47e50a6a19785e03bbd5f93bNicolas Geoffray auto it = osr_code_map_.find(method); 990b88d59ef4fe611fe47e50a6a19785e03bbd5f93bNicolas Geoffray if (it != osr_code_map_.end() && OatQuickMethodHeader::FromCodePointer(it->second) == header) { 991b88d59ef4fe611fe47e50a6a19785e03bbd5f93bNicolas Geoffray // Remove the OSR method, to avoid using it again. 992b88d59ef4fe611fe47e50a6a19785e03bbd5f93bNicolas Geoffray osr_code_map_.erase(it); 993b88d59ef4fe611fe47e50a6a19785e03bbd5f93bNicolas Geoffray } 994b88d59ef4fe611fe47e50a6a19785e03bbd5f93bNicolas Geoffray } 995bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray MutexLock mu(Thread::Current(), lock_); 996bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray number_of_deoptimizations_++; 997b88d59ef4fe611fe47e50a6a19785e03bbd5f93bNicolas Geoffray} 998b88d59ef4fe611fe47e50a6a19785e03bbd5f93bNicolas Geoffray 99938ea9bd50debc63ceb77ec1e65036d8e2070ec7dNicolas Geoffrayuint8_t* JitCodeCache::AllocateCode(size_t code_size) { 100038ea9bd50debc63ceb77ec1e65036d8e2070ec7dNicolas Geoffray size_t alignment = GetInstructionSetAlignment(kRuntimeISA); 100138ea9bd50debc63ceb77ec1e65036d8e2070ec7dNicolas Geoffray uint8_t* result = reinterpret_cast<uint8_t*>( 100238ea9bd50debc63ceb77ec1e65036d8e2070ec7dNicolas Geoffray mspace_memalign(code_mspace_, alignment, code_size)); 100338ea9bd50debc63ceb77ec1e65036d8e2070ec7dNicolas Geoffray size_t header_size = RoundUp(sizeof(OatQuickMethodHeader), alignment); 100438ea9bd50debc63ceb77ec1e65036d8e2070ec7dNicolas Geoffray // Ensure the header ends up at expected instruction alignment. 100538ea9bd50debc63ceb77ec1e65036d8e2070ec7dNicolas Geoffray DCHECK_ALIGNED_PARAM(reinterpret_cast<uintptr_t>(result + header_size), alignment); 100638ea9bd50debc63ceb77ec1e65036d8e2070ec7dNicolas Geoffray used_memory_for_code_ += mspace_usable_size(result); 100738ea9bd50debc63ceb77ec1e65036d8e2070ec7dNicolas Geoffray return result; 100838ea9bd50debc63ceb77ec1e65036d8e2070ec7dNicolas Geoffray} 100938ea9bd50debc63ceb77ec1e65036d8e2070ec7dNicolas Geoffray 101038ea9bd50debc63ceb77ec1e65036d8e2070ec7dNicolas Geoffrayvoid JitCodeCache::FreeCode(uint8_t* code) { 101138ea9bd50debc63ceb77ec1e65036d8e2070ec7dNicolas Geoffray used_memory_for_code_ -= mspace_usable_size(code); 101238ea9bd50debc63ceb77ec1e65036d8e2070ec7dNicolas Geoffray mspace_free(code_mspace_, code); 101338ea9bd50debc63ceb77ec1e65036d8e2070ec7dNicolas Geoffray} 101438ea9bd50debc63ceb77ec1e65036d8e2070ec7dNicolas Geoffray 101538ea9bd50debc63ceb77ec1e65036d8e2070ec7dNicolas Geoffrayuint8_t* JitCodeCache::AllocateData(size_t data_size) { 101638ea9bd50debc63ceb77ec1e65036d8e2070ec7dNicolas Geoffray void* result = mspace_malloc(data_mspace_, data_size); 101738ea9bd50debc63ceb77ec1e65036d8e2070ec7dNicolas Geoffray used_memory_for_data_ += mspace_usable_size(result); 101838ea9bd50debc63ceb77ec1e65036d8e2070ec7dNicolas Geoffray return reinterpret_cast<uint8_t*>(result); 101938ea9bd50debc63ceb77ec1e65036d8e2070ec7dNicolas Geoffray} 102038ea9bd50debc63ceb77ec1e65036d8e2070ec7dNicolas Geoffray 102138ea9bd50debc63ceb77ec1e65036d8e2070ec7dNicolas Geoffrayvoid JitCodeCache::FreeData(uint8_t* data) { 102238ea9bd50debc63ceb77ec1e65036d8e2070ec7dNicolas Geoffray used_memory_for_data_ -= mspace_usable_size(data); 102338ea9bd50debc63ceb77ec1e65036d8e2070ec7dNicolas Geoffray mspace_free(data_mspace_, data); 102438ea9bd50debc63ceb77ec1e65036d8e2070ec7dNicolas Geoffray} 102538ea9bd50debc63ceb77ec1e65036d8e2070ec7dNicolas Geoffray 1026bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffrayvoid JitCodeCache::Dump(std::ostream& os) { 1027bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray MutexLock mu(Thread::Current(), lock_); 1028bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray os << "Current JIT code cache size: " << PrettySize(used_memory_for_code_) << "\n" 1029bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray << "Current JIT data cache size: " << PrettySize(used_memory_for_data_) << "\n" 1030bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray << "Current JIT capacity: " << PrettySize(current_capacity_) << "\n" 1031bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray << "Current number of JIT code cache entries: " << method_code_map_.size() << "\n" 1032bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray << "Total number of JIT compilations: " << number_of_compilations_ << "\n" 1033bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray << "Total number of JIT compilations for on stack replacement: " 1034bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray << number_of_osr_compilations_ << "\n" 1035bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray << "Total number of deoptimizations: " << number_of_deoptimizations_ << "\n" 1036bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray << "Total number of JIT code cache collections: " << number_of_collections_ << std::endl; 1037933330a192d43d7c7304120999907857a89c2f96Nicolas Geoffray histogram_stack_map_memory_use_.PrintMemoryUse(os); 1038933330a192d43d7c7304120999907857a89c2f96Nicolas Geoffray histogram_code_memory_use_.PrintMemoryUse(os); 1039933330a192d43d7c7304120999907857a89c2f96Nicolas Geoffray histogram_profiling_info_memory_use_.PrintMemoryUse(os); 1040bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray} 1041bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray 1042e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier} // namespace jit 1043e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier} // namespace art 1044