diff --git a/c/class_resolver.c b/c/class_resolver.c index e867f57..9964f3e 100644 --- a/c/class_resolver.c +++ b/c/class_resolver.c @@ -2,18 +2,19 @@ #include "assert.h" #include "class_file.h" -#include "hash_table.h" -#include "malloc.h" #include "class_resolver.h" -#include "string.h" -#include "memory_allocator.h" -#include "printf.h" -#include "field_size.h" #include "debug.h" #include "fatal.h" -#include "parse_type.h" +#include "field_size.h" #include "find_attribute.h" +#include "hash_table.h" +#include "malloc.h" +#include "memory_allocator.h" +#include "native_method.h" #include "native_types_allocate.h" +#include "parse_type.h" +#include "printf.h" +#include "string.h" #include "vm_instance.h" static int field_info_field_size(struct class_file * class_file, struct field_info * field_info) @@ -441,9 +442,7 @@ struct method_info * class_resolver_lookup_method(int methods_hash_table_length, static struct Code_attribute * resolve_code_attribute(struct class_entry * class_entry, struct method_info * method_info) { - if ((method_info->access_flags & METHOD_ACC_NATIVE) != 0) { - return nullptr; - } + assert((method_info->access_flags & METHOD_ACC_NATIVE) == 0); int code_index = find_code_name_index(class_entry->class_file); assert(code_index != 0); @@ -454,7 +453,9 @@ static struct Code_attribute * resolve_code_attribute(struct class_entry * class return attribute->code; } -static void resolve_method_entry(struct class_entry * class_entry, +static void resolve_method_entry(int native_hash_table_length, + struct hash_table_entry * native_hash_table, + struct class_entry * class_entry, struct constant * method_name_constant, struct constant * method_descriptor_constant, struct method_entry * method_entry) @@ -470,7 +471,26 @@ static void resolve_method_entry(struct class_entry * class_entry, method_entry->class_entry = class_entry; method_entry->method_info = method_info; - method_entry->code_attribute = resolve_code_attribute(class_entry, method_info); + if ((method_info->access_flags & METHOD_ACC_NATIVE) == 0) { + method_entry->code_attribute = resolve_code_attribute(class_entry, method_info); + } else { + struct class_file * class_file = class_entry->class_file; + + struct constant * class_constant = &class_file->constant_pool[class_file->this_class - 1]; + assert(class_constant->tag == CONSTANT_Class); + struct constant * class_name_constant = &class_file->constant_pool[class_constant->class.name_index - 1]; + assert(class_name_constant->tag == CONSTANT_Utf8); + struct constant * method_name_constant = &class_file->constant_pool[method_info->name_index - 1]; + assert(method_name_constant->tag == CONSTANT_Utf8); + struct constant * method_descriptor_constant = &class_file->constant_pool[method_info->descriptor_index - 1]; + assert(method_descriptor_constant->tag == CONSTANT_Utf8); + + method_entry->native_func = native_method_lookup(native_hash_table_length, + native_hash_table, + class_name_constant, + method_name_constant, + method_descriptor_constant); + } debugf("method resolved:\n"); debugf(" class: "); @@ -482,6 +502,8 @@ static void resolve_method_entry(struct class_entry * class_entry, static void resolve_method_entry_from_superclasses(int class_hash_table_length, struct hash_table_entry * class_hash_table, + int native_hash_table_length, + struct hash_table_entry * native_hash_table, struct class_entry * class_entry, struct constant * method_name_constant, struct constant * method_descriptor_constant, @@ -492,7 +514,9 @@ static void resolve_method_entry_from_superclasses(int class_hash_table_length, method_entry->method_info = nullptr; while (true) { - resolve_method_entry(class_entry, + resolve_method_entry(native_hash_table_length, + native_hash_table, + class_entry, method_name_constant, method_descriptor_constant, method_entry); @@ -518,6 +542,8 @@ static void resolve_method_entry_from_superclasses(int class_hash_table_length, struct method_entry class_resolver_lookup_method_from_objectref_class(int class_hash_table_length, struct hash_table_entry * class_hash_table, + int native_hash_table_length, + struct hash_table_entry * native_hash_table, int32_t methodref_index, struct class_entry * objectref_class_entry, struct class_entry * origin_class_entry) @@ -537,6 +563,8 @@ struct method_entry class_resolver_lookup_method_from_objectref_class(int class_ resolve_method_entry_from_superclasses(class_hash_table_length, class_hash_table, + native_hash_table_length, + native_hash_table, class_entry, method_name_constant, method_descriptor_constant, @@ -547,6 +575,8 @@ struct method_entry class_resolver_lookup_method_from_objectref_class(int class_ struct method_entry * class_resolver_lookup_method_from_origin_class(int class_hash_table_length, struct hash_table_entry * class_hash_table, + int native_hash_table_length, + struct hash_table_entry * native_hash_table, int32_t methodref_index, struct class_entry * origin_class_entry) { @@ -573,6 +603,8 @@ struct method_entry * class_resolver_lookup_method_from_origin_class(int class_h resolve_method_entry_from_superclasses(class_hash_table_length, class_hash_table, + native_hash_table_length, + native_hash_table, class_entry, method_name_constant, method_descriptor_constant, @@ -597,8 +629,8 @@ struct method_entry class_resolver_lookup_method_from_method_name_method_descrip method_name_length, method_descriptor, method_descriptor_length); - if (method_info != nullptr) { + assert ((method_info->access_flags & METHOD_ACC_NATIVE) == 0); int code_index = find_code_name_index(class_entry->class_file); assert(code_index != 0); debugf("code_index: %d\n", code_index); diff --git a/c/class_resolver.h b/c/class_resolver.h index 5a48e87..25f0312 100644 --- a/c/class_resolver.h +++ b/c/class_resolver.h @@ -21,11 +21,15 @@ struct class_entry * class_resolver_lookup_class_from_class_index(int class_hash struct method_entry class_resolver_lookup_method_from_objectref_class(int class_hash_table_length, struct hash_table_entry * class_hash_table, + int native_hash_table_length, + struct hash_table_entry * native_hash_table, int32_t methodref_index, struct class_entry * objectref_class_entry, struct class_entry * origin_class_entry); struct method_entry * class_resolver_lookup_method_from_origin_class(int class_hash_table_length, struct hash_table_entry * class_hash_table, + int native_hash_table_length, + struct hash_table_entry * native_hash_table, int32_t methodref_index, struct class_entry * origin_class_entry); diff --git a/c/execute.c b/c/execute.c index cfcd658..8c4fbb6 100644 --- a/c/execute.c +++ b/c/execute.c @@ -1212,6 +1212,8 @@ void op_invokeinterface(struct vm * vm, uint32_t index, uint32_t count) struct method_entry method_entry = class_resolver_lookup_method_from_objectref_class(vm->class_hash_table.length, vm->class_hash_table.entry, + vm->native_hash_table.length, + vm->native_hash_table.entry, index, objectref->class_entry, vm->current_frame->class_entry); @@ -1241,6 +1243,8 @@ void op_invokespecial(struct vm * vm, uint32_t index) struct method_entry * method_entry = class_resolver_lookup_method_from_origin_class(vm->class_hash_table.length, vm->class_hash_table.entry, + vm->native_hash_table.length, + vm->native_hash_table.entry, index, vm->current_frame->class_entry); @@ -1252,6 +1256,8 @@ void op_invokestatic(struct vm * vm, uint32_t index) struct method_entry * method_entry = class_resolver_lookup_method_from_origin_class(vm->class_hash_table.length, vm->class_hash_table.entry, + vm->native_hash_table.length, + vm->native_hash_table.entry, index, vm->current_frame->class_entry); @@ -1284,6 +1290,8 @@ void op_invokevirtual(struct vm * vm, uint32_t index) struct method_entry method_entry = class_resolver_lookup_method_from_objectref_class(vm->class_hash_table.length, vm->class_hash_table.entry, + vm->native_hash_table.length, + vm->native_hash_table.entry, index, objectref->class_entry, vm->current_frame->class_entry); diff --git a/c/frame_stack.h b/c/frame_stack.h index d2f734f..9b3ce56 100644 --- a/c/frame_stack.h +++ b/c/frame_stack.h @@ -2,7 +2,6 @@ #include -#include "vm.h" #include "assert.h" enum initialization_state { @@ -11,10 +10,17 @@ enum initialization_state { CLASS_INITIALIZED, }; +struct vm; + +typedef void (native_func_t)(struct vm * vm, uint32_t * args); + struct method_entry { struct class_entry * class_entry; struct method_info * method_info; - struct Code_attribute * code_attribute; + union { + struct Code_attribute * code_attribute; + native_func_t * native_func; + }; }; union attribute_entry { @@ -74,6 +80,20 @@ struct stack { int32_t capacity; }; +struct vm { + struct stack frame_stack; + struct stack data_stack; + struct frame * current_frame; + struct { + int length; + struct hash_table_entry * entry; + } class_hash_table; + struct { + int length; + struct hash_table_entry * entry; + } native_hash_table; +}; + static inline struct frame * stack_push_frame(struct stack * stack, int num_frames) { struct frame * frame = &stack->frame[stack->ix]; diff --git a/c/main_dreamcast.c b/c/main_dreamcast.c index 8d1b718..7d62230 100644 --- a/c/main_dreamcast.c +++ b/c/main_dreamcast.c @@ -2,7 +2,7 @@ #include "string.h" #include "class_resolver.h" -#include "native.h" +#include "native_method.h" #include "malloc.h" #include "classpath.h" diff --git a/c/main_hosted.c b/c/main_hosted.c index ca1c9a8..48d2070 100644 --- a/c/main_hosted.c +++ b/c/main_hosted.c @@ -1,12 +1,12 @@ #include -#include "printf.h" #include "class_resolver.h" -#include "string.h" #include "file.h" #include "malloc.h" -#include "native.h" #include "memory_allocator.h" +#include "native_method.h" +#include "printf.h" +#include "string.h" void * memset(void * s, int c, size_t n); diff --git a/c/native.h b/c/native.h deleted file mode 100644 index 5c8b254..0000000 --- a/c/native.h +++ /dev/null @@ -1,10 +0,0 @@ -#pragma once - -#include "vm.h" - -void native_method_call(struct vm * vm, - struct constant * class_name_constant, - struct constant * method_name_constant, - struct constant * method_descriptor_constant, - uint32_t * args); -struct hash_table_entry * native_init_hash_table(int * hash_table_length); diff --git a/c/native/loader.c b/c/native/loader.c index 7a344b1..5d79df8 100644 --- a/c/native/loader.c +++ b/c/native/loader.c @@ -1,10 +1,10 @@ +#include "class_resolver.h" +#include "loader.h" +#include "malloc.h" +#include "native_method.h" #include "native_types.h" #include "printf.h" #include "string.h" -#include "malloc.h" -#include "loader.h" -#include "native.h" -#include "class_resolver.h" static uint8_t loader_buffer[0x100000] __attribute__ ((aligned (32))); diff --git a/c/native.c b/c/native_method.c similarity index 93% rename from c/native.c rename to c/native_method.c index ce844bb..ca4d1fd 100644 --- a/c/native.c +++ b/c/native_method.c @@ -1,8 +1,6 @@ +#include "frame_stack.h" // for native_func_t #include "hash_table.h" #include "malloc.h" -#include "string.h" -#include "printf.h" -#include "native.h" #include "native/class.h" #include "native/libcinputstream.h" #include "native/loader.h" @@ -13,14 +11,15 @@ #include "native/runtime.h" #include "native/sh4intrinsic.h" #include "native/system.h" - -typedef void (* native_func_t)(struct vm * vm, uint32_t * args); +#include "native_method.h" +#include "printf.h" +#include "string.h" struct native_method { const char * class_name; const char * method_name; const char * method_descriptor; - native_func_t func; + native_func_t * func; }; const static struct native_method native_method[] = { @@ -301,14 +300,14 @@ struct hash_table_entry * native_init_hash_table(int * hash_table_length) return native_hash_table; } -void native_method_call(struct vm * vm, - struct constant * class_name_constant, - struct constant * method_name_constant, - struct constant * method_descriptor_constant, - uint32_t * args) +native_func_t * native_method_lookup(int native_hash_table_length, + struct hash_table_entry * native_hash_table, + struct constant * class_name_constant, + struct constant * method_name_constant, + struct constant * method_descriptor_constant) { - struct hash_table_entry * e = hash_table_find3(vm->native_hash_table.length, - vm->native_hash_table.entry, + struct hash_table_entry * e = hash_table_find3(native_hash_table_length, + native_hash_table, class_name_constant->utf8.bytes, class_name_constant->utf8.length, method_name_constant->utf8.bytes, @@ -327,6 +326,5 @@ void native_method_call(struct vm * vm, assert(e != nullptr); assert(e->value != nullptr); - native_func_t func = (native_func_t)e->value; - func(vm, args); + return(native_func_t *)e->value; } diff --git a/c/native_method.h b/c/native_method.h new file mode 100644 index 0000000..d678375 --- /dev/null +++ b/c/native_method.h @@ -0,0 +1,11 @@ +#pragma once + +#include "vm.h" + +struct hash_table_entry * native_init_hash_table(int * hash_table_length); + +native_func_t * native_method_lookup(int native_hash_table_length, + struct hash_table_entry * native_hash_table, + struct constant * class_name_constant, + struct constant * method_name_constant, + struct constant * method_descriptor_constant); diff --git a/c/vm.c b/c/vm.c index 540e1cf..fb0beaf 100644 --- a/c/vm.c +++ b/c/vm.c @@ -7,7 +7,6 @@ #include "class_resolver.h" #include "printf.h" #include "string.h" -#include "native.h" #include "fatal.h" #include "debug.h" #include "find_attribute.h" @@ -174,29 +173,9 @@ void vm_native_method_call(struct vm * vm, struct class_entry * class_entry, str args[nargs - i - 1] = value; } - debugf("native: "); - 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); - debugs(" "); - struct constant * method_name_constant = &class_entry->class_file->constant_pool[method_entry->method_info->name_index - 1]; - assert(method_name_constant->tag == CONSTANT_Utf8); - debug_print__constant__utf8_string(method_name_constant); - debugs(" "); - struct constant * method_descriptor_constant = &class_entry->class_file->constant_pool[method_entry->method_info->descriptor_index - 1]; - assert(method_descriptor_constant->tag == CONSTANT_Utf8); - debug_print__constant__utf8_string(method_descriptor_constant); - debugc('\n'); - int old_stack_ix = vm->current_frame->operand_stack_ix; - native_method_call(vm, - class_name_constant, - method_name_constant, - method_descriptor_constant, - args); + method_entry->native_func(vm, args); if (return_type != 'V') { assert(old_stack_ix == vm->current_frame->operand_stack_ix - 1); diff --git a/c/vm.h b/c/vm.h index 226b17e..ee80dbc 100644 --- a/c/vm.h +++ b/c/vm.h @@ -3,20 +3,6 @@ #include "frame_stack.h" #include "class_file.h" -struct vm { - struct stack frame_stack; - struct stack data_stack; - struct frame * current_frame; - struct { - int length; - struct hash_table_entry * entry; - } class_hash_table; - struct { - int length; - struct hash_table_entry * entry; - } native_hash_table; -}; - bool vm_initialize_class(struct vm * vm, struct class_entry * class_entry); void vm_special_method_call(struct vm * vm, struct class_entry * class_entry, struct method_entry * method_entry); void vm_static_method_call(struct vm * vm, struct class_entry * class_entry, struct method_entry * method_entry); diff --git a/java.mk b/java.mk index 7237e72..0a2de3c 100644 --- a/java.mk +++ b/java.mk @@ -20,7 +20,7 @@ OBJ = \ c/hash_table.o \ c/malloc.o \ c/memory_allocator.o \ - c/native.o \ + c/native_method.o \ c/native/class.o \ c/native/loader.o \ c/native/math.o \