Compare commits

...

2 Commits

13 changed files with 114 additions and 128 deletions

View File

@ -2,18 +2,19 @@
#include "assert.h" #include "assert.h"
#include "class_file.h" #include "class_file.h"
#include "hash_table.h"
#include "malloc.h"
#include "class_resolver.h" #include "class_resolver.h"
#include "string.h"
#include "memory_allocator.h"
#include "printf.h"
#include "field_size.h"
#include "debug.h" #include "debug.h"
#include "fatal.h" #include "fatal.h"
#include "parse_type.h" #include "field_size.h"
#include "find_attribute.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 "native_types_allocate.h"
#include "parse_type.h"
#include "printf.h"
#include "string.h"
#include "vm_instance.h" #include "vm_instance.h"
static int field_info_field_size(struct class_file * class_file, struct field_info * field_info) 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, static struct Code_attribute * resolve_code_attribute(struct class_entry * class_entry,
struct method_info * method_info) struct method_info * method_info)
{ {
if ((method_info->access_flags & METHOD_ACC_NATIVE) != 0) { assert((method_info->access_flags & METHOD_ACC_NATIVE) == 0);
return nullptr;
}
int code_index = find_code_name_index(class_entry->class_file); int code_index = find_code_name_index(class_entry->class_file);
assert(code_index != 0); assert(code_index != 0);
@ -454,7 +453,8 @@ static struct Code_attribute * resolve_code_attribute(struct class_entry * class
return attribute->code; return attribute->code;
} }
static void resolve_method_entry(struct class_entry * class_entry, static void resolve_method_entry(struct vm * vm,
struct class_entry * class_entry,
struct constant * method_name_constant, struct constant * method_name_constant,
struct constant * method_descriptor_constant, struct constant * method_descriptor_constant,
struct method_entry * method_entry) struct method_entry * method_entry)
@ -470,7 +470,26 @@ static void resolve_method_entry(struct class_entry * class_entry,
method_entry->class_entry = class_entry; method_entry->class_entry = class_entry;
method_entry->method_info = method_info; method_entry->method_info = method_info;
if ((method_info->access_flags & METHOD_ACC_NATIVE) == 0) {
method_entry->code_attribute = resolve_code_attribute(class_entry, method_info); 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(vm->native_hash_table.length,
vm->native_hash_table.entry,
class_name_constant,
method_name_constant,
method_descriptor_constant);
}
debugf("method resolved:\n"); debugf("method resolved:\n");
debugf(" class: "); debugf(" class: ");
@ -480,8 +499,7 @@ static void resolve_method_entry(struct class_entry * class_entry,
debugc('\n'); debugc('\n');
} }
static void resolve_method_entry_from_superclasses(int class_hash_table_length, static void resolve_method_entry_from_superclasses(struct vm * vm,
struct hash_table_entry * class_hash_table,
struct class_entry * class_entry, struct class_entry * class_entry,
struct constant * method_name_constant, struct constant * method_name_constant,
struct constant * method_descriptor_constant, struct constant * method_descriptor_constant,
@ -492,7 +510,8 @@ static void resolve_method_entry_from_superclasses(int class_hash_table_length,
method_entry->method_info = nullptr; method_entry->method_info = nullptr;
while (true) { while (true) {
resolve_method_entry(class_entry, resolve_method_entry(vm,
class_entry,
method_name_constant, method_name_constant,
method_descriptor_constant, method_descriptor_constant,
method_entry); method_entry);
@ -508,20 +527,20 @@ static void resolve_method_entry_from_superclasses(int class_hash_table_length,
assert(class_name_constant->tag == CONSTANT_Utf8); assert(class_name_constant->tag == CONSTANT_Utf8);
// lookup the method from the superclass // lookup the method from the superclass
class_entry = class_resolver_lookup_class_from_class_index(class_hash_table_length, class_entry = class_resolver_lookup_class_from_class_index(vm->class_hash_table.length,
class_hash_table, vm->class_hash_table.entry,
class_entry, class_entry,
class_entry->class_file->super_class); class_entry->class_file->super_class);
assert(class_entry != nullptr); assert(class_entry != nullptr);
} }
} }
struct method_entry class_resolver_lookup_method_from_objectref_class(int class_hash_table_length, struct method_entry class_resolver_lookup_method_from_objectref_class(struct vm * vm,
struct hash_table_entry * class_hash_table,
int32_t methodref_index, int32_t methodref_index,
struct class_entry * objectref_class_entry, struct class_entry * objectref_class_entry)
struct class_entry * origin_class_entry)
{ {
struct class_entry * origin_class_entry = vm->current_frame->class_entry;
struct constant * methodref_constant = &origin_class_entry->class_file->constant_pool[methodref_index - 1]; struct constant * methodref_constant = &origin_class_entry->class_file->constant_pool[methodref_index - 1];
assert(methodref_constant->tag == CONSTANT_InterfaceMethodref || methodref_constant->tag == CONSTANT_Methodref); assert(methodref_constant->tag == CONSTANT_InterfaceMethodref || methodref_constant->tag == CONSTANT_Methodref);
struct constant * nameandtype_constant = &origin_class_entry->class_file->constant_pool[methodref_constant->methodref.name_and_type_index - 1]; struct constant * nameandtype_constant = &origin_class_entry->class_file->constant_pool[methodref_constant->methodref.name_and_type_index - 1];
@ -535,8 +554,7 @@ struct method_entry class_resolver_lookup_method_from_objectref_class(int class_
struct method_entry method_entry; struct method_entry method_entry;
resolve_method_entry_from_superclasses(class_hash_table_length, resolve_method_entry_from_superclasses(vm,
class_hash_table,
class_entry, class_entry,
method_name_constant, method_name_constant,
method_descriptor_constant, method_descriptor_constant,
@ -545,11 +563,10 @@ struct method_entry class_resolver_lookup_method_from_objectref_class(int class_
return method_entry; return method_entry;
} }
struct method_entry * class_resolver_lookup_method_from_origin_class(int class_hash_table_length, struct method_entry * class_resolver_lookup_method_from_origin_class(struct vm * vm,
struct hash_table_entry * class_hash_table, int32_t methodref_index)
int32_t methodref_index,
struct class_entry * origin_class_entry)
{ {
struct class_entry * origin_class_entry = vm->current_frame->class_entry;
if (origin_class_entry->attribute_entry[methodref_index - 1].method_entry != nullptr) { if (origin_class_entry->attribute_entry[methodref_index - 1].method_entry != nullptr) {
debugf("class_resolver_lookup_method_from_origin_class %d: [cached]\n", methodref_index); debugf("class_resolver_lookup_method_from_origin_class %d: [cached]\n", methodref_index);
return origin_class_entry->attribute_entry[methodref_index - 1].method_entry; return origin_class_entry->attribute_entry[methodref_index - 1].method_entry;
@ -564,15 +581,14 @@ struct method_entry * class_resolver_lookup_method_from_origin_class(int class_h
struct constant * method_descriptor_constant = &origin_class_entry->class_file->constant_pool[nameandtype_constant->nameandtype.descriptor_index - 1]; 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); assert(method_descriptor_constant->tag == CONSTANT_Utf8);
struct class_entry * class_entry = class_resolver_lookup_class_from_class_index(class_hash_table_length, struct class_entry * class_entry = class_resolver_lookup_class_from_class_index(vm->class_hash_table.length,
class_hash_table, vm->class_hash_table.entry,
origin_class_entry, origin_class_entry,
methodref_constant->methodref.class_index); methodref_constant->methodref.class_index);
struct method_entry * method_entry = malloc_class_arena((sizeof (struct method_entry))); struct method_entry * method_entry = malloc_class_arena((sizeof (struct method_entry)));
resolve_method_entry_from_superclasses(class_hash_table_length, resolve_method_entry_from_superclasses(vm,
class_hash_table,
class_entry, class_entry,
method_name_constant, method_name_constant,
method_descriptor_constant, method_descriptor_constant,
@ -597,8 +613,8 @@ struct method_entry class_resolver_lookup_method_from_method_name_method_descrip
method_name_length, method_name_length,
method_descriptor, method_descriptor,
method_descriptor_length); method_descriptor_length);
if (method_info != nullptr) { if (method_info != nullptr) {
assert ((method_info->access_flags & METHOD_ACC_NATIVE) == 0);
int code_index = find_code_name_index(class_entry->class_file); int code_index = find_code_name_index(class_entry->class_file);
assert(code_index != 0); assert(code_index != 0);
debugf("code_index: %d\n", code_index); debugf("code_index: %d\n", code_index);

View File

@ -19,15 +19,11 @@ struct class_entry * class_resolver_lookup_class_from_class_index(int class_hash
struct class_entry * class_entry, struct class_entry * class_entry,
int32_t class_index); int32_t class_index);
struct method_entry class_resolver_lookup_method_from_objectref_class(int class_hash_table_length, struct method_entry class_resolver_lookup_method_from_objectref_class(struct vm * vm,
struct hash_table_entry * class_hash_table,
int32_t methodref_index, int32_t methodref_index,
struct class_entry * objectref_class_entry, struct class_entry * objectref_class_entry);
struct class_entry * origin_class_entry); struct method_entry * class_resolver_lookup_method_from_origin_class(struct vm * vm,
struct method_entry * class_resolver_lookup_method_from_origin_class(int class_hash_table_length, int32_t methodref_index);
struct hash_table_entry * class_hash_table,
int32_t methodref_index,
struct class_entry * origin_class_entry);
struct method_entry class_resolver_lookup_method_from_method_name_method_descriptor(struct class_entry * class_entry, struct method_entry class_resolver_lookup_method_from_method_name_method_descriptor(struct class_entry * class_entry,
const uint8_t * method_name, const uint8_t * method_name,

View File

@ -1210,11 +1210,9 @@ void op_invokeinterface(struct vm * vm, uint32_t index, uint32_t count)
return vm_exception(vm, vm_instance_create(vm, "java/lang/NullPointerException")); return vm_exception(vm, vm_instance_create(vm, "java/lang/NullPointerException"));
struct method_entry method_entry = struct method_entry method_entry =
class_resolver_lookup_method_from_objectref_class(vm->class_hash_table.length, class_resolver_lookup_method_from_objectref_class(vm,
vm->class_hash_table.entry,
index, index,
objectref->class_entry, objectref->class_entry);
vm->current_frame->class_entry);
vm_special_method_call(vm, method_entry.class_entry, &method_entry); vm_special_method_call(vm, method_entry.class_entry, &method_entry);
} }
@ -1239,10 +1237,7 @@ void op_invokespecial(struct vm * vm, uint32_t index)
return vm_exception(vm, vm_instance_create(vm, "java/lang/NullPointerException")); return vm_exception(vm, vm_instance_create(vm, "java/lang/NullPointerException"));
struct method_entry * method_entry = struct method_entry * method_entry =
class_resolver_lookup_method_from_origin_class(vm->class_hash_table.length, class_resolver_lookup_method_from_origin_class(vm, index);
vm->class_hash_table.entry,
index,
vm->current_frame->class_entry);
vm_special_method_call(vm, method_entry->class_entry, method_entry); vm_special_method_call(vm, method_entry->class_entry, method_entry);
} }
@ -1250,10 +1245,7 @@ void op_invokespecial(struct vm * vm, uint32_t index)
void op_invokestatic(struct vm * vm, uint32_t index) void op_invokestatic(struct vm * vm, uint32_t index)
{ {
struct method_entry * method_entry = struct method_entry * method_entry =
class_resolver_lookup_method_from_origin_class(vm->class_hash_table.length, class_resolver_lookup_method_from_origin_class(vm, index);
vm->class_hash_table.entry,
index,
vm->current_frame->class_entry);
/* On successful resolution of the method, the class or interface that /* On successful resolution of the method, the class or interface that
declared the resolved method is initialized if that class or interface has declared the resolved method is initialized if that class or interface has
@ -1282,11 +1274,9 @@ void op_invokevirtual(struct vm * vm, uint32_t index)
return vm_exception(vm, vm_instance_create(vm, "java/lang/NullPointerException")); return vm_exception(vm, vm_instance_create(vm, "java/lang/NullPointerException"));
struct method_entry method_entry = struct method_entry method_entry =
class_resolver_lookup_method_from_objectref_class(vm->class_hash_table.length, class_resolver_lookup_method_from_objectref_class(vm,
vm->class_hash_table.entry,
index, index,
objectref->class_entry, objectref->class_entry);
vm->current_frame->class_entry);
vm_special_method_call(vm, method_entry.class_entry, &method_entry); vm_special_method_call(vm, method_entry.class_entry, &method_entry);
} }

View File

@ -2,7 +2,6 @@
#include <stdint.h> #include <stdint.h>
#include "vm.h"
#include "assert.h" #include "assert.h"
enum initialization_state { enum initialization_state {
@ -11,10 +10,17 @@ enum initialization_state {
CLASS_INITIALIZED, CLASS_INITIALIZED,
}; };
struct vm;
typedef void (native_func_t)(struct vm * vm, uint32_t * args);
struct method_entry { struct method_entry {
struct class_entry * class_entry; struct class_entry * class_entry;
struct method_info * method_info; struct method_info * method_info;
union {
struct Code_attribute * code_attribute; struct Code_attribute * code_attribute;
native_func_t * native_func;
};
}; };
union attribute_entry { union attribute_entry {
@ -74,6 +80,20 @@ struct stack {
int32_t capacity; 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) static inline struct frame * stack_push_frame(struct stack * stack, int num_frames)
{ {
struct frame * frame = &stack->frame[stack->ix]; struct frame * frame = &stack->frame[stack->ix];

View File

@ -2,7 +2,7 @@
#include "string.h" #include "string.h"
#include "class_resolver.h" #include "class_resolver.h"
#include "native.h" #include "native_method.h"
#include "malloc.h" #include "malloc.h"
#include "classpath.h" #include "classpath.h"

View File

@ -1,12 +1,12 @@
#include <stdlib.h> #include <stdlib.h>
#include "printf.h"
#include "class_resolver.h" #include "class_resolver.h"
#include "string.h"
#include "file.h" #include "file.h"
#include "malloc.h" #include "malloc.h"
#include "native.h"
#include "memory_allocator.h" #include "memory_allocator.h"
#include "native_method.h"
#include "printf.h"
#include "string.h"
void * memset(void * s, int c, size_t n); void * memset(void * s, int c, size_t n);

View File

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

View File

@ -1,10 +1,10 @@
#include "class_resolver.h"
#include "loader.h"
#include "malloc.h"
#include "native_method.h"
#include "native_types.h" #include "native_types.h"
#include "printf.h" #include "printf.h"
#include "string.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))); static uint8_t loader_buffer[0x100000] __attribute__ ((aligned (32)));

View File

@ -1,8 +1,6 @@
#include "frame_stack.h" // for native_func_t
#include "hash_table.h" #include "hash_table.h"
#include "malloc.h" #include "malloc.h"
#include "string.h"
#include "printf.h"
#include "native.h"
#include "native/class.h" #include "native/class.h"
#include "native/libcinputstream.h" #include "native/libcinputstream.h"
#include "native/loader.h" #include "native/loader.h"
@ -13,14 +11,15 @@
#include "native/runtime.h" #include "native/runtime.h"
#include "native/sh4intrinsic.h" #include "native/sh4intrinsic.h"
#include "native/system.h" #include "native/system.h"
#include "native_method.h"
typedef void (* native_func_t)(struct vm * vm, uint32_t * args); #include "printf.h"
#include "string.h"
struct native_method { struct native_method {
const char * class_name; const char * class_name;
const char * method_name; const char * method_name;
const char * method_descriptor; const char * method_descriptor;
native_func_t func; native_func_t * func;
}; };
const static struct native_method native_method[] = { 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; return native_hash_table;
} }
void native_method_call(struct vm * vm, 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 * class_name_constant,
struct constant * method_name_constant, struct constant * method_name_constant,
struct constant * method_descriptor_constant, struct constant * method_descriptor_constant)
uint32_t * args)
{ {
struct hash_table_entry * e = hash_table_find3(vm->native_hash_table.length, struct hash_table_entry * e = hash_table_find3(native_hash_table_length,
vm->native_hash_table.entry, native_hash_table,
class_name_constant->utf8.bytes, class_name_constant->utf8.bytes,
class_name_constant->utf8.length, class_name_constant->utf8.length,
method_name_constant->utf8.bytes, method_name_constant->utf8.bytes,
@ -327,6 +326,5 @@ void native_method_call(struct vm * vm,
assert(e != nullptr); assert(e != nullptr);
assert(e->value != nullptr); assert(e->value != nullptr);
native_func_t func = (native_func_t)e->value; return(native_func_t *)e->value;
func(vm, args);
} }

11
c/native_method.h Normal file
View File

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

23
c/vm.c
View File

@ -7,7 +7,6 @@
#include "class_resolver.h" #include "class_resolver.h"
#include "printf.h" #include "printf.h"
#include "string.h" #include "string.h"
#include "native.h"
#include "fatal.h" #include "fatal.h"
#include "debug.h" #include "debug.h"
#include "find_attribute.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; 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; int old_stack_ix = vm->current_frame->operand_stack_ix;
native_method_call(vm, method_entry->native_func(vm, args);
class_name_constant,
method_name_constant,
method_descriptor_constant,
args);
if (return_type != 'V') { if (return_type != 'V') {
assert(old_stack_ix == vm->current_frame->operand_stack_ix - 1); assert(old_stack_ix == vm->current_frame->operand_stack_ix - 1);

14
c/vm.h
View File

@ -3,20 +3,6 @@
#include "frame_stack.h" #include "frame_stack.h"
#include "class_file.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); 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_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); void vm_static_method_call(struct vm * vm, struct class_entry * class_entry, struct method_entry * method_entry);

View File

@ -20,7 +20,7 @@ OBJ = \
c/hash_table.o \ c/hash_table.o \
c/malloc.o \ c/malloc.o \
c/memory_allocator.o \ c/memory_allocator.o \
c/native.o \ c/native_method.o \
c/native/class.o \ c/native/class.o \
c/native/loader.o \ c/native/loader.o \
c/native/math.o \ c/native/math.o \