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