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

View file

@ -57,7 +57,7 @@ private:
static void sweeper_wait_for_iteration(); static void sweeper_wait_for_iteration();
static bool register_entry(ZNMethodTableEntry* table, size_t size, ZNMethodTableEntry entry); 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(size_t new_size);
static void rebuild_if_needed(); static void rebuild_if_needed();