Home | History | Annotate | Download | only in runtime
      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 
     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 
     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 
     51 void ClassHierarchyAnalysis::RemoveAllDependenciesFor(ArtMethod* method) {
     52   cha_dependency_map_.erase(method);
     53 }
     54 
     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:
     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 
     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:
    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:
    149   explicit CHACheckpoint(const std::unordered_set<OatQuickMethodHeader*>& method_headers)
    150       : barrier_(0),
    151         method_headers_(method_headers) {}
    152 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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