1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker * Copyright 2014 The Android Open Source Project
3*795d594fSAndroid Build Coastguard Worker *
4*795d594fSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*795d594fSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*795d594fSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*795d594fSAndroid Build Coastguard Worker *
8*795d594fSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*795d594fSAndroid Build Coastguard Worker *
10*795d594fSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*795d594fSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*795d594fSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*795d594fSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*795d594fSAndroid Build Coastguard Worker * limitations under the License.
15*795d594fSAndroid Build Coastguard Worker */
16*795d594fSAndroid Build Coastguard Worker
17*795d594fSAndroid Build Coastguard Worker #include "jit_code_cache.h"
18*795d594fSAndroid Build Coastguard Worker
19*795d594fSAndroid Build Coastguard Worker #include <sstream>
20*795d594fSAndroid Build Coastguard Worker
21*795d594fSAndroid Build Coastguard Worker #include <android-base/logging.h>
22*795d594fSAndroid Build Coastguard Worker
23*795d594fSAndroid Build Coastguard Worker #include "arch/context.h"
24*795d594fSAndroid Build Coastguard Worker #include "art_method-inl.h"
25*795d594fSAndroid Build Coastguard Worker #include "base/histogram-inl.h"
26*795d594fSAndroid Build Coastguard Worker #include "base/logging.h" // For VLOG.
27*795d594fSAndroid Build Coastguard Worker #include "base/membarrier.h"
28*795d594fSAndroid Build Coastguard Worker #include "base/memfd.h"
29*795d594fSAndroid Build Coastguard Worker #include "base/mem_map.h"
30*795d594fSAndroid Build Coastguard Worker #include "base/pointer_size.h"
31*795d594fSAndroid Build Coastguard Worker #include "base/quasi_atomic.h"
32*795d594fSAndroid Build Coastguard Worker #include "base/stl_util.h"
33*795d594fSAndroid Build Coastguard Worker #include "base/systrace.h"
34*795d594fSAndroid Build Coastguard Worker #include "base/time_utils.h"
35*795d594fSAndroid Build Coastguard Worker #include "base/utils.h"
36*795d594fSAndroid Build Coastguard Worker #include "cha.h"
37*795d594fSAndroid Build Coastguard Worker #include "debugger_interface.h"
38*795d594fSAndroid Build Coastguard Worker #include "dex/dex_file_loader.h"
39*795d594fSAndroid Build Coastguard Worker #include "dex/method_reference.h"
40*795d594fSAndroid Build Coastguard Worker #include "entrypoints/entrypoint_utils-inl.h"
41*795d594fSAndroid Build Coastguard Worker #include "entrypoints/runtime_asm_entrypoints.h"
42*795d594fSAndroid Build Coastguard Worker #include "gc/accounting/bitmap-inl.h"
43*795d594fSAndroid Build Coastguard Worker #include "gc/allocator/art-dlmalloc.h"
44*795d594fSAndroid Build Coastguard Worker #include "gc/scoped_gc_critical_section.h"
45*795d594fSAndroid Build Coastguard Worker #include "handle.h"
46*795d594fSAndroid Build Coastguard Worker #include "handle_scope-inl.h"
47*795d594fSAndroid Build Coastguard Worker #include "instrumentation.h"
48*795d594fSAndroid Build Coastguard Worker #include "intern_table.h"
49*795d594fSAndroid Build Coastguard Worker #include "jit/jit.h"
50*795d594fSAndroid Build Coastguard Worker #include "jit/profiling_info.h"
51*795d594fSAndroid Build Coastguard Worker #include "jit/jit_scoped_code_cache_write.h"
52*795d594fSAndroid Build Coastguard Worker #include "linear_alloc.h"
53*795d594fSAndroid Build Coastguard Worker #include "mirror/method_type.h"
54*795d594fSAndroid Build Coastguard Worker #include "oat/oat_file-inl.h"
55*795d594fSAndroid Build Coastguard Worker #include "oat/oat_quick_method_header.h"
56*795d594fSAndroid Build Coastguard Worker #include "object_callbacks.h"
57*795d594fSAndroid Build Coastguard Worker #include "profile/profile_compilation_info.h"
58*795d594fSAndroid Build Coastguard Worker #include "scoped_thread_state_change-inl.h"
59*795d594fSAndroid Build Coastguard Worker #include "stack.h"
60*795d594fSAndroid Build Coastguard Worker #include "thread-current-inl.h"
61*795d594fSAndroid Build Coastguard Worker #include "thread-inl.h"
62*795d594fSAndroid Build Coastguard Worker #include "thread_list.h"
63*795d594fSAndroid Build Coastguard Worker #include "well_known_classes-inl.h"
64*795d594fSAndroid Build Coastguard Worker
65*795d594fSAndroid Build Coastguard Worker namespace art HIDDEN {
66*795d594fSAndroid Build Coastguard Worker namespace jit {
67*795d594fSAndroid Build Coastguard Worker
68*795d594fSAndroid Build Coastguard Worker static constexpr size_t kCodeSizeLogThreshold = 50 * KB;
69*795d594fSAndroid Build Coastguard Worker static constexpr size_t kStackMapSizeLogThreshold = 50 * KB;
70*795d594fSAndroid Build Coastguard Worker
71*795d594fSAndroid Build Coastguard Worker class JitCodeCache::JniStubKey {
72*795d594fSAndroid Build Coastguard Worker public:
REQUIRES_SHARED(Locks::mutator_lock_)73*795d594fSAndroid Build Coastguard Worker explicit JniStubKey(ArtMethod* method) REQUIRES_SHARED(Locks::mutator_lock_)
74*795d594fSAndroid Build Coastguard Worker : shorty_(method->GetShorty()),
75*795d594fSAndroid Build Coastguard Worker is_static_(method->IsStatic()),
76*795d594fSAndroid Build Coastguard Worker is_fast_native_(method->IsFastNative()),
77*795d594fSAndroid Build Coastguard Worker is_critical_native_(method->IsCriticalNative()),
78*795d594fSAndroid Build Coastguard Worker is_synchronized_(method->IsSynchronized()) {
79*795d594fSAndroid Build Coastguard Worker DCHECK(!(is_fast_native_ && is_critical_native_));
80*795d594fSAndroid Build Coastguard Worker }
81*795d594fSAndroid Build Coastguard Worker
operator <(const JniStubKey & rhs) const82*795d594fSAndroid Build Coastguard Worker bool operator<(const JniStubKey& rhs) const {
83*795d594fSAndroid Build Coastguard Worker if (is_static_ != rhs.is_static_) {
84*795d594fSAndroid Build Coastguard Worker return rhs.is_static_;
85*795d594fSAndroid Build Coastguard Worker }
86*795d594fSAndroid Build Coastguard Worker if (is_synchronized_ != rhs.is_synchronized_) {
87*795d594fSAndroid Build Coastguard Worker return rhs.is_synchronized_;
88*795d594fSAndroid Build Coastguard Worker }
89*795d594fSAndroid Build Coastguard Worker if (is_fast_native_ != rhs.is_fast_native_) {
90*795d594fSAndroid Build Coastguard Worker return rhs.is_fast_native_;
91*795d594fSAndroid Build Coastguard Worker }
92*795d594fSAndroid Build Coastguard Worker if (is_critical_native_ != rhs.is_critical_native_) {
93*795d594fSAndroid Build Coastguard Worker return rhs.is_critical_native_;
94*795d594fSAndroid Build Coastguard Worker }
95*795d594fSAndroid Build Coastguard Worker return strcmp(shorty_, rhs.shorty_) < 0;
96*795d594fSAndroid Build Coastguard Worker }
97*795d594fSAndroid Build Coastguard Worker
98*795d594fSAndroid Build Coastguard Worker // Update the shorty to point to another method's shorty. Call this function when removing
99*795d594fSAndroid Build Coastguard Worker // the method that references the old shorty from JniCodeData and not removing the entire
100*795d594fSAndroid Build Coastguard Worker // JniCodeData; the old shorty may become a dangling pointer when that method is unloaded.
UpdateShorty(ArtMethod * method) const101*795d594fSAndroid Build Coastguard Worker void UpdateShorty(ArtMethod* method) const REQUIRES_SHARED(Locks::mutator_lock_) {
102*795d594fSAndroid Build Coastguard Worker const char* shorty = method->GetShorty();
103*795d594fSAndroid Build Coastguard Worker DCHECK_STREQ(shorty_, shorty);
104*795d594fSAndroid Build Coastguard Worker shorty_ = shorty;
105*795d594fSAndroid Build Coastguard Worker }
106*795d594fSAndroid Build Coastguard Worker
107*795d594fSAndroid Build Coastguard Worker private:
108*795d594fSAndroid Build Coastguard Worker // The shorty points to a DexFile data and may need to change
109*795d594fSAndroid Build Coastguard Worker // to point to the same shorty in a different DexFile.
110*795d594fSAndroid Build Coastguard Worker mutable const char* shorty_;
111*795d594fSAndroid Build Coastguard Worker
112*795d594fSAndroid Build Coastguard Worker const bool is_static_;
113*795d594fSAndroid Build Coastguard Worker const bool is_fast_native_;
114*795d594fSAndroid Build Coastguard Worker const bool is_critical_native_;
115*795d594fSAndroid Build Coastguard Worker const bool is_synchronized_;
116*795d594fSAndroid Build Coastguard Worker };
117*795d594fSAndroid Build Coastguard Worker
118*795d594fSAndroid Build Coastguard Worker class JitCodeCache::JniStubData {
119*795d594fSAndroid Build Coastguard Worker public:
JniStubData()120*795d594fSAndroid Build Coastguard Worker JniStubData() : code_(nullptr), methods_() {}
121*795d594fSAndroid Build Coastguard Worker
SetCode(const void * code)122*795d594fSAndroid Build Coastguard Worker void SetCode(const void* code) {
123*795d594fSAndroid Build Coastguard Worker DCHECK(code != nullptr);
124*795d594fSAndroid Build Coastguard Worker code_ = code;
125*795d594fSAndroid Build Coastguard Worker }
126*795d594fSAndroid Build Coastguard Worker
UpdateEntryPoints(const void * entrypoint)127*795d594fSAndroid Build Coastguard Worker void UpdateEntryPoints(const void* entrypoint) REQUIRES_SHARED(Locks::mutator_lock_) {
128*795d594fSAndroid Build Coastguard Worker DCHECK(IsCompiled());
129*795d594fSAndroid Build Coastguard Worker DCHECK(entrypoint == OatQuickMethodHeader::FromCodePointer(GetCode())->GetEntryPoint());
130*795d594fSAndroid Build Coastguard Worker instrumentation::Instrumentation* instrum = Runtime::Current()->GetInstrumentation();
131*795d594fSAndroid Build Coastguard Worker for (ArtMethod* m : GetMethods()) {
132*795d594fSAndroid Build Coastguard Worker // Because `m` might be in the process of being deleted,
133*795d594fSAndroid Build Coastguard Worker // - use the `ArtMethod::StillNeedsClinitCheckMayBeDead()` to check if
134*795d594fSAndroid Build Coastguard Worker // we can update the entrypoint, and
135*795d594fSAndroid Build Coastguard Worker // - call `Instrumentation::UpdateNativeMethodsCodeToJitCode` instead of the
136*795d594fSAndroid Build Coastguard Worker // more generic function `Instrumentation::UpdateMethodsCode()`.
137*795d594fSAndroid Build Coastguard Worker // The `ArtMethod::StillNeedsClinitCheckMayBeDead()` checks the class status
138*795d594fSAndroid Build Coastguard Worker // in the to-space object if any even if the method's declaring class points to
139*795d594fSAndroid Build Coastguard Worker // the from-space class object. This way we do not miss updating an entrypoint
140*795d594fSAndroid Build Coastguard Worker // even under uncommon circumstances, when during a GC the class becomes visibly
141*795d594fSAndroid Build Coastguard Worker // initialized, the method becomes hot, we compile the thunk and want to update
142*795d594fSAndroid Build Coastguard Worker // the entrypoint while the method's declaring class field still points to the
143*795d594fSAndroid Build Coastguard Worker // from-space class object with the old status.
144*795d594fSAndroid Build Coastguard Worker if (!m->StillNeedsClinitCheckMayBeDead()) {
145*795d594fSAndroid Build Coastguard Worker instrum->UpdateNativeMethodsCodeToJitCode(m, entrypoint);
146*795d594fSAndroid Build Coastguard Worker }
147*795d594fSAndroid Build Coastguard Worker }
148*795d594fSAndroid Build Coastguard Worker }
149*795d594fSAndroid Build Coastguard Worker
GetCode() const150*795d594fSAndroid Build Coastguard Worker const void* GetCode() const {
151*795d594fSAndroid Build Coastguard Worker return code_;
152*795d594fSAndroid Build Coastguard Worker }
153*795d594fSAndroid Build Coastguard Worker
IsCompiled() const154*795d594fSAndroid Build Coastguard Worker bool IsCompiled() const {
155*795d594fSAndroid Build Coastguard Worker return GetCode() != nullptr;
156*795d594fSAndroid Build Coastguard Worker }
157*795d594fSAndroid Build Coastguard Worker
AddMethod(ArtMethod * method)158*795d594fSAndroid Build Coastguard Worker void AddMethod(ArtMethod* method) {
159*795d594fSAndroid Build Coastguard Worker if (!ContainsElement(methods_, method)) {
160*795d594fSAndroid Build Coastguard Worker methods_.push_back(method);
161*795d594fSAndroid Build Coastguard Worker }
162*795d594fSAndroid Build Coastguard Worker }
163*795d594fSAndroid Build Coastguard Worker
GetMethods() const164*795d594fSAndroid Build Coastguard Worker const std::vector<ArtMethod*>& GetMethods() const {
165*795d594fSAndroid Build Coastguard Worker return methods_;
166*795d594fSAndroid Build Coastguard Worker }
167*795d594fSAndroid Build Coastguard Worker
RemoveMethodsIn(const LinearAlloc & alloc)168*795d594fSAndroid Build Coastguard Worker void RemoveMethodsIn(const LinearAlloc& alloc) REQUIRES_SHARED(Locks::mutator_lock_) {
169*795d594fSAndroid Build Coastguard Worker auto kept_end = std::partition(
170*795d594fSAndroid Build Coastguard Worker methods_.begin(),
171*795d594fSAndroid Build Coastguard Worker methods_.end(),
172*795d594fSAndroid Build Coastguard Worker [&alloc](ArtMethod* method) { return !alloc.ContainsUnsafe(method); });
173*795d594fSAndroid Build Coastguard Worker for (auto it = kept_end; it != methods_.end(); it++) {
174*795d594fSAndroid Build Coastguard Worker VLOG(jit) << "JIT removed (JNI) " << (*it)->PrettyMethod() << ": " << code_;
175*795d594fSAndroid Build Coastguard Worker }
176*795d594fSAndroid Build Coastguard Worker methods_.erase(kept_end, methods_.end());
177*795d594fSAndroid Build Coastguard Worker }
178*795d594fSAndroid Build Coastguard Worker
RemoveMethod(ArtMethod * method)179*795d594fSAndroid Build Coastguard Worker bool RemoveMethod(ArtMethod* method) REQUIRES_SHARED(Locks::mutator_lock_) {
180*795d594fSAndroid Build Coastguard Worker auto it = std::find(methods_.begin(), methods_.end(), method);
181*795d594fSAndroid Build Coastguard Worker if (it != methods_.end()) {
182*795d594fSAndroid Build Coastguard Worker VLOG(jit) << "JIT removed (JNI) " << (*it)->PrettyMethod() << ": " << code_;
183*795d594fSAndroid Build Coastguard Worker methods_.erase(it);
184*795d594fSAndroid Build Coastguard Worker return true;
185*795d594fSAndroid Build Coastguard Worker } else {
186*795d594fSAndroid Build Coastguard Worker return false;
187*795d594fSAndroid Build Coastguard Worker }
188*795d594fSAndroid Build Coastguard Worker }
189*795d594fSAndroid Build Coastguard Worker
MoveObsoleteMethod(ArtMethod * old_method,ArtMethod * new_method)190*795d594fSAndroid Build Coastguard Worker void MoveObsoleteMethod(ArtMethod* old_method, ArtMethod* new_method) {
191*795d594fSAndroid Build Coastguard Worker std::replace(methods_.begin(), methods_.end(), old_method, new_method);
192*795d594fSAndroid Build Coastguard Worker }
193*795d594fSAndroid Build Coastguard Worker
194*795d594fSAndroid Build Coastguard Worker private:
195*795d594fSAndroid Build Coastguard Worker const void* code_;
196*795d594fSAndroid Build Coastguard Worker std::vector<ArtMethod*> methods_;
197*795d594fSAndroid Build Coastguard Worker };
198*795d594fSAndroid Build Coastguard Worker
Create(bool used_only_for_profile_data,bool rwx_memory_allowed,bool is_zygote,std::string * error_msg)199*795d594fSAndroid Build Coastguard Worker JitCodeCache* JitCodeCache::Create(bool used_only_for_profile_data,
200*795d594fSAndroid Build Coastguard Worker bool rwx_memory_allowed,
201*795d594fSAndroid Build Coastguard Worker bool is_zygote,
202*795d594fSAndroid Build Coastguard Worker std::string* error_msg) {
203*795d594fSAndroid Build Coastguard Worker // Register for membarrier expedited sync core if JIT will be generating code.
204*795d594fSAndroid Build Coastguard Worker if (!used_only_for_profile_data) {
205*795d594fSAndroid Build Coastguard Worker if (art::membarrier(art::MembarrierCommand::kRegisterPrivateExpeditedSyncCore) != 0) {
206*795d594fSAndroid Build Coastguard Worker // MEMBARRIER_CMD_PRIVATE_EXPEDITED_SYNC_CORE ensures that CPU instruction pipelines are
207*795d594fSAndroid Build Coastguard Worker // flushed and it's used when adding code to the JIT. The memory used by the new code may
208*795d594fSAndroid Build Coastguard Worker // have just been released and, in theory, the old code could still be in a pipeline.
209*795d594fSAndroid Build Coastguard Worker VLOG(jit) << "Kernel does not support membarrier sync-core";
210*795d594fSAndroid Build Coastguard Worker }
211*795d594fSAndroid Build Coastguard Worker }
212*795d594fSAndroid Build Coastguard Worker
213*795d594fSAndroid Build Coastguard Worker Runtime* runtime = Runtime::Current();
214*795d594fSAndroid Build Coastguard Worker size_t initial_capacity = runtime->GetJITOptions()->GetCodeCacheInitialCapacity();
215*795d594fSAndroid Build Coastguard Worker // Check whether the provided max capacity in options is below 1GB.
216*795d594fSAndroid Build Coastguard Worker size_t max_capacity = runtime->GetJITOptions()->GetCodeCacheMaxCapacity();
217*795d594fSAndroid Build Coastguard Worker // We need to have 32 bit offsets from method headers in code cache which point to things
218*795d594fSAndroid Build Coastguard Worker // in the data cache. If the maps are more than 4G apart, having multiple maps wouldn't work.
219*795d594fSAndroid Build Coastguard Worker // Ensure we're below 1 GB to be safe.
220*795d594fSAndroid Build Coastguard Worker if (max_capacity > 1 * GB) {
221*795d594fSAndroid Build Coastguard Worker std::ostringstream oss;
222*795d594fSAndroid Build Coastguard Worker oss << "Maxium code cache capacity is limited to 1 GB, "
223*795d594fSAndroid Build Coastguard Worker << PrettySize(max_capacity) << " is too big";
224*795d594fSAndroid Build Coastguard Worker *error_msg = oss.str();
225*795d594fSAndroid Build Coastguard Worker return nullptr;
226*795d594fSAndroid Build Coastguard Worker }
227*795d594fSAndroid Build Coastguard Worker
228*795d594fSAndroid Build Coastguard Worker MutexLock mu(Thread::Current(), *Locks::jit_lock_);
229*795d594fSAndroid Build Coastguard Worker JitMemoryRegion region;
230*795d594fSAndroid Build Coastguard Worker if (!region.Initialize(initial_capacity,
231*795d594fSAndroid Build Coastguard Worker max_capacity,
232*795d594fSAndroid Build Coastguard Worker rwx_memory_allowed,
233*795d594fSAndroid Build Coastguard Worker is_zygote,
234*795d594fSAndroid Build Coastguard Worker error_msg)) {
235*795d594fSAndroid Build Coastguard Worker return nullptr;
236*795d594fSAndroid Build Coastguard Worker }
237*795d594fSAndroid Build Coastguard Worker
238*795d594fSAndroid Build Coastguard Worker if (region.HasCodeMapping()) {
239*795d594fSAndroid Build Coastguard Worker const MemMap* exec_pages = region.GetExecPages();
240*795d594fSAndroid Build Coastguard Worker runtime->AddGeneratedCodeRange(exec_pages->Begin(), exec_pages->Size());
241*795d594fSAndroid Build Coastguard Worker }
242*795d594fSAndroid Build Coastguard Worker
243*795d594fSAndroid Build Coastguard Worker std::unique_ptr<JitCodeCache> jit_code_cache(new JitCodeCache());
244*795d594fSAndroid Build Coastguard Worker if (is_zygote) {
245*795d594fSAndroid Build Coastguard Worker // Zygote should never collect code to share the memory with the children.
246*795d594fSAndroid Build Coastguard Worker jit_code_cache->garbage_collect_code_ = false;
247*795d594fSAndroid Build Coastguard Worker jit_code_cache->shared_region_ = std::move(region);
248*795d594fSAndroid Build Coastguard Worker } else {
249*795d594fSAndroid Build Coastguard Worker jit_code_cache->private_region_ = std::move(region);
250*795d594fSAndroid Build Coastguard Worker }
251*795d594fSAndroid Build Coastguard Worker
252*795d594fSAndroid Build Coastguard Worker VLOG(jit) << "Created jit code cache: initial capacity="
253*795d594fSAndroid Build Coastguard Worker << PrettySize(initial_capacity)
254*795d594fSAndroid Build Coastguard Worker << ", maximum capacity="
255*795d594fSAndroid Build Coastguard Worker << PrettySize(max_capacity);
256*795d594fSAndroid Build Coastguard Worker
257*795d594fSAndroid Build Coastguard Worker return jit_code_cache.release();
258*795d594fSAndroid Build Coastguard Worker }
259*795d594fSAndroid Build Coastguard Worker
JitCodeCache()260*795d594fSAndroid Build Coastguard Worker JitCodeCache::JitCodeCache()
261*795d594fSAndroid Build Coastguard Worker : is_weak_access_enabled_(true),
262*795d594fSAndroid Build Coastguard Worker inline_cache_cond_("Jit inline cache condition variable", *Locks::jit_lock_),
263*795d594fSAndroid Build Coastguard Worker reserved_capacity_(GetInitialCapacity() * kReservedCapacityMultiplier),
264*795d594fSAndroid Build Coastguard Worker zygote_map_(&shared_region_),
265*795d594fSAndroid Build Coastguard Worker lock_cond_("Jit code cache condition variable", *Locks::jit_lock_),
266*795d594fSAndroid Build Coastguard Worker collection_in_progress_(false),
267*795d594fSAndroid Build Coastguard Worker garbage_collect_code_(true),
268*795d594fSAndroid Build Coastguard Worker number_of_baseline_compilations_(0),
269*795d594fSAndroid Build Coastguard Worker number_of_optimized_compilations_(0),
270*795d594fSAndroid Build Coastguard Worker number_of_osr_compilations_(0),
271*795d594fSAndroid Build Coastguard Worker number_of_collections_(0),
272*795d594fSAndroid Build Coastguard Worker histogram_stack_map_memory_use_("Memory used for stack maps", 16),
273*795d594fSAndroid Build Coastguard Worker histogram_code_memory_use_("Memory used for compiled code", 16),
274*795d594fSAndroid Build Coastguard Worker histogram_profiling_info_memory_use_("Memory used for profiling info", 16) {
275*795d594fSAndroid Build Coastguard Worker }
276*795d594fSAndroid Build Coastguard Worker
~JitCodeCache()277*795d594fSAndroid Build Coastguard Worker JitCodeCache::~JitCodeCache() {
278*795d594fSAndroid Build Coastguard Worker if (private_region_.HasCodeMapping()) {
279*795d594fSAndroid Build Coastguard Worker const MemMap* exec_pages = private_region_.GetExecPages();
280*795d594fSAndroid Build Coastguard Worker Runtime::Current()->RemoveGeneratedCodeRange(exec_pages->Begin(), exec_pages->Size());
281*795d594fSAndroid Build Coastguard Worker }
282*795d594fSAndroid Build Coastguard Worker if (shared_region_.HasCodeMapping()) {
283*795d594fSAndroid Build Coastguard Worker const MemMap* exec_pages = shared_region_.GetExecPages();
284*795d594fSAndroid Build Coastguard Worker Runtime::Current()->RemoveGeneratedCodeRange(exec_pages->Begin(), exec_pages->Size());
285*795d594fSAndroid Build Coastguard Worker }
286*795d594fSAndroid Build Coastguard Worker }
287*795d594fSAndroid Build Coastguard Worker
PrivateRegionContainsPc(const void * ptr) const288*795d594fSAndroid Build Coastguard Worker bool JitCodeCache::PrivateRegionContainsPc(const void* ptr) const {
289*795d594fSAndroid Build Coastguard Worker return private_region_.IsInExecSpace(ptr);
290*795d594fSAndroid Build Coastguard Worker }
291*795d594fSAndroid Build Coastguard Worker
ContainsPc(const void * ptr) const292*795d594fSAndroid Build Coastguard Worker bool JitCodeCache::ContainsPc(const void* ptr) const {
293*795d594fSAndroid Build Coastguard Worker return PrivateRegionContainsPc(ptr) || shared_region_.IsInExecSpace(ptr);
294*795d594fSAndroid Build Coastguard Worker }
295*795d594fSAndroid Build Coastguard Worker
ContainsMethod(ArtMethod * method)296*795d594fSAndroid Build Coastguard Worker bool JitCodeCache::ContainsMethod(ArtMethod* method) {
297*795d594fSAndroid Build Coastguard Worker Thread* self = Thread::Current();
298*795d594fSAndroid Build Coastguard Worker ScopedDebugDisallowReadBarriers sddrb(self);
299*795d594fSAndroid Build Coastguard Worker ReaderMutexLock mu(self, *Locks::jit_mutator_lock_);
300*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(method->IsNative())) {
301*795d594fSAndroid Build Coastguard Worker auto it = jni_stubs_map_.find(JniStubKey(method));
302*795d594fSAndroid Build Coastguard Worker if (it != jni_stubs_map_.end() &&
303*795d594fSAndroid Build Coastguard Worker it->second.IsCompiled() &&
304*795d594fSAndroid Build Coastguard Worker ContainsElement(it->second.GetMethods(), method)) {
305*795d594fSAndroid Build Coastguard Worker return true;
306*795d594fSAndroid Build Coastguard Worker }
307*795d594fSAndroid Build Coastguard Worker } else {
308*795d594fSAndroid Build Coastguard Worker for (const auto& it : method_code_map_) {
309*795d594fSAndroid Build Coastguard Worker if (it.second == method) {
310*795d594fSAndroid Build Coastguard Worker return true;
311*795d594fSAndroid Build Coastguard Worker }
312*795d594fSAndroid Build Coastguard Worker }
313*795d594fSAndroid Build Coastguard Worker if (zygote_map_.ContainsMethod(method)) {
314*795d594fSAndroid Build Coastguard Worker return true;
315*795d594fSAndroid Build Coastguard Worker }
316*795d594fSAndroid Build Coastguard Worker }
317*795d594fSAndroid Build Coastguard Worker return false;
318*795d594fSAndroid Build Coastguard Worker }
319*795d594fSAndroid Build Coastguard Worker
GetJniStubCode(ArtMethod * method)320*795d594fSAndroid Build Coastguard Worker const void* JitCodeCache::GetJniStubCode(ArtMethod* method) {
321*795d594fSAndroid Build Coastguard Worker DCHECK(method->IsNative());
322*795d594fSAndroid Build Coastguard Worker Thread* self = Thread::Current();
323*795d594fSAndroid Build Coastguard Worker ScopedDebugDisallowReadBarriers sddrb(self);
324*795d594fSAndroid Build Coastguard Worker ReaderMutexLock mu(self, *Locks::jit_mutator_lock_);
325*795d594fSAndroid Build Coastguard Worker auto it = jni_stubs_map_.find(JniStubKey(method));
326*795d594fSAndroid Build Coastguard Worker if (it != jni_stubs_map_.end()) {
327*795d594fSAndroid Build Coastguard Worker JniStubData& data = it->second;
328*795d594fSAndroid Build Coastguard Worker if (data.IsCompiled() && ContainsElement(data.GetMethods(), method)) {
329*795d594fSAndroid Build Coastguard Worker return data.GetCode();
330*795d594fSAndroid Build Coastguard Worker }
331*795d594fSAndroid Build Coastguard Worker }
332*795d594fSAndroid Build Coastguard Worker return nullptr;
333*795d594fSAndroid Build Coastguard Worker }
334*795d594fSAndroid Build Coastguard Worker
GetSavedEntryPointOfPreCompiledMethod(ArtMethod * method)335*795d594fSAndroid Build Coastguard Worker const void* JitCodeCache::GetSavedEntryPointOfPreCompiledMethod(ArtMethod* method) {
336*795d594fSAndroid Build Coastguard Worker Thread* self = Thread::Current();
337*795d594fSAndroid Build Coastguard Worker ScopedDebugDisallowReadBarriers sddrb(self);
338*795d594fSAndroid Build Coastguard Worker if (method->IsPreCompiled()) {
339*795d594fSAndroid Build Coastguard Worker const void* code_ptr = nullptr;
340*795d594fSAndroid Build Coastguard Worker if (method->GetDeclaringClass<kWithoutReadBarrier>()->IsBootStrapClassLoaded()) {
341*795d594fSAndroid Build Coastguard Worker code_ptr = zygote_map_.GetCodeFor(method);
342*795d594fSAndroid Build Coastguard Worker } else {
343*795d594fSAndroid Build Coastguard Worker WriterMutexLock mu(self, *Locks::jit_mutator_lock_);
344*795d594fSAndroid Build Coastguard Worker auto it = saved_compiled_methods_map_.find(method);
345*795d594fSAndroid Build Coastguard Worker if (it != saved_compiled_methods_map_.end()) {
346*795d594fSAndroid Build Coastguard Worker code_ptr = it->second;
347*795d594fSAndroid Build Coastguard Worker // Now that we're using the saved entrypoint, remove it from the saved map.
348*795d594fSAndroid Build Coastguard Worker saved_compiled_methods_map_.erase(it);
349*795d594fSAndroid Build Coastguard Worker }
350*795d594fSAndroid Build Coastguard Worker }
351*795d594fSAndroid Build Coastguard Worker if (code_ptr != nullptr) {
352*795d594fSAndroid Build Coastguard Worker OatQuickMethodHeader* method_header = OatQuickMethodHeader::FromCodePointer(code_ptr);
353*795d594fSAndroid Build Coastguard Worker return method_header->GetEntryPoint();
354*795d594fSAndroid Build Coastguard Worker }
355*795d594fSAndroid Build Coastguard Worker }
356*795d594fSAndroid Build Coastguard Worker return nullptr;
357*795d594fSAndroid Build Coastguard Worker }
358*795d594fSAndroid Build Coastguard Worker
WaitForPotentialCollectionToComplete(Thread * self)359*795d594fSAndroid Build Coastguard Worker bool JitCodeCache::WaitForPotentialCollectionToComplete(Thread* self) {
360*795d594fSAndroid Build Coastguard Worker bool in_collection = false;
361*795d594fSAndroid Build Coastguard Worker while (collection_in_progress_) {
362*795d594fSAndroid Build Coastguard Worker in_collection = true;
363*795d594fSAndroid Build Coastguard Worker lock_cond_.Wait(self);
364*795d594fSAndroid Build Coastguard Worker }
365*795d594fSAndroid Build Coastguard Worker return in_collection;
366*795d594fSAndroid Build Coastguard Worker }
367*795d594fSAndroid Build Coastguard Worker
FromCodeToAllocation(const void * code)368*795d594fSAndroid Build Coastguard Worker static uintptr_t FromCodeToAllocation(const void* code) {
369*795d594fSAndroid Build Coastguard Worker size_t alignment = GetInstructionSetCodeAlignment(kRuntimeQuickCodeISA);
370*795d594fSAndroid Build Coastguard Worker return reinterpret_cast<uintptr_t>(code) - RoundUp(sizeof(OatQuickMethodHeader), alignment);
371*795d594fSAndroid Build Coastguard Worker }
372*795d594fSAndroid Build Coastguard Worker
FromAllocationToCode(const uint8_t * alloc)373*795d594fSAndroid Build Coastguard Worker static const void* FromAllocationToCode(const uint8_t* alloc) {
374*795d594fSAndroid Build Coastguard Worker size_t alignment = GetInstructionSetCodeAlignment(kRuntimeQuickCodeISA);
375*795d594fSAndroid Build Coastguard Worker return reinterpret_cast<const void*>(alloc + RoundUp(sizeof(OatQuickMethodHeader), alignment));
376*795d594fSAndroid Build Coastguard Worker }
377*795d594fSAndroid Build Coastguard Worker
GetNumberOfRoots(const uint8_t * stack_map)378*795d594fSAndroid Build Coastguard Worker static uint32_t GetNumberOfRoots(const uint8_t* stack_map) {
379*795d594fSAndroid Build Coastguard Worker // The length of the table is stored just before the stack map (and therefore at the end of
380*795d594fSAndroid Build Coastguard Worker // the table itself), in order to be able to fetch it from a `stack_map` pointer.
381*795d594fSAndroid Build Coastguard Worker return reinterpret_cast<const uint32_t*>(stack_map)[-1];
382*795d594fSAndroid Build Coastguard Worker }
383*795d594fSAndroid Build Coastguard Worker
DCheckRootsAreValid(const std::vector<Handle<mirror::Object>> & roots,bool is_shared_region)384*795d594fSAndroid Build Coastguard Worker static void DCheckRootsAreValid(const std::vector<Handle<mirror::Object>>& roots,
385*795d594fSAndroid Build Coastguard Worker bool is_shared_region)
386*795d594fSAndroid Build Coastguard Worker REQUIRES(!Locks::intern_table_lock_) REQUIRES_SHARED(Locks::mutator_lock_) {
387*795d594fSAndroid Build Coastguard Worker if (!kIsDebugBuild) {
388*795d594fSAndroid Build Coastguard Worker return;
389*795d594fSAndroid Build Coastguard Worker }
390*795d594fSAndroid Build Coastguard Worker // Put all roots in `roots_data`.
391*795d594fSAndroid Build Coastguard Worker for (Handle<mirror::Object> object : roots) {
392*795d594fSAndroid Build Coastguard Worker // Ensure the string is strongly interned. b/32995596
393*795d594fSAndroid Build Coastguard Worker if (object->IsString()) {
394*795d594fSAndroid Build Coastguard Worker ObjPtr<mirror::String> str = object->AsString();
395*795d594fSAndroid Build Coastguard Worker ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
396*795d594fSAndroid Build Coastguard Worker CHECK(class_linker->GetInternTable()->LookupStrong(Thread::Current(), str) != nullptr);
397*795d594fSAndroid Build Coastguard Worker }
398*795d594fSAndroid Build Coastguard Worker // Ensure that we don't put movable objects in the shared region.
399*795d594fSAndroid Build Coastguard Worker if (is_shared_region) {
400*795d594fSAndroid Build Coastguard Worker CHECK(!Runtime::Current()->GetHeap()->IsMovableObject(object.Get()));
401*795d594fSAndroid Build Coastguard Worker }
402*795d594fSAndroid Build Coastguard Worker }
403*795d594fSAndroid Build Coastguard Worker }
404*795d594fSAndroid Build Coastguard Worker
SweepRootTables(IsMarkedVisitor * visitor)405*795d594fSAndroid Build Coastguard Worker void JitCodeCache::SweepRootTables(IsMarkedVisitor* visitor) {
406*795d594fSAndroid Build Coastguard Worker Thread* self = Thread::Current();
407*795d594fSAndroid Build Coastguard Worker ScopedDebugDisallowReadBarriers sddrb(self);
408*795d594fSAndroid Build Coastguard Worker {
409*795d594fSAndroid Build Coastguard Worker ReaderMutexLock mu(self, *Locks::jit_mutator_lock_);
410*795d594fSAndroid Build Coastguard Worker for (const auto& entry : method_code_map_) {
411*795d594fSAndroid Build Coastguard Worker uint32_t number_of_roots = 0;
412*795d594fSAndroid Build Coastguard Worker const uint8_t* root_table = GetRootTable(entry.first, &number_of_roots);
413*795d594fSAndroid Build Coastguard Worker uint8_t* roots_data = private_region_.IsInDataSpace(root_table)
414*795d594fSAndroid Build Coastguard Worker ? private_region_.GetWritableDataAddress(root_table)
415*795d594fSAndroid Build Coastguard Worker : shared_region_.GetWritableDataAddress(root_table);
416*795d594fSAndroid Build Coastguard Worker GcRoot<mirror::Object>* roots = reinterpret_cast<GcRoot<mirror::Object>*>(roots_data);
417*795d594fSAndroid Build Coastguard Worker for (uint32_t i = 0; i < number_of_roots; ++i) {
418*795d594fSAndroid Build Coastguard Worker // This does not need a read barrier because this is called by GC.
419*795d594fSAndroid Build Coastguard Worker mirror::Object* object = roots[i].Read<kWithoutReadBarrier>();
420*795d594fSAndroid Build Coastguard Worker if (object == nullptr || object == Runtime::GetWeakClassSentinel()) {
421*795d594fSAndroid Build Coastguard Worker // entry got deleted in a previous sweep.
422*795d594fSAndroid Build Coastguard Worker } else if (object->IsString<kDefaultVerifyFlags>()) {
423*795d594fSAndroid Build Coastguard Worker mirror::Object* new_object = visitor->IsMarked(object);
424*795d594fSAndroid Build Coastguard Worker // We know the string is marked because it's a strongly-interned string that
425*795d594fSAndroid Build Coastguard Worker // is always alive.
426*795d594fSAndroid Build Coastguard Worker // TODO: Do not use IsMarked for j.l.Class, and adjust once we move this method
427*795d594fSAndroid Build Coastguard Worker // out of the weak access/creation pause. b/32167580
428*795d594fSAndroid Build Coastguard Worker DCHECK_NE(new_object, nullptr) << "old-string:" << object;
429*795d594fSAndroid Build Coastguard Worker if (new_object != object) {
430*795d594fSAndroid Build Coastguard Worker roots[i] = GcRoot<mirror::Object>(new_object);
431*795d594fSAndroid Build Coastguard Worker }
432*795d594fSAndroid Build Coastguard Worker } else if (object->IsClass<kDefaultVerifyFlags>()) {
433*795d594fSAndroid Build Coastguard Worker mirror::Object* new_klass = visitor->IsMarked(object);
434*795d594fSAndroid Build Coastguard Worker if (new_klass == nullptr) {
435*795d594fSAndroid Build Coastguard Worker roots[i] = GcRoot<mirror::Object>(Runtime::GetWeakClassSentinel());
436*795d594fSAndroid Build Coastguard Worker } else if (new_klass != object) {
437*795d594fSAndroid Build Coastguard Worker roots[i] = GcRoot<mirror::Object>(new_klass);
438*795d594fSAndroid Build Coastguard Worker }
439*795d594fSAndroid Build Coastguard Worker } else {
440*795d594fSAndroid Build Coastguard Worker mirror::Object* new_method_type = visitor->IsMarked(object);
441*795d594fSAndroid Build Coastguard Worker if (kIsDebugBuild) {
442*795d594fSAndroid Build Coastguard Worker if (new_method_type != nullptr) {
443*795d594fSAndroid Build Coastguard Worker // SweepSystemWeaks() is happening in the compaction pause. At that point
444*795d594fSAndroid Build Coastguard Worker // IsMarked(object) returns the moved address, but the content is not there yet.
445*795d594fSAndroid Build Coastguard Worker if (!Runtime::Current()->GetHeap()->IsPerformingUffdCompaction()) {
446*795d594fSAndroid Build Coastguard Worker ObjPtr<mirror::Class> method_type_class =
447*795d594fSAndroid Build Coastguard Worker WellKnownClasses::java_lang_invoke_MethodType.Get<kWithoutReadBarrier>();
448*795d594fSAndroid Build Coastguard Worker
449*795d594fSAndroid Build Coastguard Worker CHECK_EQ((new_method_type->GetClass<kVerifyNone, kWithoutReadBarrier>()),
450*795d594fSAndroid Build Coastguard Worker method_type_class.Ptr());
451*795d594fSAndroid Build Coastguard Worker }
452*795d594fSAndroid Build Coastguard Worker }
453*795d594fSAndroid Build Coastguard Worker }
454*795d594fSAndroid Build Coastguard Worker if (new_method_type == nullptr) {
455*795d594fSAndroid Build Coastguard Worker roots[i] = nullptr;
456*795d594fSAndroid Build Coastguard Worker } else if (new_method_type != object) {
457*795d594fSAndroid Build Coastguard Worker // References are updated in VisitRootTables. Reaching this means that ArtMethod is no
458*795d594fSAndroid Build Coastguard Worker // longer reachable.
459*795d594fSAndroid Build Coastguard Worker roots[i] = GcRoot<mirror::Object>(new_method_type);
460*795d594fSAndroid Build Coastguard Worker }
461*795d594fSAndroid Build Coastguard Worker }
462*795d594fSAndroid Build Coastguard Worker }
463*795d594fSAndroid Build Coastguard Worker }
464*795d594fSAndroid Build Coastguard Worker }
465*795d594fSAndroid Build Coastguard Worker MutexLock mu(self, *Locks::jit_lock_);
466*795d594fSAndroid Build Coastguard Worker // Walk over inline caches to clear entries containing unloaded classes.
467*795d594fSAndroid Build Coastguard Worker for (const auto& [_, info] : profiling_infos_) {
468*795d594fSAndroid Build Coastguard Worker InlineCache* caches = info->GetInlineCaches();
469*795d594fSAndroid Build Coastguard Worker for (size_t i = 0; i < info->number_of_inline_caches_; ++i) {
470*795d594fSAndroid Build Coastguard Worker InlineCache* cache = &caches[i];
471*795d594fSAndroid Build Coastguard Worker for (size_t j = 0; j < InlineCache::kIndividualCacheSize; ++j) {
472*795d594fSAndroid Build Coastguard Worker mirror::Class* klass = cache->classes_[j].Read<kWithoutReadBarrier>();
473*795d594fSAndroid Build Coastguard Worker if (klass != nullptr) {
474*795d594fSAndroid Build Coastguard Worker mirror::Class* new_klass = down_cast<mirror::Class*>(visitor->IsMarked(klass));
475*795d594fSAndroid Build Coastguard Worker if (new_klass != klass) {
476*795d594fSAndroid Build Coastguard Worker cache->classes_[j] = GcRoot<mirror::Class>(new_klass);
477*795d594fSAndroid Build Coastguard Worker }
478*795d594fSAndroid Build Coastguard Worker }
479*795d594fSAndroid Build Coastguard Worker }
480*795d594fSAndroid Build Coastguard Worker }
481*795d594fSAndroid Build Coastguard Worker }
482*795d594fSAndroid Build Coastguard Worker }
483*795d594fSAndroid Build Coastguard Worker
FreeCodeAndData(const void * code_ptr)484*795d594fSAndroid Build Coastguard Worker void JitCodeCache::FreeCodeAndData(const void* code_ptr) {
485*795d594fSAndroid Build Coastguard Worker if (IsInZygoteExecSpace(code_ptr)) {
486*795d594fSAndroid Build Coastguard Worker // No need to free, this is shared memory.
487*795d594fSAndroid Build Coastguard Worker return;
488*795d594fSAndroid Build Coastguard Worker }
489*795d594fSAndroid Build Coastguard Worker uintptr_t allocation = FromCodeToAllocation(code_ptr);
490*795d594fSAndroid Build Coastguard Worker const uint8_t* data = nullptr;
491*795d594fSAndroid Build Coastguard Worker if (OatQuickMethodHeader::FromCodePointer(code_ptr)->IsOptimized()) {
492*795d594fSAndroid Build Coastguard Worker data = GetRootTable(code_ptr);
493*795d594fSAndroid Build Coastguard Worker } // else this is a JNI stub without any data.
494*795d594fSAndroid Build Coastguard Worker
495*795d594fSAndroid Build Coastguard Worker FreeLocked(&private_region_, reinterpret_cast<uint8_t*>(allocation), data);
496*795d594fSAndroid Build Coastguard Worker }
497*795d594fSAndroid Build Coastguard Worker
FreeAllMethodHeaders(const std::unordered_set<OatQuickMethodHeader * > & method_headers)498*795d594fSAndroid Build Coastguard Worker void JitCodeCache::FreeAllMethodHeaders(
499*795d594fSAndroid Build Coastguard Worker const std::unordered_set<OatQuickMethodHeader*>& method_headers) {
500*795d594fSAndroid Build Coastguard Worker // We need to remove entries in method_headers from CHA dependencies
501*795d594fSAndroid Build Coastguard Worker // first since once we do FreeCode() below, the memory can be reused
502*795d594fSAndroid Build Coastguard Worker // so it's possible for the same method_header to start representing
503*795d594fSAndroid Build Coastguard Worker // different compile code.
504*795d594fSAndroid Build Coastguard Worker {
505*795d594fSAndroid Build Coastguard Worker MutexLock mu2(Thread::Current(), *Locks::cha_lock_);
506*795d594fSAndroid Build Coastguard Worker Runtime::Current()->GetClassLinker()->GetClassHierarchyAnalysis()
507*795d594fSAndroid Build Coastguard Worker ->RemoveDependentsWithMethodHeaders(method_headers);
508*795d594fSAndroid Build Coastguard Worker }
509*795d594fSAndroid Build Coastguard Worker
510*795d594fSAndroid Build Coastguard Worker {
511*795d594fSAndroid Build Coastguard Worker ScopedCodeCacheWrite scc(private_region_);
512*795d594fSAndroid Build Coastguard Worker for (const OatQuickMethodHeader* method_header : method_headers) {
513*795d594fSAndroid Build Coastguard Worker FreeCodeAndData(method_header->GetCode());
514*795d594fSAndroid Build Coastguard Worker }
515*795d594fSAndroid Build Coastguard Worker
516*795d594fSAndroid Build Coastguard Worker // We have potentially removed a lot of debug info. Do maintenance pass to save space.
517*795d594fSAndroid Build Coastguard Worker RepackNativeDebugInfoForJit();
518*795d594fSAndroid Build Coastguard Worker }
519*795d594fSAndroid Build Coastguard Worker
520*795d594fSAndroid Build Coastguard Worker // Check that the set of compiled methods exactly matches native debug information.
521*795d594fSAndroid Build Coastguard Worker // Does not check zygote methods since they can change concurrently.
522*795d594fSAndroid Build Coastguard Worker if (kIsDebugBuild && !Runtime::Current()->IsZygote()) {
523*795d594fSAndroid Build Coastguard Worker std::map<const void*, ArtMethod*> compiled_methods;
524*795d594fSAndroid Build Coastguard Worker std::set<const void*> debug_info;
525*795d594fSAndroid Build Coastguard Worker ReaderMutexLock mu2(Thread::Current(), *Locks::jit_mutator_lock_);
526*795d594fSAndroid Build Coastguard Worker VisitAllMethods([&](const void* addr, ArtMethod* method) {
527*795d594fSAndroid Build Coastguard Worker if (!IsInZygoteExecSpace(addr)) {
528*795d594fSAndroid Build Coastguard Worker CHECK(addr != nullptr && method != nullptr);
529*795d594fSAndroid Build Coastguard Worker compiled_methods.emplace(addr, method);
530*795d594fSAndroid Build Coastguard Worker }
531*795d594fSAndroid Build Coastguard Worker });
532*795d594fSAndroid Build Coastguard Worker ForEachNativeDebugSymbol([&](const void* addr, size_t, const char* name) {
533*795d594fSAndroid Build Coastguard Worker addr = AlignDown(addr,
534*795d594fSAndroid Build Coastguard Worker GetInstructionSetInstructionAlignment(kRuntimeQuickCodeISA)); // Thumb-bit.
535*795d594fSAndroid Build Coastguard Worker bool res = debug_info.emplace(addr).second;
536*795d594fSAndroid Build Coastguard Worker CHECK(res) << "Duplicate debug info: " << addr << " " << name;
537*795d594fSAndroid Build Coastguard Worker CHECK_EQ(compiled_methods.count(addr), 1u) << "Extra debug info: " << addr << " " << name;
538*795d594fSAndroid Build Coastguard Worker });
539*795d594fSAndroid Build Coastguard Worker if (!debug_info.empty()) { // If debug-info generation is enabled.
540*795d594fSAndroid Build Coastguard Worker for (const auto& [addr, method] : compiled_methods) {
541*795d594fSAndroid Build Coastguard Worker CHECK_EQ(debug_info.count(addr), 1u) << "Mising debug info";
542*795d594fSAndroid Build Coastguard Worker }
543*795d594fSAndroid Build Coastguard Worker CHECK_EQ(compiled_methods.size(), debug_info.size());
544*795d594fSAndroid Build Coastguard Worker }
545*795d594fSAndroid Build Coastguard Worker }
546*795d594fSAndroid Build Coastguard Worker }
547*795d594fSAndroid Build Coastguard Worker
RemoveMethodsIn(Thread * self,const LinearAlloc & alloc)548*795d594fSAndroid Build Coastguard Worker void JitCodeCache::RemoveMethodsIn(Thread* self, const LinearAlloc& alloc) {
549*795d594fSAndroid Build Coastguard Worker ScopedTrace trace(__PRETTY_FUNCTION__);
550*795d594fSAndroid Build Coastguard Worker ScopedDebugDisallowReadBarriers sddrb(self);
551*795d594fSAndroid Build Coastguard Worker // We use a set to first collect all method_headers whose code need to be
552*795d594fSAndroid Build Coastguard Worker // removed. We need to free the underlying code after we remove CHA dependencies
553*795d594fSAndroid Build Coastguard Worker // for entries in this set. And it's more efficient to iterate through
554*795d594fSAndroid Build Coastguard Worker // the CHA dependency map just once with an unordered_set.
555*795d594fSAndroid Build Coastguard Worker std::unordered_set<OatQuickMethodHeader*> method_headers;
556*795d594fSAndroid Build Coastguard Worker MutexLock mu(self, *Locks::jit_lock_);
557*795d594fSAndroid Build Coastguard Worker {
558*795d594fSAndroid Build Coastguard Worker WriterMutexLock mu2(self, *Locks::jit_mutator_lock_);
559*795d594fSAndroid Build Coastguard Worker // We do not check if a code cache GC is in progress, as this method comes
560*795d594fSAndroid Build Coastguard Worker // with the classlinker_classes_lock_ held, and suspending ourselves could
561*795d594fSAndroid Build Coastguard Worker // lead to a deadlock.
562*795d594fSAndroid Build Coastguard Worker for (auto it = jni_stubs_map_.begin(); it != jni_stubs_map_.end();) {
563*795d594fSAndroid Build Coastguard Worker it->second.RemoveMethodsIn(alloc);
564*795d594fSAndroid Build Coastguard Worker if (it->second.GetMethods().empty()) {
565*795d594fSAndroid Build Coastguard Worker method_headers.insert(OatQuickMethodHeader::FromCodePointer(it->second.GetCode()));
566*795d594fSAndroid Build Coastguard Worker it = jni_stubs_map_.erase(it);
567*795d594fSAndroid Build Coastguard Worker } else {
568*795d594fSAndroid Build Coastguard Worker it->first.UpdateShorty(it->second.GetMethods().front());
569*795d594fSAndroid Build Coastguard Worker ++it;
570*795d594fSAndroid Build Coastguard Worker }
571*795d594fSAndroid Build Coastguard Worker }
572*795d594fSAndroid Build Coastguard Worker for (auto it = zombie_jni_code_.begin(); it != zombie_jni_code_.end();) {
573*795d594fSAndroid Build Coastguard Worker if (alloc.ContainsUnsafe(*it)) {
574*795d594fSAndroid Build Coastguard Worker it = zombie_jni_code_.erase(it);
575*795d594fSAndroid Build Coastguard Worker } else {
576*795d594fSAndroid Build Coastguard Worker ++it;
577*795d594fSAndroid Build Coastguard Worker }
578*795d594fSAndroid Build Coastguard Worker }
579*795d594fSAndroid Build Coastguard Worker for (auto it = method_code_map_.begin(); it != method_code_map_.end();) {
580*795d594fSAndroid Build Coastguard Worker if (alloc.ContainsUnsafe(it->second)) {
581*795d594fSAndroid Build Coastguard Worker method_headers.insert(OatQuickMethodHeader::FromCodePointer(it->first));
582*795d594fSAndroid Build Coastguard Worker VLOG(jit) << "JIT removed " << it->second->PrettyMethod() << ": " << it->first;
583*795d594fSAndroid Build Coastguard Worker zombie_code_.erase(it->first);
584*795d594fSAndroid Build Coastguard Worker processed_zombie_code_.erase(it->first);
585*795d594fSAndroid Build Coastguard Worker method_code_map_reversed_.erase(it->second);
586*795d594fSAndroid Build Coastguard Worker it = method_code_map_.erase(it);
587*795d594fSAndroid Build Coastguard Worker } else {
588*795d594fSAndroid Build Coastguard Worker ++it;
589*795d594fSAndroid Build Coastguard Worker }
590*795d594fSAndroid Build Coastguard Worker }
591*795d594fSAndroid Build Coastguard Worker for (auto it = osr_code_map_.begin(); it != osr_code_map_.end();) {
592*795d594fSAndroid Build Coastguard Worker DCHECK(!ContainsElement(zombie_code_, it->second));
593*795d594fSAndroid Build Coastguard Worker if (alloc.ContainsUnsafe(it->first)) {
594*795d594fSAndroid Build Coastguard Worker // Note that the code has already been pushed to method_headers in the loop
595*795d594fSAndroid Build Coastguard Worker // above and is going to be removed in FreeCode() below.
596*795d594fSAndroid Build Coastguard Worker it = osr_code_map_.erase(it);
597*795d594fSAndroid Build Coastguard Worker } else {
598*795d594fSAndroid Build Coastguard Worker ++it;
599*795d594fSAndroid Build Coastguard Worker }
600*795d594fSAndroid Build Coastguard Worker }
601*795d594fSAndroid Build Coastguard Worker }
602*795d594fSAndroid Build Coastguard Worker
603*795d594fSAndroid Build Coastguard Worker for (auto it = processed_zombie_jni_code_.begin(); it != processed_zombie_jni_code_.end();) {
604*795d594fSAndroid Build Coastguard Worker if (alloc.ContainsUnsafe(*it)) {
605*795d594fSAndroid Build Coastguard Worker it = processed_zombie_jni_code_.erase(it);
606*795d594fSAndroid Build Coastguard Worker } else {
607*795d594fSAndroid Build Coastguard Worker ++it;
608*795d594fSAndroid Build Coastguard Worker }
609*795d594fSAndroid Build Coastguard Worker }
610*795d594fSAndroid Build Coastguard Worker
611*795d594fSAndroid Build Coastguard Worker for (auto it = profiling_infos_.begin(); it != profiling_infos_.end();) {
612*795d594fSAndroid Build Coastguard Worker ProfilingInfo* info = it->second;
613*795d594fSAndroid Build Coastguard Worker if (alloc.ContainsUnsafe(info->GetMethod())) {
614*795d594fSAndroid Build Coastguard Worker private_region_.FreeWritableData(reinterpret_cast<uint8_t*>(info));
615*795d594fSAndroid Build Coastguard Worker it = profiling_infos_.erase(it);
616*795d594fSAndroid Build Coastguard Worker } else {
617*795d594fSAndroid Build Coastguard Worker ++it;
618*795d594fSAndroid Build Coastguard Worker }
619*795d594fSAndroid Build Coastguard Worker }
620*795d594fSAndroid Build Coastguard Worker FreeAllMethodHeaders(method_headers);
621*795d594fSAndroid Build Coastguard Worker }
622*795d594fSAndroid Build Coastguard Worker
IsWeakAccessEnabled(Thread * self) const623*795d594fSAndroid Build Coastguard Worker bool JitCodeCache::IsWeakAccessEnabled(Thread* self) const {
624*795d594fSAndroid Build Coastguard Worker return gUseReadBarrier
625*795d594fSAndroid Build Coastguard Worker ? self->GetWeakRefAccessEnabled()
626*795d594fSAndroid Build Coastguard Worker : is_weak_access_enabled_.load(std::memory_order_seq_cst);
627*795d594fSAndroid Build Coastguard Worker }
628*795d594fSAndroid Build Coastguard Worker
WaitUntilInlineCacheAccessible(Thread * self)629*795d594fSAndroid Build Coastguard Worker void JitCodeCache::WaitUntilInlineCacheAccessible(Thread* self) {
630*795d594fSAndroid Build Coastguard Worker if (IsWeakAccessEnabled(self)) {
631*795d594fSAndroid Build Coastguard Worker return;
632*795d594fSAndroid Build Coastguard Worker }
633*795d594fSAndroid Build Coastguard Worker ScopedThreadSuspension sts(self, ThreadState::kWaitingWeakGcRootRead);
634*795d594fSAndroid Build Coastguard Worker MutexLock mu(self, *Locks::jit_lock_);
635*795d594fSAndroid Build Coastguard Worker while (!IsWeakAccessEnabled(self)) {
636*795d594fSAndroid Build Coastguard Worker inline_cache_cond_.Wait(self);
637*795d594fSAndroid Build Coastguard Worker }
638*795d594fSAndroid Build Coastguard Worker }
639*795d594fSAndroid Build Coastguard Worker
GetRootTable(const void * code_ptr,uint32_t * number_of_roots)640*795d594fSAndroid Build Coastguard Worker const uint8_t* JitCodeCache::GetRootTable(const void* code_ptr, uint32_t* number_of_roots) {
641*795d594fSAndroid Build Coastguard Worker OatQuickMethodHeader* method_header = OatQuickMethodHeader::FromCodePointer(code_ptr);
642*795d594fSAndroid Build Coastguard Worker uint8_t* data = method_header->GetOptimizedCodeInfoPtr();
643*795d594fSAndroid Build Coastguard Worker uint32_t num_roots = GetNumberOfRoots(data);
644*795d594fSAndroid Build Coastguard Worker if (number_of_roots != nullptr) {
645*795d594fSAndroid Build Coastguard Worker *number_of_roots = num_roots;
646*795d594fSAndroid Build Coastguard Worker }
647*795d594fSAndroid Build Coastguard Worker return data - ComputeRootTableSize(num_roots);
648*795d594fSAndroid Build Coastguard Worker }
649*795d594fSAndroid Build Coastguard Worker
BroadcastForInlineCacheAccess()650*795d594fSAndroid Build Coastguard Worker void JitCodeCache::BroadcastForInlineCacheAccess() {
651*795d594fSAndroid Build Coastguard Worker Thread* self = Thread::Current();
652*795d594fSAndroid Build Coastguard Worker MutexLock mu(self, *Locks::jit_lock_);
653*795d594fSAndroid Build Coastguard Worker inline_cache_cond_.Broadcast(self);
654*795d594fSAndroid Build Coastguard Worker }
655*795d594fSAndroid Build Coastguard Worker
AllowInlineCacheAccess()656*795d594fSAndroid Build Coastguard Worker void JitCodeCache::AllowInlineCacheAccess() {
657*795d594fSAndroid Build Coastguard Worker DCHECK(!gUseReadBarrier);
658*795d594fSAndroid Build Coastguard Worker is_weak_access_enabled_.store(true, std::memory_order_seq_cst);
659*795d594fSAndroid Build Coastguard Worker BroadcastForInlineCacheAccess();
660*795d594fSAndroid Build Coastguard Worker }
661*795d594fSAndroid Build Coastguard Worker
DisallowInlineCacheAccess()662*795d594fSAndroid Build Coastguard Worker void JitCodeCache::DisallowInlineCacheAccess() {
663*795d594fSAndroid Build Coastguard Worker DCHECK(!gUseReadBarrier);
664*795d594fSAndroid Build Coastguard Worker is_weak_access_enabled_.store(false, std::memory_order_seq_cst);
665*795d594fSAndroid Build Coastguard Worker }
666*795d594fSAndroid Build Coastguard Worker
CopyInlineCacheInto(const InlineCache & ic,StackHandleScope<InlineCache::kIndividualCacheSize> * classes)667*795d594fSAndroid Build Coastguard Worker void JitCodeCache::CopyInlineCacheInto(
668*795d594fSAndroid Build Coastguard Worker const InlineCache& ic,
669*795d594fSAndroid Build Coastguard Worker /*out*/StackHandleScope<InlineCache::kIndividualCacheSize>* classes) {
670*795d594fSAndroid Build Coastguard Worker static_assert(arraysize(ic.classes_) == InlineCache::kIndividualCacheSize);
671*795d594fSAndroid Build Coastguard Worker DCHECK_EQ(classes->Capacity(), InlineCache::kIndividualCacheSize);
672*795d594fSAndroid Build Coastguard Worker DCHECK_EQ(classes->Size(), 0u);
673*795d594fSAndroid Build Coastguard Worker WaitUntilInlineCacheAccessible(Thread::Current());
674*795d594fSAndroid Build Coastguard Worker // Note that we don't need to lock `lock_` here, the compiler calling
675*795d594fSAndroid Build Coastguard Worker // this method has already ensured the inline cache will not be deleted.
676*795d594fSAndroid Build Coastguard Worker for (const GcRoot<mirror::Class>& root : ic.classes_) {
677*795d594fSAndroid Build Coastguard Worker mirror::Class* object = root.Read();
678*795d594fSAndroid Build Coastguard Worker if (object != nullptr) {
679*795d594fSAndroid Build Coastguard Worker DCHECK_LT(classes->Size(), classes->Capacity());
680*795d594fSAndroid Build Coastguard Worker classes->NewHandle(object);
681*795d594fSAndroid Build Coastguard Worker }
682*795d594fSAndroid Build Coastguard Worker }
683*795d594fSAndroid Build Coastguard Worker }
684*795d594fSAndroid Build Coastguard Worker
Commit(Thread * self,JitMemoryRegion * region,ArtMethod * method,ArrayRef<const uint8_t> reserved_code,ArrayRef<const uint8_t> code,ArrayRef<const uint8_t> reserved_data,const std::vector<Handle<mirror::Object>> & roots,ArrayRef<const uint8_t> stack_map,const std::vector<uint8_t> & debug_info,bool is_full_debug_info,CompilationKind compilation_kind,const ArenaSet<ArtMethod * > & cha_single_implementation_list)685*795d594fSAndroid Build Coastguard Worker bool JitCodeCache::Commit(Thread* self,
686*795d594fSAndroid Build Coastguard Worker JitMemoryRegion* region,
687*795d594fSAndroid Build Coastguard Worker ArtMethod* method,
688*795d594fSAndroid Build Coastguard Worker ArrayRef<const uint8_t> reserved_code,
689*795d594fSAndroid Build Coastguard Worker ArrayRef<const uint8_t> code,
690*795d594fSAndroid Build Coastguard Worker ArrayRef<const uint8_t> reserved_data,
691*795d594fSAndroid Build Coastguard Worker const std::vector<Handle<mirror::Object>>& roots,
692*795d594fSAndroid Build Coastguard Worker ArrayRef<const uint8_t> stack_map,
693*795d594fSAndroid Build Coastguard Worker const std::vector<uint8_t>& debug_info,
694*795d594fSAndroid Build Coastguard Worker bool is_full_debug_info,
695*795d594fSAndroid Build Coastguard Worker CompilationKind compilation_kind,
696*795d594fSAndroid Build Coastguard Worker const ArenaSet<ArtMethod*>& cha_single_implementation_list) {
697*795d594fSAndroid Build Coastguard Worker DCHECK_IMPLIES(method->IsNative(), (compilation_kind != CompilationKind::kOsr));
698*795d594fSAndroid Build Coastguard Worker
699*795d594fSAndroid Build Coastguard Worker if (!method->IsNative()) {
700*795d594fSAndroid Build Coastguard Worker // We need to do this before grabbing the lock_ because it needs to be able to see the string
701*795d594fSAndroid Build Coastguard Worker // InternTable. Native methods do not have roots.
702*795d594fSAndroid Build Coastguard Worker DCheckRootsAreValid(roots, IsSharedRegion(*region));
703*795d594fSAndroid Build Coastguard Worker }
704*795d594fSAndroid Build Coastguard Worker
705*795d594fSAndroid Build Coastguard Worker const uint8_t* roots_data = reserved_data.data();
706*795d594fSAndroid Build Coastguard Worker size_t root_table_size = ComputeRootTableSize(roots.size());
707*795d594fSAndroid Build Coastguard Worker const uint8_t* stack_map_data = roots_data + root_table_size;
708*795d594fSAndroid Build Coastguard Worker
709*795d594fSAndroid Build Coastguard Worker OatQuickMethodHeader* method_header = nullptr;
710*795d594fSAndroid Build Coastguard Worker {
711*795d594fSAndroid Build Coastguard Worker MutexLock mu(self, *Locks::jit_lock_);
712*795d594fSAndroid Build Coastguard Worker const uint8_t* code_ptr = region->CommitCode(reserved_code, code, stack_map_data);
713*795d594fSAndroid Build Coastguard Worker if (code_ptr == nullptr) {
714*795d594fSAndroid Build Coastguard Worker return false;
715*795d594fSAndroid Build Coastguard Worker }
716*795d594fSAndroid Build Coastguard Worker method_header = OatQuickMethodHeader::FromCodePointer(code_ptr);
717*795d594fSAndroid Build Coastguard Worker
718*795d594fSAndroid Build Coastguard Worker // Commit roots and stack maps before updating the entry point.
719*795d594fSAndroid Build Coastguard Worker if (!region->CommitData(reserved_data, roots, stack_map)) {
720*795d594fSAndroid Build Coastguard Worker return false;
721*795d594fSAndroid Build Coastguard Worker }
722*795d594fSAndroid Build Coastguard Worker
723*795d594fSAndroid Build Coastguard Worker switch (compilation_kind) {
724*795d594fSAndroid Build Coastguard Worker case CompilationKind::kOsr:
725*795d594fSAndroid Build Coastguard Worker number_of_osr_compilations_++;
726*795d594fSAndroid Build Coastguard Worker break;
727*795d594fSAndroid Build Coastguard Worker case CompilationKind::kBaseline:
728*795d594fSAndroid Build Coastguard Worker number_of_baseline_compilations_++;
729*795d594fSAndroid Build Coastguard Worker break;
730*795d594fSAndroid Build Coastguard Worker case CompilationKind::kOptimized:
731*795d594fSAndroid Build Coastguard Worker number_of_optimized_compilations_++;
732*795d594fSAndroid Build Coastguard Worker break;
733*795d594fSAndroid Build Coastguard Worker }
734*795d594fSAndroid Build Coastguard Worker
735*795d594fSAndroid Build Coastguard Worker // We need to update the debug info before the entry point gets set.
736*795d594fSAndroid Build Coastguard Worker // At the same time we want to do under JIT lock so that debug info and JIT maps are in sync.
737*795d594fSAndroid Build Coastguard Worker if (!debug_info.empty()) {
738*795d594fSAndroid Build Coastguard Worker // NB: Don't allow packing of full info since it would remove non-backtrace data.
739*795d594fSAndroid Build Coastguard Worker AddNativeDebugInfoForJit(code_ptr, debug_info, /*allow_packing=*/ !is_full_debug_info);
740*795d594fSAndroid Build Coastguard Worker }
741*795d594fSAndroid Build Coastguard Worker
742*795d594fSAndroid Build Coastguard Worker // The following needs to be guarded by cha_lock_ also. Otherwise it's possible that the
743*795d594fSAndroid Build Coastguard Worker // compiled code is considered invalidated by some class linking, but below we still make the
744*795d594fSAndroid Build Coastguard Worker // compiled code valid for the method. Need cha_lock_ for checking all single-implementation
745*795d594fSAndroid Build Coastguard Worker // flags and register dependencies.
746*795d594fSAndroid Build Coastguard Worker {
747*795d594fSAndroid Build Coastguard Worker ScopedDebugDisallowReadBarriers sddrb(self);
748*795d594fSAndroid Build Coastguard Worker MutexLock cha_mu(self, *Locks::cha_lock_);
749*795d594fSAndroid Build Coastguard Worker bool single_impl_still_valid = true;
750*795d594fSAndroid Build Coastguard Worker for (ArtMethod* single_impl : cha_single_implementation_list) {
751*795d594fSAndroid Build Coastguard Worker if (!single_impl->HasSingleImplementation()) {
752*795d594fSAndroid Build Coastguard Worker // Simply discard the compiled code.
753*795d594fSAndroid Build Coastguard Worker // Hopefully the class hierarchy will be more stable when compilation is retried.
754*795d594fSAndroid Build Coastguard Worker single_impl_still_valid = false;
755*795d594fSAndroid Build Coastguard Worker break;
756*795d594fSAndroid Build Coastguard Worker }
757*795d594fSAndroid Build Coastguard Worker }
758*795d594fSAndroid Build Coastguard Worker
759*795d594fSAndroid Build Coastguard Worker // Discard the code if any single-implementation assumptions are now invalid.
760*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(!single_impl_still_valid)) {
761*795d594fSAndroid Build Coastguard Worker VLOG(jit) << "JIT discarded jitted code due to invalid single-implementation assumptions.";
762*795d594fSAndroid Build Coastguard Worker return false;
763*795d594fSAndroid Build Coastguard Worker }
764*795d594fSAndroid Build Coastguard Worker DCHECK(cha_single_implementation_list.empty() || !Runtime::Current()->IsJavaDebuggable())
765*795d594fSAndroid Build Coastguard Worker << "Should not be using cha on debuggable apps/runs!";
766*795d594fSAndroid Build Coastguard Worker
767*795d594fSAndroid Build Coastguard Worker ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
768*795d594fSAndroid Build Coastguard Worker for (ArtMethod* single_impl : cha_single_implementation_list) {
769*795d594fSAndroid Build Coastguard Worker class_linker->GetClassHierarchyAnalysis()->AddDependency(
770*795d594fSAndroid Build Coastguard Worker single_impl, method, method_header);
771*795d594fSAndroid Build Coastguard Worker }
772*795d594fSAndroid Build Coastguard Worker }
773*795d594fSAndroid Build Coastguard Worker
774*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(method->IsNative())) {
775*795d594fSAndroid Build Coastguard Worker ScopedDebugDisallowReadBarriers sddrb(self);
776*795d594fSAndroid Build Coastguard Worker WriterMutexLock mu2(self, *Locks::jit_mutator_lock_);
777*795d594fSAndroid Build Coastguard Worker auto it = jni_stubs_map_.find(JniStubKey(method));
778*795d594fSAndroid Build Coastguard Worker DCHECK(it != jni_stubs_map_.end())
779*795d594fSAndroid Build Coastguard Worker << "Entry inserted in NotifyCompilationOf() should be alive.";
780*795d594fSAndroid Build Coastguard Worker JniStubData* data = &it->second;
781*795d594fSAndroid Build Coastguard Worker DCHECK(ContainsElement(data->GetMethods(), method))
782*795d594fSAndroid Build Coastguard Worker << "Entry inserted in NotifyCompilationOf() should contain this method.";
783*795d594fSAndroid Build Coastguard Worker data->SetCode(code_ptr);
784*795d594fSAndroid Build Coastguard Worker data->UpdateEntryPoints(method_header->GetEntryPoint());
785*795d594fSAndroid Build Coastguard Worker } else {
786*795d594fSAndroid Build Coastguard Worker if (method->IsPreCompiled() && IsSharedRegion(*region)) {
787*795d594fSAndroid Build Coastguard Worker ScopedDebugDisallowReadBarriers sddrb(self);
788*795d594fSAndroid Build Coastguard Worker zygote_map_.Put(code_ptr, method);
789*795d594fSAndroid Build Coastguard Worker } else {
790*795d594fSAndroid Build Coastguard Worker ScopedDebugDisallowReadBarriers sddrb(self);
791*795d594fSAndroid Build Coastguard Worker WriterMutexLock mu2(self, *Locks::jit_mutator_lock_);
792*795d594fSAndroid Build Coastguard Worker method_code_map_.Put(code_ptr, method);
793*795d594fSAndroid Build Coastguard Worker
794*795d594fSAndroid Build Coastguard Worker // Searching for MethodType-s in roots. They need to be treated as strongly reachable while
795*795d594fSAndroid Build Coastguard Worker // the corresponding ArtMethod is not removed.
796*795d594fSAndroid Build Coastguard Worker ObjPtr<mirror::Class> method_type_class =
797*795d594fSAndroid Build Coastguard Worker WellKnownClasses::java_lang_invoke_MethodType.Get<kWithoutReadBarrier>();
798*795d594fSAndroid Build Coastguard Worker
799*795d594fSAndroid Build Coastguard Worker for (const Handle<mirror::Object>& root : roots) {
800*795d594fSAndroid Build Coastguard Worker ObjPtr<mirror::Class> klass = root->GetClass<kDefaultVerifyFlags, kWithoutReadBarrier>();
801*795d594fSAndroid Build Coastguard Worker if (klass == method_type_class ||
802*795d594fSAndroid Build Coastguard Worker klass == ReadBarrier::IsMarked(method_type_class.Ptr()) ||
803*795d594fSAndroid Build Coastguard Worker ReadBarrier::IsMarked(klass.Ptr()) == method_type_class) {
804*795d594fSAndroid Build Coastguard Worker auto it = method_code_map_reversed_.FindOrAdd(method, std::vector<const void*>());
805*795d594fSAndroid Build Coastguard Worker std::vector<const void*>& code_ptrs = it->second;
806*795d594fSAndroid Build Coastguard Worker
807*795d594fSAndroid Build Coastguard Worker DCHECK(std::find(code_ptrs.begin(), code_ptrs.end(), code_ptr) == code_ptrs.end());
808*795d594fSAndroid Build Coastguard Worker it->second.emplace_back(code_ptr);
809*795d594fSAndroid Build Coastguard Worker
810*795d594fSAndroid Build Coastguard Worker // `MethodType`s are strong GC roots and need write barrier.
811*795d594fSAndroid Build Coastguard Worker WriteBarrier::ForEveryFieldWrite(method->GetDeclaringClass<kWithoutReadBarrier>());
812*795d594fSAndroid Build Coastguard Worker break;
813*795d594fSAndroid Build Coastguard Worker }
814*795d594fSAndroid Build Coastguard Worker }
815*795d594fSAndroid Build Coastguard Worker }
816*795d594fSAndroid Build Coastguard Worker if (compilation_kind == CompilationKind::kOsr) {
817*795d594fSAndroid Build Coastguard Worker ScopedDebugDisallowReadBarriers sddrb(self);
818*795d594fSAndroid Build Coastguard Worker WriterMutexLock mu2(self, *Locks::jit_mutator_lock_);
819*795d594fSAndroid Build Coastguard Worker osr_code_map_.Put(method, code_ptr);
820*795d594fSAndroid Build Coastguard Worker } else if (method->StillNeedsClinitCheck()) {
821*795d594fSAndroid Build Coastguard Worker ScopedDebugDisallowReadBarriers sddrb(self);
822*795d594fSAndroid Build Coastguard Worker // This situation currently only occurs in the jit-zygote mode.
823*795d594fSAndroid Build Coastguard Worker DCHECK(!garbage_collect_code_);
824*795d594fSAndroid Build Coastguard Worker DCHECK(method->IsPreCompiled());
825*795d594fSAndroid Build Coastguard Worker // The shared region can easily be queried. For the private region, we
826*795d594fSAndroid Build Coastguard Worker // use a side map.
827*795d594fSAndroid Build Coastguard Worker if (!IsSharedRegion(*region)) {
828*795d594fSAndroid Build Coastguard Worker WriterMutexLock mu2(self, *Locks::jit_mutator_lock_);
829*795d594fSAndroid Build Coastguard Worker saved_compiled_methods_map_.Put(method, code_ptr);
830*795d594fSAndroid Build Coastguard Worker }
831*795d594fSAndroid Build Coastguard Worker } else {
832*795d594fSAndroid Build Coastguard Worker Runtime::Current()->GetInstrumentation()->UpdateMethodsCode(
833*795d594fSAndroid Build Coastguard Worker method, method_header->GetEntryPoint());
834*795d594fSAndroid Build Coastguard Worker }
835*795d594fSAndroid Build Coastguard Worker }
836*795d594fSAndroid Build Coastguard Worker VLOG(jit)
837*795d594fSAndroid Build Coastguard Worker << "JIT added (kind=" << compilation_kind << ") "
838*795d594fSAndroid Build Coastguard Worker << ArtMethod::PrettyMethod(method) << "@" << method
839*795d594fSAndroid Build Coastguard Worker << " ccache_size=" << PrettySize(CodeCacheSizeLocked()) << ": "
840*795d594fSAndroid Build Coastguard Worker << " dcache_size=" << PrettySize(DataCacheSizeLocked()) << ": "
841*795d594fSAndroid Build Coastguard Worker << reinterpret_cast<const void*>(method_header->GetEntryPoint()) << ","
842*795d594fSAndroid Build Coastguard Worker << reinterpret_cast<const void*>(method_header->GetEntryPoint() +
843*795d594fSAndroid Build Coastguard Worker method_header->GetCodeSize());
844*795d594fSAndroid Build Coastguard Worker }
845*795d594fSAndroid Build Coastguard Worker
846*795d594fSAndroid Build Coastguard Worker if (kIsDebugBuild) {
847*795d594fSAndroid Build Coastguard Worker uintptr_t entry_point = reinterpret_cast<uintptr_t>(method_header->GetEntryPoint());
848*795d594fSAndroid Build Coastguard Worker DCHECK_EQ(LookupMethodHeader(entry_point, method), method_header) << method->PrettyMethod();
849*795d594fSAndroid Build Coastguard Worker DCHECK_EQ(LookupMethodHeader(entry_point + method_header->GetCodeSize() - 1, method),
850*795d594fSAndroid Build Coastguard Worker method_header) << method->PrettyMethod();
851*795d594fSAndroid Build Coastguard Worker }
852*795d594fSAndroid Build Coastguard Worker return true;
853*795d594fSAndroid Build Coastguard Worker }
854*795d594fSAndroid Build Coastguard Worker
CodeCacheSize()855*795d594fSAndroid Build Coastguard Worker size_t JitCodeCache::CodeCacheSize() {
856*795d594fSAndroid Build Coastguard Worker MutexLock mu(Thread::Current(), *Locks::jit_lock_);
857*795d594fSAndroid Build Coastguard Worker return CodeCacheSizeLocked();
858*795d594fSAndroid Build Coastguard Worker }
859*795d594fSAndroid Build Coastguard Worker
RemoveMethod(ArtMethod * method,bool release_memory)860*795d594fSAndroid Build Coastguard Worker bool JitCodeCache::RemoveMethod(ArtMethod* method, bool release_memory) {
861*795d594fSAndroid Build Coastguard Worker // This function is used only for testing and only with non-native methods.
862*795d594fSAndroid Build Coastguard Worker CHECK(!method->IsNative());
863*795d594fSAndroid Build Coastguard Worker
864*795d594fSAndroid Build Coastguard Worker Thread* self = Thread::Current();
865*795d594fSAndroid Build Coastguard Worker ScopedDebugDisallowReadBarriers sddrb(self);
866*795d594fSAndroid Build Coastguard Worker MutexLock mu(self, *Locks::jit_lock_);
867*795d594fSAndroid Build Coastguard Worker
868*795d594fSAndroid Build Coastguard Worker bool in_cache = RemoveMethodLocked(method, release_memory);
869*795d594fSAndroid Build Coastguard Worker
870*795d594fSAndroid Build Coastguard Worker if (!in_cache) {
871*795d594fSAndroid Build Coastguard Worker return false;
872*795d594fSAndroid Build Coastguard Worker }
873*795d594fSAndroid Build Coastguard Worker
874*795d594fSAndroid Build Coastguard Worker Runtime::Current()->GetInstrumentation()->InitializeMethodsCode(method, /*aot_code=*/ nullptr);
875*795d594fSAndroid Build Coastguard Worker return true;
876*795d594fSAndroid Build Coastguard Worker }
877*795d594fSAndroid Build Coastguard Worker
RemoveMethodLocked(ArtMethod * method,bool release_memory)878*795d594fSAndroid Build Coastguard Worker bool JitCodeCache::RemoveMethodLocked(ArtMethod* method, bool release_memory) {
879*795d594fSAndroid Build Coastguard Worker if (LIKELY(!method->IsNative())) {
880*795d594fSAndroid Build Coastguard Worker auto it = profiling_infos_.find(method);
881*795d594fSAndroid Build Coastguard Worker if (it != profiling_infos_.end()) {
882*795d594fSAndroid Build Coastguard Worker profiling_infos_.erase(it);
883*795d594fSAndroid Build Coastguard Worker }
884*795d594fSAndroid Build Coastguard Worker }
885*795d594fSAndroid Build Coastguard Worker
886*795d594fSAndroid Build Coastguard Worker bool in_cache = false;
887*795d594fSAndroid Build Coastguard Worker ScopedCodeCacheWrite ccw(private_region_);
888*795d594fSAndroid Build Coastguard Worker WriterMutexLock mu(Thread::Current(), *Locks::jit_mutator_lock_);
889*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(method->IsNative())) {
890*795d594fSAndroid Build Coastguard Worker auto it = jni_stubs_map_.find(JniStubKey(method));
891*795d594fSAndroid Build Coastguard Worker if (it != jni_stubs_map_.end() && it->second.RemoveMethod(method)) {
892*795d594fSAndroid Build Coastguard Worker in_cache = true;
893*795d594fSAndroid Build Coastguard Worker if (it->second.GetMethods().empty()) {
894*795d594fSAndroid Build Coastguard Worker if (release_memory) {
895*795d594fSAndroid Build Coastguard Worker FreeCodeAndData(it->second.GetCode());
896*795d594fSAndroid Build Coastguard Worker }
897*795d594fSAndroid Build Coastguard Worker jni_stubs_map_.erase(it);
898*795d594fSAndroid Build Coastguard Worker } else {
899*795d594fSAndroid Build Coastguard Worker it->first.UpdateShorty(it->second.GetMethods().front());
900*795d594fSAndroid Build Coastguard Worker }
901*795d594fSAndroid Build Coastguard Worker zombie_jni_code_.erase(method);
902*795d594fSAndroid Build Coastguard Worker processed_zombie_jni_code_.erase(method);
903*795d594fSAndroid Build Coastguard Worker }
904*795d594fSAndroid Build Coastguard Worker } else {
905*795d594fSAndroid Build Coastguard Worker for (auto it = method_code_map_.begin(); it != method_code_map_.end();) {
906*795d594fSAndroid Build Coastguard Worker if (it->second == method) {
907*795d594fSAndroid Build Coastguard Worker in_cache = true;
908*795d594fSAndroid Build Coastguard Worker if (release_memory) {
909*795d594fSAndroid Build Coastguard Worker FreeCodeAndData(it->first);
910*795d594fSAndroid Build Coastguard Worker }
911*795d594fSAndroid Build Coastguard Worker VLOG(jit) << "JIT removed " << it->second->PrettyMethod() << ": " << it->first;
912*795d594fSAndroid Build Coastguard Worker it = method_code_map_.erase(it);
913*795d594fSAndroid Build Coastguard Worker } else {
914*795d594fSAndroid Build Coastguard Worker ++it;
915*795d594fSAndroid Build Coastguard Worker }
916*795d594fSAndroid Build Coastguard Worker }
917*795d594fSAndroid Build Coastguard Worker method_code_map_reversed_.erase(method);
918*795d594fSAndroid Build Coastguard Worker
919*795d594fSAndroid Build Coastguard Worker auto osr_it = osr_code_map_.find(method);
920*795d594fSAndroid Build Coastguard Worker if (osr_it != osr_code_map_.end()) {
921*795d594fSAndroid Build Coastguard Worker osr_code_map_.erase(osr_it);
922*795d594fSAndroid Build Coastguard Worker }
923*795d594fSAndroid Build Coastguard Worker }
924*795d594fSAndroid Build Coastguard Worker
925*795d594fSAndroid Build Coastguard Worker return in_cache;
926*795d594fSAndroid Build Coastguard Worker }
927*795d594fSAndroid Build Coastguard Worker
928*795d594fSAndroid Build Coastguard Worker // This notifies the code cache that the given method has been redefined and that it should remove
929*795d594fSAndroid Build Coastguard Worker // any cached information it has on the method. All threads must be suspended before calling this
930*795d594fSAndroid Build Coastguard Worker // method. The compiled code for the method (if there is any) must not be in any threads call stack.
NotifyMethodRedefined(ArtMethod * method)931*795d594fSAndroid Build Coastguard Worker void JitCodeCache::NotifyMethodRedefined(ArtMethod* method) {
932*795d594fSAndroid Build Coastguard Worker Thread* self = Thread::Current();
933*795d594fSAndroid Build Coastguard Worker ScopedDebugDisallowReadBarriers sddrb(self);
934*795d594fSAndroid Build Coastguard Worker MutexLock mu(self, *Locks::jit_lock_);
935*795d594fSAndroid Build Coastguard Worker RemoveMethodLocked(method, /* release_memory= */ true);
936*795d594fSAndroid Build Coastguard Worker }
937*795d594fSAndroid Build Coastguard Worker
938*795d594fSAndroid Build Coastguard Worker // This invalidates old_method. Once this function returns one can no longer use old_method to
939*795d594fSAndroid Build Coastguard Worker // execute code unless it is fixed up. This fixup will happen later in the process of installing a
940*795d594fSAndroid Build Coastguard Worker // class redefinition.
941*795d594fSAndroid Build Coastguard Worker // TODO We should add some info to ArtMethod to note that 'old_method' has been invalidated and
942*795d594fSAndroid Build Coastguard Worker // shouldn't be used since it is no longer logically in the jit code cache.
943*795d594fSAndroid Build Coastguard Worker // TODO We should add DCHECKS that validate that the JIT is paused when this method is entered.
MoveObsoleteMethod(ArtMethod * old_method,ArtMethod * new_method)944*795d594fSAndroid Build Coastguard Worker void JitCodeCache::MoveObsoleteMethod(ArtMethod* old_method, ArtMethod* new_method) {
945*795d594fSAndroid Build Coastguard Worker Thread* self = Thread::Current();
946*795d594fSAndroid Build Coastguard Worker ScopedDebugDisallowReadBarriers sddrb(self);
947*795d594fSAndroid Build Coastguard Worker WriterMutexLock mu(self, *Locks::jit_mutator_lock_);
948*795d594fSAndroid Build Coastguard Worker if (old_method->IsNative()) {
949*795d594fSAndroid Build Coastguard Worker // Update methods in jni_stubs_map_.
950*795d594fSAndroid Build Coastguard Worker for (auto& entry : jni_stubs_map_) {
951*795d594fSAndroid Build Coastguard Worker JniStubData& data = entry.second;
952*795d594fSAndroid Build Coastguard Worker data.MoveObsoleteMethod(old_method, new_method);
953*795d594fSAndroid Build Coastguard Worker }
954*795d594fSAndroid Build Coastguard Worker return;
955*795d594fSAndroid Build Coastguard Worker }
956*795d594fSAndroid Build Coastguard Worker
957*795d594fSAndroid Build Coastguard Worker // Update method_code_map_ to point to the new method.
958*795d594fSAndroid Build Coastguard Worker for (auto& it : method_code_map_) {
959*795d594fSAndroid Build Coastguard Worker if (it.second == old_method) {
960*795d594fSAndroid Build Coastguard Worker it.second = new_method;
961*795d594fSAndroid Build Coastguard Worker }
962*795d594fSAndroid Build Coastguard Worker }
963*795d594fSAndroid Build Coastguard Worker // Update osr_code_map_ to point to the new method.
964*795d594fSAndroid Build Coastguard Worker auto code_map = osr_code_map_.find(old_method);
965*795d594fSAndroid Build Coastguard Worker if (code_map != osr_code_map_.end()) {
966*795d594fSAndroid Build Coastguard Worker osr_code_map_.Put(new_method, code_map->second);
967*795d594fSAndroid Build Coastguard Worker osr_code_map_.erase(old_method);
968*795d594fSAndroid Build Coastguard Worker }
969*795d594fSAndroid Build Coastguard Worker
970*795d594fSAndroid Build Coastguard Worker auto node = method_code_map_reversed_.extract(old_method);
971*795d594fSAndroid Build Coastguard Worker if (!node.empty()) {
972*795d594fSAndroid Build Coastguard Worker node.key() = new_method;
973*795d594fSAndroid Build Coastguard Worker method_code_map_reversed_.insert(std::move(node));
974*795d594fSAndroid Build Coastguard Worker }
975*795d594fSAndroid Build Coastguard Worker }
976*795d594fSAndroid Build Coastguard Worker
TransitionToDebuggable()977*795d594fSAndroid Build Coastguard Worker void JitCodeCache::TransitionToDebuggable() {
978*795d594fSAndroid Build Coastguard Worker // Check that none of our methods have an entrypoint in the zygote exec
979*795d594fSAndroid Build Coastguard Worker // space (this should be taken care of by
980*795d594fSAndroid Build Coastguard Worker // ClassLinker::UpdateEntryPointsClassVisitor.
981*795d594fSAndroid Build Coastguard Worker Thread* self = Thread::Current();
982*795d594fSAndroid Build Coastguard Worker ScopedDebugDisallowReadBarriers sddrb(self);
983*795d594fSAndroid Build Coastguard Worker if (kIsDebugBuild) {
984*795d594fSAndroid Build Coastguard Worker // TODO: Check `jni_stubs_map_`?
985*795d594fSAndroid Build Coastguard Worker ReaderMutexLock mu2(self, *Locks::jit_mutator_lock_);
986*795d594fSAndroid Build Coastguard Worker for (const auto& entry : method_code_map_) {
987*795d594fSAndroid Build Coastguard Worker ArtMethod* method = entry.second;
988*795d594fSAndroid Build Coastguard Worker DCHECK(!method->IsPreCompiled());
989*795d594fSAndroid Build Coastguard Worker DCHECK(!IsInZygoteExecSpace(method->GetEntryPointFromQuickCompiledCode()));
990*795d594fSAndroid Build Coastguard Worker }
991*795d594fSAndroid Build Coastguard Worker }
992*795d594fSAndroid Build Coastguard Worker {
993*795d594fSAndroid Build Coastguard Worker WriterMutexLock mu(self, *Locks::jit_mutator_lock_);
994*795d594fSAndroid Build Coastguard Worker // Not strictly necessary, but this map is useless now.
995*795d594fSAndroid Build Coastguard Worker saved_compiled_methods_map_.clear();
996*795d594fSAndroid Build Coastguard Worker }
997*795d594fSAndroid Build Coastguard Worker if (kIsDebugBuild) {
998*795d594fSAndroid Build Coastguard Worker for (const auto& entry : zygote_map_) {
999*795d594fSAndroid Build Coastguard Worker ArtMethod* method = entry.method;
1000*795d594fSAndroid Build Coastguard Worker if (method != nullptr) {
1001*795d594fSAndroid Build Coastguard Worker DCHECK(!method->IsPreCompiled());
1002*795d594fSAndroid Build Coastguard Worker DCHECK(!IsInZygoteExecSpace(method->GetEntryPointFromQuickCompiledCode()));
1003*795d594fSAndroid Build Coastguard Worker }
1004*795d594fSAndroid Build Coastguard Worker }
1005*795d594fSAndroid Build Coastguard Worker }
1006*795d594fSAndroid Build Coastguard Worker }
1007*795d594fSAndroid Build Coastguard Worker
CodeCacheSizeLocked()1008*795d594fSAndroid Build Coastguard Worker size_t JitCodeCache::CodeCacheSizeLocked() {
1009*795d594fSAndroid Build Coastguard Worker return GetCurrentRegion()->GetUsedMemoryForCode();
1010*795d594fSAndroid Build Coastguard Worker }
1011*795d594fSAndroid Build Coastguard Worker
DataCacheSize()1012*795d594fSAndroid Build Coastguard Worker size_t JitCodeCache::DataCacheSize() {
1013*795d594fSAndroid Build Coastguard Worker MutexLock mu(Thread::Current(), *Locks::jit_lock_);
1014*795d594fSAndroid Build Coastguard Worker return DataCacheSizeLocked();
1015*795d594fSAndroid Build Coastguard Worker }
1016*795d594fSAndroid Build Coastguard Worker
DataCacheSizeLocked()1017*795d594fSAndroid Build Coastguard Worker size_t JitCodeCache::DataCacheSizeLocked() {
1018*795d594fSAndroid Build Coastguard Worker return GetCurrentRegion()->GetUsedMemoryForData();
1019*795d594fSAndroid Build Coastguard Worker }
1020*795d594fSAndroid Build Coastguard Worker
Reserve(Thread * self,JitMemoryRegion * region,size_t code_size,size_t stack_map_size,size_t number_of_roots,ArtMethod * method,ArrayRef<const uint8_t> * reserved_code,ArrayRef<const uint8_t> * reserved_data)1021*795d594fSAndroid Build Coastguard Worker bool JitCodeCache::Reserve(Thread* self,
1022*795d594fSAndroid Build Coastguard Worker JitMemoryRegion* region,
1023*795d594fSAndroid Build Coastguard Worker size_t code_size,
1024*795d594fSAndroid Build Coastguard Worker size_t stack_map_size,
1025*795d594fSAndroid Build Coastguard Worker size_t number_of_roots,
1026*795d594fSAndroid Build Coastguard Worker ArtMethod* method,
1027*795d594fSAndroid Build Coastguard Worker /*out*/ArrayRef<const uint8_t>* reserved_code,
1028*795d594fSAndroid Build Coastguard Worker /*out*/ArrayRef<const uint8_t>* reserved_data) {
1029*795d594fSAndroid Build Coastguard Worker code_size = OatQuickMethodHeader::InstructionAlignedSize() + code_size;
1030*795d594fSAndroid Build Coastguard Worker size_t data_size = RoundUp(ComputeRootTableSize(number_of_roots) + stack_map_size, sizeof(void*));
1031*795d594fSAndroid Build Coastguard Worker
1032*795d594fSAndroid Build Coastguard Worker const uint8_t* code;
1033*795d594fSAndroid Build Coastguard Worker const uint8_t* data;
1034*795d594fSAndroid Build Coastguard Worker while (true) {
1035*795d594fSAndroid Build Coastguard Worker bool at_max_capacity = false;
1036*795d594fSAndroid Build Coastguard Worker {
1037*795d594fSAndroid Build Coastguard Worker ScopedThreadSuspension sts(self, ThreadState::kSuspended);
1038*795d594fSAndroid Build Coastguard Worker MutexLock mu(self, *Locks::jit_lock_);
1039*795d594fSAndroid Build Coastguard Worker ScopedCodeCacheWrite ccw(*region);
1040*795d594fSAndroid Build Coastguard Worker code = region->AllocateCode(code_size);
1041*795d594fSAndroid Build Coastguard Worker data = region->AllocateData(data_size);
1042*795d594fSAndroid Build Coastguard Worker at_max_capacity = IsAtMaxCapacity();
1043*795d594fSAndroid Build Coastguard Worker }
1044*795d594fSAndroid Build Coastguard Worker if (code != nullptr && data != nullptr) {
1045*795d594fSAndroid Build Coastguard Worker break;
1046*795d594fSAndroid Build Coastguard Worker }
1047*795d594fSAndroid Build Coastguard Worker Free(self, region, code, data);
1048*795d594fSAndroid Build Coastguard Worker if (at_max_capacity) {
1049*795d594fSAndroid Build Coastguard Worker VLOG(jit) << "JIT failed to allocate code of size "
1050*795d594fSAndroid Build Coastguard Worker << PrettySize(code_size)
1051*795d594fSAndroid Build Coastguard Worker << ", and data of size "
1052*795d594fSAndroid Build Coastguard Worker << PrettySize(data_size);
1053*795d594fSAndroid Build Coastguard Worker return false;
1054*795d594fSAndroid Build Coastguard Worker }
1055*795d594fSAndroid Build Coastguard Worker // Increase the capacity and try again.
1056*795d594fSAndroid Build Coastguard Worker IncreaseCodeCacheCapacity(self);
1057*795d594fSAndroid Build Coastguard Worker }
1058*795d594fSAndroid Build Coastguard Worker
1059*795d594fSAndroid Build Coastguard Worker *reserved_code = ArrayRef<const uint8_t>(code, code_size);
1060*795d594fSAndroid Build Coastguard Worker *reserved_data = ArrayRef<const uint8_t>(data, data_size);
1061*795d594fSAndroid Build Coastguard Worker
1062*795d594fSAndroid Build Coastguard Worker MutexLock mu(self, *Locks::jit_lock_);
1063*795d594fSAndroid Build Coastguard Worker histogram_code_memory_use_.AddValue(code_size);
1064*795d594fSAndroid Build Coastguard Worker if (code_size > kCodeSizeLogThreshold) {
1065*795d594fSAndroid Build Coastguard Worker LOG(INFO) << "JIT allocated "
1066*795d594fSAndroid Build Coastguard Worker << PrettySize(code_size)
1067*795d594fSAndroid Build Coastguard Worker << " for compiled code of "
1068*795d594fSAndroid Build Coastguard Worker << ArtMethod::PrettyMethod(method);
1069*795d594fSAndroid Build Coastguard Worker }
1070*795d594fSAndroid Build Coastguard Worker histogram_stack_map_memory_use_.AddValue(data_size);
1071*795d594fSAndroid Build Coastguard Worker if (data_size > kStackMapSizeLogThreshold) {
1072*795d594fSAndroid Build Coastguard Worker LOG(INFO) << "JIT allocated "
1073*795d594fSAndroid Build Coastguard Worker << PrettySize(data_size)
1074*795d594fSAndroid Build Coastguard Worker << " for stack maps of "
1075*795d594fSAndroid Build Coastguard Worker << ArtMethod::PrettyMethod(method);
1076*795d594fSAndroid Build Coastguard Worker }
1077*795d594fSAndroid Build Coastguard Worker return true;
1078*795d594fSAndroid Build Coastguard Worker }
1079*795d594fSAndroid Build Coastguard Worker
Free(Thread * self,JitMemoryRegion * region,const uint8_t * code,const uint8_t * data)1080*795d594fSAndroid Build Coastguard Worker void JitCodeCache::Free(Thread* self,
1081*795d594fSAndroid Build Coastguard Worker JitMemoryRegion* region,
1082*795d594fSAndroid Build Coastguard Worker const uint8_t* code,
1083*795d594fSAndroid Build Coastguard Worker const uint8_t* data) {
1084*795d594fSAndroid Build Coastguard Worker MutexLock mu(self, *Locks::jit_lock_);
1085*795d594fSAndroid Build Coastguard Worker ScopedCodeCacheWrite ccw(*region);
1086*795d594fSAndroid Build Coastguard Worker FreeLocked(region, code, data);
1087*795d594fSAndroid Build Coastguard Worker }
1088*795d594fSAndroid Build Coastguard Worker
FreeLocked(JitMemoryRegion * region,const uint8_t * code,const uint8_t * data)1089*795d594fSAndroid Build Coastguard Worker void JitCodeCache::FreeLocked(JitMemoryRegion* region, const uint8_t* code, const uint8_t* data) {
1090*795d594fSAndroid Build Coastguard Worker if (code != nullptr) {
1091*795d594fSAndroid Build Coastguard Worker RemoveNativeDebugInfoForJit(reinterpret_cast<const void*>(FromAllocationToCode(code)));
1092*795d594fSAndroid Build Coastguard Worker region->FreeCode(code);
1093*795d594fSAndroid Build Coastguard Worker }
1094*795d594fSAndroid Build Coastguard Worker if (data != nullptr) {
1095*795d594fSAndroid Build Coastguard Worker region->FreeData(data);
1096*795d594fSAndroid Build Coastguard Worker }
1097*795d594fSAndroid Build Coastguard Worker }
1098*795d594fSAndroid Build Coastguard Worker
1099*795d594fSAndroid Build Coastguard Worker class MarkCodeClosure final : public Closure {
1100*795d594fSAndroid Build Coastguard Worker public:
MarkCodeClosure(JitCodeCache * code_cache,CodeCacheBitmap * bitmap,Barrier * barrier)1101*795d594fSAndroid Build Coastguard Worker MarkCodeClosure(JitCodeCache* code_cache, CodeCacheBitmap* bitmap, Barrier* barrier)
1102*795d594fSAndroid Build Coastguard Worker : code_cache_(code_cache), bitmap_(bitmap), barrier_(barrier) {}
1103*795d594fSAndroid Build Coastguard Worker
Run(Thread * thread)1104*795d594fSAndroid Build Coastguard Worker void Run(Thread* thread) override REQUIRES_SHARED(Locks::mutator_lock_) {
1105*795d594fSAndroid Build Coastguard Worker ScopedTrace trace(__PRETTY_FUNCTION__);
1106*795d594fSAndroid Build Coastguard Worker DCHECK(thread == Thread::Current() || thread->IsSuspended());
1107*795d594fSAndroid Build Coastguard Worker StackVisitor::WalkStack(
1108*795d594fSAndroid Build Coastguard Worker [&](const art::StackVisitor* stack_visitor) {
1109*795d594fSAndroid Build Coastguard Worker const OatQuickMethodHeader* method_header =
1110*795d594fSAndroid Build Coastguard Worker stack_visitor->GetCurrentOatQuickMethodHeader();
1111*795d594fSAndroid Build Coastguard Worker if (method_header == nullptr) {
1112*795d594fSAndroid Build Coastguard Worker return true;
1113*795d594fSAndroid Build Coastguard Worker }
1114*795d594fSAndroid Build Coastguard Worker const void* code = method_header->GetCode();
1115*795d594fSAndroid Build Coastguard Worker if (code_cache_->ContainsPc(code) && !code_cache_->IsInZygoteExecSpace(code)) {
1116*795d594fSAndroid Build Coastguard Worker // Use the atomic set version, as multiple threads are executing this code.
1117*795d594fSAndroid Build Coastguard Worker bitmap_->AtomicTestAndSet(FromCodeToAllocation(code));
1118*795d594fSAndroid Build Coastguard Worker }
1119*795d594fSAndroid Build Coastguard Worker return true;
1120*795d594fSAndroid Build Coastguard Worker },
1121*795d594fSAndroid Build Coastguard Worker thread,
1122*795d594fSAndroid Build Coastguard Worker /* context= */ nullptr,
1123*795d594fSAndroid Build Coastguard Worker art::StackVisitor::StackWalkKind::kSkipInlinedFrames);
1124*795d594fSAndroid Build Coastguard Worker
1125*795d594fSAndroid Build Coastguard Worker barrier_->Pass(Thread::Current());
1126*795d594fSAndroid Build Coastguard Worker }
1127*795d594fSAndroid Build Coastguard Worker
1128*795d594fSAndroid Build Coastguard Worker private:
1129*795d594fSAndroid Build Coastguard Worker JitCodeCache* const code_cache_;
1130*795d594fSAndroid Build Coastguard Worker CodeCacheBitmap* const bitmap_;
1131*795d594fSAndroid Build Coastguard Worker Barrier* const barrier_;
1132*795d594fSAndroid Build Coastguard Worker };
1133*795d594fSAndroid Build Coastguard Worker
MarkCompiledCodeOnThreadStacks(Thread * self)1134*795d594fSAndroid Build Coastguard Worker void JitCodeCache::MarkCompiledCodeOnThreadStacks(Thread* self) {
1135*795d594fSAndroid Build Coastguard Worker Barrier barrier(0);
1136*795d594fSAndroid Build Coastguard Worker size_t threads_running_checkpoint = 0;
1137*795d594fSAndroid Build Coastguard Worker MarkCodeClosure closure(this, GetLiveBitmap(), &barrier);
1138*795d594fSAndroid Build Coastguard Worker threads_running_checkpoint = Runtime::Current()->GetThreadList()->RunCheckpoint(&closure);
1139*795d594fSAndroid Build Coastguard Worker // Now that we have run our checkpoint, move to a suspended state and wait
1140*795d594fSAndroid Build Coastguard Worker // for other threads to run the checkpoint.
1141*795d594fSAndroid Build Coastguard Worker ScopedThreadSuspension sts(self, ThreadState::kSuspended);
1142*795d594fSAndroid Build Coastguard Worker if (threads_running_checkpoint != 0) {
1143*795d594fSAndroid Build Coastguard Worker barrier.Increment(self, threads_running_checkpoint);
1144*795d594fSAndroid Build Coastguard Worker }
1145*795d594fSAndroid Build Coastguard Worker }
1146*795d594fSAndroid Build Coastguard Worker
IsAtMaxCapacity() const1147*795d594fSAndroid Build Coastguard Worker bool JitCodeCache::IsAtMaxCapacity() const {
1148*795d594fSAndroid Build Coastguard Worker return private_region_.GetCurrentCapacity() == private_region_.GetMaxCapacity();
1149*795d594fSAndroid Build Coastguard Worker }
1150*795d594fSAndroid Build Coastguard Worker
IncreaseCodeCacheCapacity(Thread * self)1151*795d594fSAndroid Build Coastguard Worker void JitCodeCache::IncreaseCodeCacheCapacity(Thread* self) {
1152*795d594fSAndroid Build Coastguard Worker ScopedThreadSuspension sts(self, ThreadState::kSuspended);
1153*795d594fSAndroid Build Coastguard Worker MutexLock mu(self, *Locks::jit_lock_);
1154*795d594fSAndroid Build Coastguard Worker // Wait for a potential collection, as the size of the bitmap used by that collection
1155*795d594fSAndroid Build Coastguard Worker // is of the current capacity.
1156*795d594fSAndroid Build Coastguard Worker WaitForPotentialCollectionToComplete(self);
1157*795d594fSAndroid Build Coastguard Worker private_region_.IncreaseCodeCacheCapacity();
1158*795d594fSAndroid Build Coastguard Worker }
1159*795d594fSAndroid Build Coastguard Worker
RemoveUnmarkedCode(Thread * self)1160*795d594fSAndroid Build Coastguard Worker void JitCodeCache::RemoveUnmarkedCode(Thread* self) {
1161*795d594fSAndroid Build Coastguard Worker ScopedTrace trace(__FUNCTION__);
1162*795d594fSAndroid Build Coastguard Worker std::unordered_set<OatQuickMethodHeader*> method_headers;
1163*795d594fSAndroid Build Coastguard Worker ScopedDebugDisallowReadBarriers sddrb(self);
1164*795d594fSAndroid Build Coastguard Worker MutexLock mu(self, *Locks::jit_lock_);
1165*795d594fSAndroid Build Coastguard Worker // Iterate over all zombie code and remove entries that are not marked.
1166*795d594fSAndroid Build Coastguard Worker for (auto it = processed_zombie_code_.begin(); it != processed_zombie_code_.end();) {
1167*795d594fSAndroid Build Coastguard Worker const void* code_ptr = *it;
1168*795d594fSAndroid Build Coastguard Worker uintptr_t allocation = FromCodeToAllocation(code_ptr);
1169*795d594fSAndroid Build Coastguard Worker DCHECK(!IsInZygoteExecSpace(code_ptr));
1170*795d594fSAndroid Build Coastguard Worker if (GetLiveBitmap()->Test(allocation)) {
1171*795d594fSAndroid Build Coastguard Worker ++it;
1172*795d594fSAndroid Build Coastguard Worker } else {
1173*795d594fSAndroid Build Coastguard Worker OatQuickMethodHeader* header = OatQuickMethodHeader::FromCodePointer(code_ptr);
1174*795d594fSAndroid Build Coastguard Worker method_headers.insert(header);
1175*795d594fSAndroid Build Coastguard Worker {
1176*795d594fSAndroid Build Coastguard Worker WriterMutexLock mu2(self, *Locks::jit_mutator_lock_);
1177*795d594fSAndroid Build Coastguard Worker auto method_it = method_code_map_.find(header->GetCode());
1178*795d594fSAndroid Build Coastguard Worker
1179*795d594fSAndroid Build Coastguard Worker if (method_it != method_code_map_.end()) {
1180*795d594fSAndroid Build Coastguard Worker ArtMethod* method = method_it->second;
1181*795d594fSAndroid Build Coastguard Worker auto code_ptrs_it = method_code_map_reversed_.find(method);
1182*795d594fSAndroid Build Coastguard Worker
1183*795d594fSAndroid Build Coastguard Worker if (code_ptrs_it != method_code_map_reversed_.end()) {
1184*795d594fSAndroid Build Coastguard Worker std::vector<const void*>& code_ptrs = code_ptrs_it->second;
1185*795d594fSAndroid Build Coastguard Worker RemoveElement(code_ptrs, code_ptr);
1186*795d594fSAndroid Build Coastguard Worker
1187*795d594fSAndroid Build Coastguard Worker if (code_ptrs.empty()) {
1188*795d594fSAndroid Build Coastguard Worker method_code_map_reversed_.erase(code_ptrs_it);
1189*795d594fSAndroid Build Coastguard Worker }
1190*795d594fSAndroid Build Coastguard Worker }
1191*795d594fSAndroid Build Coastguard Worker }
1192*795d594fSAndroid Build Coastguard Worker
1193*795d594fSAndroid Build Coastguard Worker method_code_map_.erase(header->GetCode());
1194*795d594fSAndroid Build Coastguard Worker }
1195*795d594fSAndroid Build Coastguard Worker VLOG(jit) << "JIT removed " << *it;
1196*795d594fSAndroid Build Coastguard Worker it = processed_zombie_code_.erase(it);
1197*795d594fSAndroid Build Coastguard Worker }
1198*795d594fSAndroid Build Coastguard Worker }
1199*795d594fSAndroid Build Coastguard Worker for (auto it = processed_zombie_jni_code_.begin(); it != processed_zombie_jni_code_.end();) {
1200*795d594fSAndroid Build Coastguard Worker WriterMutexLock mu2(self, *Locks::jit_mutator_lock_);
1201*795d594fSAndroid Build Coastguard Worker ArtMethod* method = *it;
1202*795d594fSAndroid Build Coastguard Worker auto stub = jni_stubs_map_.find(JniStubKey(method));
1203*795d594fSAndroid Build Coastguard Worker DCHECK(stub != jni_stubs_map_.end()) << method->PrettyMethod();
1204*795d594fSAndroid Build Coastguard Worker JniStubData& data = stub->second;
1205*795d594fSAndroid Build Coastguard Worker DCHECK(data.IsCompiled());
1206*795d594fSAndroid Build Coastguard Worker DCHECK(ContainsElement(data.GetMethods(), method));
1207*795d594fSAndroid Build Coastguard Worker if (!GetLiveBitmap()->Test(FromCodeToAllocation(data.GetCode()))) {
1208*795d594fSAndroid Build Coastguard Worker data.RemoveMethod(method);
1209*795d594fSAndroid Build Coastguard Worker if (data.GetMethods().empty()) {
1210*795d594fSAndroid Build Coastguard Worker OatQuickMethodHeader* header = OatQuickMethodHeader::FromCodePointer(data.GetCode());
1211*795d594fSAndroid Build Coastguard Worker method_headers.insert(header);
1212*795d594fSAndroid Build Coastguard Worker CHECK(ContainsPc(header));
1213*795d594fSAndroid Build Coastguard Worker VLOG(jit) << "JIT removed native code of" << method->PrettyMethod();
1214*795d594fSAndroid Build Coastguard Worker jni_stubs_map_.erase(stub);
1215*795d594fSAndroid Build Coastguard Worker } else {
1216*795d594fSAndroid Build Coastguard Worker stub->first.UpdateShorty(stub->second.GetMethods().front());
1217*795d594fSAndroid Build Coastguard Worker }
1218*795d594fSAndroid Build Coastguard Worker it = processed_zombie_jni_code_.erase(it);
1219*795d594fSAndroid Build Coastguard Worker } else {
1220*795d594fSAndroid Build Coastguard Worker ++it;
1221*795d594fSAndroid Build Coastguard Worker }
1222*795d594fSAndroid Build Coastguard Worker }
1223*795d594fSAndroid Build Coastguard Worker FreeAllMethodHeaders(method_headers);
1224*795d594fSAndroid Build Coastguard Worker }
1225*795d594fSAndroid Build Coastguard Worker
1226*795d594fSAndroid Build Coastguard Worker class JitGcTask final : public Task {
1227*795d594fSAndroid Build Coastguard Worker public:
JitGcTask()1228*795d594fSAndroid Build Coastguard Worker JitGcTask() {}
1229*795d594fSAndroid Build Coastguard Worker
Run(Thread * self)1230*795d594fSAndroid Build Coastguard Worker void Run(Thread* self) override {
1231*795d594fSAndroid Build Coastguard Worker Runtime::Current()->GetJit()->GetCodeCache()->DoCollection(self);
1232*795d594fSAndroid Build Coastguard Worker }
1233*795d594fSAndroid Build Coastguard Worker
Finalize()1234*795d594fSAndroid Build Coastguard Worker void Finalize() override {
1235*795d594fSAndroid Build Coastguard Worker delete this;
1236*795d594fSAndroid Build Coastguard Worker }
1237*795d594fSAndroid Build Coastguard Worker };
1238*795d594fSAndroid Build Coastguard Worker
AddZombieCode(ArtMethod * method,const void * entry_point)1239*795d594fSAndroid Build Coastguard Worker void JitCodeCache::AddZombieCode(ArtMethod* method, const void* entry_point) {
1240*795d594fSAndroid Build Coastguard Worker CHECK(ContainsPc(entry_point));
1241*795d594fSAndroid Build Coastguard Worker CHECK(method->IsNative() || (method->GetEntryPointFromQuickCompiledCode() != entry_point));
1242*795d594fSAndroid Build Coastguard Worker const void* code_ptr = OatQuickMethodHeader::FromEntryPoint(entry_point)->GetCode();
1243*795d594fSAndroid Build Coastguard Worker if (!IsInZygoteExecSpace(code_ptr)) {
1244*795d594fSAndroid Build Coastguard Worker Thread* self = Thread::Current();
1245*795d594fSAndroid Build Coastguard Worker if (Locks::jit_mutator_lock_->IsExclusiveHeld(self)) {
1246*795d594fSAndroid Build Coastguard Worker AddZombieCodeInternal(method, code_ptr);
1247*795d594fSAndroid Build Coastguard Worker } else {
1248*795d594fSAndroid Build Coastguard Worker WriterMutexLock mu(self, *Locks::jit_mutator_lock_);
1249*795d594fSAndroid Build Coastguard Worker AddZombieCodeInternal(method, code_ptr);
1250*795d594fSAndroid Build Coastguard Worker }
1251*795d594fSAndroid Build Coastguard Worker }
1252*795d594fSAndroid Build Coastguard Worker }
1253*795d594fSAndroid Build Coastguard Worker
1254*795d594fSAndroid Build Coastguard Worker
AddZombieCodeInternal(ArtMethod * method,const void * code_ptr)1255*795d594fSAndroid Build Coastguard Worker void JitCodeCache::AddZombieCodeInternal(ArtMethod* method, const void* code_ptr) {
1256*795d594fSAndroid Build Coastguard Worker if (method->IsNative()) {
1257*795d594fSAndroid Build Coastguard Worker if (kIsDebugBuild) {
1258*795d594fSAndroid Build Coastguard Worker auto it = jni_stubs_map_.find(JniStubKey(method));
1259*795d594fSAndroid Build Coastguard Worker CHECK(it != jni_stubs_map_.end()) << method->PrettyMethod();
1260*795d594fSAndroid Build Coastguard Worker CHECK(it->second.IsCompiled()) << method->PrettyMethod();
1261*795d594fSAndroid Build Coastguard Worker CHECK_EQ(it->second.GetCode(), code_ptr) << method->PrettyMethod();
1262*795d594fSAndroid Build Coastguard Worker CHECK(ContainsElement(it->second.GetMethods(), method)) << method->PrettyMethod();
1263*795d594fSAndroid Build Coastguard Worker }
1264*795d594fSAndroid Build Coastguard Worker zombie_jni_code_.insert(method);
1265*795d594fSAndroid Build Coastguard Worker } else {
1266*795d594fSAndroid Build Coastguard Worker CHECK(!ContainsElement(zombie_code_, code_ptr));
1267*795d594fSAndroid Build Coastguard Worker zombie_code_.insert(code_ptr);
1268*795d594fSAndroid Build Coastguard Worker }
1269*795d594fSAndroid Build Coastguard Worker
1270*795d594fSAndroid Build Coastguard Worker // Arbitrary threshold of number of zombie code before doing a GC.
1271*795d594fSAndroid Build Coastguard Worker static constexpr size_t kNumberOfZombieCodeThreshold = kIsDebugBuild ? 1 : 1000;
1272*795d594fSAndroid Build Coastguard Worker size_t number_of_code_to_delete =
1273*795d594fSAndroid Build Coastguard Worker zombie_code_.size() + zombie_jni_code_.size() + osr_code_map_.size();
1274*795d594fSAndroid Build Coastguard Worker if (number_of_code_to_delete >= kNumberOfZombieCodeThreshold) {
1275*795d594fSAndroid Build Coastguard Worker JitThreadPool* pool = Runtime::Current()->GetJit()->GetThreadPool();
1276*795d594fSAndroid Build Coastguard Worker if (pool != nullptr && !std::atomic_exchange_explicit(&gc_task_scheduled_,
1277*795d594fSAndroid Build Coastguard Worker true,
1278*795d594fSAndroid Build Coastguard Worker std::memory_order_relaxed)) {
1279*795d594fSAndroid Build Coastguard Worker pool->AddTask(Thread::Current(), new JitGcTask());
1280*795d594fSAndroid Build Coastguard Worker }
1281*795d594fSAndroid Build Coastguard Worker }
1282*795d594fSAndroid Build Coastguard Worker }
1283*795d594fSAndroid Build Coastguard Worker
GetGarbageCollectCode()1284*795d594fSAndroid Build Coastguard Worker bool JitCodeCache::GetGarbageCollectCode() {
1285*795d594fSAndroid Build Coastguard Worker MutexLock mu(Thread::Current(), *Locks::jit_lock_);
1286*795d594fSAndroid Build Coastguard Worker return garbage_collect_code_;
1287*795d594fSAndroid Build Coastguard Worker }
1288*795d594fSAndroid Build Coastguard Worker
SetGarbageCollectCode(bool value)1289*795d594fSAndroid Build Coastguard Worker void JitCodeCache::SetGarbageCollectCode(bool value) {
1290*795d594fSAndroid Build Coastguard Worker Thread* self = Thread::Current();
1291*795d594fSAndroid Build Coastguard Worker MutexLock mu(self, *Locks::jit_lock_);
1292*795d594fSAndroid Build Coastguard Worker // Update the flag while holding the lock to ensure no thread will try to GC.
1293*795d594fSAndroid Build Coastguard Worker garbage_collect_code_ = value;
1294*795d594fSAndroid Build Coastguard Worker }
1295*795d594fSAndroid Build Coastguard Worker
GetProfilingInfo(ArtMethod * method,Thread * self)1296*795d594fSAndroid Build Coastguard Worker ProfilingInfo* JitCodeCache::GetProfilingInfo(ArtMethod* method, Thread* self) {
1297*795d594fSAndroid Build Coastguard Worker ScopedDebugDisallowReadBarriers sddrb(self);
1298*795d594fSAndroid Build Coastguard Worker MutexLock mu(self, *Locks::jit_lock_);
1299*795d594fSAndroid Build Coastguard Worker auto it = profiling_infos_.find(method);
1300*795d594fSAndroid Build Coastguard Worker if (it == profiling_infos_.end()) {
1301*795d594fSAndroid Build Coastguard Worker return nullptr;
1302*795d594fSAndroid Build Coastguard Worker }
1303*795d594fSAndroid Build Coastguard Worker return it->second;
1304*795d594fSAndroid Build Coastguard Worker }
1305*795d594fSAndroid Build Coastguard Worker
MaybeUpdateInlineCache(ArtMethod * method,uint32_t dex_pc,ObjPtr<mirror::Class> cls,Thread * self)1306*795d594fSAndroid Build Coastguard Worker void JitCodeCache::MaybeUpdateInlineCache(ArtMethod* method,
1307*795d594fSAndroid Build Coastguard Worker uint32_t dex_pc,
1308*795d594fSAndroid Build Coastguard Worker ObjPtr<mirror::Class> cls,
1309*795d594fSAndroid Build Coastguard Worker Thread* self) {
1310*795d594fSAndroid Build Coastguard Worker ScopedDebugDisallowReadBarriers sddrb(self);
1311*795d594fSAndroid Build Coastguard Worker MutexLock mu(self, *Locks::jit_lock_);
1312*795d594fSAndroid Build Coastguard Worker auto it = profiling_infos_.find(method);
1313*795d594fSAndroid Build Coastguard Worker if (it == profiling_infos_.end()) {
1314*795d594fSAndroid Build Coastguard Worker return;
1315*795d594fSAndroid Build Coastguard Worker }
1316*795d594fSAndroid Build Coastguard Worker ProfilingInfo* info = it->second;
1317*795d594fSAndroid Build Coastguard Worker ScopedAssertNoThreadSuspension sants("ProfilingInfo");
1318*795d594fSAndroid Build Coastguard Worker info->AddInvokeInfo(dex_pc, cls.Ptr());
1319*795d594fSAndroid Build Coastguard Worker }
1320*795d594fSAndroid Build Coastguard Worker
DoCollection(Thread * self)1321*795d594fSAndroid Build Coastguard Worker void JitCodeCache::DoCollection(Thread* self) {
1322*795d594fSAndroid Build Coastguard Worker ScopedTrace trace(__FUNCTION__);
1323*795d594fSAndroid Build Coastguard Worker
1324*795d594fSAndroid Build Coastguard Worker {
1325*795d594fSAndroid Build Coastguard Worker ScopedDebugDisallowReadBarriers sddrb(self);
1326*795d594fSAndroid Build Coastguard Worker MutexLock mu(self, *Locks::jit_lock_);
1327*795d594fSAndroid Build Coastguard Worker if (!garbage_collect_code_) {
1328*795d594fSAndroid Build Coastguard Worker return;
1329*795d594fSAndroid Build Coastguard Worker } else if (WaitForPotentialCollectionToComplete(self)) {
1330*795d594fSAndroid Build Coastguard Worker return;
1331*795d594fSAndroid Build Coastguard Worker }
1332*795d594fSAndroid Build Coastguard Worker collection_in_progress_ = true;
1333*795d594fSAndroid Build Coastguard Worker number_of_collections_++;
1334*795d594fSAndroid Build Coastguard Worker live_bitmap_.reset(CodeCacheBitmap::Create(
1335*795d594fSAndroid Build Coastguard Worker "code-cache-bitmap",
1336*795d594fSAndroid Build Coastguard Worker reinterpret_cast<uintptr_t>(private_region_.GetExecPages()->Begin()),
1337*795d594fSAndroid Build Coastguard Worker reinterpret_cast<uintptr_t>(
1338*795d594fSAndroid Build Coastguard Worker private_region_.GetExecPages()->Begin() + private_region_.GetCurrentCapacity() / 2)));
1339*795d594fSAndroid Build Coastguard Worker {
1340*795d594fSAndroid Build Coastguard Worker WriterMutexLock mu2(self, *Locks::jit_mutator_lock_);
1341*795d594fSAndroid Build Coastguard Worker processed_zombie_code_.insert(zombie_code_.begin(), zombie_code_.end());
1342*795d594fSAndroid Build Coastguard Worker zombie_code_.clear();
1343*795d594fSAndroid Build Coastguard Worker processed_zombie_jni_code_.insert(zombie_jni_code_.begin(), zombie_jni_code_.end());
1344*795d594fSAndroid Build Coastguard Worker zombie_jni_code_.clear();
1345*795d594fSAndroid Build Coastguard Worker // Empty osr method map, as osr compiled code will be deleted (except the ones
1346*795d594fSAndroid Build Coastguard Worker // on thread stacks).
1347*795d594fSAndroid Build Coastguard Worker for (auto it = osr_code_map_.begin(); it != osr_code_map_.end(); ++it) {
1348*795d594fSAndroid Build Coastguard Worker processed_zombie_code_.insert(it->second);
1349*795d594fSAndroid Build Coastguard Worker }
1350*795d594fSAndroid Build Coastguard Worker osr_code_map_.clear();
1351*795d594fSAndroid Build Coastguard Worker }
1352*795d594fSAndroid Build Coastguard Worker }
1353*795d594fSAndroid Build Coastguard Worker TimingLogger logger("JIT code cache timing logger", true, VLOG_IS_ON(jit));
1354*795d594fSAndroid Build Coastguard Worker {
1355*795d594fSAndroid Build Coastguard Worker TimingLogger::ScopedTiming st("Code cache collection", &logger);
1356*795d594fSAndroid Build Coastguard Worker
1357*795d594fSAndroid Build Coastguard Worker {
1358*795d594fSAndroid Build Coastguard Worker ScopedObjectAccess soa(self);
1359*795d594fSAndroid Build Coastguard Worker // Run a checkpoint on all threads to mark the JIT compiled code they are running.
1360*795d594fSAndroid Build Coastguard Worker MarkCompiledCodeOnThreadStacks(self);
1361*795d594fSAndroid Build Coastguard Worker
1362*795d594fSAndroid Build Coastguard Worker // Remove zombie code which hasn't been marked.
1363*795d594fSAndroid Build Coastguard Worker RemoveUnmarkedCode(self);
1364*795d594fSAndroid Build Coastguard Worker }
1365*795d594fSAndroid Build Coastguard Worker
1366*795d594fSAndroid Build Coastguard Worker gc_task_scheduled_ = false;
1367*795d594fSAndroid Build Coastguard Worker MutexLock mu(self, *Locks::jit_lock_);
1368*795d594fSAndroid Build Coastguard Worker live_bitmap_.reset(nullptr);
1369*795d594fSAndroid Build Coastguard Worker collection_in_progress_ = false;
1370*795d594fSAndroid Build Coastguard Worker lock_cond_.Broadcast(self);
1371*795d594fSAndroid Build Coastguard Worker }
1372*795d594fSAndroid Build Coastguard Worker
1373*795d594fSAndroid Build Coastguard Worker Runtime::Current()->GetJit()->AddTimingLogger(logger);
1374*795d594fSAndroid Build Coastguard Worker }
1375*795d594fSAndroid Build Coastguard Worker
LookupMethodHeader(uintptr_t pc,ArtMethod * method)1376*795d594fSAndroid Build Coastguard Worker OatQuickMethodHeader* JitCodeCache::LookupMethodHeader(uintptr_t pc, ArtMethod* method) {
1377*795d594fSAndroid Build Coastguard Worker static_assert(kRuntimeQuickCodeISA != InstructionSet::kThumb2, "kThumb2 cannot be a runtime ISA");
1378*795d594fSAndroid Build Coastguard Worker const void* pc_ptr = reinterpret_cast<const void*>(pc);
1379*795d594fSAndroid Build Coastguard Worker if (!ContainsPc(pc_ptr)) {
1380*795d594fSAndroid Build Coastguard Worker return nullptr;
1381*795d594fSAndroid Build Coastguard Worker }
1382*795d594fSAndroid Build Coastguard Worker
1383*795d594fSAndroid Build Coastguard Worker if (!kIsDebugBuild) {
1384*795d594fSAndroid Build Coastguard Worker // Called with null `method` only from MarkCodeClosure::Run() in debug build.
1385*795d594fSAndroid Build Coastguard Worker CHECK(method != nullptr);
1386*795d594fSAndroid Build Coastguard Worker }
1387*795d594fSAndroid Build Coastguard Worker
1388*795d594fSAndroid Build Coastguard Worker Thread* self = Thread::Current();
1389*795d594fSAndroid Build Coastguard Worker ScopedDebugDisallowReadBarriers sddrb(self);
1390*795d594fSAndroid Build Coastguard Worker OatQuickMethodHeader* method_header = nullptr;
1391*795d594fSAndroid Build Coastguard Worker ArtMethod* found_method = nullptr; // Only for DCHECK(), not for JNI stubs.
1392*795d594fSAndroid Build Coastguard Worker if (method != nullptr && UNLIKELY(method->IsNative())) {
1393*795d594fSAndroid Build Coastguard Worker ReaderMutexLock mu(self, *Locks::jit_mutator_lock_);
1394*795d594fSAndroid Build Coastguard Worker auto it = jni_stubs_map_.find(JniStubKey(method));
1395*795d594fSAndroid Build Coastguard Worker if (it == jni_stubs_map_.end()) {
1396*795d594fSAndroid Build Coastguard Worker return nullptr;
1397*795d594fSAndroid Build Coastguard Worker }
1398*795d594fSAndroid Build Coastguard Worker if (!ContainsElement(it->second.GetMethods(), method)) {
1399*795d594fSAndroid Build Coastguard Worker DCHECK(!OatQuickMethodHeader::FromCodePointer(it->second.GetCode())->Contains(pc))
1400*795d594fSAndroid Build Coastguard Worker << "Method missing from stub map, but pc executing the method points to the stub."
1401*795d594fSAndroid Build Coastguard Worker << " method= " << method->PrettyMethod()
1402*795d594fSAndroid Build Coastguard Worker << " pc= " << std::hex << pc;
1403*795d594fSAndroid Build Coastguard Worker return nullptr;
1404*795d594fSAndroid Build Coastguard Worker }
1405*795d594fSAndroid Build Coastguard Worker const void* code_ptr = it->second.GetCode();
1406*795d594fSAndroid Build Coastguard Worker method_header = OatQuickMethodHeader::FromCodePointer(code_ptr);
1407*795d594fSAndroid Build Coastguard Worker if (!method_header->Contains(pc)) {
1408*795d594fSAndroid Build Coastguard Worker return nullptr;
1409*795d594fSAndroid Build Coastguard Worker }
1410*795d594fSAndroid Build Coastguard Worker } else {
1411*795d594fSAndroid Build Coastguard Worker if (shared_region_.IsInExecSpace(pc_ptr)) {
1412*795d594fSAndroid Build Coastguard Worker const void* code_ptr = zygote_map_.GetCodeFor(method, pc);
1413*795d594fSAndroid Build Coastguard Worker if (code_ptr != nullptr) {
1414*795d594fSAndroid Build Coastguard Worker return OatQuickMethodHeader::FromCodePointer(code_ptr);
1415*795d594fSAndroid Build Coastguard Worker }
1416*795d594fSAndroid Build Coastguard Worker }
1417*795d594fSAndroid Build Coastguard Worker {
1418*795d594fSAndroid Build Coastguard Worker ReaderMutexLock mu(self, *Locks::jit_mutator_lock_);
1419*795d594fSAndroid Build Coastguard Worker auto it = method_code_map_.lower_bound(pc_ptr);
1420*795d594fSAndroid Build Coastguard Worker if ((it == method_code_map_.end() || it->first != pc_ptr) &&
1421*795d594fSAndroid Build Coastguard Worker it != method_code_map_.begin()) {
1422*795d594fSAndroid Build Coastguard Worker --it;
1423*795d594fSAndroid Build Coastguard Worker }
1424*795d594fSAndroid Build Coastguard Worker if (it != method_code_map_.end()) {
1425*795d594fSAndroid Build Coastguard Worker const void* code_ptr = it->first;
1426*795d594fSAndroid Build Coastguard Worker if (OatQuickMethodHeader::FromCodePointer(code_ptr)->Contains(pc)) {
1427*795d594fSAndroid Build Coastguard Worker method_header = OatQuickMethodHeader::FromCodePointer(code_ptr);
1428*795d594fSAndroid Build Coastguard Worker found_method = it->second;
1429*795d594fSAndroid Build Coastguard Worker }
1430*795d594fSAndroid Build Coastguard Worker }
1431*795d594fSAndroid Build Coastguard Worker }
1432*795d594fSAndroid Build Coastguard Worker if (method_header == nullptr && method == nullptr) {
1433*795d594fSAndroid Build Coastguard Worker ReaderMutexLock mu(self, *Locks::jit_mutator_lock_);
1434*795d594fSAndroid Build Coastguard Worker // Scan all compiled JNI stubs as well. This slow search is used only
1435*795d594fSAndroid Build Coastguard Worker // for checks in debug build, for release builds the `method` is not null.
1436*795d594fSAndroid Build Coastguard Worker for (auto&& entry : jni_stubs_map_) {
1437*795d594fSAndroid Build Coastguard Worker const JniStubData& data = entry.second;
1438*795d594fSAndroid Build Coastguard Worker if (data.IsCompiled() &&
1439*795d594fSAndroid Build Coastguard Worker OatQuickMethodHeader::FromCodePointer(data.GetCode())->Contains(pc)) {
1440*795d594fSAndroid Build Coastguard Worker method_header = OatQuickMethodHeader::FromCodePointer(data.GetCode());
1441*795d594fSAndroid Build Coastguard Worker }
1442*795d594fSAndroid Build Coastguard Worker }
1443*795d594fSAndroid Build Coastguard Worker }
1444*795d594fSAndroid Build Coastguard Worker if (method_header == nullptr) {
1445*795d594fSAndroid Build Coastguard Worker return nullptr;
1446*795d594fSAndroid Build Coastguard Worker }
1447*795d594fSAndroid Build Coastguard Worker }
1448*795d594fSAndroid Build Coastguard Worker
1449*795d594fSAndroid Build Coastguard Worker if (kIsDebugBuild && method != nullptr && !method->IsNative()) {
1450*795d594fSAndroid Build Coastguard Worker DCHECK_EQ(found_method, method)
1451*795d594fSAndroid Build Coastguard Worker << ArtMethod::PrettyMethod(method) << " "
1452*795d594fSAndroid Build Coastguard Worker << ArtMethod::PrettyMethod(found_method) << " "
1453*795d594fSAndroid Build Coastguard Worker << std::hex << pc;
1454*795d594fSAndroid Build Coastguard Worker }
1455*795d594fSAndroid Build Coastguard Worker return method_header;
1456*795d594fSAndroid Build Coastguard Worker }
1457*795d594fSAndroid Build Coastguard Worker
LookupOsrMethodHeader(ArtMethod * method)1458*795d594fSAndroid Build Coastguard Worker OatQuickMethodHeader* JitCodeCache::LookupOsrMethodHeader(ArtMethod* method) {
1459*795d594fSAndroid Build Coastguard Worker Thread* self = Thread::Current();
1460*795d594fSAndroid Build Coastguard Worker ScopedDebugDisallowReadBarriers sddrb(self);
1461*795d594fSAndroid Build Coastguard Worker ReaderMutexLock mu(self, *Locks::jit_mutator_lock_);
1462*795d594fSAndroid Build Coastguard Worker auto it = osr_code_map_.find(method);
1463*795d594fSAndroid Build Coastguard Worker if (it == osr_code_map_.end()) {
1464*795d594fSAndroid Build Coastguard Worker return nullptr;
1465*795d594fSAndroid Build Coastguard Worker }
1466*795d594fSAndroid Build Coastguard Worker return OatQuickMethodHeader::FromCodePointer(it->second);
1467*795d594fSAndroid Build Coastguard Worker }
1468*795d594fSAndroid Build Coastguard Worker
AddProfilingInfo(Thread * self,ArtMethod * method,const std::vector<uint32_t> & inline_cache_entries,const std::vector<uint32_t> & branch_cache_entries)1469*795d594fSAndroid Build Coastguard Worker ProfilingInfo* JitCodeCache::AddProfilingInfo(Thread* self,
1470*795d594fSAndroid Build Coastguard Worker ArtMethod* method,
1471*795d594fSAndroid Build Coastguard Worker const std::vector<uint32_t>& inline_cache_entries,
1472*795d594fSAndroid Build Coastguard Worker const std::vector<uint32_t>& branch_cache_entries) {
1473*795d594fSAndroid Build Coastguard Worker DCHECK(CanAllocateProfilingInfo());
1474*795d594fSAndroid Build Coastguard Worker ProfilingInfo* info = nullptr;
1475*795d594fSAndroid Build Coastguard Worker {
1476*795d594fSAndroid Build Coastguard Worker MutexLock mu(self, *Locks::jit_lock_);
1477*795d594fSAndroid Build Coastguard Worker info = AddProfilingInfoInternal(self, method, inline_cache_entries, branch_cache_entries);
1478*795d594fSAndroid Build Coastguard Worker }
1479*795d594fSAndroid Build Coastguard Worker
1480*795d594fSAndroid Build Coastguard Worker if (info == nullptr) {
1481*795d594fSAndroid Build Coastguard Worker IncreaseCodeCacheCapacity(self);
1482*795d594fSAndroid Build Coastguard Worker MutexLock mu(self, *Locks::jit_lock_);
1483*795d594fSAndroid Build Coastguard Worker info = AddProfilingInfoInternal(self, method, inline_cache_entries, branch_cache_entries);
1484*795d594fSAndroid Build Coastguard Worker }
1485*795d594fSAndroid Build Coastguard Worker return info;
1486*795d594fSAndroid Build Coastguard Worker }
1487*795d594fSAndroid Build Coastguard Worker
AddProfilingInfoInternal(Thread * self,ArtMethod * method,const std::vector<uint32_t> & inline_cache_entries,const std::vector<uint32_t> & branch_cache_entries)1488*795d594fSAndroid Build Coastguard Worker ProfilingInfo* JitCodeCache::AddProfilingInfoInternal(
1489*795d594fSAndroid Build Coastguard Worker Thread* self,
1490*795d594fSAndroid Build Coastguard Worker ArtMethod* method,
1491*795d594fSAndroid Build Coastguard Worker const std::vector<uint32_t>& inline_cache_entries,
1492*795d594fSAndroid Build Coastguard Worker const std::vector<uint32_t>& branch_cache_entries) {
1493*795d594fSAndroid Build Coastguard Worker ScopedDebugDisallowReadBarriers sddrb(self);
1494*795d594fSAndroid Build Coastguard Worker // Check whether some other thread has concurrently created it.
1495*795d594fSAndroid Build Coastguard Worker auto it = profiling_infos_.find(method);
1496*795d594fSAndroid Build Coastguard Worker if (it != profiling_infos_.end()) {
1497*795d594fSAndroid Build Coastguard Worker return it->second;
1498*795d594fSAndroid Build Coastguard Worker }
1499*795d594fSAndroid Build Coastguard Worker
1500*795d594fSAndroid Build Coastguard Worker size_t profile_info_size =
1501*795d594fSAndroid Build Coastguard Worker ProfilingInfo::ComputeSize(inline_cache_entries.size(), branch_cache_entries.size());
1502*795d594fSAndroid Build Coastguard Worker
1503*795d594fSAndroid Build Coastguard Worker const uint8_t* data = private_region_.AllocateData(profile_info_size);
1504*795d594fSAndroid Build Coastguard Worker if (data == nullptr) {
1505*795d594fSAndroid Build Coastguard Worker return nullptr;
1506*795d594fSAndroid Build Coastguard Worker }
1507*795d594fSAndroid Build Coastguard Worker uint8_t* writable_data = private_region_.GetWritableDataAddress(data);
1508*795d594fSAndroid Build Coastguard Worker ProfilingInfo* info =
1509*795d594fSAndroid Build Coastguard Worker new (writable_data) ProfilingInfo(method, inline_cache_entries, branch_cache_entries);
1510*795d594fSAndroid Build Coastguard Worker
1511*795d594fSAndroid Build Coastguard Worker profiling_infos_.Put(method, info);
1512*795d594fSAndroid Build Coastguard Worker histogram_profiling_info_memory_use_.AddValue(profile_info_size);
1513*795d594fSAndroid Build Coastguard Worker return info;
1514*795d594fSAndroid Build Coastguard Worker }
1515*795d594fSAndroid Build Coastguard Worker
MoreCore(const void * mspace,intptr_t increment)1516*795d594fSAndroid Build Coastguard Worker void* JitCodeCache::MoreCore(const void* mspace, intptr_t increment) {
1517*795d594fSAndroid Build Coastguard Worker return shared_region_.OwnsSpace(mspace)
1518*795d594fSAndroid Build Coastguard Worker ? shared_region_.MoreCore(mspace, increment)
1519*795d594fSAndroid Build Coastguard Worker : private_region_.MoreCore(mspace, increment);
1520*795d594fSAndroid Build Coastguard Worker }
1521*795d594fSAndroid Build Coastguard Worker
GetProfiledMethods(const std::set<std::string> & dex_base_locations,std::vector<ProfileMethodInfo> & methods,uint16_t inline_cache_threshold)1522*795d594fSAndroid Build Coastguard Worker void JitCodeCache::GetProfiledMethods(const std::set<std::string>& dex_base_locations,
1523*795d594fSAndroid Build Coastguard Worker std::vector<ProfileMethodInfo>& methods,
1524*795d594fSAndroid Build Coastguard Worker uint16_t inline_cache_threshold) {
1525*795d594fSAndroid Build Coastguard Worker ScopedTrace trace(__FUNCTION__);
1526*795d594fSAndroid Build Coastguard Worker Thread* self = Thread::Current();
1527*795d594fSAndroid Build Coastguard Worker
1528*795d594fSAndroid Build Coastguard Worker // Preserve class loaders to prevent unloading while we're processing
1529*795d594fSAndroid Build Coastguard Worker // ArtMethods.
1530*795d594fSAndroid Build Coastguard Worker VariableSizedHandleScope handles(self);
1531*795d594fSAndroid Build Coastguard Worker Runtime::Current()->GetClassLinker()->GetClassLoaders(self, &handles);
1532*795d594fSAndroid Build Coastguard Worker
1533*795d594fSAndroid Build Coastguard Worker // Wait for any GC to be complete, to prevent looking at ArtMethods whose
1534*795d594fSAndroid Build Coastguard Worker // class loader is being deleted. Since we remain runnable, another new GC
1535*795d594fSAndroid Build Coastguard Worker // can't get far.
1536*795d594fSAndroid Build Coastguard Worker Runtime::Current()->GetHeap()->WaitForGcToComplete(gc::kGcCauseProfileSaver, self);
1537*795d594fSAndroid Build Coastguard Worker
1538*795d594fSAndroid Build Coastguard Worker // We'll be looking at inline caches, so ensure they are accessible.
1539*795d594fSAndroid Build Coastguard Worker WaitUntilInlineCacheAccessible(self);
1540*795d594fSAndroid Build Coastguard Worker
1541*795d594fSAndroid Build Coastguard Worker SafeMap<ArtMethod*, ProfilingInfo*> profiling_infos;
1542*795d594fSAndroid Build Coastguard Worker std::vector<ArtMethod*> copies;
1543*795d594fSAndroid Build Coastguard Worker {
1544*795d594fSAndroid Build Coastguard Worker MutexLock mu(self, *Locks::jit_lock_);
1545*795d594fSAndroid Build Coastguard Worker profiling_infos = profiling_infos_;
1546*795d594fSAndroid Build Coastguard Worker ReaderMutexLock mu2(self, *Locks::jit_mutator_lock_);
1547*795d594fSAndroid Build Coastguard Worker for (const auto& entry : method_code_map_) {
1548*795d594fSAndroid Build Coastguard Worker copies.push_back(entry.second);
1549*795d594fSAndroid Build Coastguard Worker }
1550*795d594fSAndroid Build Coastguard Worker }
1551*795d594fSAndroid Build Coastguard Worker for (ArtMethod* method : copies) {
1552*795d594fSAndroid Build Coastguard Worker auto it = profiling_infos.find(method);
1553*795d594fSAndroid Build Coastguard Worker ProfilingInfo* info = (it == profiling_infos.end()) ? nullptr : it->second;
1554*795d594fSAndroid Build Coastguard Worker const DexFile* dex_file = method->GetDexFile();
1555*795d594fSAndroid Build Coastguard Worker const std::string base_location = DexFileLoader::GetBaseLocation(dex_file->GetLocation());
1556*795d594fSAndroid Build Coastguard Worker if (!ContainsElement(dex_base_locations, base_location)) {
1557*795d594fSAndroid Build Coastguard Worker // Skip dex files which are not profiled.
1558*795d594fSAndroid Build Coastguard Worker continue;
1559*795d594fSAndroid Build Coastguard Worker }
1560*795d594fSAndroid Build Coastguard Worker std::vector<ProfileMethodInfo::ProfileInlineCache> inline_caches;
1561*795d594fSAndroid Build Coastguard Worker
1562*795d594fSAndroid Build Coastguard Worker if (info != nullptr) {
1563*795d594fSAndroid Build Coastguard Worker // If the method is still baseline compiled and doesn't meet the inline cache threshold, don't
1564*795d594fSAndroid Build Coastguard Worker // save the inline caches because they might be incomplete.
1565*795d594fSAndroid Build Coastguard Worker // Although we don't deoptimize for incomplete inline caches in AOT-compiled code, inlining
1566*795d594fSAndroid Build Coastguard Worker // leads to larger generated code.
1567*795d594fSAndroid Build Coastguard Worker // If the inline cache is empty the compiler will generate a regular invoke virtual/interface.
1568*795d594fSAndroid Build Coastguard Worker const void* entry_point = method->GetEntryPointFromQuickCompiledCode();
1569*795d594fSAndroid Build Coastguard Worker if (ContainsPc(entry_point) &&
1570*795d594fSAndroid Build Coastguard Worker CodeInfo::IsBaseline(
1571*795d594fSAndroid Build Coastguard Worker OatQuickMethodHeader::FromEntryPoint(entry_point)->GetOptimizedCodeInfoPtr()) &&
1572*795d594fSAndroid Build Coastguard Worker (ProfilingInfo::GetOptimizeThreshold() - info->GetBaselineHotnessCount()) <
1573*795d594fSAndroid Build Coastguard Worker inline_cache_threshold) {
1574*795d594fSAndroid Build Coastguard Worker methods.emplace_back(/*ProfileMethodInfo*/
1575*795d594fSAndroid Build Coastguard Worker MethodReference(dex_file, method->GetDexMethodIndex()), inline_caches);
1576*795d594fSAndroid Build Coastguard Worker continue;
1577*795d594fSAndroid Build Coastguard Worker }
1578*795d594fSAndroid Build Coastguard Worker
1579*795d594fSAndroid Build Coastguard Worker for (size_t i = 0; i < info->number_of_inline_caches_; ++i) {
1580*795d594fSAndroid Build Coastguard Worker std::vector<TypeReference> profile_classes;
1581*795d594fSAndroid Build Coastguard Worker const InlineCache& cache = info->GetInlineCaches()[i];
1582*795d594fSAndroid Build Coastguard Worker ArtMethod* caller = info->GetMethod();
1583*795d594fSAndroid Build Coastguard Worker bool is_missing_types = false;
1584*795d594fSAndroid Build Coastguard Worker for (size_t k = 0; k < InlineCache::kIndividualCacheSize; k++) {
1585*795d594fSAndroid Build Coastguard Worker mirror::Class* cls = cache.classes_[k].Read();
1586*795d594fSAndroid Build Coastguard Worker if (cls == nullptr) {
1587*795d594fSAndroid Build Coastguard Worker break;
1588*795d594fSAndroid Build Coastguard Worker }
1589*795d594fSAndroid Build Coastguard Worker
1590*795d594fSAndroid Build Coastguard Worker // Check if the receiver is in the boot class path or if it's in the
1591*795d594fSAndroid Build Coastguard Worker // same class loader as the caller. If not, skip it, as there is not
1592*795d594fSAndroid Build Coastguard Worker // much we can do during AOT.
1593*795d594fSAndroid Build Coastguard Worker if (!cls->IsBootStrapClassLoaded() &&
1594*795d594fSAndroid Build Coastguard Worker caller->GetClassLoader() != cls->GetClassLoader()) {
1595*795d594fSAndroid Build Coastguard Worker is_missing_types = true;
1596*795d594fSAndroid Build Coastguard Worker continue;
1597*795d594fSAndroid Build Coastguard Worker }
1598*795d594fSAndroid Build Coastguard Worker
1599*795d594fSAndroid Build Coastguard Worker const DexFile* class_dex_file = nullptr;
1600*795d594fSAndroid Build Coastguard Worker dex::TypeIndex type_index;
1601*795d594fSAndroid Build Coastguard Worker
1602*795d594fSAndroid Build Coastguard Worker if (cls->GetDexCache() == nullptr) {
1603*795d594fSAndroid Build Coastguard Worker DCHECK(cls->IsArrayClass()) << cls->PrettyClass();
1604*795d594fSAndroid Build Coastguard Worker // Make a best effort to find the type index in the method's dex file.
1605*795d594fSAndroid Build Coastguard Worker // We could search all open dex files but that might turn expensive
1606*795d594fSAndroid Build Coastguard Worker // and probably not worth it.
1607*795d594fSAndroid Build Coastguard Worker class_dex_file = dex_file;
1608*795d594fSAndroid Build Coastguard Worker type_index = cls->FindTypeIndexInOtherDexFile(*dex_file);
1609*795d594fSAndroid Build Coastguard Worker } else {
1610*795d594fSAndroid Build Coastguard Worker class_dex_file = &(cls->GetDexFile());
1611*795d594fSAndroid Build Coastguard Worker type_index = cls->GetDexTypeIndex();
1612*795d594fSAndroid Build Coastguard Worker }
1613*795d594fSAndroid Build Coastguard Worker if (!type_index.IsValid()) {
1614*795d594fSAndroid Build Coastguard Worker // Could be a proxy class or an array for which we couldn't find the type index.
1615*795d594fSAndroid Build Coastguard Worker is_missing_types = true;
1616*795d594fSAndroid Build Coastguard Worker continue;
1617*795d594fSAndroid Build Coastguard Worker }
1618*795d594fSAndroid Build Coastguard Worker if (ContainsElement(dex_base_locations,
1619*795d594fSAndroid Build Coastguard Worker DexFileLoader::GetBaseLocation(class_dex_file->GetLocation()))) {
1620*795d594fSAndroid Build Coastguard Worker // Only consider classes from the same apk (including multidex).
1621*795d594fSAndroid Build Coastguard Worker profile_classes.emplace_back(/*ProfileMethodInfo::ProfileClassReference*/
1622*795d594fSAndroid Build Coastguard Worker class_dex_file, type_index);
1623*795d594fSAndroid Build Coastguard Worker } else {
1624*795d594fSAndroid Build Coastguard Worker is_missing_types = true;
1625*795d594fSAndroid Build Coastguard Worker }
1626*795d594fSAndroid Build Coastguard Worker }
1627*795d594fSAndroid Build Coastguard Worker if (!profile_classes.empty()) {
1628*795d594fSAndroid Build Coastguard Worker inline_caches.emplace_back(/*ProfileMethodInfo::ProfileInlineCache*/
1629*795d594fSAndroid Build Coastguard Worker cache.dex_pc_, is_missing_types, profile_classes);
1630*795d594fSAndroid Build Coastguard Worker }
1631*795d594fSAndroid Build Coastguard Worker }
1632*795d594fSAndroid Build Coastguard Worker }
1633*795d594fSAndroid Build Coastguard Worker methods.emplace_back(/*ProfileMethodInfo*/
1634*795d594fSAndroid Build Coastguard Worker MethodReference(dex_file, method->GetDexMethodIndex()), inline_caches);
1635*795d594fSAndroid Build Coastguard Worker }
1636*795d594fSAndroid Build Coastguard Worker }
1637*795d594fSAndroid Build Coastguard Worker
IsOsrCompiled(ArtMethod * method)1638*795d594fSAndroid Build Coastguard Worker bool JitCodeCache::IsOsrCompiled(ArtMethod* method) {
1639*795d594fSAndroid Build Coastguard Worker Thread* self = Thread::Current();
1640*795d594fSAndroid Build Coastguard Worker ScopedDebugDisallowReadBarriers sddrb(self);
1641*795d594fSAndroid Build Coastguard Worker ReaderMutexLock mu(self, *Locks::jit_mutator_lock_);
1642*795d594fSAndroid Build Coastguard Worker return osr_code_map_.find(method) != osr_code_map_.end();
1643*795d594fSAndroid Build Coastguard Worker }
1644*795d594fSAndroid Build Coastguard Worker
NotifyCompilationOf(ArtMethod * method,Thread * self,CompilationKind compilation_kind,bool prejit)1645*795d594fSAndroid Build Coastguard Worker bool JitCodeCache::NotifyCompilationOf(ArtMethod* method,
1646*795d594fSAndroid Build Coastguard Worker Thread* self,
1647*795d594fSAndroid Build Coastguard Worker CompilationKind compilation_kind,
1648*795d594fSAndroid Build Coastguard Worker bool prejit) {
1649*795d594fSAndroid Build Coastguard Worker const void* existing_entry_point = method->GetEntryPointFromQuickCompiledCode();
1650*795d594fSAndroid Build Coastguard Worker if (compilation_kind == CompilationKind::kBaseline && ContainsPc(existing_entry_point)) {
1651*795d594fSAndroid Build Coastguard Worker // The existing entry point is either already baseline, or optimized. No
1652*795d594fSAndroid Build Coastguard Worker // need to compile.
1653*795d594fSAndroid Build Coastguard Worker VLOG(jit) << "Not compiling "
1654*795d594fSAndroid Build Coastguard Worker << method->PrettyMethod()
1655*795d594fSAndroid Build Coastguard Worker << " baseline, because it has already been compiled";
1656*795d594fSAndroid Build Coastguard Worker return false;
1657*795d594fSAndroid Build Coastguard Worker }
1658*795d594fSAndroid Build Coastguard Worker
1659*795d594fSAndroid Build Coastguard Worker if (method->NeedsClinitCheckBeforeCall() && !prejit) {
1660*795d594fSAndroid Build Coastguard Worker // We do not need a synchronization barrier for checking the visibly initialized status
1661*795d594fSAndroid Build Coastguard Worker // or checking the initialized status just for requesting visible initialization.
1662*795d594fSAndroid Build Coastguard Worker ClassStatus status = method->GetDeclaringClass()
1663*795d594fSAndroid Build Coastguard Worker ->GetStatus<kDefaultVerifyFlags, /*kWithSynchronizationBarrier=*/ false>();
1664*795d594fSAndroid Build Coastguard Worker if (status != ClassStatus::kVisiblyInitialized) {
1665*795d594fSAndroid Build Coastguard Worker // Unless we're pre-jitting, we currently don't save the JIT compiled code if we cannot
1666*795d594fSAndroid Build Coastguard Worker // update the entrypoint due to needing an initialization check.
1667*795d594fSAndroid Build Coastguard Worker if (status == ClassStatus::kInitialized) {
1668*795d594fSAndroid Build Coastguard Worker // Request visible initialization but do not block to allow compiling other methods.
1669*795d594fSAndroid Build Coastguard Worker // Hopefully, this will complete by the time the method becomes hot again.
1670*795d594fSAndroid Build Coastguard Worker Runtime::Current()->GetClassLinker()->MakeInitializedClassesVisiblyInitialized(
1671*795d594fSAndroid Build Coastguard Worker self, /*wait=*/ false);
1672*795d594fSAndroid Build Coastguard Worker }
1673*795d594fSAndroid Build Coastguard Worker VLOG(jit) << "Not compiling "
1674*795d594fSAndroid Build Coastguard Worker << method->PrettyMethod()
1675*795d594fSAndroid Build Coastguard Worker << " because it has the resolution stub";
1676*795d594fSAndroid Build Coastguard Worker return false;
1677*795d594fSAndroid Build Coastguard Worker }
1678*795d594fSAndroid Build Coastguard Worker }
1679*795d594fSAndroid Build Coastguard Worker
1680*795d594fSAndroid Build Coastguard Worker ScopedDebugDisallowReadBarriers sddrb(self);
1681*795d594fSAndroid Build Coastguard Worker if (compilation_kind == CompilationKind::kOsr) {
1682*795d594fSAndroid Build Coastguard Worker ReaderMutexLock mu(self, *Locks::jit_mutator_lock_);
1683*795d594fSAndroid Build Coastguard Worker if (osr_code_map_.find(method) != osr_code_map_.end()) {
1684*795d594fSAndroid Build Coastguard Worker return false;
1685*795d594fSAndroid Build Coastguard Worker }
1686*795d594fSAndroid Build Coastguard Worker }
1687*795d594fSAndroid Build Coastguard Worker
1688*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(method->IsNative())) {
1689*795d594fSAndroid Build Coastguard Worker JniStubKey key(method);
1690*795d594fSAndroid Build Coastguard Worker MutexLock mu2(self, *Locks::jit_lock_);
1691*795d594fSAndroid Build Coastguard Worker WriterMutexLock mu(self, *Locks::jit_mutator_lock_);
1692*795d594fSAndroid Build Coastguard Worker auto it = jni_stubs_map_.find(key);
1693*795d594fSAndroid Build Coastguard Worker bool new_compilation = false;
1694*795d594fSAndroid Build Coastguard Worker if (it == jni_stubs_map_.end()) {
1695*795d594fSAndroid Build Coastguard Worker // Create a new entry to mark the stub as being compiled.
1696*795d594fSAndroid Build Coastguard Worker it = jni_stubs_map_.Put(key, JniStubData{});
1697*795d594fSAndroid Build Coastguard Worker new_compilation = true;
1698*795d594fSAndroid Build Coastguard Worker }
1699*795d594fSAndroid Build Coastguard Worker JniStubData* data = &it->second;
1700*795d594fSAndroid Build Coastguard Worker data->AddMethod(method);
1701*795d594fSAndroid Build Coastguard Worker if (data->IsCompiled()) {
1702*795d594fSAndroid Build Coastguard Worker OatQuickMethodHeader* method_header = OatQuickMethodHeader::FromCodePointer(data->GetCode());
1703*795d594fSAndroid Build Coastguard Worker const void* entrypoint = method_header->GetEntryPoint();
1704*795d594fSAndroid Build Coastguard Worker // Update also entrypoints of other methods held by the JniStubData.
1705*795d594fSAndroid Build Coastguard Worker // We could simply update the entrypoint of `method` but if the last JIT GC has
1706*795d594fSAndroid Build Coastguard Worker // changed these entrypoints to GenericJNI in preparation for a full GC, we may
1707*795d594fSAndroid Build Coastguard Worker // as well change them back as this stub shall not be collected anyway and this
1708*795d594fSAndroid Build Coastguard Worker // can avoid a few expensive GenericJNI calls.
1709*795d594fSAndroid Build Coastguard Worker for (ArtMethod* m : it->second.GetMethods()) {
1710*795d594fSAndroid Build Coastguard Worker zombie_jni_code_.erase(m);
1711*795d594fSAndroid Build Coastguard Worker processed_zombie_jni_code_.erase(m);
1712*795d594fSAndroid Build Coastguard Worker }
1713*795d594fSAndroid Build Coastguard Worker data->UpdateEntryPoints(entrypoint);
1714*795d594fSAndroid Build Coastguard Worker }
1715*795d594fSAndroid Build Coastguard Worker return new_compilation;
1716*795d594fSAndroid Build Coastguard Worker } else {
1717*795d594fSAndroid Build Coastguard Worker if (compilation_kind == CompilationKind::kBaseline) {
1718*795d594fSAndroid Build Coastguard Worker DCHECK(CanAllocateProfilingInfo());
1719*795d594fSAndroid Build Coastguard Worker }
1720*795d594fSAndroid Build Coastguard Worker }
1721*795d594fSAndroid Build Coastguard Worker return true;
1722*795d594fSAndroid Build Coastguard Worker }
1723*795d594fSAndroid Build Coastguard Worker
NotifyCompilerUse(ArtMethod * method,Thread * self)1724*795d594fSAndroid Build Coastguard Worker ProfilingInfo* JitCodeCache::NotifyCompilerUse(ArtMethod* method, Thread* self) {
1725*795d594fSAndroid Build Coastguard Worker ScopedDebugDisallowReadBarriers sddrb(self);
1726*795d594fSAndroid Build Coastguard Worker MutexLock mu(self, *Locks::jit_lock_);
1727*795d594fSAndroid Build Coastguard Worker auto it = profiling_infos_.find(method);
1728*795d594fSAndroid Build Coastguard Worker if (it == profiling_infos_.end()) {
1729*795d594fSAndroid Build Coastguard Worker return nullptr;
1730*795d594fSAndroid Build Coastguard Worker }
1731*795d594fSAndroid Build Coastguard Worker if (!it->second->IncrementInlineUse()) {
1732*795d594fSAndroid Build Coastguard Worker // Overflow of inlining uses, just bail.
1733*795d594fSAndroid Build Coastguard Worker return nullptr;
1734*795d594fSAndroid Build Coastguard Worker }
1735*795d594fSAndroid Build Coastguard Worker return it->second;
1736*795d594fSAndroid Build Coastguard Worker }
1737*795d594fSAndroid Build Coastguard Worker
DoneCompilerUse(ArtMethod * method,Thread * self)1738*795d594fSAndroid Build Coastguard Worker void JitCodeCache::DoneCompilerUse(ArtMethod* method, Thread* self) {
1739*795d594fSAndroid Build Coastguard Worker ScopedDebugDisallowReadBarriers sddrb(self);
1740*795d594fSAndroid Build Coastguard Worker MutexLock mu(self, *Locks::jit_lock_);
1741*795d594fSAndroid Build Coastguard Worker auto it = profiling_infos_.find(method);
1742*795d594fSAndroid Build Coastguard Worker DCHECK(it != profiling_infos_.end());
1743*795d594fSAndroid Build Coastguard Worker it->second->DecrementInlineUse();
1744*795d594fSAndroid Build Coastguard Worker }
1745*795d594fSAndroid Build Coastguard Worker
DoneCompiling(ArtMethod * method,Thread * self)1746*795d594fSAndroid Build Coastguard Worker void JitCodeCache::DoneCompiling(ArtMethod* method, Thread* self) {
1747*795d594fSAndroid Build Coastguard Worker DCHECK_EQ(Thread::Current(), self);
1748*795d594fSAndroid Build Coastguard Worker ScopedDebugDisallowReadBarriers sddrb(self);
1749*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(method->IsNative())) {
1750*795d594fSAndroid Build Coastguard Worker WriterMutexLock mu(self, *Locks::jit_mutator_lock_);
1751*795d594fSAndroid Build Coastguard Worker auto it = jni_stubs_map_.find(JniStubKey(method));
1752*795d594fSAndroid Build Coastguard Worker DCHECK(it != jni_stubs_map_.end());
1753*795d594fSAndroid Build Coastguard Worker JniStubData* data = &it->second;
1754*795d594fSAndroid Build Coastguard Worker DCHECK(ContainsElement(data->GetMethods(), method));
1755*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(!data->IsCompiled())) {
1756*795d594fSAndroid Build Coastguard Worker // Failed to compile; the JNI compiler never fails, but the cache may be full.
1757*795d594fSAndroid Build Coastguard Worker jni_stubs_map_.erase(it); // Remove the entry added in NotifyCompilationOf().
1758*795d594fSAndroid Build Coastguard Worker } // else Commit() updated entrypoints of all methods in the JniStubData.
1759*795d594fSAndroid Build Coastguard Worker }
1760*795d594fSAndroid Build Coastguard Worker }
1761*795d594fSAndroid Build Coastguard Worker
InvalidateAllCompiledCode()1762*795d594fSAndroid Build Coastguard Worker void JitCodeCache::InvalidateAllCompiledCode() {
1763*795d594fSAndroid Build Coastguard Worker Thread* self = Thread::Current();
1764*795d594fSAndroid Build Coastguard Worker ScopedDebugDisallowReadBarriers sddrb(self);
1765*795d594fSAndroid Build Coastguard Worker VLOG(jit) << "Invalidating all compiled code";
1766*795d594fSAndroid Build Coastguard Worker Runtime* runtime = Runtime::Current();
1767*795d594fSAndroid Build Coastguard Worker ClassLinker* linker = runtime->GetClassLinker();
1768*795d594fSAndroid Build Coastguard Worker instrumentation::Instrumentation* instr = runtime->GetInstrumentation();
1769*795d594fSAndroid Build Coastguard Worker
1770*795d594fSAndroid Build Coastguard Worker {
1771*795d594fSAndroid Build Coastguard Worker WriterMutexLock mu(self, *Locks::jit_mutator_lock_);
1772*795d594fSAndroid Build Coastguard Worker // Change entry points of native methods back to the GenericJNI entrypoint.
1773*795d594fSAndroid Build Coastguard Worker for (const auto& entry : jni_stubs_map_) {
1774*795d594fSAndroid Build Coastguard Worker const JniStubData& data = entry.second;
1775*795d594fSAndroid Build Coastguard Worker if (!data.IsCompiled() || IsInZygoteExecSpace(data.GetCode())) {
1776*795d594fSAndroid Build Coastguard Worker continue;
1777*795d594fSAndroid Build Coastguard Worker }
1778*795d594fSAndroid Build Coastguard Worker const OatQuickMethodHeader* method_header =
1779*795d594fSAndroid Build Coastguard Worker OatQuickMethodHeader::FromCodePointer(data.GetCode());
1780*795d594fSAndroid Build Coastguard Worker for (ArtMethod* method : data.GetMethods()) {
1781*795d594fSAndroid Build Coastguard Worker if (method->GetEntryPointFromQuickCompiledCode() == method_header->GetEntryPoint()) {
1782*795d594fSAndroid Build Coastguard Worker instr->InitializeMethodsCode(method, /*aot_code=*/ nullptr);
1783*795d594fSAndroid Build Coastguard Worker }
1784*795d594fSAndroid Build Coastguard Worker }
1785*795d594fSAndroid Build Coastguard Worker }
1786*795d594fSAndroid Build Coastguard Worker
1787*795d594fSAndroid Build Coastguard Worker for (const auto& entry : method_code_map_) {
1788*795d594fSAndroid Build Coastguard Worker ArtMethod* meth = entry.second;
1789*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(meth->IsObsolete())) {
1790*795d594fSAndroid Build Coastguard Worker linker->SetEntryPointsForObsoleteMethod(meth);
1791*795d594fSAndroid Build Coastguard Worker } else {
1792*795d594fSAndroid Build Coastguard Worker instr->InitializeMethodsCode(meth, /*aot_code=*/ nullptr);
1793*795d594fSAndroid Build Coastguard Worker }
1794*795d594fSAndroid Build Coastguard Worker }
1795*795d594fSAndroid Build Coastguard Worker osr_code_map_.clear();
1796*795d594fSAndroid Build Coastguard Worker saved_compiled_methods_map_.clear();
1797*795d594fSAndroid Build Coastguard Worker }
1798*795d594fSAndroid Build Coastguard Worker
1799*795d594fSAndroid Build Coastguard Worker for (const auto& entry : zygote_map_) {
1800*795d594fSAndroid Build Coastguard Worker if (entry.method == nullptr) {
1801*795d594fSAndroid Build Coastguard Worker continue;
1802*795d594fSAndroid Build Coastguard Worker }
1803*795d594fSAndroid Build Coastguard Worker if (entry.method->IsPreCompiled()) {
1804*795d594fSAndroid Build Coastguard Worker entry.method->ClearPreCompiled();
1805*795d594fSAndroid Build Coastguard Worker }
1806*795d594fSAndroid Build Coastguard Worker instr->InitializeMethodsCode(entry.method, /*aot_code=*/nullptr);
1807*795d594fSAndroid Build Coastguard Worker }
1808*795d594fSAndroid Build Coastguard Worker }
1809*795d594fSAndroid Build Coastguard Worker
InvalidateCompiledCodeFor(ArtMethod * method,const OatQuickMethodHeader * header)1810*795d594fSAndroid Build Coastguard Worker void JitCodeCache::InvalidateCompiledCodeFor(ArtMethod* method,
1811*795d594fSAndroid Build Coastguard Worker const OatQuickMethodHeader* header) {
1812*795d594fSAndroid Build Coastguard Worker DCHECK(!method->IsNative());
1813*795d594fSAndroid Build Coastguard Worker const void* method_entrypoint = method->GetEntryPointFromQuickCompiledCode();
1814*795d594fSAndroid Build Coastguard Worker
1815*795d594fSAndroid Build Coastguard Worker // Clear the method counter if we are running jitted code since we might want to jit this again in
1816*795d594fSAndroid Build Coastguard Worker // the future.
1817*795d594fSAndroid Build Coastguard Worker if (method_entrypoint == header->GetEntryPoint()) {
1818*795d594fSAndroid Build Coastguard Worker // The entrypoint is the one to invalidate, so we just update it to the interpreter entry point.
1819*795d594fSAndroid Build Coastguard Worker Runtime::Current()->GetInstrumentation()->InitializeMethodsCode(method, /*aot_code=*/ nullptr);
1820*795d594fSAndroid Build Coastguard Worker } else {
1821*795d594fSAndroid Build Coastguard Worker Thread* self = Thread::Current();
1822*795d594fSAndroid Build Coastguard Worker ScopedDebugDisallowReadBarriers sddrb(self);
1823*795d594fSAndroid Build Coastguard Worker WriterMutexLock mu(self, *Locks::jit_mutator_lock_);
1824*795d594fSAndroid Build Coastguard Worker auto it = osr_code_map_.find(method);
1825*795d594fSAndroid Build Coastguard Worker if (it != osr_code_map_.end() && OatQuickMethodHeader::FromCodePointer(it->second) == header) {
1826*795d594fSAndroid Build Coastguard Worker // Remove the OSR method, to avoid using it again.
1827*795d594fSAndroid Build Coastguard Worker osr_code_map_.erase(it);
1828*795d594fSAndroid Build Coastguard Worker }
1829*795d594fSAndroid Build Coastguard Worker }
1830*795d594fSAndroid Build Coastguard Worker
1831*795d594fSAndroid Build Coastguard Worker // In case the method was pre-compiled, clear that information so we
1832*795d594fSAndroid Build Coastguard Worker // can recompile it ourselves.
1833*795d594fSAndroid Build Coastguard Worker if (method->IsPreCompiled()) {
1834*795d594fSAndroid Build Coastguard Worker method->ClearPreCompiled();
1835*795d594fSAndroid Build Coastguard Worker }
1836*795d594fSAndroid Build Coastguard Worker }
1837*795d594fSAndroid Build Coastguard Worker
Dump(std::ostream & os)1838*795d594fSAndroid Build Coastguard Worker void JitCodeCache::Dump(std::ostream& os) {
1839*795d594fSAndroid Build Coastguard Worker MutexLock mu(Thread::Current(), *Locks::jit_lock_);
1840*795d594fSAndroid Build Coastguard Worker os << "Current JIT code cache size (used / resident): "
1841*795d594fSAndroid Build Coastguard Worker << GetCurrentRegion()->GetUsedMemoryForCode() / KB << "KB / "
1842*795d594fSAndroid Build Coastguard Worker << GetCurrentRegion()->GetResidentMemoryForCode() / KB << "KB\n"
1843*795d594fSAndroid Build Coastguard Worker << "Current JIT data cache size (used / resident): "
1844*795d594fSAndroid Build Coastguard Worker << GetCurrentRegion()->GetUsedMemoryForData() / KB << "KB / "
1845*795d594fSAndroid Build Coastguard Worker << GetCurrentRegion()->GetResidentMemoryForData() / KB << "KB\n";
1846*795d594fSAndroid Build Coastguard Worker if (!Runtime::Current()->IsZygote()) {
1847*795d594fSAndroid Build Coastguard Worker os << "Zygote JIT code cache size (at point of fork): "
1848*795d594fSAndroid Build Coastguard Worker << shared_region_.GetUsedMemoryForCode() / KB << "KB / "
1849*795d594fSAndroid Build Coastguard Worker << shared_region_.GetResidentMemoryForCode() / KB << "KB\n"
1850*795d594fSAndroid Build Coastguard Worker << "Zygote JIT data cache size (at point of fork): "
1851*795d594fSAndroid Build Coastguard Worker << shared_region_.GetUsedMemoryForData() / KB << "KB / "
1852*795d594fSAndroid Build Coastguard Worker << shared_region_.GetResidentMemoryForData() / KB << "KB\n";
1853*795d594fSAndroid Build Coastguard Worker }
1854*795d594fSAndroid Build Coastguard Worker ReaderMutexLock mu2(Thread::Current(), *Locks::jit_mutator_lock_);
1855*795d594fSAndroid Build Coastguard Worker os << "Current JIT mini-debug-info size: " << PrettySize(GetJitMiniDebugInfoMemUsage()) << "\n"
1856*795d594fSAndroid Build Coastguard Worker << "Current JIT capacity: " << PrettySize(GetCurrentRegion()->GetCurrentCapacity()) << "\n"
1857*795d594fSAndroid Build Coastguard Worker << "Current number of JIT JNI stub entries: " << jni_stubs_map_.size() << "\n"
1858*795d594fSAndroid Build Coastguard Worker << "Current number of JIT code cache entries: " << method_code_map_.size() << "\n"
1859*795d594fSAndroid Build Coastguard Worker << "Total number of JIT baseline compilations: " << number_of_baseline_compilations_ << "\n"
1860*795d594fSAndroid Build Coastguard Worker << "Total number of JIT optimized compilations: " << number_of_optimized_compilations_ << "\n"
1861*795d594fSAndroid Build Coastguard Worker << "Total number of JIT compilations for on stack replacement: "
1862*795d594fSAndroid Build Coastguard Worker << number_of_osr_compilations_ << "\n"
1863*795d594fSAndroid Build Coastguard Worker << "Total number of JIT code cache collections: " << number_of_collections_ << std::endl;
1864*795d594fSAndroid Build Coastguard Worker histogram_stack_map_memory_use_.PrintMemoryUse(os);
1865*795d594fSAndroid Build Coastguard Worker histogram_code_memory_use_.PrintMemoryUse(os);
1866*795d594fSAndroid Build Coastguard Worker histogram_profiling_info_memory_use_.PrintMemoryUse(os);
1867*795d594fSAndroid Build Coastguard Worker }
1868*795d594fSAndroid Build Coastguard Worker
DumpAllCompiledMethods(std::ostream & os)1869*795d594fSAndroid Build Coastguard Worker void JitCodeCache::DumpAllCompiledMethods(std::ostream& os) {
1870*795d594fSAndroid Build Coastguard Worker ReaderMutexLock mu(Thread::Current(), *Locks::jit_mutator_lock_);
1871*795d594fSAndroid Build Coastguard Worker for (const auto& [code_ptr, meth] : method_code_map_) { // Includes OSR methods.
1872*795d594fSAndroid Build Coastguard Worker OatQuickMethodHeader* header = OatQuickMethodHeader::FromCodePointer(code_ptr);
1873*795d594fSAndroid Build Coastguard Worker os << meth->PrettyMethod() << "@" << std::hex
1874*795d594fSAndroid Build Coastguard Worker << code_ptr << "-" << reinterpret_cast<uintptr_t>(code_ptr) + header->GetCodeSize() << '\n';
1875*795d594fSAndroid Build Coastguard Worker }
1876*795d594fSAndroid Build Coastguard Worker os << "JNIStubs: \n";
1877*795d594fSAndroid Build Coastguard Worker for (const auto& [_, data] : jni_stubs_map_) {
1878*795d594fSAndroid Build Coastguard Worker const void* code_ptr = data.GetCode();
1879*795d594fSAndroid Build Coastguard Worker if (code_ptr == nullptr) {
1880*795d594fSAndroid Build Coastguard Worker continue;
1881*795d594fSAndroid Build Coastguard Worker }
1882*795d594fSAndroid Build Coastguard Worker OatQuickMethodHeader* header = OatQuickMethodHeader::FromCodePointer(code_ptr);
1883*795d594fSAndroid Build Coastguard Worker os << std::hex << code_ptr << "-"
1884*795d594fSAndroid Build Coastguard Worker << reinterpret_cast<uintptr_t>(code_ptr) + header->GetCodeSize() << " ";
1885*795d594fSAndroid Build Coastguard Worker for (ArtMethod* m : data.GetMethods()) {
1886*795d594fSAndroid Build Coastguard Worker os << m->PrettyMethod() << ";";
1887*795d594fSAndroid Build Coastguard Worker }
1888*795d594fSAndroid Build Coastguard Worker os << "\n";
1889*795d594fSAndroid Build Coastguard Worker }
1890*795d594fSAndroid Build Coastguard Worker }
1891*795d594fSAndroid Build Coastguard Worker
PostForkChildAction(bool is_system_server,bool is_zygote)1892*795d594fSAndroid Build Coastguard Worker void JitCodeCache::PostForkChildAction(bool is_system_server, bool is_zygote) {
1893*795d594fSAndroid Build Coastguard Worker Thread* self = Thread::Current();
1894*795d594fSAndroid Build Coastguard Worker
1895*795d594fSAndroid Build Coastguard Worker // Remove potential tasks that have been inherited from the zygote.
1896*795d594fSAndroid Build Coastguard Worker // We do this now and not in Jit::PostForkChildAction, as system server calls
1897*795d594fSAndroid Build Coastguard Worker // JitCodeCache::PostForkChildAction first, and then does some code loading
1898*795d594fSAndroid Build Coastguard Worker // that may result in new JIT tasks that we want to keep.
1899*795d594fSAndroid Build Coastguard Worker Runtime* runtime = Runtime::Current();
1900*795d594fSAndroid Build Coastguard Worker JitThreadPool* pool = runtime->GetJit()->GetThreadPool();
1901*795d594fSAndroid Build Coastguard Worker if (pool != nullptr) {
1902*795d594fSAndroid Build Coastguard Worker pool->RemoveAllTasks(self);
1903*795d594fSAndroid Build Coastguard Worker }
1904*795d594fSAndroid Build Coastguard Worker
1905*795d594fSAndroid Build Coastguard Worker MutexLock mu(self, *Locks::jit_lock_);
1906*795d594fSAndroid Build Coastguard Worker
1907*795d594fSAndroid Build Coastguard Worker // Reset potential writable MemMaps inherited from the zygote. We never want
1908*795d594fSAndroid Build Coastguard Worker // to write to them.
1909*795d594fSAndroid Build Coastguard Worker shared_region_.ResetWritableMappings();
1910*795d594fSAndroid Build Coastguard Worker
1911*795d594fSAndroid Build Coastguard Worker if (is_zygote || runtime->IsSafeMode()) {
1912*795d594fSAndroid Build Coastguard Worker // Don't create a private region for a child zygote. Regions are usually map shared
1913*795d594fSAndroid Build Coastguard Worker // (to satisfy dual-view), and we don't want children of a child zygote to inherit it.
1914*795d594fSAndroid Build Coastguard Worker return;
1915*795d594fSAndroid Build Coastguard Worker }
1916*795d594fSAndroid Build Coastguard Worker
1917*795d594fSAndroid Build Coastguard Worker // Reset all statistics to be specific to this process.
1918*795d594fSAndroid Build Coastguard Worker number_of_baseline_compilations_ = 0;
1919*795d594fSAndroid Build Coastguard Worker number_of_optimized_compilations_ = 0;
1920*795d594fSAndroid Build Coastguard Worker number_of_osr_compilations_ = 0;
1921*795d594fSAndroid Build Coastguard Worker number_of_collections_ = 0;
1922*795d594fSAndroid Build Coastguard Worker histogram_stack_map_memory_use_.Reset();
1923*795d594fSAndroid Build Coastguard Worker histogram_code_memory_use_.Reset();
1924*795d594fSAndroid Build Coastguard Worker histogram_profiling_info_memory_use_.Reset();
1925*795d594fSAndroid Build Coastguard Worker
1926*795d594fSAndroid Build Coastguard Worker size_t initial_capacity = runtime->GetJITOptions()->GetCodeCacheInitialCapacity();
1927*795d594fSAndroid Build Coastguard Worker size_t max_capacity = runtime->GetJITOptions()->GetCodeCacheMaxCapacity();
1928*795d594fSAndroid Build Coastguard Worker std::string error_msg;
1929*795d594fSAndroid Build Coastguard Worker if (!private_region_.Initialize(initial_capacity,
1930*795d594fSAndroid Build Coastguard Worker max_capacity,
1931*795d594fSAndroid Build Coastguard Worker /* rwx_memory_allowed= */ !is_system_server,
1932*795d594fSAndroid Build Coastguard Worker is_zygote,
1933*795d594fSAndroid Build Coastguard Worker &error_msg)) {
1934*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Could not create private region after zygote fork: " << error_msg;
1935*795d594fSAndroid Build Coastguard Worker }
1936*795d594fSAndroid Build Coastguard Worker if (private_region_.HasCodeMapping()) {
1937*795d594fSAndroid Build Coastguard Worker const MemMap* exec_pages = private_region_.GetExecPages();
1938*795d594fSAndroid Build Coastguard Worker runtime->AddGeneratedCodeRange(exec_pages->Begin(), exec_pages->Size());
1939*795d594fSAndroid Build Coastguard Worker }
1940*795d594fSAndroid Build Coastguard Worker }
1941*795d594fSAndroid Build Coastguard Worker
GetCurrentRegion()1942*795d594fSAndroid Build Coastguard Worker JitMemoryRegion* JitCodeCache::GetCurrentRegion() {
1943*795d594fSAndroid Build Coastguard Worker return Runtime::Current()->IsZygote() ? &shared_region_ : &private_region_;
1944*795d594fSAndroid Build Coastguard Worker }
1945*795d594fSAndroid Build Coastguard Worker
VisitAllMethods(const std::function<void (const void *,ArtMethod *)> & cb)1946*795d594fSAndroid Build Coastguard Worker void JitCodeCache::VisitAllMethods(const std::function<void(const void*, ArtMethod*)>& cb) {
1947*795d594fSAndroid Build Coastguard Worker for (const auto& it : jni_stubs_map_) {
1948*795d594fSAndroid Build Coastguard Worker const JniStubData& data = it.second;
1949*795d594fSAndroid Build Coastguard Worker if (data.IsCompiled()) {
1950*795d594fSAndroid Build Coastguard Worker for (ArtMethod* method : data.GetMethods()) {
1951*795d594fSAndroid Build Coastguard Worker cb(data.GetCode(), method);
1952*795d594fSAndroid Build Coastguard Worker }
1953*795d594fSAndroid Build Coastguard Worker }
1954*795d594fSAndroid Build Coastguard Worker }
1955*795d594fSAndroid Build Coastguard Worker for (const auto& it : method_code_map_) { // Includes OSR methods.
1956*795d594fSAndroid Build Coastguard Worker cb(it.first, it.second);
1957*795d594fSAndroid Build Coastguard Worker }
1958*795d594fSAndroid Build Coastguard Worker for (const auto& it : saved_compiled_methods_map_) {
1959*795d594fSAndroid Build Coastguard Worker cb(it.second, it.first);
1960*795d594fSAndroid Build Coastguard Worker }
1961*795d594fSAndroid Build Coastguard Worker for (const auto& it : zygote_map_) {
1962*795d594fSAndroid Build Coastguard Worker if (it.code_ptr != nullptr && it.method != nullptr) {
1963*795d594fSAndroid Build Coastguard Worker cb(it.code_ptr, it.method);
1964*795d594fSAndroid Build Coastguard Worker }
1965*795d594fSAndroid Build Coastguard Worker }
1966*795d594fSAndroid Build Coastguard Worker }
1967*795d594fSAndroid Build Coastguard Worker
Initialize(uint32_t number_of_methods)1968*795d594fSAndroid Build Coastguard Worker void ZygoteMap::Initialize(uint32_t number_of_methods) {
1969*795d594fSAndroid Build Coastguard Worker MutexLock mu(Thread::Current(), *Locks::jit_lock_);
1970*795d594fSAndroid Build Coastguard Worker // Allocate for 40-80% capacity. This will offer OK lookup times, and termination
1971*795d594fSAndroid Build Coastguard Worker // cases.
1972*795d594fSAndroid Build Coastguard Worker size_t capacity = RoundUpToPowerOfTwo(number_of_methods * 100 / 80);
1973*795d594fSAndroid Build Coastguard Worker const uint8_t* memory = region_->AllocateData(
1974*795d594fSAndroid Build Coastguard Worker capacity * sizeof(Entry) + sizeof(ZygoteCompilationState));
1975*795d594fSAndroid Build Coastguard Worker if (memory == nullptr) {
1976*795d594fSAndroid Build Coastguard Worker LOG(WARNING) << "Could not allocate data for the zygote map";
1977*795d594fSAndroid Build Coastguard Worker return;
1978*795d594fSAndroid Build Coastguard Worker }
1979*795d594fSAndroid Build Coastguard Worker const Entry* data = reinterpret_cast<const Entry*>(memory);
1980*795d594fSAndroid Build Coastguard Worker region_->FillData(data, capacity, Entry { nullptr, nullptr });
1981*795d594fSAndroid Build Coastguard Worker map_ = ArrayRef(data, capacity);
1982*795d594fSAndroid Build Coastguard Worker compilation_state_ = reinterpret_cast<const ZygoteCompilationState*>(
1983*795d594fSAndroid Build Coastguard Worker memory + capacity * sizeof(Entry));
1984*795d594fSAndroid Build Coastguard Worker region_->WriteData(compilation_state_, ZygoteCompilationState::kInProgress);
1985*795d594fSAndroid Build Coastguard Worker }
1986*795d594fSAndroid Build Coastguard Worker
GetCodeFor(ArtMethod * method,uintptr_t pc) const1987*795d594fSAndroid Build Coastguard Worker const void* ZygoteMap::GetCodeFor(ArtMethod* method, uintptr_t pc) const {
1988*795d594fSAndroid Build Coastguard Worker if (map_.empty()) {
1989*795d594fSAndroid Build Coastguard Worker return nullptr;
1990*795d594fSAndroid Build Coastguard Worker }
1991*795d594fSAndroid Build Coastguard Worker
1992*795d594fSAndroid Build Coastguard Worker if (method == nullptr) {
1993*795d594fSAndroid Build Coastguard Worker // Do a linear search. This should only be used in debug builds.
1994*795d594fSAndroid Build Coastguard Worker CHECK(kIsDebugBuild);
1995*795d594fSAndroid Build Coastguard Worker for (const Entry& entry : map_) {
1996*795d594fSAndroid Build Coastguard Worker const void* code_ptr = entry.code_ptr;
1997*795d594fSAndroid Build Coastguard Worker if (code_ptr != nullptr) {
1998*795d594fSAndroid Build Coastguard Worker OatQuickMethodHeader* method_header = OatQuickMethodHeader::FromCodePointer(code_ptr);
1999*795d594fSAndroid Build Coastguard Worker if (method_header->Contains(pc)) {
2000*795d594fSAndroid Build Coastguard Worker return code_ptr;
2001*795d594fSAndroid Build Coastguard Worker }
2002*795d594fSAndroid Build Coastguard Worker }
2003*795d594fSAndroid Build Coastguard Worker }
2004*795d594fSAndroid Build Coastguard Worker return nullptr;
2005*795d594fSAndroid Build Coastguard Worker }
2006*795d594fSAndroid Build Coastguard Worker
2007*795d594fSAndroid Build Coastguard Worker std::hash<ArtMethod*> hf;
2008*795d594fSAndroid Build Coastguard Worker size_t index = hf(method) & (map_.size() - 1u);
2009*795d594fSAndroid Build Coastguard Worker size_t original_index = index;
2010*795d594fSAndroid Build Coastguard Worker // Loop over the array: we know this loop terminates as we will either
2011*795d594fSAndroid Build Coastguard Worker // encounter the given method, or a null entry. Both terminate the loop.
2012*795d594fSAndroid Build Coastguard Worker // Note that the zygote may concurrently write new entries to the map. That's OK as the
2013*795d594fSAndroid Build Coastguard Worker // map is never resized.
2014*795d594fSAndroid Build Coastguard Worker while (true) {
2015*795d594fSAndroid Build Coastguard Worker const Entry& entry = map_[index];
2016*795d594fSAndroid Build Coastguard Worker if (entry.method == nullptr) {
2017*795d594fSAndroid Build Coastguard Worker // Not compiled yet.
2018*795d594fSAndroid Build Coastguard Worker return nullptr;
2019*795d594fSAndroid Build Coastguard Worker }
2020*795d594fSAndroid Build Coastguard Worker if (entry.method == method) {
2021*795d594fSAndroid Build Coastguard Worker if (entry.code_ptr == nullptr) {
2022*795d594fSAndroid Build Coastguard Worker // This is a race with the zygote which wrote the method, but hasn't written the
2023*795d594fSAndroid Build Coastguard Worker // code. Just bail and wait for the next time we need the method.
2024*795d594fSAndroid Build Coastguard Worker return nullptr;
2025*795d594fSAndroid Build Coastguard Worker }
2026*795d594fSAndroid Build Coastguard Worker if (pc != 0 && !OatQuickMethodHeader::FromCodePointer(entry.code_ptr)->Contains(pc)) {
2027*795d594fSAndroid Build Coastguard Worker return nullptr;
2028*795d594fSAndroid Build Coastguard Worker }
2029*795d594fSAndroid Build Coastguard Worker return entry.code_ptr;
2030*795d594fSAndroid Build Coastguard Worker }
2031*795d594fSAndroid Build Coastguard Worker index = (index + 1) & (map_.size() - 1);
2032*795d594fSAndroid Build Coastguard Worker DCHECK_NE(original_index, index);
2033*795d594fSAndroid Build Coastguard Worker }
2034*795d594fSAndroid Build Coastguard Worker }
2035*795d594fSAndroid Build Coastguard Worker
Put(const void * code,ArtMethod * method)2036*795d594fSAndroid Build Coastguard Worker void ZygoteMap::Put(const void* code, ArtMethod* method) {
2037*795d594fSAndroid Build Coastguard Worker if (map_.empty()) {
2038*795d594fSAndroid Build Coastguard Worker return;
2039*795d594fSAndroid Build Coastguard Worker }
2040*795d594fSAndroid Build Coastguard Worker CHECK(Runtime::Current()->IsZygote());
2041*795d594fSAndroid Build Coastguard Worker std::hash<ArtMethod*> hf;
2042*795d594fSAndroid Build Coastguard Worker size_t index = hf(method) & (map_.size() - 1);
2043*795d594fSAndroid Build Coastguard Worker size_t original_index = index;
2044*795d594fSAndroid Build Coastguard Worker // Because the size of the map is bigger than the number of methods that will
2045*795d594fSAndroid Build Coastguard Worker // be added, we are guaranteed to find a free slot in the array, and
2046*795d594fSAndroid Build Coastguard Worker // therefore for this loop to terminate.
2047*795d594fSAndroid Build Coastguard Worker while (true) {
2048*795d594fSAndroid Build Coastguard Worker const Entry* entry = &map_[index];
2049*795d594fSAndroid Build Coastguard Worker if (entry->method == nullptr) {
2050*795d594fSAndroid Build Coastguard Worker // Note that readers can read this memory concurrently, but that's OK as
2051*795d594fSAndroid Build Coastguard Worker // we are writing pointers.
2052*795d594fSAndroid Build Coastguard Worker region_->WriteData(entry, Entry { method, code });
2053*795d594fSAndroid Build Coastguard Worker break;
2054*795d594fSAndroid Build Coastguard Worker }
2055*795d594fSAndroid Build Coastguard Worker index = (index + 1) & (map_.size() - 1);
2056*795d594fSAndroid Build Coastguard Worker DCHECK_NE(original_index, index);
2057*795d594fSAndroid Build Coastguard Worker }
2058*795d594fSAndroid Build Coastguard Worker DCHECK_EQ(GetCodeFor(method), code);
2059*795d594fSAndroid Build Coastguard Worker }
2060*795d594fSAndroid Build Coastguard Worker
2061*795d594fSAndroid Build Coastguard Worker } // namespace jit
2062*795d594fSAndroid Build Coastguard Worker } // namespace art
2063