8152947: VM crash with assert(!removed || is_in_use()) failed: unused osr nmethod should be invalidated
authorthartmann
Wed, 30 Mar 2016 08:00:51 +0200
changeset 36815 573180d7f578
parent 36814 2c9a2b0e5c07
child 36816 987a22271911
8152947: VM crash with assert(!removed || is_in_use()) failed: unused osr nmethod should be invalidated Summary: Check OSR invalidation after nmethod state transition. Reviewed-by: ddmitriev, vlivanov
hotspot/src/share/vm/code/nmethod.cpp
--- a/hotspot/src/share/vm/code/nmethod.cpp	Thu Mar 24 15:53:19 2016 -0700
+++ b/hotspot/src/share/vm/code/nmethod.cpp	Wed Mar 30 08:00:51 2016 +0200
@@ -1332,8 +1332,19 @@
   }
   // Unlink the osr method, so we do not look this up again
   if (is_osr_method()) {
-    invalidate_osr_method();
+    // Invalidate the osr nmethod only once
+    if (is_in_use()) {
+      invalidate_osr_method();
+    }
+#ifdef ASSERT
+    if (method() != NULL) {
+      // Make sure osr nmethod is invalidated, i.e. not on the list
+      bool found = method()->method_holder()->remove_osr_nmethod(this);
+      assert(!found, "osr nmethod should have been invalidated");
+    }
+#endif
   }
+
   // If _method is already NULL the Method* is about to be unloaded,
   // so we don't have to break the cycle. Note that it is possible to
   // have the Method* live here, in case we unload the nmethod because
@@ -1386,16 +1397,9 @@
 
 void nmethod::invalidate_osr_method() {
   assert(_entry_bci != InvocationEntryBci, "wrong kind of nmethod");
-#ifndef ASSERT
-  // Make sure osr nmethod is invalidated only once
-  if (!is_in_use()) {
-    return;
-  }
-#endif
   // Remove from list of active nmethods
   if (method() != NULL) {
-    bool removed = method()->method_holder()->remove_osr_nmethod(this);
-    assert(!removed || is_in_use(), "unused osr nmethod should be invalidated");
+    method()->method_holder()->remove_osr_nmethod(this);
   }
 }
 
@@ -1444,8 +1448,9 @@
     // invalidate osr nmethod before acquiring the patching lock since
     // they both acquire leaf locks and we don't want a deadlock.
     // This logic is equivalent to the logic below for patching the
-    // verified entry point of regular methods.
-    if (is_osr_method()) {
+    // verified entry point of regular methods. We check that the
+    // nmethod is in use to ensure that it is invalidated only once.
+    if (is_osr_method() && is_in_use()) {
       // this effectively makes the osr nmethod not entrant
       invalidate_osr_method();
     }
@@ -1511,6 +1516,14 @@
     }
   } // leave critical region under Patching_lock
 
+#ifdef ASSERT
+  if (is_osr_method() && method() != NULL) {
+    // Make sure osr nmethod is invalidated, i.e. not on the list
+    bool found = method()->method_holder()->remove_osr_nmethod(this);
+    assert(!found, "osr nmethod should have been invalidated");
+  }
+#endif
+
   // When the nmethod becomes zombie it is no longer alive so the
   // dependencies must be flushed.  nmethods in the not_entrant
   // state will be flushed later when the transition to zombie