summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Vladimir Marko <vmarko@google.com> 2024-10-14 09:56:26 +0000
committer VladimĂ­r Marko <vmarko@google.com> 2024-10-17 07:08:14 +0000
commit625356946238649c5fae5ee96c1d0c3a9acdaf8b (patch)
treed646afe7178a1a3b26c4edb5c80ac8a9635f13a9
parent3e5cfa5a7557395123f4f4648a761d88eda358b7 (diff)
Share `RegTypeCache` for all methods in a `Class`.
Test: m test-art-host-gtest Test: testrunner.py --host --optimizing Bug: 181943478 Change-Id: Ic5e2ad1a83a9013a428b51ef39641d8a1f34cee9
-rw-r--r--dex2oat/verifier_deps_test.cc7
-rw-r--r--oatdump/oatdump.cc38
-rw-r--r--openjdkjvmti/ti_method.cc10
-rw-r--r--runtime/verifier/class_verifier.cc114
-rw-r--r--runtime/verifier/method_verifier.cc127
-rw-r--r--runtime/verifier/method_verifier.h41
-rw-r--r--runtime/verifier/reg_type_cache-inl.h1
-rw-r--r--runtime/verifier/reg_type_cache.cc12
-rw-r--r--runtime/verifier/reg_type_cache.h29
-rw-r--r--runtime/verifier/reg_type_test.cc102
10 files changed, 232 insertions, 249 deletions
diff --git a/dex2oat/verifier_deps_test.cc b/dex2oat/verifier_deps_test.cc
index 2cddcedcfa..46e40902de 100644
--- a/dex2oat/verifier_deps_test.cc
+++ b/dex2oat/verifier_deps_test.cc
@@ -37,6 +37,7 @@
#include "thread.h"
#include "utils/atomic_dex_ref_map-inl.h"
#include "verifier/method_verifier-inl.h"
+#include "verifier/reg_type_cache.h"
namespace art {
namespace verifier {
@@ -161,8 +162,10 @@ class VerifierDepsTest : public CommonCompilerDriverTest {
method.GetInvokeType(class_def->access_flags_));
CHECK(resolved_method != nullptr);
if (method_name == resolved_method->GetName()) {
+ RegTypeCache reg_types(soa.Self(), class_linker_, Runtime::Current()->GetArenaPool());
std::unique_ptr<MethodVerifier> verifier(
MethodVerifier::CreateVerifier(soa.Self(),
+ &reg_types,
callbacks_->GetVerifierDeps(),
primary_dex_file_,
dex_cache_handle,
@@ -171,9 +174,7 @@ class VerifierDepsTest : public CommonCompilerDriverTest {
method.GetCodeItem(),
method.GetIndex(),
method.GetAccessFlags(),
- /* can_load_classes= */ true,
- /* verify to dump */ false,
- /* allow_thread_suspension= */ true,
+ /* verify_to_dump= */ false,
/* api_level= */ 0));
verifier->Verify();
soa.Self()->SetVerifierDeps(nullptr);
diff --git a/oatdump/oatdump.cc b/oatdump/oatdump.cc
index 726d6b085f..06d9e98218 100644
--- a/oatdump/oatdump.cc
+++ b/oatdump/oatdump.cc
@@ -1180,14 +1180,14 @@ class OatDumper {
hs.reset(new StackHandleScope<1>(Thread::Current()));
vios->Stream() << "VERIFIER TYPE ANALYSIS:\n";
ScopedIndentation indent2(vios);
- verifier.reset(DumpVerifier(vios,
- soa,
- hs.get(),
- dex_method_idx,
- &dex_file,
- class_def,
- code_item,
- method_access_flags));
+ DumpVerifier(vios,
+ soa,
+ hs.get(),
+ dex_method_idx,
+ &dex_file,
+ class_def,
+ code_item,
+ method_access_flags);
}
{
vios->Stream() << "OatMethodOffsets ";
@@ -1493,14 +1493,14 @@ class OatDumper {
code_item_accessor.HasCodeItem();
}
- verifier::MethodVerifier* DumpVerifier(VariableIndentationOutputStream* vios,
- ScopedObjectAccess& soa,
- StackHandleScope<1>* hs,
- uint32_t dex_method_idx,
- const DexFile* dex_file,
- const dex::ClassDef& class_def,
- const dex::CodeItem* code_item,
- uint32_t method_access_flags)
+ void DumpVerifier(VariableIndentationOutputStream* vios,
+ ScopedObjectAccess& soa,
+ StackHandleScope<1>* hs,
+ uint32_t dex_method_idx,
+ const DexFile* dex_file,
+ const dex::ClassDef& class_def,
+ const dex::CodeItem* code_item,
+ uint32_t method_access_flags)
REQUIRES_SHARED(Locks::mutator_lock_) {
if ((method_access_flags & kAccNative) == 0) {
Runtime* const runtime = Runtime::Current();
@@ -1512,9 +1512,9 @@ class OatDumper {
dex_method_idx, dex_cache, *options_.class_loader_);
if (method == nullptr) {
soa.Self()->ClearException();
- return nullptr;
+ return;
}
- return verifier::MethodVerifier::VerifyMethodAndDump(
+ verifier::MethodVerifier::VerifyMethodAndDump(
soa.Self(),
vios,
dex_method_idx,
@@ -1526,8 +1526,6 @@ class OatDumper {
method_access_flags,
/* api_level= */ 0);
}
-
- return nullptr;
}
void DumpCode(VariableIndentationOutputStream* vios,
diff --git a/openjdkjvmti/ti_method.cc b/openjdkjvmti/ti_method.cc
index 0557234a46..6150a4692b 100644
--- a/openjdkjvmti/ti_method.cc
+++ b/openjdkjvmti/ti_method.cc
@@ -79,6 +79,7 @@
#include "ti_phase.h"
#include "verifier/register_line-inl.h"
#include "verifier/reg_type-inl.h"
+#include "verifier/reg_type_cache.h"
#include "verifier/method_verifier-inl.h"
namespace openjdkjvmti {
@@ -637,9 +638,16 @@ class CommonLocalVariableClosure : public art::Closure {
art::StackHandleScope<2> hs(art::Thread::Current());
art::Handle<art::mirror::DexCache> dex_cache(hs.NewHandle(method->GetDexCache()));
art::Handle<art::mirror::ClassLoader> class_loader(hs.NewHandle(method->GetClassLoader()));
+ art::Thread* self = art::Thread::Current();
+ art::Runtime* runtime = art::Runtime::Current();
+ art::ClassLinker* class_linker = runtime->GetClassLinker();
+ art::ArenaPool* arena_pool = runtime->GetArenaPool();
+ art::verifier::RegTypeCache reg_types(
+ self, class_linker, arena_pool, /* can_load_classes= */ false, /* can_suspend= */ false);
std::unique_ptr<art::verifier::MethodVerifier> verifier(
art::verifier::MethodVerifier::CalculateVerificationInfo(
- art::Thread::Current(),
+ self,
+ &reg_types,
method,
dex_cache,
class_loader,
diff --git a/runtime/verifier/class_verifier.cc b/runtime/verifier/class_verifier.cc
index eea737608b..d6fd64e376 100644
--- a/runtime/verifier/class_verifier.cc
+++ b/runtime/verifier/class_verifier.cc
@@ -111,65 +111,69 @@ FailureKind ClassVerifier::VerifyClass(Thread* self,
MethodVerifier::FailureData failure_data;
ClassLinker* const linker = Runtime::Current()->GetClassLinker();
- for (const ClassAccessor::Method& method : accessor.GetMethods()) {
- int64_t* previous_idx = &previous_method_idx[method.IsStaticOrDirect() ? 0u : 1u];
- self->AllowThreadSuspension();
- const uint32_t method_idx = method.GetIndex();
- if (method_idx == *previous_idx) {
- // smali can create dex files with two encoded_methods sharing the same method_idx
- // http://code.google.com/p/smali/issues/detail?id=119
- continue;
- }
- *previous_idx = method_idx;
- std::string hard_failure_msg;
- MethodVerifier::FailureData result =
- MethodVerifier::VerifyMethod(self,
- linker,
- Runtime::Current()->GetArenaPool(),
- verifier_deps,
- method_idx,
- dex_file,
- dex_cache,
- class_loader,
- class_def,
- method.GetCodeItem(),
- method.GetAccessFlags(),
- log_level,
- api_level,
- Runtime::Current()->IsAotCompiler(),
- &hard_failure_msg);
- if (result.kind == FailureKind::kHardFailure) {
- if (failure_data.kind == FailureKind::kHardFailure) {
- // If we logged an error before, we need a newline.
- *error += "\n";
- } else {
- // If we didn't log a hard failure before, print the header of the message.
- *error += "Verifier rejected class ";
- *error += PrettyDescriptor(dex_file->GetClassDescriptor(class_def));
- *error += ":";
+ if (accessor.NumMethods() != 0u) {
+ ArenaPool* arena_pool = Runtime::Current()->GetArenaPool();
+ RegTypeCache reg_types(self, linker, arena_pool);
+ for (const ClassAccessor::Method& method : accessor.GetMethods()) {
+ int64_t* previous_idx = &previous_method_idx[method.IsStaticOrDirect() ? 0u : 1u];
+ self->AllowThreadSuspension();
+ const uint32_t method_idx = method.GetIndex();
+ if (method_idx == *previous_idx) {
+ // smali can create dex files with two encoded_methods sharing the same method_idx
+ // http://code.google.com/p/smali/issues/detail?id=119
+ continue;
}
- *error += " ";
- *error += hard_failure_msg;
- } else if (result.kind != FailureKind::kNoFailure) {
- UpdateMethodFlags(method.GetIndex(), klass, dex_cache, callbacks, result.types);
- if ((result.types & VerifyError::VERIFY_ERROR_LOCKING) != 0) {
- // Print a warning about expected slow-down.
- // Use a string temporary to print one contiguous warning.
- std::string tmp =
- StringPrintf("Method %s failed lock verification and will run slower.",
- dex_file->PrettyMethod(method.GetIndex()).c_str());
- if (!gPrintedDxMonitorText) {
- tmp +=
- "\nCommon causes for lock verification issues are non-optimized dex code\n"
- "and incorrect proguard optimizations.";
- gPrintedDxMonitorText = true;
+ *previous_idx = method_idx;
+ std::string hard_failure_msg;
+ MethodVerifier::FailureData result =
+ MethodVerifier::VerifyMethod(self,
+ arena_pool,
+ &reg_types,
+ verifier_deps,
+ method_idx,
+ dex_file,
+ dex_cache,
+ class_loader,
+ class_def,
+ method.GetCodeItem(),
+ method.GetAccessFlags(),
+ log_level,
+ api_level,
+ Runtime::Current()->IsAotCompiler(),
+ &hard_failure_msg);
+ if (result.kind == FailureKind::kHardFailure) {
+ if (failure_data.kind == FailureKind::kHardFailure) {
+ // If we logged an error before, we need a newline.
+ *error += "\n";
+ } else {
+ // If we didn't log a hard failure before, print the header of the message.
+ *error += "Verifier rejected class ";
+ *error += PrettyDescriptor(dex_file->GetClassDescriptor(class_def));
+ *error += ":";
+ }
+ *error += " ";
+ *error += hard_failure_msg;
+ } else if (result.kind != FailureKind::kNoFailure) {
+ UpdateMethodFlags(method.GetIndex(), klass, dex_cache, callbacks, result.types);
+ if ((result.types & VerifyError::VERIFY_ERROR_LOCKING) != 0) {
+ // Print a warning about expected slow-down.
+ // Use a string temporary to print one contiguous warning.
+ std::string tmp =
+ StringPrintf("Method %s failed lock verification and will run slower.",
+ dex_file->PrettyMethod(method.GetIndex()).c_str());
+ if (!gPrintedDxMonitorText) {
+ tmp +=
+ "\nCommon causes for lock verification issues are non-optimized dex code\n"
+ "and incorrect proguard optimizations.";
+ gPrintedDxMonitorText = true;
+ }
+ LOG(WARNING) << tmp;
}
- LOG(WARNING) << tmp;
}
- }
- // Merge the result for the method into the global state for the class.
- failure_data.Merge(result);
+ // Merge the result for the method into the global state for the class.
+ failure_data.Merge(result);
+ }
}
uint64_t elapsed_time_microseconds = timer.Stop();
VLOG(verifier) << "VerifyClass took " << PrettyDuration(UsToNs(elapsed_time_microseconds))
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc
index f464edfd34..aebf1ec5c2 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -56,6 +56,7 @@
#include "mirror/var_handle.h"
#include "obj_ptr-inl.h"
#include "reg_type-inl.h"
+#include "reg_type_cache.h"
#include "register_line-inl.h"
#include "runtime.h"
#include "scoped_newline.h"
@@ -129,14 +130,12 @@ class MethodVerifier final : public ::art::verifier::MethodVerifier {
private:
MethodVerifier(Thread* self,
- ClassLinker* class_linker,
ArenaPool* arena_pool,
+ RegTypeCache* reg_types,
VerifierDeps* verifier_deps,
const DexFile* dex_file,
const dex::CodeItem* code_item,
uint32_t method_idx,
- bool can_load_classes,
- bool allow_thread_suspension,
bool aot_mode,
Handle<mirror::DexCache> dex_cache,
Handle<mirror::ClassLoader> class_loader,
@@ -145,15 +144,13 @@ class MethodVerifier final : public ::art::verifier::MethodVerifier {
bool verify_to_dump,
uint32_t api_level) REQUIRES_SHARED(Locks::mutator_lock_)
: art::verifier::MethodVerifier(self,
- class_linker,
arena_pool,
+ reg_types,
verifier_deps,
dex_file,
class_def,
code_item,
method_idx,
- can_load_classes,
- allow_thread_suspension,
aot_mode),
method_access_flags_(access_flags),
return_type_(nullptr),
@@ -163,7 +160,7 @@ class MethodVerifier final : public ::art::verifier::MethodVerifier {
interesting_dex_pc_(-1),
monitor_enter_dex_pcs_(nullptr),
verify_to_dump_(verify_to_dump),
- allow_thread_suspension_(allow_thread_suspension),
+ allow_thread_suspension_(reg_types->CanSuspend()),
is_constructor_(false),
api_level_(api_level == 0 ? std::numeric_limits<uint32_t>::max() : api_level) {
}
@@ -4879,30 +4876,31 @@ bool MethodVerifier<kVerifierDebug>::PotentiallyMarkRuntimeThrow() {
} // namespace
} // namespace impl
+inline ClassLinker* MethodVerifier::GetClassLinker() const {
+ return reg_types_.GetClassLinker();
+}
+
MethodVerifier::MethodVerifier(Thread* self,
- ClassLinker* class_linker,
ArenaPool* arena_pool,
+ RegTypeCache* reg_types,
VerifierDeps* verifier_deps,
const DexFile* dex_file,
const dex::ClassDef& class_def,
const dex::CodeItem* code_item,
uint32_t dex_method_idx,
- bool can_load_classes,
- bool allow_thread_suspension,
bool aot_mode)
: self_(self),
arena_stack_(arena_pool),
allocator_(&arena_stack_),
- reg_types_(self, class_linker, can_load_classes, allocator_, allow_thread_suspension),
+ reg_types_(*reg_types),
reg_table_(allocator_),
work_insn_idx_(dex::kDexNoIndex),
dex_method_idx_(dex_method_idx),
dex_file_(dex_file),
class_def_(class_def),
code_item_accessor_(*dex_file, code_item),
- // TODO: make it designated initialization when we compile as C++20.
- flags_({false, false}),
- const_flags_({aot_mode, can_load_classes}),
+ flags_{ .have_pending_hard_failure_ = false, .have_pending_runtime_throw_failure_ = false },
+ const_flags_{ .aot_mode_ = aot_mode, .can_load_classes_ = reg_types->CanLoadClasses() },
encountered_failure_types_(0),
verifier_deps_(verifier_deps),
link_(nullptr) {
@@ -4913,8 +4911,8 @@ MethodVerifier::~MethodVerifier() {
}
MethodVerifier::FailureData MethodVerifier::VerifyMethod(Thread* self,
- ClassLinker* class_linker,
ArenaPool* arena_pool,
+ RegTypeCache* reg_types,
VerifierDeps* verifier_deps,
uint32_t method_idx,
const DexFile* dex_file,
@@ -4929,8 +4927,8 @@ MethodVerifier::FailureData MethodVerifier::VerifyMethod(Thread* self,
std::string* hard_failure_msg) {
if (VLOG_IS_ON(verifier_debug)) {
return VerifyMethod<true>(self,
- class_linker,
arena_pool,
+ reg_types,
verifier_deps,
method_idx,
dex_file,
@@ -4945,8 +4943,8 @@ MethodVerifier::FailureData MethodVerifier::VerifyMethod(Thread* self,
hard_failure_msg);
} else {
return VerifyMethod<false>(self,
- class_linker,
arena_pool,
+ reg_types,
verifier_deps,
method_idx,
dex_file,
@@ -4981,8 +4979,8 @@ static inline bool CanRuntimeHandleVerificationFailure(uint32_t encountered_fail
template <bool kVerifierDebug>
MethodVerifier::FailureData MethodVerifier::VerifyMethod(Thread* self,
- ClassLinker* class_linker,
ArenaPool* arena_pool,
+ RegTypeCache* reg_types,
VerifierDeps* verifier_deps,
uint32_t method_idx,
const DexFile* dex_file,
@@ -4999,20 +4997,18 @@ MethodVerifier::FailureData MethodVerifier::VerifyMethod(Thread* self,
uint64_t start_ns = kTimeVerifyMethod ? NanoTime() : 0;
impl::MethodVerifier<kVerifierDebug> verifier(self,
- class_linker,
arena_pool,
+ reg_types,
verifier_deps,
dex_file,
code_item,
method_idx,
- /* can_load_classes= */ true,
- /* allow_thread_suspension= */ true,
aot_mode,
dex_cache,
class_loader,
class_def,
method_access_flags,
- /* verify to dump */ false,
+ /* verify_to_dump= */ false,
api_level);
if (verifier.Verify()) {
// Verification completed, however failures may be pending that didn't cause the verification
@@ -5105,21 +5101,21 @@ MethodVerifier::FailureData MethodVerifier::VerifyMethod(Thread* self,
MethodVerifier* MethodVerifier::CalculateVerificationInfo(
Thread* self,
+ RegTypeCache* reg_types,
ArtMethod* method,
Handle<mirror::DexCache> dex_cache,
Handle<mirror::ClassLoader> class_loader,
uint32_t dex_pc) {
+ Runtime* runtime = Runtime::Current();
std::unique_ptr<impl::MethodVerifier<false>> verifier(
new impl::MethodVerifier<false>(self,
- Runtime::Current()->GetClassLinker(),
- Runtime::Current()->GetArenaPool(),
+ runtime->GetArenaPool(),
+ reg_types,
/* verifier_deps= */ nullptr,
method->GetDexFile(),
method->GetCodeItem(),
method->GetDexMethodIndex(),
- /* can_load_classes= */ false,
- /* allow_thread_suspension= */ false,
- Runtime::Current()->IsAotCompiler(),
+ runtime->IsAotCompiler(),
dex_cache,
class_loader,
*method->GetDeclaringClass()->GetClassDef(),
@@ -5128,7 +5124,7 @@ MethodVerifier* MethodVerifier::CalculateVerificationInfo(
// Just use the verifier at the current skd-version.
// This might affect what soft-verifier errors are reported.
// Callers can then filter out relevant errors if needed.
- Runtime::Current()->GetTargetSdkVersion()));
+ runtime->GetTargetSdkVersion()));
verifier->interesting_dex_pc_ = dex_pc;
verifier->Verify();
if (VLOG_IS_ON(verifier)) {
@@ -5143,44 +5139,42 @@ MethodVerifier* MethodVerifier::CalculateVerificationInfo(
}
}
-MethodVerifier* MethodVerifier::VerifyMethodAndDump(Thread* self,
- VariableIndentationOutputStream* vios,
- uint32_t dex_method_idx,
- const DexFile* dex_file,
- Handle<mirror::DexCache> dex_cache,
- Handle<mirror::ClassLoader> class_loader,
- const dex::ClassDef& class_def,
- const dex::CodeItem* code_item,
- uint32_t method_access_flags,
- uint32_t api_level) {
- impl::MethodVerifier<false>* verifier = new impl::MethodVerifier<false>(
+void MethodVerifier::VerifyMethodAndDump(Thread* self,
+ VariableIndentationOutputStream* vios,
+ uint32_t dex_method_idx,
+ const DexFile* dex_file,
+ Handle<mirror::DexCache> dex_cache,
+ Handle<mirror::ClassLoader> class_loader,
+ const dex::ClassDef& class_def,
+ const dex::CodeItem* code_item,
+ uint32_t method_access_flags,
+ uint32_t api_level) {
+ Runtime* runtime = Runtime::Current();
+ ClassLinker* class_linker = runtime->GetClassLinker();
+ ArenaPool* arena_pool = runtime->GetArenaPool();
+ RegTypeCache reg_types(self, class_linker, arena_pool);
+ impl::MethodVerifier<false> verifier(
self,
- Runtime::Current()->GetClassLinker(),
- Runtime::Current()->GetArenaPool(),
+ arena_pool,
+ &reg_types,
/* verifier_deps= */ nullptr,
dex_file,
code_item,
dex_method_idx,
- /* can_load_classes= */ true,
- /* allow_thread_suspension= */ true,
- Runtime::Current()->IsAotCompiler(),
+ runtime->IsAotCompiler(),
dex_cache,
class_loader,
class_def,
method_access_flags,
/* verify_to_dump= */ true,
api_level);
- verifier->Verify();
- verifier->DumpFailures(vios->Stream());
- vios->Stream() << verifier->info_messages_.str();
- // Only dump and return if no hard failures. Otherwise the verifier may be not fully initialized
+ verifier.Verify();
+ verifier.DumpFailures(vios->Stream());
+ vios->Stream() << verifier.info_messages_.str();
+ // Only dump if no hard failures. Otherwise the verifier may be not fully initialized
// and querying any info is dangerous/can abort.
- if (verifier->flags_.have_pending_hard_failure_) {
- delete verifier;
- return nullptr;
- } else {
- verifier->Dump(vios);
- return verifier;
+ if (!verifier.flags_.have_pending_hard_failure_) {
+ verifier.Dump(vios);
}
}
@@ -5189,19 +5183,23 @@ void MethodVerifier::FindLocksAtDexPc(
uint32_t dex_pc,
std::vector<MethodVerifier::DexLockInfo>* monitor_enter_dex_pcs,
uint32_t api_level) {
- StackHandleScope<2> hs(Thread::Current());
+ Thread* self = Thread::Current();
+ StackHandleScope<2> hs(self);
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(),
- Runtime::Current()->GetArenaPool(),
+ Runtime* runtime = Runtime::Current();
+ ClassLinker* class_linker = runtime->GetClassLinker();
+ ArenaPool* arena_pool = runtime->GetArenaPool();
+ RegTypeCache reg_types(
+ self, class_linker, arena_pool, /* can_load_classes= */ false, /* can_suspend= */ false);
+ impl::MethodVerifier<false> verifier(self,
+ arena_pool,
+ &reg_types,
/* verifier_deps= */ nullptr,
m->GetDexFile(),
m->GetCodeItem(),
m->GetDexMethodIndex(),
- /* can_load_classes= */ false,
- /* allow_thread_suspension= */ false,
- Runtime::Current()->IsAotCompiler(),
+ runtime->IsAotCompiler(),
dex_cache,
class_loader,
m->GetClassDef(),
@@ -5214,6 +5212,7 @@ void MethodVerifier::FindLocksAtDexPc(
}
MethodVerifier* MethodVerifier::CreateVerifier(Thread* self,
+ RegTypeCache* reg_types,
VerifierDeps* verifier_deps,
const DexFile* dex_file,
Handle<mirror::DexCache> dex_cache,
@@ -5222,19 +5221,15 @@ MethodVerifier* MethodVerifier::CreateVerifier(Thread* self,
const dex::CodeItem* code_item,
uint32_t method_idx,
uint32_t access_flags,
- bool can_load_classes,
bool verify_to_dump,
- bool allow_thread_suspension,
uint32_t api_level) {
return new impl::MethodVerifier<false>(self,
- Runtime::Current()->GetClassLinker(),
Runtime::Current()->GetArenaPool(),
+ reg_types,
verifier_deps,
dex_file,
code_item,
method_idx,
- can_load_classes,
- allow_thread_suspension,
Runtime::Current()->IsAotCompiler(),
dex_cache,
class_loader,
diff --git a/runtime/verifier/method_verifier.h b/runtime/verifier/method_verifier.h
index 5caa0ba363..e12a2f8fb1 100644
--- a/runtime/verifier/method_verifier.h
+++ b/runtime/verifier/method_verifier.h
@@ -32,7 +32,6 @@
#include "dex/method_reference.h"
#include "handle.h"
#include "instruction_flags.h"
-#include "reg_type_cache.h"
#include "register_line.h"
#include "verifier_enums.h"
@@ -51,6 +50,7 @@ struct CodeItem;
} // namespace dex
namespace mirror {
+class ClassLoader;
class DexCache;
} // namespace mirror
@@ -60,6 +60,7 @@ class MethodVerifier;
class RegisterLine;
using RegisterLineArenaUniquePtr = std::unique_ptr<RegisterLine, RegisterLineArenaDelete>;
class RegType;
+class RegTypeCache;
struct ScopedNewLine;
class VerifierDeps;
@@ -97,21 +98,22 @@ class PcToRegisterLineTable {
// The verifier
class MethodVerifier {
public:
- EXPORT static MethodVerifier* VerifyMethodAndDump(Thread* self,
- VariableIndentationOutputStream* vios,
- uint32_t method_idx,
- const DexFile* dex_file,
- Handle<mirror::DexCache> dex_cache,
- Handle<mirror::ClassLoader> class_loader,
- const dex::ClassDef& class_def,
- const dex::CodeItem* code_item,
- uint32_t method_access_flags,
- uint32_t api_level)
+ EXPORT static void VerifyMethodAndDump(Thread* self,
+ VariableIndentationOutputStream* vios,
+ uint32_t method_idx,
+ const DexFile* dex_file,
+ Handle<mirror::DexCache> dex_cache,
+ Handle<mirror::ClassLoader> class_loader,
+ const dex::ClassDef& class_def,
+ const dex::CodeItem* code_item,
+ uint32_t method_access_flags,
+ uint32_t api_level)
REQUIRES_SHARED(Locks::mutator_lock_);
// Calculates the type information at the given `dex_pc`.
// No classes will be loaded.
EXPORT static MethodVerifier* CalculateVerificationInfo(Thread* self,
+ RegTypeCache* reg_types,
ArtMethod* method,
Handle<mirror::DexCache> dex_cache,
Handle<mirror::ClassLoader> class_loader,
@@ -175,9 +177,7 @@ class MethodVerifier {
return encountered_failure_types_;
}
- ClassLinker* GetClassLinker() const {
- return reg_types_.GetClassLinker();
- }
+ ClassLinker* GetClassLinker() const;
bool IsAotMode() const {
return const_flags_.aot_mode_;
@@ -193,15 +193,13 @@ class MethodVerifier {
protected:
MethodVerifier(Thread* self,
- ClassLinker* class_linker,
ArenaPool* arena_pool,
+ RegTypeCache* reg_types,
VerifierDeps* verifier_deps,
const DexFile* dex_file,
const dex::ClassDef& class_def,
const dex::CodeItem* code_item,
uint32_t dex_method_idx,
- bool can_load_classes,
- bool allow_thread_suspension,
bool aot_mode)
REQUIRES_SHARED(Locks::mutator_lock_);
@@ -227,8 +225,8 @@ class MethodVerifier {
* for code flow problems.
*/
static FailureData VerifyMethod(Thread* self,
- ClassLinker* class_linker,
ArenaPool* arena_pool,
+ RegTypeCache* reg_types,
VerifierDeps* verifier_deps,
uint32_t method_idx,
const DexFile* dex_file,
@@ -245,8 +243,8 @@ class MethodVerifier {
template <bool kVerifierDebug>
static FailureData VerifyMethod(Thread* self,
- ClassLinker* class_linker,
ArenaPool* arena_pool,
+ RegTypeCache* reg_types,
VerifierDeps* verifier_deps,
uint32_t method_idx,
const DexFile* dex_file,
@@ -267,6 +265,7 @@ class MethodVerifier {
// has an irrecoverable corruption.
virtual bool Verify() REQUIRES_SHARED(Locks::mutator_lock_) = 0;
static MethodVerifier* CreateVerifier(Thread* self,
+ RegTypeCache* reg_types,
VerifierDeps* verifier_deps,
const DexFile* dex_file,
Handle<mirror::DexCache> dex_cache,
@@ -275,9 +274,7 @@ class MethodVerifier {
const dex::CodeItem* code_item,
uint32_t method_idx,
uint32_t access_flags,
- bool can_load_classes,
bool verify_to_dump,
- bool allow_thread_suspension,
uint32_t api_level)
REQUIRES_SHARED(Locks::mutator_lock_);
@@ -290,7 +287,7 @@ class MethodVerifier {
ArenaStack arena_stack_;
ScopedArenaAllocator allocator_;
- RegTypeCache reg_types_;
+ RegTypeCache& reg_types_; // TODO: Change to a pointer in a separate CL.
PcToRegisterLineTable reg_table_;
diff --git a/runtime/verifier/reg_type_cache-inl.h b/runtime/verifier/reg_type_cache-inl.h
index addf958472..40abf27041 100644
--- a/runtime/verifier/reg_type_cache-inl.h
+++ b/runtime/verifier/reg_type_cache-inl.h
@@ -18,7 +18,6 @@
#define ART_RUNTIME_VERIFIER_REG_TYPE_CACHE_INL_H_
#include "base/bit_vector-inl.h"
-#include "class_linker.h"
#include "class_root-inl.h"
#include "mirror/class-inl.h"
#include "mirror/method_handle_impl.h"
diff --git a/runtime/verifier/reg_type_cache.cc b/runtime/verifier/reg_type_cache.cc
index 71a6f3f318..b435b01d02 100644
--- a/runtime/verifier/reg_type_cache.cc
+++ b/runtime/verifier/reg_type_cache.cc
@@ -283,15 +283,17 @@ const RegType& RegTypeCache::FromClass(const char* descriptor,
RegTypeCache::RegTypeCache(Thread* self,
ClassLinker* class_linker,
+ ArenaPool* arena_pool,
bool can_load_classes,
- ScopedArenaAllocator& allocator,
bool can_suspend)
- : entries_(allocator.Adapter(kArenaAllocVerifier)),
- klass_entries_(allocator.Adapter(kArenaAllocVerifier)),
- allocator_(allocator),
+ : arena_stack_(arena_pool),
+ allocator_(&arena_stack_),
+ entries_(allocator_.Adapter(kArenaAllocVerifier)),
+ klass_entries_(allocator_.Adapter(kArenaAllocVerifier)),
handles_(self),
class_linker_(class_linker),
- can_load_classes_(can_load_classes) {
+ can_load_classes_(can_load_classes),
+ can_suspend_(can_suspend) {
DCHECK(can_suspend || !can_load_classes) << "Cannot load classes if suspension is disabled!";
if (kIsDebugBuild && can_suspend) {
Thread::Current()->AssertThreadSuspensionIsAllowable(gAborting == 0);
diff --git a/runtime/verifier/reg_type_cache.h b/runtime/verifier/reg_type_cache.h
index d9d3ddc2a2..106d12340a 100644
--- a/runtime/verifier/reg_type_cache.h
+++ b/runtime/verifier/reg_type_cache.h
@@ -66,11 +66,20 @@ static constexpr size_t kDefaultArenaBitVectorBytes = 8;
class RegTypeCache {
public:
- RegTypeCache(Thread* self,
- ClassLinker* class_linker,
- bool can_load_classes,
- ScopedArenaAllocator& allocator,
- bool can_suspend = true);
+ EXPORT RegTypeCache(Thread* self,
+ ClassLinker* class_linker,
+ ArenaPool* arena_pool,
+ bool can_load_classes = true,
+ bool can_suspend = true);
+
+ bool CanLoadClasses() const {
+ return can_load_classes_;
+ }
+
+ bool CanSuspend() const {
+ return can_suspend_;
+ }
+
const art::verifier::RegType& GetFromId(uint16_t id) const;
// Find a RegType, returns null if not found.
const RegType* FindClass(ObjPtr<mirror::Class> klass, bool precise) const
@@ -195,15 +204,16 @@ class RegTypeCache {
// verifier and return a string view.
std::string_view AddString(const std::string_view& str);
+ // Arena allocator.
+ ArenaStack arena_stack_;
+ ScopedArenaAllocator allocator_;
+
// The actual storage for the RegTypes.
ScopedArenaVector<const RegType*> entries_;
// Fast lookup for quickly finding entries that have a matching class.
ScopedArenaVector<std::pair<Handle<mirror::Class>, const RegType*>> klass_entries_;
- // Arena allocator.
- ScopedArenaAllocator& allocator_;
-
// Handle scope containing classes.
VariableSizedHandleScope handles_;
ScopedNullHandle<mirror::Class> null_handle_;
@@ -213,6 +223,9 @@ class RegTypeCache {
// Whether or not we're allowed to load classes.
const bool can_load_classes_;
+ // Whether or not we're allowed to suspend.
+ const bool can_suspend_;
+
DISALLOW_COPY_AND_ASSIGN(RegTypeCache);
};
diff --git a/runtime/verifier/reg_type_test.cc b/runtime/verifier/reg_type_test.cc
index b9d618f16e..ec7fc45e4f 100644
--- a/runtime/verifier/reg_type_test.cc
+++ b/runtime/verifier/reg_type_test.cc
@@ -53,11 +53,9 @@ class RegTypeTest : public CommonRuntimeTest {
TEST_F(RegTypeTest, ConstLoHi) {
// Tests creating primitive types types.
- ArenaStack stack(Runtime::Current()->GetArenaPool());
- ScopedArenaAllocator allocator(&stack);
+ ArenaPool* arena_pool = Runtime::Current()->GetArenaPool();
ScopedObjectAccess soa(Thread::Current());
- RegTypeCache cache(
- soa.Self(), Runtime::Current()->GetClassLinker(), /* can_load_classes= */ true, allocator);
+ RegTypeCache cache(soa.Self(), Runtime::Current()->GetClassLinker(), arena_pool);
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);
@@ -78,11 +76,9 @@ TEST_F(RegTypeTest, ConstLoHi) {
}
TEST_F(RegTypeTest, Pairs) {
- ArenaStack stack(Runtime::Current()->GetArenaPool());
- ScopedArenaAllocator allocator(&stack);
+ ArenaPool* arena_pool = Runtime::Current()->GetArenaPool();
ScopedObjectAccess soa(Thread::Current());
- RegTypeCache cache(
- soa.Self(), Runtime::Current()->GetClassLinker(), /* can_load_classes= */ true, allocator);
+ RegTypeCache cache(soa.Self(), Runtime::Current()->GetClassLinker(), arena_pool);
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);
@@ -105,11 +101,9 @@ TEST_F(RegTypeTest, Pairs) {
}
TEST_F(RegTypeTest, Primitives) {
- ArenaStack stack(Runtime::Current()->GetArenaPool());
- ScopedArenaAllocator allocator(&stack);
+ ArenaPool* arena_pool = Runtime::Current()->GetArenaPool();
ScopedObjectAccess soa(Thread::Current());
- RegTypeCache cache(
- soa.Self(), Runtime::Current()->GetClassLinker(), /* can_load_classes= */ true, allocator);
+ RegTypeCache cache(soa.Self(), Runtime::Current()->GetClassLinker(), arena_pool);
const RegType& bool_reg_type = cache.Boolean();
EXPECT_FALSE(bool_reg_type.IsUndefined());
@@ -381,12 +375,10 @@ class RegTypeReferenceTest : public RegTypeTest {};
TEST_F(RegTypeReferenceTest, JavaLangObjectImprecise) {
// Tests matching precisions. A reference type that was created precise doesn't
// match the one that is imprecise.
- ArenaStack stack(Runtime::Current()->GetArenaPool());
- ScopedArenaAllocator allocator(&stack);
+ ArenaPool* arena_pool = Runtime::Current()->GetArenaPool();
ScopedObjectAccess soa(Thread::Current());
ScopedNullHandle<mirror::ClassLoader> loader;
- RegTypeCache cache(
- soa.Self(), Runtime::Current()->GetClassLinker(), /* can_load_classes= */ true, allocator);
+ RegTypeCache cache(soa.Self(), Runtime::Current()->GetClassLinker(), arena_pool);
const RegType& imprecise_obj = cache.JavaLangObject(false);
const RegType& precise_obj = cache.JavaLangObject(true);
const RegType& precise_obj_2 = PreciseJavaLangObjectFromDescriptor(&cache, loader);
@@ -400,12 +392,10 @@ TEST_F(RegTypeReferenceTest, JavaLangObjectImprecise) {
TEST_F(RegTypeReferenceTest, UnresolvedType) {
// Tests creating unresolved types. Miss for the first time asking the cache and
// a hit second time.
- ArenaStack stack(Runtime::Current()->GetArenaPool());
- ScopedArenaAllocator allocator(&stack);
+ ArenaPool* arena_pool = Runtime::Current()->GetArenaPool();
ScopedObjectAccess soa(Thread::Current());
ScopedNullHandle<mirror::ClassLoader> loader;
- RegTypeCache cache(
- soa.Self(), Runtime::Current()->GetClassLinker(), /* can_load_classes= */ true, allocator);
+ RegTypeCache cache(soa.Self(), Runtime::Current()->GetClassLinker(), arena_pool);
const RegType& ref_type_0 = cache.FromDescriptor(loader, "Ljava/lang/DoesNotExist;");
EXPECT_TRUE(ref_type_0.IsUnresolvedReference());
EXPECT_TRUE(ref_type_0.IsNonZeroReferenceTypes());
@@ -420,12 +410,10 @@ TEST_F(RegTypeReferenceTest, UnresolvedType) {
TEST_F(RegTypeReferenceTest, UnresolvedUnintializedType) {
// Tests creating types uninitialized types from unresolved types.
- ArenaStack stack(Runtime::Current()->GetArenaPool());
- ScopedArenaAllocator allocator(&stack);
+ ArenaPool* arena_pool = Runtime::Current()->GetArenaPool();
ScopedObjectAccess soa(Thread::Current());
ScopedNullHandle<mirror::ClassLoader> loader;
- RegTypeCache cache(
- soa.Self(), Runtime::Current()->GetClassLinker(), /* can_load_classes= */ true, allocator);
+ RegTypeCache cache(soa.Self(), Runtime::Current()->GetClassLinker(), arena_pool);
const RegType& ref_type_0 = cache.FromDescriptor(loader, "Ljava/lang/DoesNotExist;");
EXPECT_TRUE(ref_type_0.IsUnresolvedReference());
const RegType& ref_type = cache.FromDescriptor(loader, "Ljava/lang/DoesNotExist;");
@@ -446,12 +434,10 @@ TEST_F(RegTypeReferenceTest, UnresolvedUnintializedType) {
TEST_F(RegTypeReferenceTest, Dump) {
// Tests types for proper Dump messages.
- ArenaStack stack(Runtime::Current()->GetArenaPool());
- ScopedArenaAllocator allocator(&stack);
+ ArenaPool* arena_pool = Runtime::Current()->GetArenaPool();
ScopedObjectAccess soa(Thread::Current());
ScopedNullHandle<mirror::ClassLoader> loader;
- RegTypeCache cache(
- soa.Self(), Runtime::Current()->GetClassLinker(), /* can_load_classes= */ true, allocator);
+ RegTypeCache cache(soa.Self(), Runtime::Current()->GetClassLinker(), arena_pool);
const RegType& unresolved_ref = cache.FromDescriptor(loader, "Ljava/lang/DoesNotExist;");
const RegType& unresolved_ref_another =
cache.FromDescriptor(loader, "Ljava/lang/DoesNotExistEither;");
@@ -477,12 +463,10 @@ TEST_F(RegTypeReferenceTest, JavalangString) {
// Add a class to the cache then look for the same class and make sure it is a
// Hit the second time. Then check for the same effect when using
// The JavaLangObject method instead of FromDescriptor. String class is final.
- ArenaStack stack(Runtime::Current()->GetArenaPool());
- ScopedArenaAllocator allocator(&stack);
+ ArenaPool* arena_pool = Runtime::Current()->GetArenaPool();
ScopedObjectAccess soa(Thread::Current());
ScopedNullHandle<mirror::ClassLoader> loader;
- RegTypeCache cache(
- soa.Self(), Runtime::Current()->GetClassLinker(), /* can_load_classes= */ true, allocator);
+ RegTypeCache cache(soa.Self(), Runtime::Current()->GetClassLinker(), arena_pool);
const RegType& ref_type = cache.JavaLangString();
const RegType& ref_type_2 = cache.JavaLangString();
const RegType& ref_type_3 = cache.FromDescriptor(loader, "Ljava/lang/String;");
@@ -501,12 +485,10 @@ TEST_F(RegTypeReferenceTest, JavalangObject) {
// Add a class to the cache then look for the same class and make sure it is a
// Hit the second time. Then I am checking for the same effect when using
// The JavaLangObject method instead of FromDescriptor. Object Class in not final.
- ArenaStack stack(Runtime::Current()->GetArenaPool());
- ScopedArenaAllocator allocator(&stack);
+ ArenaPool* arena_pool = Runtime::Current()->GetArenaPool();
ScopedObjectAccess soa(Thread::Current());
ScopedNullHandle<mirror::ClassLoader> loader;
- RegTypeCache cache(
- soa.Self(), Runtime::Current()->GetClassLinker(), /* can_load_classes= */ true, allocator);
+ RegTypeCache cache(soa.Self(), Runtime::Current()->GetClassLinker(), arena_pool);
const RegType& ref_type = cache.JavaLangObject(true);
const RegType& ref_type_2 = cache.JavaLangObject(true);
const RegType& ref_type_3 = PreciseJavaLangObjectFromDescriptor(&cache, loader);
@@ -519,11 +501,9 @@ TEST_F(RegTypeReferenceTest, Merging) {
// Tests merging logic
// String and object , LUB is object.
ScopedObjectAccess soa(Thread::Current());
- ArenaStack stack(Runtime::Current()->GetArenaPool());
- ScopedArenaAllocator allocator(&stack);
+ ArenaPool* arena_pool = Runtime::Current()->GetArenaPool();
ScopedNullHandle<mirror::ClassLoader> loader;
- RegTypeCache cache_new(
- soa.Self(), Runtime::Current()->GetClassLinker(), /* can_load_classes= */ true, allocator);
+ RegTypeCache cache_new(soa.Self(), Runtime::Current()->GetClassLinker(), arena_pool);
const RegType& string = cache_new.JavaLangString();
const RegType& Object = cache_new.JavaLangObject(true);
EXPECT_TRUE(string.Merge(Object, &cache_new, /* verifier= */ nullptr).IsJavaLangObject());
@@ -545,11 +525,9 @@ TEST_F(RegTypeReferenceTest, Merging) {
TEST_F(RegTypeTest, MergingFloat) {
// Testing merging logic with float and float constants.
- ArenaStack stack(Runtime::Current()->GetArenaPool());
- ScopedArenaAllocator allocator(&stack);
+ ArenaPool* arena_pool = Runtime::Current()->GetArenaPool();
ScopedObjectAccess soa(Thread::Current());
- RegTypeCache cache_new(
- soa.Self(), Runtime::Current()->GetClassLinker(), /* can_load_classes= */ true, allocator);
+ RegTypeCache cache_new(soa.Self(), Runtime::Current()->GetClassLinker(), arena_pool);
constexpr int32_t kTestConstantValue = 10;
const RegType& float_type = cache_new.Float();
@@ -579,11 +557,9 @@ TEST_F(RegTypeTest, MergingFloat) {
TEST_F(RegTypeTest, MergingLong) {
// Testing merging logic with long and long constants.
- ArenaStack stack(Runtime::Current()->GetArenaPool());
- ScopedArenaAllocator allocator(&stack);
+ ArenaPool* arena_pool = Runtime::Current()->GetArenaPool();
ScopedObjectAccess soa(Thread::Current());
- RegTypeCache cache_new(
- soa.Self(), Runtime::Current()->GetClassLinker(), /* can_load_classes= */ true, allocator);
+ RegTypeCache cache_new(soa.Self(), Runtime::Current()->GetClassLinker(), arena_pool);
constexpr int32_t kTestConstantValue = 10;
const RegType& long_lo_type = cache_new.LongLo();
@@ -640,11 +616,9 @@ TEST_F(RegTypeTest, MergingLong) {
TEST_F(RegTypeTest, MergingDouble) {
// Testing merging logic with double and double constants.
- ArenaStack stack(Runtime::Current()->GetArenaPool());
- ScopedArenaAllocator allocator(&stack);
+ ArenaPool* arena_pool = Runtime::Current()->GetArenaPool();
ScopedObjectAccess soa(Thread::Current());
- RegTypeCache cache_new(
- soa.Self(), Runtime::Current()->GetClassLinker(), /* can_load_classes= */ true, allocator);
+ RegTypeCache cache_new(soa.Self(), Runtime::Current()->GetClassLinker(), arena_pool);
constexpr int32_t kTestConstantValue = 10;
const RegType& double_lo_type = cache_new.DoubleLo();
@@ -752,15 +726,13 @@ TEST_F(RegTypeTest, MergeSemiLatticeRef) {
// |
// 0
- ArenaStack stack(Runtime::Current()->GetArenaPool());
- ScopedArenaAllocator allocator(&stack);
+ ArenaPool* arena_pool = Runtime::Current()->GetArenaPool();
ScopedObjectAccess soa(Thread::Current());
ScopedDisableMovingGC no_gc(soa.Self());
ScopedNullHandle<mirror::ClassLoader> loader;
- RegTypeCache cache(
- soa.Self(), Runtime::Current()->GetClassLinker(), /* can_load_classes= */ true, allocator);
+ RegTypeCache cache(soa.Self(), Runtime::Current()->GetClassLinker(), arena_pool);
const RegType& conflict = cache.Conflict();
const RegType& zero = cache.Zero();
@@ -1081,11 +1053,9 @@ TEST_F(RegTypeTest, MergeSemiLatticeRef) {
TEST_F(RegTypeTest, ConstPrecision) {
// Tests creating primitive types types.
- ArenaStack stack(Runtime::Current()->GetArenaPool());
- ScopedArenaAllocator allocator(&stack);
+ ArenaPool* arena_pool = Runtime::Current()->GetArenaPool();
ScopedObjectAccess soa(Thread::Current());
- RegTypeCache cache_new(
- soa.Self(), Runtime::Current()->GetClassLinker(), /* can_load_classes= */ true, allocator);
+ RegTypeCache cache_new(soa.Self(), Runtime::Current()->GetClassLinker(), arena_pool);
const RegType& imprecise_const = cache_new.FromCat1Const(10, false);
const RegType& precise_const = cache_new.FromCat1Const(10, true);
@@ -1110,8 +1080,7 @@ TEST_F(RegTypeOOMTest, ClassJoinOOM) {
// Tests that we don't abort with OOMs.
- ArenaStack stack(Runtime::Current()->GetArenaPool());
- ScopedArenaAllocator allocator(&stack);
+ ArenaPool* arena_pool = Runtime::Current()->GetArenaPool();
ScopedObjectAccess soa(Thread::Current());
ScopedDisableMovingGC no_gc(soa.Self());
@@ -1125,8 +1094,7 @@ TEST_F(RegTypeOOMTest, ClassJoinOOM) {
constexpr const char* kNumberArrayFive = "[[[[[Ljava/lang/Number;";
ScopedNullHandle<mirror::ClassLoader> loader;
- RegTypeCache cache(
- soa.Self(), Runtime::Current()->GetClassLinker(), /* can_load_classes= */ true, allocator);
+ RegTypeCache cache(soa.Self(), Runtime::Current()->GetClassLinker(), arena_pool);
const RegType& int_array_array = cache.FromDescriptor(loader, kIntArrayFive);
ASSERT_TRUE(int_array_array.HasClass());
const RegType& float_array_array = cache.FromDescriptor(loader, kFloatArrayFive);
@@ -1148,8 +1116,7 @@ TEST_F(RegTypeOOMTest, ClassJoinOOM) {
class RegTypeClassJoinTest : public RegTypeTest {
protected:
void TestClassJoin(const char* in1, const char* in2, const char* out) {
- ArenaStack stack(Runtime::Current()->GetArenaPool());
- ScopedArenaAllocator allocator(&stack);
+ ArenaPool* arena_pool = Runtime::Current()->GetArenaPool();
ScopedObjectAccess soa(Thread::Current());
jobject jclass_loader = LoadDex("Interfaces");
@@ -1166,8 +1133,7 @@ class RegTypeClassJoinTest : public RegTypeTest {
ScopedDisableMovingGC no_gc(soa.Self());
- RegTypeCache cache(
- soa.Self(), Runtime::Current()->GetClassLinker(), /* can_load_classes= */ true, allocator);
+ RegTypeCache cache(soa.Self(), Runtime::Current()->GetClassLinker(), arena_pool);
const RegType& c1_reg_type = *cache.InsertClass(in1, c1.Get(), false);
const RegType& c2_reg_type = *cache.InsertClass(in2, c2.Get(), false);