diff --git a/c/class_resolver.c b/c/class_resolver.c index 561f331..ac3939c 100644 --- a/c/class_resolver.c +++ b/c/class_resolver.c @@ -10,6 +10,7 @@ #include "memory_allocator.h" #include "printf.h" #include "field_size.h" +#include "debug.h" static int field_info_field_size(struct class_file * class_file, struct field_info * field_info) { @@ -328,7 +329,7 @@ struct field_entry * class_resolver_lookup_field_from_fieldref_index(int fields_ int fieldref_index) { if (class_entry->attribute_entry[fieldref_index - 1].field_entry != nullptr) { - debugf("class_resolver_lookup_method_from_fieldref_index %d: [cached]\n", fieldref_index); + debugf("class_resolver_lookup_field_from_fieldref_index %d: [cached]\n", fieldref_index); return class_entry->attribute_entry[fieldref_index - 1].field_entry; } @@ -381,44 +382,71 @@ struct method_info * class_resolver_lookup_method(int methods_hash_table_length, return (struct method_info *)e->value; } -struct method_info * class_resolver_lookup_method_from_methodref_index(int methods_hash_table_length, - struct hash_table_entry * methods_hash_table, - struct class_entry * class_entry, - int methodref_index) +struct method_entry * class_resolver_lookup_method_from_methodref_index(int class_hash_table_length, + struct hash_table_entry * class_hash_table, + int32_t methodref_index, + struct class_entry * original_class_entry) { - if (class_entry->attribute_entry[methodref_index - 1].method_info != nullptr) { + if (original_class_entry->attribute_entry[methodref_index - 1].method_entry != nullptr) { debugf("class_resolver_lookup_method_from_methodref_index %d: [cached]\n", methodref_index); - return class_entry->attribute_entry[methodref_index - 1].method_info; + return original_class_entry->attribute_entry[methodref_index - 1].method_entry; } - struct constant * methodref_constant = &class_entry->class_file->constant_pool[methodref_index - 1]; - #ifdef DEBUG + struct constant * methodref_constant = &original_class_entry->class_file->constant_pool[methodref_index - 1]; assert(methodref_constant->tag == CONSTANT_Methodref); - #endif - struct constant * nameandtype_constant = &class_entry->class_file->constant_pool[methodref_constant->methodref.name_and_type_index - 1]; - #ifdef DEBUG + struct constant * nameandtype_constant = &original_class_entry->class_file->constant_pool[methodref_constant->methodref.name_and_type_index - 1]; assert(nameandtype_constant->tag == CONSTANT_NameAndType); - #endif - struct constant * method_name_constant = &class_entry->class_file->constant_pool[nameandtype_constant->nameandtype.name_index - 1]; - #ifdef DEBUG + struct constant * method_name_constant = &original_class_entry->class_file->constant_pool[nameandtype_constant->nameandtype.name_index - 1]; assert(method_name_constant->tag == CONSTANT_Utf8); - #endif - struct constant * method_descriptor_constant = &class_entry->class_file->constant_pool[nameandtype_constant->nameandtype.descriptor_index - 1]; - #ifdef DEBUG + struct constant * method_descriptor_constant = &original_class_entry->class_file->constant_pool[nameandtype_constant->nameandtype.descriptor_index - 1]; assert(method_descriptor_constant->tag == CONSTANT_Utf8); - #endif - struct method_info * method_info = class_resolver_lookup_method(methods_hash_table_length, - methods_hash_table, - method_name_constant->utf8.bytes, - method_name_constant->utf8.length, - method_descriptor_constant->utf8.bytes, - method_descriptor_constant->utf8.length); + struct class_entry * class_entry = class_resolver_lookup_class_from_class_index(class_hash_table_length, + class_hash_table, + original_class_entry, + methodref_constant->methodref.class_index); - // cache the result - class_entry->attribute_entry[methodref_index - 1].method_info = method_info; + while (true) { + struct method_info * method_info = class_resolver_lookup_method(class_entry->methods.length, + class_entry->methods.entry, + method_name_constant->utf8.bytes, + method_name_constant->utf8.length, + method_descriptor_constant->utf8.bytes, + method_descriptor_constant->utf8.length); + if (method_info != nullptr) { + // cache the result + debugf("method resolved:\n"); + debugf(" class: "); + debug_print__class_entry__class_name(class_entry); + debugf("\n method: "); + debug_print__method_info__method_name(class_entry, method_info); + debugc('\n'); - return method_info; + struct method_entry * method_entry = malloc_class_arena((sizeof (struct method_entry))); + method_entry->class_entry = class_entry; + method_entry->method_info = method_info; + original_class_entry->attribute_entry[methodref_index - 1].method_entry = method_entry; + return method_entry; + } + + if (class_entry->class_file->super_class == 0) + break; + + struct constant * class_constant = &class_entry->class_file->constant_pool[class_entry->class_file->super_class - 1]; + assert(class_constant->tag == CONSTANT_Class); + struct constant * class_name_constant = &class_entry->class_file->constant_pool[class_constant->class.name_index - 1]; + assert(class_name_constant->tag == CONSTANT_Utf8); + print_utf8_string(class_name_constant); + debugf("\n"); + + // lookup the method from the superclass + class_entry = class_resolver_lookup_class_from_class_index(class_hash_table_length, + class_hash_table, + class_entry, + class_entry->class_file->super_class); + assert(class_entry != nullptr); + } + return nullptr; } int32_t * class_resolver_lookup_string(int class_hash_table_length, diff --git a/c/class_resolver.h b/c/class_resolver.h index 1da8b21..bc6d419 100644 --- a/c/class_resolver.h +++ b/c/class_resolver.h @@ -11,9 +11,14 @@ enum initialization_state { CLASS_INITIALIZED, }; -union attribute_entry { +struct method_entry { struct class_entry * class_entry; struct method_info * method_info; +}; + +union attribute_entry { + struct class_entry * class_entry; + struct method_entry * method_entry; struct field_entry * field_entry; int32_t * string_objectref; }; @@ -66,10 +71,10 @@ struct method_info * class_resolver_lookup_method(int methods_hash_table_length, int method_name_length, const uint8_t * method_descriptor, int method_descriptor_length); -struct method_info * class_resolver_lookup_method_from_methodref_index(int methods_hash_table_length, - struct hash_table_entry * methods_hash_table, - struct class_entry * class_entry, - int methodref_index); +struct method_entry * class_resolver_lookup_method_from_methodref_index(int class_hash_table_length, + struct hash_table_entry * class_hash_table, + int32_t methodref_index, + struct class_entry * original_class_entry); struct field_entry * class_resolver_lookup_field(int fields_hash_table_length, struct hash_table_entry * fields_hash_table, const uint8_t * field_name, diff --git a/c/debug.c b/c/debug.c new file mode 100644 index 0000000..1f01408 --- /dev/null +++ b/c/debug.c @@ -0,0 +1,32 @@ +#include "printf.h" +#include "debug.h" +#include "assert.h" + +void debug_print__constant__utf8_string(struct constant * constant) +{ + for (int i = 0; i < constant->utf8.length; i++) { + debugc(constant->utf8.bytes[i]); + } +} + +void debug_print__class_entry__class_name(struct class_entry * class_entry) +{ + struct constant * class_constant = &class_entry->class_file->constant_pool[class_entry->class_file->this_class - 1]; + assert(class_constant->tag == CONSTANT_Class); + struct constant * class_name_constant = &class_entry->class_file->constant_pool[class_constant->class.name_index - 1]; + assert(class_name_constant->tag == CONSTANT_Utf8); + debug_print__constant__utf8_string(class_name_constant); +} + +void debug_print__method_info__method_name(struct class_entry * class_entry, struct method_info * method_info) +{ + struct constant * method_name_constant = &class_entry->class_file->constant_pool[method_info->name_index - 1]; + assert(method_name_constant->tag == CONSTANT_Utf8); + debug_print__constant__utf8_string(method_name_constant); + + debugc(' '); + + struct constant * method_descriptor_constant = &class_entry->class_file->constant_pool[method_info->descriptor_index - 1]; + assert(method_descriptor_constant->tag == CONSTANT_Utf8); + debug_print__constant__utf8_string(method_descriptor_constant); +} diff --git a/c/debug.h b/c/debug.h new file mode 100644 index 0000000..aa7d923 --- /dev/null +++ b/c/debug.h @@ -0,0 +1,8 @@ +#pragma once + +#include "class_file.h" +#include "class_resolver.h" + +void debug_print__constant__utf8_string(struct constant * constant); +void debug_print__class_entry__class_name(struct class_entry * class_entry); +void debug_print__method_info__method_name(struct class_entry * class_entry, struct method_info * method_info); diff --git a/c/execute.c b/c/execute.c index e6d7da8..655a289 100644 --- a/c/execute.c +++ b/c/execute.c @@ -1122,39 +1122,39 @@ void op_invokeinterface(struct vm * vm, uint32_t index, uint32_t count) void op_invokespecial(struct vm * vm, uint32_t index) { - struct class_entry * class_entry; - struct method_info * method_info; - class_entry_method_info_from_constant_index(vm, index, - &class_entry, - &method_info); + 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); - vm_special_method_call(vm, class_entry, method_info); + vm_special_method_call(vm, method_entry->class_entry, method_entry->method_info); } void op_invokestatic(struct vm * vm, uint32_t index) { - struct class_entry * class_entry; - struct method_info * method_info; - class_entry_method_info_from_constant_index(vm, index, - &class_entry, - &method_info); + 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); /* On successful resolution of the method, the class or interface that declared the resolved method is initialized if that class or interface has not already been initialized (ยง5.5). */ - vm_static_method_call(vm, class_entry, method_info); + vm_static_method_call(vm, method_entry->class_entry, method_entry->method_info); } void op_invokevirtual(struct vm * vm, uint32_t index) { - struct class_entry * class_entry; - struct method_info * method_info; - class_entry_method_info_from_constant_index(vm, index, - &class_entry, - &method_info); + 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); - vm_special_method_call(vm, class_entry, method_info); + vm_special_method_call(vm, method_entry->class_entry, method_entry->method_info); } void op_ior(struct vm * vm) diff --git a/c/execute_helper.h b/c/execute_helper.h index 6f37bf8..cf6ac7a 100644 --- a/c/execute_helper.h +++ b/c/execute_helper.h @@ -36,29 +36,3 @@ static inline void class_entry_field_entry_from_constant_index(struct vm * vm, assert((*field_descriptor_constant)->tag == CONSTANT_Utf8); #endif } - -static inline void class_entry_method_info_from_constant_index(struct vm * vm, - int32_t index, - struct class_entry ** class_entry, - struct method_info ** method_info) -{ - struct constant * methodref_constant = &vm->current_frame->class_entry->class_file->constant_pool[index - 1]; - #ifdef DEBUG - assert(methodref_constant->tag == CONSTANT_Methodref); - #endif - - *class_entry = class_resolver_lookup_class_from_class_index(vm->class_hash_table.length, - vm->class_hash_table.entry, - vm->current_frame->class_entry, - methodref_constant->methodref.class_index); - assert(*class_entry != nullptr); - - int methods_hash_table_length = (*class_entry)->methods.length; - struct hash_table_entry * methods_hash_table = (*class_entry)->methods.entry; - - *method_info = class_resolver_lookup_method_from_methodref_index(methods_hash_table_length, - methods_hash_table, - vm->current_frame->class_entry, - index); - assert(*method_info != nullptr); -} diff --git a/java.mk b/java.mk index 6893389..a8e2510 100644 --- a/java.mk +++ b/java.mk @@ -17,7 +17,8 @@ OBJ = \ c/printf.o \ c/parse.o \ c/unparse.o \ - c/native.o + c/native.o \ + c/debug.o MAIN_DREAMCAST_OBJ = \ c/sh7091_scif.o \ diff --git a/p/InheritanceTest.java b/p/InheritanceTest.java index 7a6ce1e..11fe675 100644 --- a/p/InheritanceTest.java +++ b/p/InheritanceTest.java @@ -5,22 +5,18 @@ class A { static int baz = 3; static int bleh = 4; - /* - public int foo(int a, int b) { - return a + b; + public int foo(int a) { + return a + baz; } - */ } class B extends A { static int baz = 5; int horse; - /* public int bar(int a) { return a * egg; } - */ } class InheritanceTest { @@ -58,7 +54,13 @@ class InheritanceTest { return b.egg * b.horse; } + static int method_test() { + B b = new B(); + b.egg = 5; + return b.foo(b.bar(6)); + } + public static void main() { - instance_test(); + method_test(); } } diff --git a/p/InterfaceTest.java b/p/InterfaceTest.java new file mode 100644 index 0000000..aedca60 --- /dev/null +++ b/p/InterfaceTest.java @@ -0,0 +1,17 @@ +package p; + +class InterfaceTest implements Interface +{ + public static int test() + { + InterfaceTest it = new InterfaceTest(); + System.out.println(it.a); + Interface.a = "1234"; + return (int)it.a.getBytes()[0]; + } + + public static void main() + { + test(); + } +}