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