8215754: ZGC: nmethod is not unlinked from Method before rendezvous handshake
Reviewed-by: pliden, neliasso
This commit is contained in:
parent
804d51618f
commit
c03e894387
@ -1159,6 +1159,19 @@ void nmethod::log_state_change() const {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void nmethod::unlink_from_method(bool acquire_lock) {
|
||||||
|
// We need to check if both the _code and _from_compiled_code_entry_point
|
||||||
|
// refer to this nmethod because there is a race in setting these two fields
|
||||||
|
// in Method* as seen in bugid 4947125.
|
||||||
|
// If the vep() points to the zombie nmethod, the memory for the nmethod
|
||||||
|
// could be flushed and the compiler and vtable stubs could still call
|
||||||
|
// through it.
|
||||||
|
if (method() != NULL && (method()->code() == this ||
|
||||||
|
method()->from_compiled_entry() == verified_entry_point())) {
|
||||||
|
method()->clear_code(acquire_lock);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Common functionality for both make_not_entrant and make_zombie
|
* Common functionality for both make_not_entrant and make_zombie
|
||||||
*/
|
*/
|
||||||
@ -1246,17 +1259,7 @@ bool nmethod::make_not_entrant_or_zombie(int state) {
|
|||||||
JVMCI_ONLY(maybe_invalidate_installed_code());
|
JVMCI_ONLY(maybe_invalidate_installed_code());
|
||||||
|
|
||||||
// Remove nmethod from method.
|
// Remove nmethod from method.
|
||||||
// We need to check if both the _code and _from_compiled_code_entry_point
|
unlink_from_method(false /* already owns Patching_lock */);
|
||||||
// refer to this nmethod because there is a race in setting these two fields
|
|
||||||
// in Method* as seen in bugid 4947125.
|
|
||||||
// If the vep() points to the zombie nmethod, the memory for the nmethod
|
|
||||||
// could be flushed and the compiler and vtable stubs could still call
|
|
||||||
// through it.
|
|
||||||
if (method() != NULL && (method()->code() == this ||
|
|
||||||
method()->from_compiled_entry() == verified_entry_point())) {
|
|
||||||
HandleMark hm;
|
|
||||||
method()->clear_code(false /* already owns Patching_lock */);
|
|
||||||
}
|
|
||||||
} // leave critical region under Patching_lock
|
} // leave critical region under Patching_lock
|
||||||
|
|
||||||
#ifdef ASSERT
|
#ifdef ASSERT
|
||||||
|
@ -376,6 +376,8 @@ class nmethod : public CompiledMethod {
|
|||||||
|
|
||||||
int comp_level() const { return _comp_level; }
|
int comp_level() const { return _comp_level; }
|
||||||
|
|
||||||
|
void unlink_from_method(bool acquire_lock);
|
||||||
|
|
||||||
// Support for oops in scopes and relocs:
|
// Support for oops in scopes and relocs:
|
||||||
// Note: index 0 is reserved for null.
|
// Note: index 0 is reserved for null.
|
||||||
oop oop_at(int index) const;
|
oop oop_at(int index) const;
|
||||||
|
@ -42,6 +42,11 @@ bool ZBarrierSetNMethod::nmethod_entry_barrier(nmethod* nm) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (nm->is_unloading()) {
|
if (nm->is_unloading()) {
|
||||||
|
// We don't need to take the lock when unlinking nmethods from
|
||||||
|
// the Method, because it is only concurrently unlinked by
|
||||||
|
// the entry barrier, which acquires the per nmethod lock.
|
||||||
|
nm->unlink_from_method(false /* acquire_lock */);
|
||||||
|
|
||||||
// We can end up calling nmethods that are unloading
|
// We can end up calling nmethods that are unloading
|
||||||
// since we clear compiled ICs lazily. Returning false
|
// since we clear compiled ICs lazily. Returning false
|
||||||
// will re-resovle the call and update the compiled IC.
|
// will re-resovle the call and update the compiled IC.
|
||||||
|
@ -611,15 +611,20 @@ public:
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ZLocker<ZReentrantLock> locker(ZNMethodTable::lock_for_nmethod(nm));
|
||||||
|
|
||||||
if (nm->is_unloading()) {
|
if (nm->is_unloading()) {
|
||||||
// Unlinking of the dependencies must happen before the
|
// Unlinking of the dependencies must happen before the
|
||||||
// handshake separating unlink and purge.
|
// handshake separating unlink and purge.
|
||||||
nm->flush_dependencies(false /* delete_immediately */);
|
nm->flush_dependencies(false /* delete_immediately */);
|
||||||
|
|
||||||
|
// We don't need to take the lock when unlinking nmethods from
|
||||||
|
// the Method, because it is only concurrently unlinked by
|
||||||
|
// the entry barrier, which acquires the per nmethod lock.
|
||||||
|
nm->unlink_from_method(false /* acquire_lock */);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ZLocker<ZReentrantLock> locker(ZNMethodTable::lock_for_nmethod(nm));
|
|
||||||
|
|
||||||
// Heal oops and disarm
|
// Heal oops and disarm
|
||||||
ZNMethodOopClosure cl;
|
ZNMethodOopClosure cl;
|
||||||
ZNMethodTable::entry_oops_do(entry, &cl);
|
ZNMethodTable::entry_oops_do(entry, &cl);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user