initial throw/catch implementation

This commit is contained in:
Zack Buhman 2025-01-05 20:36:07 -06:00
parent 6760cd0b0b
commit 7914abe702
6 changed files with 54 additions and 7 deletions

View File

@ -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);
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;

View File

@ -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)

View File

@ -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];
}

View File

@ -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)

View File

@ -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);

View File

@ -10,6 +10,7 @@ class TestException {
test2();
} catch (Exception e) {
System.out.println(e);
throw e;
}
}