1 /*
2 * Copyright (C) 2016 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 "cha.h"
18
19 #include "art_method-inl.h"
20 #include "jit/jit.h"
21 #include "jit/jit_code_cache.h"
22 #include "linear_alloc.h"
23 #include "runtime.h"
24 #include "scoped_thread_state_change-inl.h"
25 #include "stack.h"
26 #include "thread.h"
27 #include "thread_list.h"
28 #include "thread_pool.h"
29
30 namespace art {
31
AddDependency(ArtMethod * method,ArtMethod * dependent_method,OatQuickMethodHeader * dependent_header)32 void ClassHierarchyAnalysis::AddDependency(ArtMethod* method,
33 ArtMethod* dependent_method,
34 OatQuickMethodHeader* dependent_header) {
35 const auto it = cha_dependency_map_.insert(
36 decltype(cha_dependency_map_)::value_type(method, ListOfDependentPairs())).first;
37 it->second.push_back({dependent_method, dependent_header});
38 }
39
40 static const ClassHierarchyAnalysis::ListOfDependentPairs s_empty_vector;
41
GetDependents(ArtMethod * method)42 const ClassHierarchyAnalysis::ListOfDependentPairs& ClassHierarchyAnalysis::GetDependents(
43 ArtMethod* method) {
44 auto it = cha_dependency_map_.find(method);
45 if (it != cha_dependency_map_.end()) {
46 return it->second;
47 }
48 return s_empty_vector;
49 }
50
RemoveAllDependenciesFor(ArtMethod * method)51 void ClassHierarchyAnalysis::RemoveAllDependenciesFor(ArtMethod* method) {
52 cha_dependency_map_.erase(method);
53 }
54
RemoveDependentsWithMethodHeaders(const std::unordered_set<OatQuickMethodHeader * > & method_headers)55 void ClassHierarchyAnalysis::RemoveDependentsWithMethodHeaders(
56 const std::unordered_set<OatQuickMethodHeader*>& method_headers) {
57 // Iterate through all entries in the dependency map and remove any entry that
58 // contains one of those in method_headers.
59 for (auto map_it = cha_dependency_map_.begin(); map_it != cha_dependency_map_.end(); ) {
60 ListOfDependentPairs& dependents = map_it->second;
61 dependents.erase(
62 std::remove_if(
63 dependents.begin(),
64 dependents.end(),
65 [&method_headers](MethodAndMethodHeaderPair& dependent) {
66 return method_headers.find(dependent.second) != method_headers.end();
67 }),
68 dependents.end());
69
70 // Remove the map entry if there are no more dependents.
71 if (dependents.empty()) {
72 map_it = cha_dependency_map_.erase(map_it);
73 } else {
74 map_it++;
75 }
76 }
77 }
78
79 // This stack visitor walks the stack and for compiled code with certain method
80 // headers, sets the should_deoptimize flag on stack to 1.
81 // TODO: also set the register value to 1 when should_deoptimize is allocated in
82 // a register.
83 class CHAStackVisitor FINAL : public StackVisitor {
84 public:
CHAStackVisitor(Thread * thread_in,Context * context,const std::unordered_set<OatQuickMethodHeader * > & method_headers)85 CHAStackVisitor(Thread* thread_in,
86 Context* context,
87 const std::unordered_set<OatQuickMethodHeader*>& method_headers)
88 : StackVisitor(thread_in, context, StackVisitor::StackWalkKind::kSkipInlinedFrames),
89 method_headers_(method_headers) {
90 }
91
VisitFrame()92 bool VisitFrame() OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_) {
93 ArtMethod* method = GetMethod();
94 // Avoid types of methods that do not have an oat quick method header.
95 if (method == nullptr ||
96 method->IsRuntimeMethod() ||
97 method->IsNative() ||
98 method->IsProxyMethod()) {
99 return true;
100 }
101 if (GetCurrentQuickFrame() == nullptr) {
102 // Not compiled code.
103 return true;
104 }
105 // Method may have multiple versions of compiled code. Check
106 // the method header to see if it has should_deoptimize flag.
107 const OatQuickMethodHeader* method_header = GetCurrentOatQuickMethodHeader();
108 DCHECK(method_header != nullptr);
109 if (!method_header->HasShouldDeoptimizeFlag()) {
110 // This compiled version doesn't have should_deoptimize flag. Skip.
111 return true;
112 }
113 auto it = std::find(method_headers_.begin(), method_headers_.end(), method_header);
114 if (it == method_headers_.end()) {
115 // Not in the list of method headers that should be deoptimized.
116 return true;
117 }
118
119 // The compiled code on stack is not valid anymore. Need to deoptimize.
120 SetShouldDeoptimizeFlag();
121
122 return true;
123 }
124
125 private:
SetShouldDeoptimizeFlag()126 void SetShouldDeoptimizeFlag() REQUIRES_SHARED(Locks::mutator_lock_) {
127 QuickMethodFrameInfo frame_info = GetCurrentQuickFrameInfo();
128 size_t frame_size = frame_info.FrameSizeInBytes();
129 uint8_t* sp = reinterpret_cast<uint8_t*>(GetCurrentQuickFrame());
130 size_t core_spill_size = POPCOUNT(frame_info.CoreSpillMask()) *
131 GetBytesPerGprSpillLocation(kRuntimeISA);
132 size_t fpu_spill_size = POPCOUNT(frame_info.FpSpillMask()) *
133 GetBytesPerFprSpillLocation(kRuntimeISA);
134 size_t offset = frame_size - core_spill_size - fpu_spill_size - kShouldDeoptimizeFlagSize;
135 uint8_t* should_deoptimize_addr = sp + offset;
136 // Set deoptimization flag to 1.
137 DCHECK(*should_deoptimize_addr == 0 || *should_deoptimize_addr == 1);
138 *should_deoptimize_addr = 1;
139 }
140
141 // Set of method headers for compiled code that should be deoptimized.
142 const std::unordered_set<OatQuickMethodHeader*>& method_headers_;
143
144 DISALLOW_COPY_AND_ASSIGN(CHAStackVisitor);
145 };
146
147 class CHACheckpoint FINAL : public Closure {
148 public:
CHACheckpoint(const std::unordered_set<OatQuickMethodHeader * > & method_headers)149 explicit CHACheckpoint(const std::unordered_set<OatQuickMethodHeader*>& method_headers)
150 : barrier_(0),
151 method_headers_(method_headers) {}
152
Run(Thread * thread)153 void Run(Thread* thread) OVERRIDE {
154 // Note thread and self may not be equal if thread was already suspended at
155 // the point of the request.
156 Thread* self = Thread::Current();
157 ScopedObjectAccess soa(self);
158 CHAStackVisitor visitor(thread, nullptr, method_headers_);
159 visitor.WalkStack();
160 barrier_.Pass(self);
161 }
162
WaitForThreadsToRunThroughCheckpoint(size_t threads_running_checkpoint)163 void WaitForThreadsToRunThroughCheckpoint(size_t threads_running_checkpoint) {
164 Thread* self = Thread::Current();
165 ScopedThreadStateChange tsc(self, kWaitingForCheckPointsToRun);
166 barrier_.Increment(self, threads_running_checkpoint);
167 }
168
169 private:
170 // The barrier to be passed through and for the requestor to wait upon.
171 Barrier barrier_;
172 // List of method headers for invalidated compiled code.
173 const std::unordered_set<OatQuickMethodHeader*>& method_headers_;
174
175 DISALLOW_COPY_AND_ASSIGN(CHACheckpoint);
176 };
177
VerifyNonSingleImplementation(mirror::Class * verify_class,uint16_t verify_index,ArtMethod * excluded_method)178 void ClassHierarchyAnalysis::VerifyNonSingleImplementation(mirror::Class* verify_class,
179 uint16_t verify_index,
180 ArtMethod* excluded_method) {
181 // Grab cha_lock_ to make sure all single-implementation updates are seen.
182 PointerSize image_pointer_size =
183 Runtime::Current()->GetClassLinker()->GetImagePointerSize();
184 MutexLock cha_mu(Thread::Current(), *Locks::cha_lock_);
185 while (verify_class != nullptr) {
186 if (verify_index >= verify_class->GetVTableLength()) {
187 return;
188 }
189 ArtMethod* verify_method = verify_class->GetVTableEntry(verify_index, image_pointer_size);
190 if (verify_method != excluded_method) {
191 DCHECK(!verify_method->HasSingleImplementation())
192 << "class: " << verify_class->PrettyClass()
193 << " verify_method: " << verify_method->PrettyMethod(true)
194 << " excluded_method: " << excluded_method->PrettyMethod(true);
195 if (verify_method->IsAbstract()) {
196 DCHECK(verify_method->GetSingleImplementation(image_pointer_size) == nullptr);
197 }
198 }
199 verify_class = verify_class->GetSuperClass();
200 }
201 }
202
CheckVirtualMethodSingleImplementationInfo(Handle<mirror::Class> klass,ArtMethod * virtual_method,ArtMethod * method_in_super,std::unordered_set<ArtMethod * > & invalidated_single_impl_methods,PointerSize pointer_size)203 void ClassHierarchyAnalysis::CheckVirtualMethodSingleImplementationInfo(
204 Handle<mirror::Class> klass,
205 ArtMethod* virtual_method,
206 ArtMethod* method_in_super,
207 std::unordered_set<ArtMethod*>& invalidated_single_impl_methods,
208 PointerSize pointer_size) {
209 // TODO: if klass is not instantiable, virtual_method isn't invocable yet so
210 // even if it overrides, it doesn't invalidate single-implementation
211 // assumption.
212
213 DCHECK((virtual_method != method_in_super) || virtual_method->IsAbstract());
214 DCHECK(method_in_super->GetDeclaringClass()->IsResolved()) << "class isn't resolved";
215 // If virtual_method doesn't come from a default interface method, it should
216 // be supplied by klass.
217 DCHECK(virtual_method == method_in_super ||
218 virtual_method->IsCopied() ||
219 virtual_method->GetDeclaringClass() == klass.Get());
220
221 // To make updating single-implementation flags simple, we always maintain the following
222 // invariant:
223 // Say all virtual methods in the same vtable slot, starting from the bottom child class
224 // to super classes, is a sequence of unique methods m3, m2, m1, ... (after removing duplicate
225 // methods for inherited methods).
226 // For example for the following class hierarchy,
227 // class A { void m() { ... } }
228 // class B extends A { void m() { ... } }
229 // class C extends B {}
230 // class D extends C { void m() { ... } }
231 // the sequence is D.m(), B.m(), A.m().
232 // The single-implementation status for that sequence of methods begin with one or two true's,
233 // then become all falses. The only case where two true's are possible is for one abstract
234 // method m and one non-abstract method mImpl that overrides method m.
235 // With the invariant, when linking in a new class, we only need to at most update one or
236 // two methods in the sequence for their single-implementation status, in order to maintain
237 // the invariant.
238
239 if (!method_in_super->HasSingleImplementation()) {
240 // method_in_super already has multiple implementations. All methods in the
241 // same vtable slots in its super classes should have
242 // non-single-implementation already.
243 if (kIsDebugBuild) {
244 VerifyNonSingleImplementation(klass->GetSuperClass()->GetSuperClass(),
245 method_in_super->GetMethodIndex(),
246 nullptr /* excluded_method */);
247 }
248 return;
249 }
250
251 uint16_t method_index = method_in_super->GetMethodIndex();
252 if (method_in_super->IsAbstract()) {
253 if (kIsDebugBuild) {
254 // An abstract method should have made all methods in the same vtable
255 // slot above it in the class hierarchy having non-single-implementation.
256 mirror::Class* super_super = klass->GetSuperClass()->GetSuperClass();
257 VerifyNonSingleImplementation(super_super,
258 method_index,
259 method_in_super);
260 }
261
262 if (virtual_method->IsAbstract()) {
263 // SUPER: abstract, VIRTUAL: abstract.
264 if (method_in_super == virtual_method) {
265 DCHECK(klass->IsInstantiable());
266 // An instantiable subclass hasn't provided a concrete implementation of
267 // the abstract method. Invoking method_in_super may throw AbstractMethodError.
268 // This is an uncommon case, so we simply treat method_in_super as not
269 // having single-implementation.
270 invalidated_single_impl_methods.insert(method_in_super);
271 return;
272 } else {
273 // One abstract method overrides another abstract method. This is an uncommon
274 // case. We simply treat method_in_super as not having single-implementation.
275 invalidated_single_impl_methods.insert(method_in_super);
276 return;
277 }
278 } else {
279 // SUPER: abstract, VIRTUAL: non-abstract.
280 // A non-abstract method overrides an abstract method.
281 if (method_in_super->GetSingleImplementation(pointer_size) == nullptr) {
282 // Abstract method_in_super has no implementation yet.
283 // We need to grab cha_lock_ since there may be multiple class linking
284 // going on that can check/modify the single-implementation flag/method
285 // of method_in_super.
286 MutexLock cha_mu(Thread::Current(), *Locks::cha_lock_);
287 if (!method_in_super->HasSingleImplementation()) {
288 return;
289 }
290 if (method_in_super->GetSingleImplementation(pointer_size) == nullptr) {
291 // virtual_method becomes the first implementation for method_in_super.
292 method_in_super->SetSingleImplementation(virtual_method, pointer_size);
293 // Keep method_in_super's single-implementation status.
294 return;
295 }
296 // Fall through to invalidate method_in_super's single-implementation status.
297 }
298 // Abstract method_in_super already got one implementation.
299 // Invalidate method_in_super's single-implementation status.
300 invalidated_single_impl_methods.insert(method_in_super);
301 return;
302 }
303 } else {
304 if (virtual_method->IsAbstract()) {
305 // SUPER: non-abstract, VIRTUAL: abstract.
306 // An abstract method overrides a non-abstract method. This is an uncommon
307 // case, we simply treat both methods as not having single-implementation.
308 invalidated_single_impl_methods.insert(virtual_method);
309 // Fall-through to handle invalidating method_in_super of its
310 // single-implementation status.
311 }
312
313 // SUPER: non-abstract, VIRTUAL: non-abstract/abstract(fall-through from previous if).
314 // Invalidate method_in_super's single-implementation status.
315 invalidated_single_impl_methods.insert(method_in_super);
316
317 // method_in_super might be the single-implementation of another abstract method,
318 // which should be also invalidated of its single-implementation status.
319 mirror::Class* super_super = klass->GetSuperClass()->GetSuperClass();
320 while (super_super != nullptr &&
321 method_index < super_super->GetVTableLength()) {
322 ArtMethod* method_in_super_super = super_super->GetVTableEntry(method_index, pointer_size);
323 if (method_in_super_super != method_in_super) {
324 if (method_in_super_super->IsAbstract()) {
325 if (method_in_super_super->HasSingleImplementation()) {
326 // Invalidate method_in_super's single-implementation status.
327 invalidated_single_impl_methods.insert(method_in_super_super);
328 // No need to further traverse up the class hierarchy since if there
329 // are cases that one abstract method overrides another method, we
330 // should have made that method having non-single-implementation already.
331 } else {
332 // method_in_super_super is already non-single-implementation.
333 // No need to further traverse up the class hierarchy.
334 }
335 } else {
336 DCHECK(!method_in_super_super->HasSingleImplementation());
337 // No need to further traverse up the class hierarchy since two non-abstract
338 // methods (method_in_super and method_in_super_super) should have set all
339 // other methods (abstract or not) in the vtable slot to be non-single-implementation.
340 }
341
342 if (kIsDebugBuild) {
343 VerifyNonSingleImplementation(super_super->GetSuperClass(),
344 method_index,
345 method_in_super_super);
346 }
347 // No need to go any further.
348 return;
349 } else {
350 super_super = super_super->GetSuperClass();
351 }
352 }
353 }
354 }
355
CheckInterfaceMethodSingleImplementationInfo(Handle<mirror::Class> klass,ArtMethod * interface_method,ArtMethod * implementation_method,std::unordered_set<ArtMethod * > & invalidated_single_impl_methods,PointerSize pointer_size)356 void ClassHierarchyAnalysis::CheckInterfaceMethodSingleImplementationInfo(
357 Handle<mirror::Class> klass,
358 ArtMethod* interface_method,
359 ArtMethod* implementation_method,
360 std::unordered_set<ArtMethod*>& invalidated_single_impl_methods,
361 PointerSize pointer_size) {
362 DCHECK(klass->IsInstantiable());
363 DCHECK(interface_method->IsAbstract() || interface_method->IsDefault());
364
365 if (!interface_method->HasSingleImplementation()) {
366 return;
367 }
368
369 if (implementation_method->IsAbstract()) {
370 // An instantiable class doesn't supply an implementation for
371 // interface_method. Invoking the interface method on the class will throw
372 // AbstractMethodError. This is an uncommon case, so we simply treat
373 // interface_method as not having single-implementation.
374 invalidated_single_impl_methods.insert(interface_method);
375 return;
376 }
377
378 // We need to grab cha_lock_ since there may be multiple class linking going
379 // on that can check/modify the single-implementation flag/method of
380 // interface_method.
381 MutexLock cha_mu(Thread::Current(), *Locks::cha_lock_);
382 // Do this check again after we grab cha_lock_.
383 if (!interface_method->HasSingleImplementation()) {
384 return;
385 }
386
387 ArtMethod* single_impl = interface_method->GetSingleImplementation(pointer_size);
388 if (single_impl == nullptr) {
389 // implementation_method becomes the first implementation for
390 // interface_method.
391 interface_method->SetSingleImplementation(implementation_method, pointer_size);
392 // Keep interface_method's single-implementation status.
393 return;
394 }
395 DCHECK(!single_impl->IsAbstract());
396 if (single_impl->GetDeclaringClass() == implementation_method->GetDeclaringClass()) {
397 // Same implementation. Since implementation_method may be a copy of a default
398 // method, we need to check the declaring class for equality.
399 return;
400 }
401 // Another implementation for interface_method.
402 invalidated_single_impl_methods.insert(interface_method);
403 }
404
InitSingleImplementationFlag(Handle<mirror::Class> klass,ArtMethod * method,PointerSize pointer_size)405 void ClassHierarchyAnalysis::InitSingleImplementationFlag(Handle<mirror::Class> klass,
406 ArtMethod* method,
407 PointerSize pointer_size) {
408 DCHECK(method->IsCopied() || method->GetDeclaringClass() == klass.Get());
409 if (klass->IsFinal() || method->IsFinal()) {
410 // Final classes or methods do not need CHA for devirtualization.
411 // This frees up modifier bits for intrinsics which currently are only
412 // used for static methods or methods of final classes.
413 return;
414 }
415 if (method->IsAbstract()) {
416 // single-implementation of abstract method shares the same field
417 // that's used for JNI function of native method. It's fine since a method
418 // cannot be both abstract and native.
419 DCHECK(!method->IsNative()) << "Abstract method cannot be native";
420
421 if (method->GetDeclaringClass()->IsInstantiable()) {
422 // Rare case, but we do accept it (such as 800-smali/smali/b_26143249.smali).
423 // Do not attempt to devirtualize it.
424 method->SetHasSingleImplementation(false);
425 DCHECK(method->GetSingleImplementation(pointer_size) == nullptr);
426 } else {
427 // Abstract method starts with single-implementation flag set and null
428 // implementation method.
429 method->SetHasSingleImplementation(true);
430 DCHECK(method->GetSingleImplementation(pointer_size) == nullptr);
431 }
432 } else {
433 method->SetHasSingleImplementation(true);
434 // Single implementation of non-abstract method is itself.
435 DCHECK_EQ(method->GetSingleImplementation(pointer_size), method);
436 }
437 }
438
UpdateAfterLoadingOf(Handle<mirror::Class> klass)439 void ClassHierarchyAnalysis::UpdateAfterLoadingOf(Handle<mirror::Class> klass) {
440 PointerSize image_pointer_size = Runtime::Current()->GetClassLinker()->GetImagePointerSize();
441 if (klass->IsInterface()) {
442 for (ArtMethod& method : klass->GetDeclaredVirtualMethods(image_pointer_size)) {
443 DCHECK(method.IsAbstract() || method.IsDefault());
444 InitSingleImplementationFlag(klass, &method, image_pointer_size);
445 }
446 return;
447 }
448
449 mirror::Class* super_class = klass->GetSuperClass();
450 if (super_class == nullptr) {
451 return;
452 }
453
454 // Keeps track of all methods whose single-implementation assumption
455 // is invalidated by linking `klass`.
456 std::unordered_set<ArtMethod*> invalidated_single_impl_methods;
457
458 // Do an entry-by-entry comparison of vtable contents with super's vtable.
459 for (int32_t i = 0; i < super_class->GetVTableLength(); ++i) {
460 ArtMethod* method = klass->GetVTableEntry(i, image_pointer_size);
461 ArtMethod* method_in_super = super_class->GetVTableEntry(i, image_pointer_size);
462 if (method == method_in_super) {
463 // vtable slot entry is inherited from super class.
464 if (method->IsAbstract() && klass->IsInstantiable()) {
465 // An instantiable class that inherits an abstract method is treated as
466 // supplying an implementation that throws AbstractMethodError.
467 CheckVirtualMethodSingleImplementationInfo(klass,
468 method,
469 method_in_super,
470 invalidated_single_impl_methods,
471 image_pointer_size);
472 }
473 continue;
474 }
475 InitSingleImplementationFlag(klass, method, image_pointer_size);
476 CheckVirtualMethodSingleImplementationInfo(klass,
477 method,
478 method_in_super,
479 invalidated_single_impl_methods,
480 image_pointer_size);
481 }
482 // For new virtual methods that don't override.
483 for (int32_t i = super_class->GetVTableLength(); i < klass->GetVTableLength(); ++i) {
484 ArtMethod* method = klass->GetVTableEntry(i, image_pointer_size);
485 InitSingleImplementationFlag(klass, method, image_pointer_size);
486 }
487
488 if (klass->IsInstantiable()) {
489 auto* iftable = klass->GetIfTable();
490 const size_t ifcount = klass->GetIfTableCount();
491 for (size_t i = 0; i < ifcount; ++i) {
492 mirror::Class* interface = iftable->GetInterface(i);
493 for (size_t j = 0, count = iftable->GetMethodArrayCount(i); j < count; ++j) {
494 ArtMethod* interface_method = interface->GetVirtualMethod(j, image_pointer_size);
495 mirror::PointerArray* method_array = iftable->GetMethodArray(i);
496 ArtMethod* implementation_method =
497 method_array->GetElementPtrSize<ArtMethod*>(j, image_pointer_size);
498 DCHECK(implementation_method != nullptr) << klass->PrettyClass();
499 CheckInterfaceMethodSingleImplementationInfo(klass,
500 interface_method,
501 implementation_method,
502 invalidated_single_impl_methods,
503 image_pointer_size);
504 }
505 }
506 }
507
508 InvalidateSingleImplementationMethods(invalidated_single_impl_methods);
509 }
510
InvalidateSingleImplementationMethods(std::unordered_set<ArtMethod * > & invalidated_single_impl_methods)511 void ClassHierarchyAnalysis::InvalidateSingleImplementationMethods(
512 std::unordered_set<ArtMethod*>& invalidated_single_impl_methods) {
513 if (!invalidated_single_impl_methods.empty()) {
514 Runtime* const runtime = Runtime::Current();
515 Thread *self = Thread::Current();
516 // Method headers for compiled code to be invalidated.
517 std::unordered_set<OatQuickMethodHeader*> dependent_method_headers;
518 PointerSize image_pointer_size =
519 Runtime::Current()->GetClassLinker()->GetImagePointerSize();
520
521 {
522 // We do this under cha_lock_. Committing code also grabs this lock to
523 // make sure the code is only committed when all single-implementation
524 // assumptions are still true.
525 MutexLock cha_mu(self, *Locks::cha_lock_);
526 // Invalidate compiled methods that assume some virtual calls have only
527 // single implementations.
528 for (ArtMethod* invalidated : invalidated_single_impl_methods) {
529 if (!invalidated->HasSingleImplementation()) {
530 // It might have been invalidated already when other class linking is
531 // going on.
532 continue;
533 }
534 invalidated->SetHasSingleImplementation(false);
535 if (invalidated->IsAbstract()) {
536 // Clear the single implementation method.
537 invalidated->SetSingleImplementation(nullptr, image_pointer_size);
538 }
539
540 if (runtime->IsAotCompiler()) {
541 // No need to invalidate any compiled code as the AotCompiler doesn't
542 // run any code.
543 continue;
544 }
545
546 // Invalidate all dependents.
547 for (const auto& dependent : GetDependents(invalidated)) {
548 ArtMethod* method = dependent.first;;
549 OatQuickMethodHeader* method_header = dependent.second;
550 VLOG(class_linker) << "CHA invalidated compiled code for " << method->PrettyMethod();
551 DCHECK(runtime->UseJitCompilation());
552 runtime->GetJit()->GetCodeCache()->InvalidateCompiledCodeFor(
553 method, method_header);
554 dependent_method_headers.insert(method_header);
555 }
556 RemoveAllDependenciesFor(invalidated);
557 }
558 }
559
560 if (dependent_method_headers.empty()) {
561 return;
562 }
563 // Deoptimze compiled code on stack that should have been invalidated.
564 CHACheckpoint checkpoint(dependent_method_headers);
565 size_t threads_running_checkpoint = runtime->GetThreadList()->RunCheckpoint(&checkpoint);
566 if (threads_running_checkpoint != 0) {
567 checkpoint.WaitForThreadsToRunThroughCheckpoint(threads_running_checkpoint);
568 }
569 }
570 }
571
RemoveDependenciesForLinearAlloc(const LinearAlloc * linear_alloc)572 void ClassHierarchyAnalysis::RemoveDependenciesForLinearAlloc(const LinearAlloc* linear_alloc) {
573 MutexLock mu(Thread::Current(), *Locks::cha_lock_);
574 for (auto it = cha_dependency_map_.begin(); it != cha_dependency_map_.end(); ) {
575 // Use unsafe to avoid locking since the allocator is going to be deleted.
576 if (linear_alloc->ContainsUnsafe(it->first)) {
577 // About to delete the ArtMethod, erase the entry from the map.
578 it = cha_dependency_map_.erase(it);
579 } else {
580 ++it;
581 }
582 }
583 }
584
585 } // namespace art
586