memoize native method lookups in method_entry

This commit is contained in:
Zack Buhman 2025-01-21 21:31:32 -06:00
parent 45501b58cb
commit 8f49f69e7e
13 changed files with 114 additions and 86 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,9 @@ 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(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_name_constant,
struct constant * method_descriptor_constant, struct constant * method_descriptor_constant,
struct method_entry * method_entry) 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->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(native_hash_table_length,
native_hash_table,
class_name_constant,
method_name_constant,
method_descriptor_constant);
}
debugf("method resolved:\n"); debugf("method resolved:\n");
debugf(" class: "); 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, static void resolve_method_entry_from_superclasses(int class_hash_table_length,
struct hash_table_entry * class_hash_table, 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 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 +514,9 @@ 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(native_hash_table_length,
native_hash_table,
class_entry,
method_name_constant, method_name_constant,
method_descriptor_constant, method_descriptor_constant,
method_entry); 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 method_entry class_resolver_lookup_method_from_objectref_class(int class_hash_table_length,
struct hash_table_entry * class_hash_table, struct hash_table_entry * class_hash_table,
int native_hash_table_length,
struct hash_table_entry * native_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)
@ -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, resolve_method_entry_from_superclasses(class_hash_table_length,
class_hash_table, class_hash_table,
native_hash_table_length,
native_hash_table,
class_entry, class_entry,
method_name_constant, method_name_constant,
method_descriptor_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 method_entry * class_resolver_lookup_method_from_origin_class(int class_hash_table_length,
struct hash_table_entry * class_hash_table, struct hash_table_entry * class_hash_table,
int native_hash_table_length,
struct hash_table_entry * native_hash_table,
int32_t methodref_index, int32_t methodref_index,
struct class_entry * origin_class_entry) 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, resolve_method_entry_from_superclasses(class_hash_table_length,
class_hash_table, class_hash_table,
native_hash_table_length,
native_hash_table,
class_entry, class_entry,
method_name_constant, method_name_constant,
method_descriptor_constant, method_descriptor_constant,
@ -597,8 +629,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

@ -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 method_entry class_resolver_lookup_method_from_objectref_class(int class_hash_table_length,
struct hash_table_entry * class_hash_table, struct hash_table_entry * class_hash_table,
int native_hash_table_length,
struct hash_table_entry * native_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);
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(int class_hash_table_length,
struct hash_table_entry * class_hash_table, struct hash_table_entry * class_hash_table,
int native_hash_table_length,
struct hash_table_entry * native_hash_table,
int32_t methodref_index, int32_t methodref_index,
struct class_entry * origin_class_entry); struct class_entry * origin_class_entry);

View File

@ -1212,6 +1212,8 @@ void op_invokeinterface(struct vm * vm, uint32_t index, uint32_t count)
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->class_hash_table.length,
vm->class_hash_table.entry, vm->class_hash_table.entry,
vm->native_hash_table.length,
vm->native_hash_table.entry,
index, index,
objectref->class_entry, objectref->class_entry,
vm->current_frame->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 = 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->class_hash_table.length,
vm->class_hash_table.entry, vm->class_hash_table.entry,
vm->native_hash_table.length,
vm->native_hash_table.entry,
index, index,
vm->current_frame->class_entry); vm->current_frame->class_entry);
@ -1252,6 +1256,8 @@ 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->class_hash_table.length,
vm->class_hash_table.entry, vm->class_hash_table.entry,
vm->native_hash_table.length,
vm->native_hash_table.entry,
index, index,
vm->current_frame->class_entry); vm->current_frame->class_entry);
@ -1284,6 +1290,8 @@ void op_invokevirtual(struct vm * vm, uint32_t index)
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->class_hash_table.length,
vm->class_hash_table.entry, vm->class_hash_table.entry,
vm->native_hash_table.length,
vm->native_hash_table.entry,
index, index,
objectref->class_entry, objectref->class_entry,
vm->current_frame->class_entry); vm->current_frame->class_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 \