Add support for nested method verifiers
Can occur in the following scenario:
MethodVerifier::Verify -> MethodVerifier::GetStaticField ->
ResolveFieldJLS -> ThrowNoSuchFieldError -> EnsureInitialized ->
VerifyClass
Also fixed another case where we can be requested to dump for ANR
while we are suspended in one of the AllowSuspension points.
Bug: 20140397
Change-Id: Ib17f6b98954caa5d1ea1c1dcde66091cc6d11c25
diff --git a/runtime/thread.cc b/runtime/thread.cc
index 89fc00e..af11f73 100644
--- a/runtime/thread.cc
+++ b/runtime/thread.cc
@@ -2308,8 +2308,8 @@
mapper.VisitShadowFrame(shadow_frame);
}
}
- if (tlsPtr_.method_verifier != nullptr) {
- tlsPtr_.method_verifier->VisitRoots(visitor, RootInfo(kRootNativeStack, thread_id));
+ for (auto* verifier = tlsPtr_.method_verifier; verifier != nullptr; verifier = verifier->link_) {
+ verifier->VisitRoots(visitor, RootInfo(kRootNativeStack, thread_id));
}
// Visit roots on this thread's stack
Context* context = GetLongJumpContext();
@@ -2433,14 +2433,14 @@
tlsPtr_.debug_invoke_req = nullptr;
}
-void Thread::SetVerifier(verifier::MethodVerifier* verifier) {
- CHECK(tlsPtr_.method_verifier == nullptr);
+void Thread::PushVerifier(verifier::MethodVerifier* verifier) {
+ verifier->link_ = tlsPtr_.method_verifier;
tlsPtr_.method_verifier = verifier;
}
-void Thread::ClearVerifier(verifier::MethodVerifier* verifier) {
+void Thread::PopVerifier(verifier::MethodVerifier* verifier) {
CHECK_EQ(tlsPtr_.method_verifier, verifier);
- tlsPtr_.method_verifier = nullptr;
+ tlsPtr_.method_verifier = verifier->link_;
}
} // namespace art
diff --git a/runtime/thread.h b/runtime/thread.h
index f89e46b..b095e22 100644
--- a/runtime/thread.h
+++ b/runtime/thread.h
@@ -895,8 +895,8 @@
return tls32_.suspended_at_suspend_check;
}
- void SetVerifier(verifier::MethodVerifier* verifier);
- void ClearVerifier(verifier::MethodVerifier* verifier);
+ void PushVerifier(verifier::MethodVerifier* verifier);
+ void PopVerifier(verifier::MethodVerifier* verifier);
private:
explicit Thread(bool daemon);
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc
index d0f8468..9fc2658 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -395,12 +395,12 @@
has_virtual_or_interface_invokes_(false),
verify_to_dump_(verify_to_dump),
allow_thread_suspension_(allow_thread_suspension) {
- self->SetVerifier(this);
+ self->PushVerifier(this);
DCHECK(class_def != nullptr);
}
MethodVerifier::~MethodVerifier() {
- Thread::Current()->ClearVerifier(this);
+ Thread::Current()->PopVerifier(this);
STLDeleteElements(&failure_messages_);
}
diff --git a/runtime/verifier/method_verifier.h b/runtime/verifier/method_verifier.h
index c813634..8c0321e 100644
--- a/runtime/verifier/method_verifier.h
+++ b/runtime/verifier/method_verifier.h
@@ -31,6 +31,7 @@
class Instruction;
struct ReferenceMap2Visitor;
+class Thread;
namespace verifier {
@@ -738,6 +739,10 @@
// FindLocksAtDexPC, resulting in deadlocks.
const bool allow_thread_suspension_;
+ // Link, for the method verifier root linked list.
+ MethodVerifier* link_;
+
+ friend class art::Thread;
DISALLOW_COPY_AND_ASSIGN(MethodVerifier);
};
std::ostream& operator<<(std::ostream& os, const MethodVerifier::FailureKind& rhs);