ART: Verifier cleanup

Start making the method verifier more independent of externalities.
This will be implemented as incremental changes.

In this CL, replace querrying Runtime::Current() for the classlinker
with requiring the classlinker to use at construction time.

Test: m test-art-host
Change-Id: Id0a6a1f01c77bfe4cc9adfb490fc6ebc7bbf6392
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 731dfe7..fc32114 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -1079,7 +1079,7 @@
   // initialize the StackOverflowError class (as it might require running the verifier). Instead,
   // ensure that the class will be initialized.
   if (kMemoryToolIsAvailable && !Runtime::Current()->IsAotCompiler()) {
-    verifier::ClassVerifier::Init();  // Need to prepare the verifier.
+    verifier::ClassVerifier::Init(this);  // Need to prepare the verifier.
 
     ObjPtr<mirror::Class> soe_klass = FindSystemClass(self, "Ljava/lang/StackOverflowError;");
     if (soe_klass == nullptr || !EnsureInitialized(self, hs.NewHandle(soe_klass), true, true)) {
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index 0b4b43b..534d69d 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -1608,7 +1608,7 @@
 
   CHECK(class_linker_ != nullptr);
 
-  verifier::ClassVerifier::Init();
+  verifier::ClassVerifier::Init(class_linker_);
 
   if (runtime_options.Exists(Opt::MethodTrace)) {
     trace_config_.reset(new TraceConfig());
diff --git a/runtime/verifier/class_verifier.cc b/runtime/verifier/class_verifier.cc
index 649fb11..aa1b7bd 100644
--- a/runtime/verifier/class_verifier.cc
+++ b/runtime/verifier/class_verifier.cc
@@ -140,6 +140,7 @@
     std::string hard_failure_msg;
     MethodVerifier::FailureData result =
         MethodVerifier::VerifyMethod(self,
+                                     linker,
                                      method_idx,
                                      dex_file,
                                      dex_cache,
@@ -190,8 +191,8 @@
   }
 }
 
-void ClassVerifier::Init() {
-  MethodVerifier::Init();
+void ClassVerifier::Init(ClassLinker* class_linker) {
+  MethodVerifier::Init(class_linker);
 }
 
 void ClassVerifier::Shutdown() {
diff --git a/runtime/verifier/class_verifier.h b/runtime/verifier/class_verifier.h
index b7d3850..db5e4f5 100644
--- a/runtime/verifier/class_verifier.h
+++ b/runtime/verifier/class_verifier.h
@@ -29,6 +29,7 @@
 
 namespace art {
 
+class ClassLinker;
 class CompilerCallbacks;
 class DexFile;
 class RootVisitor;
@@ -70,7 +71,7 @@
                                  std::string* error)
       REQUIRES_SHARED(Locks::mutator_lock_);
 
-  static void Init() REQUIRES_SHARED(Locks::mutator_lock_);
+  static void Init(ClassLinker* class_linker) REQUIRES_SHARED(Locks::mutator_lock_);
   static void Shutdown();
 
   static void VisitStaticRoots(RootVisitor* visitor)
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc
index 26de3061..01be756 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -151,6 +151,7 @@
 
  private:
   MethodVerifier(Thread* self,
+                 ClassLinker* class_linker,
                  const DexFile* dex_file,
                  Handle<mirror::DexCache> dex_cache,
                  Handle<mirror::ClassLoader> class_loader,
@@ -700,6 +701,7 @@
 
 template <bool kVerifierDebug>
 MethodVerifier<kVerifierDebug>::MethodVerifier(Thread* self,
+                                               ClassLinker* class_linker,
                                                const DexFile* dex_file,
                                                Handle<mirror::DexCache> dex_cache,
                                                Handle<mirror::ClassLoader> class_loader,
@@ -716,6 +718,7 @@
                                                bool fill_register_lines,
                                                uint32_t api_level)
     : art::verifier::MethodVerifier(self,
+                                    class_linker,
                                     dex_file,
                                     code_item,
                                     dex_method_idx,
@@ -1006,7 +1009,7 @@
   // Iterate over each of the handlers to verify target addresses.
   const uint8_t* handlers_ptr = code_item_accessor_.GetCatchHandlerData();
   const uint32_t handlers_size = DecodeUnsignedLeb128(&handlers_ptr);
-  ClassLinker* linker = Runtime::Current()->GetClassLinker();
+  ClassLinker* linker = GetClassLinker();
   for (uint32_t idx = 0; idx < handlers_size; idx++) {
     CatchHandlerIterator iterator(handlers_ptr);
     for (; iterator.HasNext(); iterator.Next()) {
@@ -2432,7 +2435,7 @@
       const RegType& res_type = ResolveClass<CheckAccess::kYes>(type_idx);
       if (res_type.IsConflict()) {
         // If this is a primitive type, fail HARD.
-        ObjPtr<mirror::Class> klass = Runtime::Current()->GetClassLinker()->LookupResolvedType(
+        ObjPtr<mirror::Class> klass = GetClassLinker()->LookupResolvedType(
             type_idx, dex_cache_.Get(), class_loader_.Get());
         if (klass != nullptr && klass->IsPrimitive()) {
           Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "using primitive type "
@@ -3595,7 +3598,7 @@
     CatchHandlerIterator iterator(code_item_accessor_, *try_item);
 
     // Need the linker to try and resolve the handled class to check if it's Throwable.
-    ClassLinker* linker = Runtime::Current()->GetClassLinker();
+    ClassLinker* linker = GetClassLinker();
 
     for (; iterator.HasNext(); iterator.Next()) {
       dex::TypeIndex handler_type_idx = iterator.GetHandlerTypeIndex();
@@ -3724,7 +3727,7 @@
 template <bool kVerifierDebug>
 template <CheckAccess C>
 const RegType& MethodVerifier<kVerifierDebug>::ResolveClass(dex::TypeIndex class_idx) {
-  ClassLinker* linker = Runtime::Current()->GetClassLinker();
+  ClassLinker* linker = GetClassLinker();
   ObjPtr<mirror::Class> klass = can_load_classes_
       ? linker->ResolveType(class_idx, dex_cache_, class_loader_)
       : linker->LookupResolvedType(class_idx, dex_cache_.Get(), class_loader_.Get());
@@ -3886,7 +3889,7 @@
   }
   ObjPtr<mirror::Class> klass = klass_type.GetClass();
   const RegType& referrer = GetDeclaringClass();
-  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+  ClassLinker* class_linker = GetClassLinker();
   PointerSize pointer_size = class_linker->GetImagePointerSize();
 
   ArtMethod* res_method = dex_cache_->GetResolvedMethod(dex_method_idx, pointer_size);
@@ -4344,8 +4347,7 @@
   const char* method_name = method->GetName();
 
   const char* expected_return_descriptor;
-  ObjPtr<mirror::ObjectArray<mirror::Class>> class_roots =
-      Runtime::Current()->GetClassLinker()->GetClassRoots();
+  ObjPtr<mirror::ObjectArray<mirror::Class>> class_roots = GetClassLinker()->GetClassRoots();
   if (klass == GetClassRoot<mirror::MethodHandle>(class_roots)) {
     expected_return_descriptor = mirror::MethodHandle::GetReturnTypeDescriptor(method_name);
   } else if (klass == GetClassRoot<mirror::VarHandle>(class_roots)) {
@@ -4410,8 +4412,7 @@
         << this_type;
     return false;
   } else {
-    ObjPtr<mirror::ObjectArray<mirror::Class>> class_roots =
-        Runtime::Current()->GetClassLinker()->GetClassRoots();
+    ObjPtr<mirror::ObjectArray<mirror::Class>> class_roots = GetClassLinker()->GetClassRoots();
     if (!this_type.GetClass()->IsSubClass(GetClassRoot<mirror::MethodHandle>(class_roots)) &&
         !this_type.GetClass()->IsSubClass(GetClassRoot<mirror::VarHandle>(class_roots))) {
       Fail(VERIFY_ERROR_BAD_CLASS_HARD)
@@ -4715,7 +4716,7 @@
 
     return nullptr;  // Can't resolve Class so no more to do here, will do checking at runtime.
   }
-  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+  ClassLinker* class_linker = GetClassLinker();
   ArtField* field = class_linker->ResolveFieldJLS(field_idx, dex_cache_, class_loader_);
 
   // Record result of the field resolution attempt.
@@ -4765,7 +4766,7 @@
 
     return nullptr;  // Can't resolve Class so no more to do here
   }
-  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+  ClassLinker* class_linker = GetClassLinker();
   ArtField* field = class_linker->ResolveFieldJLS(field_idx, dex_cache_, class_loader_);
 
   // Record result of the field resolution attempt.
@@ -5135,6 +5136,7 @@
 }  // namespace impl
 
 MethodVerifier::MethodVerifier(Thread* self,
+                               ClassLinker* class_linker,
                                const DexFile* dex_file,
                                const dex::CodeItem* code_item,
                                uint32_t dex_method_idx,
@@ -5144,7 +5146,7 @@
     : self_(self),
       arena_stack_(Runtime::Current()->GetArenaPool()),
       allocator_(&arena_stack_),
-      reg_types_(can_load_classes, allocator_, allow_thread_suspension),
+      reg_types_(class_linker, can_load_classes, allocator_, allow_thread_suspension),
       reg_table_(allocator_),
       work_insn_idx_(dex::kDexNoIndex),
       dex_method_idx_(dex_method_idx),
@@ -5155,6 +5157,7 @@
       can_load_classes_(can_load_classes),
       allow_soft_failures_(allow_soft_failures),
       has_check_casts_(false),
+      class_linker_(class_linker),
       link_(nullptr) {
   self->PushVerifier(this);
 }
@@ -5165,6 +5168,7 @@
 }
 
 MethodVerifier::FailureData MethodVerifier::VerifyMethod(Thread* self,
+                                                         ClassLinker* class_linker,
                                                          uint32_t method_idx,
                                                          const DexFile* dex_file,
                                                          Handle<mirror::DexCache> dex_cache,
@@ -5181,6 +5185,7 @@
                                                          std::string* hard_failure_msg) {
   if (VLOG_IS_ON(verifier_debug)) {
     return VerifyMethod<true>(self,
+                              class_linker,
                               method_idx,
                               dex_file,
                               dex_cache,
@@ -5197,6 +5202,7 @@
                               hard_failure_msg);
   } else {
     return VerifyMethod<false>(self,
+                               class_linker,
                                method_idx,
                                dex_file,
                                dex_cache,
@@ -5216,6 +5222,7 @@
 
 template <bool kVerifierDebug>
 MethodVerifier::FailureData MethodVerifier::VerifyMethod(Thread* self,
+                                                         ClassLinker* class_linker,
                                                          uint32_t method_idx,
                                                          const DexFile* dex_file,
                                                          Handle<mirror::DexCache> dex_cache,
@@ -5234,6 +5241,7 @@
   uint64_t start_ns = kTimeVerifyMethod ? NanoTime() : 0;
 
   impl::MethodVerifier<kVerifierDebug> verifier(self,
+                                                class_linker,
                                                 dex_file,
                                                 dex_cache,
                                                 class_loader,
@@ -5379,6 +5387,7 @@
       Handle<mirror::ClassLoader> class_loader) {
   std::unique_ptr<impl::MethodVerifier<false>> verifier(
       new impl::MethodVerifier<false>(self,
+                                      Runtime::Current()->GetClassLinker(),
                                       method->GetDexFile(),
                                       dex_cache,
                                       class_loader,
@@ -5423,6 +5432,7 @@
                                                     uint32_t api_level) {
   impl::MethodVerifier<false>* verifier = new impl::MethodVerifier<false>(
       self,
+      Runtime::Current()->GetClassLinker(),
       dex_file,
       dex_cache,
       class_loader,
@@ -5461,6 +5471,7 @@
   Handle<mirror::DexCache> dex_cache(hs.NewHandle(m->GetDexCache()));
   Handle<mirror::ClassLoader> class_loader(hs.NewHandle(m->GetClassLoader()));
   impl::MethodVerifier<false> verifier(hs.Self(),
+                                       Runtime::Current()->GetClassLinker(),
                                        m->GetDexFile(),
                                        dex_cache,
                                        class_loader,
@@ -5497,6 +5508,7 @@
                                                bool allow_thread_suspension,
                                                uint32_t api_level) {
   return new impl::MethodVerifier<false>(self,
+                                         Runtime::Current()->GetClassLinker(),
                                          dex_file,
                                          dex_cache,
                                          class_loader,
@@ -5514,8 +5526,8 @@
                                          api_level);
 }
 
-void MethodVerifier::Init() {
-  art::verifier::RegTypeCache::Init();
+void MethodVerifier::Init(ClassLinker* class_linker) {
+  art::verifier::RegTypeCache::Init(class_linker);
 }
 
 void MethodVerifier::Shutdown() {
diff --git a/runtime/verifier/method_verifier.h b/runtime/verifier/method_verifier.h
index 2b9a4bc..f77fa1f 100644
--- a/runtime/verifier/method_verifier.h
+++ b/runtime/verifier/method_verifier.h
@@ -163,7 +163,7 @@
                                uint32_t api_level)
       REQUIRES_SHARED(Locks::mutator_lock_);
 
-  static void Init() REQUIRES_SHARED(Locks::mutator_lock_);
+  static void Init(ClassLinker* class_linker) REQUIRES_SHARED(Locks::mutator_lock_);
   static void Shutdown();
 
   virtual ~MethodVerifier();
@@ -194,8 +194,13 @@
     return encountered_failure_types_;
   }
 
+  ClassLinker* GetClassLinker() {
+    return class_linker_;
+  }
+
  protected:
   MethodVerifier(Thread* self,
+                 ClassLinker* class_linker,
                  const DexFile* dex_file,
                  const dex::CodeItem* code_item,
                  uint32_t dex_method_idx,
@@ -226,6 +231,7 @@
    *      for code flow problems.
    */
   static FailureData VerifyMethod(Thread* self,
+                                  ClassLinker* class_linker,
                                   uint32_t method_idx,
                                   const DexFile* dex_file,
                                   Handle<mirror::DexCache> dex_cache,
@@ -244,6 +250,7 @@
 
   template <bool kVerifierDebug>
   static FailureData VerifyMethod(Thread* self,
+                                  ClassLinker* class_linker,
                                   uint32_t method_idx,
                                   const DexFile* dex_file,
                                   Handle<mirror::DexCache> dex_cache,
@@ -351,6 +358,9 @@
   // check-cast.
   bool has_check_casts_;
 
+  // Classlinker to use when resolving.
+  ClassLinker* class_linker_;
+
   // Link, for the method verifier root linked list.
   MethodVerifier* link_;
 
diff --git a/runtime/verifier/reg_type.cc b/runtime/verifier/reg_type.cc
index c8ef80f..b6e05b5 100644
--- a/runtime/verifier/reg_type.cc
+++ b/runtime/verifier/reg_type.cc
@@ -605,7 +605,9 @@
 
 namespace {
 
-ObjPtr<mirror::Class> ArrayClassJoin(ObjPtr<mirror::Class> s, ObjPtr<mirror::Class> t)
+ObjPtr<mirror::Class> ArrayClassJoin(ObjPtr<mirror::Class> s,
+                                     ObjPtr<mirror::Class> t,
+                                     ClassLinker* class_linker)
     REQUIRES_SHARED(Locks::mutator_lock_);
 
 ObjPtr<mirror::Class> InterfaceClassJoin(ObjPtr<mirror::Class> s, ObjPtr<mirror::Class> t)
@@ -631,7 +633,9 @@
  *
  * [1] Java bytecode verification: algorithms and formalizations, Xavier Leroy
  */
-ObjPtr<mirror::Class> ClassJoin(ObjPtr<mirror::Class> s, ObjPtr<mirror::Class> t)
+ObjPtr<mirror::Class> ClassJoin(ObjPtr<mirror::Class> s,
+                                ObjPtr<mirror::Class> t,
+                                ClassLinker* class_linker)
     REQUIRES_SHARED(Locks::mutator_lock_) {
   DCHECK(!s->IsPrimitive()) << s->PrettyClass();
   DCHECK(!t->IsPrimitive()) << t->PrettyClass();
@@ -642,7 +646,7 @@
   } else if (t->IsAssignableFrom(s)) {
     return t;
   } else if (s->IsArrayClass() && t->IsArrayClass()) {
-    return ArrayClassJoin(s, t);
+    return ArrayClassJoin(s, t, class_linker);
   } else if (s->IsInterface() || t->IsInterface()) {
     return InterfaceClassJoin(s, t);
   } else {
@@ -669,7 +673,9 @@
   }
 }
 
-ObjPtr<mirror::Class> ArrayClassJoin(ObjPtr<mirror::Class> s, ObjPtr<mirror::Class> t) {
+ObjPtr<mirror::Class> ArrayClassJoin(ObjPtr<mirror::Class> s,
+                                     ObjPtr<mirror::Class> t,
+                                     ClassLinker* class_linker) {
   ObjPtr<mirror::Class> s_ct = s->GetComponentType();
   ObjPtr<mirror::Class> t_ct = t->GetComponentType();
   if (s_ct->IsPrimitive() || t_ct->IsPrimitive()) {
@@ -680,14 +686,13 @@
     return result;
   }
   Thread* self = Thread::Current();
-  ObjPtr<mirror::Class> common_elem = ClassJoin(s_ct, t_ct);
+  ObjPtr<mirror::Class> common_elem = ClassJoin(s_ct, t_ct, class_linker);
   if (UNLIKELY(common_elem == nullptr)) {
     self->AssertPendingException();
     return nullptr;
   }
   // Note: The following lookup invalidates existing ObjPtr<>s.
-  ObjPtr<mirror::Class> array_class =
-      Runtime::Current()->GetClassLinker()->FindArrayClass(self, common_elem);
+  ObjPtr<mirror::Class> array_class = class_linker->FindArrayClass(self, common_elem);
   if (UNLIKELY(array_class == nullptr)) {
     self->AssertPendingException();
     return nullptr;
@@ -867,7 +872,9 @@
       // Do not cache the classes as ClassJoin() can suspend and invalidate ObjPtr<>s.
       DCHECK(GetClass() != nullptr && !GetClass()->IsPrimitive());
       DCHECK(incoming_type.GetClass() != nullptr && !incoming_type.GetClass()->IsPrimitive());
-      ObjPtr<mirror::Class> join_class = ClassJoin(GetClass(), incoming_type.GetClass());
+      ObjPtr<mirror::Class> join_class = ClassJoin(GetClass(),
+                                                   incoming_type.GetClass(),
+                                                   reg_types->GetClassLinker());
       if (UNLIKELY(join_class == nullptr)) {
         // Internal error joining the classes (e.g., OOME). Report an unresolved reference type.
         // We cannot report an unresolved merge type, as that will attempt to merge the resolved
diff --git a/runtime/verifier/reg_type_cache.cc b/runtime/verifier/reg_type_cache.cc
index 1553017..2edb0f1 100644
--- a/runtime/verifier/reg_type_cache.cc
+++ b/runtime/verifier/reg_type_cache.cc
@@ -39,6 +39,12 @@
 const PreciseConstType* RegTypeCache::small_precise_constants_[kMaxSmallConstant -
                                                                kMinSmallConstant + 1];
 
+namespace {
+
+ClassLinker* gInitClassLinker = nullptr;
+
+}  // namespace
+
 ALWAYS_INLINE static inline bool MatchingPrecisionForClass(const RegType* entry, bool precise)
     REQUIRES_SHARED(Locks::mutator_lock_) {
   if (entry->IsPreciseReference() == precise) {
@@ -153,15 +159,14 @@
                                                  ObjPtr<mirror::ClassLoader> loader) {
   // Class was not found, must create new type.
   // Try resolving class
-  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
   Thread* self = Thread::Current();
   StackHandleScope<1> hs(self);
   Handle<mirror::ClassLoader> class_loader(hs.NewHandle(loader));
   ObjPtr<mirror::Class> klass = nullptr;
   if (can_load_classes_) {
-    klass = class_linker->FindClass(self, descriptor, class_loader);
+    klass = class_linker_->FindClass(self, descriptor, class_loader);
   } else {
-    klass = class_linker->LookupClass(self, descriptor, loader);
+    klass = class_linker_->LookupClass(self, descriptor, loader);
     if (klass != nullptr && !klass->IsResolved()) {
       // We found the class but without it being loaded its not safe for use.
       klass = nullptr;
@@ -277,11 +282,16 @@
   return *reg_type;
 }
 
-RegTypeCache::RegTypeCache(bool can_load_classes, ScopedArenaAllocator& allocator, bool can_suspend)
+RegTypeCache::RegTypeCache(ClassLinker* class_linker,
+                           bool can_load_classes,
+                           ScopedArenaAllocator& allocator,
+                           bool can_suspend)
     : entries_(allocator.Adapter(kArenaAllocVerifier)),
       klass_entries_(allocator.Adapter(kArenaAllocVerifier)),
-      can_load_classes_(can_load_classes),
-      allocator_(allocator) {
+      allocator_(allocator),
+      class_linker_(class_linker),
+      can_load_classes_(can_load_classes) {
+  DCHECK_EQ(class_linker, gInitClassLinker);
   DCHECK(can_suspend || !can_load_classes) << "Cannot load classes if suspension is disabled!";
   if (kIsDebugBuild && can_suspend) {
     Thread::Current()->AssertThreadSuspensionIsAllowable(gAborting == 0);
@@ -337,7 +347,9 @@
 };
 }  // namespace
 
-void RegTypeCache::CreatePrimitiveAndSmallConstantTypes() {
+void RegTypeCache::CreatePrimitiveAndSmallConstantTypes(ClassLinker* class_linker) {
+  gInitClassLinker = class_linker;
+
   // Note: this must have the same order as FillPrimitiveAndSmallConstantTypes.
 
   // It is acceptable to pass on the const char* in type to CreateInstance, as all calls below are
@@ -349,8 +361,7 @@
     // Try loading the class from linker.
     DCHECK(type.descriptor != nullptr);
     if (strlen(type.descriptor) > 0) {
-      klass = art::Runtime::Current()->GetClassLinker()->FindSystemClass(Thread::Current(),
-                                                                         type.descriptor);
+      klass = class_linker->FindSystemClass(Thread::Current(), type.descriptor);
       DCHECK(klass != nullptr);
     }
     const Type* entry = Type::CreateInstance(klass,
diff --git a/runtime/verifier/reg_type_cache.h b/runtime/verifier/reg_type_cache.h
index a9a8116..a6d226a 100644
--- a/runtime/verifier/reg_type_cache.h
+++ b/runtime/verifier/reg_type_cache.h
@@ -28,10 +28,13 @@
 #include "gc_root.h"
 
 namespace art {
+
 namespace mirror {
 class Class;
 class ClassLoader;
 }  // namespace mirror
+
+class ClassLinker;
 class ScopedArenaAllocator;
 
 namespace verifier {
@@ -62,12 +65,15 @@
 
 class RegTypeCache {
  public:
-  RegTypeCache(bool can_load_classes, ScopedArenaAllocator& allocator, bool can_suspend = true);
+  RegTypeCache(ClassLinker* class_linker,
+               bool can_load_classes,
+               ScopedArenaAllocator& allocator,
+               bool can_suspend = true);
   ~RegTypeCache();
-  static void Init() REQUIRES_SHARED(Locks::mutator_lock_) {
+  static void Init(ClassLinker* class_linker) REQUIRES_SHARED(Locks::mutator_lock_) {
     if (!RegTypeCache::primitive_initialized_) {
       CHECK_EQ(RegTypeCache::primitive_count_, 0);
-      CreatePrimitiveAndSmallConstantTypes();
+      CreatePrimitiveAndSmallConstantTypes(class_linker);
       CHECK_EQ(RegTypeCache::primitive_count_, kNumPrimitivesAndSmallConstants);
       RegTypeCache::primitive_initialized_ = true;
     }
@@ -160,6 +166,10 @@
   static void VisitStaticRoots(RootVisitor* visitor)
       REQUIRES_SHARED(Locks::mutator_lock_);
 
+  ClassLinker* GetClassLinker() {
+    return class_linker_;
+  }
+
  private:
   void FillPrimitiveAndSmallConstantTypes() REQUIRES_SHARED(Locks::mutator_lock_);
   ObjPtr<mirror::Class> ResolveClass(const char* descriptor, ObjPtr<mirror::ClassLoader> loader)
@@ -177,7 +187,8 @@
   // verifier and return a string view.
   std::string_view AddString(const std::string_view& str);
 
-  static void CreatePrimitiveAndSmallConstantTypes() REQUIRES_SHARED(Locks::mutator_lock_);
+  static void CreatePrimitiveAndSmallConstantTypes(ClassLinker* class_linker)
+      REQUIRES_SHARED(Locks::mutator_lock_);
 
   // A quick look up for popular small constants.
   static constexpr int32_t kMinSmallConstant = -1;
@@ -200,12 +211,14 @@
   // Fast lookup for quickly finding entries that have a matching class.
   ScopedArenaVector<std::pair<GcRoot<mirror::Class>, const RegType*>> klass_entries_;
 
-  // Whether or not we're allowed to load classes.
-  const bool can_load_classes_;
-
   // Arena allocator.
   ScopedArenaAllocator& allocator_;
 
+  ClassLinker* class_linker_;
+
+  // Whether or not we're allowed to load classes.
+  const bool can_load_classes_;
+
   DISALLOW_COPY_AND_ASSIGN(RegTypeCache);
 };
 
diff --git a/runtime/verifier/reg_type_test.cc b/runtime/verifier/reg_type_test.cc
index 3e80e5a..9cac5fb 100644
--- a/runtime/verifier/reg_type_test.cc
+++ b/runtime/verifier/reg_type_test.cc
@@ -38,7 +38,7 @@
   ArenaStack stack(Runtime::Current()->GetArenaPool());
   ScopedArenaAllocator allocator(&stack);
   ScopedObjectAccess soa(Thread::Current());
-  RegTypeCache cache(true, allocator);
+  RegTypeCache cache(Runtime::Current()->GetClassLinker(), true, allocator);
   const RegType& ref_type_const_0 = cache.FromCat1Const(10, true);
   const RegType& ref_type_const_1 = cache.FromCat1Const(10, true);
   const RegType& ref_type_const_2 = cache.FromCat1Const(30, true);
@@ -62,7 +62,7 @@
   ArenaStack stack(Runtime::Current()->GetArenaPool());
   ScopedArenaAllocator allocator(&stack);
   ScopedObjectAccess soa(Thread::Current());
-  RegTypeCache cache(true, allocator);
+  RegTypeCache cache(Runtime::Current()->GetClassLinker(), true, allocator);
   int64_t val = static_cast<int32_t>(1234);
   const RegType& precise_lo = cache.FromCat2ConstLo(static_cast<int32_t>(val), true);
   const RegType& precise_hi = cache.FromCat2ConstHi(static_cast<int32_t>(val >> 32), true);
@@ -88,7 +88,7 @@
   ArenaStack stack(Runtime::Current()->GetArenaPool());
   ScopedArenaAllocator allocator(&stack);
   ScopedObjectAccess soa(Thread::Current());
-  RegTypeCache cache(true, allocator);
+  RegTypeCache cache(Runtime::Current()->GetClassLinker(), true, allocator);
 
   const RegType& bool_reg_type = cache.Boolean();
   EXPECT_FALSE(bool_reg_type.IsUndefined());
@@ -363,7 +363,7 @@
   ArenaStack stack(Runtime::Current()->GetArenaPool());
   ScopedArenaAllocator allocator(&stack);
   ScopedObjectAccess soa(Thread::Current());
-  RegTypeCache cache(true, allocator);
+  RegTypeCache cache(Runtime::Current()->GetClassLinker(), true, allocator);
   const RegType& imprecise_obj = cache.JavaLangObject(false);
   const RegType& precise_obj = cache.JavaLangObject(true);
   const RegType& precise_obj_2 = cache.FromDescriptor(nullptr, "Ljava/lang/Object;", true);
@@ -380,7 +380,7 @@
   ArenaStack stack(Runtime::Current()->GetArenaPool());
   ScopedArenaAllocator allocator(&stack);
   ScopedObjectAccess soa(Thread::Current());
-  RegTypeCache cache(true, allocator);
+  RegTypeCache cache(Runtime::Current()->GetClassLinker(), true, allocator);
   const RegType& ref_type_0 = cache.FromDescriptor(nullptr, "Ljava/lang/DoesNotExist;", true);
   EXPECT_TRUE(ref_type_0.IsUnresolvedReference());
   EXPECT_TRUE(ref_type_0.IsNonZeroReferenceTypes());
@@ -398,7 +398,7 @@
   ArenaStack stack(Runtime::Current()->GetArenaPool());
   ScopedArenaAllocator allocator(&stack);
   ScopedObjectAccess soa(Thread::Current());
-  RegTypeCache cache(true, allocator);
+  RegTypeCache cache(Runtime::Current()->GetClassLinker(), true, allocator);
   const RegType& ref_type_0 = cache.FromDescriptor(nullptr, "Ljava/lang/DoesNotExist;", true);
   EXPECT_TRUE(ref_type_0.IsUnresolvedReference());
   const RegType& ref_type = cache.FromDescriptor(nullptr, "Ljava/lang/DoesNotExist;", true);
@@ -422,7 +422,7 @@
   ArenaStack stack(Runtime::Current()->GetArenaPool());
   ScopedArenaAllocator allocator(&stack);
   ScopedObjectAccess soa(Thread::Current());
-  RegTypeCache cache(true, allocator);
+  RegTypeCache cache(Runtime::Current()->GetClassLinker(), true, allocator);
   const RegType& unresolved_ref = cache.FromDescriptor(nullptr, "Ljava/lang/DoesNotExist;", true);
   const RegType& unresolved_ref_another = cache.FromDescriptor(nullptr, "Ljava/lang/DoesNotExistEither;", true);
   const RegType& resolved_ref = cache.JavaLangString();
@@ -450,7 +450,7 @@
   ArenaStack stack(Runtime::Current()->GetArenaPool());
   ScopedArenaAllocator allocator(&stack);
   ScopedObjectAccess soa(Thread::Current());
-  RegTypeCache cache(true, allocator);
+  RegTypeCache cache(Runtime::Current()->GetClassLinker(), true, allocator);
   const RegType& ref_type = cache.JavaLangString();
   const RegType& ref_type_2 = cache.JavaLangString();
   const RegType& ref_type_3 = cache.FromDescriptor(nullptr, "Ljava/lang/String;", true);
@@ -472,7 +472,7 @@
   ArenaStack stack(Runtime::Current()->GetArenaPool());
   ScopedArenaAllocator allocator(&stack);
   ScopedObjectAccess soa(Thread::Current());
-  RegTypeCache cache(true, allocator);
+  RegTypeCache cache(Runtime::Current()->GetClassLinker(), true, allocator);
   const RegType& ref_type = cache.JavaLangObject(true);
   const RegType& ref_type_2 = cache.JavaLangObject(true);
   const RegType& ref_type_3 = cache.FromDescriptor(nullptr, "Ljava/lang/Object;", true);
@@ -487,7 +487,7 @@
   ScopedObjectAccess soa(Thread::Current());
   ArenaStack stack(Runtime::Current()->GetArenaPool());
   ScopedArenaAllocator allocator(&stack);
-  RegTypeCache cache_new(true, allocator);
+  RegTypeCache cache_new(Runtime::Current()->GetClassLinker(), true, allocator);
   const RegType& string = cache_new.JavaLangString();
   const RegType& Object = cache_new.JavaLangObject(true);
   EXPECT_TRUE(string.Merge(Object, &cache_new, /* verifier= */ nullptr).IsJavaLangObject());
@@ -512,7 +512,7 @@
   ArenaStack stack(Runtime::Current()->GetArenaPool());
   ScopedArenaAllocator allocator(&stack);
   ScopedObjectAccess soa(Thread::Current());
-  RegTypeCache cache_new(true, allocator);
+  RegTypeCache cache_new(Runtime::Current()->GetClassLinker(), true, allocator);
 
   constexpr int32_t kTestConstantValue = 10;
   const RegType& float_type = cache_new.Float();
@@ -545,7 +545,7 @@
   ArenaStack stack(Runtime::Current()->GetArenaPool());
   ScopedArenaAllocator allocator(&stack);
   ScopedObjectAccess soa(Thread::Current());
-  RegTypeCache cache_new(true, allocator);
+  RegTypeCache cache_new(Runtime::Current()->GetClassLinker(), true, allocator);
 
   constexpr int32_t kTestConstantValue = 10;
   const RegType& long_lo_type = cache_new.LongLo();
@@ -605,7 +605,7 @@
   ArenaStack stack(Runtime::Current()->GetArenaPool());
   ScopedArenaAllocator allocator(&stack);
   ScopedObjectAccess soa(Thread::Current());
-  RegTypeCache cache_new(true, allocator);
+  RegTypeCache cache_new(Runtime::Current()->GetClassLinker(), true, allocator);
 
   constexpr int32_t kTestConstantValue = 10;
   const RegType& double_lo_type = cache_new.DoubleLo();
@@ -719,7 +719,7 @@
 
   ScopedDisableMovingGC no_gc(soa.Self());
 
-  RegTypeCache cache(true, allocator);
+  RegTypeCache cache(Runtime::Current()->GetClassLinker(), true, allocator);
 
   const RegType& conflict = cache.Conflict();
   const RegType& zero = cache.Zero();
@@ -1043,7 +1043,7 @@
   ArenaStack stack(Runtime::Current()->GetArenaPool());
   ScopedArenaAllocator allocator(&stack);
   ScopedObjectAccess soa(Thread::Current());
-  RegTypeCache cache_new(true, allocator);
+  RegTypeCache cache_new(Runtime::Current()->GetClassLinker(), true, allocator);
   const RegType& imprecise_const = cache_new.FromCat1Const(10, false);
   const RegType& precise_const = cache_new.FromCat1Const(10, true);
 
@@ -1082,7 +1082,7 @@
   constexpr const char* kNumberArrayFour = "[[[[Ljava/lang/Number;";
   constexpr const char* kNumberArrayFive = "[[[[[Ljava/lang/Number;";
 
-  RegTypeCache cache(true, allocator);
+  RegTypeCache cache(Runtime::Current()->GetClassLinker(), true, allocator);
   const RegType& int_array_array = cache.From(nullptr, kIntArrayFive, false);
   ASSERT_TRUE(int_array_array.HasClass());
   const RegType& float_array_array = cache.From(nullptr, kFloatArrayFive, false);
@@ -1122,7 +1122,7 @@
 
     ScopedDisableMovingGC no_gc(soa.Self());
 
-    RegTypeCache cache(true, allocator);
+    RegTypeCache cache(Runtime::Current()->GetClassLinker(), true, allocator);
     const RegType& c1_reg_type = *cache.InsertClass(in1, c1.Get(), false);
     const RegType& c2_reg_type = *cache.InsertClass(in2, c2.Get(), false);