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