--- old/src/share/vm/code/nmethod.cpp 2013-08-14 16:14:19.799432337 +0200 +++ new/src/share/vm/code/nmethod.cpp 2013-08-14 16:14:19.527432342 +0200 @@ -1302,6 +1302,13 @@ methodHandle the_method(method()); No_Safepoint_Verifier nsv; + // during patching, depending on the nmethod state we must notify the GC that + // code has been unloaded, unregistering it. We cannot do this right while + // holding the Patching_lock because we need to use the CodeCache_lock. This + // would be prone to deadlocks. + // This flag is used to remember whether we need to later lock and unregister. + bool nmethod_needs_unregister = false; + { // invalidate osr nmethod before acquiring the patching lock since // they both acquire leaf locks and we don't want a deadlock. @@ -1334,10 +1341,11 @@ inc_decompile_count(); } - // If the state is becoming a zombie, unregister the nmethod with heap + // If the state is becoming a zombie, signal to unregister the nmethod with + // the heap. // This nmethod may have already been unloaded during a full GC. if ((state == zombie) && !is_unloaded()) { - Universe::heap()->unregister_nmethod(this); + nmethod_needs_unregister = true; } // Change state @@ -1375,6 +1383,9 @@ // safepoint can sneak in, otherwise the oops used by the // dependency logic could have become stale. MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); + if (nmethod_needs_unregister) { + Universe::heap()->unregister_nmethod(this); + } flush_dependencies(NULL); } @@ -1838,7 +1849,8 @@ // oops. void nmethod::oops_do(OopClosure* f, bool do_strong_roots_only) { // make sure the oops ready to receive visitors - assert(!is_zombie() && !is_unloaded(), + assert(NMethodSweeper::is_sweeping(this) || is_marked_for_deoptimization() || + (!is_zombie() && !is_unloaded()), "should not call follow on zombie or unloaded nmethod"); // If the method is not entrant or zombie then a JMP is plastered over the