Explictly pass VerifierDeps when asking for class verification.
This will simplify creating and populating VerifierDeps at runtime,
which is needed for doing and saving background verifcation of secondary
dex files.
Test: test.py
Bug: 158463186
Change-Id: Ic17913ebd173700e866ba9309bf6ae131fcbc423
diff --git a/dex2oat/driver/compiler_driver.cc b/dex2oat/driver/compiler_driver.cc
index 9d14608..c94c57f 100644
--- a/dex2oat/driver/compiler_driver.cc
+++ b/dex2oat/driver/compiler_driver.cc
@@ -1899,6 +1899,7 @@
std::string error_msg;
failure_kind =
verifier::ClassVerifier::VerifyClass(soa.Self(),
+ soa.Self()->GetVerifierDeps(),
&dex_file,
dex_cache,
class_loader,
@@ -1938,7 +1939,10 @@
return; // Do not update state.
} else if (!SkipClass(jclass_loader, dex_file, klass.Get())) {
CHECK(klass->IsResolved()) << klass->PrettyClass();
- failure_kind = class_linker->VerifyClass(soa.Self(), klass, log_level_);
+ failure_kind = class_linker->VerifyClass(soa.Self(),
+ soa.Self()->GetVerifierDeps(),
+ klass,
+ log_level_);
if (klass->IsErroneous()) {
// ClassLinker::VerifyClass throws, which isn't useful in the compiler.
@@ -1994,7 +1998,10 @@
// Make the skip a soft failure, essentially being considered as verify at runtime.
failure_kind = verifier::FailureKind::kSoftFailure;
}
- verifier::VerifierDeps::MaybeRecordVerificationStatus(dex_file, class_def, failure_kind);
+ verifier::VerifierDeps::MaybeRecordVerificationStatus(soa.Self()->GetVerifierDeps(),
+ dex_file,
+ class_def,
+ failure_kind);
soa.Self()->AssertNoPendingException();
}
diff --git a/dex2oat/verifier_deps_test.cc b/dex2oat/verifier_deps_test.cc
index f37248d..e833180 100644
--- a/dex2oat/verifier_deps_test.cc
+++ b/dex2oat/verifier_deps_test.cc
@@ -163,9 +163,9 @@
method.GetInvokeType(class_def->access_flags_));
CHECK(resolved_method != nullptr);
if (method_name == resolved_method->GetName()) {
- soa.Self()->SetVerifierDeps(callbacks_->GetVerifierDeps());
std::unique_ptr<MethodVerifier> verifier(
MethodVerifier::CreateVerifier(soa.Self(),
+ callbacks_->GetVerifierDeps(),
primary_dex_file_,
dex_cache_handle,
class_loader_handle,
@@ -547,25 +547,23 @@
ASSERT_GT(dex_files.size(), 0u);
const DexFile* dex_file = dex_files[0];
VerifierDeps deps1(dex_files);
- Thread* const self = Thread::Current();
- ASSERT_TRUE(self->GetVerifierDeps() == nullptr);
- self->SetVerifierDeps(&deps1);
- deps1.MaybeRecordVerificationStatus(*dex_file,
+ deps1.MaybeRecordVerificationStatus(&deps1,
+ *dex_file,
dex_file->GetClassDef(0u),
verifier::FailureKind::kHardFailure);
- deps1.MaybeRecordVerificationStatus(*dex_file,
+ deps1.MaybeRecordVerificationStatus(&deps1,
+ *dex_file,
dex_file->GetClassDef(1u),
verifier::FailureKind::kHardFailure);
VerifierDeps deps2(dex_files);
- self->SetVerifierDeps(nullptr);
- self->SetVerifierDeps(&deps2);
- deps2.MaybeRecordVerificationStatus(*dex_file,
+ deps2.MaybeRecordVerificationStatus(&deps2,
+ *dex_file,
dex_file->GetClassDef(1u),
verifier::FailureKind::kHardFailure);
- deps2.MaybeRecordVerificationStatus(*dex_file,
+ deps2.MaybeRecordVerificationStatus(&deps2,
+ *dex_file,
dex_file->GetClassDef(0u),
verifier::FailureKind::kHardFailure);
- self->SetVerifierDeps(nullptr);
std::vector<uint8_t> buffer1;
deps1.Encode(dex_files, &buffer1);
std::vector<uint8_t> buffer2;
diff --git a/openjdkjvmti/ti_redefine.cc b/openjdkjvmti/ti_redefine.cc
index 487d9da..b2b839b 100644
--- a/openjdkjvmti/ti_redefine.cc
+++ b/openjdkjvmti/ti_redefine.cc
@@ -1613,6 +1613,7 @@
// TODO Make verification log level lower
art::verifier::FailureKind failure =
art::verifier::ClassVerifier::VerifyClass(driver_->self_,
+ /*verifier_deps=*/nullptr,
dex_file_.get(),
hs.NewHandle(iter.GetNewDexCache()),
hs.NewHandle(GetClassLoader()),
diff --git a/runtime/aot_class_linker.cc b/runtime/aot_class_linker.cc
index 5059466..5d8b61d 100644
--- a/runtime/aot_class_linker.cc
+++ b/runtime/aot_class_linker.cc
@@ -103,10 +103,12 @@
return success;
}
-verifier::FailureKind AotClassLinker::PerformClassVerification(Thread* self,
- Handle<mirror::Class> klass,
- verifier::HardFailLogMode log_level,
- std::string* error_msg) {
+verifier::FailureKind AotClassLinker::PerformClassVerification(
+ Thread* self,
+ verifier::VerifierDeps* verifier_deps,
+ Handle<mirror::Class> klass,
+ verifier::HardFailLogMode log_level,
+ std::string* error_msg) {
Runtime* const runtime = Runtime::Current();
CompilerCallbacks* callbacks = runtime->GetCompilerCallbacks();
ClassStatus old_status = callbacks->GetPreviousClassState(
@@ -125,7 +127,7 @@
return verifier::FailureKind::kSoftFailure;
}
// Do the actual work.
- return ClassLinker::PerformClassVerification(self, klass, log_level, error_msg);
+ return ClassLinker::PerformClassVerification(self, verifier_deps, klass, log_level, error_msg);
}
bool AotClassLinker::CanReferenceInBootImageExtension(ObjPtr<mirror::Class> klass, gc::Heap* heap) {
diff --git a/runtime/aot_class_linker.h b/runtime/aot_class_linker.h
index a094e3a..9be8869 100644
--- a/runtime/aot_class_linker.h
+++ b/runtime/aot_class_linker.h
@@ -52,6 +52,7 @@
// Overridden version of PerformClassVerification allows skipping verification if the class was
// previously verified but unloaded.
verifier::FailureKind PerformClassVerification(Thread* self,
+ verifier::VerifierDeps* verifier_deps,
Handle<mirror::Class> klass,
verifier::HardFailLogMode log_level,
std::string* error_msg)
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 11b5480..e894037 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -4464,6 +4464,7 @@
}
bool ClassLinker::AttemptSupertypeVerification(Thread* self,
+ verifier::VerifierDeps* verifier_deps,
Handle<mirror::Class> klass,
Handle<mirror::Class> supertype) {
DCHECK(self != nullptr);
@@ -4471,7 +4472,7 @@
DCHECK(supertype != nullptr);
if (!supertype->IsVerified() && !supertype->IsErroneous()) {
- VerifyClass(self, supertype);
+ VerifyClass(self, verifier_deps, supertype);
}
if (supertype->IsVerified()
@@ -4508,8 +4509,10 @@
return false;
}
-verifier::FailureKind ClassLinker::VerifyClass(
- Thread* self, Handle<mirror::Class> klass, verifier::HardFailLogMode log_level) {
+verifier::FailureKind ClassLinker::VerifyClass(Thread* self,
+ verifier::VerifierDeps* verifier_deps,
+ Handle<mirror::Class> klass,
+ verifier::HardFailLogMode log_level) {
{
// TODO: assert that the monitor on the Class is held
ObjectLock<mirror::Class> lock(self, klass);
@@ -4577,7 +4580,8 @@
StackHandleScope<2> hs(self);
MutableHandle<mirror::Class> supertype(hs.NewHandle(klass->GetSuperClass()));
// If we have a superclass and we get a hard verification failure we can return immediately.
- if (supertype != nullptr && !AttemptSupertypeVerification(self, klass, supertype)) {
+ if (supertype != nullptr &&
+ !AttemptSupertypeVerification(self, verifier_deps, klass, supertype)) {
CHECK(self->IsExceptionPending()) << "Verification error should be pending.";
return verifier::FailureKind::kHardFailure;
}
@@ -4603,7 +4607,7 @@
// We only care if we have default interfaces and can skip if we are already verified...
if (LIKELY(!iface->HasDefaultMethods() || iface->IsVerified())) {
continue;
- } else if (UNLIKELY(!AttemptSupertypeVerification(self, klass, iface))) {
+ } else if (UNLIKELY(!AttemptSupertypeVerification(self, verifier_deps, klass, iface))) {
// We had a hard failure while verifying this interface. Just return immediately.
CHECK(self->IsExceptionPending()) << "Verification error should be pending.";
return verifier::FailureKind::kHardFailure;
@@ -4643,7 +4647,7 @@
std::string error_msg;
verifier::FailureKind verifier_failure = verifier::FailureKind::kNoFailure;
if (!preverified) {
- verifier_failure = PerformClassVerification(self, klass, log_level, &error_msg);
+ verifier_failure = PerformClassVerification(self, verifier_deps, klass, log_level, &error_msg);
}
// Verification is done, grab the lock again.
@@ -4728,11 +4732,13 @@
}
verifier::FailureKind ClassLinker::PerformClassVerification(Thread* self,
+ verifier::VerifierDeps* verifier_deps,
Handle<mirror::Class> klass,
verifier::HardFailLogMode log_level,
std::string* error_msg) {
Runtime* const runtime = Runtime::Current();
return verifier::ClassVerifier::VerifyClass(self,
+ verifier_deps,
klass.Get(),
runtime->GetCompilerCallbacks(),
runtime->IsAotCompiler(),
@@ -5233,7 +5239,7 @@
<< klass->PrettyClass() << ": state=" << klass->GetStatus();
if (!klass->IsVerified()) {
- VerifyClass(self, klass);
+ VerifyClass(self, /*verifier_deps= */ nullptr, klass);
if (!klass->IsVerified()) {
// We failed to verify, expect either the klass to be erroneous or verification failed at
// compile time.
diff --git a/runtime/class_linker.h b/runtime/class_linker.h
index 95dc6cf..d6e34ff 100644
--- a/runtime/class_linker.h
+++ b/runtime/class_linker.h
@@ -98,6 +98,10 @@
using MethodDexCacheType = std::atomic<MethodDexCachePair>;
} // namespace mirror
+namespace verifier {
+class VerifierDeps;
+}
+
class ClassVisitor {
public:
virtual ~ClassVisitor() {}
@@ -553,6 +557,7 @@
verifier::FailureKind VerifyClass(
Thread* self,
+ verifier::VerifierDeps* verifier_deps,
Handle<mirror::Class> klass,
verifier::HardFailLogMode log_level = verifier::HardFailLogMode::kLogNone)
REQUIRES_SHARED(Locks::mutator_lock_)
@@ -851,6 +856,7 @@
REQUIRES(!Locks::dex_lock_);
virtual verifier::FailureKind PerformClassVerification(Thread* self,
+ verifier::VerifierDeps* verifier_deps,
Handle<mirror::Class> klass,
verifier::HardFailLogMode log_level,
std::string* error_msg)
@@ -882,6 +888,7 @@
// appropriate exceptions if verification failed hard. Returns true for successful verification or
// soft-failures.
bool AttemptSupertypeVerification(Thread* self,
+ verifier::VerifierDeps* verifier_deps,
Handle<mirror::Class> klass,
Handle<mirror::Class> supertype)
REQUIRES(!Locks::dex_lock_)
diff --git a/runtime/jit/jit.cc b/runtime/jit/jit.cc
index d7583b1..0af9aa3 100644
--- a/runtime/jit/jit.cc
+++ b/runtime/jit/jit.cc
@@ -909,7 +909,8 @@
continue;
}
++number_of_classes;
- if (linker->VerifyClass(self, klass) == verifier::FailureKind::kHardFailure) {
+ if (linker->VerifyClass(self, /* verifier_deps= */ nullptr, klass) ==
+ verifier::FailureKind::kHardFailure) {
DCHECK(self->IsExceptionPending());
LOG(FATAL) << "Methods in the boot classpath failed to verify: "
<< self->GetException()->Dump();
diff --git a/runtime/oat_file_manager.cc b/runtime/oat_file_manager.cc
index 8a0f550..25a2413 100644
--- a/runtime/oat_file_manager.cc
+++ b/runtime/oat_file_manager.cc
@@ -735,7 +735,7 @@
}
CHECK(h_class->IsResolved()) << h_class->PrettyDescriptor();
- class_linker->VerifyClass(self, h_class);
+ class_linker->VerifyClass(self, &verifier_deps, h_class);
if (h_class->IsErroneous()) {
// ClassLinker::VerifyClass throws, which isn't useful here.
CHECK(soa.Self()->IsExceptionPending());
diff --git a/runtime/transaction_test.cc b/runtime/transaction_test.cc
index 2964427..91eafab 100644
--- a/runtime/transaction_test.cc
+++ b/runtime/transaction_test.cc
@@ -63,13 +63,13 @@
h_klass.Assign(class_linker_->FindClass(soa.Self(), "LTransaction$AbortHelperClass;",
class_loader));
ASSERT_TRUE(h_klass != nullptr);
- class_linker_->VerifyClass(soa.Self(), h_klass);
+ class_linker_->VerifyClass(soa.Self(), /* verifier_deps= */ nullptr, h_klass);
ASSERT_TRUE(h_klass->IsVerified());
// Load and verify tested class.
h_klass.Assign(class_linker_->FindClass(soa.Self(), tested_class_signature, class_loader));
ASSERT_TRUE(h_klass != nullptr);
- class_linker_->VerifyClass(soa.Self(), h_klass);
+ class_linker_->VerifyClass(soa.Self(), /* verifier_deps= */ nullptr, h_klass);
ASSERT_TRUE(h_klass->IsVerified());
ClassStatus old_status = h_klass->GetStatus();
@@ -543,7 +543,7 @@
hs.NewHandle(class_linker_->FindClass(soa.Self(), "LTransaction$EmptyStatic;",
class_loader)));
ASSERT_TRUE(h_klass != nullptr);
- class_linker_->VerifyClass(soa.Self(), h_klass);
+ class_linker_->VerifyClass(soa.Self(), /* verifier_deps= */ nullptr, h_klass);
ASSERT_TRUE(h_klass->IsVerified());
EnterTransactionMode();
@@ -566,7 +566,7 @@
hs.NewHandle(class_linker_->FindClass(soa.Self(), "LTransaction$StaticFieldClass;",
class_loader)));
ASSERT_TRUE(h_klass != nullptr);
- class_linker_->VerifyClass(soa.Self(), h_klass);
+ class_linker_->VerifyClass(soa.Self(), /* verifier_deps= */ nullptr, h_klass);
ASSERT_TRUE(h_klass->IsVerified());
EnterTransactionMode();
diff --git a/runtime/verifier/class_verifier.cc b/runtime/verifier/class_verifier.cc
index 5b6a07d..7559f98 100644
--- a/runtime/verifier/class_verifier.cc
+++ b/runtime/verifier/class_verifier.cc
@@ -113,6 +113,7 @@
};
DelayedVerifyCallback dvc;
FailureKind res = CommonVerifyClass(self,
+ /*verifier_deps=*/nullptr,
h_klass.Get(),
/*callbacks=*/nullptr,
&dvc,
@@ -128,6 +129,7 @@
}
FailureKind ClassVerifier::VerifyClass(Thread* self,
+ VerifierDeps* verifier_deps,
ObjPtr<mirror::Class> klass,
CompilerCallbacks* callbacks,
bool allow_soft_failures,
@@ -139,6 +141,7 @@
}
StandardVerifyCallback svc;
return CommonVerifyClass(self,
+ verifier_deps,
klass,
callbacks,
&svc,
@@ -149,6 +152,7 @@
}
FailureKind ClassVerifier::CommonVerifyClass(Thread* self,
+ VerifierDeps* verifier_deps,
ObjPtr<mirror::Class> klass,
CompilerCallbacks* callbacks,
VerifierCallback* verifier_callback,
@@ -184,6 +188,7 @@
Handle<mirror::DexCache> dex_cache(hs.NewHandle(klass->GetDexCache()));
Handle<mirror::ClassLoader> class_loader(hs.NewHandle(klass->GetClassLoader()));
return VerifyClass(self,
+ verifier_deps,
&dex_file,
dex_cache,
class_loader,
@@ -198,6 +203,7 @@
FailureKind ClassVerifier::VerifyClass(Thread* self,
+ VerifierDeps* verifier_deps,
const DexFile* dex_file,
Handle<mirror::DexCache> dex_cache,
Handle<mirror::ClassLoader> class_loader,
@@ -209,6 +215,7 @@
std::string* error) {
StandardVerifyCallback svc;
return VerifyClass(self,
+ verifier_deps,
dex_file,
dex_cache,
class_loader,
@@ -222,6 +229,7 @@
}
FailureKind ClassVerifier::VerifyClass(Thread* self,
+ VerifierDeps* verifier_deps,
const DexFile* dex_file,
Handle<mirror::DexCache> dex_cache,
Handle<mirror::ClassLoader> class_loader,
@@ -273,6 +281,7 @@
MethodVerifier::VerifyMethod(self,
linker,
Runtime::Current()->GetArenaPool(),
+ verifier_deps,
method_idx,
dex_file,
dex_cache,
diff --git a/runtime/verifier/class_verifier.h b/runtime/verifier/class_verifier.h
index 0b22966..fa9dd97 100644
--- a/runtime/verifier/class_verifier.h
+++ b/runtime/verifier/class_verifier.h
@@ -49,6 +49,8 @@
namespace verifier {
+class VerifierDeps;
+
// Verifier that ensures the complete class is OK.
class ClassVerifier {
public:
@@ -64,6 +66,7 @@
REQUIRES_SHARED(Locks::mutator_lock_);
// Verify a class. Returns "kNoFailure" on success.
static FailureKind VerifyClass(Thread* self,
+ VerifierDeps* verifier_deps,
ObjPtr<mirror::Class> klass,
CompilerCallbacks* callbacks,
bool allow_soft_failures,
@@ -72,6 +75,7 @@
std::string* error)
REQUIRES_SHARED(Locks::mutator_lock_);
static FailureKind VerifyClass(Thread* self,
+ VerifierDeps* verifier_deps,
const DexFile* dex_file,
Handle<mirror::DexCache> dex_cache,
Handle<mirror::ClassLoader> class_loader,
@@ -91,6 +95,7 @@
private:
static FailureKind CommonVerifyClass(Thread* self,
+ VerifierDeps* verifier_deps,
ObjPtr<mirror::Class> klass,
CompilerCallbacks* callbacks,
VerifierCallback* verifier_callback,
@@ -101,6 +106,7 @@
REQUIRES_SHARED(Locks::mutator_lock_);
static FailureKind VerifyClass(Thread* self,
+ VerifierDeps* verifier_deps,
const DexFile* dex_file,
Handle<mirror::DexCache> dex_cache,
Handle<mirror::ClassLoader> class_loader,
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc
index 5761429..59e9fba 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -153,6 +153,7 @@
MethodVerifier(Thread* self,
ClassLinker* class_linker,
ArenaPool* arena_pool,
+ VerifierDeps* verifier_deps,
const DexFile* dex_file,
const dex::CodeItem* code_item,
uint32_t method_idx,
@@ -172,6 +173,7 @@
: art::verifier::MethodVerifier(self,
class_linker,
arena_pool,
+ verifier_deps,
dex_file,
class_def,
code_item,
@@ -5075,6 +5077,7 @@
MethodVerifier::MethodVerifier(Thread* self,
ClassLinker* class_linker,
ArenaPool* arena_pool,
+ VerifierDeps* verifier_deps,
const DexFile* dex_file,
const dex::ClassDef& class_def,
const dex::CodeItem* code_item,
@@ -5099,6 +5102,7 @@
can_load_classes_(can_load_classes),
allow_soft_failures_(allow_soft_failures),
class_linker_(class_linker),
+ verifier_deps_(verifier_deps),
link_(nullptr) {
self->PushVerifier(this);
}
@@ -5111,6 +5115,7 @@
MethodVerifier::FailureData MethodVerifier::VerifyMethod(Thread* self,
ClassLinker* class_linker,
ArenaPool* arena_pool,
+ VerifierDeps* verifier_deps,
uint32_t method_idx,
const DexFile* dex_file,
Handle<mirror::DexCache> dex_cache,
@@ -5131,6 +5136,7 @@
return VerifyMethod<true>(self,
class_linker,
arena_pool,
+ verifier_deps,
method_idx,
dex_file,
dex_cache,
@@ -5151,6 +5157,7 @@
return VerifyMethod<false>(self,
class_linker,
arena_pool,
+ verifier_deps,
method_idx,
dex_file,
dex_cache,
@@ -5190,6 +5197,7 @@
MethodVerifier::FailureData MethodVerifier::VerifyMethod(Thread* self,
ClassLinker* class_linker,
ArenaPool* arena_pool,
+ VerifierDeps* verifier_deps,
uint32_t method_idx,
const DexFile* dex_file,
Handle<mirror::DexCache> dex_cache,
@@ -5212,6 +5220,7 @@
impl::MethodVerifier<kVerifierDebug> verifier(self,
class_linker,
arena_pool,
+ verifier_deps,
dex_file,
code_item,
method_idx,
@@ -5367,6 +5376,7 @@
new impl::MethodVerifier<false>(self,
Runtime::Current()->GetClassLinker(),
Runtime::Current()->GetArenaPool(),
+ /* verifier_deps= */ nullptr,
method->GetDexFile(),
method->GetCodeItem(),
method->GetDexMethodIndex(),
@@ -5414,6 +5424,7 @@
self,
Runtime::Current()->GetClassLinker(),
Runtime::Current()->GetArenaPool(),
+ /* verifier_deps= */ nullptr,
dex_file,
code_item,
dex_method_idx,
@@ -5455,6 +5466,7 @@
impl::MethodVerifier<false> verifier(hs.Self(),
Runtime::Current()->GetClassLinker(),
Runtime::Current()->GetArenaPool(),
+ /* verifier_deps= */ nullptr,
m->GetDexFile(),
m->GetCodeItem(),
m->GetDexMethodIndex(),
@@ -5477,6 +5489,7 @@
}
MethodVerifier* MethodVerifier::CreateVerifier(Thread* self,
+ VerifierDeps* verifier_deps,
const DexFile* dex_file,
Handle<mirror::DexCache> dex_cache,
Handle<mirror::ClassLoader> class_loader,
@@ -5494,6 +5507,7 @@
return new impl::MethodVerifier<false>(self,
Runtime::Current()->GetClassLinker(),
Runtime::Current()->GetArenaPool(),
+ verifier_deps,
dex_file,
code_item,
method_idx,
diff --git a/runtime/verifier/method_verifier.h b/runtime/verifier/method_verifier.h
index 4d4dd5b..1dfcaab 100644
--- a/runtime/verifier/method_verifier.h
+++ b/runtime/verifier/method_verifier.h
@@ -62,6 +62,7 @@
using RegisterLineArenaUniquePtr = std::unique_ptr<RegisterLine, RegisterLineArenaDelete>;
class RegType;
struct ScopedNewLine;
+class VerifierDeps;
// We don't need to store the register data for many instructions, because we either only need
// it at branch points (for verification) or GC points and branches (for verification +
@@ -203,11 +204,11 @@
virtual const RegType& ResolveCheckedClass(dex::TypeIndex class_idx)
REQUIRES_SHARED(Locks::mutator_lock_) = 0;
- uint32_t GetEncounteredFailureTypes() {
+ uint32_t GetEncounteredFailureTypes() const {
return encountered_failure_types_;
}
- ClassLinker* GetClassLinker() {
+ ClassLinker* GetClassLinker() const {
return class_linker_;
}
@@ -215,10 +216,15 @@
return flags_.aot_mode_;
}
+ VerifierDeps* GetVerifierDeps() const {
+ return verifier_deps_;
+ }
+
protected:
MethodVerifier(Thread* self,
ClassLinker* class_linker,
ArenaPool* arena_pool,
+ VerifierDeps* verifier_deps,
const DexFile* dex_file,
const dex::ClassDef& class_def,
const dex::CodeItem* code_item,
@@ -253,6 +259,7 @@
static FailureData VerifyMethod(Thread* self,
ClassLinker* class_linker,
ArenaPool* arena_pool,
+ VerifierDeps* verifier_deps,
uint32_t method_idx,
const DexFile* dex_file,
Handle<mirror::DexCache> dex_cache,
@@ -275,6 +282,7 @@
static FailureData VerifyMethod(Thread* self,
ClassLinker* class_linker,
ArenaPool* arena_pool,
+ VerifierDeps* verifier_deps,
uint32_t method_idx,
const DexFile* dex_file,
Handle<mirror::DexCache> dex_cache,
@@ -299,6 +307,7 @@
// has an irrecoverable corruption.
virtual bool Verify() REQUIRES_SHARED(Locks::mutator_lock_) = 0;
static MethodVerifier* CreateVerifier(Thread* self,
+ VerifierDeps* verifier_deps,
const DexFile* dex_file,
Handle<mirror::DexCache> dex_cache,
Handle<mirror::ClassLoader> class_loader,
@@ -386,6 +395,10 @@
// Classlinker to use when resolving.
ClassLinker* class_linker_;
+ // The verifier deps object we are going to report type assigability
+ // constraints to. Can be null for runtime verification.
+ VerifierDeps* verifier_deps_;
+
// Link, for the method verifier root linked list.
MethodVerifier* link_;
diff --git a/runtime/verifier/method_verifier_test.cc b/runtime/verifier/method_verifier_test.cc
index 800e8a1..9761982 100644
--- a/runtime/verifier/method_verifier_test.cc
+++ b/runtime/verifier/method_verifier_test.cc
@@ -45,8 +45,14 @@
// Verify the class
std::string error_msg;
- FailureKind failure = ClassVerifier::VerifyClass(
- self, klass, nullptr, true, HardFailLogMode::kLogWarning, /* api_level= */ 0u, &error_msg);
+ FailureKind failure = ClassVerifier::VerifyClass(self,
+ /* verifier_deps= */ nullptr,
+ klass,
+ nullptr,
+ true,
+ HardFailLogMode::kLogWarning,
+ /* api_level= */ 0u,
+ &error_msg);
if (android::base::StartsWith(descriptor, "Ljava/lang/invoke")) {
ASSERT_TRUE(failure == FailureKind::kSoftFailure ||
diff --git a/runtime/verifier/reg_type-inl.h b/runtime/verifier/reg_type-inl.h
index b6af1d3..efe03a8 100644
--- a/runtime/verifier/reg_type-inl.h
+++ b/runtime/verifier/reg_type-inl.h
@@ -116,16 +116,22 @@
// Record assignability dependency. The `verifier` is null during unit tests and
// VerifiedMethod::GenerateSafeCastSet.
if (verifier != nullptr && result) {
- VerifierDeps::MaybeRecordAssignability(
- verifier->GetDexFile(), verifier->GetClassDef(), lhs.GetClass(), rhs.GetClass());
+ VerifierDeps::MaybeRecordAssignability(verifier->GetVerifierDeps(),
+ verifier->GetDexFile(),
+ verifier->GetClassDef(),
+ lhs.GetClass(),
+ rhs.GetClass());
}
return result;
} else {
// For unresolved types, we don't know if they are assignable, and the
// verifier will continue assuming they are. We need to record that.
if (verifier != nullptr) {
- VerifierDeps::MaybeRecordAssignability(
- verifier->GetDexFile(), verifier->GetClassDef(), lhs, rhs);
+ VerifierDeps::MaybeRecordAssignability(verifier->GetVerifierDeps(),
+ verifier->GetDexFile(),
+ verifier->GetClassDef(),
+ lhs,
+ rhs);
}
// Unresolved types are only assignable for null and equality.
// Null cannot be the left-hand side.
diff --git a/runtime/verifier/reg_type.cc b/runtime/verifier/reg_type.cc
index 351aa55..5af2d4b 100644
--- a/runtime/verifier/reg_type.cc
+++ b/runtime/verifier/reg_type.cc
@@ -901,11 +901,13 @@
// Record the dependency that both `GetClass()` and `incoming_type.GetClass()`
// are assignable to `join_class`. The `verifier` is null during unit tests.
if (verifier != nullptr) {
- VerifierDeps::MaybeRecordAssignability(verifier->GetDexFile(),
+ VerifierDeps::MaybeRecordAssignability(verifier->GetVerifierDeps(),
+ verifier->GetDexFile(),
verifier->GetClassDef(),
join_class,
GetClass());
- VerifierDeps::MaybeRecordAssignability(verifier->GetDexFile(),
+ VerifierDeps::MaybeRecordAssignability(verifier->GetVerifierDeps(),
+ verifier->GetDexFile(),
verifier->GetClassDef(),
join_class,
incoming_type.GetClass());
diff --git a/runtime/verifier/verifier_deps.cc b/runtime/verifier/verifier_deps.cc
index 7a27a01..c9128f8 100644
--- a/runtime/verifier/verifier_deps.cc
+++ b/runtime/verifier/verifier_deps.cc
@@ -112,25 +112,18 @@
return GetIdFromString(dex_file, klass->GetDescriptor(&temp));
}
-static inline VerifierDeps* GetMainVerifierDeps() {
+static inline VerifierDeps* GetMainVerifierDeps(VerifierDeps* local_deps) {
// The main VerifierDeps is the one set in the compiler callbacks, which at the
// end of verification will have all the per-thread VerifierDeps merged into it.
CompilerCallbacks* callbacks = Runtime::Current()->GetCompilerCallbacks();
if (callbacks == nullptr) {
- return nullptr;
+ DCHECK(!Runtime::Current()->IsAotCompiler());
+ return local_deps;
}
+ DCHECK(Runtime::Current()->IsAotCompiler());
return callbacks->GetVerifierDeps();
}
-static inline VerifierDeps* GetThreadLocalVerifierDeps() {
- // During AOT, each thread has its own VerifierDeps, to avoid lock contention. At the end
- // of full verification, these VerifierDeps will be merged into the main one.
- if (!Runtime::Current()->IsAotCompiler()) {
- return nullptr;
- }
- return Thread::Current()->GetVerifierDeps();
-}
-
static bool FindExistingStringId(const std::vector<std::string>& strings,
const std::string& str,
uint32_t* found_id) {
@@ -156,7 +149,7 @@
// We use the main `VerifierDeps` for adding new strings to simplify
// synchronization/merging of these entries between threads.
- VerifierDeps* singleton = GetMainVerifierDeps();
+ VerifierDeps* singleton = GetMainVerifierDeps(this);
DexFileDeps* deps = singleton->GetDexFileDeps(dex_file);
DCHECK(deps != nullptr);
@@ -285,16 +278,16 @@
}
}
-void VerifierDeps::MaybeRecordVerificationStatus(const DexFile& dex_file,
+void VerifierDeps::MaybeRecordVerificationStatus(VerifierDeps* verifier_deps,
+ const DexFile& dex_file,
const dex::ClassDef& class_def,
FailureKind failure_kind) {
- VerifierDeps* thread_deps = GetThreadLocalVerifierDeps();
- if (thread_deps != nullptr) {
+ if (verifier_deps != nullptr) {
switch (failure_kind) {
case verifier::FailureKind::kHardFailure:
case verifier::FailureKind::kSoftFailure: {
// Class will be verified at runtime.
- DexFileDeps* dex_deps = thread_deps->GetDexFileDeps(dex_file);
+ DexFileDeps* dex_deps = verifier_deps->GetDexFileDeps(dex_file);
uint16_t index = dex_file.GetIndexForClassDef(class_def);
dex_deps->assignable_types_[index].clear();
break;
@@ -302,7 +295,7 @@
case verifier::FailureKind::kAccessChecksFailure:
case verifier::FailureKind::kTypeChecksFailure:
case verifier::FailureKind::kNoFailure: {
- thread_deps->RecordClassVerified(dex_file, class_def);
+ verifier_deps->RecordClassVerified(dex_file, class_def);
break;
}
}
@@ -315,23 +308,23 @@
dex_deps->verified_classes_[dex_file.GetIndexForClassDef(class_def)] = true;
}
-void VerifierDeps::MaybeRecordAssignability(const DexFile& dex_file,
+void VerifierDeps::MaybeRecordAssignability(VerifierDeps* verifier_deps,
+ const DexFile& dex_file,
const dex::ClassDef& class_def,
ObjPtr<mirror::Class> destination,
ObjPtr<mirror::Class> source) {
- VerifierDeps* thread_deps = GetThreadLocalVerifierDeps();
- if (thread_deps != nullptr) {
- thread_deps->AddAssignability(dex_file, class_def, destination, source);
+ if (verifier_deps != nullptr) {
+ verifier_deps->AddAssignability(dex_file, class_def, destination, source);
}
}
-void VerifierDeps::MaybeRecordAssignability(const DexFile& dex_file,
+void VerifierDeps::MaybeRecordAssignability(VerifierDeps* verifier_deps,
+ const DexFile& dex_file,
const dex::ClassDef& class_def,
const RegType& destination,
const RegType& source) {
- VerifierDeps* thread_deps = GetThreadLocalVerifierDeps();
- if (thread_deps != nullptr) {
- thread_deps->AddAssignability(dex_file, class_def, destination, source);
+ if (verifier_deps != nullptr) {
+ verifier_deps->AddAssignability(dex_file, class_def, destination, source);
}
}
diff --git a/runtime/verifier/verifier_deps.h b/runtime/verifier/verifier_deps.h
index 40ece5f..2e8ef4e 100644
--- a/runtime/verifier/verifier_deps.h
+++ b/runtime/verifier/verifier_deps.h
@@ -80,7 +80,8 @@
REQUIRES(!Locks::verifier_deps_lock_);
// Record the verification status of the class defined in `class_def`.
- static void MaybeRecordVerificationStatus(const DexFile& dex_file,
+ static void MaybeRecordVerificationStatus(VerifierDeps* verifier_deps,
+ const DexFile& dex_file,
const dex::ClassDef& class_def,
FailureKind failure_kind)
REQUIRES(!Locks::verifier_deps_lock_);
@@ -88,7 +89,8 @@
// Record the outcome `is_assignable` of type assignability test from `source`
// to `destination` as defined by RegType::AssignableFrom. `dex_file` is the
// owner of the method for which MethodVerifier performed the assignability test.
- static void MaybeRecordAssignability(const DexFile& dex_file,
+ static void MaybeRecordAssignability(VerifierDeps* verifier_deps,
+ const DexFile& dex_file,
const dex::ClassDef& class_def,
ObjPtr<mirror::Class> destination,
ObjPtr<mirror::Class> source)
@@ -97,7 +99,8 @@
// Record that `source` is assignable to `destination`. `dex_file` is the
// owner of the method for which MethodVerifier performed the assignability test.
- static void MaybeRecordAssignability(const DexFile& dex_file,
+ static void MaybeRecordAssignability(VerifierDeps* verifier_deps,
+ const DexFile& dex_file,
const dex::ClassDef& class_def,
const RegType& destination,
const RegType& source)
diff --git a/tools/art_verifier/art_verifier.cc b/tools/art_verifier/art_verifier.cc
index 6fe27d6..313c470 100644
--- a/tools/art_verifier/art_verifier.cc
+++ b/tools/art_verifier/art_verifier.cc
@@ -247,6 +247,7 @@
std::string error_msg;
verifier::FailureKind res =
verifier::ClassVerifier::VerifyClass(soa.Self(),
+ /* verifier_deps= */ nullptr,
h_klass.Get(),
runtime->GetCompilerCallbacks(),
true,