OSDN Git Service

Add support for nested method verifiers
authorMathieu Chartier <mathieuc@google.com>
Tue, 31 Mar 2015 21:59:59 +0000 (14:59 -0700)
committerMathieu Chartier <mathieuc@google.com>
Thu, 9 Apr 2015 22:18:14 +0000 (15:18 -0700)
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

runtime/thread.cc
runtime/thread.h
runtime/verifier/method_verifier.cc
runtime/verifier/method_verifier.h

index 89fc00e..af11f73 100644 (file)
@@ -2308,8 +2308,8 @@ void Thread::VisitRoots(RootVisitor* visitor) {
       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 @@ void Thread::ClearDebugInvokeReq() {
   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
index f89e46b..b095e22 100644 (file)
@@ -895,8 +895,8 @@ class Thread {
     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);
index d0f8468..9fc2658 100644 (file)
@@ -395,12 +395,12 @@ MethodVerifier::MethodVerifier(Thread* self,
       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_);
 }
 
index c813634..8c0321e 100644 (file)
@@ -31,6 +31,7 @@ namespace art {
 
 class Instruction;
 struct ReferenceMap2Visitor;
+class Thread;
 
 namespace verifier {
 
@@ -738,6 +739,10 @@ class MethodVerifier {
   // 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);