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);