/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "cha.h"

#include "art_method-inl.h"
#include "base/logging.h"  // For VLOG
#include "base/mutex.h"
#include "jit/jit.h"
#include "jit/jit_code_cache.h"
#include "linear_alloc.h"
#include "mirror/class_loader.h"
#include "runtime.h"
#include "scoped_thread_state_change-inl.h"
#include "stack.h"
#include "thread.h"
#include "thread_list.h"
#include "thread_pool.h"

namespace art HIDDEN {

void ClassHierarchyAnalysis::AddDependency(ArtMethod* method,
                                           ArtMethod* dependent_method,
                                           OatQuickMethodHeader* dependent_header) {
  const auto it = cha_dependency_map_.insert(
      decltype(cha_dependency_map_)::value_type(method, ListOfDependentPairs())).first;
  it->second.push_back({dependent_method, dependent_header});
}

static const ClassHierarchyAnalysis::ListOfDependentPairs s_empty_vector;

const ClassHierarchyAnalysis::ListOfDependentPairs& ClassHierarchyAnalysis::GetDependents(
    ArtMethod* method) {
  auto it = cha_dependency_map_.find(method);
  if (it != cha_dependency_map_.end()) {
    return it->second;
  }
  return s_empty_vector;
}

void ClassHierarchyAnalysis::RemoveAllDependenciesFor(ArtMethod* method) {
  cha_dependency_map_.erase(method);
}

void ClassHierarchyAnalysis::RemoveDependentsWithMethodHeaders(
    const std::unordered_set<OatQuickMethodHeader*>& method_headers) {
  // Iterate through all entries in the dependency map and remove any entry that
  // contains one of those in method_headers.
  for (auto map_it = cha_dependency_map_.begin(); map_it != cha_dependency_map_.end(); ) {
    ListOfDependentPairs& dependents = map_it->second;
    dependents.erase(
        std::remove_if(
            dependents.begin(),
            dependents.end(),
            [&method_headers](MethodAndMethodHeaderPair& dependent) {
              return method_headers.find(dependent.second) != method_headers.end();
            }),
        dependents.end());

    // Remove the map entry if there are no more dependents.
    if (dependents.empty()) {
      map_it = cha_dependency_map_.erase(map_it);
    } else {
      map_it++;
    }
  }
}

void ClassHierarchyAnalysis::ResetSingleImplementationInHierarchy(ObjPtr<mirror::Class> klass,
                                                                  const LinearAlloc* alloc,
                                                                  const PointerSize pointer_size)
                                                                  const {
  // Presumably called from some sort of class visitor, no null pointers expected.
  DCHECK(klass != nullptr);
  DCHECK(alloc != nullptr);

  // Skip interfaces since they cannot provide SingleImplementations to work with.
  if (klass->IsInterface()) {
    return;
  }

  // This method is called while visiting classes in the class table of a class loader.
  // That means, some 'klass'es can belong to other classloaders. Argument 'alloc'
  // allows to explicitly indicate a classloader, which is going to be deleted.
  // Filter out classes, that do not belong to it.
  if (!alloc->ContainsUnsafe(klass->GetMethodsPtr())) {
    return;
  }

  // CHA analysis is only applied to resolved classes.
  if (!klass->IsResolved()) {
    return;
  }

  ObjPtr<mirror::Class> super = klass->GetSuperClass<kDefaultVerifyFlags, kWithoutReadBarrier>();

  // Skip Object class and primitive classes.
  if (super == nullptr) {
    return;
  }

  // The class is going to be deleted. Iterate over the virtual methods of its superclasses to see
  // if they have SingleImplementations methods defined by 'klass'.
  // Skip all virtual methods that do not override methods from super class since they cannot be
  // SingleImplementations for anything.
  int32_t vtbl_size = super->GetVTableLength<kDefaultVerifyFlags>();
  ObjPtr<mirror::ClassLoader> loader =
      klass->GetClassLoader<kDefaultVerifyFlags, kWithoutReadBarrier>();
  for (int vtbl_index = 0; vtbl_index < vtbl_size; ++vtbl_index) {
    ArtMethod* method =
        klass->GetVTableEntry<kDefaultVerifyFlags, kWithoutReadBarrier>(vtbl_index, pointer_size);
    if (!alloc->ContainsUnsafe(method)) {
      continue;
    }

    // Find all occurrences of virtual methods in parents' SingleImplementations fields
    // and reset them.
    // No need to reset SingleImplementations for the method itself (it will be cleared anyways),
    // so start with a superclass and move up looking into a corresponding vtbl slot.
    for (ObjPtr<mirror::Class> super_it = super;
         super_it != nullptr &&
             super_it->GetVTableLength<kDefaultVerifyFlags>() > vtbl_index;
         super_it = super_it->GetSuperClass<kDefaultVerifyFlags, kWithoutReadBarrier>()) {
      // Skip superclasses that are also going to be unloaded.
      ObjPtr<mirror::ClassLoader> super_loader = super_it->
          GetClassLoader<kDefaultVerifyFlags, kWithoutReadBarrier>();
      if (super_loader == loader) {
        continue;
      }

      ArtMethod* super_method = super_it->
          GetVTableEntry<kDefaultVerifyFlags, kWithoutReadBarrier>(vtbl_index, pointer_size);
      if (super_method->IsAbstract() &&
          super_method->HasSingleImplementation() &&
          super_method->GetSingleImplementation(pointer_size) == method) {
        // Do like there was no single implementation defined previously
        // for this method of the superclass.
        super_method->SetSingleImplementation(nullptr, pointer_size);
      } else {
        // No related SingleImplementations could possibly be found any further.
        DCHECK(!super_method->HasSingleImplementation());
        break;
      }
    }
  }

  // Check all possible interface methods too.
  ObjPtr<mirror::IfTable> iftable = klass->GetIfTable<kDefaultVerifyFlags, kWithoutReadBarrier>();
  const size_t ifcount = klass->GetIfTableCount<kDefaultVerifyFlags>();
  for (size_t i = 0; i < ifcount; ++i) {
    ObjPtr<mirror::Class> interface =
        iftable->GetInterface<kDefaultVerifyFlags, kWithoutReadBarrier>(i);
    for (size_t j = 0,
         count = iftable->GetMethodArrayCount<kDefaultVerifyFlags, kWithoutReadBarrier>(i);
         j < count;
         ++j) {
      ArtMethod* method = interface->GetVirtualMethod(j, pointer_size);
      if (method->HasSingleImplementation() &&
          alloc->ContainsUnsafe(method->GetSingleImplementation(pointer_size)) &&
          !method->IsDefault()) {
        // Do like there was no single implementation defined previously for this method.
        method->SetSingleImplementation(nullptr, pointer_size);
      }
    }
  }
}

// This stack visitor walks the stack and for compiled code with certain method
// headers, sets the should_deoptimize flag on stack to 1.
// TODO: also set the register value to 1 when should_deoptimize is allocated in
// a register.
class CHAStackVisitor final  : public StackVisitor {
 public:
  CHAStackVisitor(Thread* thread_in,
                  Context* context,
                  const std::unordered_set<OatQuickMethodHeader*>& method_headers)
      : StackVisitor(thread_in, context, StackVisitor::StackWalkKind::kSkipInlinedFrames),
        method_headers_(method_headers) {
  }

  bool VisitFrame() override REQUIRES_SHARED(Locks::mutator_lock_) {
    ArtMethod* method = GetMethod();
    // Avoid types of methods that do not have an oat quick method header.
    if (method == nullptr ||
        method->IsRuntimeMethod() ||
        method->IsNative() ||
        method->IsProxyMethod()) {
      return true;
    }
    if (GetCurrentQuickFrame() == nullptr) {
      // Not compiled code.
      return true;
    }
    // Method may have multiple versions of compiled code. Check
    // the method header to see if it has should_deoptimize flag.
    const OatQuickMethodHeader* method_header = GetCurrentOatQuickMethodHeader();
    DCHECK(method_header != nullptr);
    if (!method_header->HasShouldDeoptimizeFlag()) {
      // This compiled version doesn't have should_deoptimize flag. Skip.
      return true;
    }
    auto it = std::find(method_headers_.begin(), method_headers_.end(), method_header);
    if (it == method_headers_.end()) {
      // Not in the list of method headers that should be deoptimized.
      return true;
    }

    // The compiled code on stack is not valid anymore. Need to deoptimize.
    SetShouldDeoptimizeFlag(DeoptimizeFlagValue::kCHA);

    return true;
  }

 private:
  // Set of method headers for compiled code that should be deoptimized.
  const std::unordered_set<OatQuickMethodHeader*>& method_headers_;

  DISALLOW_COPY_AND_ASSIGN(CHAStackVisitor);
};

class CHACheckpoint final : public Closure {
 public:
  explicit CHACheckpoint(const std::unordered_set<OatQuickMethodHeader*>& method_headers)
      : barrier_(0),
        method_headers_(method_headers) {}

  void Run(Thread* thread) override REQUIRES_SHARED(Locks::mutator_lock_) {
    // Note thread and self may not be equal if thread was already suspended at
    // the point of the request.
    Thread* self = Thread::Current();
    CHAStackVisitor visitor(thread, nullptr, method_headers_);
    visitor.WalkStack();
    barrier_.Pass(self);
  }

  void WaitForThreadsToRunThroughCheckpoint(size_t threads_running_checkpoint) {
    Thread* self = Thread::Current();
    ScopedThreadStateChange tsc(self, ThreadState::kWaitingForCheckPointsToRun);
    barrier_.Increment(self, threads_running_checkpoint);
  }

 private:
  // The barrier to be passed through and for the requestor to wait upon.
  Barrier barrier_;
  // List of method headers for invalidated compiled code.
  const std::unordered_set<OatQuickMethodHeader*>& method_headers_;

  DISALLOW_COPY_AND_ASSIGN(CHACheckpoint);
};


static void VerifyNonSingleImplementation(ObjPtr<mirror::Class> verify_class,
                                          uint16_t verify_index,
                                          ArtMethod* excluded_method)
    REQUIRES_SHARED(Locks::mutator_lock_) {
  if (!kIsDebugBuild) {
    return;
  }

  // Grab cha_lock_ to make sure all single-implementation updates are seen.
  MutexLock cha_mu(Thread::Current(), *Locks::cha_lock_);

  PointerSize image_pointer_size =
      Runtime::Current()->GetClassLinker()->GetImagePointerSize();

  ObjPtr<mirror::Class> input_verify_class = verify_class;

  while (verify_class != nullptr) {
    if (verify_index >= verify_class->GetVTableLength()) {
      return;
    }
    ArtMethod* verify_method = verify_class->GetVTableEntry(verify_index, image_pointer_size);
    if (verify_method != excluded_method) {
      auto construct_parent_chain = [](ObjPtr<mirror::Class> failed, ObjPtr<mirror::Class> in)
          REQUIRES_SHARED(Locks::mutator_lock_) {
        std::string tmp = in->PrettyClass();
        while (in != failed) {
          in = in->GetSuperClass();
          tmp += "->" + in->PrettyClass();
        }
        return tmp;
      };
      DCHECK(!verify_method->HasSingleImplementation())
          << "class: " << verify_class->PrettyClass()
          << " verify_method: " << verify_method->PrettyMethod(true)
          << " (" << construct_parent_chain(verify_class, input_verify_class) << ")"
          << " excluded_method: " << ArtMethod::PrettyMethod(excluded_method);
      if (verify_method->IsAbstract()) {
        DCHECK(verify_method->GetSingleImplementation(image_pointer_size) == nullptr);
      }
    }
    verify_class = verify_class->GetSuperClass();
  }
}

void ClassHierarchyAnalysis::CheckVirtualMethodSingleImplementationInfo(
    Handle<mirror::Class> klass,
    ArtMethod* virtual_method,
    ArtMethod* method_in_super,
    std::unordered_set<ArtMethod*>& invalidated_single_impl_methods,
    PointerSize pointer_size) {
  // TODO: if klass is not instantiable, virtual_method isn't invocable yet so
  // even if it overrides, it doesn't invalidate single-implementation
  // assumption.

  DCHECK_IMPLIES(virtual_method == method_in_super, virtual_method->IsAbstract());
  DCHECK(method_in_super->GetDeclaringClass()->IsResolved()) << "class isn't resolved";
  // If virtual_method doesn't come from a default interface method, it should
  // be supplied by klass.
  DCHECK(virtual_method == method_in_super ||
         virtual_method->IsCopied() ||
         virtual_method->GetDeclaringClass() == klass.Get());

  // To make updating single-implementation flags simple, we always maintain the following
  // invariant:
  // Say all virtual methods in the same vtable slot, starting from the bottom child class
  // to super classes, is a sequence of unique methods m3, m2, m1, ... (after removing duplicate
  // methods for inherited methods).
  // For example for the following class hierarchy,
  //   class A { void m() { ... } }
  //   class B extends A { void m() { ... } }
  //   class C extends B {}
  //   class D extends C { void m() { ... } }
  // the sequence is D.m(), B.m(), A.m().
  // The single-implementation status for that sequence of methods begin with one or two true's,
  // then become all falses. The only case where two true's are possible is for one abstract
  // method m and one non-abstract method mImpl that overrides method m.
  // With the invariant, when linking in a new class, we only need to at most update one or
  // two methods in the sequence for their single-implementation status, in order to maintain
  // the invariant.

  if (!method_in_super->HasSingleImplementation()) {
    // method_in_super already has multiple implementations. All methods in the
    // same vtable slots in its super classes should have
    // non-single-implementation already.
    VerifyNonSingleImplementation(klass->GetSuperClass()->GetSuperClass(),
                                  method_in_super->GetMethodIndex(),
                                  /* excluded_method= */ nullptr);
    return;
  }

  uint16_t method_index = method_in_super->GetMethodIndex();
  if (method_in_super->IsAbstract()) {
    // An abstract method should have made all methods in the same vtable
    // slot above it in the class hierarchy having non-single-implementation.
    VerifyNonSingleImplementation(klass->GetSuperClass()->GetSuperClass(),
                                  method_index,
                                  method_in_super);

    if (virtual_method->IsAbstract()) {
      // SUPER: abstract, VIRTUAL: abstract.
      if (method_in_super == virtual_method) {
        DCHECK(klass->IsInstantiable());
        // An instantiable subclass hasn't provided a concrete implementation of
        // the abstract method. Invoking method_in_super may throw AbstractMethodError.
        // This is an uncommon case, so we simply treat method_in_super as not
        // having single-implementation.
        invalidated_single_impl_methods.insert(method_in_super);
        return;
      } else {
        // One abstract method overrides another abstract method. This is an uncommon
        // case. We simply treat method_in_super as not having single-implementation.
        invalidated_single_impl_methods.insert(method_in_super);
        return;
      }
    } else {
      // SUPER: abstract, VIRTUAL: non-abstract.
      // A non-abstract method overrides an abstract method.
      if (!virtual_method->IsDefaultConflicting() &&
          method_in_super->GetSingleImplementation(pointer_size) == nullptr) {
        // Abstract method_in_super has no implementation yet.
        // We need to grab cha_lock_ since there may be multiple class linking
        // going on that can check/modify the single-implementation flag/method
        // of method_in_super.
        MutexLock cha_mu(Thread::Current(), *Locks::cha_lock_);
        if (!method_in_super->HasSingleImplementation()) {
          return;
        }
        if (method_in_super->GetSingleImplementation(pointer_size) == nullptr) {
          // virtual_method becomes the first implementation for method_in_super.
          method_in_super->SetSingleImplementation(virtual_method, pointer_size);
          // Keep method_in_super's single-implementation status.
          return;
        }
        // Fall through to invalidate method_in_super's single-implementation status.
      }
      // Abstract method_in_super already got one implementation.
      // Invalidate method_in_super's single-implementation status.
      invalidated_single_impl_methods.insert(method_in_super);
      return;
    }
  } else {
    if (virtual_method->IsAbstract()) {
      // SUPER: non-abstract, VIRTUAL: abstract.
      // An abstract method overrides a non-abstract method. This is an uncommon
      // case, we simply treat both methods as not having single-implementation.
      invalidated_single_impl_methods.insert(virtual_method);
      // Fall-through to handle invalidating method_in_super of its
      // single-implementation status.
    }

    // SUPER: non-abstract, VIRTUAL: non-abstract/abstract(fall-through from previous if).
    // Invalidate method_in_super's single-implementation status.
    invalidated_single_impl_methods.insert(method_in_super);

    // method_in_super might be the single-implementation of another abstract method,
    // which should be also invalidated of its single-implementation status.
    ObjPtr<mirror::Class> super_super = klass->GetSuperClass()->GetSuperClass();
    while (super_super != nullptr &&
           method_index < super_super->GetVTableLength()) {
      ArtMethod* method_in_super_super = super_super->GetVTableEntry(method_index, pointer_size);
      if (method_in_super_super != method_in_super) {
        if (method_in_super_super->IsAbstract()) {
          if (method_in_super_super->HasSingleImplementation()) {
            // Invalidate method_in_super's single-implementation status.
            invalidated_single_impl_methods.insert(method_in_super_super);
            // No need to further traverse up the class hierarchy since if there
            // are cases that one abstract method overrides another method, we
            // should have made that method having non-single-implementation already.
          } else {
            // method_in_super_super is already non-single-implementation.
            // No need to further traverse up the class hierarchy.
          }
        } else {
          DCHECK(!method_in_super_super->HasSingleImplementation());
          // No need to further traverse up the class hierarchy since two non-abstract
          // methods (method_in_super and method_in_super_super) should have set all
          // other methods (abstract or not) in the vtable slot to be non-single-implementation.
        }

        VerifyNonSingleImplementation(super_super->GetSuperClass(),
                                      method_index,
                                      method_in_super_super);
        // No need to go any further.
        return;
      } else {
        super_super = super_super->GetSuperClass();
      }
    }
  }
}

void ClassHierarchyAnalysis::CheckInterfaceMethodSingleImplementationInfo(
    Handle<mirror::Class> klass,
    ArtMethod* interface_method,
    ArtMethod* implementation_method,
    std::unordered_set<ArtMethod*>& invalidated_single_impl_methods,
    PointerSize pointer_size) {
  DCHECK(klass->IsInstantiable());
  DCHECK(interface_method->IsAbstract() || interface_method->IsDefault());

  if (!interface_method->HasSingleImplementation()) {
    return;
  }

  if (!implementation_method->IsInvokable()) {
    DCHECK(implementation_method->IsAbstract() || implementation_method->IsDefaultConflicting());
    // An instantiable class doesn't supply an implementation for interface_method,
    // or has conflicting default method implementations. Invoking the interface method
    // on the  class will throw AbstractMethodError or IncompatibleClassChangeError.
    // (Note: The RI throws AME instead of ICCE for default conflict.) This is an uncommon
    // case, so we simply treat interface_method as not having single-implementation.
    invalidated_single_impl_methods.insert(interface_method);
    return;
  }

  // We need to grab cha_lock_ since there may be multiple class linking going
  // on that can check/modify the single-implementation flag/method of
  // interface_method.
  MutexLock cha_mu(Thread::Current(), *Locks::cha_lock_);
  // Do this check again after we grab cha_lock_.
  if (!interface_method->HasSingleImplementation()) {
    return;
  }

  ArtMethod* single_impl = interface_method->GetSingleImplementation(pointer_size);
  if (single_impl == nullptr) {
    // implementation_method becomes the first implementation for
    // interface_method.
    interface_method->SetSingleImplementation(implementation_method, pointer_size);
    // Keep interface_method's single-implementation status.
    return;
  }
  DCHECK(single_impl->IsInvokable());
  if ((single_impl->GetDeclaringClass() == implementation_method->GetDeclaringClass())) {
    // Same implementation. Since implementation_method may be a copy of a default
    // method, we need to check the declaring class for equality.
    return;
  }
  // Another implementation for interface_method.
  invalidated_single_impl_methods.insert(interface_method);
}

void ClassHierarchyAnalysis::InitSingleImplementationFlag(Handle<mirror::Class> klass,
                                                          ArtMethod* method,
                                                          PointerSize pointer_size) {
  DCHECK(method->IsCopied() || method->GetDeclaringClass() == klass.Get());
  if (klass->IsFinal() || method->IsFinal()) {
    // Final classes or methods do not need CHA for devirtualization.
    // This frees up modifier bits for intrinsics which currently are only
    // used for static methods or methods of final classes.
    return;
  }
  if (method->IsAbstract()) {
    // single-implementation of abstract method shares the same field
    // that's used for JNI function of native method. It's fine since a method
    // cannot be both abstract and native.
    DCHECK(!method->IsNative()) << "Abstract method cannot be native";

    if (method->GetDeclaringClass()->IsInstantiable()) {
      // Rare case, but we do accept it (such as 800-smali/smali/b_26143249.smali).
      // Do not attempt to devirtualize it.
      method->SetHasSingleImplementation(false);
      DCHECK(method->GetSingleImplementation(pointer_size) == nullptr);
    } else {
      // Abstract method starts with single-implementation flag set and null
      // implementation method.
      method->SetHasSingleImplementation(true);
      DCHECK(!method->HasCodeItem()) << method->PrettyMethod();
      DCHECK(method->GetSingleImplementation(pointer_size) == nullptr) << method->PrettyMethod();
    }
  // Default conflicting methods cannot be treated with single implementations,
  // as we need to call them (and not inline them) in case of ICCE.
  // See class_linker.cc:EnsureThrowsInvocationError.
  } else if (!method->IsDefaultConflicting()) {
    method->SetHasSingleImplementation(true);
    // Single implementation of non-abstract method is itself.
    DCHECK_EQ(method->GetSingleImplementation(pointer_size), method);
  }
}

void ClassHierarchyAnalysis::UpdateAfterLoadingOf(Handle<mirror::Class> klass) {
  PointerSize image_pointer_size = Runtime::Current()->GetClassLinker()->GetImagePointerSize();
  if (klass->IsInterface()) {
    for (ArtMethod& method : klass->GetDeclaredVirtualMethods(image_pointer_size)) {
      DCHECK(method.IsAbstract() || method.IsDefault());
      InitSingleImplementationFlag(klass, &method, image_pointer_size);
    }
    return;
  }

  ObjPtr<mirror::Class> super_class = klass->GetSuperClass();
  if (super_class == nullptr) {
    return;
  }

  // Keeps track of all methods whose single-implementation assumption
  // is invalidated by linking `klass`.
  std::unordered_set<ArtMethod*> invalidated_single_impl_methods;

  // Do an entry-by-entry comparison of vtable contents with super's vtable.
  for (int32_t i = 0; i < super_class->GetVTableLength(); ++i) {
    ArtMethod* method = klass->GetVTableEntry(i, image_pointer_size);
    ArtMethod* method_in_super = super_class->GetVTableEntry(i, image_pointer_size);
    if (method == method_in_super) {
      // vtable slot entry is inherited from super class.
      if (method->IsAbstract() && klass->IsInstantiable()) {
        // An instantiable class that inherits an abstract method is treated as
        // supplying an implementation that throws AbstractMethodError.
        CheckVirtualMethodSingleImplementationInfo(klass,
                                                   method,
                                                   method_in_super,
                                                   invalidated_single_impl_methods,
                                                   image_pointer_size);
      }
      continue;
    }
    InitSingleImplementationFlag(klass, method, image_pointer_size);
    CheckVirtualMethodSingleImplementationInfo(klass,
                                               method,
                                               method_in_super,
                                               invalidated_single_impl_methods,
                                               image_pointer_size);
  }
  // For new virtual methods that don't override.
  for (int32_t i = super_class->GetVTableLength(); i < klass->GetVTableLength(); ++i) {
    ArtMethod* method = klass->GetVTableEntry(i, image_pointer_size);
    InitSingleImplementationFlag(klass, method, image_pointer_size);
  }

  if (klass->IsInstantiable()) {
    ObjPtr<mirror::IfTable> iftable = klass->GetIfTable();
    const size_t ifcount = klass->GetIfTableCount();
    for (size_t i = 0; i < ifcount; ++i) {
      ObjPtr<mirror::Class> interface = iftable->GetInterface(i);
      for (size_t j = 0, count = iftable->GetMethodArrayCount(i); j < count; ++j) {
        ArtMethod* interface_method = interface->GetVirtualMethod(j, image_pointer_size);
        ObjPtr<mirror::PointerArray> method_array = iftable->GetMethodArray(i);
        ArtMethod* implementation_method =
            method_array->GetElementPtrSize<ArtMethod*>(j, image_pointer_size);
        DCHECK(implementation_method != nullptr) << klass->PrettyClass();
        CheckInterfaceMethodSingleImplementationInfo(klass,
                                                     interface_method,
                                                     implementation_method,
                                                     invalidated_single_impl_methods,
                                                     image_pointer_size);
      }
    }
  }

  InvalidateSingleImplementationMethods(invalidated_single_impl_methods);
}

void ClassHierarchyAnalysis::InvalidateSingleImplementationMethods(
    std::unordered_set<ArtMethod*>& invalidated_single_impl_methods) {
  if (!invalidated_single_impl_methods.empty()) {
    Runtime* const runtime = Runtime::Current();
    Thread *self = Thread::Current();
    // Method headers for compiled code to be invalidated.
    std::unordered_set<OatQuickMethodHeader*> dependent_method_headers;
    PointerSize image_pointer_size =
        Runtime::Current()->GetClassLinker()->GetImagePointerSize();

    {
      // We do this under cha_lock_. Committing code also grabs this lock to
      // make sure the code is only committed when all single-implementation
      // assumptions are still true.
      std::vector<std::pair<ArtMethod*, OatQuickMethodHeader*>> headers;
      {
        MutexLock cha_mu(self, *Locks::cha_lock_);
        // Invalidate compiled methods that assume some virtual calls have only
        // single implementations.
        for (ArtMethod* invalidated : invalidated_single_impl_methods) {
          if (!invalidated->HasSingleImplementation()) {
            // It might have been invalidated already when other class linking is
            // going on.
            continue;
          }
          invalidated->SetHasSingleImplementation(false);
          if (invalidated->IsAbstract()) {
            // Clear the single implementation method.
            invalidated->SetSingleImplementation(nullptr, image_pointer_size);
          }

          if (runtime->IsAotCompiler()) {
            // No need to invalidate any compiled code as the AotCompiler doesn't
            // run any code.
            continue;
          }

          // Invalidate all dependents.
          for (const auto& dependent : GetDependents(invalidated)) {
            ArtMethod* method = dependent.first;;
            OatQuickMethodHeader* method_header = dependent.second;
            VLOG(class_linker) << "CHA invalidated compiled code for " << method->PrettyMethod();
            DCHECK(runtime->UseJitCompilation());
            // We need to call JitCodeCache::InvalidateCompiledCodeFor but we cannot do it here
            // since it would run into problems with lock-ordering. We don't want to re-order the
            // locks since that would make code-commit racy.
            headers.push_back({method, method_header});
            dependent_method_headers.insert(method_header);
          }
          RemoveAllDependenciesFor(invalidated);
        }
      }
      // Since we are still loading the class that invalidated the code it's fine we have this after
      // getting rid of the dependency. Any calls would need to be with the old version (since the
      // new one isn't loaded yet) which still works fine. We will deoptimize just after this to
      // ensure everything gets the new state.
      jit::Jit* jit = Runtime::Current()->GetJit();
      if (jit != nullptr) {
        jit::JitCodeCache* code_cache = jit->GetCodeCache();
        for (const auto& pair : headers) {
          code_cache->InvalidateCompiledCodeFor(pair.first, pair.second);
        }
      }
    }

    if (dependent_method_headers.empty()) {
      return;
    }
    // Deoptimze compiled code on stack that should have been invalidated.
    CHACheckpoint checkpoint(dependent_method_headers);
    size_t threads_running_checkpoint = runtime->GetThreadList()->RunCheckpoint(&checkpoint);
    if (threads_running_checkpoint != 0) {
      checkpoint.WaitForThreadsToRunThroughCheckpoint(threads_running_checkpoint);
    }
  }
}

void ClassHierarchyAnalysis::RemoveDependenciesForLinearAlloc(Thread* self,
                                                              const LinearAlloc* linear_alloc) {
  MutexLock mu(self, *Locks::cha_lock_);
  for (auto it = cha_dependency_map_.begin(); it != cha_dependency_map_.end(); ) {
    // Use unsafe to avoid locking since the allocator is going to be deleted.
    if (linear_alloc->ContainsUnsafe(it->first)) {
      // About to delete the ArtMethod, erase the entry from the map.
      it = cha_dependency_map_.erase(it);
    } else {
      ++it;
    }
  }
}

}  // namespace art
