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