• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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