8264731: Introduce InstanceKlass::method_at_itable_or_null()

Reviewed-by: coleenp, dholmes
This commit is contained in:
Vladimir Ivanov 2021-04-07 21:07:12 +00:00
parent 22b20f8e92
commit 6e2b82a45f
3 changed files with 39 additions and 32 deletions

View File

@ -3150,41 +3150,47 @@ jint InstanceKlass::jvmti_class_status() const {
return result;
}
Method* InstanceKlass::method_at_itable(Klass* holder, int index, TRAPS) {
itableOffsetEntry* ioe = (itableOffsetEntry*)start_of_itable();
int method_table_offset_in_words = ioe->offset()/wordSize;
int nof_interfaces = (method_table_offset_in_words - itable_offset_in_words())
/ itableOffsetEntry::size();
for (int cnt = 0 ; ; cnt ++, ioe ++) {
Method* InstanceKlass::method_at_itable(InstanceKlass* holder, int index, TRAPS) {
bool implements_interface; // initialized by method_at_itable_or_null
Method* m = method_at_itable_or_null(holder, index,
implements_interface); // out parameter
if (m != NULL) {
assert(implements_interface, "sanity");
return m;
} else if (implements_interface) {
// Throw AbstractMethodError since corresponding itable slot is empty.
THROW_NULL(vmSymbols::java_lang_AbstractMethodError());
} else {
// If the interface isn't implemented by the receiver class,
// the VM should throw IncompatibleClassChangeError.
if (cnt >= nof_interfaces) {
ResourceMark rm(THREAD);
stringStream ss;
bool same_module = (module() == holder->module());
ss.print("Receiver class %s does not implement "
"the interface %s defining the method to be called "
"(%s%s%s)",
external_name(), holder->external_name(),
(same_module) ? joint_in_module_of_loader(holder) : class_in_module_of_loader(),
(same_module) ? "" : "; ",
(same_module) ? "" : holder->class_in_module_of_loader());
THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), ss.as_string());
}
Klass* ik = ioe->interface_klass();
if (ik == holder) break;
ResourceMark rm(THREAD);
stringStream ss;
bool same_module = (module() == holder->module());
ss.print("Receiver class %s does not implement "
"the interface %s defining the method to be called "
"(%s%s%s)",
external_name(), holder->external_name(),
(same_module) ? joint_in_module_of_loader(holder) : class_in_module_of_loader(),
(same_module) ? "" : "; ",
(same_module) ? "" : holder->class_in_module_of_loader());
THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), ss.as_string());
}
itableMethodEntry* ime = ioe->first_method_entry(this);
Method* m = ime[index].method();
if (m == NULL) {
THROW_NULL(vmSymbols::java_lang_AbstractMethodError());
}
return m;
}
Method* InstanceKlass::method_at_itable_or_null(InstanceKlass* holder, int index, bool& implements_interface) {
klassItable itable(this);
for (int i = 0; i < itable.size_offset_table(); i++) {
itableOffsetEntry* offset_entry = itable.offset_entry(i);
if (offset_entry->interface_klass() == holder) {
implements_interface = true;
itableMethodEntry* ime = offset_entry->first_method_entry(this);
Method* m = ime[index].method();
return m;
}
}
implements_interface = false;
return NULL; // offset entry not found
}
#if INCLUDE_JVMTI
// update default_methods for redefineclasses for methods that are

View File

@ -1108,7 +1108,8 @@ public:
// Java itable
klassItable itable() const; // return klassItable wrapper
Method* method_at_itable(Klass* holder, int index, TRAPS);
Method* method_at_itable(InstanceKlass* holder, int index, TRAPS);
Method* method_at_itable_or_null(InstanceKlass* holder, int index, bool& itable_entry_found);
#if INCLUDE_JVMTI
void adjust_default_methods(bool* trace_name_printed);

View File

@ -906,7 +906,7 @@ static void jni_invoke_nonstatic(JNIEnv *env, JavaValue* result, jobject receive
{
Method* m = Method::resolve_jmethod_id(method_id);
number_of_parameters = m->size_of_parameters();
Klass* holder = m->method_holder();
InstanceKlass* holder = m->method_holder();
if (call_type != JNI_VIRTUAL) {
selected_method = m;
} else if (!m->has_itable_index()) {