diff --git a/c/class_resolver.c b/c/class_resolver.c index 2a5acff..f32adc7 100644 --- a/c/class_resolver.c +++ b/c/class_resolver.c @@ -389,7 +389,7 @@ struct method_entry class_resolver_lookup_method_from_interfacemethodref_index(i struct class_entry * origin_class_entry) { 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]; assert(nameandtype_constant->tag == CONSTANT_NameAndType); struct constant * method_name_constant = &origin_class_entry->class_file->constant_pool[nameandtype_constant->nameandtype.name_index - 1]; diff --git a/c/execute.c b/c/execute.c index f4b54e9..cac7f4a 100644 --- a/c/execute.c +++ b/c/execute.c @@ -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); } +#include "debug.h" + void op_invokevirtual(struct vm * vm, uint32_t index) { - struct method_entry * method_entry = - class_resolver_lookup_method_from_methodref_index(vm->class_hash_table.length, - vm->class_hash_table.entry, - index, - vm->current_frame->class_entry); + struct class_entry * origin_class_entry = 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) diff --git a/c/frame.c b/c/frame.c index b79d3b0..b033308 100644 --- a/c/frame.c +++ b/c/frame.c @@ -48,7 +48,7 @@ int find_constantvalue_name_index(struct class_file * class_file) 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->utf8.length >= 2); diff --git a/c/frame.h b/c/frame.h index 74fa9c1..7eeb09d 100644 --- a/c/frame.h +++ b/c/frame.h @@ -164,3 +164,4 @@ void vm_start(int class_hash_table_length, struct hash_table_entry * class_hash_table, const uint8_t * main_class, int main_class_length); +int descriptor_nargs(struct constant * descriptor_constant, uint8_t * return_type); diff --git a/java/lang/String.java b/java/lang/String.java index 4a781d4..82b7cd2 100644 --- a/java/lang/String.java +++ b/java/lang/String.java @@ -19,8 +19,8 @@ public class String { return this.value; } - public static String valueOf(Object obj) { - return (obj == null) ? "null" : obj.toString(); + public String toString() { + return this; } public static String valueOf(boolean b) { @@ -42,4 +42,8 @@ public class String { public static String valueOf(double d) { return Double.toString(d); } + + public static String valueOf(Object obj) { + return (obj == null) ? "null" : obj.toString(); + } }