1 /*
2 * Copyright 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "jit_code_cache.h"
18
19 #include <sstream>
20
21 #include "arch/context.h"
22 #include "art_method-inl.h"
23 #include "base/enums.h"
24 #include "base/logging.h" // For VLOG.
25 #include "base/quasi_atomic.h"
26 #include "base/stl_util.h"
27 #include "base/systrace.h"
28 #include "base/time_utils.h"
29 #include "cha.h"
30 #include "debugger_interface.h"
31 #include "dex/dex_file_loader.h"
32 #include "entrypoints/runtime_asm_entrypoints.h"
33 #include "gc/accounting/bitmap-inl.h"
34 #include "gc/scoped_gc_critical_section.h"
35 #include "handle.h"
36 #include "intern_table.h"
37 #include "jit/jit.h"
38 #include "jit/profiling_info.h"
39 #include "linear_alloc.h"
40 #include "mem_map.h"
41 #include "oat_file-inl.h"
42 #include "oat_quick_method_header.h"
43 #include "object_callbacks.h"
44 #include "profile_compilation_info.h"
45 #include "scoped_thread_state_change-inl.h"
46 #include "stack.h"
47 #include "thread-current-inl.h"
48 #include "thread_list.h"
49
50 namespace art {
51 namespace jit {
52
53 static constexpr int kProtData = PROT_READ | PROT_WRITE;
54 static constexpr int kProtCode = PROT_READ | PROT_EXEC;
55
56 static constexpr size_t kCodeSizeLogThreshold = 50 * KB;
57 static constexpr size_t kStackMapSizeLogThreshold = 50 * KB;
58
59 class JitCodeCache::JniStubKey {
60 public:
REQUIRES_SHARED(Locks::mutator_lock_)61 explicit JniStubKey(ArtMethod* method) REQUIRES_SHARED(Locks::mutator_lock_)
62 : shorty_(method->GetShorty()),
63 is_static_(method->IsStatic()),
64 is_fast_native_(method->IsFastNative()),
65 is_critical_native_(method->IsCriticalNative()),
66 is_synchronized_(method->IsSynchronized()) {
67 DCHECK(!(is_fast_native_ && is_critical_native_));
68 }
69
operator <(const JniStubKey & rhs) const70 bool operator<(const JniStubKey& rhs) const {
71 if (is_static_ != rhs.is_static_) {
72 return rhs.is_static_;
73 }
74 if (is_synchronized_ != rhs.is_synchronized_) {
75 return rhs.is_synchronized_;
76 }
77 if (is_fast_native_ != rhs.is_fast_native_) {
78 return rhs.is_fast_native_;
79 }
80 if (is_critical_native_ != rhs.is_critical_native_) {
81 return rhs.is_critical_native_;
82 }
83 return strcmp(shorty_, rhs.shorty_) < 0;
84 }
85
86 // Update the shorty to point to another method's shorty. Call this function when removing
87 // the method that references the old shorty from JniCodeData and not removing the entire
88 // JniCodeData; the old shorty may become a dangling pointer when that method is unloaded.
UpdateShorty(ArtMethod * method) const89 void UpdateShorty(ArtMethod* method) const REQUIRES_SHARED(Locks::mutator_lock_) {
90 const char* shorty = method->GetShorty();
91 DCHECK_STREQ(shorty_, shorty);
92 shorty_ = shorty;
93 }
94
95 private:
96 // The shorty points to a DexFile data and may need to change
97 // to point to the same shorty in a different DexFile.
98 mutable const char* shorty_;
99
100 const bool is_static_;
101 const bool is_fast_native_;
102 const bool is_critical_native_;
103 const bool is_synchronized_;
104 };
105
106 class JitCodeCache::JniStubData {
107 public:
JniStubData()108 JniStubData() : code_(nullptr), methods_() {}
109
SetCode(const void * code)110 void SetCode(const void* code) {
111 DCHECK(code != nullptr);
112 code_ = code;
113 }
114
GetCode() const115 const void* GetCode() const {
116 return code_;
117 }
118
IsCompiled() const119 bool IsCompiled() const {
120 return GetCode() != nullptr;
121 }
122
AddMethod(ArtMethod * method)123 void AddMethod(ArtMethod* method) {
124 if (!ContainsElement(methods_, method)) {
125 methods_.push_back(method);
126 }
127 }
128
GetMethods() const129 const std::vector<ArtMethod*>& GetMethods() const {
130 return methods_;
131 }
132
RemoveMethodsIn(const LinearAlloc & alloc)133 void RemoveMethodsIn(const LinearAlloc& alloc) {
134 auto kept_end = std::remove_if(
135 methods_.begin(),
136 methods_.end(),
137 [&alloc](ArtMethod* method) { return alloc.ContainsUnsafe(method); });
138 methods_.erase(kept_end, methods_.end());
139 }
140
RemoveMethod(ArtMethod * method)141 bool RemoveMethod(ArtMethod* method) {
142 auto it = std::find(methods_.begin(), methods_.end(), method);
143 if (it != methods_.end()) {
144 methods_.erase(it);
145 return true;
146 } else {
147 return false;
148 }
149 }
150
MoveObsoleteMethod(ArtMethod * old_method,ArtMethod * new_method)151 void MoveObsoleteMethod(ArtMethod* old_method, ArtMethod* new_method) {
152 std::replace(methods_.begin(), methods_.end(), old_method, new_method);
153 }
154
155 private:
156 const void* code_;
157 std::vector<ArtMethod*> methods_;
158 };
159
Create(size_t initial_capacity,size_t max_capacity,bool generate_debug_info,bool used_only_for_profile_data,std::string * error_msg)160 JitCodeCache* JitCodeCache::Create(size_t initial_capacity,
161 size_t max_capacity,
162 bool generate_debug_info,
163 bool used_only_for_profile_data,
164 std::string* error_msg) {
165 ScopedTrace trace(__PRETTY_FUNCTION__);
166 CHECK_GE(max_capacity, initial_capacity);
167
168 // Generating debug information is for using the Linux perf tool on
169 // host which does not work with ashmem.
170 // Also, target linux does not support ashmem.
171 bool use_ashmem = !generate_debug_info && !kIsTargetLinux;
172
173 // With 'perf', we want a 1-1 mapping between an address and a method.
174 bool garbage_collect_code = !generate_debug_info;
175
176 // We need to have 32 bit offsets from method headers in code cache which point to things
177 // in the data cache. If the maps are more than 4G apart, having multiple maps wouldn't work.
178 // Ensure we're below 1 GB to be safe.
179 if (max_capacity > 1 * GB) {
180 std::ostringstream oss;
181 oss << "Maxium code cache capacity is limited to 1 GB, "
182 << PrettySize(max_capacity) << " is too big";
183 *error_msg = oss.str();
184 return nullptr;
185 }
186
187 // Decide how we should map the code and data sections.
188 // If we use the code cache just for profiling we do not need to map the code section as
189 // executable.
190 // NOTE 1: this is yet another workaround to bypass strict SElinux policies in order to be able
191 // to profile system server.
192 // NOTE 2: We could just not create the code section at all but we will need to
193 // special case too many cases.
194 int memmap_flags_prot_code = used_only_for_profile_data ? (kProtCode & ~PROT_EXEC) : kProtCode;
195
196 std::string error_str;
197 // Map name specific for android_os_Debug.cpp accounting.
198 // Map in low 4gb to simplify accessing root tables for x86_64.
199 // We could do PC-relative addressing to avoid this problem, but that
200 // would require reserving code and data area before submitting, which
201 // means more windows for the code memory to be RWX.
202 std::unique_ptr<MemMap> data_map(MemMap::MapAnonymous(
203 "data-code-cache", nullptr,
204 max_capacity,
205 kProtData,
206 /* low_4gb */ true,
207 /* reuse */ false,
208 &error_str,
209 use_ashmem));
210 if (data_map == nullptr) {
211 std::ostringstream oss;
212 oss << "Failed to create read write cache: " << error_str << " size=" << max_capacity;
213 *error_msg = oss.str();
214 return nullptr;
215 }
216
217 // Align both capacities to page size, as that's the unit mspaces use.
218 initial_capacity = RoundDown(initial_capacity, 2 * kPageSize);
219 max_capacity = RoundDown(max_capacity, 2 * kPageSize);
220
221 // Data cache is 1 / 2 of the map.
222 // TODO: Make this variable?
223 size_t data_size = max_capacity / 2;
224 size_t code_size = max_capacity - data_size;
225 DCHECK_EQ(code_size + data_size, max_capacity);
226 uint8_t* divider = data_map->Begin() + data_size;
227
228 MemMap* code_map = data_map->RemapAtEnd(
229 divider,
230 "jit-code-cache",
231 memmap_flags_prot_code | PROT_WRITE,
232 &error_str, use_ashmem);
233 if (code_map == nullptr) {
234 std::ostringstream oss;
235 oss << "Failed to create read write execute cache: " << error_str << " size=" << max_capacity;
236 *error_msg = oss.str();
237 return nullptr;
238 }
239 DCHECK_EQ(code_map->Begin(), divider);
240 data_size = initial_capacity / 2;
241 code_size = initial_capacity - data_size;
242 DCHECK_EQ(code_size + data_size, initial_capacity);
243 return new JitCodeCache(
244 code_map,
245 data_map.release(),
246 code_size,
247 data_size,
248 max_capacity,
249 garbage_collect_code,
250 memmap_flags_prot_code);
251 }
252
JitCodeCache(MemMap * code_map,MemMap * data_map,size_t initial_code_capacity,size_t initial_data_capacity,size_t max_capacity,bool garbage_collect_code,int memmap_flags_prot_code)253 JitCodeCache::JitCodeCache(MemMap* code_map,
254 MemMap* data_map,
255 size_t initial_code_capacity,
256 size_t initial_data_capacity,
257 size_t max_capacity,
258 bool garbage_collect_code,
259 int memmap_flags_prot_code)
260 : lock_("Jit code cache", kJitCodeCacheLock),
261 lock_cond_("Jit code cache condition variable", lock_),
262 collection_in_progress_(false),
263 code_map_(code_map),
264 data_map_(data_map),
265 max_capacity_(max_capacity),
266 current_capacity_(initial_code_capacity + initial_data_capacity),
267 code_end_(initial_code_capacity),
268 data_end_(initial_data_capacity),
269 last_collection_increased_code_cache_(false),
270 last_update_time_ns_(0),
271 garbage_collect_code_(garbage_collect_code),
272 used_memory_for_data_(0),
273 used_memory_for_code_(0),
274 number_of_compilations_(0),
275 number_of_osr_compilations_(0),
276 number_of_collections_(0),
277 histogram_stack_map_memory_use_("Memory used for stack maps", 16),
278 histogram_code_memory_use_("Memory used for compiled code", 16),
279 histogram_profiling_info_memory_use_("Memory used for profiling info", 16),
280 is_weak_access_enabled_(true),
281 inline_cache_cond_("Jit inline cache condition variable", lock_),
282 memmap_flags_prot_code_(memmap_flags_prot_code) {
283
284 DCHECK_GE(max_capacity, initial_code_capacity + initial_data_capacity);
285 code_mspace_ = create_mspace_with_base(code_map_->Begin(), code_end_, false /*locked*/);
286 data_mspace_ = create_mspace_with_base(data_map_->Begin(), data_end_, false /*locked*/);
287
288 if (code_mspace_ == nullptr || data_mspace_ == nullptr) {
289 PLOG(FATAL) << "create_mspace_with_base failed";
290 }
291
292 SetFootprintLimit(current_capacity_);
293
294 CheckedCall(mprotect,
295 "mprotect jit code cache",
296 code_map_->Begin(),
297 code_map_->Size(),
298 memmap_flags_prot_code_);
299 CheckedCall(mprotect,
300 "mprotect jit data cache",
301 data_map_->Begin(),
302 data_map_->Size(),
303 kProtData);
304
305 VLOG(jit) << "Created jit code cache: initial data size="
306 << PrettySize(initial_data_capacity)
307 << ", initial code size="
308 << PrettySize(initial_code_capacity);
309 }
310
~JitCodeCache()311 JitCodeCache::~JitCodeCache() {}
312
ContainsPc(const void * ptr) const313 bool JitCodeCache::ContainsPc(const void* ptr) const {
314 return code_map_->Begin() <= ptr && ptr < code_map_->End();
315 }
316
ContainsMethod(ArtMethod * method)317 bool JitCodeCache::ContainsMethod(ArtMethod* method) {
318 MutexLock mu(Thread::Current(), lock_);
319 if (UNLIKELY(method->IsNative())) {
320 auto it = jni_stubs_map_.find(JniStubKey(method));
321 if (it != jni_stubs_map_.end() &&
322 it->second.IsCompiled() &&
323 ContainsElement(it->second.GetMethods(), method)) {
324 return true;
325 }
326 } else {
327 for (const auto& it : method_code_map_) {
328 if (it.second == method) {
329 return true;
330 }
331 }
332 }
333 return false;
334 }
335
GetJniStubCode(ArtMethod * method)336 const void* JitCodeCache::GetJniStubCode(ArtMethod* method) {
337 DCHECK(method->IsNative());
338 MutexLock mu(Thread::Current(), lock_);
339 auto it = jni_stubs_map_.find(JniStubKey(method));
340 if (it != jni_stubs_map_.end()) {
341 JniStubData& data = it->second;
342 if (data.IsCompiled() && ContainsElement(data.GetMethods(), method)) {
343 return data.GetCode();
344 }
345 }
346 return nullptr;
347 }
348
349 class ScopedCodeCacheWrite : ScopedTrace {
350 public:
ScopedCodeCacheWrite(const JitCodeCache * const code_cache,bool only_for_tlb_shootdown=false)351 explicit ScopedCodeCacheWrite(const JitCodeCache* const code_cache,
352 bool only_for_tlb_shootdown = false)
353 : ScopedTrace("ScopedCodeCacheWrite"),
354 code_cache_(code_cache),
355 only_for_tlb_shootdown_(only_for_tlb_shootdown) {
356 ScopedTrace trace("mprotect all");
357 CheckedCall(
358 mprotect,
359 "make code writable",
360 code_cache_->code_map_->Begin(),
361 only_for_tlb_shootdown_ ? kPageSize : code_cache_->code_map_->Size(),
362 code_cache_->memmap_flags_prot_code_ | PROT_WRITE);
363 }
364
~ScopedCodeCacheWrite()365 ~ScopedCodeCacheWrite() {
366 ScopedTrace trace("mprotect code");
367 CheckedCall(
368 mprotect,
369 "make code protected",
370 code_cache_->code_map_->Begin(),
371 only_for_tlb_shootdown_ ? kPageSize : code_cache_->code_map_->Size(),
372 code_cache_->memmap_flags_prot_code_);
373 }
374
375 private:
376 const JitCodeCache* const code_cache_;
377
378 // If we're using ScopedCacheWrite only for TLB shootdown, we limit the scope of mprotect to
379 // one page.
380 const bool only_for_tlb_shootdown_;
381
382 DISALLOW_COPY_AND_ASSIGN(ScopedCodeCacheWrite);
383 };
384
CommitCode(Thread * self,ArtMethod * method,uint8_t * stack_map,uint8_t * method_info,uint8_t * roots_data,size_t frame_size_in_bytes,size_t core_spill_mask,size_t fp_spill_mask,const uint8_t * code,size_t code_size,size_t data_size,bool osr,Handle<mirror::ObjectArray<mirror::Object>> roots,bool has_should_deoptimize_flag,const ArenaSet<ArtMethod * > & cha_single_implementation_list)385 uint8_t* JitCodeCache::CommitCode(Thread* self,
386 ArtMethod* method,
387 uint8_t* stack_map,
388 uint8_t* method_info,
389 uint8_t* roots_data,
390 size_t frame_size_in_bytes,
391 size_t core_spill_mask,
392 size_t fp_spill_mask,
393 const uint8_t* code,
394 size_t code_size,
395 size_t data_size,
396 bool osr,
397 Handle<mirror::ObjectArray<mirror::Object>> roots,
398 bool has_should_deoptimize_flag,
399 const ArenaSet<ArtMethod*>& cha_single_implementation_list) {
400 uint8_t* result = CommitCodeInternal(self,
401 method,
402 stack_map,
403 method_info,
404 roots_data,
405 frame_size_in_bytes,
406 core_spill_mask,
407 fp_spill_mask,
408 code,
409 code_size,
410 data_size,
411 osr,
412 roots,
413 has_should_deoptimize_flag,
414 cha_single_implementation_list);
415 if (result == nullptr) {
416 // Retry.
417 GarbageCollectCache(self);
418 result = CommitCodeInternal(self,
419 method,
420 stack_map,
421 method_info,
422 roots_data,
423 frame_size_in_bytes,
424 core_spill_mask,
425 fp_spill_mask,
426 code,
427 code_size,
428 data_size,
429 osr,
430 roots,
431 has_should_deoptimize_flag,
432 cha_single_implementation_list);
433 }
434 return result;
435 }
436
WaitForPotentialCollectionToComplete(Thread * self)437 bool JitCodeCache::WaitForPotentialCollectionToComplete(Thread* self) {
438 bool in_collection = false;
439 while (collection_in_progress_) {
440 in_collection = true;
441 lock_cond_.Wait(self);
442 }
443 return in_collection;
444 }
445
FromCodeToAllocation(const void * code)446 static uintptr_t FromCodeToAllocation(const void* code) {
447 size_t alignment = GetInstructionSetAlignment(kRuntimeISA);
448 return reinterpret_cast<uintptr_t>(code) - RoundUp(sizeof(OatQuickMethodHeader), alignment);
449 }
450
ComputeRootTableSize(uint32_t number_of_roots)451 static uint32_t ComputeRootTableSize(uint32_t number_of_roots) {
452 return sizeof(uint32_t) + number_of_roots * sizeof(GcRoot<mirror::Object>);
453 }
454
GetNumberOfRoots(const uint8_t * stack_map)455 static uint32_t GetNumberOfRoots(const uint8_t* stack_map) {
456 // The length of the table is stored just before the stack map (and therefore at the end of
457 // the table itself), in order to be able to fetch it from a `stack_map` pointer.
458 return reinterpret_cast<const uint32_t*>(stack_map)[-1];
459 }
460
FillRootTableLength(uint8_t * roots_data,uint32_t length)461 static void FillRootTableLength(uint8_t* roots_data, uint32_t length) {
462 // Store the length of the table at the end. This will allow fetching it from a `stack_map`
463 // pointer.
464 reinterpret_cast<uint32_t*>(roots_data)[length] = length;
465 }
466
FromStackMapToRoots(const uint8_t * stack_map_data)467 static const uint8_t* FromStackMapToRoots(const uint8_t* stack_map_data) {
468 return stack_map_data - ComputeRootTableSize(GetNumberOfRoots(stack_map_data));
469 }
470
FillRootTable(uint8_t * roots_data,Handle<mirror::ObjectArray<mirror::Object>> roots)471 static void FillRootTable(uint8_t* roots_data, Handle<mirror::ObjectArray<mirror::Object>> roots)
472 REQUIRES_SHARED(Locks::mutator_lock_) {
473 GcRoot<mirror::Object>* gc_roots = reinterpret_cast<GcRoot<mirror::Object>*>(roots_data);
474 const uint32_t length = roots->GetLength();
475 // Put all roots in `roots_data`.
476 for (uint32_t i = 0; i < length; ++i) {
477 ObjPtr<mirror::Object> object = roots->Get(i);
478 if (kIsDebugBuild) {
479 // Ensure the string is strongly interned. b/32995596
480 if (object->IsString()) {
481 ObjPtr<mirror::String> str = reinterpret_cast<mirror::String*>(object.Ptr());
482 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
483 CHECK(class_linker->GetInternTable()->LookupStrong(Thread::Current(), str) != nullptr);
484 }
485 }
486 gc_roots[i] = GcRoot<mirror::Object>(object);
487 }
488 }
489
GetRootTable(const void * code_ptr,uint32_t * number_of_roots=nullptr)490 static uint8_t* GetRootTable(const void* code_ptr, uint32_t* number_of_roots = nullptr) {
491 OatQuickMethodHeader* method_header = OatQuickMethodHeader::FromCodePointer(code_ptr);
492 uint8_t* data = method_header->GetOptimizedCodeInfoPtr();
493 uint32_t roots = GetNumberOfRoots(data);
494 if (number_of_roots != nullptr) {
495 *number_of_roots = roots;
496 }
497 return data - ComputeRootTableSize(roots);
498 }
499
500 // Use a sentinel for marking entries in the JIT table that have been cleared.
501 // This helps diagnosing in case the compiled code tries to wrongly access such
502 // entries.
503 static mirror::Class* const weak_sentinel =
504 reinterpret_cast<mirror::Class*>(Context::kBadGprBase + 0xff);
505
506 // Helper for the GC to process a weak class in a JIT root table.
ProcessWeakClass(GcRoot<mirror::Class> * root_ptr,IsMarkedVisitor * visitor,mirror::Class * update)507 static inline void ProcessWeakClass(GcRoot<mirror::Class>* root_ptr,
508 IsMarkedVisitor* visitor,
509 mirror::Class* update)
510 REQUIRES_SHARED(Locks::mutator_lock_) {
511 // This does not need a read barrier because this is called by GC.
512 mirror::Class* cls = root_ptr->Read<kWithoutReadBarrier>();
513 if (cls != nullptr && cls != weak_sentinel) {
514 DCHECK((cls->IsClass<kDefaultVerifyFlags, kWithoutReadBarrier>()));
515 // Look at the classloader of the class to know if it has been unloaded.
516 // This does not need a read barrier because this is called by GC.
517 mirror::Object* class_loader =
518 cls->GetClassLoader<kDefaultVerifyFlags, kWithoutReadBarrier>();
519 if (class_loader == nullptr || visitor->IsMarked(class_loader) != nullptr) {
520 // The class loader is live, update the entry if the class has moved.
521 mirror::Class* new_cls = down_cast<mirror::Class*>(visitor->IsMarked(cls));
522 // Note that new_object can be null for CMS and newly allocated objects.
523 if (new_cls != nullptr && new_cls != cls) {
524 *root_ptr = GcRoot<mirror::Class>(new_cls);
525 }
526 } else {
527 // The class loader is not live, clear the entry.
528 *root_ptr = GcRoot<mirror::Class>(update);
529 }
530 }
531 }
532
SweepRootTables(IsMarkedVisitor * visitor)533 void JitCodeCache::SweepRootTables(IsMarkedVisitor* visitor) {
534 MutexLock mu(Thread::Current(), lock_);
535 for (const auto& entry : method_code_map_) {
536 uint32_t number_of_roots = 0;
537 uint8_t* roots_data = GetRootTable(entry.first, &number_of_roots);
538 GcRoot<mirror::Object>* roots = reinterpret_cast<GcRoot<mirror::Object>*>(roots_data);
539 for (uint32_t i = 0; i < number_of_roots; ++i) {
540 // This does not need a read barrier because this is called by GC.
541 mirror::Object* object = roots[i].Read<kWithoutReadBarrier>();
542 if (object == nullptr || object == weak_sentinel) {
543 // entry got deleted in a previous sweep.
544 } else if (object->IsString<kDefaultVerifyFlags, kWithoutReadBarrier>()) {
545 mirror::Object* new_object = visitor->IsMarked(object);
546 // We know the string is marked because it's a strongly-interned string that
547 // is always alive. The IsMarked implementation of the CMS collector returns
548 // null for newly allocated objects, but we know those haven't moved. Therefore,
549 // only update the entry if we get a different non-null string.
550 // TODO: Do not use IsMarked for j.l.Class, and adjust once we move this method
551 // out of the weak access/creation pause. b/32167580
552 if (new_object != nullptr && new_object != object) {
553 DCHECK(new_object->IsString());
554 roots[i] = GcRoot<mirror::Object>(new_object);
555 }
556 } else {
557 ProcessWeakClass(
558 reinterpret_cast<GcRoot<mirror::Class>*>(&roots[i]), visitor, weak_sentinel);
559 }
560 }
561 }
562 // Walk over inline caches to clear entries containing unloaded classes.
563 for (ProfilingInfo* info : profiling_infos_) {
564 for (size_t i = 0; i < info->number_of_inline_caches_; ++i) {
565 InlineCache* cache = &info->cache_[i];
566 for (size_t j = 0; j < InlineCache::kIndividualCacheSize; ++j) {
567 ProcessWeakClass(&cache->classes_[j], visitor, nullptr);
568 }
569 }
570 }
571 }
572
FreeCode(const void * code_ptr)573 void JitCodeCache::FreeCode(const void* code_ptr) {
574 uintptr_t allocation = FromCodeToAllocation(code_ptr);
575 // Notify native debugger that we are about to remove the code.
576 // It does nothing if we are not using native debugger.
577 MutexLock mu(Thread::Current(), *Locks::native_debug_interface_lock_);
578 RemoveNativeDebugInfoForJit(code_ptr);
579 if (OatQuickMethodHeader::FromCodePointer(code_ptr)->IsOptimized()) {
580 FreeData(GetRootTable(code_ptr));
581 } // else this is a JNI stub without any data.
582 FreeCode(reinterpret_cast<uint8_t*>(allocation));
583 }
584
FreeAllMethodHeaders(const std::unordered_set<OatQuickMethodHeader * > & method_headers)585 void JitCodeCache::FreeAllMethodHeaders(
586 const std::unordered_set<OatQuickMethodHeader*>& method_headers) {
587 {
588 MutexLock mu(Thread::Current(), *Locks::cha_lock_);
589 Runtime::Current()->GetClassLinker()->GetClassHierarchyAnalysis()
590 ->RemoveDependentsWithMethodHeaders(method_headers);
591 }
592
593 // We need to remove entries in method_headers from CHA dependencies
594 // first since once we do FreeCode() below, the memory can be reused
595 // so it's possible for the same method_header to start representing
596 // different compile code.
597 MutexLock mu(Thread::Current(), lock_);
598 ScopedCodeCacheWrite scc(this);
599 for (const OatQuickMethodHeader* method_header : method_headers) {
600 FreeCode(method_header->GetCode());
601 }
602 }
603
RemoveMethodsIn(Thread * self,const LinearAlloc & alloc)604 void JitCodeCache::RemoveMethodsIn(Thread* self, const LinearAlloc& alloc) {
605 ScopedTrace trace(__PRETTY_FUNCTION__);
606 // We use a set to first collect all method_headers whose code need to be
607 // removed. We need to free the underlying code after we remove CHA dependencies
608 // for entries in this set. And it's more efficient to iterate through
609 // the CHA dependency map just once with an unordered_set.
610 std::unordered_set<OatQuickMethodHeader*> method_headers;
611 {
612 MutexLock mu(self, lock_);
613 // We do not check if a code cache GC is in progress, as this method comes
614 // with the classlinker_classes_lock_ held, and suspending ourselves could
615 // lead to a deadlock.
616 {
617 ScopedCodeCacheWrite scc(this);
618 for (auto it = jni_stubs_map_.begin(); it != jni_stubs_map_.end();) {
619 it->second.RemoveMethodsIn(alloc);
620 if (it->second.GetMethods().empty()) {
621 method_headers.insert(OatQuickMethodHeader::FromCodePointer(it->second.GetCode()));
622 it = jni_stubs_map_.erase(it);
623 } else {
624 it->first.UpdateShorty(it->second.GetMethods().front());
625 ++it;
626 }
627 }
628 for (auto it = method_code_map_.begin(); it != method_code_map_.end();) {
629 if (alloc.ContainsUnsafe(it->second)) {
630 method_headers.insert(OatQuickMethodHeader::FromCodePointer(it->first));
631 it = method_code_map_.erase(it);
632 } else {
633 ++it;
634 }
635 }
636 }
637 for (auto it = osr_code_map_.begin(); it != osr_code_map_.end();) {
638 if (alloc.ContainsUnsafe(it->first)) {
639 // Note that the code has already been pushed to method_headers in the loop
640 // above and is going to be removed in FreeCode() below.
641 it = osr_code_map_.erase(it);
642 } else {
643 ++it;
644 }
645 }
646 for (auto it = profiling_infos_.begin(); it != profiling_infos_.end();) {
647 ProfilingInfo* info = *it;
648 if (alloc.ContainsUnsafe(info->GetMethod())) {
649 info->GetMethod()->SetProfilingInfo(nullptr);
650 FreeData(reinterpret_cast<uint8_t*>(info));
651 it = profiling_infos_.erase(it);
652 } else {
653 ++it;
654 }
655 }
656 }
657 FreeAllMethodHeaders(method_headers);
658 }
659
IsWeakAccessEnabled(Thread * self) const660 bool JitCodeCache::IsWeakAccessEnabled(Thread* self) const {
661 return kUseReadBarrier
662 ? self->GetWeakRefAccessEnabled()
663 : is_weak_access_enabled_.LoadSequentiallyConsistent();
664 }
665
WaitUntilInlineCacheAccessible(Thread * self)666 void JitCodeCache::WaitUntilInlineCacheAccessible(Thread* self) {
667 if (IsWeakAccessEnabled(self)) {
668 return;
669 }
670 ScopedThreadSuspension sts(self, kWaitingWeakGcRootRead);
671 MutexLock mu(self, lock_);
672 while (!IsWeakAccessEnabled(self)) {
673 inline_cache_cond_.Wait(self);
674 }
675 }
676
BroadcastForInlineCacheAccess()677 void JitCodeCache::BroadcastForInlineCacheAccess() {
678 Thread* self = Thread::Current();
679 MutexLock mu(self, lock_);
680 inline_cache_cond_.Broadcast(self);
681 }
682
AllowInlineCacheAccess()683 void JitCodeCache::AllowInlineCacheAccess() {
684 DCHECK(!kUseReadBarrier);
685 is_weak_access_enabled_.StoreSequentiallyConsistent(true);
686 BroadcastForInlineCacheAccess();
687 }
688
DisallowInlineCacheAccess()689 void JitCodeCache::DisallowInlineCacheAccess() {
690 DCHECK(!kUseReadBarrier);
691 is_weak_access_enabled_.StoreSequentiallyConsistent(false);
692 }
693
CopyInlineCacheInto(const InlineCache & ic,Handle<mirror::ObjectArray<mirror::Class>> array)694 void JitCodeCache::CopyInlineCacheInto(const InlineCache& ic,
695 Handle<mirror::ObjectArray<mirror::Class>> array) {
696 WaitUntilInlineCacheAccessible(Thread::Current());
697 // Note that we don't need to lock `lock_` here, the compiler calling
698 // this method has already ensured the inline cache will not be deleted.
699 for (size_t in_cache = 0, in_array = 0;
700 in_cache < InlineCache::kIndividualCacheSize;
701 ++in_cache) {
702 mirror::Class* object = ic.classes_[in_cache].Read();
703 if (object != nullptr) {
704 array->Set(in_array++, object);
705 }
706 }
707 }
708
ClearMethodCounter(ArtMethod * method,bool was_warm)709 static void ClearMethodCounter(ArtMethod* method, bool was_warm) {
710 if (was_warm) {
711 // Don't do any read barrier, as the declaring class of `method` may
712 // be in the process of being GC'ed (reading the declaring class is done
713 // when DCHECKing the declaring class is resolved, which we know it is
714 // at this point).
715 method->SetPreviouslyWarm<kWithoutReadBarrier>();
716 }
717 // We reset the counter to 1 so that the profile knows that the method was executed at least once.
718 // This is required for layout purposes.
719 // We also need to make sure we'll pass the warmup threshold again, so we set to 0 if
720 // the warmup threshold is 1.
721 uint16_t jit_warmup_threshold = Runtime::Current()->GetJITOptions()->GetWarmupThreshold();
722 method->SetCounter(std::min(jit_warmup_threshold - 1, 1));
723 }
724
CommitCodeInternal(Thread * self,ArtMethod * method,uint8_t * stack_map,uint8_t * method_info,uint8_t * roots_data,size_t frame_size_in_bytes,size_t core_spill_mask,size_t fp_spill_mask,const uint8_t * code,size_t code_size,size_t data_size,bool osr,Handle<mirror::ObjectArray<mirror::Object>> roots,bool has_should_deoptimize_flag,const ArenaSet<ArtMethod * > & cha_single_implementation_list)725 uint8_t* JitCodeCache::CommitCodeInternal(Thread* self,
726 ArtMethod* method,
727 uint8_t* stack_map,
728 uint8_t* method_info,
729 uint8_t* roots_data,
730 size_t frame_size_in_bytes,
731 size_t core_spill_mask,
732 size_t fp_spill_mask,
733 const uint8_t* code,
734 size_t code_size,
735 size_t data_size,
736 bool osr,
737 Handle<mirror::ObjectArray<mirror::Object>> roots,
738 bool has_should_deoptimize_flag,
739 const ArenaSet<ArtMethod*>&
740 cha_single_implementation_list) {
741 DCHECK_NE(stack_map != nullptr, method->IsNative());
742 DCHECK(!method->IsNative() || !osr);
743 size_t alignment = GetInstructionSetAlignment(kRuntimeISA);
744 // Ensure the header ends up at expected instruction alignment.
745 size_t header_size = RoundUp(sizeof(OatQuickMethodHeader), alignment);
746 size_t total_size = header_size + code_size;
747
748 OatQuickMethodHeader* method_header = nullptr;
749 uint8_t* code_ptr = nullptr;
750 uint8_t* memory = nullptr;
751 {
752 ScopedThreadSuspension sts(self, kSuspended);
753 MutexLock mu(self, lock_);
754 WaitForPotentialCollectionToComplete(self);
755 {
756 ScopedCodeCacheWrite scc(this);
757 memory = AllocateCode(total_size);
758 if (memory == nullptr) {
759 return nullptr;
760 }
761 code_ptr = memory + header_size;
762
763 std::copy(code, code + code_size, code_ptr);
764 method_header = OatQuickMethodHeader::FromCodePointer(code_ptr);
765 new (method_header) OatQuickMethodHeader(
766 (stack_map != nullptr) ? code_ptr - stack_map : 0u,
767 (method_info != nullptr) ? code_ptr - method_info : 0u,
768 frame_size_in_bytes,
769 core_spill_mask,
770 fp_spill_mask,
771 code_size);
772 // Flush caches before we remove write permission because some ARMv8 Qualcomm kernels may
773 // trigger a segfault if a page fault occurs when requesting a cache maintenance operation.
774 // This is a kernel bug that we need to work around until affected devices (e.g. Nexus 5X and
775 // 6P) stop being supported or their kernels are fixed.
776 //
777 // For reference, this behavior is caused by this commit:
778 // https://android.googlesource.com/kernel/msm/+/3fbe6bc28a6b9939d0650f2f17eb5216c719950c
779 FlushInstructionCache(reinterpret_cast<char*>(code_ptr),
780 reinterpret_cast<char*>(code_ptr + code_size));
781 DCHECK(!Runtime::Current()->IsAotCompiler());
782 if (has_should_deoptimize_flag) {
783 method_header->SetHasShouldDeoptimizeFlag();
784 }
785 }
786
787 number_of_compilations_++;
788 }
789 // We need to update the entry point in the runnable state for the instrumentation.
790 {
791 // Need cha_lock_ for checking all single-implementation flags and register
792 // dependencies.
793 MutexLock cha_mu(self, *Locks::cha_lock_);
794 bool single_impl_still_valid = true;
795 for (ArtMethod* single_impl : cha_single_implementation_list) {
796 if (!single_impl->HasSingleImplementation()) {
797 // Simply discard the compiled code. Clear the counter so that it may be recompiled later.
798 // Hopefully the class hierarchy will be more stable when compilation is retried.
799 single_impl_still_valid = false;
800 ClearMethodCounter(method, /*was_warm*/ false);
801 break;
802 }
803 }
804
805 // Discard the code if any single-implementation assumptions are now invalid.
806 if (!single_impl_still_valid) {
807 VLOG(jit) << "JIT discarded jitted code due to invalid single-implementation assumptions.";
808 return nullptr;
809 }
810 DCHECK(cha_single_implementation_list.empty() || !Runtime::Current()->IsJavaDebuggable())
811 << "Should not be using cha on debuggable apps/runs!";
812
813 for (ArtMethod* single_impl : cha_single_implementation_list) {
814 Runtime::Current()->GetClassLinker()->GetClassHierarchyAnalysis()->AddDependency(
815 single_impl, method, method_header);
816 }
817
818 // The following needs to be guarded by cha_lock_ also. Otherwise it's
819 // possible that the compiled code is considered invalidated by some class linking,
820 // but below we still make the compiled code valid for the method.
821 MutexLock mu(self, lock_);
822 if (UNLIKELY(method->IsNative())) {
823 DCHECK(stack_map == nullptr);
824 DCHECK(roots_data == nullptr);
825 auto it = jni_stubs_map_.find(JniStubKey(method));
826 DCHECK(it != jni_stubs_map_.end())
827 << "Entry inserted in NotifyCompilationOf() should be alive.";
828 JniStubData* data = &it->second;
829 DCHECK(ContainsElement(data->GetMethods(), method))
830 << "Entry inserted in NotifyCompilationOf() should contain this method.";
831 data->SetCode(code_ptr);
832 instrumentation::Instrumentation* instrum = Runtime::Current()->GetInstrumentation();
833 for (ArtMethod* m : data->GetMethods()) {
834 instrum->UpdateMethodsCode(m, method_header->GetEntryPoint());
835 }
836 } else {
837 // Fill the root table before updating the entry point.
838 DCHECK_EQ(FromStackMapToRoots(stack_map), roots_data);
839 DCHECK_LE(roots_data, stack_map);
840 FillRootTable(roots_data, roots);
841 {
842 // Flush data cache, as compiled code references literals in it.
843 // We also need a TLB shootdown to act as memory barrier across cores.
844 ScopedCodeCacheWrite ccw(this, /* only_for_tlb_shootdown */ true);
845 FlushDataCache(reinterpret_cast<char*>(roots_data),
846 reinterpret_cast<char*>(roots_data + data_size));
847 }
848 method_code_map_.Put(code_ptr, method);
849 if (osr) {
850 number_of_osr_compilations_++;
851 osr_code_map_.Put(method, code_ptr);
852 } else {
853 Runtime::Current()->GetInstrumentation()->UpdateMethodsCode(
854 method, method_header->GetEntryPoint());
855 }
856 }
857 if (collection_in_progress_) {
858 // We need to update the live bitmap if there is a GC to ensure it sees this new
859 // code.
860 GetLiveBitmap()->AtomicTestAndSet(FromCodeToAllocation(code_ptr));
861 }
862 last_update_time_ns_.StoreRelease(NanoTime());
863 VLOG(jit)
864 << "JIT added (osr=" << std::boolalpha << osr << std::noboolalpha << ") "
865 << ArtMethod::PrettyMethod(method) << "@" << method
866 << " ccache_size=" << PrettySize(CodeCacheSizeLocked()) << ": "
867 << " dcache_size=" << PrettySize(DataCacheSizeLocked()) << ": "
868 << reinterpret_cast<const void*>(method_header->GetEntryPoint()) << ","
869 << reinterpret_cast<const void*>(method_header->GetEntryPoint() +
870 method_header->GetCodeSize());
871 histogram_code_memory_use_.AddValue(code_size);
872 if (code_size > kCodeSizeLogThreshold) {
873 LOG(INFO) << "JIT allocated "
874 << PrettySize(code_size)
875 << " for compiled code of "
876 << ArtMethod::PrettyMethod(method);
877 }
878 }
879
880 return reinterpret_cast<uint8_t*>(method_header);
881 }
882
CodeCacheSize()883 size_t JitCodeCache::CodeCacheSize() {
884 MutexLock mu(Thread::Current(), lock_);
885 return CodeCacheSizeLocked();
886 }
887
RemoveMethod(ArtMethod * method,bool release_memory)888 bool JitCodeCache::RemoveMethod(ArtMethod* method, bool release_memory) {
889 // This function is used only for testing and only with non-native methods.
890 CHECK(!method->IsNative());
891
892 MutexLock mu(Thread::Current(), lock_);
893
894 bool osr = osr_code_map_.find(method) != osr_code_map_.end();
895 bool in_cache = RemoveMethodLocked(method, release_memory);
896
897 if (!in_cache) {
898 return false;
899 }
900
901 method->ClearCounter();
902 Runtime::Current()->GetInstrumentation()->UpdateMethodsCode(
903 method, GetQuickToInterpreterBridge());
904 VLOG(jit)
905 << "JIT removed (osr=" << std::boolalpha << osr << std::noboolalpha << ") "
906 << ArtMethod::PrettyMethod(method) << "@" << method
907 << " ccache_size=" << PrettySize(CodeCacheSizeLocked()) << ": "
908 << " dcache_size=" << PrettySize(DataCacheSizeLocked());
909 return true;
910 }
911
RemoveMethodLocked(ArtMethod * method,bool release_memory)912 bool JitCodeCache::RemoveMethodLocked(ArtMethod* method, bool release_memory) {
913 if (LIKELY(!method->IsNative())) {
914 ProfilingInfo* info = method->GetProfilingInfo(kRuntimePointerSize);
915 if (info != nullptr) {
916 RemoveElement(profiling_infos_, info);
917 }
918 method->SetProfilingInfo(nullptr);
919 }
920
921 bool in_cache = false;
922 ScopedCodeCacheWrite ccw(this);
923 if (UNLIKELY(method->IsNative())) {
924 auto it = jni_stubs_map_.find(JniStubKey(method));
925 if (it != jni_stubs_map_.end() && it->second.RemoveMethod(method)) {
926 in_cache = true;
927 if (it->second.GetMethods().empty()) {
928 if (release_memory) {
929 FreeCode(it->second.GetCode());
930 }
931 jni_stubs_map_.erase(it);
932 } else {
933 it->first.UpdateShorty(it->second.GetMethods().front());
934 }
935 }
936 } else {
937 for (auto it = method_code_map_.begin(); it != method_code_map_.end();) {
938 if (it->second == method) {
939 in_cache = true;
940 if (release_memory) {
941 FreeCode(it->first);
942 }
943 it = method_code_map_.erase(it);
944 } else {
945 ++it;
946 }
947 }
948
949 auto osr_it = osr_code_map_.find(method);
950 if (osr_it != osr_code_map_.end()) {
951 osr_code_map_.erase(osr_it);
952 }
953 }
954
955 return in_cache;
956 }
957
958 // This notifies the code cache that the given method has been redefined and that it should remove
959 // any cached information it has on the method. All threads must be suspended before calling this
960 // method. The compiled code for the method (if there is any) must not be in any threads call stack.
NotifyMethodRedefined(ArtMethod * method)961 void JitCodeCache::NotifyMethodRedefined(ArtMethod* method) {
962 MutexLock mu(Thread::Current(), lock_);
963 RemoveMethodLocked(method, /* release_memory */ true);
964 }
965
966 // This invalidates old_method. Once this function returns one can no longer use old_method to
967 // execute code unless it is fixed up. This fixup will happen later in the process of installing a
968 // class redefinition.
969 // TODO We should add some info to ArtMethod to note that 'old_method' has been invalidated and
970 // shouldn't be used since it is no longer logically in the jit code cache.
971 // TODO We should add DCHECKS that validate that the JIT is paused when this method is entered.
MoveObsoleteMethod(ArtMethod * old_method,ArtMethod * new_method)972 void JitCodeCache::MoveObsoleteMethod(ArtMethod* old_method, ArtMethod* new_method) {
973 MutexLock mu(Thread::Current(), lock_);
974 if (old_method->IsNative()) {
975 // Update methods in jni_stubs_map_.
976 for (auto& entry : jni_stubs_map_) {
977 JniStubData& data = entry.second;
978 data.MoveObsoleteMethod(old_method, new_method);
979 }
980 return;
981 }
982 // Update ProfilingInfo to the new one and remove it from the old_method.
983 if (old_method->GetProfilingInfo(kRuntimePointerSize) != nullptr) {
984 DCHECK_EQ(old_method->GetProfilingInfo(kRuntimePointerSize)->GetMethod(), old_method);
985 ProfilingInfo* info = old_method->GetProfilingInfo(kRuntimePointerSize);
986 old_method->SetProfilingInfo(nullptr);
987 // Since the JIT should be paused and all threads suspended by the time this is called these
988 // checks should always pass.
989 DCHECK(!info->IsInUseByCompiler());
990 new_method->SetProfilingInfo(info);
991 info->method_ = new_method;
992 }
993 // Update method_code_map_ to point to the new method.
994 for (auto& it : method_code_map_) {
995 if (it.second == old_method) {
996 it.second = new_method;
997 }
998 }
999 // Update osr_code_map_ to point to the new method.
1000 auto code_map = osr_code_map_.find(old_method);
1001 if (code_map != osr_code_map_.end()) {
1002 osr_code_map_.Put(new_method, code_map->second);
1003 osr_code_map_.erase(old_method);
1004 }
1005 }
1006
CodeCacheSizeLocked()1007 size_t JitCodeCache::CodeCacheSizeLocked() {
1008 return used_memory_for_code_;
1009 }
1010
DataCacheSize()1011 size_t JitCodeCache::DataCacheSize() {
1012 MutexLock mu(Thread::Current(), lock_);
1013 return DataCacheSizeLocked();
1014 }
1015
DataCacheSizeLocked()1016 size_t JitCodeCache::DataCacheSizeLocked() {
1017 return used_memory_for_data_;
1018 }
1019
ClearData(Thread * self,uint8_t * stack_map_data,uint8_t * roots_data)1020 void JitCodeCache::ClearData(Thread* self,
1021 uint8_t* stack_map_data,
1022 uint8_t* roots_data) {
1023 DCHECK_EQ(FromStackMapToRoots(stack_map_data), roots_data);
1024 MutexLock mu(self, lock_);
1025 FreeData(reinterpret_cast<uint8_t*>(roots_data));
1026 }
1027
ReserveData(Thread * self,size_t stack_map_size,size_t method_info_size,size_t number_of_roots,ArtMethod * method,uint8_t ** stack_map_data,uint8_t ** method_info_data,uint8_t ** roots_data)1028 size_t JitCodeCache::ReserveData(Thread* self,
1029 size_t stack_map_size,
1030 size_t method_info_size,
1031 size_t number_of_roots,
1032 ArtMethod* method,
1033 uint8_t** stack_map_data,
1034 uint8_t** method_info_data,
1035 uint8_t** roots_data) {
1036 size_t table_size = ComputeRootTableSize(number_of_roots);
1037 size_t size = RoundUp(stack_map_size + method_info_size + table_size, sizeof(void*));
1038 uint8_t* result = nullptr;
1039
1040 {
1041 ScopedThreadSuspension sts(self, kSuspended);
1042 MutexLock mu(self, lock_);
1043 WaitForPotentialCollectionToComplete(self);
1044 result = AllocateData(size);
1045 }
1046
1047 if (result == nullptr) {
1048 // Retry.
1049 GarbageCollectCache(self);
1050 ScopedThreadSuspension sts(self, kSuspended);
1051 MutexLock mu(self, lock_);
1052 WaitForPotentialCollectionToComplete(self);
1053 result = AllocateData(size);
1054 }
1055
1056 MutexLock mu(self, lock_);
1057 histogram_stack_map_memory_use_.AddValue(size);
1058 if (size > kStackMapSizeLogThreshold) {
1059 LOG(INFO) << "JIT allocated "
1060 << PrettySize(size)
1061 << " for stack maps of "
1062 << ArtMethod::PrettyMethod(method);
1063 }
1064 if (result != nullptr) {
1065 *roots_data = result;
1066 *stack_map_data = result + table_size;
1067 *method_info_data = *stack_map_data + stack_map_size;
1068 FillRootTableLength(*roots_data, number_of_roots);
1069 return size;
1070 } else {
1071 *roots_data = nullptr;
1072 *stack_map_data = nullptr;
1073 *method_info_data = nullptr;
1074 return 0;
1075 }
1076 }
1077
1078 class MarkCodeVisitor FINAL : public StackVisitor {
1079 public:
MarkCodeVisitor(Thread * thread_in,JitCodeCache * code_cache_in)1080 MarkCodeVisitor(Thread* thread_in, JitCodeCache* code_cache_in)
1081 : StackVisitor(thread_in, nullptr, StackVisitor::StackWalkKind::kSkipInlinedFrames),
1082 code_cache_(code_cache_in),
1083 bitmap_(code_cache_->GetLiveBitmap()) {}
1084
VisitFrame()1085 bool VisitFrame() OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_) {
1086 const OatQuickMethodHeader* method_header = GetCurrentOatQuickMethodHeader();
1087 if (method_header == nullptr) {
1088 return true;
1089 }
1090 const void* code = method_header->GetCode();
1091 if (code_cache_->ContainsPc(code)) {
1092 // Use the atomic set version, as multiple threads are executing this code.
1093 bitmap_->AtomicTestAndSet(FromCodeToAllocation(code));
1094 }
1095 return true;
1096 }
1097
1098 private:
1099 JitCodeCache* const code_cache_;
1100 CodeCacheBitmap* const bitmap_;
1101 };
1102
1103 class MarkCodeClosure FINAL : public Closure {
1104 public:
MarkCodeClosure(JitCodeCache * code_cache,Barrier * barrier)1105 MarkCodeClosure(JitCodeCache* code_cache, Barrier* barrier)
1106 : code_cache_(code_cache), barrier_(barrier) {}
1107
Run(Thread * thread)1108 void Run(Thread* thread) OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_) {
1109 ScopedTrace trace(__PRETTY_FUNCTION__);
1110 DCHECK(thread == Thread::Current() || thread->IsSuspended());
1111 MarkCodeVisitor visitor(thread, code_cache_);
1112 visitor.WalkStack();
1113 if (kIsDebugBuild) {
1114 // The stack walking code queries the side instrumentation stack if it
1115 // sees an instrumentation exit pc, so the JIT code of methods in that stack
1116 // must have been seen. We sanity check this below.
1117 for (const instrumentation::InstrumentationStackFrame& frame
1118 : *thread->GetInstrumentationStack()) {
1119 // The 'method_' in InstrumentationStackFrame is the one that has return_pc_ in
1120 // its stack frame, it is not the method owning return_pc_. We just pass null to
1121 // LookupMethodHeader: the method is only checked against in debug builds.
1122 OatQuickMethodHeader* method_header =
1123 code_cache_->LookupMethodHeader(frame.return_pc_, /* method */ nullptr);
1124 if (method_header != nullptr) {
1125 const void* code = method_header->GetCode();
1126 CHECK(code_cache_->GetLiveBitmap()->Test(FromCodeToAllocation(code)));
1127 }
1128 }
1129 }
1130 barrier_->Pass(Thread::Current());
1131 }
1132
1133 private:
1134 JitCodeCache* const code_cache_;
1135 Barrier* const barrier_;
1136 };
1137
NotifyCollectionDone(Thread * self)1138 void JitCodeCache::NotifyCollectionDone(Thread* self) {
1139 collection_in_progress_ = false;
1140 lock_cond_.Broadcast(self);
1141 }
1142
SetFootprintLimit(size_t new_footprint)1143 void JitCodeCache::SetFootprintLimit(size_t new_footprint) {
1144 size_t per_space_footprint = new_footprint / 2;
1145 DCHECK(IsAlignedParam(per_space_footprint, kPageSize));
1146 DCHECK_EQ(per_space_footprint * 2, new_footprint);
1147 mspace_set_footprint_limit(data_mspace_, per_space_footprint);
1148 {
1149 ScopedCodeCacheWrite scc(this);
1150 mspace_set_footprint_limit(code_mspace_, per_space_footprint);
1151 }
1152 }
1153
IncreaseCodeCacheCapacity()1154 bool JitCodeCache::IncreaseCodeCacheCapacity() {
1155 if (current_capacity_ == max_capacity_) {
1156 return false;
1157 }
1158
1159 // Double the capacity if we're below 1MB, or increase it by 1MB if
1160 // we're above.
1161 if (current_capacity_ < 1 * MB) {
1162 current_capacity_ *= 2;
1163 } else {
1164 current_capacity_ += 1 * MB;
1165 }
1166 if (current_capacity_ > max_capacity_) {
1167 current_capacity_ = max_capacity_;
1168 }
1169
1170 VLOG(jit) << "Increasing code cache capacity to " << PrettySize(current_capacity_);
1171
1172 SetFootprintLimit(current_capacity_);
1173
1174 return true;
1175 }
1176
MarkCompiledCodeOnThreadStacks(Thread * self)1177 void JitCodeCache::MarkCompiledCodeOnThreadStacks(Thread* self) {
1178 Barrier barrier(0);
1179 size_t threads_running_checkpoint = 0;
1180 MarkCodeClosure closure(this, &barrier);
1181 threads_running_checkpoint = Runtime::Current()->GetThreadList()->RunCheckpoint(&closure);
1182 // Now that we have run our checkpoint, move to a suspended state and wait
1183 // for other threads to run the checkpoint.
1184 ScopedThreadSuspension sts(self, kSuspended);
1185 if (threads_running_checkpoint != 0) {
1186 barrier.Increment(self, threads_running_checkpoint);
1187 }
1188 }
1189
ShouldDoFullCollection()1190 bool JitCodeCache::ShouldDoFullCollection() {
1191 if (current_capacity_ == max_capacity_) {
1192 // Always do a full collection when the code cache is full.
1193 return true;
1194 } else if (current_capacity_ < kReservedCapacity) {
1195 // Always do partial collection when the code cache size is below the reserved
1196 // capacity.
1197 return false;
1198 } else if (last_collection_increased_code_cache_) {
1199 // This time do a full collection.
1200 return true;
1201 } else {
1202 // This time do a partial collection.
1203 return false;
1204 }
1205 }
1206
GarbageCollectCache(Thread * self)1207 void JitCodeCache::GarbageCollectCache(Thread* self) {
1208 ScopedTrace trace(__FUNCTION__);
1209 if (!garbage_collect_code_) {
1210 MutexLock mu(self, lock_);
1211 IncreaseCodeCacheCapacity();
1212 return;
1213 }
1214
1215 // Wait for an existing collection, or let everyone know we are starting one.
1216 {
1217 ScopedThreadSuspension sts(self, kSuspended);
1218 MutexLock mu(self, lock_);
1219 if (WaitForPotentialCollectionToComplete(self)) {
1220 return;
1221 } else {
1222 number_of_collections_++;
1223 live_bitmap_.reset(CodeCacheBitmap::Create(
1224 "code-cache-bitmap",
1225 reinterpret_cast<uintptr_t>(code_map_->Begin()),
1226 reinterpret_cast<uintptr_t>(code_map_->Begin() + current_capacity_ / 2)));
1227 collection_in_progress_ = true;
1228 }
1229 }
1230
1231 TimingLogger logger("JIT code cache timing logger", true, VLOG_IS_ON(jit));
1232 {
1233 TimingLogger::ScopedTiming st("Code cache collection", &logger);
1234
1235 bool do_full_collection = false;
1236 {
1237 MutexLock mu(self, lock_);
1238 do_full_collection = ShouldDoFullCollection();
1239 }
1240
1241 VLOG(jit) << "Do "
1242 << (do_full_collection ? "full" : "partial")
1243 << " code cache collection, code="
1244 << PrettySize(CodeCacheSize())
1245 << ", data=" << PrettySize(DataCacheSize());
1246
1247 DoCollection(self, /* collect_profiling_info */ do_full_collection);
1248
1249 VLOG(jit) << "After code cache collection, code="
1250 << PrettySize(CodeCacheSize())
1251 << ", data=" << PrettySize(DataCacheSize());
1252
1253 {
1254 MutexLock mu(self, lock_);
1255
1256 // Increase the code cache only when we do partial collections.
1257 // TODO: base this strategy on how full the code cache is?
1258 if (do_full_collection) {
1259 last_collection_increased_code_cache_ = false;
1260 } else {
1261 last_collection_increased_code_cache_ = true;
1262 IncreaseCodeCacheCapacity();
1263 }
1264
1265 bool next_collection_will_be_full = ShouldDoFullCollection();
1266
1267 // Start polling the liveness of compiled code to prepare for the next full collection.
1268 if (next_collection_will_be_full) {
1269 // Save the entry point of methods we have compiled, and update the entry
1270 // point of those methods to the interpreter. If the method is invoked, the
1271 // interpreter will update its entry point to the compiled code and call it.
1272 for (ProfilingInfo* info : profiling_infos_) {
1273 const void* entry_point = info->GetMethod()->GetEntryPointFromQuickCompiledCode();
1274 if (ContainsPc(entry_point)) {
1275 info->SetSavedEntryPoint(entry_point);
1276 // Don't call Instrumentation::UpdateMethodsCode(), as it can check the declaring
1277 // class of the method. We may be concurrently running a GC which makes accessing
1278 // the class unsafe. We know it is OK to bypass the instrumentation as we've just
1279 // checked that the current entry point is JIT compiled code.
1280 info->GetMethod()->SetEntryPointFromQuickCompiledCode(GetQuickToInterpreterBridge());
1281 }
1282 }
1283
1284 DCHECK(CheckLiveCompiledCodeHasProfilingInfo());
1285
1286 // Change entry points of native methods back to the GenericJNI entrypoint.
1287 for (const auto& entry : jni_stubs_map_) {
1288 const JniStubData& data = entry.second;
1289 if (!data.IsCompiled()) {
1290 continue;
1291 }
1292 // Make sure a single invocation of the GenericJNI trampoline tries to recompile.
1293 uint16_t new_counter = Runtime::Current()->GetJit()->HotMethodThreshold() - 1u;
1294 const OatQuickMethodHeader* method_header =
1295 OatQuickMethodHeader::FromCodePointer(data.GetCode());
1296 for (ArtMethod* method : data.GetMethods()) {
1297 if (method->GetEntryPointFromQuickCompiledCode() == method_header->GetEntryPoint()) {
1298 // Don't call Instrumentation::UpdateMethodsCode(), same as for normal methods above.
1299 method->SetCounter(new_counter);
1300 method->SetEntryPointFromQuickCompiledCode(GetQuickGenericJniStub());
1301 }
1302 }
1303 }
1304 }
1305 live_bitmap_.reset(nullptr);
1306 NotifyCollectionDone(self);
1307 }
1308 }
1309 Runtime::Current()->GetJit()->AddTimingLogger(logger);
1310 }
1311
RemoveUnmarkedCode(Thread * self)1312 void JitCodeCache::RemoveUnmarkedCode(Thread* self) {
1313 ScopedTrace trace(__FUNCTION__);
1314 std::unordered_set<OatQuickMethodHeader*> method_headers;
1315 {
1316 MutexLock mu(self, lock_);
1317 ScopedCodeCacheWrite scc(this);
1318 // Iterate over all compiled code and remove entries that are not marked.
1319 for (auto it = jni_stubs_map_.begin(); it != jni_stubs_map_.end();) {
1320 JniStubData* data = &it->second;
1321 if (!data->IsCompiled() || GetLiveBitmap()->Test(FromCodeToAllocation(data->GetCode()))) {
1322 ++it;
1323 } else {
1324 method_headers.insert(OatQuickMethodHeader::FromCodePointer(data->GetCode()));
1325 it = jni_stubs_map_.erase(it);
1326 }
1327 }
1328 for (auto it = method_code_map_.begin(); it != method_code_map_.end();) {
1329 const void* code_ptr = it->first;
1330 uintptr_t allocation = FromCodeToAllocation(code_ptr);
1331 if (GetLiveBitmap()->Test(allocation)) {
1332 ++it;
1333 } else {
1334 method_headers.insert(OatQuickMethodHeader::FromCodePointer(code_ptr));
1335 it = method_code_map_.erase(it);
1336 }
1337 }
1338 }
1339 FreeAllMethodHeaders(method_headers);
1340 }
1341
DoCollection(Thread * self,bool collect_profiling_info)1342 void JitCodeCache::DoCollection(Thread* self, bool collect_profiling_info) {
1343 ScopedTrace trace(__FUNCTION__);
1344 {
1345 MutexLock mu(self, lock_);
1346 if (collect_profiling_info) {
1347 // Clear the profiling info of methods that do not have compiled code as entrypoint.
1348 // Also remove the saved entry point from the ProfilingInfo objects.
1349 for (ProfilingInfo* info : profiling_infos_) {
1350 const void* ptr = info->GetMethod()->GetEntryPointFromQuickCompiledCode();
1351 if (!ContainsPc(ptr) && !info->IsInUseByCompiler()) {
1352 info->GetMethod()->SetProfilingInfo(nullptr);
1353 }
1354
1355 if (info->GetSavedEntryPoint() != nullptr) {
1356 info->SetSavedEntryPoint(nullptr);
1357 // We are going to move this method back to interpreter. Clear the counter now to
1358 // give it a chance to be hot again.
1359 ClearMethodCounter(info->GetMethod(), /*was_warm*/ true);
1360 }
1361 }
1362 } else if (kIsDebugBuild) {
1363 // Sanity check that the profiling infos do not have a dangling entry point.
1364 for (ProfilingInfo* info : profiling_infos_) {
1365 DCHECK(info->GetSavedEntryPoint() == nullptr);
1366 }
1367 }
1368
1369 // Mark compiled code that are entrypoints of ArtMethods. Compiled code that is not
1370 // an entry point is either:
1371 // - an osr compiled code, that will be removed if not in a thread call stack.
1372 // - discarded compiled code, that will be removed if not in a thread call stack.
1373 for (const auto& entry : jni_stubs_map_) {
1374 const JniStubData& data = entry.second;
1375 const void* code_ptr = data.GetCode();
1376 const OatQuickMethodHeader* method_header = OatQuickMethodHeader::FromCodePointer(code_ptr);
1377 for (ArtMethod* method : data.GetMethods()) {
1378 if (method_header->GetEntryPoint() == method->GetEntryPointFromQuickCompiledCode()) {
1379 GetLiveBitmap()->AtomicTestAndSet(FromCodeToAllocation(code_ptr));
1380 break;
1381 }
1382 }
1383 }
1384 for (const auto& it : method_code_map_) {
1385 ArtMethod* method = it.second;
1386 const void* code_ptr = it.first;
1387 const OatQuickMethodHeader* method_header = OatQuickMethodHeader::FromCodePointer(code_ptr);
1388 if (method_header->GetEntryPoint() == method->GetEntryPointFromQuickCompiledCode()) {
1389 GetLiveBitmap()->AtomicTestAndSet(FromCodeToAllocation(code_ptr));
1390 }
1391 }
1392
1393 // Empty osr method map, as osr compiled code will be deleted (except the ones
1394 // on thread stacks).
1395 osr_code_map_.clear();
1396 }
1397
1398 // Run a checkpoint on all threads to mark the JIT compiled code they are running.
1399 MarkCompiledCodeOnThreadStacks(self);
1400
1401 // At this point, mutator threads are still running, and entrypoints of methods can
1402 // change. We do know they cannot change to a code cache entry that is not marked,
1403 // therefore we can safely remove those entries.
1404 RemoveUnmarkedCode(self);
1405
1406 if (collect_profiling_info) {
1407 MutexLock mu(self, lock_);
1408 // Free all profiling infos of methods not compiled nor being compiled.
1409 auto profiling_kept_end = std::remove_if(profiling_infos_.begin(), profiling_infos_.end(),
1410 [this] (ProfilingInfo* info) NO_THREAD_SAFETY_ANALYSIS {
1411 const void* ptr = info->GetMethod()->GetEntryPointFromQuickCompiledCode();
1412 // We have previously cleared the ProfilingInfo pointer in the ArtMethod in the hope
1413 // that the compiled code would not get revived. As mutator threads run concurrently,
1414 // they may have revived the compiled code, and now we are in the situation where
1415 // a method has compiled code but no ProfilingInfo.
1416 // We make sure compiled methods have a ProfilingInfo object. It is needed for
1417 // code cache collection.
1418 if (ContainsPc(ptr) &&
1419 info->GetMethod()->GetProfilingInfo(kRuntimePointerSize) == nullptr) {
1420 info->GetMethod()->SetProfilingInfo(info);
1421 } else if (info->GetMethod()->GetProfilingInfo(kRuntimePointerSize) != info) {
1422 // No need for this ProfilingInfo object anymore.
1423 FreeData(reinterpret_cast<uint8_t*>(info));
1424 return true;
1425 }
1426 return false;
1427 });
1428 profiling_infos_.erase(profiling_kept_end, profiling_infos_.end());
1429 DCHECK(CheckLiveCompiledCodeHasProfilingInfo());
1430 }
1431 }
1432
CheckLiveCompiledCodeHasProfilingInfo()1433 bool JitCodeCache::CheckLiveCompiledCodeHasProfilingInfo() {
1434 ScopedTrace trace(__FUNCTION__);
1435 // Check that methods we have compiled do have a ProfilingInfo object. We would
1436 // have memory leaks of compiled code otherwise.
1437 for (const auto& it : method_code_map_) {
1438 ArtMethod* method = it.second;
1439 if (method->GetProfilingInfo(kRuntimePointerSize) == nullptr) {
1440 const void* code_ptr = it.first;
1441 const OatQuickMethodHeader* method_header = OatQuickMethodHeader::FromCodePointer(code_ptr);
1442 if (method_header->GetEntryPoint() == method->GetEntryPointFromQuickCompiledCode()) {
1443 // If the code is not dead, then we have a problem. Note that this can even
1444 // happen just after a collection, as mutator threads are running in parallel
1445 // and could deoptimize an existing compiled code.
1446 return false;
1447 }
1448 }
1449 }
1450 return true;
1451 }
1452
LookupMethodHeader(uintptr_t pc,ArtMethod * method)1453 OatQuickMethodHeader* JitCodeCache::LookupMethodHeader(uintptr_t pc, ArtMethod* method) {
1454 static_assert(kRuntimeISA != InstructionSet::kThumb2, "kThumb2 cannot be a runtime ISA");
1455 if (kRuntimeISA == InstructionSet::kArm) {
1456 // On Thumb-2, the pc is offset by one.
1457 --pc;
1458 }
1459 if (!ContainsPc(reinterpret_cast<const void*>(pc))) {
1460 return nullptr;
1461 }
1462
1463 if (!kIsDebugBuild) {
1464 // Called with null `method` only from MarkCodeClosure::Run() in debug build.
1465 CHECK(method != nullptr);
1466 }
1467
1468 MutexLock mu(Thread::Current(), lock_);
1469 OatQuickMethodHeader* method_header = nullptr;
1470 ArtMethod* found_method = nullptr; // Only for DCHECK(), not for JNI stubs.
1471 if (method != nullptr && UNLIKELY(method->IsNative())) {
1472 auto it = jni_stubs_map_.find(JniStubKey(method));
1473 if (it == jni_stubs_map_.end() || !ContainsElement(it->second.GetMethods(), method)) {
1474 return nullptr;
1475 }
1476 const void* code_ptr = it->second.GetCode();
1477 method_header = OatQuickMethodHeader::FromCodePointer(code_ptr);
1478 if (!method_header->Contains(pc)) {
1479 return nullptr;
1480 }
1481 } else {
1482 auto it = method_code_map_.lower_bound(reinterpret_cast<const void*>(pc));
1483 if (it != method_code_map_.begin()) {
1484 --it;
1485 const void* code_ptr = it->first;
1486 if (OatQuickMethodHeader::FromCodePointer(code_ptr)->Contains(pc)) {
1487 method_header = OatQuickMethodHeader::FromCodePointer(code_ptr);
1488 found_method = it->second;
1489 }
1490 }
1491 if (method_header == nullptr && method == nullptr) {
1492 // Scan all compiled JNI stubs as well. This slow search is used only
1493 // for checks in debug build, for release builds the `method` is not null.
1494 for (auto&& entry : jni_stubs_map_) {
1495 const JniStubData& data = entry.second;
1496 if (data.IsCompiled() &&
1497 OatQuickMethodHeader::FromCodePointer(data.GetCode())->Contains(pc)) {
1498 method_header = OatQuickMethodHeader::FromCodePointer(data.GetCode());
1499 }
1500 }
1501 }
1502 if (method_header == nullptr) {
1503 return nullptr;
1504 }
1505 }
1506
1507 if (kIsDebugBuild && method != nullptr && !method->IsNative()) {
1508 // When we are walking the stack to redefine classes and creating obsolete methods it is
1509 // possible that we might have updated the method_code_map by making this method obsolete in a
1510 // previous frame. Therefore we should just check that the non-obsolete version of this method
1511 // is the one we expect. We change to the non-obsolete versions in the error message since the
1512 // obsolete version of the method might not be fully initialized yet. This situation can only
1513 // occur when we are in the process of allocating and setting up obsolete methods. Otherwise
1514 // method and it->second should be identical. (See openjdkjvmti/ti_redefine.cc for more
1515 // information.)
1516 DCHECK_EQ(found_method->GetNonObsoleteMethod(), method->GetNonObsoleteMethod())
1517 << ArtMethod::PrettyMethod(method->GetNonObsoleteMethod()) << " "
1518 << ArtMethod::PrettyMethod(found_method->GetNonObsoleteMethod()) << " "
1519 << std::hex << pc;
1520 }
1521 return method_header;
1522 }
1523
LookupOsrMethodHeader(ArtMethod * method)1524 OatQuickMethodHeader* JitCodeCache::LookupOsrMethodHeader(ArtMethod* method) {
1525 MutexLock mu(Thread::Current(), lock_);
1526 auto it = osr_code_map_.find(method);
1527 if (it == osr_code_map_.end()) {
1528 return nullptr;
1529 }
1530 return OatQuickMethodHeader::FromCodePointer(it->second);
1531 }
1532
AddProfilingInfo(Thread * self,ArtMethod * method,const std::vector<uint32_t> & entries,bool retry_allocation)1533 ProfilingInfo* JitCodeCache::AddProfilingInfo(Thread* self,
1534 ArtMethod* method,
1535 const std::vector<uint32_t>& entries,
1536 bool retry_allocation)
1537 // No thread safety analysis as we are using TryLock/Unlock explicitly.
1538 NO_THREAD_SAFETY_ANALYSIS {
1539 ProfilingInfo* info = nullptr;
1540 if (!retry_allocation) {
1541 // If we are allocating for the interpreter, just try to lock, to avoid
1542 // lock contention with the JIT.
1543 if (lock_.ExclusiveTryLock(self)) {
1544 info = AddProfilingInfoInternal(self, method, entries);
1545 lock_.ExclusiveUnlock(self);
1546 }
1547 } else {
1548 {
1549 MutexLock mu(self, lock_);
1550 info = AddProfilingInfoInternal(self, method, entries);
1551 }
1552
1553 if (info == nullptr) {
1554 GarbageCollectCache(self);
1555 MutexLock mu(self, lock_);
1556 info = AddProfilingInfoInternal(self, method, entries);
1557 }
1558 }
1559 return info;
1560 }
1561
AddProfilingInfoInternal(Thread * self ATTRIBUTE_UNUSED,ArtMethod * method,const std::vector<uint32_t> & entries)1562 ProfilingInfo* JitCodeCache::AddProfilingInfoInternal(Thread* self ATTRIBUTE_UNUSED,
1563 ArtMethod* method,
1564 const std::vector<uint32_t>& entries) {
1565 size_t profile_info_size = RoundUp(
1566 sizeof(ProfilingInfo) + sizeof(InlineCache) * entries.size(),
1567 sizeof(void*));
1568
1569 // Check whether some other thread has concurrently created it.
1570 ProfilingInfo* info = method->GetProfilingInfo(kRuntimePointerSize);
1571 if (info != nullptr) {
1572 return info;
1573 }
1574
1575 uint8_t* data = AllocateData(profile_info_size);
1576 if (data == nullptr) {
1577 return nullptr;
1578 }
1579 info = new (data) ProfilingInfo(method, entries);
1580
1581 // Make sure other threads see the data in the profiling info object before the
1582 // store in the ArtMethod's ProfilingInfo pointer.
1583 QuasiAtomic::ThreadFenceRelease();
1584
1585 method->SetProfilingInfo(info);
1586 profiling_infos_.push_back(info);
1587 histogram_profiling_info_memory_use_.AddValue(profile_info_size);
1588 return info;
1589 }
1590
1591 // NO_THREAD_SAFETY_ANALYSIS as this is called from mspace code, at which point the lock
1592 // is already held.
MoreCore(const void * mspace,intptr_t increment)1593 void* JitCodeCache::MoreCore(const void* mspace, intptr_t increment) NO_THREAD_SAFETY_ANALYSIS {
1594 if (code_mspace_ == mspace) {
1595 size_t result = code_end_;
1596 code_end_ += increment;
1597 return reinterpret_cast<void*>(result + code_map_->Begin());
1598 } else {
1599 DCHECK_EQ(data_mspace_, mspace);
1600 size_t result = data_end_;
1601 data_end_ += increment;
1602 return reinterpret_cast<void*>(result + data_map_->Begin());
1603 }
1604 }
1605
GetProfiledMethods(const std::set<std::string> & dex_base_locations,std::vector<ProfileMethodInfo> & methods)1606 void JitCodeCache::GetProfiledMethods(const std::set<std::string>& dex_base_locations,
1607 std::vector<ProfileMethodInfo>& methods) {
1608 ScopedTrace trace(__FUNCTION__);
1609 MutexLock mu(Thread::Current(), lock_);
1610 uint16_t jit_compile_threshold = Runtime::Current()->GetJITOptions()->GetCompileThreshold();
1611 for (const ProfilingInfo* info : profiling_infos_) {
1612 ArtMethod* method = info->GetMethod();
1613 const DexFile* dex_file = method->GetDexFile();
1614 const std::string base_location = DexFileLoader::GetBaseLocation(dex_file->GetLocation());
1615 if (!ContainsElement(dex_base_locations, base_location)) {
1616 // Skip dex files which are not profiled.
1617 continue;
1618 }
1619 std::vector<ProfileMethodInfo::ProfileInlineCache> inline_caches;
1620
1621 // If the method didn't reach the compilation threshold don't save the inline caches.
1622 // They might be incomplete and cause unnecessary deoptimizations.
1623 // If the inline cache is empty the compiler will generate a regular invoke virtual/interface.
1624 if (method->GetCounter() < jit_compile_threshold) {
1625 methods.emplace_back(/*ProfileMethodInfo*/
1626 MethodReference(dex_file, method->GetDexMethodIndex()), inline_caches);
1627 continue;
1628 }
1629
1630 for (size_t i = 0; i < info->number_of_inline_caches_; ++i) {
1631 std::vector<TypeReference> profile_classes;
1632 const InlineCache& cache = info->cache_[i];
1633 ArtMethod* caller = info->GetMethod();
1634 bool is_missing_types = false;
1635 for (size_t k = 0; k < InlineCache::kIndividualCacheSize; k++) {
1636 mirror::Class* cls = cache.classes_[k].Read();
1637 if (cls == nullptr) {
1638 break;
1639 }
1640
1641 // Check if the receiver is in the boot class path or if it's in the
1642 // same class loader as the caller. If not, skip it, as there is not
1643 // much we can do during AOT.
1644 if (!cls->IsBootStrapClassLoaded() &&
1645 caller->GetClassLoader() != cls->GetClassLoader()) {
1646 is_missing_types = true;
1647 continue;
1648 }
1649
1650 const DexFile* class_dex_file = nullptr;
1651 dex::TypeIndex type_index;
1652
1653 if (cls->GetDexCache() == nullptr) {
1654 DCHECK(cls->IsArrayClass()) << cls->PrettyClass();
1655 // Make a best effort to find the type index in the method's dex file.
1656 // We could search all open dex files but that might turn expensive
1657 // and probably not worth it.
1658 class_dex_file = dex_file;
1659 type_index = cls->FindTypeIndexInOtherDexFile(*dex_file);
1660 } else {
1661 class_dex_file = &(cls->GetDexFile());
1662 type_index = cls->GetDexTypeIndex();
1663 }
1664 if (!type_index.IsValid()) {
1665 // Could be a proxy class or an array for which we couldn't find the type index.
1666 is_missing_types = true;
1667 continue;
1668 }
1669 if (ContainsElement(dex_base_locations,
1670 DexFileLoader::GetBaseLocation(class_dex_file->GetLocation()))) {
1671 // Only consider classes from the same apk (including multidex).
1672 profile_classes.emplace_back(/*ProfileMethodInfo::ProfileClassReference*/
1673 class_dex_file, type_index);
1674 } else {
1675 is_missing_types = true;
1676 }
1677 }
1678 if (!profile_classes.empty()) {
1679 inline_caches.emplace_back(/*ProfileMethodInfo::ProfileInlineCache*/
1680 cache.dex_pc_, is_missing_types, profile_classes);
1681 }
1682 }
1683 methods.emplace_back(/*ProfileMethodInfo*/
1684 MethodReference(dex_file, method->GetDexMethodIndex()), inline_caches);
1685 }
1686 }
1687
GetLastUpdateTimeNs() const1688 uint64_t JitCodeCache::GetLastUpdateTimeNs() const {
1689 return last_update_time_ns_.LoadAcquire();
1690 }
1691
IsOsrCompiled(ArtMethod * method)1692 bool JitCodeCache::IsOsrCompiled(ArtMethod* method) {
1693 MutexLock mu(Thread::Current(), lock_);
1694 return osr_code_map_.find(method) != osr_code_map_.end();
1695 }
1696
NotifyCompilationOf(ArtMethod * method,Thread * self,bool osr)1697 bool JitCodeCache::NotifyCompilationOf(ArtMethod* method, Thread* self, bool osr) {
1698 if (!osr && ContainsPc(method->GetEntryPointFromQuickCompiledCode())) {
1699 return false;
1700 }
1701
1702 MutexLock mu(self, lock_);
1703 if (osr && (osr_code_map_.find(method) != osr_code_map_.end())) {
1704 return false;
1705 }
1706
1707 if (UNLIKELY(method->IsNative())) {
1708 JniStubKey key(method);
1709 auto it = jni_stubs_map_.find(key);
1710 bool new_compilation = false;
1711 if (it == jni_stubs_map_.end()) {
1712 // Create a new entry to mark the stub as being compiled.
1713 it = jni_stubs_map_.Put(key, JniStubData{});
1714 new_compilation = true;
1715 }
1716 JniStubData* data = &it->second;
1717 data->AddMethod(method);
1718 if (data->IsCompiled()) {
1719 OatQuickMethodHeader* method_header = OatQuickMethodHeader::FromCodePointer(data->GetCode());
1720 const void* entrypoint = method_header->GetEntryPoint();
1721 // Update also entrypoints of other methods held by the JniStubData.
1722 // We could simply update the entrypoint of `method` but if the last JIT GC has
1723 // changed these entrypoints to GenericJNI in preparation for a full GC, we may
1724 // as well change them back as this stub shall not be collected anyway and this
1725 // can avoid a few expensive GenericJNI calls.
1726 instrumentation::Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation();
1727 for (ArtMethod* m : data->GetMethods()) {
1728 // Call the dedicated method instead of the more generic UpdateMethodsCode, because
1729 // `m` might be in the process of being deleted.
1730 instrumentation->UpdateNativeMethodsCodeToJitCode(m, entrypoint);
1731 }
1732 if (collection_in_progress_) {
1733 GetLiveBitmap()->AtomicTestAndSet(FromCodeToAllocation(data->GetCode()));
1734 }
1735 }
1736 return new_compilation;
1737 } else {
1738 ProfilingInfo* info = method->GetProfilingInfo(kRuntimePointerSize);
1739 if (info == nullptr) {
1740 VLOG(jit) << method->PrettyMethod() << " needs a ProfilingInfo to be compiled";
1741 // Because the counter is not atomic, there are some rare cases where we may not hit the
1742 // threshold for creating the ProfilingInfo. Reset the counter now to "correct" this.
1743 ClearMethodCounter(method, /*was_warm*/ false);
1744 return false;
1745 }
1746
1747 if (info->IsMethodBeingCompiled(osr)) {
1748 return false;
1749 }
1750
1751 info->SetIsMethodBeingCompiled(true, osr);
1752 return true;
1753 }
1754 }
1755
NotifyCompilerUse(ArtMethod * method,Thread * self)1756 ProfilingInfo* JitCodeCache::NotifyCompilerUse(ArtMethod* method, Thread* self) {
1757 MutexLock mu(self, lock_);
1758 ProfilingInfo* info = method->GetProfilingInfo(kRuntimePointerSize);
1759 if (info != nullptr) {
1760 if (!info->IncrementInlineUse()) {
1761 // Overflow of inlining uses, just bail.
1762 return nullptr;
1763 }
1764 }
1765 return info;
1766 }
1767
DoneCompilerUse(ArtMethod * method,Thread * self)1768 void JitCodeCache::DoneCompilerUse(ArtMethod* method, Thread* self) {
1769 MutexLock mu(self, lock_);
1770 ProfilingInfo* info = method->GetProfilingInfo(kRuntimePointerSize);
1771 DCHECK(info != nullptr);
1772 info->DecrementInlineUse();
1773 }
1774
DoneCompiling(ArtMethod * method,Thread * self,bool osr)1775 void JitCodeCache::DoneCompiling(ArtMethod* method, Thread* self, bool osr) {
1776 DCHECK_EQ(Thread::Current(), self);
1777 MutexLock mu(self, lock_);
1778 if (UNLIKELY(method->IsNative())) {
1779 auto it = jni_stubs_map_.find(JniStubKey(method));
1780 DCHECK(it != jni_stubs_map_.end());
1781 JniStubData* data = &it->second;
1782 DCHECK(ContainsElement(data->GetMethods(), method));
1783 if (UNLIKELY(!data->IsCompiled())) {
1784 // Failed to compile; the JNI compiler never fails, but the cache may be full.
1785 jni_stubs_map_.erase(it); // Remove the entry added in NotifyCompilationOf().
1786 } // else CommitCodeInternal() updated entrypoints of all methods in the JniStubData.
1787 } else {
1788 ProfilingInfo* info = method->GetProfilingInfo(kRuntimePointerSize);
1789 DCHECK(info->IsMethodBeingCompiled(osr));
1790 info->SetIsMethodBeingCompiled(false, osr);
1791 }
1792 }
1793
GetMemorySizeOfCodePointer(const void * ptr)1794 size_t JitCodeCache::GetMemorySizeOfCodePointer(const void* ptr) {
1795 MutexLock mu(Thread::Current(), lock_);
1796 return mspace_usable_size(reinterpret_cast<const void*>(FromCodeToAllocation(ptr)));
1797 }
1798
InvalidateCompiledCodeFor(ArtMethod * method,const OatQuickMethodHeader * header)1799 void JitCodeCache::InvalidateCompiledCodeFor(ArtMethod* method,
1800 const OatQuickMethodHeader* header) {
1801 DCHECK(!method->IsNative());
1802 ProfilingInfo* profiling_info = method->GetProfilingInfo(kRuntimePointerSize);
1803 if ((profiling_info != nullptr) &&
1804 (profiling_info->GetSavedEntryPoint() == header->GetEntryPoint())) {
1805 // Prevent future uses of the compiled code.
1806 profiling_info->SetSavedEntryPoint(nullptr);
1807 }
1808
1809 if (method->GetEntryPointFromQuickCompiledCode() == header->GetEntryPoint()) {
1810 // The entrypoint is the one to invalidate, so we just update it to the interpreter entry point
1811 // and clear the counter to get the method Jitted again.
1812 Runtime::Current()->GetInstrumentation()->UpdateMethodsCode(
1813 method, GetQuickToInterpreterBridge());
1814 ClearMethodCounter(method, /*was_warm*/ profiling_info != nullptr);
1815 } else {
1816 MutexLock mu(Thread::Current(), lock_);
1817 auto it = osr_code_map_.find(method);
1818 if (it != osr_code_map_.end() && OatQuickMethodHeader::FromCodePointer(it->second) == header) {
1819 // Remove the OSR method, to avoid using it again.
1820 osr_code_map_.erase(it);
1821 }
1822 }
1823 }
1824
AllocateCode(size_t code_size)1825 uint8_t* JitCodeCache::AllocateCode(size_t code_size) {
1826 size_t alignment = GetInstructionSetAlignment(kRuntimeISA);
1827 uint8_t* result = reinterpret_cast<uint8_t*>(
1828 mspace_memalign(code_mspace_, alignment, code_size));
1829 size_t header_size = RoundUp(sizeof(OatQuickMethodHeader), alignment);
1830 // Ensure the header ends up at expected instruction alignment.
1831 DCHECK_ALIGNED_PARAM(reinterpret_cast<uintptr_t>(result + header_size), alignment);
1832 used_memory_for_code_ += mspace_usable_size(result);
1833 return result;
1834 }
1835
FreeCode(uint8_t * code)1836 void JitCodeCache::FreeCode(uint8_t* code) {
1837 used_memory_for_code_ -= mspace_usable_size(code);
1838 mspace_free(code_mspace_, code);
1839 }
1840
AllocateData(size_t data_size)1841 uint8_t* JitCodeCache::AllocateData(size_t data_size) {
1842 void* result = mspace_malloc(data_mspace_, data_size);
1843 used_memory_for_data_ += mspace_usable_size(result);
1844 return reinterpret_cast<uint8_t*>(result);
1845 }
1846
FreeData(uint8_t * data)1847 void JitCodeCache::FreeData(uint8_t* data) {
1848 used_memory_for_data_ -= mspace_usable_size(data);
1849 mspace_free(data_mspace_, data);
1850 }
1851
Dump(std::ostream & os)1852 void JitCodeCache::Dump(std::ostream& os) {
1853 MutexLock mu(Thread::Current(), lock_);
1854 MutexLock mu2(Thread::Current(), *Locks::native_debug_interface_lock_);
1855 os << "Current JIT code cache size: " << PrettySize(used_memory_for_code_) << "\n"
1856 << "Current JIT data cache size: " << PrettySize(used_memory_for_data_) << "\n"
1857 << "Current JIT mini-debug-info size: " << PrettySize(GetJitNativeDebugInfoMemUsage()) << "\n"
1858 << "Current JIT capacity: " << PrettySize(current_capacity_) << "\n"
1859 << "Current number of JIT JNI stub entries: " << jni_stubs_map_.size() << "\n"
1860 << "Current number of JIT code cache entries: " << method_code_map_.size() << "\n"
1861 << "Total number of JIT compilations: " << number_of_compilations_ << "\n"
1862 << "Total number of JIT compilations for on stack replacement: "
1863 << number_of_osr_compilations_ << "\n"
1864 << "Total number of JIT code cache collections: " << number_of_collections_ << std::endl;
1865 histogram_stack_map_memory_use_.PrintMemoryUse(os);
1866 histogram_code_memory_use_.PrintMemoryUse(os);
1867 histogram_profiling_info_memory_use_.PrintMemoryUse(os);
1868 }
1869
1870 } // namespace jit
1871 } // namespace art
1872