src/share/vm/code/nmethod.cpp

Print this page
rev 5061 : imported patch nmethod_changes_original
rev 5062 : fix nmethod unregister synchronization

*** 1300,1309 **** --- 1300,1316 ---- // Make sure neither the nmethod nor the method is flushed in case of a safepoint in code below. nmethodLocker nml(this); 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. // This logic is equivalent to the logic below for patching the // verified entry point of regular methods.
*** 1332,1345 **** // It's a true state change, so mark the method as decompiled. // Do it only for transition from alive. inc_decompile_count(); } ! // If the state is becoming a zombie, unregister the nmethod with heap // This nmethod may have already been unloaded during a full GC. if ((state == zombie) && !is_unloaded()) { ! Universe::heap()->unregister_nmethod(this); } // Change state _state = state; --- 1339,1353 ---- // It's a true state change, so mark the method as decompiled. // Do it only for transition from alive. inc_decompile_count(); } ! // 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()) { ! nmethod_needs_unregister = true; } // Change state _state = state;
*** 1373,1382 **** --- 1381,1393 ---- { // Flushing dependecies must be done before any possible // 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); } // zombie only - if a JVMTI agent has enabled the CompiledMethodUnload // event and it hasn't already been reported for this nmethod then
*** 1836,1846 **** // only in the second case. The weak roots in the nmethod // are the oops in the ExceptionCache and the InlineCache // 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(), "should not call follow on zombie or unloaded nmethod"); // If the method is not entrant or zombie then a JMP is plastered over the // first few bytes. If an oop in the old code was there, that oop // should not get GC'd. Skip the first few bytes of oops on --- 1847,1858 ---- // only in the second case. The weak roots in the nmethod // are the oops in the ExceptionCache and the InlineCache // oops. void nmethod::oops_do(OopClosure* f, bool do_strong_roots_only) { // make sure the oops ready to receive visitors ! 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 // first few bytes. If an oop in the old code was there, that oop // should not get GC'd. Skip the first few bytes of oops on