Skip to content

Commit

Permalink
8078725: method adjustments can be done just once for all classes inv…
Browse files Browse the repository at this point in the history
…olved into redefinition

Walk all classes at the end of redefinition and adjust method entries and clean MethodData

Reviewed-by: mbaesken
Backport-of: 351280b
  • Loading branch information
TheRealMDoerr committed Jun 28, 2024
1 parent 3702e90 commit 2a5a4d7
Show file tree
Hide file tree
Showing 9 changed files with 82 additions and 139 deletions.
23 changes: 8 additions & 15 deletions src/hotspot/share/oops/cpCache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -606,7 +606,7 @@ void ConstantPoolCacheEntry::adjust_method_entry(Method* old_method,

// a constant pool cache entry should never contain old or obsolete methods
bool ConstantPoolCacheEntry::check_no_old_or_obsolete_entries() {
Method* m = get_interesting_method_entry(NULL);
Method* m = get_interesting_method_entry();
// return false if m refers to a non-deleted old or obsolete method
if (m != NULL) {
assert(m->is_valid() && m->is_method(), "m is a valid method");
Expand All @@ -616,7 +616,7 @@ bool ConstantPoolCacheEntry::check_no_old_or_obsolete_entries() {
}
}

Method* ConstantPoolCacheEntry::get_interesting_method_entry(Klass* k) {
Method* ConstantPoolCacheEntry::get_interesting_method_entry() {
if (!is_method_entry()) {
// not a method entry so not interesting by default
return NULL;
Expand All @@ -637,12 +637,9 @@ Method* ConstantPoolCacheEntry::get_interesting_method_entry(Klass* k) {
}
}
assert(m != NULL && m->is_method(), "sanity check");
if (m == NULL || !m->is_method() || (k != NULL && m->method_holder() != k)) {
// robustness for above sanity checks or method is not in
// the interesting class
if (m == NULL || !m->is_method()) {
return NULL;
}
// the method is in the interesting class so the entry is interesting
return m;
}
#endif // INCLUDE_JVMTI
Expand Down Expand Up @@ -801,10 +798,10 @@ void ConstantPoolCache::set_archived_references(oop o) {
// RedefineClasses() API support:
// If any entry of this ConstantPoolCache points to any of
// old_methods, replace it with the corresponding new_method.
void ConstantPoolCache::adjust_method_entries(InstanceKlass* holder, bool * trace_name_printed) {
void ConstantPoolCache::adjust_method_entries(bool * trace_name_printed) {
for (int i = 0; i < length(); i++) {
ConstantPoolCacheEntry* entry = entry_at(i);
Method* old_method = entry->get_interesting_method_entry(holder);
Method* old_method = entry->get_interesting_method_entry();
if (old_method == NULL || !old_method->is_old()) {
continue; // skip uninteresting entries
}
Expand All @@ -813,19 +810,15 @@ void ConstantPoolCache::adjust_method_entries(InstanceKlass* holder, bool * trac
entry->initialize_entry(entry->constant_pool_index());
continue;
}
Method* new_method = holder->method_with_idnum(old_method->orig_method_idnum());

assert(new_method != NULL, "method_with_idnum() should not be NULL");
assert(old_method != new_method, "sanity check");

Method* new_method = old_method->get_new_method();
entry_at(i)->adjust_method_entry(old_method, new_method, trace_name_printed);
}
}

// the constant pool cache should never contain old or obsolete methods
bool ConstantPoolCache::check_no_old_or_obsolete_entries() {
for (int i = 1; i < length(); i++) {
if (entry_at(i)->get_interesting_method_entry(NULL) != NULL &&
if (entry_at(i)->get_interesting_method_entry() != NULL &&
!entry_at(i)->check_no_old_or_obsolete_entries()) {
return false;
}
Expand All @@ -835,7 +828,7 @@ bool ConstantPoolCache::check_no_old_or_obsolete_entries() {

void ConstantPoolCache::dump_cache() {
for (int i = 1; i < length(); i++) {
if (entry_at(i)->get_interesting_method_entry(NULL) != NULL) {
if (entry_at(i)->get_interesting_method_entry() != NULL) {
entry_at(i)->print(tty, i);
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/hotspot/share/oops/cpCache.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -385,7 +385,7 @@ class ConstantPoolCacheEntry {
void adjust_method_entry(Method* old_method, Method* new_method,
bool* trace_name_printed);
bool check_no_old_or_obsolete_entries();
Method* get_interesting_method_entry(Klass* k);
Method* get_interesting_method_entry();
#endif // INCLUDE_JVMTI

// Debugging & Printing
Expand Down Expand Up @@ -506,7 +506,7 @@ class ConstantPoolCache: public MetaspaceObj {
// trace_name_printed is set to true if the current call has
// printed the klass name so that other routines in the adjust_*
// group don't print the klass name.
void adjust_method_entries(InstanceKlass* holder, bool* trace_name_printed);
void adjust_method_entries(bool* trace_name_printed);
bool check_no_old_or_obsolete_entries();
void dump_cache();
#endif // INCLUDE_JVMTI
Expand Down
12 changes: 4 additions & 8 deletions src/hotspot/share/oops/instanceKlass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2949,22 +2949,18 @@ Method* InstanceKlass::method_at_itable(Klass* holder, int index, TRAPS) {
// not yet in the vtable due to concurrent subclass define and superinterface
// redefinition
// Note: those in the vtable, should have been updated via adjust_method_entries
void InstanceKlass::adjust_default_methods(InstanceKlass* holder, bool* trace_name_printed) {
void InstanceKlass::adjust_default_methods(bool* trace_name_printed) {
// search the default_methods for uses of either obsolete or EMCP methods
if (default_methods() != NULL) {
for (int index = 0; index < default_methods()->length(); index ++) {
Method* old_method = default_methods()->at(index);
if (old_method == NULL || old_method->method_holder() != holder || !old_method->is_old()) {
if (old_method == NULL || !old_method->is_old()) {
continue; // skip uninteresting entries
}
assert(!old_method->is_deleted(), "default methods may not be deleted");

Method* new_method = holder->method_with_idnum(old_method->orig_method_idnum());

assert(new_method != NULL, "method_with_idnum() should not be NULL");
assert(old_method != new_method, "sanity check");

Method* new_method = old_method->get_new_method();
default_methods()->at_put(index, new_method);

if (log_is_enabled(Info, redefine, class, update)) {
ResourceMark rm;
if (!(*trace_name_printed)) {
Expand Down
2 changes: 1 addition & 1 deletion src/hotspot/share/oops/instanceKlass.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1155,7 +1155,7 @@ class InstanceKlass: public Klass {
Method* method_at_itable(Klass* holder, int index, TRAPS);

#if INCLUDE_JVMTI
void adjust_default_methods(InstanceKlass* holder, bool* trace_name_printed);
void adjust_default_methods(bool* trace_name_printed);
#endif // INCLUDE_JVMTI

void clean_weak_instanceklass_links();
Expand Down
24 changes: 8 additions & 16 deletions src/hotspot/share/oops/klassVtable.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
Expand Down Expand Up @@ -964,21 +964,18 @@ bool klassVtable::adjust_default_method(int vtable_index, Method* old_method, Me
}

// search the vtable for uses of either obsolete or EMCP methods
void klassVtable::adjust_method_entries(InstanceKlass* holder, bool * trace_name_printed) {
void klassVtable::adjust_method_entries(bool * trace_name_printed) {
int prn_enabled = 0;
for (int index = 0; index < length(); index++) {
Method* old_method = unchecked_method_at(index);
if (old_method == NULL || old_method->method_holder() != holder || !old_method->is_old()) {
if (old_method == NULL || !old_method->is_old()) {
continue; // skip uninteresting entries
}
assert(!old_method->is_deleted(), "vtable methods may not be deleted");

Method* new_method = holder->method_with_idnum(old_method->orig_method_idnum());

assert(new_method != NULL, "method_with_idnum() should not be NULL");
assert(old_method != new_method, "sanity check");

Method* new_method = old_method->get_new_method();
put_method_at(new_method, index);

// For default methods, need to update the _default_methods array
// which can only have one method entry for a given signature
bool updated_default = false;
Expand Down Expand Up @@ -1294,21 +1291,16 @@ void klassItable::initialize_itable_for_interface(int method_table_offset, Klass

#if INCLUDE_JVMTI
// search the itable for uses of either obsolete or EMCP methods
void klassItable::adjust_method_entries(InstanceKlass* holder, bool * trace_name_printed) {
void klassItable::adjust_method_entries(bool * trace_name_printed) {

itableMethodEntry* ime = method_entry(0);
for (int i = 0; i < _size_method_table; i++, ime++) {
Method* old_method = ime->method();
if (old_method == NULL || old_method->method_holder() != holder || !old_method->is_old()) {
if (old_method == NULL || !old_method->is_old()) {
continue; // skip uninteresting entries
}
assert(!old_method->is_deleted(), "itable methods may not be deleted");

Method* new_method = holder->method_with_idnum(old_method->orig_method_idnum());

assert(new_method != NULL, "method_with_idnum() should not be NULL");
assert(old_method != new_method, "sanity check");

Method* new_method = old_method->get_new_method();
ime->initialize(new_method);

if (log_is_enabled(Info, redefine, class, update)) {
Expand Down
4 changes: 2 additions & 2 deletions src/hotspot/share/oops/klassVtable.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ class klassVtable {
// printed the klass name so that other routines in the adjust_*
// group don't print the klass name.
bool adjust_default_method(int vtable_index, Method* old_method, Method* new_method);
void adjust_method_entries(InstanceKlass* holder, bool * trace_name_printed);
void adjust_method_entries(bool* trace_name_printed);
bool check_no_old_or_obsolete_entries();
void dump_vtable();
#endif // INCLUDE_JVMTI
Expand Down Expand Up @@ -322,7 +322,7 @@ class klassItable {
// trace_name_printed is set to true if the current call has
// printed the klass name so that other routines in the adjust_*
// group don't print the klass name.
void adjust_method_entries(InstanceKlass* holder, bool * trace_name_printed);
void adjust_method_entries(bool* trace_name_printed);
bool check_no_old_or_obsolete_entries();
void dump_itable();
#endif // INCLUDE_JVMTI
Expand Down
Loading

1 comment on commit 2a5a4d7

@openjdk-notifier
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.