diff --git a/c/class_resolver.c b/c/class_resolver.c index 078b45d..4165842 100644 --- a/c/class_resolver.c +++ b/c/class_resolver.c @@ -515,8 +515,13 @@ struct method_entry * class_resolver_lookup_method_from_methodref_index(int clas struct attribute_info * attribute = find_attribute(code_index, method_info->attributes_count, method_info->attributes); - assert(attribute != nullptr); - method_entry->code_attribute = attribute->code; + if ((method_info->access_flags & METHOD_ACC_NATIVE) != 0) { + assert(attribute == nullptr); + method_entry->code_attribute = nullptr; + } else { + assert(attribute != nullptr); + method_entry->code_attribute = attribute->code; + } origin_class_entry->attribute_entry[methodref_index - 1].method_entry = method_entry; return method_entry; diff --git a/c/execute.c b/c/execute.c index 13ffd92..2d752e7 100644 --- a/c/execute.c +++ b/c/execute.c @@ -7,7 +7,6 @@ #include "field_size.h" #include "debug.h" #include "parse_type.h" -#include "backtrace.h" void op_aaload(struct vm * vm) { @@ -126,8 +125,8 @@ void op_astore_3(struct vm * vm) void op_athrow(struct vm * vm) { - backtrace_print(vm); - assert(!"op_athrow"); + int32_t * objectref = (int32_t *)operand_stack_pop_u32(vm->current_frame); + vm_exception(vm, objectref); } void op_baload(struct vm * vm) diff --git a/c/find_attribute.c b/c/find_attribute.c index f7ca750..0a0abbb 100644 --- a/c/find_attribute.c +++ b/c/find_attribute.c @@ -47,7 +47,9 @@ struct attribute_info * find_attribute(int name_index, int attributes_count, struct attribute_info * attributes) { + debugf("find_attribute: name_index=%d attributes_count=%d\n", name_index, attributes_count); for (int i = 0; i < attributes_count; i++) { + debugf("find_attribute: attribute[%d]: %d\n", i, attributes[i].attribute_name_index); if (attributes[i].attribute_name_index == name_index) return &attributes[i]; } diff --git a/c/frame.c b/c/frame.c index de6dd1d..8d76660 100644 --- a/c/frame.c +++ b/c/frame.c @@ -12,6 +12,7 @@ #include "fatal.h" #include "debug.h" #include "find_attribute.h" +#include "backtrace.h" int descriptor_nargs(struct constant * descriptor_constant, uint8_t * return_type) { @@ -173,9 +174,10 @@ void vm_native_method_call(struct vm * vm, struct class_entry * class_entry, str struct constant * class_constant = &class_entry->class_file->constant_pool[class_entry->class_file->this_class - 1]; struct constant * class_name_constant = &class_entry->class_file->constant_pool[class_constant->class.name_index - 1]; debug_print__constant__utf8_string(class_name_constant); - debugf(" "); + debugs(" "); struct constant * method_name_constant = &class_entry->class_file->constant_pool[method_entry->method_info->name_index - 1]; debug_print__constant__utf8_string(method_name_constant); + debugc('\n'); int java_lang_math_length = 14; @@ -470,7 +472,44 @@ void vm_method_return(struct vm * vm) break; } assert(old_frame->operand_stack_ix == 0); - debugf("vm_method_return\n"); + if (vm->frame_stack.ix > 0) { + debugs("vm_method_return\n"); + debugs("current_frame:\n class: "); + debug_print__class_entry__class_name(vm->current_frame->class_entry); + debugs("\n method: "); + debug_print__method_info__method_name(vm->current_frame->class_entry, vm->current_frame->method_info); + debugf("\n pc: %d", vm->current_frame->pc); + debugf("\n next_pc: %d\n", vm->current_frame->next_pc); + } +} + +void vm_exception(struct vm * vm, int32_t * objectref) +{ + // If objectref is null, athrow throws a NullPointerException instead of objectref. + assert(objectref != nullptr); + + while (vm->frame_stack.ix > 0) { + for (int i = 0; i < vm->current_frame->code_attribute->exception_table_length; i++) { + struct exception_table_entry * entry = &vm->current_frame->code_attribute->exception_table[i]; + if (vm->current_frame->pc >= entry->start_pc && vm->current_frame->pc < entry->end_pc) { + operand_stack_push_u32(vm->current_frame, (uint32_t)objectref); + vm->current_frame->next_pc = entry->handler_pc; + + debugs("vm_exception (handled)\n"); + debugs("current_frame:\n class: "); + debug_print__class_entry__class_name(vm->current_frame->class_entry); + debugs("\n method: "); + debug_print__method_info__method_name(vm->current_frame->class_entry, vm->current_frame->method_info); + debugf("\n pc: %d", vm->current_frame->pc); + debugf("\n next_pc: %d\n", vm->current_frame->next_pc); + + return; + } + } + vm->current_frame = stack_pop_frame(&vm->frame_stack, 1); + } + backtrace_print(vm); + assert(!"exception"); } static void print_vm_stack(struct vm * vm) diff --git a/c/frame.h b/c/frame.h index b0a90a8..5c02b24 100644 --- a/c/frame.h +++ b/c/frame.h @@ -165,3 +165,4 @@ struct vm * vm_start(int class_hash_table_length, const uint8_t * main_class_name, int main_class_name_length); int descriptor_nargs(struct constant * descriptor_constant, uint8_t * return_type); +void vm_exception(struct vm * vm, int32_t * objectref); diff --git a/p/TestException.java b/p/TestException.java index bf9273a..19984a6 100644 --- a/p/TestException.java +++ b/p/TestException.java @@ -10,6 +10,7 @@ class TestException { test2(); } catch (Exception e) { System.out.println(e); + throw e; } }