8217309: ZGC: Fix ZNMethodTable corruption

Reviewed-by: eosterlund, stefank
This commit is contained in:
Per Lidén 2019-01-24 12:23:01 +01:00
parent 25bd20f5d9
commit ad65ea3c85
3 changed files with 14 additions and 20 deletions

View File

@ -1100,7 +1100,11 @@ void nmethod::make_unloaded() {
"must be at safepoint");
// Unregister must be done before the state change
Universe::heap()->unregister_nmethod(this);
{
MutexLockerEx ml(SafepointSynchronize::is_at_safepoint() ? NULL : CodeCache_lock,
Mutex::_no_safepoint_check_flag);
Universe::heap()->unregister_nmethod(this);
}
// Log the unloading.
log_state_change();

View File

@ -264,21 +264,17 @@ bool ZNMethodTable::register_entry(ZNMethodTableEntry* table, size_t size, ZNMet
}
}
bool ZNMethodTable::unregister_entry(ZNMethodTableEntry* table, size_t size, nmethod* nm) {
void ZNMethodTable::unregister_entry(ZNMethodTableEntry* table, size_t size, nmethod* nm) {
if (size == 0) {
// Table is empty
return false;
return;
}
size_t index = first_index(nm, size);
for (;;) {
const ZNMethodTableEntry table_entry = table[index];
if (!table_entry.registered() && !table_entry.unregistered()) {
// Entry not found
return false;
}
assert(table_entry.registered() || table_entry.unregistered(), "Entry not found");
if (table_entry.registered() && table_entry.method() == nm) {
// Remove entry
@ -287,7 +283,7 @@ bool ZNMethodTable::unregister_entry(ZNMethodTableEntry* table, size_t size, nme
// Destroy GC data
ZNMethodData::destroy(gc_data(nm));
set_gc_data(nm, NULL);
return true;
return;
}
index = next_index(index, size);
@ -451,8 +447,6 @@ void ZNMethodTable::sweeper_wait_for_iteration() {
return;
}
assert(CodeCache_lock->owned_by_self(), "Lock must be held");
while (_iter_table != NULL) {
MutexUnlockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
os::naked_short_sleep(1);
@ -460,6 +454,7 @@ void ZNMethodTable::sweeper_wait_for_iteration() {
}
void ZNMethodTable::unregister_nmethod(nmethod* nm) {
assert(CodeCache_lock->owned_by_self(), "Lock must be held");
ResourceMark rm;
sweeper_wait_for_iteration();
@ -467,14 +462,9 @@ void ZNMethodTable::unregister_nmethod(nmethod* nm) {
log_unregister(nm);
// Remove entry
if (unregister_entry(_table, _size, nm)) {
// Entry was unregistered. When unregister_entry() instead returns
// false the nmethod was not in the table (because it didn't have
// any oops) so we do not want to decrease the number of registered
// entries in that case.
_nregistered--;
_nunregistered++;
}
unregister_entry(_table, _size, nm);
_nunregistered++;
_nregistered--;
}
void ZNMethodTable::disarm_nmethod(nmethod* nm) {

View File

@ -57,7 +57,7 @@ private:
static void sweeper_wait_for_iteration();
static bool register_entry(ZNMethodTableEntry* table, size_t size, ZNMethodTableEntry entry);
static bool unregister_entry(ZNMethodTableEntry* table, size_t size, nmethod* nm);
static void unregister_entry(ZNMethodTableEntry* table, size_t size, nmethod* nm);
static void rebuild(size_t new_size);
static void rebuild_if_needed();