diff --git a/Makefile b/Makefile index e0e2f48..0c1c651 100644 --- a/Makefile +++ b/Makefile @@ -43,7 +43,7 @@ main: $(MAIN_OBJ) $(CC) $(ARCH) $^ -o $@ clean: - rm -f main print_class c/*.o + rm -f main print_class c/*.o c/*.d .SUFFIXES: .INTERMEDIATE: diff --git a/c/assert.h b/c/assert.h new file mode 100644 index 0000000..d708512 --- /dev/null +++ b/c/assert.h @@ -0,0 +1,11 @@ +#pragma once + +#if defined(__linux__) +#include "assert_hosted.h" +#elif defined(_WIN32) +#include "assert_hosted.h" +#elif defined(__APPLE__) +#include "assert_hosted.h" +#else +#include "assert_dreamcast.h" +#endif diff --git a/c/assert_dreamcast.h b/c/assert_dreamcast.h new file mode 100644 index 0000000..cdf3044 --- /dev/null +++ b/c/assert_dreamcast.h @@ -0,0 +1,3 @@ +#pragma once + +#define assert(b) diff --git a/c/assert_hosted.h b/c/assert_hosted.h new file mode 100644 index 0000000..7cf48a1 --- /dev/null +++ b/c/assert_hosted.h @@ -0,0 +1,3 @@ +#pragma once + +#include diff --git a/c/class_file.c b/c/class_file.c index 540e9c8..a0fd380 100644 --- a/c/class_file.c +++ b/c/class_file.c @@ -1,7 +1,4 @@ -#ifdef DEBUG -#include -#endif - +#include "assert.h" #include "class_file.h" #include "malloc.h" #include "bytes.h" diff --git a/c/class_resolver.c b/c/class_resolver.c index 5cecf81..1e195db 100644 --- a/c/class_resolver.c +++ b/c/class_resolver.c @@ -1,16 +1,14 @@ #include -#include -#include -#include +#include "assert.h" #include "class_file.h" -#include "file.h" #include "hash_table.h" #include "malloc.h" #include "class_resolver.h" #include "string.h" #include "debug_class_file.h" #include "memory_allocator.h" +#include "printf.h" static void class_resolver_create_interfaces_hash_table(struct class_entry * class_entry) { @@ -53,7 +51,7 @@ static int field_size(struct class_file * class_file, struct field_info * field_ static int32_t class_resolver_create_fields_hash_table(struct class_entry * class_entry) { struct class_file * class_file = class_entry->class_file; - int fields_hash_table_length = class_file->fields_count * 2; + int fields_hash_table_length = hash_table_next_power_of_two(class_file->fields_count * 2); uint32_t fields_hash_table_size = (sizeof (struct hash_table_entry)) * fields_hash_table_length; struct hash_table_entry * fields_hash_table = malloc_class_arena(fields_hash_table_size); uint32_t field_entry_size = (sizeof (struct field_entry)) * class_file->fields_count; @@ -97,7 +95,7 @@ static int32_t class_resolver_create_fields_hash_table(struct class_entry * clas static void class_resolver_create_methods_hash_table(struct class_entry * class_entry) { struct class_file * class_file = class_entry->class_file; - int methods_hash_table_length = class_file->methods_count * 2; + int methods_hash_table_length = hash_table_next_power_of_two(class_file->methods_count * 2); uint32_t methods_hash_table_size = (sizeof (struct hash_table_entry)) * methods_hash_table_length; struct hash_table_entry * methods_hash_table = malloc_class_arena(methods_hash_table_size); for (int i = 0; i < class_file->methods_count; i++) { @@ -149,30 +147,20 @@ static void class_resolver_allocate_attribute_entry(struct class_entry * class_e class_entry->attribute_entry = attribute_entry; } -struct hash_table_entry * class_resolver_load_from_filenames(const char * filenames[], int length, int * hash_table_length) +struct hash_table_entry * class_resolver_load_from_buffers(const uint8_t * class_names[], + const int class_names_length[], + uint8_t * buffers[], + int length, + int * hash_table_length) { - int class_hash_table_length = length * 2; + int class_hash_table_length = hash_table_next_power_of_two(hash_table_next_power_of_two(length * 2)); 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); uint32_t class_entry_size = (sizeof (struct class_entry)) * length; struct class_entry * class_entry = malloc_class_arena(class_entry_size); for (int i = 0; i < length; i++) { - uint32_t filename_length = string_length(filenames[i]); - const char * suffix = ".class"; - uint32_t suffix_length = string_length(suffix); - const char * filename_suffix = &filenames[i][filename_length - suffix_length]; - if (filename_length <= suffix_length || !string_equal(suffix, filename_suffix)) { - printf("invalid class filename: %s\n", filenames[i]); - continue; - } - uint32_t class_name_length = filename_length - suffix_length; - - printf("load class: %s\n", filenames[i]); - - uint8_t * buf = file_read(filenames[i]); - struct class_file * class_file = class_file_parse(buf); - free(buf); + struct class_file * class_file = class_file_parse(buffers[i]); assert(class_file->magic == 0xcafebabe); @@ -181,8 +169,8 @@ struct hash_table_entry * class_resolver_load_from_filenames(const char * filena hash_table_add(class_hash_table_length, class_hash_table, - (const uint8_t *)filenames[i], - class_name_length, + class_names[i], + class_names_length[i], &class_entry[i]); // make hash table for interfaces diff --git a/c/class_resolver.h b/c/class_resolver.h index fa17ea1..26238ba 100644 --- a/c/class_resolver.h +++ b/c/class_resolver.h @@ -48,7 +48,11 @@ struct class_entry { } methods; }; -struct hash_table_entry * class_resolver_load_from_filenames(const char * filenames[], int length, int * hash_table_length); +struct hash_table_entry * class_resolver_load_from_buffers(const uint8_t * class_names[], + const int class_names_length[], + uint8_t * buffers[], + int length, + int * hash_table_length); struct class_entry * class_resolver_lookup_class(int class_hash_table_length, struct hash_table_entry * class_hash_table, const uint8_t * class_name, diff --git a/c/debug_class_file.c b/c/debug_class_file.c index 4f10a56..5856bf9 100644 --- a/c/debug_class_file.c +++ b/c/debug_class_file.c @@ -1,13 +1,13 @@ -#include -#include #include -#include #include +#include "assert.h" #include "class_file.h" #include "bytes.h" #include "decode.h" #include "debug_class_file.h" +#include "printf.h" +#include "string.h" void print_utf8_string(struct constant * constant) { @@ -163,9 +163,9 @@ void print_attribute(const char * indent, struct attribute_info * attribute, str fputs(indent, stdout); printf("attributes:\n"); for (int i = 0; i < attribute->code->attributes_count; i++) { - char indent2[strlen(indent) + 2 + 1]; - strcpy(indent2, indent); - strcpy(indent2 + strlen(indent), " "); + char indent2[string_length(indent) + 2 + 1]; + string_copy(indent2, indent); + string_copy(indent2 + string_length(indent), " "); fputs(indent, stdout); printf(" attribute %d:\n", i); print_attribute(indent2, &attribute->code->attributes[i], constant_pool); diff --git a/c/decode.c b/c/decode.c index 0557117..cccaed1 100644 --- a/c/decode.c +++ b/c/decode.c @@ -1,10 +1,10 @@ #include -#include -#include +#include "assert.h" #include "decode.h" #include "execute.h" #include "bswap.h" +#include "printf.h" static inline uint32_t _u4(const uint8_t * buf) { diff --git a/c/execute.c b/c/execute.c index 01d297e..fc47c8d 100644 --- a/c/execute.c +++ b/c/execute.c @@ -1,10 +1,9 @@ -#include - #include "execute.h" #include "memory_allocator.h" #include "bswap.h" #include "class_resolver.h" #include "execute_helper.h" +#include "printf.h" void op_aaload(struct vm * vm) { diff --git a/c/file.c b/c/file.c index 07b9ed4..675d819 100644 --- a/c/file.c +++ b/c/file.c @@ -5,7 +5,7 @@ #include "file.h" -uint8_t * file_read(const char * path) +uint8_t * file_read(const char * path, size_t * file_size) { int ret; FILE * f = fopen(path, "rb"); @@ -21,5 +21,7 @@ uint8_t * file_read(const char * path) size_t read = fread(buf, 1, size, f); assert(read == size); + *file_size = size; + return buf; } diff --git a/c/file.h b/c/file.h index 69b502c..9ada825 100644 --- a/c/file.h +++ b/c/file.h @@ -2,4 +2,4 @@ #include -uint8_t * file_read(const char * path); +uint8_t * file_read(const char * path, size_t * file_size); diff --git a/c/frame.c b/c/frame.c index b95e584..7d73609 100644 --- a/c/frame.c +++ b/c/frame.c @@ -1,7 +1,6 @@ #include -#include -#include +#include "assert.h" #include "class_file.h" #include "memory.h" #include "debug_class_file.h" @@ -9,6 +8,7 @@ #include "decode.h" #include "frame.h" #include "class_resolver.h" +#include "printf.h" struct Code_attribute * get_code_attribute(int code_name_index, int attributes_count, diff --git a/c/frame.h b/c/frame.h index e885e29..4c6dd52 100644 --- a/c/frame.h +++ b/c/frame.h @@ -1,7 +1,6 @@ #pragma once -#include - +#include "assert.h" #include "class_file.h" #include "class_resolver.h" diff --git a/c/hash_table.c b/c/hash_table.c index 79ee5cb..f4c48ed 100644 --- a/c/hash_table.c +++ b/c/hash_table.c @@ -1,10 +1,22 @@ -#include - +#include "assert.h" #include "malloc.h" #include "hash_table.h" +#include "printf.h" static const uint32_t fnv_offset_basis = 0x811c9dc5; +int32_t hash_table_next_power_of_two(int32_t n) +{ + n--; + n |= n >> 1; + n |= n >> 2; + n |= n >> 4; + n |= n >> 8; + n |= n >> 16; + n++; + return n; +} + static uint32_t fnv_1(uint32_t hash, const uint8_t * buf, int length) { const uint32_t fnv_prime = 0x01000193; @@ -26,9 +38,6 @@ void hash_table_init(int hash_table_length, } } - -#include - void print_key(const uint8_t * key, int key_length) { printf("key: "); @@ -44,6 +53,7 @@ void hash_table_add(int hash_table_length, void * value) { assert(hash_table_length != 0); + assert((hash_table_length & (hash_table_length - 1)) == 0); uint32_t hash = fnv_1(fnv_offset_basis, key, key_length) & (hash_table_length - 1); struct hash_table_entry * e = &entry[hash]; @@ -82,17 +92,19 @@ struct hash_table_entry * hash_table_find(int hash_table_length, int key_length) { assert(hash_table_length != 0); + assert((hash_table_length & (hash_table_length - 1)) == 0); uint32_t hash = fnv_1(fnv_offset_basis, key, key_length) & (hash_table_length - 1); struct hash_table_entry * e = &entry[hash]; while (e != nullptr && e->key != nullptr) { - printf("key find: %p ", e->key); - print_key(e->key, e->key_length); + //printf("key find: %p ", e->key); + //print_key(e->key, e->key_length); if (e->key_length == key_length && key_equal(key, e->key, e->key_length)) { return e; } e = e->next; } + fflush(stdout); return nullptr; } @@ -120,6 +132,7 @@ void hash_table_add2(int hash_table_length, void * value) { assert(hash_table_length != 0); + 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); @@ -152,6 +165,7 @@ struct hash_table_entry * hash_table_find2(int hash_table_length, int key2_length) { assert(hash_table_length != 0); + 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); diff --git a/c/hash_table.h b/c/hash_table.h index 3fe36a5..fc88ebc 100644 --- a/c/hash_table.h +++ b/c/hash_table.h @@ -9,6 +9,8 @@ struct hash_table_entry { struct hash_table_entry * next; }; +int32_t hash_table_next_power_of_two(int32_t n); + void hash_table_init(int hash_table_length, struct hash_table_entry * entry); diff --git a/c/main.c b/c/main.c index fdcd410..9a7efef 100644 --- a/c/main.c +++ b/c/main.c @@ -1,6 +1,47 @@ +#include +#include +#include + #include "frame.h" #include "class_resolver.h" #include "string.h" +#include "file.h" + +static struct hash_table_entry * load_from_filenames(const char * filenames[], int length, int * hash_table_length) +{ + const uint8_t ** class_names = (const uint8_t **)filenames; + int class_names_length[length]; + uint8_t * buffers[length]; + size_t file_size[length]; + + for (int i = 0; i < length; i++) { + uint32_t filename_length = string_length(filenames[i]); + const char * suffix = ".class"; + uint32_t suffix_length = string_length(suffix); + const char * filename_suffix = &filenames[i][filename_length - suffix_length]; + if (filename_length <= suffix_length || !string_equal(suffix, filename_suffix)) { + printf("invalid class filename: %s\n", filenames[i]); + continue; + } + class_names_length[i] = filename_length - suffix_length; + printf("load class: %s\n", filenames[i]); + + buffers[i] = file_read(filenames[i], &file_size[i]); + } + + struct hash_table_entry * class_hash_table = class_resolver_load_from_buffers(class_names, + class_names_length, + buffers, + length, + hash_table_length); + + for (int i = 0; i < length; i++) { + memset(buffers[i], 0, file_size[i]); + free(buffers[i]); + } + + return class_hash_table; +} int main(int argc, const char * argv[]) { @@ -12,7 +53,7 @@ int main(int argc, const char * argv[]) int num_class_filenames = argc - 2; int class_hash_table_length; - struct hash_table_entry * class_hash_table = class_resolver_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); struct class_entry * class_entry = class_resolver_lookup_class(class_hash_table_length, class_hash_table, diff --git a/c/malloc.c b/c/malloc.c index 3386130..de894b0 100644 --- a/c/malloc.c +++ b/c/malloc.c @@ -1,7 +1,6 @@ +#include "assert.h" #include "malloc.h" -#include - struct arena { uint8_t * mem; uint32_t size; diff --git a/c/memory_allocator.c b/c/memory_allocator.c index 0535fea..f9705cf 100644 --- a/c/memory_allocator.c +++ b/c/memory_allocator.c @@ -1,6 +1,8 @@ -#include #include +#include "assert.h" +#include "printf.h" + #define block_power (5UL) #define block_size (1UL << block_power) //static uint8_t memory[0x100]; @@ -31,8 +33,6 @@ static inline uint32_t find_contiguous_blocks(uint32_t blocks, int * zero_crossi return blocks; } -#include - void * memory_allocate(uint32_t size) { assert(size != 0); diff --git a/c/print_class.c b/c/print_class.c index edb6fd6..6afb9a7 100644 --- a/c/print_class.c +++ b/c/print_class.c @@ -1,8 +1,7 @@ -#include -#include - +#include "assert.h" #include "debug_class_file.h" #include "file.h" +#include "printf.h" int main(int argc, char * argv[]) { diff --git a/c/printf.h b/c/printf.h new file mode 100644 index 0000000..6a53840 --- /dev/null +++ b/c/printf.h @@ -0,0 +1,11 @@ +#pragma once + +#if defined(__linux__) +#include "printf_hosted.h" +#elif defined(_WIN32) +#include "printf_hosted.h" +#elif defined(__APPLE__) +#include "printf_hosted.h" +#else +#include "printf_dreamcast.h" +#endif diff --git a/c/printf_dreamcast.c b/c/printf_dreamcast.c new file mode 100644 index 0000000..e69de29 diff --git a/c/printf_hosted.h b/c/printf_hosted.h new file mode 100644 index 0000000..1e6b64e --- /dev/null +++ b/c/printf_hosted.h @@ -0,0 +1,6 @@ +#pragma once + +#include + +#define debugf(fmt, ...) printf((fmt), __VA_ARGS__); +#define debugc(c) putc(stdout, c); diff --git a/c/string.h b/c/string.h index 2da8d26..5fab4c5 100644 --- a/c/string.h +++ b/c/string.h @@ -9,6 +9,14 @@ static inline int string_length(const char * s) return si - s; } +static inline void string_copy(char * dst, const char * src) +{ + while (*src != 0) { + *dst++ = *src++; + } + *dst = 0; +} + static inline bool string_equal(const char * a, const char * b) { int i = 0; diff --git a/c/test_hash_table.c b/c/test_hash_table.c index df7a42f..441e779 100644 --- a/c/test_hash_table.c +++ b/c/test_hash_table.c @@ -145,11 +145,7 @@ static uint32_t _strlen(const char * s) return si - s; } -void print_key(const uint8_t * key, int key_length) -{ - for (int i = 0; i < key_length; i++) - fputc(key[i], stdout); -} +void print_key(const uint8_t * key, int key_length); int main() { diff --git a/p/Fields.java b/p/Fields.java new file mode 100644 index 0000000..bef791f --- /dev/null +++ b/p/Fields.java @@ -0,0 +1,11 @@ +package p; + +class Fields { + int foo; + long bar; + int[] spam; + static float baz; + static float bleh; + static double qux; + static Object eggs; +} diff --git a/p/Generic.java b/p/Generic.java new file mode 100644 index 0000000..c33b9ee --- /dev/null +++ b/p/Generic.java @@ -0,0 +1,22 @@ +package p; + +class Generic +{ + T obj1; // An object of type T + U obj2; // An object of type U + + // constructor + Generic(T obj1, U obj2) + { + this.obj1 = obj1; + this.obj2 = obj2; + } + + // To print objects of T and U + public static void print() + { + float ff = 1.0f; + Float f = new Float(f); + Generic g = new Generic(1, f); + } +}