diff --git a/.gitignore b/.gitignore index 2556324..17c1e98 100644 --- a/.gitignore +++ b/.gitignore @@ -4,5 +4,6 @@ *.gch *.csv *.class +*.out main print_class \ No newline at end of file diff --git a/c/a.out b/c/a.out deleted file mode 100755 index 82903c4..0000000 Binary files a/c/a.out and /dev/null differ diff --git a/c/class_resolver.c b/c/class_resolver.c index e118e04..d8fa8d4 100644 --- a/c/class_resolver.c +++ b/c/class_resolver.c @@ -62,7 +62,7 @@ struct hash_table_entry * class_resolver_load_from_filenames(const char * filena int fields_hash_table_length = 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)) * length; + uint32_t field_entry_size = (sizeof (struct field_entry)) * class_file->fields_count; struct field_entry * field_entry = malloc_class_arena(field_entry_size); for (int i = 0; i < class_file->fields_count; i++) { u2 name_index = class_file->fields[i].name_index; @@ -95,15 +95,20 @@ struct hash_table_entry * class_resolver_load_from_filenames(const char * filena u2 name_index = class_file->methods[i].name_index; struct constant * name_constant = &class_file->constant_pool[name_index - 1]; assert(name_constant->tag == CONSTANT_Utf8); + u2 descriptor_index = class_file->methods[i].descriptor_index; + struct constant * descriptor_constant = &class_file->constant_pool[descriptor_index - 1]; + assert(descriptor_constant->tag == CONSTANT_Utf8); printf("hash table entry for method: "); print_utf8_string(name_constant); printf("\n"); - hash_table_add(methods_hash_table_length, - methods_hash_table, - name_constant->utf8.bytes, - name_constant->utf8.length, - (void *)&class_file->methods[i]); + hash_table_add2(methods_hash_table_length, + methods_hash_table, + name_constant->utf8.bytes, + name_constant->utf8.length, + descriptor_constant->utf8.bytes, + descriptor_constant->utf8.length, + (void *)&class_file->methods[i]); } class_entry[i].methods.length = methods_hash_table_length; @@ -157,19 +162,25 @@ struct field_entry * class_resolver_lookup_field(struct class_entry * class_entr struct method_info * class_resolver_lookup_method(struct class_entry * class_entry, const uint8_t * method_name, - int method_name_length) + int method_name_length, + const uint8_t * method_descriptor, + int method_descriptor_length) { printf("class_resolver_lookup_method: "); for (int i = 0; i < method_name_length; i++) { fputc(method_name[i], stdout); } + fputc(' ', stdout); + for (int i = 0; i < method_descriptor_length; i++) { fputc(method_descriptor[i], stdout); } fputc('\n', stdout); int methods_hash_table_length = class_entry->methods.length; struct hash_table_entry * methods_hash_table = class_entry->methods.entry; - struct hash_table_entry * e = hash_table_find(methods_hash_table_length, - methods_hash_table, - method_name, - method_name_length); + struct hash_table_entry * e = hash_table_find2(methods_hash_table_length, + methods_hash_table, + method_name, + method_name_length, + method_descriptor, + method_descriptor_length); assert(e != nullptr); return (struct method_info *)e->value; diff --git a/c/class_resolver.h b/c/class_resolver.h index dbe91f3..1815c9d 100644 --- a/c/class_resolver.h +++ b/c/class_resolver.h @@ -43,7 +43,9 @@ struct class_entry * class_resolver_lookup_class(int class_hash_table_length, int class_name_length); struct method_info * class_resolver_lookup_method(struct class_entry * class_entry, const uint8_t * method_name, - int method_name_length); + int method_name_length, + const uint8_t * method_descriptor, + int method_descriptor_length); struct field_entry * class_resolver_lookup_field(struct class_entry * class_entry, const uint8_t * field_name, int field_name_length); diff --git a/c/execute.c b/c/execute.c index 84e8761..708e2d2 100644 --- a/c/execute.c +++ b/c/execute.c @@ -920,6 +920,10 @@ void op_invokestatic(struct vm * vm, uint32_t index) #ifdef DEBUG assert(method_name_constant->tag == CONSTANT_Utf8); #endif + struct constant * method_descriptor_constant = &vm->current_thread.current_class->constant_pool[nameandtype_constant->nameandtype.descriptor_index - 1]; + #ifdef DEBUG + assert(method_descriptor_constant->tag == CONSTANT_Utf8); + #endif struct class_entry * class_entry = class_resolver_lookup_class(vm->class_hash_table.length, vm->class_hash_table.entry, @@ -929,7 +933,9 @@ void op_invokestatic(struct vm * vm, uint32_t index) struct method_info * method_info = class_resolver_lookup_method(class_entry, method_name_constant->utf8.bytes, - method_name_constant->utf8.length); + method_name_constant->utf8.length, + method_descriptor_constant->utf8.bytes, + method_descriptor_constant->utf8.length); assert(method_info != nullptr); /* On successful resolution of the method, the class or interface that diff --git a/c/frame.c b/c/frame.c index 5e1916a..235494d 100644 --- a/c/frame.c +++ b/c/frame.c @@ -121,11 +121,15 @@ bool vm_initialize_class(struct vm * vm, struct class_entry * class_entry) /* Next, if C declares a class or interface initialization method, execute that method. */ const uint8_t * method_name = (const uint8_t *)""; - int method_length = 8; + int method_name_length = 8; + const uint8_t * method_descriptor = (const uint8_t *)"()V"; + int method_descriptor_length = 3; struct method_info * method_info = class_resolver_lookup_method(class_entry, method_name, - method_length); + method_name_length, + method_descriptor, + method_descriptor_length); if (method_info != nullptr) { assert((method_info->access_flags & METHOD_ACC_STATIC) != 0); printf("\n"); diff --git a/c/hash_table.c b/c/hash_table.c index 9c871df..1456ba3 100644 --- a/c/hash_table.c +++ b/c/hash_table.c @@ -1,12 +1,11 @@ #include "malloc.h" #include "hash_table.h" -static uint32_t fnv_1(const uint8_t * buf, int length) -{ - const uint32_t fnv_offset_basis = 0x811c9dc5; - const uint32_t fnv_prime = 0x01000193; +static const uint32_t fnv_offset_basis = 0x811c9dc5; - uint32_t hash = fnv_offset_basis; +static uint32_t fnv_1(uint32_t hash, const uint8_t * buf, int length) +{ + const uint32_t fnv_prime = 0x01000193; for (int i = 0; i < length; i++) { hash = hash * fnv_prime; @@ -25,13 +24,24 @@ void hash_table_init(int hash_table_length, } } + +#include + +void print_key(const uint8_t * key, int key_length) +{ + printf("key: "); + for (int i = 0; i < key_length; i++) + fputc(key[i], stdout); + fputc('\n', stdout); +} + void hash_table_add(int hash_table_length, struct hash_table_entry * entry, const uint8_t * key, int key_length, void * value) { - uint32_t hash = fnv_1(key, key_length) & (hash_table_length - 1); + uint32_t hash = fnv_1(fnv_offset_basis, key, key_length) & (hash_table_length - 1); struct hash_table_entry * e = &entry[hash]; while (e->next != nullptr) { @@ -44,7 +54,12 @@ void hash_table_add(int hash_table_length, e = e->next; } - e->key = key; + uint8_t * key_copy = malloc_class_arena(key_length); + for (int i = 0; i < key_length; i++) key_copy[i] = key[i]; + printf("key copy: %p ", key_copy); + print_key(key_copy, key_length); + + e->key = key_copy; e->key_length = key_length; e->value = value; } @@ -63,11 +78,88 @@ struct hash_table_entry * hash_table_find(int hash_table_length, const uint8_t * key, int key_length) { - uint32_t hash = fnv_1(key, key_length) & (hash_table_length - 1); + 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) { - if (e->key_length == key_length && key_equal(e->key, key, 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; + } + return nullptr; +} + +static inline bool key_equal2(const uint8_t * a1, int a1_length, + const uint8_t * a2, int a2_length, + const uint8_t * b) +{ + for (int i = 0; i < a1_length; i++) { + if (a1[i] != b[i]) + return false; + } + for (int i = 0; i < a2_length; i++) { + if (a2[i] != b[a1_length + i]) + return false; + } + return true; +} + +void hash_table_add2(int hash_table_length, + struct hash_table_entry * entry, + const uint8_t * key1, + int key1_length, + const uint8_t * key2, + int key2_length, + void * value) +{ + uint32_t hash = fnv_offset_basis; + hash = fnv_1(hash, key1, key1_length); + hash = fnv_1(hash, key2, key2_length); + hash &= (hash_table_length - 1); + 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 = e->next; + } + + uint8_t * key_copy = malloc_class_arena(key1_length + key2_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]; + e->key = key_copy; + e->key_length = key1_length + key2_length; + e->value = value; +} + +struct hash_table_entry * hash_table_find2(int hash_table_length, + struct hash_table_entry * entry, + const uint8_t * key1, + int key1_length, + const uint8_t * key2, + int key2_length) +{ + uint32_t hash = fnv_offset_basis; + hash = fnv_1(hash, key1, key1_length); + hash = fnv_1(hash, key2, key2_length); + hash &= (hash_table_length - 1); + + struct hash_table_entry * e = &entry[hash]; + + while (e != nullptr && e->key != nullptr) { + bool equal = + e->key_length == (key1_length + key2_length) && + key_equal2(key1, key1_length, + key2, key2_length, + e->key); + if (equal) { return e; } e = e->next; diff --git a/c/hash_table.h b/c/hash_table.h index e316a4e..8cd76d6 100644 --- a/c/hash_table.h +++ b/c/hash_table.h @@ -22,3 +22,18 @@ struct hash_table_entry * hash_table_find(int hash_table_length, struct hash_table_entry * entry, const uint8_t * key, int key_length); + +void hash_table_add2(int hash_table_length, + struct hash_table_entry * entry, + const uint8_t * key1, + int key1_length, + const uint8_t * key2, + int key2_length, + void * value); + +struct hash_table_entry * hash_table_find2(int hash_table_length, + struct hash_table_entry * entry, + const uint8_t * key1, + int key1_length, + const uint8_t * key2, + int key2_length); diff --git a/c/main.c b/c/main.c index 4d7e780..4447875 100644 --- a/c/main.c +++ b/c/main.c @@ -21,9 +21,13 @@ int main(int argc, const char * argv[]) const char * method_name = "main"; int method_name_length = string_length(method_name); + const char * method_descriptor = "()V"; + int method_descriptor_length = string_length(method_descriptor); struct method_info * method_info = class_resolver_lookup_method(class_entry, (const uint8_t *)method_name, - method_name_length); + method_name_length, + (const uint8_t *)method_descriptor, + method_descriptor_length); struct vm vm; vm.class_hash_table.entry = class_hash_table; diff --git a/c/malloc.c b/c/malloc.c index cafd2c5..1f6b035 100644 --- a/c/malloc.c +++ b/c/malloc.c @@ -1,5 +1,7 @@ #include "malloc.h" +#include + struct arena { uint8_t * mem; uint32_t size; @@ -16,7 +18,9 @@ struct arena class_arena = { void * malloc_class_arena(uint32_t size) { + assert((class_arena.ix & (~3)) == class_arena.ix); void * ptr = &class_arena.mem[class_arena.ix]; + size = (size + 3) & (~3); class_arena.ix += size; return ptr; } diff --git a/c/test_hash_table.c b/c/test_hash_table.c index e22bba9..df7a42f 100644 --- a/c/test_hash_table.c +++ b/c/test_hash_table.c @@ -145,6 +145,12 @@ 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); +} + int main() { int hash_table_length = 128 * 2; @@ -170,6 +176,7 @@ int main() printf("collision %s\n", e->key); } assert(e != nullptr); - printf("%s %d\n", e->key, (int)e->value); + print_key(e->key, e->key_length); + printf(" %d\n", (int)e->value); } } diff --git a/p/Instance.java b/p/Instance.java new file mode 100644 index 0000000..935f903 --- /dev/null +++ b/p/Instance.java @@ -0,0 +1,24 @@ +package p; + +class Instance { + int a; + int b; + + public Instance(int a) { + this.a = a; + this.b = 13; + } + + int mul() { + return a * b; + } + + static int test() { + Instance i = new Instance(12); + return i.mul(); + } + + public static void main() { + test(); + } +} diff --git a/p/StaticMethodOverloading.java b/p/StaticMethodOverloading.java new file mode 100644 index 0000000..d1c4451 --- /dev/null +++ b/p/StaticMethodOverloading.java @@ -0,0 +1,19 @@ +package p; + +class StaticMethodOverloading { + static int test() { + return test(4); + } + + static int test(int a) { + return test(a, 3); + } + + static int test(int a, int b) { + return a * b + 1; + } + + public static void main() { + test(); + } +}