/*
 * Copyright (C) 2011 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.
 */

#ifndef ART_RUNTIME_CLASS_LINKER_H_
#define ART_RUNTIME_CLASS_LINKER_H_

#include <list>
#include <set>
#include <string>
#include <type_traits>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>

#include "base/enums.h"
#include "base/mutex.h"
#include "base/intrusive_forward_list.h"
#include "base/locks.h"
#include "base/macros.h"
#include "dex/class_accessor.h"
#include "dex/dex_cache_resolved_classes.h"
#include "dex/dex_file_types.h"
#include "gc_root.h"
#include "handle.h"
#include "jni.h"
#include "mirror/class.h"
#include "verifier/verifier_enums.h"

namespace art {

namespace dex {
struct ClassDef;
struct MethodHandleItem;
}  // namespace dex

namespace gc {
namespace space {
class ImageSpace;
}  // namespace space
}  // namespace gc

namespace linker {
struct CompilationHelper;
class ImageWriter;
class OatWriter;
}  // namespace linker

namespace mirror {
class ClassLoader;
class DexCache;
class DexCachePointerArray;
class DexCacheMethodHandlesTest_Open_Test;
class DexCacheTest_Open_Test;
class IfTable;
class MethodHandle;
class MethodHandlesLookup;
class MethodType;
template<class T> class ObjectArray;
class StackTraceElement;
template <typename T> struct NativeDexCachePair;
using MethodDexCachePair = NativeDexCachePair<ArtMethod>;
using MethodDexCacheType = std::atomic<MethodDexCachePair>;
}  // namespace mirror

class ArtField;
class ArtMethod;
class ClassHierarchyAnalysis;
enum class ClassRoot : uint32_t;
class ClassTable;
class DexFile;
template<class T> class Handle;
class ImtConflictTable;
template<typename T> class LengthPrefixedArray;
template<class T> class MutableHandle;
class InternTable;
class LinearAlloc;
class OatFile;
template<class T> class ObjectLock;
class Runtime;
class ScopedObjectAccessAlreadyRunnable;
template<size_t kNumReferences> class PACKED(4) StackHandleScope;
class Thread;

enum VisitRootFlags : uint8_t;

class ClassVisitor {
 public:
  virtual ~ClassVisitor() {}
  // Return true to continue visiting.
  virtual bool operator()(ObjPtr<mirror::Class> klass) = 0;
};

class ClassLoaderVisitor {
 public:
  virtual ~ClassLoaderVisitor() {}
  virtual void Visit(ObjPtr<mirror::ClassLoader> class_loader)
      REQUIRES_SHARED(Locks::classlinker_classes_lock_, Locks::mutator_lock_) = 0;
};

class AllocatorVisitor {
 public:
  virtual ~AllocatorVisitor() {}
  // Return true to continue visiting.
  virtual bool Visit(LinearAlloc* alloc)
      REQUIRES_SHARED(Locks::classlinker_classes_lock_, Locks::mutator_lock_) = 0;
};

class ClassLinker {
 public:
  static constexpr bool kAppImageMayContainStrings = true;

  explicit ClassLinker(InternTable* intern_table,
                       bool fast_class_not_found_exceptions = true);
  virtual ~ClassLinker();

  // Initialize class linker by bootstraping from dex files.
  bool InitWithoutImage(std::vector<std::unique_ptr<const DexFile>> boot_class_path,
                        std::string* error_msg)
      REQUIRES_SHARED(Locks::mutator_lock_)
      REQUIRES(!Locks::dex_lock_);

  // Initialize class linker from one or more boot images.
  bool InitFromBootImage(std::string* error_msg)
      REQUIRES_SHARED(Locks::mutator_lock_)
      REQUIRES(!Locks::dex_lock_);

  // Add boot class path dex files that were not included in the boot image.
  // ClassLinker takes ownership of these dex files.
  void AddExtraBootDexFiles(Thread* self,
                            std::vector<std::unique_ptr<const DexFile>>&& additional_dex_files)
      REQUIRES_SHARED(Locks::mutator_lock_);

  // Add an image space to the class linker, may fix up classloader fields and dex cache fields.
  // The dex files that were newly opened for the space are placed in the out argument
  // out_dex_files. Returns true if the operation succeeded.
  // The space must be already added to the heap before calling AddImageSpace since we need to
  // properly handle read barriers and object marking.
  bool AddImageSpace(gc::space::ImageSpace* space,
                     Handle<mirror::ClassLoader> class_loader,
                     jobjectArray dex_elements,
                     const char* dex_location,
                     std::vector<std::unique_ptr<const DexFile>>* out_dex_files,
                     std::string* error_msg)
      REQUIRES(!Locks::dex_lock_)
      REQUIRES_SHARED(Locks::mutator_lock_);

  bool OpenImageDexFiles(gc::space::ImageSpace* space,
                         std::vector<std::unique_ptr<const DexFile>>* out_dex_files,
                         std::string* error_msg)
      REQUIRES(!Locks::dex_lock_)
      REQUIRES_SHARED(Locks::mutator_lock_);

  // Finds a class by its descriptor, loading it if necessary.
  // If class_loader is null, searches boot_class_path_.
  ObjPtr<mirror::Class> FindClass(Thread* self,
                                  const char* descriptor,
                                  Handle<mirror::ClassLoader> class_loader)
      REQUIRES_SHARED(Locks::mutator_lock_)
      REQUIRES(!Locks::dex_lock_);

  // Finds a class by its descriptor using the "system" class loader, ie by searching the
  // boot_class_path_.
  ObjPtr<mirror::Class> FindSystemClass(Thread* self, const char* descriptor)
      REQUIRES_SHARED(Locks::mutator_lock_)
      REQUIRES(!Locks::dex_lock_) {
    return FindClass(self, descriptor, ScopedNullHandle<mirror::ClassLoader>());
  }

  // Finds the array class given for the element class.
  ObjPtr<mirror::Class> FindArrayClass(Thread* self, ObjPtr<mirror::Class> element_class)
      REQUIRES_SHARED(Locks::mutator_lock_)
      REQUIRES(!Locks::dex_lock_);

  // Returns true if the class linker is initialized.
  bool IsInitialized() const {
    return init_done_;
  }

  // Define a new a class based on a ClassDef from a DexFile
  ObjPtr<mirror::Class> DefineClass(Thread* self,
                                    const char* descriptor,
                                    size_t hash,
                                    Handle<mirror::ClassLoader> class_loader,
                                    const DexFile& dex_file,
                                    const dex::ClassDef& dex_class_def)
      REQUIRES_SHARED(Locks::mutator_lock_)
      REQUIRES(!Locks::dex_lock_);

  // Finds a class by its descriptor, returning null if it isn't wasn't loaded
  // by the given 'class_loader'.
  ObjPtr<mirror::Class> LookupClass(Thread* self,
                                    const char* descriptor,
                                    ObjPtr<mirror::ClassLoader> class_loader)
      REQUIRES(!Locks::classlinker_classes_lock_)
      REQUIRES_SHARED(Locks::mutator_lock_);

  // Finds all the classes with the given descriptor, regardless of ClassLoader.
  void LookupClasses(const char* descriptor, std::vector<ObjPtr<mirror::Class>>& classes)
      REQUIRES(!Locks::classlinker_classes_lock_)
      REQUIRES_SHARED(Locks::mutator_lock_);

  ObjPtr<mirror::Class> LookupPrimitiveClass(char type) REQUIRES_SHARED(Locks::mutator_lock_);
  ObjPtr<mirror::Class> FindPrimitiveClass(char type) REQUIRES_SHARED(Locks::mutator_lock_);

  void DumpForSigQuit(std::ostream& os) REQUIRES(!Locks::classlinker_classes_lock_);

  size_t NumLoadedClasses()
      REQUIRES(!Locks::classlinker_classes_lock_)
      REQUIRES_SHARED(Locks::mutator_lock_);

  // Resolve a String with the given index from the DexFile associated with the given `referrer`,
  // storing the result in the DexCache. The `referrer` is used to identify the target DexCache
  // to use for resolution.
  ObjPtr<mirror::String> ResolveString(dex::StringIndex string_idx,
                                       ArtField* referrer)
      REQUIRES_SHARED(Locks::mutator_lock_);
  ObjPtr<mirror::String> ResolveString(dex::StringIndex string_idx,
                                       ArtMethod* referrer)
      REQUIRES_SHARED(Locks::mutator_lock_);

  // Resolve a String with the given index from the DexFile associated with the given DexCache,
  // storing the result in the DexCache.
  ObjPtr<mirror::String> ResolveString(dex::StringIndex string_idx,
                                       Handle<mirror::DexCache> dex_cache)
      REQUIRES_SHARED(Locks::mutator_lock_);

  // Find a String with the given index from the DexFile associated with the given DexCache,
  // storing the result in the DexCache if found. Return null if not found.
  ObjPtr<mirror::String> LookupString(dex::StringIndex string_idx,
                                      ObjPtr<mirror::DexCache> dex_cache)
      REQUIRES_SHARED(Locks::mutator_lock_);

  // Resolve a Type with the given index from the DexFile associated with the given `referrer`,
  // storing the result in the DexCache. The `referrer` is used to identify the target DexCache
  // and ClassLoader to use for resolution.
  ObjPtr<mirror::Class> ResolveType(dex::TypeIndex type_idx, ObjPtr<mirror::Class> referrer)
      REQUIRES_SHARED(Locks::mutator_lock_)
      REQUIRES(!Locks::dex_lock_, !Roles::uninterruptible_);
  ObjPtr<mirror::Class> ResolveType(dex::TypeIndex type_idx, ArtField* referrer)
      REQUIRES_SHARED(Locks::mutator_lock_)
      REQUIRES(!Locks::dex_lock_, !Roles::uninterruptible_);
  ObjPtr<mirror::Class> ResolveType(dex::TypeIndex type_idx, ArtMethod* referrer)
      REQUIRES_SHARED(Locks::mutator_lock_)
      REQUIRES(!Locks::dex_lock_, !Roles::uninterruptible_);

  // Resolve a type with the given index from the DexFile associated with the given DexCache
  // and ClassLoader, storing the result in DexCache. The ClassLoader is used to search for
  // the type, since it may be referenced from but not contained within the DexFile.
  ObjPtr<mirror::Class> ResolveType(dex::TypeIndex type_idx,
                                    Handle<mirror::DexCache> dex_cache,
                                    Handle<mirror::ClassLoader> class_loader)
      REQUIRES_SHARED(Locks::mutator_lock_)
      REQUIRES(!Locks::dex_lock_, !Roles::uninterruptible_);

  // Look up a resolved type with the given index from the DexFile associated with the given
  // `referrer`, storing the result in the DexCache. The `referrer` is used to identify the
  // target DexCache and ClassLoader to use for lookup.
  ObjPtr<mirror::Class> LookupResolvedType(dex::TypeIndex type_idx,
                                           ObjPtr<mirror::Class> referrer)
      REQUIRES_SHARED(Locks::mutator_lock_);
  ObjPtr<mirror::Class> LookupResolvedType(dex::TypeIndex type_idx, ArtField* referrer)
      REQUIRES_SHARED(Locks::mutator_lock_);
  ObjPtr<mirror::Class> LookupResolvedType(dex::TypeIndex type_idx, ArtMethod* referrer)
      REQUIRES_SHARED(Locks::mutator_lock_);

  // Look up a resolved type with the given index from the DexFile associated with the given
  // DexCache and ClassLoader. The ClassLoader is used to search for the type, since it may
  // be referenced from but not contained within the DexFile.
  ObjPtr<mirror::Class> LookupResolvedType(dex::TypeIndex type_idx,
                                           ObjPtr<mirror::DexCache> dex_cache,
                                           ObjPtr<mirror::ClassLoader> class_loader)
      REQUIRES_SHARED(Locks::mutator_lock_);

  // Determine whether a dex cache result should be trusted, or an IncompatibleClassChangeError
  // check and IllegalAccessError check should be performed even after a hit.
  enum class ResolveMode {  // private.
    kNoChecks,
    kCheckICCEAndIAE
  };

  // Look up a previously resolved method with the given index.
  ArtMethod* LookupResolvedMethod(uint32_t method_idx,
                                  ObjPtr<mirror::DexCache> dex_cache,
                                  ObjPtr<mirror::ClassLoader> class_loader)
      REQUIRES_SHARED(Locks::mutator_lock_);

  // Find a method with the given index from class `klass`, and update the dex cache.
  ArtMethod* FindResolvedMethod(ObjPtr<mirror::Class> klass,
                                ObjPtr<mirror::DexCache> dex_cache,
                                ObjPtr<mirror::ClassLoader> class_loader,
                                uint32_t method_idx)
      REQUIRES_SHARED(Locks::mutator_lock_);

  // Find a method using the wrong lookup mechanism. If `klass` is an interface,
  // search for a class method. If it is a class, search for an interface method.
  // This is useful when throwing IncompatibleClassChangeError.
  ArtMethod* FindIncompatibleMethod(ObjPtr<mirror::Class> klass,
                                    ObjPtr<mirror::DexCache> dex_cache,
                                    ObjPtr<mirror::ClassLoader> class_loader,
                                    uint32_t method_idx)
      REQUIRES_SHARED(Locks::mutator_lock_);

  // Resolve a method with a given ID from the DexFile associated with the given DexCache
  // and ClassLoader, storing the result in DexCache. The ClassLinker and ClassLoader are
  // used as in ResolveType. What is unique is the method type argument which is used to
  // determine if this method is a direct, static, or virtual method.
  template <ResolveMode kResolveMode>
  ArtMethod* ResolveMethod(uint32_t method_idx,
                           Handle<mirror::DexCache> dex_cache,
                           Handle<mirror::ClassLoader> class_loader,
                           ArtMethod* referrer,
                           InvokeType type)
      REQUIRES_SHARED(Locks::mutator_lock_)
      REQUIRES(!Locks::dex_lock_, !Roles::uninterruptible_);

  template <InvokeType type, ResolveMode kResolveMode>
  ArtMethod* GetResolvedMethod(uint32_t method_idx, ArtMethod* referrer)
      REQUIRES_SHARED(Locks::mutator_lock_);

  template <ResolveMode kResolveMode>
  ArtMethod* ResolveMethod(Thread* self, uint32_t method_idx, ArtMethod* referrer, InvokeType type)
      REQUIRES_SHARED(Locks::mutator_lock_)
      REQUIRES(!Locks::dex_lock_, !Roles::uninterruptible_);
  ArtMethod* ResolveMethodWithoutInvokeType(uint32_t method_idx,
                                            Handle<mirror::DexCache> dex_cache,
                                            Handle<mirror::ClassLoader> class_loader)
      REQUIRES_SHARED(Locks::mutator_lock_)
      REQUIRES(!Locks::dex_lock_, !Roles::uninterruptible_);

  ArtField* LookupResolvedField(uint32_t field_idx, ArtMethod* referrer, bool is_static)
      REQUIRES_SHARED(Locks::mutator_lock_);
  ArtField* ResolveField(uint32_t field_idx, ArtMethod* referrer, bool is_static)
      REQUIRES_SHARED(Locks::mutator_lock_)
      REQUIRES(!Locks::dex_lock_, !Roles::uninterruptible_);

  // Resolve a field with a given ID from the DexFile associated with the given DexCache
  // and ClassLoader, storing the result in DexCache. The ClassLinker and ClassLoader
  // are used as in ResolveType. What is unique is the is_static argument which is used
  // to determine if we are resolving a static or non-static field.
  ArtField* ResolveField(uint32_t field_idx,
                         Handle<mirror::DexCache> dex_cache,
                         Handle<mirror::ClassLoader> class_loader,
                         bool is_static)
      REQUIRES_SHARED(Locks::mutator_lock_)
      REQUIRES(!Locks::dex_lock_, !Roles::uninterruptible_);

  // Resolve a field with a given ID from the DexFile associated with the given DexCache
  // and ClassLoader, storing the result in DexCache. The ClassLinker and ClassLoader
  // are used as in ResolveType. No is_static argument is provided so that Java
  // field resolution semantics are followed.
  ArtField* ResolveFieldJLS(uint32_t field_idx,
                            Handle<mirror::DexCache> dex_cache,
                            Handle<mirror::ClassLoader> class_loader)
      REQUIRES_SHARED(Locks::mutator_lock_)
      REQUIRES(!Locks::dex_lock_, !Roles::uninterruptible_);

  // Find a field with a given ID from the DexFile associated with the given DexCache
  // and ClassLoader, storing the result in DexCache. The declaring class is assumed
  // to have been already resolved into `klass`. The `is_static` argument is used to
  // determine if we are resolving a static or non-static field.
  ArtField* FindResolvedField(ObjPtr<mirror::Class> klass,
                              ObjPtr<mirror::DexCache> dex_cache,
                              ObjPtr<mirror::ClassLoader> class_loader,
                              uint32_t field_idx,
                              bool is_static)
      REQUIRES_SHARED(Locks::mutator_lock_);

  // Find a field with a given ID from the DexFile associated with the given DexCache
  // and ClassLoader, storing the result in DexCache. The declaring class is assumed
  // to have been already resolved into `klass`. No is_static argument is provided
  // so that Java field resolution semantics are followed.
  ArtField* FindResolvedFieldJLS(ObjPtr<mirror::Class> klass,
                                 ObjPtr<mirror::DexCache> dex_cache,
                                 ObjPtr<mirror::ClassLoader> class_loader,
                                 uint32_t field_idx)
      REQUIRES_SHARED(Locks::mutator_lock_);

  // Resolve a method type with a given ID from the DexFile associated with a given DexCache
  // and ClassLoader, storing the result in the DexCache.
  ObjPtr<mirror::MethodType> ResolveMethodType(Thread* self,
                                               dex::ProtoIndex proto_idx,
                                               Handle<mirror::DexCache> dex_cache,
                                               Handle<mirror::ClassLoader> class_loader)
      REQUIRES_SHARED(Locks::mutator_lock_)
      REQUIRES(!Locks::dex_lock_, !Roles::uninterruptible_);

  ObjPtr<mirror::MethodType> ResolveMethodType(Thread* self,
                                               dex::ProtoIndex proto_idx,
                                               ArtMethod* referrer)
      REQUIRES_SHARED(Locks::mutator_lock_);

  // Resolve a method handle with a given ID from the DexFile. The
  // result is not cached in the DexCache as the instance will only be
  // used once in most circumstances.
  ObjPtr<mirror::MethodHandle> ResolveMethodHandle(Thread* self,
                                                   uint32_t method_handle_idx,
                                                   ArtMethod* referrer)
      REQUIRES_SHARED(Locks::mutator_lock_);

  // Returns true on success, false if there's an exception pending.
  // can_run_clinit=false allows the compiler to attempt to init a class,
  // given the restriction that no <clinit> execution is possible.
  bool EnsureInitialized(Thread* self,
                         Handle<mirror::Class> c,
                         bool can_init_fields,
                         bool can_init_parents)
      REQUIRES_SHARED(Locks::mutator_lock_)
      REQUIRES(!Locks::dex_lock_, !Roles::uninterruptible_);

  // Initializes classes that have instances in the image but that have
  // <clinit> methods so they could not be initialized by the compiler.
  void RunRootClinits(Thread* self)
      REQUIRES_SHARED(Locks::mutator_lock_)
      REQUIRES(!Locks::dex_lock_, !Roles::uninterruptible_);

  // Directly register an already existing dex cache. RegisterDexFile should be preferred since that
  // reduplicates DexCaches when possible. The DexCache given to this function must already be fully
  // initialized and not already registered.
  void RegisterExistingDexCache(ObjPtr<mirror::DexCache> cache,
                                ObjPtr<mirror::ClassLoader> class_loader)
      REQUIRES(!Locks::dex_lock_)
      REQUIRES_SHARED(Locks::mutator_lock_);
  ObjPtr<mirror::DexCache> RegisterDexFile(const DexFile& dex_file,
                                           ObjPtr<mirror::ClassLoader> class_loader)
      REQUIRES(!Locks::dex_lock_)
      REQUIRES_SHARED(Locks::mutator_lock_);

  const std::vector<const DexFile*>& GetBootClassPath() {
    return boot_class_path_;
  }

  void VisitClasses(ClassVisitor* visitor)
      REQUIRES(!Locks::classlinker_classes_lock_)
      REQUIRES_SHARED(Locks::mutator_lock_);

  // Less efficient variant of VisitClasses that copies the class_table_ into secondary storage
  // so that it can visit individual classes without holding the doesn't hold the
  // Locks::classlinker_classes_lock_. As the Locks::classlinker_classes_lock_ isn't held this code
  // can race with insertion and deletion of classes while the visitor is being called.
  void VisitClassesWithoutClassesLock(ClassVisitor* visitor)
      REQUIRES_SHARED(Locks::mutator_lock_)
      REQUIRES(!Locks::dex_lock_);

  void VisitClassRoots(RootVisitor* visitor, VisitRootFlags flags)
      REQUIRES(!Locks::classlinker_classes_lock_, !Locks::trace_lock_)
      REQUIRES_SHARED(Locks::mutator_lock_);
  void VisitRoots(RootVisitor* visitor, VisitRootFlags flags)
      REQUIRES(!Locks::dex_lock_, !Locks::classlinker_classes_lock_, !Locks::trace_lock_)
      REQUIRES_SHARED(Locks::mutator_lock_);

  bool IsDexFileRegistered(Thread* self, const DexFile& dex_file)
      REQUIRES(!Locks::dex_lock_)
      REQUIRES_SHARED(Locks::mutator_lock_);
  ObjPtr<mirror::DexCache> FindDexCache(Thread* self, const DexFile& dex_file)
      REQUIRES(!Locks::dex_lock_)
      REQUIRES_SHARED(Locks::mutator_lock_);
  ClassTable* FindClassTable(Thread* self, ObjPtr<mirror::DexCache> dex_cache)
      REQUIRES(!Locks::dex_lock_)
      REQUIRES_SHARED(Locks::mutator_lock_);

  LengthPrefixedArray<ArtField>* AllocArtFieldArray(Thread* self,
                                                    LinearAlloc* allocator,
                                                    size_t length);

  LengthPrefixedArray<ArtMethod>* AllocArtMethodArray(Thread* self,
                                                      LinearAlloc* allocator,
                                                      size_t length);

  // Convenience AllocClass() overload that uses mirror::Class::InitializeClassVisitor
  // for the class initialization and uses the `java_lang_Class` from class roots
  // instead of an explicit argument.
  ObjPtr<mirror::Class> AllocClass(Thread* self, uint32_t class_size)
      REQUIRES_SHARED(Locks::mutator_lock_)
      REQUIRES(!Roles::uninterruptible_);

  // Setup the classloader, class def index, type idx so that we can insert this class in the class
  // table.
  void SetupClass(const DexFile& dex_file,
                  const dex::ClassDef& dex_class_def,
                  Handle<mirror::Class> klass,
                  ObjPtr<mirror::ClassLoader> class_loader)
      REQUIRES_SHARED(Locks::mutator_lock_);

  void LoadClass(Thread* self,
                 const DexFile& dex_file,
                 const dex::ClassDef& dex_class_def,
                 Handle<mirror::Class> klass)
      REQUIRES_SHARED(Locks::mutator_lock_);

  // Link the class and place it into the class-table using the given descriptor. NB if the
  // descriptor is null the class will not be placed in any class-table. This is useful implementing
  // obsolete classes and should not be used otherwise.
  bool LinkClass(Thread* self,
                 const char* descriptor,
                 Handle<mirror::Class> klass,
                 Handle<mirror::ObjectArray<mirror::Class>> interfaces,
                 MutableHandle<mirror::Class>* h_new_class_out)
      REQUIRES_SHARED(Locks::mutator_lock_)
      REQUIRES(!Locks::classlinker_classes_lock_);

  ObjPtr<mirror::PointerArray> AllocPointerArray(Thread* self, size_t length)
      REQUIRES_SHARED(Locks::mutator_lock_)
      REQUIRES(!Roles::uninterruptible_);

  ObjPtr<mirror::IfTable> AllocIfTable(Thread* self, size_t ifcount)
      REQUIRES_SHARED(Locks::mutator_lock_)
      REQUIRES(!Roles::uninterruptible_);

  ObjPtr<mirror::ObjectArray<mirror::StackTraceElement>> AllocStackTraceElementArray(Thread* self,
                                                                                     size_t length)
      REQUIRES_SHARED(Locks::mutator_lock_)
      REQUIRES(!Roles::uninterruptible_);

  verifier::FailureKind VerifyClass(
      Thread* self,
      Handle<mirror::Class> klass,
      verifier::HardFailLogMode log_level = verifier::HardFailLogMode::kLogNone)
      REQUIRES_SHARED(Locks::mutator_lock_)
      REQUIRES(!Locks::dex_lock_);
  bool VerifyClassUsingOatFile(const DexFile& dex_file,
                               ObjPtr<mirror::Class> klass,
                               ClassStatus& oat_file_class_status)
      REQUIRES_SHARED(Locks::mutator_lock_)
      REQUIRES(!Locks::dex_lock_);
  void ResolveClassExceptionHandlerTypes(Handle<mirror::Class> klass)
      REQUIRES_SHARED(Locks::mutator_lock_)
      REQUIRES(!Locks::dex_lock_);
  void ResolveMethodExceptionHandlerTypes(ArtMethod* klass)
      REQUIRES_SHARED(Locks::mutator_lock_)
      REQUIRES(!Locks::dex_lock_);

  ObjPtr<mirror::Class> CreateProxyClass(ScopedObjectAccessAlreadyRunnable& soa,
                                         jstring name,
                                         jobjectArray interfaces,
                                         jobject loader,
                                         jobjectArray methods,
                                         jobjectArray throws)
      REQUIRES_SHARED(Locks::mutator_lock_);

  // Get the oat code for a method when its class isn't yet initialized.
  const void* GetQuickOatCodeFor(ArtMethod* method)
      REQUIRES_SHARED(Locks::mutator_lock_);

  pid_t GetClassesLockOwner();  // For SignalCatcher.
  pid_t GetDexLockOwner();  // For SignalCatcher.

  // Is the given entry point quick code to run the resolution stub?
  bool IsQuickResolutionStub(const void* entry_point) const;

  // Is the given entry point quick code to bridge into the interpreter?
  bool IsQuickToInterpreterBridge(const void* entry_point) const;

  // Is the given entry point quick code to run the generic JNI stub?
  bool IsQuickGenericJniStub(const void* entry_point) const;

  // Is the given entry point the JNI dlsym lookup stub?
  bool IsJniDlsymLookupStub(const void* entry_point) const;

  const void* GetQuickToInterpreterBridgeTrampoline() const {
    return quick_to_interpreter_bridge_trampoline_;
  }

  InternTable* GetInternTable() const {
    return intern_table_;
  }

  // Set the entrypoints up for method to the enter the interpreter.
  void SetEntryPointsToInterpreter(ArtMethod* method) const
      REQUIRES_SHARED(Locks::mutator_lock_);

  // Set the entrypoints up for an obsolete method.
  void SetEntryPointsForObsoleteMethod(ArtMethod* method) const
      REQUIRES_SHARED(Locks::mutator_lock_);

  // Attempts to insert a class into a class table.  Returns null if
  // the class was inserted, otherwise returns an existing class with
  // the same descriptor and ClassLoader.
  ObjPtr<mirror::Class> InsertClass(const char* descriptor,
                                    ObjPtr<mirror::Class> klass,
                                    size_t hash)
      REQUIRES(!Locks::classlinker_classes_lock_)
      REQUIRES_SHARED(Locks::mutator_lock_);

  // Add an oat file with .bss GC roots to be visited again at the end of GC
  // for collector types that need it.
  void WriteBarrierForBootOatFileBssRoots(const OatFile* oat_file)
      REQUIRES(!Locks::classlinker_classes_lock_)
      REQUIRES_SHARED(Locks::mutator_lock_);

  template <ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
  ObjPtr<mirror::ObjectArray<mirror::Class>> GetClassRoots() REQUIRES_SHARED(Locks::mutator_lock_);

  // Move the class table to the pre-zygote table to reduce memory usage. This works by ensuring
  // that no more classes are ever added to the pre zygote table which makes it that the pages
  // always remain shared dirty instead of private dirty.
  void MoveClassTableToPreZygote()
      REQUIRES(!Locks::classlinker_classes_lock_)
      REQUIRES_SHARED(Locks::mutator_lock_);

  // Creates a GlobalRef PathClassLoader or DelegateLastClassLoader (specified by loader_class)
  // that can be used to load classes from the given dex files. The parent of the class loader
  // will be set to `parent_loader`. If `parent_loader` is null the parent will be
  // the boot class loader.
  // If class_loader points to a different class than PathClassLoader or DelegateLastClassLoader
  // this method will abort.
  // Note: the objects are not completely set up. Do not use this outside of tests and the compiler.
  jobject CreateWellKnownClassLoader(Thread* self,
                                     const std::vector<const DexFile*>& dex_files,
                                     jclass loader_class,
                                     jobject parent_loader,
                                     jobject shared_libraries = nullptr)
      REQUIRES_SHARED(Locks::mutator_lock_)
      REQUIRES(!Locks::dex_lock_);

  // Calls CreateWellKnownClassLoader(self,
  //                                  dex_files,
  //                                  WellKnownClasses::dalvik_system_PathClassLoader,
  //                                  nullptr)
  jobject CreatePathClassLoader(Thread* self, const std::vector<const DexFile*>& dex_files)
      REQUIRES_SHARED(Locks::mutator_lock_)
      REQUIRES(!Locks::dex_lock_);

  // Non-GlobalRef version of CreateWellKnownClassLoader
  ObjPtr<mirror::ClassLoader> CreateWellKnownClassLoader(
      Thread* self,
      const std::vector<const DexFile*>& dex_files,
      Handle<mirror::Class> loader_class,
      Handle<mirror::ClassLoader> parent_loader,
      Handle<mirror::ObjectArray<mirror::ClassLoader>> shared_libraries)
          REQUIRES_SHARED(Locks::mutator_lock_)
          REQUIRES(!Locks::dex_lock_);

  PointerSize GetImagePointerSize() const {
    return image_pointer_size_;
  }

  // Used by image writer for checking.
  bool ClassInClassTable(ObjPtr<mirror::Class> klass)
      REQUIRES(Locks::classlinker_classes_lock_)
      REQUIRES_SHARED(Locks::mutator_lock_);

  // Clear the ArrayClass cache. This is necessary when cleaning up for the image, as the cache
  // entries are roots, but potentially not image classes.
  void DropFindArrayClassCache() REQUIRES_SHARED(Locks::mutator_lock_);

  // Clean up class loaders, this needs to happen after JNI weak globals are cleared.
  void CleanupClassLoaders()
      REQUIRES(!Locks::classlinker_classes_lock_)
      REQUIRES_SHARED(Locks::mutator_lock_);

  // Unlike GetOrCreateAllocatorForClassLoader, GetAllocatorForClassLoader asserts that the
  // allocator for this class loader is already created.
  LinearAlloc* GetAllocatorForClassLoader(ObjPtr<mirror::ClassLoader> class_loader)
      REQUIRES_SHARED(Locks::mutator_lock_);

  // Return the linear alloc for a class loader if it is already allocated, otherwise allocate and
  // set it. TODO: Consider using a lock other than classlinker_classes_lock_.
  LinearAlloc* GetOrCreateAllocatorForClassLoader(ObjPtr<mirror::ClassLoader> class_loader)
      REQUIRES(!Locks::classlinker_classes_lock_)
      REQUIRES_SHARED(Locks::mutator_lock_);

  // May be called with null class_loader due to legacy code. b/27954959
  void InsertDexFileInToClassLoader(ObjPtr<mirror::Object> dex_file,
                                    ObjPtr<mirror::ClassLoader> class_loader)
      REQUIRES(!Locks::classlinker_classes_lock_)
      REQUIRES_SHARED(Locks::mutator_lock_);

  static bool ShouldUseInterpreterEntrypoint(ArtMethod* method, const void* quick_code)
      REQUIRES_SHARED(Locks::mutator_lock_);

  std::set<DexCacheResolvedClasses> GetResolvedClasses(bool ignore_boot_classes)
      REQUIRES(!Locks::dex_lock_);

  static bool IsBootClassLoader(ScopedObjectAccessAlreadyRunnable& soa,
                                ObjPtr<mirror::ClassLoader> class_loader)
      REQUIRES_SHARED(Locks::mutator_lock_);

  ArtMethod* AddMethodToConflictTable(ObjPtr<mirror::Class> klass,
                                      ArtMethod* conflict_method,
                                      ArtMethod* interface_method,
                                      ArtMethod* method,
                                      bool force_new_conflict_method)
      REQUIRES_SHARED(Locks::mutator_lock_);

  // Create a conflict table with a specified capacity.
  ImtConflictTable* CreateImtConflictTable(size_t count, LinearAlloc* linear_alloc);

  // Static version for when the class linker is not yet created.
  static ImtConflictTable* CreateImtConflictTable(size_t count,
                                                  LinearAlloc* linear_alloc,
                                                  PointerSize pointer_size);


  // Create the IMT and conflict tables for a class.
  void FillIMTAndConflictTables(ObjPtr<mirror::Class> klass) REQUIRES_SHARED(Locks::mutator_lock_);

  // Visit all of the class tables. This is used by dex2oat to allow pruning dex caches.
  template <class Visitor>
  void VisitClassTables(const Visitor& visitor)
      REQUIRES(!Locks::classlinker_classes_lock_)
      REQUIRES_SHARED(Locks::mutator_lock_);

  // Visit all of the allocators that belong to classloaders except boot classloader.
  // This is used by 616-cha-unloading test to confirm memory reuse.
  void VisitAllocators(AllocatorVisitor* visitor) const
      REQUIRES_SHARED(Locks::classlinker_classes_lock_, Locks::mutator_lock_);

  // Throw the class initialization failure recorded when first trying to initialize the given
  // class.
  void ThrowEarlierClassFailure(ObjPtr<mirror::Class> c,
                                bool wrap_in_no_class_def = false,
                                bool log = false)
      REQUIRES_SHARED(Locks::mutator_lock_)
      REQUIRES(!Locks::dex_lock_);

  // Get the actual holding class for a copied method. Pretty slow, don't call often.
  ObjPtr<mirror::Class> GetHoldingClassOfCopiedMethod(ArtMethod* method)
      REQUIRES_SHARED(Locks::mutator_lock_);

  // Returns null if not found.
  // This returns a pointer to the class-table, without requiring any locking - including the
  // boot class-table. It is the caller's responsibility to access this under lock, if required.
  ClassTable* ClassTableForClassLoader(ObjPtr<mirror::ClassLoader> class_loader)
      REQUIRES_SHARED(Locks::mutator_lock_)
      NO_THREAD_SAFETY_ANALYSIS;

  void AppendToBootClassPath(Thread* self, const DexFile& dex_file)
      REQUIRES_SHARED(Locks::mutator_lock_)
      REQUIRES(!Locks::dex_lock_);

  // Visit all of the class loaders in the class linker.
  void VisitClassLoaders(ClassLoaderVisitor* visitor) const
      REQUIRES_SHARED(Locks::classlinker_classes_lock_, Locks::mutator_lock_);

  // Checks that a class and its superclass from another class loader have the same virtual methods.
  bool ValidateSuperClassDescriptors(Handle<mirror::Class> klass)
      REQUIRES_SHARED(Locks::mutator_lock_);

  ClassHierarchyAnalysis* GetClassHierarchyAnalysis() {
    return cha_.get();
  }

  void MakeInitializedClassesVisiblyInitialized(Thread* self, bool wait);

  struct DexCacheData {
    // Construct an invalid data object.
    DexCacheData()
        : weak_root(nullptr),
          dex_file(nullptr),
          class_table(nullptr) { }

    // Check if the data is valid.
    bool IsValid() const {
      return dex_file != nullptr;
    }

    // Weak root to the DexCache. Note: Do not decode this unnecessarily or else class unloading may
    // not work properly.
    jweak weak_root;
    // The following field caches the DexCache's field here to avoid unnecessary jweak decode that
    // triggers read barriers (and marks them alive unnecessarily and messes with class unloading.)
    const DexFile* dex_file;
    // Identify the associated class loader's class table. This is used to make sure that
    // the Java call to native DexCache.setResolvedType() inserts the resolved type in that
    // class table. It is also used to make sure we don't register the same dex cache with
    // multiple class loaders.
    ClassTable* class_table;
  };

  // Forces a class to be marked as initialized without actually running initializers. Should only
  // be used by plugin code when creating new classes directly.
  void ForceClassInitialized(Thread* self, Handle<mirror::Class> klass)
      REQUIRES_SHARED(Locks::mutator_lock_)
      REQUIRES(!Locks::dex_lock_, !Roles::uninterruptible_);

 protected:
  virtual bool InitializeClass(Thread* self,
                               Handle<mirror::Class> klass,
                               bool can_run_clinit,
                               bool can_init_parents)
      REQUIRES_SHARED(Locks::mutator_lock_)
      REQUIRES(!Locks::dex_lock_);

  virtual verifier::FailureKind PerformClassVerification(Thread* self,
                                                         Handle<mirror::Class> klass,
                                                         verifier::HardFailLogMode log_level,
                                                         std::string* error_msg)
      REQUIRES_SHARED(Locks::mutator_lock_);

  virtual bool CanAllocClass() REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Locks::dex_lock_) {
    return true;
  }

 private:
  class LinkInterfaceMethodsHelper;
  class VisiblyInitializedCallback;

  struct ClassLoaderData {
    jweak weak_root;  // Weak root to enable class unloading.
    ClassTable* class_table;
    LinearAlloc* allocator;
  };

  void VisiblyInitializedCallbackDone(Thread* self, VisiblyInitializedCallback* callback);
  VisiblyInitializedCallback* MarkClassInitialized(Thread* self, Handle<mirror::Class> klass)
      REQUIRES_SHARED(Locks::mutator_lock_);

  // Ensures that the supertype of 'klass' ('supertype') is verified. Returns false and throws
  // appropriate exceptions if verification failed hard. Returns true for successful verification or
  // soft-failures.
  bool AttemptSupertypeVerification(Thread* self,
                                    Handle<mirror::Class> klass,
                                    Handle<mirror::Class> supertype)
      REQUIRES(!Locks::dex_lock_)
      REQUIRES_SHARED(Locks::mutator_lock_);

  void DeleteClassLoader(Thread* self, const ClassLoaderData& data, bool cleanup_cha)
      REQUIRES_SHARED(Locks::mutator_lock_);

  void VisitClassesInternal(ClassVisitor* visitor)
      REQUIRES_SHARED(Locks::classlinker_classes_lock_, Locks::mutator_lock_);

  // Returns the number of zygote and image classes.
  size_t NumZygoteClasses() const
      REQUIRES(Locks::classlinker_classes_lock_)
      REQUIRES_SHARED(Locks::mutator_lock_);

  // Returns the number of non zygote nor image classes.
  size_t NumNonZygoteClasses() const
      REQUIRES(Locks::classlinker_classes_lock_)
      REQUIRES_SHARED(Locks::mutator_lock_);

  void FinishInit(Thread* self)
      REQUIRES_SHARED(Locks::mutator_lock_)
      REQUIRES(!Locks::dex_lock_, !Roles::uninterruptible_);

  // If we do not allow moving classes (`art::kMovingClass` is false) or if
  // parameter `kMovable` is false (or both), the class object is allocated in
  // the non-moving space.
  template <bool kMovable = true, class PreFenceVisitor>
  ObjPtr<mirror::Class> AllocClass(Thread* self,
                                   ObjPtr<mirror::Class> java_lang_Class,
                                   uint32_t class_size,
                                   const PreFenceVisitor& pre_fence_visitor)
      REQUIRES_SHARED(Locks::mutator_lock_)
      REQUIRES(!Roles::uninterruptible_);

  // Convenience AllocClass() overload that uses mirror::Class::InitializeClassVisitor
  // for the class initialization.
  template <bool kMovable = true>
  ObjPtr<mirror::Class> AllocClass(Thread* self,
                                   ObjPtr<mirror::Class> java_lang_Class,
                                   uint32_t class_size)
      REQUIRES_SHARED(Locks::mutator_lock_)
      REQUIRES(!Roles::uninterruptible_);

  // Allocate a primitive array class and store it in appropriate class root.
  void AllocPrimitiveArrayClass(Thread* self,
                                ClassRoot primitive_root,
                                ClassRoot array_root)
      REQUIRES_SHARED(Locks::mutator_lock_)
      REQUIRES(!Roles::uninterruptible_);

  // Finish setup of an array class.
  void FinishArrayClassSetup(ObjPtr<mirror::Class> array_class)
      REQUIRES_SHARED(Locks::mutator_lock_)
      REQUIRES(!Roles::uninterruptible_);

  // Finish setup of a core array class (Object[], Class[], String[] and
  // primitive arrays) and insert it into the class table.
  void FinishCoreArrayClassSetup(ClassRoot array_root)
      REQUIRES_SHARED(Locks::mutator_lock_)
      REQUIRES(!Roles::uninterruptible_);

  ObjPtr<mirror::DexCache> AllocDexCache(/*out*/ ObjPtr<mirror::String>* out_location,
                                         Thread* self,
                                         const DexFile& dex_file)
      REQUIRES_SHARED(Locks::mutator_lock_)
      REQUIRES(!Roles::uninterruptible_);

  // Used for tests and AppendToBootClassPath.
  ObjPtr<mirror::DexCache> AllocAndInitializeDexCache(Thread* self,
                                                      const DexFile& dex_file,
                                                      LinearAlloc* linear_alloc)
      REQUIRES_SHARED(Locks::mutator_lock_)
      REQUIRES(!Locks::dex_lock_)
      REQUIRES(!Roles::uninterruptible_);

  // Create a primitive class and store it in the appropriate class root.
  void CreatePrimitiveClass(Thread* self, Primitive::Type type, ClassRoot primitive_root)
      REQUIRES_SHARED(Locks::mutator_lock_)
      REQUIRES(!Roles::uninterruptible_);

  ObjPtr<mirror::Class> CreateArrayClass(Thread* self,
                                         const char* descriptor,
                                         size_t hash,
                                         Handle<mirror::ClassLoader> class_loader)
      REQUIRES_SHARED(Locks::mutator_lock_)
      REQUIRES(!Locks::dex_lock_, !Roles::uninterruptible_);

  void AppendToBootClassPath(const DexFile& dex_file, ObjPtr<mirror::DexCache> dex_cache)
      REQUIRES_SHARED(Locks::mutator_lock_)
      REQUIRES(!Locks::dex_lock_);

  // Precomputes size needed for Class, in the case of a non-temporary class this size must be
  // sufficient to hold all static fields.
  uint32_t SizeOfClassWithoutEmbeddedTables(const DexFile& dex_file,
                                            const dex::ClassDef& dex_class_def);

  void LoadField(const ClassAccessor::Field& field, Handle<mirror::Class> klass, ArtField* dst)
      REQUIRES_SHARED(Locks::mutator_lock_);

  void LoadMethod(const DexFile& dex_file,
                  const ClassAccessor::Method& method,
                  Handle<mirror::Class> klass,
                  ArtMethod* dst)
      REQUIRES_SHARED(Locks::mutator_lock_);

  void FixupStaticTrampolines(ObjPtr<mirror::Class> klass) REQUIRES_SHARED(Locks::mutator_lock_);

  // Finds a class in a Path- or DexClassLoader, loading it if necessary without using JNI. Hash
  // function is supposed to be ComputeModifiedUtf8Hash(descriptor). Returns true if the
  // class-loader chain could be handled, false otherwise, i.e., a non-supported class-loader
  // was encountered while walking the parent chain (currently only BootClassLoader and
  // PathClassLoader are supported).
  bool FindClassInBaseDexClassLoader(ScopedObjectAccessAlreadyRunnable& soa,
                                     Thread* self,
                                     const char* descriptor,
                                     size_t hash,
                                     Handle<mirror::ClassLoader> class_loader,
                                     /*out*/ ObjPtr<mirror::Class>* result)
      REQUIRES_SHARED(Locks::mutator_lock_)
      REQUIRES(!Locks::dex_lock_);

  bool FindClassInSharedLibraries(ScopedObjectAccessAlreadyRunnable& soa,
                                  Thread* self,
                                  const char* descriptor,
                                  size_t hash,
                                  Handle<mirror::ClassLoader> class_loader,
                                  /*out*/ ObjPtr<mirror::Class>* result)
      REQUIRES_SHARED(Locks::mutator_lock_)
      REQUIRES(!Locks::dex_lock_);

  // Finds the class in the classpath of the given class loader. It only searches the class loader
  // dex files and does not recurse into its parent.
  // The method checks that the provided class loader is either a PathClassLoader or a
  // DexClassLoader.
  // If the class is found the method returns the resolved class. Otherwise it returns null.
  ObjPtr<mirror::Class> FindClassInBaseDexClassLoaderClassPath(
          ScopedObjectAccessAlreadyRunnable& soa,
          const char* descriptor,
          size_t hash,
          Handle<mirror::ClassLoader> class_loader)
      REQUIRES_SHARED(Locks::mutator_lock_)
      REQUIRES(!Locks::dex_lock_);

  // Finds the class in the boot class loader.
  // If the class is found the method returns the resolved class. Otherwise it returns null.
  ObjPtr<mirror::Class> FindClassInBootClassLoaderClassPath(Thread* self,
                                                            const char* descriptor,
                                                            size_t hash)
      REQUIRES_SHARED(Locks::mutator_lock_)
      REQUIRES(!Locks::dex_lock_);

  // Implementation of LookupResolvedType() called when the type was not found in the dex cache.
  ObjPtr<mirror::Class> DoLookupResolvedType(dex::TypeIndex type_idx,
                                             ObjPtr<mirror::Class> referrer)
      REQUIRES_SHARED(Locks::mutator_lock_);
  ObjPtr<mirror::Class> DoLookupResolvedType(dex::TypeIndex type_idx,
                                             ObjPtr<mirror::DexCache> dex_cache,
                                             ObjPtr<mirror::ClassLoader> class_loader)
      REQUIRES_SHARED(Locks::mutator_lock_);

  // Implementation of ResolveString() called when the string was not found in the dex cache.
  ObjPtr<mirror::String> DoResolveString(dex::StringIndex string_idx,
                                         ObjPtr<mirror::DexCache> dex_cache)
      REQUIRES_SHARED(Locks::mutator_lock_);
  ObjPtr<mirror::String> DoResolveString(dex::StringIndex string_idx,
                                         Handle<mirror::DexCache> dex_cache)
      REQUIRES_SHARED(Locks::mutator_lock_);

  // Implementation of LookupString() called when the string was not found in the dex cache.
  ObjPtr<mirror::String> DoLookupString(dex::StringIndex string_idx,
                                        ObjPtr<mirror::DexCache> dex_cache)
      REQUIRES_SHARED(Locks::mutator_lock_);

  // Implementation of ResolveType() called when the type was not found in the dex cache. May be
  // used with ArtField*, ArtMethod* or ObjPtr<Class>.
  template <typename RefType>
  ObjPtr<mirror::Class> DoResolveType(dex::TypeIndex type_idx, RefType referrer)
      REQUIRES_SHARED(Locks::mutator_lock_)
      REQUIRES(!Locks::dex_lock_, !Roles::uninterruptible_);
  ObjPtr<mirror::Class> DoResolveType(dex::TypeIndex type_idx,
                                      Handle<mirror::DexCache> dex_cache,
                                      Handle<mirror::ClassLoader> class_loader)
      REQUIRES_SHARED(Locks::mutator_lock_)
      REQUIRES(!Locks::dex_lock_, !Roles::uninterruptible_);

  // Finds a class by its descriptor, returning NULL if it isn't wasn't loaded
  // by the given 'class_loader'. Uses the provided hash for the descriptor.
  ObjPtr<mirror::Class> LookupClass(Thread* self,
                                    const char* descriptor,
                                    size_t hash,
                                    ObjPtr<mirror::ClassLoader> class_loader)
      REQUIRES(!Locks::classlinker_classes_lock_)
      REQUIRES_SHARED(Locks::mutator_lock_);

  // Find a field by its field index.
  ArtField* LookupResolvedField(uint32_t field_idx,
                                ObjPtr<mirror::DexCache> dex_cache,
                                ObjPtr<mirror::ClassLoader> class_loader,
                                bool is_static)
      REQUIRES_SHARED(Locks::mutator_lock_);

  void RegisterDexFileLocked(const DexFile& dex_file,
                             ObjPtr<mirror::DexCache> dex_cache,
                             ObjPtr<mirror::ClassLoader> class_loader)
      REQUIRES(Locks::dex_lock_)
      REQUIRES_SHARED(Locks::mutator_lock_);
  DexCacheData FindDexCacheDataLocked(const DexFile& dex_file)
      REQUIRES(Locks::dex_lock_)
      REQUIRES_SHARED(Locks::mutator_lock_);
  static ObjPtr<mirror::DexCache> DecodeDexCache(Thread* self, const DexCacheData& data)
      REQUIRES_SHARED(Locks::mutator_lock_);
  // Called to ensure that the dex cache has been registered with the same class loader.
  // If yes, returns the dex cache, otherwise throws InternalError and returns null.
  ObjPtr<mirror::DexCache> EnsureSameClassLoader(Thread* self,
                                                 ObjPtr<mirror::DexCache> dex_cache,
                                                 const DexCacheData& data,
                                                 ObjPtr<mirror::ClassLoader> class_loader)
      REQUIRES(!Locks::dex_lock_)
      REQUIRES_SHARED(Locks::mutator_lock_);

  bool InitializeDefaultInterfaceRecursive(Thread* self,
                                           Handle<mirror::Class> klass,
                                           bool can_run_clinit,
                                           bool can_init_parents)
      REQUIRES(!Locks::dex_lock_)
      REQUIRES_SHARED(Locks::mutator_lock_);
  bool WaitForInitializeClass(Handle<mirror::Class> klass,
                              Thread* self,
                              ObjectLock<mirror::Class>& lock);

  bool IsSameDescriptorInDifferentClassContexts(Thread* self,
                                                const char* descriptor,
                                                Handle<mirror::ClassLoader> class_loader1,
                                                Handle<mirror::ClassLoader> class_loader2)
      REQUIRES_SHARED(Locks::mutator_lock_);

  bool IsSameMethodSignatureInDifferentClassContexts(Thread* self,
                                                     ArtMethod* method,
                                                     ObjPtr<mirror::Class> klass1,
                                                     ObjPtr<mirror::Class> klass2)
      REQUIRES_SHARED(Locks::mutator_lock_);

  bool LinkSuperClass(Handle<mirror::Class> klass)
      REQUIRES_SHARED(Locks::mutator_lock_);

  bool LoadSuperAndInterfaces(Handle<mirror::Class> klass, const DexFile& dex_file)
      REQUIRES_SHARED(Locks::mutator_lock_)
      REQUIRES(!Locks::dex_lock_);

  bool LinkMethods(Thread* self,
                   Handle<mirror::Class> klass,
                   Handle<mirror::ObjectArray<mirror::Class>> interfaces,
                   bool* out_new_conflict,
                   ArtMethod** out_imt)
      REQUIRES_SHARED(Locks::mutator_lock_);

  ObjPtr<mirror::MethodHandle> ResolveMethodHandleForField(
      Thread* self,
      const dex::MethodHandleItem& method_handle,
      ArtMethod* referrer) REQUIRES_SHARED(Locks::mutator_lock_);

  ObjPtr<mirror::MethodHandle> ResolveMethodHandleForMethod(
      Thread* self,
      const dex::MethodHandleItem& method_handle,
      ArtMethod* referrer) REQUIRES_SHARED(Locks::mutator_lock_);

  // A wrapper class representing the result of a method translation used for linking methods and
  // updating superclass default methods. For each method in a classes vtable there are 4 states it
  // could be in:
  // 1) No translation is necessary. In this case there is no MethodTranslation object for it. This
  //    is the standard case and is true when the method is not overridable by a default method,
  //    the class defines a concrete implementation of the method, the default method implementation
  //    remains the same, or an abstract method stayed abstract.
  // 2) The method must be translated to a different default method. We note this with
  //    CreateTranslatedMethod.
  // 3) The method must be replaced with a conflict method. This happens when a superclass
  //    implements an interface with a default method and this class implements an unrelated
  //    interface that also defines that default method. We note this with CreateConflictingMethod.
  // 4) The method must be replaced with an abstract miranda method. This happens when a superclass
  //    implements an interface with a default method and this class implements a subinterface of
  //    the superclass's interface which declares the default method abstract. We note this with
  //    CreateAbstractMethod.
  //
  // When a method translation is unnecessary (case #1), we don't put it into the
  // default_translation maps. So an instance of MethodTranslation must be in one of #2-#4.
  class MethodTranslation {
   public:
    // This slot must become a default conflict method.
    static MethodTranslation CreateConflictingMethod() {
      return MethodTranslation(Type::kConflict, /*translation=*/nullptr);
    }

    // This slot must become an abstract method.
    static MethodTranslation CreateAbstractMethod() {
      return MethodTranslation(Type::kAbstract, /*translation=*/nullptr);
    }

    // Use the given method as the current value for this vtable slot during translation.
    static MethodTranslation CreateTranslatedMethod(ArtMethod* new_method) {
      return MethodTranslation(Type::kTranslation, new_method);
    }

    // Returns true if this is a method that must become a conflict method.
    bool IsInConflict() const {
      return type_ == Type::kConflict;
    }

    // Returns true if this is a method that must become an abstract method.
    bool IsAbstract() const {
      return type_ == Type::kAbstract;
    }

    // Returns true if this is a method that must become a different method.
    bool IsTranslation() const {
      return type_ == Type::kTranslation;
    }

    // Get the translated version of this method.
    ArtMethod* GetTranslation() const {
      DCHECK(IsTranslation());
      DCHECK(translation_ != nullptr);
      return translation_;
    }

   private:
    enum class Type {
      kTranslation,
      kConflict,
      kAbstract,
    };

    MethodTranslation(Type type, ArtMethod* translation)
        : translation_(translation), type_(type) {}

    ArtMethod* const translation_;
    const Type type_;
  };

  // Links the virtual methods for the given class and records any default methods that will need to
  // be updated later.
  //
  // Arguments:
  // * self - The current thread.
  // * klass - class, whose vtable will be filled in.
  // * default_translations - Vtable index to new method map.
  //                          Any vtable entries that need to be updated with new default methods
  //                          are stored into the default_translations map. The default_translations
  //                          map is keyed on the vtable index that needs to be updated. We use this
  //                          map because if we override a default method with another default
  //                          method we need to update the vtable to point to the new method.
  //                          Unfortunately since we copy the ArtMethod* we cannot just do a simple
  //                          scan, we therefore store the vtable index's that might need to be
  //                          updated with the method they will turn into.
  // TODO This whole default_translations thing is very dirty. There should be a better way.
  bool LinkVirtualMethods(
        Thread* self,
        Handle<mirror::Class> klass,
        /*out*/std::unordered_map<size_t, MethodTranslation>* default_translations)
      REQUIRES_SHARED(Locks::mutator_lock_);

  // Sets up the interface lookup table (IFTable) in the correct order to allow searching for
  // default methods.
  bool SetupInterfaceLookupTable(Thread* self,
                                 Handle<mirror::Class> klass,
                                 Handle<mirror::ObjectArray<mirror::Class>> interfaces)
      REQUIRES_SHARED(Locks::mutator_lock_);


  enum class DefaultMethodSearchResult {
    kDefaultFound,
    kAbstractFound,
    kDefaultConflict
  };

  // Find the default method implementation for 'interface_method' in 'klass', if one exists.
  //
  // Arguments:
  // * self - The current thread.
  // * target_method - The method we are trying to find a default implementation for.
  // * klass - The class we are searching for a definition of target_method.
  // * out_default_method - The pointer we will store the found default method to on success.
  //
  // Return value:
  // * kDefaultFound - There were no conflicting method implementations found in the class while
  //                   searching for target_method. The default method implementation is stored into
  //                   out_default_method.
  // * kAbstractFound - There were no conflicting method implementations found in the class while
  //                   searching for target_method but no default implementation was found either.
  //                   out_default_method is set to null and the method should be considered not
  //                   implemented.
  // * kDefaultConflict - Conflicting method implementations were found when searching for
  //                      target_method. The value of *out_default_method is null.
  DefaultMethodSearchResult FindDefaultMethodImplementation(
      Thread* self,
      ArtMethod* target_method,
      Handle<mirror::Class> klass,
      /*out*/ArtMethod** out_default_method) const
      REQUIRES_SHARED(Locks::mutator_lock_);

  // Sets the imt entries and fixes up the vtable for the given class by linking all the interface
  // methods. See LinkVirtualMethods for an explanation of what default_translations is.
  bool LinkInterfaceMethods(
      Thread* self,
      Handle<mirror::Class> klass,
      const std::unordered_map<size_t, MethodTranslation>& default_translations,
      bool* out_new_conflict,
      ArtMethod** out_imt)
      REQUIRES_SHARED(Locks::mutator_lock_);

  bool LinkStaticFields(Thread* self, Handle<mirror::Class> klass, size_t* class_size)
      REQUIRES_SHARED(Locks::mutator_lock_);
  bool LinkInstanceFields(Thread* self, Handle<mirror::Class> klass)
      REQUIRES_SHARED(Locks::mutator_lock_);
  bool LinkFields(Thread* self, Handle<mirror::Class> klass, bool is_static, size_t* class_size)
      REQUIRES_SHARED(Locks::mutator_lock_);
  void CreateReferenceInstanceOffsets(Handle<mirror::Class> klass)
      REQUIRES_SHARED(Locks::mutator_lock_);

  void CheckProxyConstructor(ArtMethod* constructor) const
      REQUIRES_SHARED(Locks::mutator_lock_);
  void CheckProxyMethod(ArtMethod* method, ArtMethod* prototype) const
      REQUIRES_SHARED(Locks::mutator_lock_);

  size_t GetDexCacheCount() REQUIRES_SHARED(Locks::mutator_lock_, Locks::dex_lock_) {
    return dex_caches_.size();
  }
  const std::list<DexCacheData>& GetDexCachesData()
      REQUIRES_SHARED(Locks::mutator_lock_, Locks::dex_lock_) {
    return dex_caches_;
  }

  void CreateProxyConstructor(Handle<mirror::Class> klass, ArtMethod* out)
      REQUIRES_SHARED(Locks::mutator_lock_);
  void CreateProxyMethod(Handle<mirror::Class> klass, ArtMethod* prototype, ArtMethod* out)
      REQUIRES_SHARED(Locks::mutator_lock_);

  // Register a class loader and create its class table and allocator. Should not be called if
  // these are already created.
  void RegisterClassLoader(ObjPtr<mirror::ClassLoader> class_loader)
      REQUIRES_SHARED(Locks::mutator_lock_)
      REQUIRES(Locks::classlinker_classes_lock_);

  // Insert a new class table if not found.
  ClassTable* InsertClassTableForClassLoader(ObjPtr<mirror::ClassLoader> class_loader)
      REQUIRES_SHARED(Locks::mutator_lock_)
      REQUIRES(Locks::classlinker_classes_lock_);

  // EnsureResolved is called to make sure that a class in the class_table_ has been resolved
  // before returning it to the caller. Its the responsibility of the thread that placed the class
  // in the table to make it resolved. The thread doing resolution must notify on the class' lock
  // when resolution has occurred. This happens in mirror::Class::SetStatus. As resolution may
  // retire a class, the version of the class in the table is returned and this may differ from
  // the class passed in.
  ObjPtr<mirror::Class> EnsureResolved(Thread* self,
                                       const char* descriptor,
                                       ObjPtr<mirror::Class> klass)
      WARN_UNUSED
      REQUIRES_SHARED(Locks::mutator_lock_)
      REQUIRES(!Locks::dex_lock_);

  void FixupTemporaryDeclaringClass(ObjPtr<mirror::Class> temp_class,
                                    ObjPtr<mirror::Class> new_class)
      REQUIRES_SHARED(Locks::mutator_lock_);

  void SetClassRoot(ClassRoot class_root, ObjPtr<mirror::Class> klass)
      REQUIRES_SHARED(Locks::mutator_lock_);

  // Return the quick generic JNI stub for testing.
  const void* GetRuntimeQuickGenericJniStub() const;

  bool CanWeInitializeClass(ObjPtr<mirror::Class> klass,
                            bool can_init_statics,
                            bool can_init_parents)
      REQUIRES_SHARED(Locks::mutator_lock_);

  void UpdateClassMethods(ObjPtr<mirror::Class> klass,
                          LengthPrefixedArray<ArtMethod>* new_methods)
      REQUIRES_SHARED(Locks::mutator_lock_)
      REQUIRES(!Locks::classlinker_classes_lock_);

  // Check that c1 == FindSystemClass(self, descriptor). Abort with class dumps otherwise.
  void CheckSystemClass(Thread* self, Handle<mirror::Class> c1, const char* descriptor)
      REQUIRES(!Locks::dex_lock_)
      REQUIRES_SHARED(Locks::mutator_lock_);

  // Allocate method arrays for interfaces.
  bool AllocateIfTableMethodArrays(Thread* self,
                                   Handle<mirror::Class> klass,
                                   Handle<mirror::IfTable> iftable)
      REQUIRES_SHARED(Locks::mutator_lock_);

  // Sets imt_ref appropriately for LinkInterfaceMethods.
  // If there is no method in the imt location of imt_ref it will store the given method there.
  // Otherwise it will set the conflict method which will figure out which method to use during
  // runtime.
  void SetIMTRef(ArtMethod* unimplemented_method,
                 ArtMethod* imt_conflict_method,
                 ArtMethod* current_method,
                 /*out*/bool* new_conflict,
                 /*out*/ArtMethod** imt_ref) REQUIRES_SHARED(Locks::mutator_lock_);

  void FillIMTFromIfTable(ObjPtr<mirror::IfTable> if_table,
                          ArtMethod* unimplemented_method,
                          ArtMethod* imt_conflict_method,
                          ObjPtr<mirror::Class> klass,
                          bool create_conflict_tables,
                          bool ignore_copied_methods,
                          /*out*/bool* new_conflict,
                          /*out*/ArtMethod** imt) REQUIRES_SHARED(Locks::mutator_lock_);

  void FillImtFromSuperClass(Handle<mirror::Class> klass,
                             ArtMethod* unimplemented_method,
                             ArtMethod* imt_conflict_method,
                             bool* new_conflict,
                             ArtMethod** imt) REQUIRES_SHARED(Locks::mutator_lock_);

  // Check invoke type against the referenced class. Throws IncompatibleClassChangeError
  // (if `kThrowOnError`) and returns true on mismatch (kInterface on a non-interface class,
  // kVirtual on interface, kDefault on interface for dex files not supporting default methods),
  // otherwise returns false.
  template <bool kThrowOnError, typename ClassGetter>
  static bool CheckInvokeClassMismatch(ObjPtr<mirror::DexCache> dex_cache,
                                       InvokeType type,
                                       ClassGetter class_getter)
      REQUIRES_SHARED(Locks::mutator_lock_);
  // Helper that feeds the above function with `ClassGetter` doing `LookupResolvedType()`.
  template <bool kThrow>
  bool CheckInvokeClassMismatch(ObjPtr<mirror::DexCache> dex_cache,
                                InvokeType type,
                                uint32_t method_idx,
                                ObjPtr<mirror::ClassLoader> class_loader)
      REQUIRES_SHARED(Locks::mutator_lock_);

  ObjPtr<mirror::IfTable> GetArrayIfTable() REQUIRES_SHARED(Locks::mutator_lock_);

  std::vector<const DexFile*> boot_class_path_;
  std::vector<std::unique_ptr<const DexFile>> boot_dex_files_;

  // JNI weak globals and side data to allow dex caches to get unloaded. We lazily delete weak
  // globals when we register new dex files.
  std::list<DexCacheData> dex_caches_ GUARDED_BY(Locks::dex_lock_);

  // This contains the class loaders which have class tables. It is populated by
  // InsertClassTableForClassLoader.
  std::list<ClassLoaderData> class_loaders_
      GUARDED_BY(Locks::classlinker_classes_lock_);

  // Boot class path table. Since the class loader for this is null.
  std::unique_ptr<ClassTable> boot_class_table_ GUARDED_BY(Locks::classlinker_classes_lock_);

  // New class roots, only used by CMS since the GC needs to mark these in the pause.
  std::vector<GcRoot<mirror::Class>> new_class_roots_ GUARDED_BY(Locks::classlinker_classes_lock_);

  // Boot image oat files with new .bss GC roots to be visited in the pause by CMS.
  std::vector<const OatFile*> new_bss_roots_boot_oat_files_
      GUARDED_BY(Locks::classlinker_classes_lock_);

  // Number of times we've searched dex caches for a class. After a certain number of misses we move
  // the classes into the class_table_ to avoid dex cache based searches.
  Atomic<uint32_t> failed_dex_cache_class_lookups_;

  // Well known mirror::Class roots.
  GcRoot<mirror::ObjectArray<mirror::Class>> class_roots_;

  // A cache of the last FindArrayClass results. The cache serves to avoid creating array class
  // descriptors for the sake of performing FindClass.
  static constexpr size_t kFindArrayCacheSize = 16;
  GcRoot<mirror::Class> find_array_class_cache_[kFindArrayCacheSize];
  size_t find_array_class_cache_next_victim_;

  bool init_done_;
  bool log_new_roots_ GUARDED_BY(Locks::classlinker_classes_lock_);

  InternTable* intern_table_;

  const bool fast_class_not_found_exceptions_;

  // Trampolines within the image the bounce to runtime entrypoints. Done so that there is a single
  // patch point within the image. TODO: make these proper relocations.
  const void* quick_resolution_trampoline_;
  const void* quick_imt_conflict_trampoline_;
  const void* quick_generic_jni_trampoline_;
  const void* quick_to_interpreter_bridge_trampoline_;

  // Image pointer size.
  PointerSize image_pointer_size_;

  // Classes to transition from ClassStatus::kInitialized to ClassStatus::kVisiblyInitialized.
  Mutex visibly_initialized_callback_lock_;
  std::unique_ptr<VisiblyInitializedCallback> visibly_initialized_callback_
      GUARDED_BY(visibly_initialized_callback_lock_);
  IntrusiveForwardList<VisiblyInitializedCallback> running_visibly_initialized_callbacks_
      GUARDED_BY(visibly_initialized_callback_lock_);

  std::unique_ptr<ClassHierarchyAnalysis> cha_;

  class FindVirtualMethodHolderVisitor;

  friend class AppImageLoadingHelper;
  friend class ImageDumper;  // for DexLock
  friend struct linker::CompilationHelper;  // For Compile in ImageTest.
  friend class linker::ImageWriter;  // for GetClassRoots
  friend class JniCompilerTest;  // for GetRuntimeQuickGenericJniStub
  friend class JniInternalTest;  // for GetRuntimeQuickGenericJniStub
  friend class VMClassLoader;  // for LookupClass and FindClassInBaseDexClassLoader.
  ART_FRIEND_TEST(ClassLinkerTest, RegisterDexFileName);  // for DexLock, and RegisterDexFileLocked
  ART_FRIEND_TEST(mirror::DexCacheMethodHandlesTest, Open);  // for AllocDexCache
  ART_FRIEND_TEST(mirror::DexCacheTest, Open);  // for AllocDexCache
  DISALLOW_COPY_AND_ASSIGN(ClassLinker);
};

class ClassLoadCallback {
 public:
  virtual ~ClassLoadCallback() {}

  // Called immediately before beginning class-definition and immediately before returning from it.
  virtual void BeginDefineClass() REQUIRES_SHARED(Locks::mutator_lock_) {}
  virtual void EndDefineClass() REQUIRES_SHARED(Locks::mutator_lock_) {}

  // If set we will replace initial_class_def & initial_dex_file with the final versions. The
  // callback author is responsible for ensuring these are allocated in such a way they can be
  // cleaned up if another transformation occurs. Note that both must be set or null/unchanged on
  // return.
  // Note: the class may be temporary, in which case a following ClassPrepare event will be a
  //       different object. It is the listener's responsibility to handle this.
  // Note: This callback is rarely useful so a default implementation has been given that does
  //       nothing.
  virtual void ClassPreDefine(const char* descriptor ATTRIBUTE_UNUSED,
                              Handle<mirror::Class> klass ATTRIBUTE_UNUSED,
                              Handle<mirror::ClassLoader> class_loader ATTRIBUTE_UNUSED,
                              const DexFile& initial_dex_file ATTRIBUTE_UNUSED,
                              const dex::ClassDef& initial_class_def ATTRIBUTE_UNUSED,
                              /*out*/DexFile const** final_dex_file ATTRIBUTE_UNUSED,
                              /*out*/dex::ClassDef const** final_class_def ATTRIBUTE_UNUSED)
      REQUIRES_SHARED(Locks::mutator_lock_) {}

  // A class has been loaded.
  // Note: the class may be temporary, in which case a following ClassPrepare event will be a
  //       different object. It is the listener's responsibility to handle this.
  virtual void ClassLoad(Handle<mirror::Class> klass) REQUIRES_SHARED(Locks::mutator_lock_) = 0;

  // A class has been prepared, i.e., resolved. As the ClassLoad event might have been for a
  // temporary class, provide both the former and the current class.
  virtual void ClassPrepare(Handle<mirror::Class> temp_klass,
                            Handle<mirror::Class> klass) REQUIRES_SHARED(Locks::mutator_lock_) = 0;
};

}  // namespace art

#endif  // ART_RUNTIME_CLASS_LINKER_H_
