jvm/c/native.c

201 lines
6.3 KiB
C

#include "hash_table.h"
#include "malloc.h"
#include "string.h"
#include "printf.h"
#include "native.h"
#include "native/class.h"
#include "native/loader.h"
#include "native/math.h"
#include "native/memory.h"
#include "native/object.h"
#include "native/printstream.h"
typedef void (* native_func_t)(struct vm * vm, uint32_t * args);
struct native_method {
const char * class_name;
const char * method_name;
const char * method_descriptor;
native_func_t func;
};
const static struct native_method native_method[] = {
{
.class_name = "java/lang/Math",
.method_name = "sin",
.method_descriptor = "(F)F",
.func = native_java_lang_math_sin_1,
},
{
.class_name = "java/lang/Math",
.method_name = "cos",
.method_descriptor = "(F)F",
.func = native_java_lang_math_cos_1,
},
{
.class_name = "javva/lang/Math",
.method_name = "abs",
.method_descriptor = "(F)F",
.func = native_java_lang_math_abs_1,
},
{
.class_name = "java/misc/Memory",
.method_name = "putU4",
.method_descriptor = "(II)V",
.func = native_java_misc_memory_putU4_2,
},
{
.class_name = "java/misc/Memory",
.method_name = "putU2",
.method_descriptor = "(II)V",
.func = native_java_misc_memory_putU2_2,
},
{
.class_name = "java/misc/Memory",
.method_name = "putU1",
.method_descriptor = "(II)V",
.func = native_java_misc_memory_putU1_2,
},
{
.class_name = "java/misc/Memory",
.method_name = "getU4",
.method_descriptor = "(I)I",
.func = native_java_misc_memory_getU4_1,
},
{
.class_name = "java/misc/Memory",
.method_name = "getU2",
.method_descriptor = "(I)I",
.func = native_java_misc_memory_getU2_1,
},
{
.class_name = "java/misc/Memory",
.method_name = "getU1",
.method_descriptor = "(I)I",
.func = native_java_misc_memory_getU1_1,
},
{
.class_name = "java/misc/Memory",
.method_name = "putSQ1",
.method_descriptor = "(Ljava/lang/Object;I)V",
.func = native_java_misc_memory_putSQ1_2,
},
{
.class_name = "java/misc/Memory",
.method_name = "isBigEndian",
.method_descriptor = "()Z",
.func = native_java_misc_memory_isbigendian_0,
},
{
.class_name = "java/io/PrintStream",
.method_name = "_write",
.method_descriptor = "([B)V",
.func = native_java_io_printstream_write_ba_1,
},
{
.class_name = "java/io/PrintStream",
.method_name = "_write",
.method_descriptor = "([C)V",
.func = native_java_io_printstream_write_ca_1,
},
{
.class_name = "java/io/PrintStream",
.method_name = "_write",
.method_descriptor = "(Ljava/lang/String;)V",
.func = native_java_io_printstream_write_s_1,
},
{
.class_name = "jvm/internal/Loader",
.method_name = "load",
.method_descriptor = "([II)V",
.func = native_jvm_internal_loader_load_2,
},
{
.class_name = "jvm/internal/Loader",
.method_name = "getBuffer",
.method_descriptor = "()I",
.func = native_jvm_internal_loader_getbuffer_0,
},
{
.class_name = "java/lang/Class",
.method_name = "getClassName",
.method_descriptor = "()Ljava/lang/String;",
.func = native_java_lang_class_getclassname_1,
},
{
.class_name = "java/lang/Object",
.method_name = "getClass",
.method_descriptor = "()Ljava/lang/Class;",
.func = native_java_lang_object_getclass_1,
},
{
.class_name = "java/lang/Object",
.method_name = "hashCode",
.method_descriptor = "()I",
.func = native_java_lang_object_hashcode_1,
},
};
struct hash_table_entry * native_init_hash_table(int * hash_table_length)
{
int native_length = (sizeof (native_method)) / (sizeof (native_method[0]));
int native_hash_table_length = hash_table_next_power_of_two(native_length * 2);
uint32_t native_hash_table_size = (sizeof (struct hash_table_entry)) * native_hash_table_length;
struct hash_table_entry * native_hash_table = malloc_class_arena(native_hash_table_size);
hash_table_init(native_hash_table_length, native_hash_table);
for (int i = 0; i < native_length; i++) {
assert(native_method[i].class_name != nullptr);
assert(native_method[i].method_name != nullptr);
assert(native_method[i].method_descriptor != nullptr);
assert(native_method[i].func != nullptr);
int class_name_length = string_length(native_method[i].class_name);
int method_name_length = string_length(native_method[i].method_name);
int method_descriptor_length = string_length(native_method[i].method_descriptor);
debugf("native_init_hash_table add: %s %s %s → %p\n",
native_method[i].class_name,
native_method[i].method_name,
native_method[i].method_descriptor,
native_method[i].func
);
hash_table_add3(native_hash_table_length,
native_hash_table,
(const uint8_t *)native_method[i].class_name,
class_name_length,
(const uint8_t *)native_method[i].method_name,
method_name_length,
(const uint8_t *)native_method[i].method_descriptor,
method_descriptor_length,
native_method[i].func
);
}
*hash_table_length = native_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)
{
struct hash_table_entry * e = hash_table_find3(vm->native_hash_table.length,
vm->native_hash_table.entry,
class_name_constant->utf8.bytes,
class_name_constant->utf8.length,
method_name_constant->utf8.bytes,
method_name_constant->utf8.length,
method_descriptor_constant->utf8.bytes,
method_descriptor_constant->utf8.length
);
assert(e != nullptr);
assert(e->value != nullptr);
native_func_t func = (native_func_t)e->value;
func(vm, args);
}