native: lookup native methods by hash table entry
This commit is contained in:
parent
d1483a0c15
commit
aaa55a4f9d
11
Makefile
11
Makefile
@ -3,11 +3,14 @@
|
|||||||
|
|
||||||
include java.mk
|
include java.mk
|
||||||
|
|
||||||
|
MAKEFILE_PATH := $(patsubst %/,%,$(dir $(abspath $(firstword $(MAKEFILE_LIST)))))
|
||||||
CC ?= gcc
|
CC ?= gcc
|
||||||
ARCH = -m32
|
ARCH = -m32
|
||||||
CFLAGS += -Wall -Werror -Wfatal-errors -Wno-error=unused-variable -fstack-protector -std=c2x -g
|
CFLAGS += -Wall -Werror -Wfatal-errors -Wno-error=unused-variable -fstack-protector -std=c2x -g
|
||||||
|
CFLAGS += -I$(MAKEFILE_PATH)/
|
||||||
|
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
|
||||||
@ -22,7 +25,11 @@ main: $(OBJ) $(MAIN_HOSTED_OBJ)
|
|||||||
$(CC) $(ARCH) $(LDFLAGS) $^ -o $@
|
$(CC) $(ARCH) $(LDFLAGS) $^ -o $@
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f main print_class c/*.o c/*.d *.elf *.bin
|
rm -f main print_class *.elf *.bin
|
||||||
|
find -P \
|
||||||
|
-regextype posix-egrep \
|
||||||
|
-regex '.*\.(o|d|gch)$$' \
|
||||||
|
-exec rm {} \;
|
||||||
|
|
||||||
.SUFFIXES:
|
.SUFFIXES:
|
||||||
.INTERMEDIATE:
|
.INTERMEDIATE:
|
||||||
|
@ -7,8 +7,9 @@ LIB ?= $(MAKEFILE_PATH)/dreamcast
|
|||||||
CFLAGS += -D__dreamcast__
|
CFLAGS += -D__dreamcast__
|
||||||
CFLAGS += -DDEBUG
|
CFLAGS += -DDEBUG
|
||||||
#CFLAGS += -DDEBUG_PRINT
|
#CFLAGS += -DDEBUG_PRINT
|
||||||
CFLAGS += -I$(MAKEFILE_PATH)
|
CFLAGS += -I$(MAKEFILE_PATH)/c
|
||||||
CFLAGS += -I$(MAKEFILE_PATH)/dreamcast/
|
CFLAGS += -I$(MAKEFILE_PATH)/dreamcast
|
||||||
|
CFLAGS += -I$(MAKEFILE_PATH)/
|
||||||
CFLAGS += -Wno-error=strict-aliasing -fno-strict-aliasing
|
CFLAGS += -Wno-error=strict-aliasing -fno-strict-aliasing
|
||||||
CARCH = -m4-single -ml
|
CARCH = -m4-single -ml
|
||||||
|
|
||||||
|
@ -1,3 +1,15 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <assert.h>
|
extern void __assert_fail (const char *__assertion, const char *__file,
|
||||||
|
unsigned int __line, const char *__function)
|
||||||
|
__attribute__ ((__noreturn__));
|
||||||
|
|
||||||
|
#define __ASSERT_FUNCTION __func__
|
||||||
|
|
||||||
|
#define assert(expr) \
|
||||||
|
((void) sizeof ((expr) ? 1 : 0), __extension__ ({ \
|
||||||
|
if (expr) \
|
||||||
|
; /* empty */ \
|
||||||
|
else \
|
||||||
|
__assert_fail (#expr, __FILE__, __LINE__, __ASSERT_FUNCTION); \
|
||||||
|
}))
|
||||||
|
@ -4,22 +4,16 @@
|
|||||||
#include "find_attribute.h"
|
#include "find_attribute.h"
|
||||||
#include "memory_allocator.h"
|
#include "memory_allocator.h"
|
||||||
#include "native_types_allocate.h"
|
#include "native_types_allocate.h"
|
||||||
|
#include "vm_instance.h"
|
||||||
|
|
||||||
struct objectref * backtrace_allocate(struct vm * vm)
|
struct objectref * backtrace_allocate(struct vm * vm)
|
||||||
{
|
{
|
||||||
struct class_entry * class_entry = class_resolver_lookup_class(vm->class_hash_table.length,
|
struct objectref * objectref = vm_instance_create(vm, "java/lang/Backtrace");
|
||||||
vm->class_hash_table.entry,
|
assert(objectref != nullptr);
|
||||||
(const uint8_t *)"java/lang/Backtrace",
|
assert(objectref->class_entry->instance_fields_count >= 1);
|
||||||
19);
|
|
||||||
debugf("backtrace class entry: %p\n", class_entry);
|
|
||||||
|
|
||||||
assert(class_entry->instance_fields_count >= 1);
|
|
||||||
struct objectref * objectref = obj_allocate(vm, class_entry->instance_fields_count);
|
|
||||||
objectref->class_entry = class_entry;
|
|
||||||
|
|
||||||
int num_entries = vm->frame_stack.ix;
|
int num_entries = vm->frame_stack.ix;
|
||||||
struct arrayref * arrayref = prim_array_allocate(vm, (sizeof (struct backtrace_entry)), num_entries);
|
struct arrayref * arrayref = prim_array_allocate(vm, (sizeof (struct backtrace_entry)), num_entries);
|
||||||
arrayref->length = num_entries;
|
|
||||||
arrayref->class_entry = nullptr;
|
arrayref->class_entry = nullptr;
|
||||||
|
|
||||||
struct backtrace_entry * backtrace_entry = (struct backtrace_entry *)&arrayref->u32[0];
|
struct backtrace_entry * backtrace_entry = (struct backtrace_entry *)&arrayref->u32[0];
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "native_types.h"
|
||||||
#include "frame.h"
|
#include "frame.h"
|
||||||
|
|
||||||
struct backtrace_entry {
|
struct backtrace_entry {
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
#include "find_attribute.h"
|
#include "find_attribute.h"
|
||||||
#include "frame.h"
|
#include "frame.h"
|
||||||
#include "native_types_allocate.h"
|
#include "native_types_allocate.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)
|
||||||
{
|
{
|
||||||
@ -219,7 +220,7 @@ struct hash_table_entry * class_resolver_load_from_buffers(const uint8_t ** buff
|
|||||||
int length,
|
int length,
|
||||||
int * hash_table_length)
|
int * hash_table_length)
|
||||||
{
|
{
|
||||||
int class_hash_table_length = hash_table_next_power_of_two(hash_table_next_power_of_two(length * 2));
|
int class_hash_table_length = hash_table_next_power_of_two(length * 2);
|
||||||
uint32_t class_hash_table_size = (sizeof (struct hash_table_entry)) * class_hash_table_length;
|
uint32_t class_hash_table_size = (sizeof (struct hash_table_entry)) * class_hash_table_length;
|
||||||
struct hash_table_entry * class_hash_table = malloc_class_arena(class_hash_table_size);
|
struct hash_table_entry * class_hash_table = malloc_class_arena(class_hash_table_size);
|
||||||
hash_table_init(class_hash_table_length, class_hash_table);
|
hash_table_init(class_hash_table_length, class_hash_table);
|
||||||
@ -605,12 +606,6 @@ struct objectref * class_resolver_lookup_string(struct vm * vm,
|
|||||||
struct constant * utf8_constant = &class_entry->class_file->constant_pool[string_constant->string.string_index - 1];
|
struct constant * utf8_constant = &class_entry->class_file->constant_pool[string_constant->string.string_index - 1];
|
||||||
assert(utf8_constant->tag == CONSTANT_Utf8);
|
assert(utf8_constant->tag == CONSTANT_Utf8);
|
||||||
|
|
||||||
struct class_entry * string_class_entry = class_resolver_lookup_class(vm->class_hash_table.length,
|
|
||||||
vm->class_hash_table.entry,
|
|
||||||
(const uint8_t *)"java/lang/String",
|
|
||||||
16);
|
|
||||||
debugf("string class entry: %p\n", string_class_entry);
|
|
||||||
|
|
||||||
int32_t count = utf8_constant->utf8.length;
|
int32_t count = utf8_constant->utf8.length;
|
||||||
struct arrayref * arrayref = prim_array_allocate(vm, 1, count);
|
struct arrayref * arrayref = prim_array_allocate(vm, 1, count);
|
||||||
assert(arrayref != nullptr);
|
assert(arrayref != nullptr);
|
||||||
@ -620,14 +615,9 @@ struct objectref * class_resolver_lookup_string(struct vm * vm,
|
|||||||
arrayref->u8[i] = utf8_constant->utf8.bytes[i];
|
arrayref->u8[i] = utf8_constant->utf8.bytes[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(string_class_entry != nullptr);
|
struct objectref * objectref = vm_instance_create(vm, "java/lang/String");
|
||||||
int fields_count = string_class_entry->instance_fields_count;
|
|
||||||
struct objectref * objectref = obj_allocate(vm, fields_count);
|
|
||||||
assert(objectref != nullptr);
|
assert(objectref != nullptr);
|
||||||
objectref->class_entry = string_class_entry;
|
assert(objectref->class_entry->instance_fields_count >= 1);
|
||||||
for (int i = 0; i < fields_count; i++) {
|
|
||||||
objectref->oref[i] = nullptr;
|
|
||||||
}
|
|
||||||
objectref->aref[0] = arrayref;
|
objectref->aref[0] = arrayref;
|
||||||
|
|
||||||
// cache the result
|
// cache the result
|
||||||
|
@ -1,25 +1,25 @@
|
|||||||
#include "example/GdromClassLoader.class.h"
|
#include "classes/example/GdromClassLoader.class.h"
|
||||||
#include "example/GdromDirectoryRecordHandler.class.h"
|
#include "classes/example/GdromDirectoryRecordHandler.class.h"
|
||||||
#include "filesystem/iso9660/ByteParser.class.h"
|
#include "classes/filesystem/iso9660/ByteParser.class.h"
|
||||||
#include "filesystem/iso9660/DirectoryRecord.class.h"
|
#include "classes/filesystem/iso9660/DirectoryRecord.class.h"
|
||||||
#include "filesystem/iso9660/ExtentReader.class.h"
|
#include "classes/filesystem/iso9660/ExtentReader.class.h"
|
||||||
#include "filesystem/iso9660/PrimaryVolumeDescriptor.class.h"
|
#include "classes/filesystem/iso9660/PrimaryVolumeDescriptor.class.h"
|
||||||
#include "filesystem/iso9660/VolumeParser.class.h"
|
#include "classes/filesystem/iso9660/VolumeParser.class.h"
|
||||||
#include "java/io/PrintStream.class.h"
|
#include "classes/java/io/PrintStream.class.h"
|
||||||
#include "java/lang/DecimalDigits.class.h"
|
#include "classes/java/lang/DecimalDigits.class.h"
|
||||||
#include "java/lang/Integer.class.h"
|
#include "classes/java/lang/Integer.class.h"
|
||||||
#include "java/lang/Object.class.h"
|
#include "classes/java/lang/Object.class.h"
|
||||||
#include "java/lang/String.class.h"
|
#include "classes/java/lang/String.class.h"
|
||||||
#include "java/lang/System.class.h"
|
#include "classes/java/lang/System.class.h"
|
||||||
#include "java/misc/Memory.class.h"
|
#include "classes/java/misc/Memory.class.h"
|
||||||
#include "sega/dreamcast/gdrom/G1IF.class.h"
|
#include "classes/sega/dreamcast/gdrom/G1IF.class.h"
|
||||||
#include "sega/dreamcast/gdrom/GdromIF.class.h"
|
#include "classes/sega/dreamcast/gdrom/GdromIF.class.h"
|
||||||
#include "sega/dreamcast/gdrom/GdromBits.class.h"
|
#include "classes/sega/dreamcast/gdrom/GdromBits.class.h"
|
||||||
#include "sega/dreamcast/gdrom/Gdrom.class.h"
|
#include "classes/sega/dreamcast/gdrom/Gdrom.class.h"
|
||||||
#include "sega/dreamcast/gdrom/GdromExtentReader.class.h"
|
#include "classes/sega/dreamcast/gdrom/GdromExtentReader.class.h"
|
||||||
#include "sega/dreamcast/gdrom/GdromCommandPacketFormat_cd_read.class.h"
|
#include "classes/sega/dreamcast/gdrom/GdromCommandPacketFormat_cd_read.class.h"
|
||||||
#include "sega/dreamcast/gdrom/GdromCommandPacketFormat.class.h"
|
#include "classes/sega/dreamcast/gdrom/GdromCommandPacketFormat.class.h"
|
||||||
#include "sega/dreamcast/gdrom/GdromCommandPacketFormat_get_toc.class.h"
|
#include "classes/sega/dreamcast/gdrom/GdromCommandPacketFormat_get_toc.class.h"
|
||||||
#include "sega/dreamcast/gdrom/GdromCommandPacketInterface.class.h"
|
#include "classes/sega/dreamcast/gdrom/GdromCommandPacketInterface.class.h"
|
||||||
#include "sega/dreamcast/gdrom/GdromProtocol.class.h"
|
#include "classes/sega/dreamcast/gdrom/GdromProtocol.class.h"
|
||||||
#include "jvm/internal/Loader.class.h"
|
#include "classes/jvm/internal/Loader.class.h"
|
||||||
|
@ -1,25 +1,25 @@
|
|||||||
(const uint8_t *)&_binary_example_GdromClassLoader_class_start,
|
(const uint8_t *)&_binary_classes_example_GdromClassLoader_class_start,
|
||||||
(const uint8_t *)&_binary_example_GdromDirectoryRecordHandler_class_start,
|
(const uint8_t *)&_binary_classes_example_GdromDirectoryRecordHandler_class_start,
|
||||||
(const uint8_t *)&_binary_filesystem_iso9660_ByteParser_class_start,
|
(const uint8_t *)&_binary_classes_filesystem_iso9660_ByteParser_class_start,
|
||||||
(const uint8_t *)&_binary_filesystem_iso9660_DirectoryRecord_class_start,
|
(const uint8_t *)&_binary_classes_filesystem_iso9660_DirectoryRecord_class_start,
|
||||||
(const uint8_t *)&_binary_filesystem_iso9660_ExtentReader_class_start,
|
(const uint8_t *)&_binary_classes_filesystem_iso9660_ExtentReader_class_start,
|
||||||
(const uint8_t *)&_binary_filesystem_iso9660_PrimaryVolumeDescriptor_class_start,
|
(const uint8_t *)&_binary_classes_filesystem_iso9660_PrimaryVolumeDescriptor_class_start,
|
||||||
(const uint8_t *)&_binary_filesystem_iso9660_VolumeParser_class_start,
|
(const uint8_t *)&_binary_classes_filesystem_iso9660_VolumeParser_class_start,
|
||||||
(const uint8_t *)&_binary_java_io_PrintStream_class_start,
|
(const uint8_t *)&_binary_classes_java_io_PrintStream_class_start,
|
||||||
(const uint8_t *)&_binary_java_lang_DecimalDigits_class_start,
|
(const uint8_t *)&_binary_classes_java_lang_DecimalDigits_class_start,
|
||||||
(const uint8_t *)&_binary_java_lang_Integer_class_start,
|
(const uint8_t *)&_binary_classes_java_lang_Integer_class_start,
|
||||||
(const uint8_t *)&_binary_java_lang_Object_class_start,
|
(const uint8_t *)&_binary_classes_java_lang_Object_class_start,
|
||||||
(const uint8_t *)&_binary_java_lang_String_class_start,
|
(const uint8_t *)&_binary_classes_java_lang_String_class_start,
|
||||||
(const uint8_t *)&_binary_java_lang_System_class_start,
|
(const uint8_t *)&_binary_classes_java_lang_System_class_start,
|
||||||
(const uint8_t *)&_binary_java_misc_Memory_class_start,
|
(const uint8_t *)&_binary_classes_java_misc_Memory_class_start,
|
||||||
(const uint8_t *)&_binary_sega_dreamcast_gdrom_G1IF_class_start,
|
(const uint8_t *)&_binary_classes_sega_dreamcast_gdrom_G1IF_class_start,
|
||||||
(const uint8_t *)&_binary_sega_dreamcast_gdrom_GdromIF_class_start,
|
(const uint8_t *)&_binary_classes_sega_dreamcast_gdrom_GdromIF_class_start,
|
||||||
(const uint8_t *)&_binary_sega_dreamcast_gdrom_GdromBits_class_start,
|
(const uint8_t *)&_binary_classes_sega_dreamcast_gdrom_GdromBits_class_start,
|
||||||
(const uint8_t *)&_binary_sega_dreamcast_gdrom_Gdrom_class_start,
|
(const uint8_t *)&_binary_classes_sega_dreamcast_gdrom_Gdrom_class_start,
|
||||||
(const uint8_t *)&_binary_sega_dreamcast_gdrom_GdromExtentReader_class_start,
|
(const uint8_t *)&_binary_classes_sega_dreamcast_gdrom_GdromExtentReader_class_start,
|
||||||
(const uint8_t *)&_binary_sega_dreamcast_gdrom_GdromCommandPacketFormat_cd_read_class_start,
|
(const uint8_t *)&_binary_classes_sega_dreamcast_gdrom_GdromCommandPacketFormat_cd_read_class_start,
|
||||||
(const uint8_t *)&_binary_sega_dreamcast_gdrom_GdromCommandPacketFormat_class_start,
|
(const uint8_t *)&_binary_classes_sega_dreamcast_gdrom_GdromCommandPacketFormat_class_start,
|
||||||
(const uint8_t *)&_binary_sega_dreamcast_gdrom_GdromCommandPacketFormat_get_toc_class_start,
|
(const uint8_t *)&_binary_classes_sega_dreamcast_gdrom_GdromCommandPacketFormat_get_toc_class_start,
|
||||||
(const uint8_t *)&_binary_sega_dreamcast_gdrom_GdromCommandPacketInterface_class_start,
|
(const uint8_t *)&_binary_classes_sega_dreamcast_gdrom_GdromCommandPacketInterface_class_start,
|
||||||
(const uint8_t *)&_binary_sega_dreamcast_gdrom_GdromProtocol_class_start,
|
(const uint8_t *)&_binary_classes_sega_dreamcast_gdrom_GdromProtocol_class_start,
|
||||||
(const uint8_t *)&_binary_jvm_internal_Loader_class_start,
|
(const uint8_t *)&_binary_classes_jvm_internal_Loader_class_start,
|
||||||
|
@ -74,7 +74,6 @@ void op_anewarray(struct vm * vm, uint32_t index)
|
|||||||
int32_t count = operand_stack_pop_u32(vm->current_frame);
|
int32_t count = operand_stack_pop_u32(vm->current_frame);
|
||||||
struct arrayref * arrayref = ref_array_allocate(vm, count);
|
struct arrayref * arrayref = ref_array_allocate(vm, count);
|
||||||
assert(arrayref != nullptr);
|
assert(arrayref != nullptr);
|
||||||
arrayref->length = count;
|
|
||||||
arrayref->class_entry = class_entry;
|
arrayref->class_entry = class_entry;
|
||||||
|
|
||||||
/* All components of the new array are initialized to null, the default value
|
/* All components of the new array are initialized to null, the default value
|
||||||
@ -1171,8 +1170,6 @@ void op_invokevirtual(struct vm * vm, uint32_t index)
|
|||||||
assert(interfacemethodref_constant->tag == CONSTANT_Methodref);
|
assert(interfacemethodref_constant->tag == CONSTANT_Methodref);
|
||||||
struct constant * nameandtype_constant = &origin_class_entry->class_file->constant_pool[interfacemethodref_constant->interfacemethodref.name_and_type_index - 1];
|
struct constant * nameandtype_constant = &origin_class_entry->class_file->constant_pool[interfacemethodref_constant->interfacemethodref.name_and_type_index - 1];
|
||||||
assert(nameandtype_constant->tag == CONSTANT_NameAndType);
|
assert(nameandtype_constant->tag == CONSTANT_NameAndType);
|
||||||
struct constant * method_name_constant = &origin_class_entry->class_file->constant_pool[nameandtype_constant->nameandtype.name_index - 1];
|
|
||||||
assert(method_name_constant->tag == CONSTANT_Utf8);
|
|
||||||
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);
|
||||||
|
|
||||||
@ -1665,7 +1662,6 @@ static struct arrayref * _multiarray(struct vm * vm, int32_t * dims, int num_dim
|
|||||||
arrayref = prim_array_allocate(vm, element_size, count);
|
arrayref = prim_array_allocate(vm, element_size, count);
|
||||||
}
|
}
|
||||||
assert(arrayref != nullptr);
|
assert(arrayref != nullptr);
|
||||||
arrayref->length = count;
|
|
||||||
arrayref->class_entry = nullptr;
|
arrayref->class_entry = nullptr;
|
||||||
|
|
||||||
int32_t array_element_size = count * element_size; // bytes
|
int32_t array_element_size = count * element_size; // bytes
|
||||||
@ -1749,7 +1745,6 @@ void op_newarray(struct vm * vm, uint32_t atype)
|
|||||||
int32_t element_size = array_element_size(atype);
|
int32_t element_size = array_element_size(atype);
|
||||||
struct arrayref * arrayref = prim_array_allocate(vm, element_size, count);
|
struct arrayref * arrayref = prim_array_allocate(vm, element_size, count);
|
||||||
assert(arrayref != nullptr);
|
assert(arrayref != nullptr);
|
||||||
arrayref->length = count;
|
|
||||||
arrayref->class_entry = nullptr;
|
arrayref->class_entry = nullptr;
|
||||||
|
|
||||||
/* Each of the elements of the new array is initialized to the default initial
|
/* Each of the elements of the new array is initialized to the default initial
|
||||||
|
4
c/file.c
4
c/file.c
@ -1,13 +1,15 @@
|
|||||||
#include <assert.h>
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#include "file.h"
|
#include "file.h"
|
||||||
|
#include "assert.h"
|
||||||
|
#include "printf.h"
|
||||||
|
|
||||||
uint8_t * file_read(const char * path, size_t * file_size)
|
uint8_t * file_read(const char * path, size_t * file_size)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
debugf("file_read: ", path);
|
||||||
FILE * f = fopen(path, "rb");
|
FILE * f = fopen(path, "rb");
|
||||||
assert(f != nullptr);
|
assert(f != nullptr);
|
||||||
ret = fseek(f, 0L, SEEK_END);
|
ret = fseek(f, 0L, SEEK_END);
|
||||||
|
172
c/frame.c
172
c/frame.c
@ -171,165 +171,35 @@ 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:\n ");
|
debugf("native: ");
|
||||||
struct constant * class_constant = &class_entry->class_file->constant_pool[class_entry->class_file->this_class - 1];
|
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];
|
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);
|
debug_print__constant__utf8_string(class_name_constant);
|
||||||
debugs(" ");
|
debugs(" ");
|
||||||
struct constant * method_name_constant = &class_entry->class_file->constant_pool[method_entry->method_info->name_index - 1];
|
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);
|
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');
|
debugc('\n');
|
||||||
|
|
||||||
|
int old_stack_ix = vm->current_frame->operand_stack_ix;
|
||||||
|
|
||||||
int java_lang_math_length = 14;
|
native_method_call(vm,
|
||||||
bool java_lang_math =
|
class_name_constant,
|
||||||
class_name_constant->utf8.length == java_lang_math_length &&
|
method_name_constant,
|
||||||
hash_table_key_equal(class_name_constant->utf8.bytes, (const uint8_t *)"java/lang/Math", class_name_constant->utf8.length);
|
method_descriptor_constant,
|
||||||
if (java_lang_math) {
|
args);
|
||||||
if (method_name_constant->utf8.length == 3) {
|
|
||||||
if (hash_table_key_equal(method_name_constant->utf8.bytes, (const uint8_t *)"sin", 3)) {
|
if (return_type != 'V') {
|
||||||
assert(nargs == 1);
|
assert(old_stack_ix == vm->current_frame->operand_stack_ix - 1);
|
||||||
assert(return_type == 'F');
|
} else {
|
||||||
uint32_t value = native_java_lang_math_sin_1(args);
|
assert(old_stack_ix == vm->current_frame->operand_stack_ix);
|
||||||
operand_stack_push_u32(vm->current_frame, value);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (hash_table_key_equal(method_name_constant->utf8.bytes, (const uint8_t *)"cos", 3)) {
|
|
||||||
assert(nargs == 1);
|
|
||||||
assert(return_type == 'F');
|
|
||||||
uint32_t value = native_java_lang_math_cos_1(args);
|
|
||||||
operand_stack_push_u32(vm->current_frame, value);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (hash_table_key_equal(method_name_constant->utf8.bytes, (const uint8_t *)"abs", 3)) {
|
|
||||||
assert(nargs == 1);
|
|
||||||
assert(return_type == 'F');
|
|
||||||
uint32_t value = native_java_lang_math_abs_1(args);
|
|
||||||
operand_stack_push_u32(vm->current_frame, value);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int java_misc_memory_length = 16;
|
|
||||||
bool java_misc_memory =
|
|
||||||
class_name_constant->utf8.length == java_misc_memory_length &&
|
|
||||||
hash_table_key_equal(class_name_constant->utf8.bytes, (const uint8_t *)"java/misc/Memory", class_name_constant->utf8.length);
|
|
||||||
if (java_misc_memory) {
|
|
||||||
if (method_name_constant->utf8.length == 5) {
|
|
||||||
if (hash_table_key_equal(method_name_constant->utf8.bytes, (const uint8_t *)"putU", 4)) {
|
|
||||||
assert(nargs == 2);
|
|
||||||
assert(return_type == 'V');
|
|
||||||
switch (method_name_constant->utf8.bytes[4]) {
|
|
||||||
case '4': native_java_misc_memory_putU4_2(args); break;
|
|
||||||
case '2': native_java_misc_memory_putU2_2(args); break;
|
|
||||||
case '1': native_java_misc_memory_putU1_2(args); break;
|
|
||||||
default: assert(false);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (hash_table_key_equal(method_name_constant->utf8.bytes, (const uint8_t *)"getU", 4)) {
|
|
||||||
assert(nargs == 1);
|
|
||||||
assert(return_type == 'I');
|
|
||||||
uint32_t value;
|
|
||||||
switch (method_name_constant->utf8.bytes[4]) {
|
|
||||||
case '4': value = native_java_misc_memory_getU4_1(args); break;
|
|
||||||
case '2': value = native_java_misc_memory_getU2_1(args); break;
|
|
||||||
case '1': value = native_java_misc_memory_getU1_1(args); break;
|
|
||||||
default: assert(false);
|
|
||||||
}
|
|
||||||
operand_stack_push_u32(vm->current_frame, value);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (method_name_constant->utf8.length == 6) {
|
|
||||||
if (hash_table_key_equal(method_name_constant->utf8.bytes, (const uint8_t *)"putSQ", 5)) {
|
|
||||||
assert(nargs == 2);
|
|
||||||
assert(return_type == 'V');
|
|
||||||
switch (method_name_constant->utf8.bytes[5]) {
|
|
||||||
//case '2': value = native_java_misc_memory_putSQ2_2(args); break;
|
|
||||||
case '1': native_java_misc_memory_putSQ1_2(args); break;
|
|
||||||
default: assert(false);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (method_name_constant->utf8.length == 11) {
|
|
||||||
if (hash_table_key_equal(method_name_constant->utf8.bytes, (const uint8_t *)"isBigEndian", 11)) {
|
|
||||||
assert(nargs == 0);
|
|
||||||
assert(return_type == 'Z');
|
|
||||||
uint32_t value = native_java_misc_memory_isbigendian();
|
|
||||||
operand_stack_push_u32(vm->current_frame, value);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int java_misc_resource_length = 18;
|
|
||||||
bool java_misc_resource =
|
|
||||||
class_name_constant->utf8.length == java_misc_resource_length &&
|
|
||||||
hash_table_key_equal(class_name_constant->utf8.bytes, (const uint8_t *)"java/misc/Resource", class_name_constant->utf8.length);
|
|
||||||
if (java_misc_resource) {
|
|
||||||
int getresource_length = 11;
|
|
||||||
bool getresource =
|
|
||||||
method_name_constant->utf8.length == getresource_length &&
|
|
||||||
hash_table_key_equal(method_name_constant->utf8.bytes, (const uint8_t *)"getResource", method_name_constant->utf8.length);
|
|
||||||
if (getresource) {
|
|
||||||
assert(nargs == 1);
|
|
||||||
assert(return_type == '[');
|
|
||||||
uint32_t value = java_misc_resource_getresource_1(args);
|
|
||||||
operand_stack_push_u32(vm->current_frame, value);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int java_io_printstream_length = 19;
|
|
||||||
bool java_io_printstream =
|
|
||||||
class_name_constant->utf8.length == java_io_printstream_length &&
|
|
||||||
hash_table_key_equal(class_name_constant->utf8.bytes, (const uint8_t *)"java/io/PrintStream", class_name_constant->utf8.length);
|
|
||||||
if (java_io_printstream) {
|
|
||||||
int write_length = 5;
|
|
||||||
bool write =
|
|
||||||
method_name_constant->utf8.length == write_length &&
|
|
||||||
hash_table_key_equal(method_name_constant->utf8.bytes, (const uint8_t *)"write", method_name_constant->utf8.length);
|
|
||||||
if (write) {
|
|
||||||
if (nargs == 1) {
|
|
||||||
assert(return_type == 'V');
|
|
||||||
native_java_io_printstream_write_1(args);
|
|
||||||
return;
|
|
||||||
} else if (nargs == 2) {
|
|
||||||
assert(return_type == 'V');
|
|
||||||
native_java_io_printstream_write_2(args);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int jvm_internal_loader_length = 19;
|
|
||||||
bool jvm_internal_loader =
|
|
||||||
class_name_constant->utf8.length == jvm_internal_loader_length &&
|
|
||||||
hash_table_key_equal(class_name_constant->utf8.bytes, (const uint8_t *)"jvm/internal/Loader", class_name_constant->utf8.length);
|
|
||||||
if (jvm_internal_loader) {
|
|
||||||
if (method_name_constant->utf8.length == 4) {
|
|
||||||
if (hash_table_key_equal(method_name_constant->utf8.bytes, (const uint8_t *)"load", 4)) {
|
|
||||||
assert(nargs == 2);
|
|
||||||
assert(return_type == 'V');
|
|
||||||
native_jvm_internal_loader_load(args);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (method_name_constant->utf8.length == 9) {
|
|
||||||
if (hash_table_key_equal(method_name_constant->utf8.bytes, (const uint8_t *)"getBuffer", 9)) {
|
|
||||||
assert(nargs == 0);
|
|
||||||
assert(return_type == 'I');
|
|
||||||
uint32_t value = native_jvm_internal_loader_getbuffer();
|
|
||||||
operand_stack_push_u32(vm->current_frame, value);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void vm_method_call(struct vm * vm, struct class_entry * class_entry, struct method_entry * method_entry, int nargs, uint8_t return_type)
|
void vm_method_call(struct vm * vm, struct class_entry * class_entry, struct method_entry * method_entry, int nargs, uint8_t return_type)
|
||||||
@ -587,6 +457,8 @@ void vm_execute(struct vm * vm)
|
|||||||
|
|
||||||
struct vm * vm_start(int class_hash_table_length,
|
struct vm * vm_start(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,
|
||||||
const uint8_t * main_class_name,
|
const uint8_t * main_class_name,
|
||||||
int main_class_name_length)
|
int main_class_name_length)
|
||||||
{
|
{
|
||||||
@ -611,6 +483,8 @@ struct vm * vm_start(int class_hash_table_length,
|
|||||||
static struct vm vm;
|
static struct vm vm;
|
||||||
vm.class_hash_table.length = class_hash_table_length;
|
vm.class_hash_table.length = class_hash_table_length;
|
||||||
vm.class_hash_table.entry = class_hash_table;
|
vm.class_hash_table.entry = class_hash_table;
|
||||||
|
vm.native_hash_table.length = native_hash_table_length;
|
||||||
|
vm.native_hash_table.entry = native_hash_table;
|
||||||
|
|
||||||
vm.frame_stack.ix = 0;
|
vm.frame_stack.ix = 0;
|
||||||
vm.frame_stack.capacity = 1024;
|
vm.frame_stack.capacity = 1024;
|
||||||
|
@ -35,7 +35,12 @@ struct vm {
|
|||||||
int length;
|
int length;
|
||||||
struct hash_table_entry * entry;
|
struct hash_table_entry * entry;
|
||||||
} class_hash_table;
|
} 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];
|
||||||
@ -185,6 +190,8 @@ void vm_method_return(struct vm * vm);
|
|||||||
void vm_execute(struct vm * vm);
|
void vm_execute(struct vm * vm);
|
||||||
struct vm * vm_start(int class_hash_table_length,
|
struct vm * vm_start(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,
|
||||||
const uint8_t * main_class_name,
|
const uint8_t * main_class_name,
|
||||||
int main_class_name_length);
|
int main_class_name_length);
|
||||||
int descriptor_nargs(struct constant * descriptor_constant, uint8_t * return_type);
|
int descriptor_nargs(struct constant * descriptor_constant, uint8_t * return_type);
|
||||||
|
115
c/hash_table.c
115
c/hash_table.c
@ -186,26 +186,105 @@ struct hash_table_entry * hash_table_find2(int hash_table_length,
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
struct hash_table_entry * hash_table_add3(int hash_table_length,
|
||||||
void hash_table_add_int(int hash_table_length,
|
struct hash_table_entry * entry,
|
||||||
struct hash_table_entry * entry,
|
const uint8_t * key1,
|
||||||
int key,
|
int key1_length,
|
||||||
void * value)
|
const uint8_t * key2,
|
||||||
|
int key2_length,
|
||||||
|
const uint8_t * key3,
|
||||||
|
int key3_length,
|
||||||
|
void * value)
|
||||||
{
|
{
|
||||||
hash_table_add(hash_table_length,
|
assert(hash_table_length != 0);
|
||||||
entry,
|
assert((hash_table_length & (hash_table_length - 1)) == 0);
|
||||||
(const uint8_t *)&key,
|
uint32_t hash = fnv_offset_basis;
|
||||||
4,
|
hash = fnv_1(hash, key1, key1_length);
|
||||||
value);
|
hash = fnv_1(hash, key2, key2_length);
|
||||||
|
hash = fnv_1(hash, key3, key3_length);
|
||||||
|
hash &= (hash_table_length - 1);
|
||||||
|
|
||||||
|
printf("hash: %d %u %p\n", hash_table_length, hash, value);
|
||||||
|
|
||||||
|
struct hash_table_entry * e = &entry[hash];
|
||||||
|
|
||||||
|
while (e->next != nullptr) {
|
||||||
|
e = e->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (e->key != nullptr) {
|
||||||
|
// allocate e from overflow
|
||||||
|
e->next = malloc_class_arena((sizeof (struct hash_table_entry)));
|
||||||
|
e->next->key = nullptr;
|
||||||
|
e->next->next = nullptr;
|
||||||
|
e = e->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t * key_copy = malloc_class_arena(key1_length + key2_length + key3_length);
|
||||||
|
for (int i = 0; i < key1_length; i++) key_copy[i] = key1[i];
|
||||||
|
for (int i = 0; i < key2_length; i++) key_copy[key1_length + i] = key2[i];
|
||||||
|
for (int i = 0; i < key3_length; i++) key_copy[key1_length + key2_length + i] = key3[i];
|
||||||
|
e->key = key_copy;
|
||||||
|
e->key_length = key1_length + key2_length + key3_length;
|
||||||
|
e->value = value;
|
||||||
|
|
||||||
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct hash_table_entry * hash_table_find_int(int hash_table_length,
|
static inline bool key_equal3(const uint8_t * a1, int a1_length,
|
||||||
struct hash_table_entry * entry,
|
const uint8_t * a2, int a2_length,
|
||||||
int key)
|
const uint8_t * a3, int a3_length,
|
||||||
|
const uint8_t * b)
|
||||||
{
|
{
|
||||||
return hash_table_find(hash_table_length,
|
for (int i = 0; i < a1_length; i++) {
|
||||||
entry,
|
if (a1[i] != b[i])
|
||||||
(const uint8_t *)&key,
|
return false;
|
||||||
4);
|
}
|
||||||
|
for (int i = 0; i < a2_length; i++) {
|
||||||
|
if (a2[i] != b[a1_length + i])
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < a3_length; i++) {
|
||||||
|
if (a3[i] != b[a1_length + a2_length + i])
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct hash_table_entry * hash_table_find3(int hash_table_length,
|
||||||
|
struct hash_table_entry * entry,
|
||||||
|
const uint8_t * key1,
|
||||||
|
int key1_length,
|
||||||
|
const uint8_t * key2,
|
||||||
|
int key2_length,
|
||||||
|
const uint8_t * key3,
|
||||||
|
int key3_length)
|
||||||
|
{
|
||||||
|
if (hash_table_length == 0)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
assert((hash_table_length & (hash_table_length - 1)) == 0);
|
||||||
|
uint32_t hash = fnv_offset_basis;
|
||||||
|
hash = fnv_1(hash, key1, key1_length);
|
||||||
|
hash = fnv_1(hash, key2, key2_length);
|
||||||
|
hash = fnv_1(hash, key3, key3_length);
|
||||||
|
hash &= (hash_table_length - 1);
|
||||||
|
|
||||||
|
printf("hash: %d %u\n", hash_table_length, hash);
|
||||||
|
|
||||||
|
struct hash_table_entry * e = &entry[hash];
|
||||||
|
|
||||||
|
while (e != nullptr && e->key != nullptr) {
|
||||||
|
bool equal =
|
||||||
|
e->key_length == (key1_length + key2_length + key3_length) &&
|
||||||
|
key_equal3(key1, key1_length,
|
||||||
|
key2, key2_length,
|
||||||
|
key3, key3_length,
|
||||||
|
e->key);
|
||||||
|
if (equal) {
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
e = e->next;
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
@ -40,6 +40,25 @@ struct hash_table_entry * hash_table_find2(int hash_table_length,
|
|||||||
const uint8_t * key2,
|
const uint8_t * key2,
|
||||||
int key2_length);
|
int key2_length);
|
||||||
|
|
||||||
|
struct hash_table_entry * hash_table_add3(int hash_table_length,
|
||||||
|
struct hash_table_entry * entry,
|
||||||
|
const uint8_t * key1,
|
||||||
|
int key1_length,
|
||||||
|
const uint8_t * key2,
|
||||||
|
int key2_length,
|
||||||
|
const uint8_t * key3,
|
||||||
|
int key3_length,
|
||||||
|
void * value);
|
||||||
|
|
||||||
|
struct hash_table_entry * hash_table_find3(int hash_table_length,
|
||||||
|
struct hash_table_entry * entry,
|
||||||
|
const uint8_t * key1,
|
||||||
|
int key1_length,
|
||||||
|
const uint8_t * key2,
|
||||||
|
int key2_length,
|
||||||
|
const uint8_t * key3,
|
||||||
|
int key3_length);
|
||||||
|
|
||||||
static inline bool hash_table_key_equal(const uint8_t * a, const uint8_t * b, int length)
|
static inline bool hash_table_key_equal(const uint8_t * a, const uint8_t * b, int length)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < length; i++) {
|
for (int i = 0; i < length; i++) {
|
||||||
|
@ -2,15 +2,13 @@
|
|||||||
|
|
||||||
#include "string.h"
|
#include "string.h"
|
||||||
#include "class_resolver.h"
|
#include "class_resolver.h"
|
||||||
#include "frame.h"
|
#include "native.h"
|
||||||
#include "printf.h"
|
|
||||||
#include "malloc.h"
|
#include "malloc.h"
|
||||||
#include "memory_allocator.h"
|
|
||||||
|
|
||||||
#include "sh7091_scif.h"
|
|
||||||
|
|
||||||
#include "classpath.h"
|
#include "classpath.h"
|
||||||
|
|
||||||
|
#include "sh7091_scif.h"
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
scif_init(0);
|
scif_init(0);
|
||||||
@ -36,9 +34,15 @@ void main()
|
|||||||
class_file_buffers_length,
|
class_file_buffers_length,
|
||||||
&class_hash_table_length);
|
&class_hash_table_length);
|
||||||
|
|
||||||
|
int native_hash_table_length;
|
||||||
|
struct hash_table_entry * native_hash_table = native_init_hash_table(&native_hash_table_length);
|
||||||
|
|
||||||
struct vm * vm = vm_start(class_hash_table_length,
|
struct vm * vm = vm_start(class_hash_table_length,
|
||||||
class_hash_table,
|
class_hash_table,
|
||||||
|
native_hash_table_length,
|
||||||
|
native_hash_table,
|
||||||
main_class,
|
main_class,
|
||||||
main_class_length);
|
main_class_length);
|
||||||
|
|
||||||
vm_execute(vm);
|
vm_execute(vm);
|
||||||
}
|
}
|
||||||
|
@ -1,15 +1,14 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "printf.h"
|
#include "printf.h"
|
||||||
#include "frame.h"
|
|
||||||
#include "class_resolver.h"
|
#include "class_resolver.h"
|
||||||
#include "string.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 "backtrace.h"
|
|
||||||
#include "gc.h"
|
void * memset(void * s, int c, size_t n);
|
||||||
|
|
||||||
static struct hash_table_entry * load_from_filenames(const char * filenames[], int length, int * hash_table_length)
|
static struct hash_table_entry * load_from_filenames(const char * filenames[], int length, int * hash_table_length)
|
||||||
{
|
{
|
||||||
@ -49,15 +48,17 @@ int main(int argc, const char * argv[])
|
|||||||
int class_hash_table_length;
|
int class_hash_table_length;
|
||||||
struct hash_table_entry * class_hash_table = load_from_filenames(class_filenames, num_class_filenames, &class_hash_table_length);
|
struct hash_table_entry * class_hash_table = load_from_filenames(class_filenames, num_class_filenames, &class_hash_table_length);
|
||||||
|
|
||||||
|
int native_hash_table_length;
|
||||||
|
struct hash_table_entry * native_hash_table = native_init_hash_table(&native_hash_table_length);
|
||||||
|
|
||||||
debugf("vm_start\n");
|
debugf("vm_start\n");
|
||||||
|
|
||||||
struct vm * vm = vm_start(class_hash_table_length,
|
struct vm * vm = vm_start(class_hash_table_length,
|
||||||
class_hash_table,
|
class_hash_table,
|
||||||
|
native_hash_table_length,
|
||||||
|
native_hash_table,
|
||||||
main_class,
|
main_class,
|
||||||
main_class_length);
|
main_class_length);
|
||||||
|
|
||||||
vm_execute(vm);
|
vm_execute(vm);
|
||||||
|
|
||||||
gc_mark(vm);
|
|
||||||
gc_sweep();
|
|
||||||
}
|
}
|
||||||
|
320
c/native.c
320
c/native.c
@ -1,166 +1,168 @@
|
|||||||
#include "native.h"
|
#include "hash_table.h"
|
||||||
#include "printf.h"
|
|
||||||
#include "string.h"
|
|
||||||
#include "malloc.h"
|
#include "malloc.h"
|
||||||
#include "memory_allocator.h"
|
#include "string.h"
|
||||||
#include "class_resolver.h"
|
#include "printf.h"
|
||||||
#include "frame.h"
|
#include "native.h"
|
||||||
|
#include "native/math.h"
|
||||||
|
#include "native/memory.h"
|
||||||
|
#include "native/printstream.h"
|
||||||
|
#include "native/loader.h"
|
||||||
|
|
||||||
void native_java_io_printstream_write_1(uint32_t * args)
|
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_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,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
struct hash_table_entry * native_init_hash_table(int * hash_table_length)
|
||||||
{
|
{
|
||||||
struct arrayref * arrayref = (struct arrayref *)args[0];
|
int native_length = (sizeof (native_method)) / (sizeof (native_method[0]));
|
||||||
print_string((const char *)arrayref->u8, arrayref->length);
|
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_java_io_printstream_write_2(uint32_t * args)
|
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)
|
||||||
{
|
{
|
||||||
//uint32_t this = args[0];
|
struct hash_table_entry * e = hash_table_find3(vm->native_hash_table.length,
|
||||||
struct arrayref * arrayref = (struct arrayref *)args[1];
|
vm->native_hash_table.entry,
|
||||||
print_string((const char *)arrayref->u8, arrayref->length);
|
class_name_constant->utf8.bytes,
|
||||||
}
|
class_name_constant->utf8.length,
|
||||||
|
method_name_constant->utf8.bytes,
|
||||||
void native_java_misc_memory_putU4_2(uint32_t * args)
|
method_name_constant->utf8.length,
|
||||||
{
|
method_descriptor_constant->utf8.bytes,
|
||||||
uint32_t * address = (uint32_t *)args[0];
|
method_descriptor_constant->utf8.length
|
||||||
uint32_t value = args[1];
|
);
|
||||||
*address = value;
|
assert(e != nullptr);
|
||||||
}
|
assert(e->value != nullptr);
|
||||||
|
|
||||||
void native_java_misc_memory_putU2_2(uint32_t * args)
|
native_func_t func = (native_func_t)e->value;
|
||||||
{
|
func(vm, args);
|
||||||
uint16_t * address = (uint16_t *)args[0];
|
|
||||||
uint16_t value = args[1];
|
|
||||||
*address = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
void native_java_misc_memory_putU1_2(uint32_t * args)
|
|
||||||
{
|
|
||||||
uint8_t * address = (uint8_t *)args[0];
|
|
||||||
uint8_t value = args[1];
|
|
||||||
*address = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t native_java_misc_memory_getU4_1(uint32_t * args)
|
|
||||||
{
|
|
||||||
uint32_t * address = (uint32_t *)args[0];
|
|
||||||
uint32_t value = *address;
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t native_java_misc_memory_getU2_1(uint32_t * args)
|
|
||||||
{
|
|
||||||
uint16_t * address = (uint16_t *)args[0];
|
|
||||||
uint16_t value = *address;
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t native_java_misc_memory_getU1_1(uint32_t * args)
|
|
||||||
{
|
|
||||||
uint8_t * address = (uint8_t *)args[0];
|
|
||||||
uint8_t value = *address;
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
extern uint32_t store_queue[0x4000000] __asm("store_queue");
|
|
||||||
|
|
||||||
void native_java_misc_memory_putSQ1_2(uint32_t * args)
|
|
||||||
{
|
|
||||||
#if defined(__dreamcast__)
|
|
||||||
struct objectref * objectref = (struct objectref *)args[0];
|
|
||||||
uint32_t address = (uint32_t)args[1];
|
|
||||||
store_queue[0] = objectref->u32[0];
|
|
||||||
store_queue[1] = objectref->u32[1];
|
|
||||||
store_queue[2] = objectref->u32[2];
|
|
||||||
store_queue[3] = objectref->u32[3];
|
|
||||||
store_queue[4] = objectref->u32[4];
|
|
||||||
store_queue[5] = objectref->u32[5];
|
|
||||||
store_queue[6] = objectref->u32[6];
|
|
||||||
store_queue[7] = objectref->u32[7];
|
|
||||||
|
|
||||||
*((uint32_t*)0xff000038) = ((address >> 26) & 0b111) << 2;
|
|
||||||
|
|
||||||
__asm__ volatile ("pref @%0"
|
|
||||||
: // output
|
|
||||||
: "r" (&store_queue[0]) // input
|
|
||||||
: "memory");
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t __attribute__ ((noinline)) __attribute__ ((optimize(0)))
|
|
||||||
native_java_lang_math_sin_1(uint32_t * args)
|
|
||||||
{
|
|
||||||
float arg = ((float *)args)[0];
|
|
||||||
float value = __builtin_sinf(arg);
|
|
||||||
return *((uint32_t *)&value);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t __attribute__ ((noinline)) __attribute__ ((optimize(0)))
|
|
||||||
native_java_lang_math_cos_1(uint32_t * args)
|
|
||||||
{
|
|
||||||
float arg = ((float *)args)[0];
|
|
||||||
float value = __builtin_cosf(arg);
|
|
||||||
return *((uint32_t *)&value);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t native_java_lang_math_abs_1(uint32_t * args)
|
|
||||||
{
|
|
||||||
float arg = ((float *)args)[0];
|
|
||||||
float value = __builtin_fabsf(arg);
|
|
||||||
return *((uint32_t *)&value);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(__dreamcast__)
|
|
||||||
#include "resources.inc.c"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
uint32_t java_misc_resource_getresource_1(uint32_t * args)
|
|
||||||
{
|
|
||||||
struct objectref * objectref = (struct objectref *)args[0];
|
|
||||||
struct arrayref * arrayref = objectref->aref[0];
|
|
||||||
#if defined(__dreamcast__)
|
|
||||||
uint32_t resource = find_resource(arrayref->u8, arrayref->length);
|
|
||||||
return resource;
|
|
||||||
#else
|
|
||||||
(void)arrayref;
|
|
||||||
return 0;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t native_java_misc_memory_isbigendian()
|
|
||||||
{
|
|
||||||
return (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__);
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint8_t loader_buffer[0x100000] __attribute__ ((aligned (32)));
|
|
||||||
|
|
||||||
uint32_t native_jvm_internal_loader_getbuffer()
|
|
||||||
{
|
|
||||||
return (uint32_t)&loader_buffer[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
extern struct vm vm;
|
|
||||||
|
|
||||||
void native_jvm_internal_loader_load(uint32_t * args)
|
|
||||||
{
|
|
||||||
struct arrayref * arrayref = (struct arrayref *)args[0];
|
|
||||||
const uint8_t ** buffers = (const uint8_t **)&arrayref->u32[0];
|
|
||||||
int32_t num_buffers = (int32_t)args[1];
|
|
||||||
printf("num_buffers: %d\n", num_buffers);
|
|
||||||
printf("loader_buffer[0]: %p ; buffers[0]: %p\n", &loader_buffer[0], (uint32_t)buffers[0]);
|
|
||||||
|
|
||||||
const uint8_t * main_class = (const uint8_t *)"Main";
|
|
||||||
int main_class_length = string_length((const char *)main_class);
|
|
||||||
|
|
||||||
memory_reset_free_list();
|
|
||||||
malloc_class_arena_reset();
|
|
||||||
|
|
||||||
int class_hash_table_length;
|
|
||||||
struct hash_table_entry * class_hash_table = class_resolver_load_from_buffers(buffers,
|
|
||||||
num_buffers,
|
|
||||||
&class_hash_table_length);
|
|
||||||
|
|
||||||
vm_start(class_hash_table_length,
|
|
||||||
class_hash_table,
|
|
||||||
main_class,
|
|
||||||
main_class_length);
|
|
||||||
}
|
}
|
||||||
|
25
c/native.h
25
c/native.h
@ -1,21 +1,10 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <stdint.h>
|
#include "frame.h"
|
||||||
|
|
||||||
void native_java_io_printstream_write(uint32_t * arrayref);
|
void native_method_call(struct vm * vm,
|
||||||
void native_java_io_printstream_write_1(uint32_t * args);
|
struct constant * class_name_constant,
|
||||||
void native_java_io_printstream_write_2(uint32_t * args);
|
struct constant * method_name_constant,
|
||||||
void native_java_misc_memory_putU4_2(uint32_t * args);
|
struct constant * method_descriptor_constant,
|
||||||
void native_java_misc_memory_putU2_2(uint32_t * args);
|
uint32_t * args);
|
||||||
void native_java_misc_memory_putU1_2(uint32_t * args);
|
struct hash_table_entry * native_init_hash_table(int * hash_table_length);
|
||||||
uint32_t native_java_misc_memory_getU4_1(uint32_t * args);
|
|
||||||
uint32_t native_java_misc_memory_getU2_1(uint32_t * args);
|
|
||||||
uint32_t native_java_misc_memory_getU1_1(uint32_t * args);
|
|
||||||
void native_java_misc_memory_putSQ1_2(uint32_t * args);
|
|
||||||
uint32_t native_java_lang_math_sin_1(uint32_t * args);
|
|
||||||
uint32_t native_java_lang_math_cos_1(uint32_t * args);
|
|
||||||
uint32_t native_java_lang_math_abs_1(uint32_t * args);
|
|
||||||
uint32_t java_misc_resource_getresource_1(uint32_t * args);
|
|
||||||
uint32_t native_java_misc_memory_isbigendian();
|
|
||||||
uint32_t native_jvm_internal_loader_getbuffer();
|
|
||||||
void native_jvm_internal_loader_load(uint32_t * args);
|
|
||||||
|
42
c/native/loader.c
Normal file
42
c/native/loader.c
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
#include "native_types.h"
|
||||||
|
#include "printf.h"
|
||||||
|
#include "string.h"
|
||||||
|
#include "malloc.h"
|
||||||
|
#include "loader.h"
|
||||||
|
|
||||||
|
static uint8_t loader_buffer[0x100000] __attribute__ ((aligned (32)));
|
||||||
|
|
||||||
|
void native_jvm_internal_loader_getbuffer_0(struct vm * vm, uint32_t * args)
|
||||||
|
{
|
||||||
|
uint32_t value = (uint32_t)&loader_buffer[0];
|
||||||
|
operand_stack_push_u32(vm->current_frame, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern struct vm vm;
|
||||||
|
|
||||||
|
void native_jvm_internal_loader_load_2(struct vm * vm, uint32_t * args)
|
||||||
|
{
|
||||||
|
struct arrayref * arrayref = (struct arrayref *)args[0];
|
||||||
|
const uint8_t ** buffers = (const uint8_t **)&arrayref->u32[0];
|
||||||
|
int32_t num_buffers = (int32_t)args[1];
|
||||||
|
debugf("num_buffers: %d\n", num_buffers);
|
||||||
|
debugf("loader_buffer[0]: %p ; buffers[0]: %p\n", &loader_buffer[0], (uint32_t)buffers[0]);
|
||||||
|
|
||||||
|
const uint8_t * main_class = (const uint8_t *)"Main";
|
||||||
|
int main_class_length = string_length((const char *)main_class);
|
||||||
|
|
||||||
|
memory_reset_free_list();
|
||||||
|
malloc_class_arena_reset();
|
||||||
|
|
||||||
|
int class_hash_table_length;
|
||||||
|
struct hash_table_entry * class_hash_table = class_resolver_load_from_buffers(buffers,
|
||||||
|
num_buffers,
|
||||||
|
&class_hash_table_length);
|
||||||
|
|
||||||
|
vm_start(class_hash_table_length,
|
||||||
|
class_hash_table,
|
||||||
|
vm->native_hash_table.length,
|
||||||
|
vm->native_hash_table.entry,
|
||||||
|
main_class,
|
||||||
|
main_class_length);
|
||||||
|
}
|
8
c/native/loader.h
Normal file
8
c/native/loader.h
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "frame.h"
|
||||||
|
|
||||||
|
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);
|
24
c/native/math.c
Normal file
24
c/native/math.c
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
#include "math.h"
|
||||||
|
|
||||||
|
void __attribute__ ((noinline)) __attribute__ ((optimize(0)))
|
||||||
|
native_java_lang_math_sin_1(struct vm * vm, uint32_t * args)
|
||||||
|
{
|
||||||
|
float arg = ((float *)args)[0];
|
||||||
|
float value = __builtin_sinf(arg);
|
||||||
|
operand_stack_push_u32(vm->current_frame, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void __attribute__ ((noinline)) __attribute__ ((optimize(0)))
|
||||||
|
native_java_lang_math_cos_1(struct vm * vm, uint32_t * args)
|
||||||
|
{
|
||||||
|
float arg = ((float *)args)[0];
|
||||||
|
float value = __builtin_cosf(arg);
|
||||||
|
operand_stack_push_u32(vm->current_frame, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void native_java_lang_math_abs_1(struct vm * vm, uint32_t * args)
|
||||||
|
{
|
||||||
|
float arg = ((float *)args)[0];
|
||||||
|
float value = __builtin_fabsf(arg);
|
||||||
|
operand_stack_push_u32(vm->current_frame, value);
|
||||||
|
}
|
9
c/native/math.h
Normal file
9
c/native/math.h
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "frame.h"
|
||||||
|
|
||||||
|
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_abs_1(struct vm * vm, uint32_t * args);
|
75
c/native/memory.c
Normal file
75
c/native/memory.c
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
#include "native_types.h"
|
||||||
|
#include "memory.h"
|
||||||
|
|
||||||
|
void native_java_misc_memory_putU4_2(struct vm * vm, uint32_t * args)
|
||||||
|
{
|
||||||
|
uint32_t * address = (uint32_t *)args[0];
|
||||||
|
uint32_t value = args[1];
|
||||||
|
*address = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void native_java_misc_memory_putU2_2(struct vm * vm, uint32_t * args)
|
||||||
|
{
|
||||||
|
uint16_t * address = (uint16_t *)args[0];
|
||||||
|
uint16_t value = args[1];
|
||||||
|
*address = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void native_java_misc_memory_putU1_2(struct vm * vm, uint32_t * args)
|
||||||
|
{
|
||||||
|
uint8_t * address = (uint8_t *)args[0];
|
||||||
|
uint8_t value = args[1];
|
||||||
|
*address = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void native_java_misc_memory_getU4_1(struct vm * vm, uint32_t * args)
|
||||||
|
{
|
||||||
|
uint32_t * address = (uint32_t *)args[0];
|
||||||
|
uint32_t value = *address;
|
||||||
|
operand_stack_push_u32(vm->current_frame, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void native_java_misc_memory_getU2_1(struct vm * vm, uint32_t * args)
|
||||||
|
{
|
||||||
|
uint16_t * address = (uint16_t *)args[0];
|
||||||
|
uint16_t value = *address;
|
||||||
|
operand_stack_push_u32(vm->current_frame, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void native_java_misc_memory_getU1_1(struct vm * vm, uint32_t * args)
|
||||||
|
{
|
||||||
|
uint8_t * address = (uint8_t *)args[0];
|
||||||
|
uint8_t value = *address;
|
||||||
|
operand_stack_push_u32(vm->current_frame, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern uint32_t store_queue[0x4000000] __asm("store_queue");
|
||||||
|
|
||||||
|
void native_java_misc_memory_putSQ1_2(struct vm * vm, uint32_t * args)
|
||||||
|
{
|
||||||
|
#if defined(__dreamcast__)
|
||||||
|
struct objectref * objectref = (struct objectref *)args[0];
|
||||||
|
uint32_t address = (uint32_t)args[1];
|
||||||
|
store_queue[0] = objectref->u32[0];
|
||||||
|
store_queue[1] = objectref->u32[1];
|
||||||
|
store_queue[2] = objectref->u32[2];
|
||||||
|
store_queue[3] = objectref->u32[3];
|
||||||
|
store_queue[4] = objectref->u32[4];
|
||||||
|
store_queue[5] = objectref->u32[5];
|
||||||
|
store_queue[6] = objectref->u32[6];
|
||||||
|
store_queue[7] = objectref->u32[7];
|
||||||
|
|
||||||
|
*((uint32_t*)0xff000038) = ((address >> 26) & 0b111) << 2;
|
||||||
|
|
||||||
|
__asm__ volatile ("pref @%0"
|
||||||
|
: // output
|
||||||
|
: "r" (&store_queue[0]) // input
|
||||||
|
: "memory");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void native_java_misc_memory_isbigendian_0(struct vm * vm, uint32_t * args)
|
||||||
|
{
|
||||||
|
uint32_t value = (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__);
|
||||||
|
operand_stack_push_u32(vm->current_frame, value);
|
||||||
|
}
|
14
c/native/memory.h
Normal file
14
c/native/memory.h
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "frame.h"
|
||||||
|
|
||||||
|
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_putU1_2(struct vm * vm, uint32_t * args);
|
||||||
|
void native_java_misc_memory_getU4_1(struct vm * vm, uint32_t * args);
|
||||||
|
void native_java_misc_memory_getU2_1(struct vm * vm, uint32_t * args);
|
||||||
|
void native_java_misc_memory_getU1_1(struct vm * vm, uint32_t * args);
|
||||||
|
void native_java_misc_memory_putSQ1_2(struct vm * vm, uint32_t * args);
|
||||||
|
void native_java_misc_memory_isbigendian_0(struct vm * vm, uint32_t * args);
|
9
c/native/printstream.c
Normal file
9
c/native/printstream.c
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
#include "native_types.h"
|
||||||
|
#include "printstream.h"
|
||||||
|
#include "printf.h"
|
||||||
|
|
||||||
|
void native_java_io_printstream_write_1(struct vm * vm, uint32_t * args)
|
||||||
|
{
|
||||||
|
struct arrayref * arrayref = (struct arrayref *)args[0];
|
||||||
|
print_string((const char *)arrayref->u8, arrayref->length);
|
||||||
|
}
|
7
c/native/printstream.h
Normal file
7
c/native/printstream.h
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "frame.h"
|
||||||
|
|
||||||
|
void native_java_io_printstream_write_1(struct vm * vm, uint32_t * args);
|
@ -1,8 +1,8 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
|
#include "assert.h"
|
||||||
#include "class_resolver.h"
|
#include "class_resolver.h"
|
||||||
#include "memory_allocator.h"
|
#include "memory_allocator.h"
|
||||||
|
|
||||||
|
@ -21,6 +21,7 @@ static inline struct arrayref * prim_array_allocate(struct vm * vm, int element_
|
|||||||
if (arrayref != nullptr) {
|
if (arrayref != nullptr) {
|
||||||
arrayref->tag.type = TAG_TYPE_PRIM_ARRAY;
|
arrayref->tag.type = TAG_TYPE_PRIM_ARRAY;
|
||||||
arrayref->tag.mark = 0;
|
arrayref->tag.mark = 0;
|
||||||
|
arrayref->length = count;
|
||||||
}
|
}
|
||||||
return arrayref;
|
return arrayref;
|
||||||
}
|
}
|
||||||
@ -32,6 +33,7 @@ static inline struct arrayref * ref_array_allocate(struct vm * vm, int count)
|
|||||||
if (arrayref != nullptr) {
|
if (arrayref != nullptr) {
|
||||||
arrayref->tag.type = TAG_TYPE_REF_ARRAY;
|
arrayref->tag.type = TAG_TYPE_REF_ARRAY;
|
||||||
arrayref->tag.mark = 0;
|
arrayref->tag.mark = 0;
|
||||||
|
arrayref->length = count;
|
||||||
}
|
}
|
||||||
return arrayref;
|
return arrayref;
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
#include "hash_table.h"
|
#include "hash_table.h"
|
||||||
|
#include "assert.h"
|
||||||
|
|
||||||
static const char * names[] = {
|
static const char * names[] = {
|
||||||
"java/beans/Introspector.java",
|
"java/beans/Introspector.java",
|
||||||
|
23
c/vm_instance.c
Normal file
23
c/vm_instance.c
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
#include "string.h"
|
||||||
|
#include "native_types_allocate.h"
|
||||||
|
#include "vm_instance.h"
|
||||||
|
|
||||||
|
struct objectref * vm_instance_create(struct vm * vm, const char * class_name)
|
||||||
|
{
|
||||||
|
struct class_entry * class_entry = class_resolver_lookup_class(vm->class_hash_table.length,
|
||||||
|
vm->class_hash_table.entry,
|
||||||
|
(const uint8_t *)class_name,
|
||||||
|
string_length(class_name));
|
||||||
|
assert(class_entry != nullptr);
|
||||||
|
|
||||||
|
struct objectref * objectref = obj_allocate(vm, class_entry->instance_fields_count);
|
||||||
|
if (objectref != nullptr) {
|
||||||
|
objectref->class_entry = class_entry;
|
||||||
|
|
||||||
|
for (int i = 0; i < class_entry->instance_fields_count; i++) {
|
||||||
|
objectref->oref[i] = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return objectref;
|
||||||
|
}
|
5
c/vm_instance.h
Normal file
5
c/vm_instance.h
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "frame.h"
|
||||||
|
|
||||||
|
struct objectref * vm_instance_create(struct vm * vm, const char * class_name);
|
18
classes/java/lang/Class.java
Normal file
18
classes/java/lang/Class.java
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
package java.lang;
|
||||||
|
|
||||||
|
public class Class {
|
||||||
|
private Object object;
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
private Class() {
|
||||||
|
}
|
||||||
|
|
||||||
|
private native String getClassName();
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
if (this.name == null) {
|
||||||
|
this.name = getClassName();
|
||||||
|
}
|
||||||
|
return this.name;
|
||||||
|
}
|
||||||
|
}
|
@ -3,7 +3,12 @@ package java.lang;
|
|||||||
public class Object {
|
public class Object {
|
||||||
public Object() {}
|
public Object() {}
|
||||||
|
|
||||||
|
public final native Class getClass();
|
||||||
|
|
||||||
|
public native int hashCode();
|
||||||
|
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "Object";
|
return null;
|
||||||
|
//return getClass().getName() + "@" + Integer.toString(hashCode());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,4 @@ public class Memory {
|
|||||||
public static native void putSQ1(Object object, int address);
|
public static native void putSQ1(Object object, int address);
|
||||||
|
|
||||||
public static native boolean isBigEndian();
|
public static native boolean isBigEndian();
|
||||||
|
|
||||||
// .length of the returned byte array must not be accessed
|
|
||||||
public static native byte[] wrapAddress(int address);
|
|
||||||
}
|
}
|
||||||
|
24
classes/test/TestGeneric.java
Normal file
24
classes/test/TestGeneric.java
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
package test;
|
||||||
|
|
||||||
|
class Test<T> {
|
||||||
|
T obj;
|
||||||
|
|
||||||
|
Test(T obj) {
|
||||||
|
this.obj = obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
public T getObject() {
|
||||||
|
return this.obj;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class TestGeneric {
|
||||||
|
public static void main(String[] args)
|
||||||
|
{
|
||||||
|
Test<Integer> ti = new Test<Integer>(15);
|
||||||
|
System.out.println(ti.getObject());
|
||||||
|
|
||||||
|
Test<String> ts = new Test<String>("GeeksForGeeks");
|
||||||
|
System.out.println(ts.getObject());
|
||||||
|
}
|
||||||
|
}
|
50
classpath.mk
50
classpath.mk
@ -1,26 +1,26 @@
|
|||||||
CLASS_PATH = \
|
CLASS_PATH = \
|
||||||
example/GdromClassLoader.class.o \
|
classes/example/GdromClassLoader.class.o \
|
||||||
example/GdromDirectoryRecordHandler.class.o \
|
classes/example/GdromDirectoryRecordHandler.class.o \
|
||||||
filesystem/iso9660/ByteParser.class.o \
|
classes/filesystem/iso9660/ByteParser.class.o \
|
||||||
filesystem/iso9660/DirectoryRecord.class.o \
|
classes/filesystem/iso9660/DirectoryRecord.class.o \
|
||||||
filesystem/iso9660/ExtentReader.class.o \
|
classes/filesystem/iso9660/ExtentReader.class.o \
|
||||||
filesystem/iso9660/PrimaryVolumeDescriptor.class.o \
|
classes/filesystem/iso9660/PrimaryVolumeDescriptor.class.o \
|
||||||
filesystem/iso9660/VolumeParser.class.o \
|
classes/filesystem/iso9660/VolumeParser.class.o \
|
||||||
java/io/PrintStream.class.o \
|
classes/java/io/PrintStream.class.o \
|
||||||
java/lang/DecimalDigits.class.o \
|
classes/java/lang/DecimalDigits.class.o \
|
||||||
java/lang/Integer.class.o \
|
classes/java/lang/Integer.class.o \
|
||||||
java/lang/Object.class.o \
|
classes/java/lang/Object.class.o \
|
||||||
java/lang/String.class.o \
|
classes/java/lang/String.class.o \
|
||||||
java/lang/System.class.o \
|
classes/java/lang/System.class.o \
|
||||||
java/misc/Memory.class.o \
|
classes/java/misc/Memory.class.o \
|
||||||
sega/dreamcast/gdrom/G1IF.class.o \
|
classes/sega/dreamcast/gdrom/G1IF.class.o \
|
||||||
sega/dreamcast/gdrom/GdromIF.class.o \
|
classes/sega/dreamcast/gdrom/GdromIF.class.o \
|
||||||
sega/dreamcast/gdrom/GdromBits.class.o \
|
classes/sega/dreamcast/gdrom/GdromBits.class.o \
|
||||||
sega/dreamcast/gdrom/Gdrom.class.o \
|
classes/sega/dreamcast/gdrom/Gdrom.class.o \
|
||||||
sega/dreamcast/gdrom/GdromExtentReader.class.o \
|
classes/sega/dreamcast/gdrom/GdromExtentReader.class.o \
|
||||||
sega/dreamcast/gdrom/GdromCommandPacketFormat_cd_read.class.o \
|
classes/sega/dreamcast/gdrom/GdromCommandPacketFormat_cd_read.class.o \
|
||||||
sega/dreamcast/gdrom/GdromCommandPacketFormat.class.o \
|
classes/sega/dreamcast/gdrom/GdromCommandPacketFormat.class.o \
|
||||||
sega/dreamcast/gdrom/GdromCommandPacketFormat_get_toc.class.o \
|
classes/sega/dreamcast/gdrom/GdromCommandPacketFormat_get_toc.class.o \
|
||||||
sega/dreamcast/gdrom/GdromCommandPacketInterface.class.o \
|
classes/sega/dreamcast/gdrom/GdromCommandPacketInterface.class.o \
|
||||||
sega/dreamcast/gdrom/GdromProtocol.class.o \
|
classes/sega/dreamcast/gdrom/GdromProtocol.class.o \
|
||||||
jvm/internal/Loader.class.o
|
classes/jvm/internal/Loader.class.o
|
||||||
|
@ -39,27 +39,29 @@ function classpath_inc_c () {
|
|||||||
|
|
||||||
function make_header () {
|
function make_header () {
|
||||||
while read line; do
|
while read line; do
|
||||||
truncate -s0 "${line}.h"
|
local filename="${line}.h"
|
||||||
|
|
||||||
local name0="${line//\//_}"
|
local name0="${line//\//_}"
|
||||||
local name1="${name0//$/_}"
|
local name1="${name0//$/_}"
|
||||||
local name="${name1//./_}"
|
local name="${name1//./_}"
|
||||||
|
|
||||||
echo '#pragma once' > "${line}.h"
|
truncate -s0 "${filename}"
|
||||||
echo '' >> "${line}.h"
|
|
||||||
echo '#include <stdint.h>' >> "${line}.h"
|
echo '#pragma once' > "${filename}"
|
||||||
echo '' >> "${line}.h"
|
echo '' >> "${filename}"
|
||||||
echo '#ifdef __cplusplus' >> "${line}.h"
|
echo '#include <stdint.h>' >> "${filename}"
|
||||||
echo 'extern C {' >> "${line}.h"
|
echo '' >> "${filename}"
|
||||||
echo '#endif' >> "${line}.h"
|
echo '#ifdef __cplusplus' >> "${filename}"
|
||||||
echo '' >> "${line}.h"
|
echo 'extern C {' >> "${filename}"
|
||||||
echo "extern uint32_t _binary_${name}_start __asm(\"_binary_${name}_start\");" >> "${line}.h"
|
echo '#endif' >> "${filename}"
|
||||||
echo "extern uint32_t _binary_${name}_end __asm(\"_binary_${name}_end\");" >> "${line}.h"
|
echo '' >> "${filename}"
|
||||||
echo "extern uint32_t _binary_${name}_size __asm(\"_binary_${name}_size\");" >> "${line}.h"
|
echo "extern uint32_t _binary_${name}_start __asm(\"_binary_${name}_start\");" >> "${filename}"
|
||||||
echo '' >> "${line}.h"
|
echo "extern uint32_t _binary_${name}_end __asm(\"_binary_${name}_end\");" >> "${filename}"
|
||||||
echo '#ifdef __cplusplus' >> "${line}.h"
|
echo "extern uint32_t _binary_${name}_size __asm(\"_binary_${name}_size\");" >> "${filename}"
|
||||||
echo '}' >> "${line}.h"
|
echo '' >> "${filename}"
|
||||||
echo '#endif' >> "${line}.h"
|
echo '#ifdef __cplusplus' >> "${filename}"
|
||||||
|
echo '}' >> "${filename}"
|
||||||
|
echo '#endif' >> "${filename}"
|
||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -102,7 +104,7 @@ function boot_classes () {
|
|||||||
local length=${#boot_classes[@]}
|
local length=${#boot_classes[@]}
|
||||||
|
|
||||||
for ((i=0;i<length;i++)); do
|
for ((i=0;i<length;i++)); do
|
||||||
local class="${boot_classes[i]}"
|
local class="classes/${boot_classes[i]}"
|
||||||
echo "$class"
|
echo "$class"
|
||||||
done
|
done
|
||||||
}
|
}
|
||||||
@ -111,7 +113,7 @@ function boot_sources () {
|
|||||||
local length=${#boot_classes[@]}
|
local length=${#boot_classes[@]}
|
||||||
|
|
||||||
for ((i=0;i<length;i++)); do
|
for ((i=0;i<length;i++)); do
|
||||||
local class="${boot_classes[i]}"
|
local class="classes/${boot_classes[i]}"
|
||||||
local source="${class%.class}.java"
|
local source="${class%.class}.java"
|
||||||
if [ -f "$source" ]; then
|
if [ -f "$source" ]; then
|
||||||
echo "$source"
|
echo "$source"
|
||||||
@ -151,7 +153,7 @@ function application_classes () {
|
|||||||
local length=${#application_classes[@]}
|
local length=${#application_classes[@]}
|
||||||
|
|
||||||
for ((i=0;i<length;i++)); do
|
for ((i=0;i<length;i++)); do
|
||||||
local class="${application_classes[i]}"
|
local class="classes/${application_classes[i]}"
|
||||||
echo "$class"
|
echo "$class"
|
||||||
done
|
done
|
||||||
}
|
}
|
||||||
@ -160,7 +162,7 @@ function application_sources () {
|
|||||||
local length=${#application_classes[@]}
|
local length=${#application_classes[@]}
|
||||||
|
|
||||||
for ((i=0;i<length;i++)); do
|
for ((i=0;i<length;i++)); do
|
||||||
local class="${application_classes[i]}"
|
local class="classes/${application_classes[i]}"
|
||||||
local source="${class%.class}.java"
|
local source="${class%.class}.java"
|
||||||
if [ -f "$source" ]; then
|
if [ -f "$source" ]; then
|
||||||
echo "$source"
|
echo "$source"
|
||||||
@ -176,6 +178,7 @@ function find_sources () {
|
|||||||
find model/ example/ sega/ java/ filesystem/ -name '*.java' -not -name 'Test*' | sort
|
find model/ example/ sega/ java/ filesystem/ -name '*.java' -not -name 'Test*' | sort
|
||||||
}
|
}
|
||||||
|
|
||||||
|
set -eux
|
||||||
|
|
||||||
find . -name '*.class' -exec rm -f {} \;
|
find . -name '*.class' -exec rm -f {} \;
|
||||||
|
|
||||||
|
39
java.mk
39
java.mk
@ -6,25 +6,30 @@
|
|||||||
javac -Xlint:-options --source 8 --target 8 --boot-class-path . $(<:classes/%=%)
|
javac -Xlint:-options --source 8 --target 8 --boot-class-path . $(<:classes/%=%)
|
||||||
|
|
||||||
OBJ = \
|
OBJ = \
|
||||||
c/decode.o \
|
|
||||||
c/class_file.o \
|
|
||||||
c/debug_class_file.o \
|
|
||||||
c/malloc.o \
|
|
||||||
c/execute.o \
|
|
||||||
c/memory_allocator.o \
|
|
||||||
c/class_resolver.o \
|
|
||||||
c/hash_table.o \
|
|
||||||
c/frame.o \
|
|
||||||
c/printf.o \
|
|
||||||
c/parse.o \
|
|
||||||
c/unparse.o \
|
|
||||||
c/native.o \
|
|
||||||
c/debug.o \
|
|
||||||
c/fatal.o \
|
|
||||||
c/parse_type.o \
|
|
||||||
c/backtrace.o \
|
c/backtrace.o \
|
||||||
|
c/class_file.o \
|
||||||
|
c/class_resolver.o \
|
||||||
|
c/debug.o \
|
||||||
|
c/debug_class_file.o \
|
||||||
|
c/decode.o \
|
||||||
|
c/execute.o \
|
||||||
|
c/fatal.o \
|
||||||
c/find_attribute.o \
|
c/find_attribute.o \
|
||||||
c/gc.o
|
c/frame.o \
|
||||||
|
c/gc.o \
|
||||||
|
c/hash_table.o \
|
||||||
|
c/malloc.o \
|
||||||
|
c/memory_allocator.o \
|
||||||
|
c/native.o \
|
||||||
|
c/native/loader.o \
|
||||||
|
c/native/math.o \
|
||||||
|
c/native/memory.o \
|
||||||
|
c/native/printstream.o \
|
||||||
|
c/parse.o \
|
||||||
|
c/parse_type.o \
|
||||||
|
c/printf.o \
|
||||||
|
c/unparse.o \
|
||||||
|
c/vm_instance.o
|
||||||
|
|
||||||
MAIN_DREAMCAST_OBJ = \
|
MAIN_DREAMCAST_OBJ = \
|
||||||
c/main_dreamcast.o \
|
c/main_dreamcast.o \
|
||||||
|
Loading…
x
Reference in New Issue
Block a user