correct invokevirtual method resolution order

This commit is contained in:
Zack Buhman 2024-12-29 12:25:31 -06:00
parent 5c88c8f7c1
commit 9677332560
5 changed files with 37 additions and 10 deletions

View File

@ -389,7 +389,7 @@ struct method_entry class_resolver_lookup_method_from_interfacemethodref_index(i
struct class_entry * origin_class_entry) struct class_entry * origin_class_entry)
{ {
struct constant * interfacemethodref_constant = &origin_class_entry->class_file->constant_pool[interfacemethodref_index - 1]; struct constant * interfacemethodref_constant = &origin_class_entry->class_file->constant_pool[interfacemethodref_index - 1];
assert(interfacemethodref_constant->tag == CONSTANT_InterfaceMethodref); assert(interfacemethodref_constant->tag == CONSTANT_InterfaceMethodref || interfacemethodref_constant->tag == CONSTANT_Methodref);
struct constant * nameandtype_constant = &origin_class_entry->class_file->constant_pool[interfacemethodref_constant->interfacemethodref.name_and_type_index - 1]; struct constant * nameandtype_constant = &origin_class_entry->class_file->constant_pool[interfacemethodref_constant->interfacemethodref.name_and_type_index - 1];
assert(nameandtype_constant->tag == CONSTANT_NameAndType); assert(nameandtype_constant->tag == CONSTANT_NameAndType);
struct constant * method_name_constant = &origin_class_entry->class_file->constant_pool[nameandtype_constant->nameandtype.name_index - 1]; struct constant * method_name_constant = &origin_class_entry->class_file->constant_pool[nameandtype_constant->nameandtype.name_index - 1];

View File

@ -1157,15 +1157,37 @@ void op_invokestatic(struct vm * vm, uint32_t index)
vm_static_method_call(vm, method_entry->class_entry, method_entry->method_info); vm_static_method_call(vm, method_entry->class_entry, method_entry->method_info);
} }
#include "debug.h"
void op_invokevirtual(struct vm * vm, uint32_t index) void op_invokevirtual(struct vm * vm, uint32_t index)
{ {
struct method_entry * method_entry = struct class_entry * origin_class_entry = vm->current_frame->class_entry;
class_resolver_lookup_method_from_methodref_index(vm->class_hash_table.length,
vm->class_hash_table.entry,
index,
vm->current_frame->class_entry);
vm_special_method_call(vm, method_entry->class_entry, method_entry->method_info); struct constant * interfacemethodref_constant = &origin_class_entry->class_file->constant_pool[index - 1];
assert(interfacemethodref_constant->tag == CONSTANT_Methodref);
struct constant * nameandtype_constant = &origin_class_entry->class_file->constant_pool[interfacemethodref_constant->interfacemethodref.name_and_type_index - 1];
assert(nameandtype_constant->tag == CONSTANT_NameAndType);
struct constant * method_name_constant = &origin_class_entry->class_file->constant_pool[nameandtype_constant->nameandtype.name_index - 1];
assert(method_name_constant->tag == CONSTANT_Utf8);
struct constant * method_descriptor_constant = &origin_class_entry->class_file->constant_pool[nameandtype_constant->nameandtype.descriptor_index - 1];
assert(method_descriptor_constant->tag == CONSTANT_Utf8);
uint8_t return_type;
int nargs = descriptor_nargs(method_descriptor_constant, &return_type);
(void)return_type;
int32_t * objectref = (int32_t *)operand_stack_peek_u32(vm->current_frame, nargs + 1);
assert(objectref != nullptr);
struct class_entry * class_entry = (struct class_entry *)objectref[0];
struct method_entry method_entry =
class_resolver_lookup_method_from_interfacemethodref_index(vm->class_hash_table.length,
vm->class_hash_table.entry,
index,
class_entry,
vm->current_frame->class_entry);
vm_special_method_call(vm, method_entry.class_entry, method_entry.method_info);
} }
void op_ior(struct vm * vm) void op_ior(struct vm * vm)

View File

@ -48,7 +48,7 @@ int find_constantvalue_name_index(struct class_file * class_file)
return 0; return 0;
} }
static int descriptor_nargs(struct constant * descriptor_constant, uint8_t * return_type) int descriptor_nargs(struct constant * descriptor_constant, uint8_t * return_type)
{ {
assert(descriptor_constant->tag == CONSTANT_Utf8); assert(descriptor_constant->tag == CONSTANT_Utf8);
assert(descriptor_constant->utf8.length >= 2); assert(descriptor_constant->utf8.length >= 2);

View File

@ -164,3 +164,4 @@ void vm_start(int class_hash_table_length,
struct hash_table_entry * class_hash_table, struct hash_table_entry * class_hash_table,
const uint8_t * main_class, const uint8_t * main_class,
int main_class_length); int main_class_length);
int descriptor_nargs(struct constant * descriptor_constant, uint8_t * return_type);

View File

@ -19,8 +19,8 @@ public class String {
return this.value; return this.value;
} }
public static String valueOf(Object obj) { public String toString() {
return (obj == null) ? "null" : obj.toString(); return this;
} }
public static String valueOf(boolean b) { public static String valueOf(boolean b) {
@ -42,4 +42,8 @@ public class String {
public static String valueOf(double d) { public static String valueOf(double d) {
return Double.toString(d); return Double.toString(d);
} }
public static String valueOf(Object obj) {
return (obj == null) ? "null" : obj.toString();
}
} }