java.nio: partial Path/Files/FileSystem/InputStream implementation
This commit is contained in:
parent
e83cf7f092
commit
86e18a0944
2
Makefile
2
Makefile
@ -10,7 +10,7 @@ CFLAGS += -Wall -Werror -Wfatal-errors -Wno-error=unused-variable -fstack-protec
|
|||||||
CFLAGS += -I$(MAKEFILE_PATH)/
|
CFLAGS += -I$(MAKEFILE_PATH)/
|
||||||
CFLAGS += -I$(MAKEFILE_PATH)/c
|
CFLAGS += -I$(MAKEFILE_PATH)/c
|
||||||
CFLAGS += -DDEBUG
|
CFLAGS += -DDEBUG
|
||||||
CFLAGS += -DDEBUG_PRINT
|
#CFLAGS += -DDEBUG_PRINT
|
||||||
LDFLAGS = -lm
|
LDFLAGS = -lm
|
||||||
OPT ?= -O0
|
OPT ?= -O0
|
||||||
DEPFLAGS = -MMD -MP
|
DEPFLAGS = -MMD -MP
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "native_types.h"
|
#include "native_types.h"
|
||||||
#include "frame.h"
|
#include "vm.h"
|
||||||
|
|
||||||
struct backtrace_entry {
|
struct backtrace_entry {
|
||||||
struct class_file * class_file;
|
struct class_file * class_file;
|
||||||
|
@ -13,7 +13,6 @@
|
|||||||
#include "fatal.h"
|
#include "fatal.h"
|
||||||
#include "parse_type.h"
|
#include "parse_type.h"
|
||||||
#include "find_attribute.h"
|
#include "find_attribute.h"
|
||||||
#include "frame.h"
|
|
||||||
#include "native_types_allocate.h"
|
#include "native_types_allocate.h"
|
||||||
#include "vm_instance.h"
|
#include "vm_instance.h"
|
||||||
|
|
||||||
|
@ -5,53 +5,7 @@
|
|||||||
#include "class_file.h"
|
#include "class_file.h"
|
||||||
#include "hash_table.h"
|
#include "hash_table.h"
|
||||||
#include "native_types.h"
|
#include "native_types.h"
|
||||||
|
#include "vm.h"
|
||||||
enum initialization_state {
|
|
||||||
CLASS_UNINITIALIZED,
|
|
||||||
CLASS_INITIALIZING,
|
|
||||||
CLASS_INITIALIZED,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct method_entry {
|
|
||||||
struct class_entry * class_entry;
|
|
||||||
struct method_info * method_info;
|
|
||||||
struct Code_attribute * code_attribute;
|
|
||||||
};
|
|
||||||
|
|
||||||
union attribute_entry {
|
|
||||||
struct class_entry * class_entry;
|
|
||||||
struct method_entry * method_entry;
|
|
||||||
struct field_entry * field_entry;
|
|
||||||
struct objectref * string_objectref;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct field_entry {
|
|
||||||
struct class_entry * class_entry;
|
|
||||||
struct field_info * field_info;
|
|
||||||
union {
|
|
||||||
int32_t instance_index;
|
|
||||||
int32_t static_index;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
struct class_entry {
|
|
||||||
struct class_file * class_file;
|
|
||||||
enum initialization_state initialization_state;
|
|
||||||
union attribute_entry * attribute_entry;
|
|
||||||
int32_t static_fields_count;
|
|
||||||
int32_t * static_fields;
|
|
||||||
int32_t instance_fields_count;
|
|
||||||
|
|
||||||
struct {
|
|
||||||
int length;
|
|
||||||
struct hash_table_entry * entry;
|
|
||||||
} fields;
|
|
||||||
|
|
||||||
struct {
|
|
||||||
int length;
|
|
||||||
struct hash_table_entry * entry;
|
|
||||||
} methods;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct hash_table_entry * class_resolver_load_from_buffers(const uint8_t ** buffers,
|
struct hash_table_entry * class_resolver_load_from_buffers(const uint8_t ** buffers,
|
||||||
int length,
|
int length,
|
||||||
@ -94,3 +48,7 @@ bool class_resolver_instanceof(int class_hash_table_length,
|
|||||||
struct class_entry * origin_class_entry,
|
struct class_entry * origin_class_entry,
|
||||||
const int class_index,
|
const int class_index,
|
||||||
struct objectref * objectref);
|
struct objectref * objectref);
|
||||||
|
|
||||||
|
struct objectref * class_resolver_lookup_string(struct vm * vm,
|
||||||
|
struct class_entry * class_entry,
|
||||||
|
const int string_index);
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "frame.h"
|
#include "vm.h"
|
||||||
|
|
||||||
uint32_t decode_print_instruction(const uint8_t * code, uint32_t pc);
|
uint32_t decode_print_instruction(const uint8_t * code, uint32_t pc);
|
||||||
void decode_execute_instruction(struct vm * vm, const uint8_t * code, uint32_t pc);
|
void decode_execute_instruction(struct vm * vm, const uint8_t * code, uint32_t pc);
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include "frame.h"
|
#include "vm.h"
|
||||||
|
|
||||||
void op_aaload(struct vm * vm);
|
void op_aaload(struct vm * vm);
|
||||||
void op_aastore(struct vm * vm);
|
void op_aastore(struct vm * vm);
|
||||||
|
@ -1,8 +1,3 @@
|
|||||||
// declared here due to circular frame.h include in class_resolver.h
|
|
||||||
struct objectref * class_resolver_lookup_string(struct vm * vm,
|
|
||||||
struct class_entry * class_entry,
|
|
||||||
const int string_index);
|
|
||||||
|
|
||||||
static inline struct field_entry * field_entry_from_constant_index(int class_hash_table_length,
|
static inline struct field_entry * field_entry_from_constant_index(int class_hash_table_length,
|
||||||
struct hash_table_entry * class_hash_table,
|
struct hash_table_entry * class_hash_table,
|
||||||
struct class_entry * origin_class_entry,
|
struct class_entry * origin_class_entry,
|
||||||
|
@ -1,9 +1,56 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "vm.h"
|
||||||
#include "assert.h"
|
#include "assert.h"
|
||||||
#include "class_file.h"
|
|
||||||
#include "class_resolver.h"
|
enum initialization_state {
|
||||||
#include "native_types.h"
|
CLASS_UNINITIALIZED,
|
||||||
|
CLASS_INITIALIZING,
|
||||||
|
CLASS_INITIALIZED,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct method_entry {
|
||||||
|
struct class_entry * class_entry;
|
||||||
|
struct method_info * method_info;
|
||||||
|
struct Code_attribute * code_attribute;
|
||||||
|
};
|
||||||
|
|
||||||
|
union attribute_entry {
|
||||||
|
struct class_entry * class_entry;
|
||||||
|
struct method_entry * method_entry;
|
||||||
|
struct field_entry * field_entry;
|
||||||
|
struct objectref * string_objectref;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct field_entry {
|
||||||
|
struct class_entry * class_entry;
|
||||||
|
struct field_info * field_info;
|
||||||
|
union {
|
||||||
|
int32_t instance_index;
|
||||||
|
int32_t static_index;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
struct class_entry {
|
||||||
|
struct class_file * class_file;
|
||||||
|
enum initialization_state initialization_state;
|
||||||
|
union attribute_entry * attribute_entry;
|
||||||
|
int32_t static_fields_count;
|
||||||
|
int32_t * static_fields;
|
||||||
|
int32_t instance_fields_count;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
int length;
|
||||||
|
struct hash_table_entry * entry;
|
||||||
|
} fields;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
int length;
|
||||||
|
struct hash_table_entry * entry;
|
||||||
|
} methods;
|
||||||
|
};
|
||||||
|
|
||||||
struct frame {
|
struct frame {
|
||||||
struct class_entry * class_entry;
|
struct class_entry * class_entry;
|
||||||
@ -27,20 +74,6 @@ 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];
|
||||||
@ -182,17 +215,3 @@ static inline double operand_stack_pop_f64(struct frame * frame)
|
|||||||
double f = *((double *)&value);
|
double f = *((double *)&value);
|
||||||
return f;
|
return f;
|
||||||
}
|
}
|
||||||
|
|
||||||
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_static_method_call(struct vm * vm, struct class_entry * class_entry, struct method_entry * method_entry);
|
|
||||||
void vm_method_return(struct vm * vm);
|
|
||||||
void vm_execute(struct vm * vm);
|
|
||||||
struct vm * vm_start(int class_hash_table_length,
|
|
||||||
struct hash_table_entry * class_hash_table,
|
|
||||||
int native_hash_table_length,
|
|
||||||
struct hash_table_entry * native_hash_table,
|
|
||||||
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, struct objectref * objectref);
|
|
4
c/gc.c
4
c/gc.c
@ -1,6 +1,8 @@
|
|||||||
#include "frame.h"
|
#include "gc.h"
|
||||||
#include "memory_allocator.h"
|
#include "memory_allocator.h"
|
||||||
#include "printf.h"
|
#include "printf.h"
|
||||||
|
#include "hash_table.h"
|
||||||
|
#include "native_types.h"
|
||||||
|
|
||||||
static void walk_address(void * address);
|
static void walk_address(void * address);
|
||||||
|
|
||||||
|
2
c/gc.h
2
c/gc.h
@ -1,6 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "frame.h"
|
#include "vm.h"
|
||||||
|
|
||||||
void gc_mark(struct vm * vm);
|
void gc_mark(struct vm * vm);
|
||||||
void gc_sweep();
|
void gc_sweep();
|
||||||
|
21
c/native.c
21
c/native.c
@ -4,6 +4,7 @@
|
|||||||
#include "printf.h"
|
#include "printf.h"
|
||||||
#include "native.h"
|
#include "native.h"
|
||||||
#include "native/class.h"
|
#include "native/class.h"
|
||||||
|
#include "native/libcinputstream.h"
|
||||||
#include "native/loader.h"
|
#include "native/loader.h"
|
||||||
#include "native/math.h"
|
#include "native/math.h"
|
||||||
#include "native/memory.h"
|
#include "native/memory.h"
|
||||||
@ -160,6 +161,26 @@ const static struct native_method native_method[] = {
|
|||||||
.method_descriptor = "(Ljava/lang/Object;)I",
|
.method_descriptor = "(Ljava/lang/Object;)I",
|
||||||
.func = native_java_lang_system_hashcode_1,
|
.func = native_java_lang_system_hashcode_1,
|
||||||
},
|
},
|
||||||
|
#if !defined(__dreamcast__)
|
||||||
|
{
|
||||||
|
.class_name = "jvm/internal/LibcInputStream",
|
||||||
|
.method_name = "_open",
|
||||||
|
.method_descriptor = "([B)I",
|
||||||
|
.func = native_jvm_internal_libcinputstream_open_1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.class_name = "jvm/internal/LibcInputStream",
|
||||||
|
.method_name = "_close",
|
||||||
|
.method_descriptor = "(I)V",
|
||||||
|
.func = native_jvm_internal_libcinputstream_close_1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.class_name = "jvm/internal/LibcInputStream",
|
||||||
|
.method_name = "_read",
|
||||||
|
.method_descriptor = "(I)I",
|
||||||
|
.func = native_jvm_internal_libcinputstream_read_1,
|
||||||
|
},
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
struct hash_table_entry * native_init_hash_table(int * hash_table_length)
|
struct hash_table_entry * native_init_hash_table(int * hash_table_length)
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "frame.h"
|
#include "vm.h"
|
||||||
|
|
||||||
void native_method_call(struct vm * vm,
|
void native_method_call(struct vm * vm,
|
||||||
struct constant * class_name_constant,
|
struct constant * class_name_constant,
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#include "class.h"
|
#include "class.h"
|
||||||
#include "printf.h"
|
#include "printf.h"
|
||||||
#include "vm_instance.h"
|
#include "vm_instance.h"
|
||||||
|
#include "class_resolver.h"
|
||||||
|
|
||||||
void native_java_lang_class_getname_1(struct vm * vm, uint32_t * args)
|
void native_java_lang_class_getname_1(struct vm * vm, uint32_t * args)
|
||||||
{
|
{
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include "frame.h"
|
#include "vm.h"
|
||||||
|
|
||||||
void native_java_lang_class_getname_1(struct vm * vm, uint32_t * args);
|
void native_java_lang_class_getname_1(struct vm * vm, uint32_t * args);
|
||||||
void native_java_lang_class_getsuperclass_1(struct vm * vm, uint32_t * args);
|
void native_java_lang_class_getsuperclass_1(struct vm * vm, uint32_t * args);
|
||||||
|
38
c/native/libcinputstream.c
Normal file
38
c/native/libcinputstream.c
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "libcinputstream.h"
|
||||||
|
#include "assert.h"
|
||||||
|
#include "native_types.h"
|
||||||
|
|
||||||
|
void native_jvm_internal_libcinputstream_open_1(struct vm * vm, uint32_t * args)
|
||||||
|
{
|
||||||
|
struct arrayref * arrayref = (struct arrayref *)args[0];
|
||||||
|
assert(arrayref != nullptr);
|
||||||
|
assert(arrayref->length > 0);
|
||||||
|
assert(arrayref->u8[arrayref->length - 1] == 0);
|
||||||
|
FILE * file = fopen((const char *)arrayref->u8, "rb");
|
||||||
|
assert(file != nullptr);
|
||||||
|
|
||||||
|
operand_stack_push_u32(vm->current_frame, (uint32_t)file);
|
||||||
|
}
|
||||||
|
|
||||||
|
void native_jvm_internal_libcinputstream_close_1(struct vm * vm, uint32_t * args)
|
||||||
|
{
|
||||||
|
FILE * file = (FILE *)args[0];
|
||||||
|
assert(file != nullptr);
|
||||||
|
int ret = fclose(file);
|
||||||
|
assert(ret == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void native_jvm_internal_libcinputstream_read_1(struct vm * vm, uint32_t * args)
|
||||||
|
{
|
||||||
|
FILE * file = (FILE *)args[0];
|
||||||
|
assert(file != nullptr);
|
||||||
|
|
||||||
|
uint8_t buf[1];
|
||||||
|
int32_t size = fread(buf, 1, 1, file);
|
||||||
|
if (size == 0)
|
||||||
|
operand_stack_push_u32(vm->current_frame, (uint32_t)-1);
|
||||||
|
else
|
||||||
|
operand_stack_push_u32(vm->current_frame, (uint32_t)buf[0]);
|
||||||
|
}
|
9
c/native/libcinputstream.h
Normal file
9
c/native/libcinputstream.h
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "vm.h"
|
||||||
|
|
||||||
|
void native_jvm_internal_libcinputstream_open_1(struct vm * vm, uint32_t * args);
|
||||||
|
void native_jvm_internal_libcinputstream_close_1(struct vm * vm, uint32_t * args);
|
||||||
|
void native_jvm_internal_libcinputstream_read_1(struct vm * vm, uint32_t * args);
|
@ -4,6 +4,7 @@
|
|||||||
#include "malloc.h"
|
#include "malloc.h"
|
||||||
#include "loader.h"
|
#include "loader.h"
|
||||||
#include "native.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)));
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include "frame.h"
|
#include "vm.h"
|
||||||
|
|
||||||
void native_jvm_internal_loader_getbuffer_0(struct vm * vm, uint32_t * args);
|
void native_jvm_internal_loader_getbuffer_0(struct vm * vm, uint32_t * args);
|
||||||
void native_jvm_internal_loader_load_2(struct vm * vm, uint32_t * args);
|
void native_jvm_internal_loader_load_2(struct vm * vm, uint32_t * args);
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include "frame.h"
|
#include "vm.h"
|
||||||
|
|
||||||
void native_java_lang_math_sin_1(struct vm * vm, uint32_t * args);
|
void native_java_lang_math_sin_1(struct vm * vm, uint32_t * args);
|
||||||
void native_java_lang_math_cos_1(struct vm * vm, uint32_t * args);
|
void native_java_lang_math_cos_1(struct vm * vm, uint32_t * args);
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include "frame.h"
|
#include "vm.h"
|
||||||
|
|
||||||
void native_java_misc_memory_putU4_2(struct vm * vm, uint32_t * args);
|
void native_java_misc_memory_putU4_2(struct vm * vm, uint32_t * args);
|
||||||
void native_java_misc_memory_putU2_2(struct vm * vm, uint32_t * args);
|
void native_java_misc_memory_putU2_2(struct vm * vm, uint32_t * args);
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#include "object.h"
|
#include "object.h"
|
||||||
#include "vm_instance.h"
|
#include "vm_instance.h"
|
||||||
|
#include "native_types.h"
|
||||||
|
|
||||||
void native_java_lang_object_getclass_1(struct vm * vm, uint32_t * args)
|
void native_java_lang_object_getclass_1(struct vm * vm, uint32_t * args)
|
||||||
{
|
{
|
||||||
|
@ -2,6 +2,6 @@
|
|||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include "frame.h"
|
#include "vm.h"
|
||||||
|
|
||||||
void native_java_lang_object_getclass_1(struct vm * vm, uint32_t * args);
|
void native_java_lang_object_getclass_1(struct vm * vm, uint32_t * args);
|
||||||
|
@ -5,18 +5,22 @@
|
|||||||
void native_java_io_printstream_write_ba_1(struct vm * vm, uint32_t * args)
|
void native_java_io_printstream_write_ba_1(struct vm * vm, uint32_t * args)
|
||||||
{
|
{
|
||||||
struct arrayref * arrayref = (struct arrayref *)args[0];
|
struct arrayref * arrayref = (struct arrayref *)args[0];
|
||||||
|
assert(arrayref != nullptr);
|
||||||
print_bytes(arrayref->u8, arrayref->length);
|
print_bytes(arrayref->u8, arrayref->length);
|
||||||
}
|
}
|
||||||
|
|
||||||
void native_java_io_printstream_write_ca_1(struct vm * vm, uint32_t * args)
|
void native_java_io_printstream_write_ca_1(struct vm * vm, uint32_t * args)
|
||||||
{
|
{
|
||||||
struct arrayref * arrayref = (struct arrayref *)args[0];
|
struct arrayref * arrayref = (struct arrayref *)args[0];
|
||||||
|
assert(arrayref != nullptr);
|
||||||
print_chars(arrayref->u16, arrayref->length);
|
print_chars(arrayref->u16, arrayref->length);
|
||||||
}
|
}
|
||||||
|
|
||||||
void native_java_io_printstream_write_s_1(struct vm * vm, uint32_t * args)
|
void native_java_io_printstream_write_s_1(struct vm * vm, uint32_t * args)
|
||||||
{
|
{
|
||||||
struct objectref * objectref = (struct objectref *)args[0];
|
struct objectref * objectref = (struct objectref *)args[0];
|
||||||
|
assert(objectref != nullptr);
|
||||||
struct arrayref * arrayref = objectref->aref[0];
|
struct arrayref * arrayref = objectref->aref[0];
|
||||||
|
assert(arrayref != nullptr);
|
||||||
print_chars(arrayref->u16, arrayref->length);
|
print_chars(arrayref->u16, arrayref->length);
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include "frame.h"
|
#include "vm.h"
|
||||||
|
|
||||||
void native_java_io_printstream_write_ba_1(struct vm * vm, uint32_t * args);
|
void native_java_io_printstream_write_ba_1(struct vm * vm, uint32_t * args);
|
||||||
void native_java_io_printstream_write_ca_1(struct vm * vm, uint32_t * args);
|
void native_java_io_printstream_write_ca_1(struct vm * vm, uint32_t * args);
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include "frame.h"
|
#include "vm.h"
|
||||||
|
|
||||||
void native_java_lang_runtime_freememory_0(struct vm * vm, uint32_t * args);
|
void native_java_lang_runtime_freememory_0(struct vm * vm, uint32_t * args);
|
||||||
void native_java_lang_runtime_gc_0(struct vm * vm, uint32_t * args);
|
void native_java_lang_runtime_gc_0(struct vm * vm, uint32_t * args);
|
||||||
|
@ -2,6 +2,6 @@
|
|||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include "frame.h"
|
#include "vm.h"
|
||||||
|
|
||||||
void native_java_lang_system_hashcode_1(struct vm * vm, uint32_t * args);
|
void native_java_lang_system_hashcode_1(struct vm * vm, uint32_t * args);
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include "assert.h"
|
#include "assert.h"
|
||||||
#include "class_resolver.h"
|
|
||||||
#include "memory_allocator.h"
|
#include "memory_allocator.h"
|
||||||
|
|
||||||
enum tag_type {
|
enum tag_type {
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "native_types.h"
|
#include "native_types.h"
|
||||||
#include "frame.h"
|
|
||||||
#include "gc.h"
|
#include "gc.h"
|
||||||
|
#include "vm.h"
|
||||||
|
#include "memory_allocator.h"
|
||||||
|
|
||||||
static inline void * gc_memory_allocate(struct vm * vm, int size)
|
static inline void * gc_memory_allocate(struct vm * vm, int size)
|
||||||
{
|
{
|
||||||
|
@ -4,7 +4,6 @@
|
|||||||
#include "class_file.h"
|
#include "class_file.h"
|
||||||
#include "bytes.h"
|
#include "bytes.h"
|
||||||
#include "decode.h"
|
#include "decode.h"
|
||||||
#include "frame.h"
|
|
||||||
#include "class_resolver.h"
|
#include "class_resolver.h"
|
||||||
#include "printf.h"
|
#include "printf.h"
|
||||||
#include "string.h"
|
#include "string.h"
|
||||||
@ -104,20 +103,26 @@ bool vm_initialize_class(struct vm * vm, struct class_entry * class_entry)
|
|||||||
|
|
||||||
for (int j = 0; j < field_info->attributes_count; j++) {
|
for (int j = 0; j < field_info->attributes_count; j++) {
|
||||||
if (field_info->attributes[j].attribute_name_index == constantvalue_name_index) {
|
if (field_info->attributes[j].attribute_name_index == constantvalue_name_index) {
|
||||||
struct attribute_info * attribute = &field_info->attributes[j];
|
|
||||||
struct constant * constantvalue = &class_file->constant_pool[attribute->constantvalue->constantvalue_index - 1];
|
|
||||||
assert(constantvalue->tag == CONSTANT_Integer); // also need to support CONSTANT_String
|
|
||||||
|
|
||||||
struct constant * name_constant = &class_file->constant_pool[field_info->name_index - 1];
|
struct constant * name_constant = &class_file->constant_pool[field_info->name_index - 1];
|
||||||
assert(name_constant->tag == CONSTANT_Utf8);
|
assert(name_constant->tag == CONSTANT_Utf8);
|
||||||
|
|
||||||
struct field_entry * field_entry = class_resolver_lookup_field(class_entry->fields.length,
|
struct field_entry * field_entry = class_resolver_lookup_field(class_entry->fields.length,
|
||||||
class_entry->fields.entry,
|
class_entry->fields.entry,
|
||||||
name_constant->utf8.bytes,
|
name_constant->utf8.bytes,
|
||||||
name_constant->utf8.length);
|
name_constant->utf8.length);
|
||||||
assert(field_entry != nullptr);
|
assert(field_entry != nullptr);
|
||||||
|
|
||||||
|
struct attribute_info * attribute = &field_info->attributes[j];
|
||||||
|
struct constant * constantvalue = &class_file->constant_pool[attribute->constantvalue->constantvalue_index - 1];
|
||||||
|
if (constantvalue->tag == CONSTANT_Integer) {
|
||||||
class_entry->static_fields[field_entry->static_index] = constantvalue->integer.bytes;
|
class_entry->static_fields[field_entry->static_index] = constantvalue->integer.bytes;
|
||||||
debugf(" constantvalue: %d\n", constantvalue->integer.bytes);
|
} else if (constantvalue->tag == CONSTANT_String) {
|
||||||
|
struct objectref * objectref = class_resolver_lookup_string(vm,
|
||||||
|
class_entry,
|
||||||
|
attribute->constantvalue->constantvalue_index);
|
||||||
|
class_entry->static_fields[field_entry->static_index] = (int32_t)objectref;
|
||||||
|
} else {
|
||||||
|
assert(!"invalid constantvalue tag");
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
}
|
}
|
32
c/vm.h
Normal file
32
c/vm.h
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "frame_stack.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);
|
||||||
|
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_method_return(struct vm * vm);
|
||||||
|
void vm_execute(struct vm * vm);
|
||||||
|
struct vm * vm_start(int class_hash_table_length,
|
||||||
|
struct hash_table_entry * class_hash_table,
|
||||||
|
int native_hash_table_length,
|
||||||
|
struct hash_table_entry * native_hash_table,
|
||||||
|
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, struct objectref * objectref);
|
@ -1,6 +1,7 @@
|
|||||||
#include "string.h"
|
#include "string.h"
|
||||||
#include "native_types_allocate.h"
|
#include "native_types_allocate.h"
|
||||||
#include "vm_instance.h"
|
#include "vm_instance.h"
|
||||||
|
#include "class_resolver.h"
|
||||||
|
|
||||||
struct objectref * vm_instance_create(struct vm * vm, const char * class_name)
|
struct objectref * vm_instance_create(struct vm * vm, const char * class_name)
|
||||||
{
|
{
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "frame.h"
|
#include "vm.h"
|
||||||
|
|
||||||
struct objectref * vm_instance_create(struct vm * vm, const char * class_name);
|
struct objectref * vm_instance_create(struct vm * vm, const char * class_name);
|
||||||
struct objectref * vm_instance_string_from_constant(struct vm * vm, struct constant * constant);
|
struct objectref * vm_instance_string_from_constant(struct vm * vm, struct constant * constant);
|
||||||
|
7
classes/java/io/Closeable.java
Normal file
7
classes/java/io/Closeable.java
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
package java.io;
|
||||||
|
|
||||||
|
public interface Closeable
|
||||||
|
extends AutoCloseable {
|
||||||
|
|
||||||
|
void close() throws IOException;
|
||||||
|
}
|
4
classes/java/io/IOException.java
Normal file
4
classes/java/io/IOException.java
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
package java.io;
|
||||||
|
|
||||||
|
public class IOException extends Exception {
|
||||||
|
}
|
72
classes/java/io/InputStream.java
Normal file
72
classes/java/io/InputStream.java
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
package java.io;
|
||||||
|
|
||||||
|
public abstract class InputStream
|
||||||
|
implements Closeable {
|
||||||
|
|
||||||
|
public InputStream() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public int available() throws IOException {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void close() throws IOException {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void mark(int readlimit) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract int read() throws IOException;
|
||||||
|
|
||||||
|
public int read(byte[] b) throws IOException {
|
||||||
|
return read(b, 0, b.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int read(byte[] b,
|
||||||
|
int off,
|
||||||
|
int len) throws IOException {
|
||||||
|
if (off < 0 || len < 0 || len > b.length - off)
|
||||||
|
throw new IndexOutOfBoundsException();
|
||||||
|
|
||||||
|
if (b == null)
|
||||||
|
throw new NullPointerException();
|
||||||
|
|
||||||
|
for (int i = 0; i < len; i++) {
|
||||||
|
try {
|
||||||
|
int c = read();
|
||||||
|
boolean endOfStream = c == -1;
|
||||||
|
if (endOfStream) {
|
||||||
|
if (i == 0)
|
||||||
|
return -1;
|
||||||
|
else
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
b[off + i] = (byte)c;
|
||||||
|
} catch (IOException e) {
|
||||||
|
if (i == 0)
|
||||||
|
throw e;
|
||||||
|
else
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void reset() throws IOException {
|
||||||
|
throw new IOException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public long skip(long n)
|
||||||
|
throws IOException {
|
||||||
|
|
||||||
|
long ni = n;
|
||||||
|
while (ni > 0L) {
|
||||||
|
int b = read();
|
||||||
|
if (b < 0)
|
||||||
|
break;
|
||||||
|
ni -= 1;
|
||||||
|
}
|
||||||
|
return n - ni;
|
||||||
|
}
|
||||||
|
}
|
@ -1,7 +1,7 @@
|
|||||||
package java.lang;
|
package java.lang;
|
||||||
|
|
||||||
public final class Class<T> {
|
public final class Class<T> {
|
||||||
private Object klass; // struct class_entry *
|
private int class_entry; // is actually struct class_entry *
|
||||||
private String name;
|
private String name;
|
||||||
|
|
||||||
private Class() {
|
private Class() {
|
||||||
|
26
classes/java/nio/file/FileSystem.java
Normal file
26
classes/java/nio/file/FileSystem.java
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
package java.nio.file;
|
||||||
|
|
||||||
|
import java.io.Closeable;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.file.spi.FileSystemProvider;
|
||||||
|
|
||||||
|
public abstract class FileSystem
|
||||||
|
implements Closeable {
|
||||||
|
|
||||||
|
protected FileSystem() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract void close()
|
||||||
|
throws IOException;
|
||||||
|
|
||||||
|
public abstract Path getPath(String first,
|
||||||
|
String... more);
|
||||||
|
|
||||||
|
public abstract String getSeparator();
|
||||||
|
|
||||||
|
public abstract boolean isOpen();
|
||||||
|
|
||||||
|
public abstract boolean isReadOnly();
|
||||||
|
|
||||||
|
public abstract FileSystemProvider provider();
|
||||||
|
}
|
12
classes/java/nio/file/FileSystems.java
Normal file
12
classes/java/nio/file/FileSystems.java
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
package java.nio.file;
|
||||||
|
|
||||||
|
import jvm.internal.LibcFileSystem;
|
||||||
|
|
||||||
|
public final class FileSystems {
|
||||||
|
private FileSystems() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static FileSystem getDefault() {
|
||||||
|
return LibcFileSystem.getLibcFileSystem();
|
||||||
|
}
|
||||||
|
}
|
15
classes/java/nio/file/Files.java
Normal file
15
classes/java/nio/file/Files.java
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
package java.nio.file;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
public final class Files {
|
||||||
|
|
||||||
|
|
||||||
|
public static InputStream newInputStream(Path path,
|
||||||
|
OpenOption... options)
|
||||||
|
throws IOException {
|
||||||
|
|
||||||
|
return path.getFileSystem().provider().newInputStream(path, options);
|
||||||
|
}
|
||||||
|
}
|
4
classes/java/nio/file/OpenOption.java
Normal file
4
classes/java/nio/file/OpenOption.java
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
package java.nio.file;
|
||||||
|
|
||||||
|
public interface OpenOption {
|
||||||
|
}
|
7
classes/java/nio/file/Path.java
Normal file
7
classes/java/nio/file/Path.java
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
package java.nio.file;
|
||||||
|
|
||||||
|
public interface Path
|
||||||
|
// extends Comparable<Path>, Iterable<Path>
|
||||||
|
{
|
||||||
|
FileSystem getFileSystem();
|
||||||
|
}
|
18
classes/java/nio/file/spi/FileSystemProvider.java
Normal file
18
classes/java/nio/file/spi/FileSystemProvider.java
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
package java.nio.file.spi;
|
||||||
|
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.OpenOption;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public abstract class FileSystemProvider {
|
||||||
|
protected FileSystemProvider() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public InputStream newInputStream(Path path,
|
||||||
|
OpenOption... options)
|
||||||
|
throws IOException {
|
||||||
|
|
||||||
|
throw new IOException();
|
||||||
|
}
|
||||||
|
}
|
43
classes/jvm/internal/LibcFileSystem.java
Normal file
43
classes/jvm/internal/LibcFileSystem.java
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
package jvm.internal;
|
||||||
|
|
||||||
|
import java.nio.file.FileSystem;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.spi.FileSystemProvider;
|
||||||
|
|
||||||
|
public class LibcFileSystem extends FileSystem {
|
||||||
|
private static final String separator = "/";
|
||||||
|
|
||||||
|
private static LibcFileSystem libcFileSystem = new LibcFileSystem();
|
||||||
|
|
||||||
|
public static LibcFileSystem getLibcFileSystem() {
|
||||||
|
return libcFileSystem;
|
||||||
|
}
|
||||||
|
|
||||||
|
private LibcFileSystem() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void close() {
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
public Path getPath(String first, String ... more) {
|
||||||
|
return LibcPath.fromString(first, more);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSeparator() {
|
||||||
|
return LibcFileSystem.separator;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isOpen() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isReadOnly() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public FileSystemProvider provider() {
|
||||||
|
return LibcFileSystemProvider.getLibcFileSystemProvider();
|
||||||
|
}
|
||||||
|
}
|
26
classes/jvm/internal/LibcFileSystemProvider.java
Normal file
26
classes/jvm/internal/LibcFileSystemProvider.java
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
package jvm.internal;
|
||||||
|
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.OpenOption;
|
||||||
|
import java.nio.file.FileSystem;
|
||||||
|
import java.nio.file.spi.FileSystemProvider;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public class LibcFileSystemProvider extends FileSystemProvider {
|
||||||
|
private static LibcFileSystemProvider libcFileSystemProvider = new LibcFileSystemProvider();
|
||||||
|
|
||||||
|
private LibcFileSystemProvider() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static LibcFileSystemProvider getLibcFileSystemProvider() {
|
||||||
|
return libcFileSystemProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
public InputStream newInputStream(Path path,
|
||||||
|
OpenOption... options)
|
||||||
|
throws IOException {
|
||||||
|
return new LibcInputStream((LibcPath)path);
|
||||||
|
}
|
||||||
|
}
|
25
classes/jvm/internal/LibcInputStream.java
Normal file
25
classes/jvm/internal/LibcInputStream.java
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
package jvm.internal;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
public class LibcInputStream extends InputStream {
|
||||||
|
private int file; // is actually FILE *
|
||||||
|
|
||||||
|
private static native int _open(byte[] path);
|
||||||
|
|
||||||
|
public LibcInputStream(LibcPath path) {
|
||||||
|
file = _open(path.path);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static native void _close(int file);
|
||||||
|
|
||||||
|
public void close() {
|
||||||
|
_close(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static native int _read(int file);
|
||||||
|
|
||||||
|
public int read() {
|
||||||
|
return _read(file);
|
||||||
|
}
|
||||||
|
}
|
43
classes/jvm/internal/LibcPath.java
Normal file
43
classes/jvm/internal/LibcPath.java
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
package jvm.internal;
|
||||||
|
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.FileSystem;
|
||||||
|
|
||||||
|
public class LibcPath implements Path {
|
||||||
|
public byte[] path;
|
||||||
|
|
||||||
|
public LibcPath(byte[] path) {
|
||||||
|
this.path = path;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int copyInto(byte[] dest, int offset, String s) {
|
||||||
|
int length = s.length();
|
||||||
|
for (int i = 0; i < length; i++) {
|
||||||
|
dest[offset + i] = (byte)s.charAt(i);
|
||||||
|
}
|
||||||
|
return offset + length;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static LibcPath fromString(String first, String... more) {
|
||||||
|
int length = first.length();
|
||||||
|
for (int i = 0; i < more.length; i++) {
|
||||||
|
length += more[i].length();
|
||||||
|
}
|
||||||
|
length += more.length + 1; // including C string null terminator
|
||||||
|
|
||||||
|
byte[] path = new byte[length];
|
||||||
|
int offset = 0;
|
||||||
|
offset = copyInto(path, offset, first);
|
||||||
|
byte sep = (byte)'/';
|
||||||
|
for (int i = 0; i < more.length; i++) {
|
||||||
|
path[offset++] = sep;
|
||||||
|
offset = copyInto(path, offset, more[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new LibcPath(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
public FileSystem getFileSystem() {
|
||||||
|
return LibcFileSystem.getLibcFileSystem();
|
||||||
|
}
|
||||||
|
}
|
16
classes/test/TestInputStream.java
Normal file
16
classes/test/TestInputStream.java
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
package test;
|
||||||
|
|
||||||
|
import java.nio.file.FileSystems;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
class TestInputStream {
|
||||||
|
public static void main() throws IOException {
|
||||||
|
Path path = FileSystems.getDefault().getPath("/home/bilbo/source.txt");
|
||||||
|
InputStream is = Files.newInputStream(path);
|
||||||
|
char c = (char)is.read();
|
||||||
|
System.out.println(c);
|
||||||
|
}
|
||||||
|
}
|
3
java.mk
3
java.mk
@ -15,7 +15,7 @@ OBJ = \
|
|||||||
c/execute.o \
|
c/execute.o \
|
||||||
c/fatal.o \
|
c/fatal.o \
|
||||||
c/find_attribute.o \
|
c/find_attribute.o \
|
||||||
c/frame.o \
|
c/vm.o \
|
||||||
c/gc.o \
|
c/gc.o \
|
||||||
c/hash_table.o \
|
c/hash_table.o \
|
||||||
c/malloc.o \
|
c/malloc.o \
|
||||||
@ -42,6 +42,7 @@ MAIN_DREAMCAST_OBJ = \
|
|||||||
|
|
||||||
MAIN_HOSTED_OBJ = \
|
MAIN_HOSTED_OBJ = \
|
||||||
c/file.o \
|
c/file.o \
|
||||||
|
c/native/libcinputstream.o \
|
||||||
c/main_hosted.o
|
c/main_hosted.o
|
||||||
|
|
||||||
PRINT_CLASS_OBJ = \
|
PRINT_CLASS_OBJ = \
|
||||||
|
Loading…
x
Reference in New Issue
Block a user