diff --git a/c/class_resolver.c b/c/class_resolver.c index cde445a..5cecf81 100644 --- a/c/class_resolver.c +++ b/c/class_resolver.c @@ -12,6 +12,143 @@ #include "debug_class_file.h" #include "memory_allocator.h" +static void class_resolver_create_interfaces_hash_table(struct class_entry * class_entry) +{ + /* + struct class_file * class_file = class_entry->class_file; + + uint32_t interfaces_hash_table_size = (sizeof (struct hash_table_entry)) * class_file->interfaces_count * 3 / 2; + struct hash_table_entry * interfaces_hash_table = malloc_class_arena(interfaces_hash_table_size); + for (int i = 0; i < class_file->interfaces_count; i++) { + + } + */ +} + +static int field_size(struct class_file * class_file, struct field_info * field_info) +{ + struct constant * field_descriptor_constant = &class_file->constant_pool[field_info->descriptor_index - 1]; + #ifdef DEBUG + assert(field_descriptor_constant->tag == CONSTANT_Utf8); + #endif + + switch (field_descriptor_constant->utf8.bytes[0]) { + case 'B': [[fallthrough]]; + case 'C': [[fallthrough]]; + case 'F': [[fallthrough]]; + case 'I': [[fallthrough]]; + case 'L': [[fallthrough]]; + case 'S': [[fallthrough]]; + case 'Z': [[fallthrough]]; + case '[': + return 1; + case 'D': [[fallthrough]]; + case 'J': + return 2; + default: + assert(false); + } +} + +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; + 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; + struct field_entry * field_entry = malloc_class_arena(field_entry_size); + + int32_t static_index = 0; + int32_t instance_index = 0; + + for (int i = 0; i < class_file->fields_count; i++) { + u2 name_index = class_file->fields[i].name_index; + struct constant * name_constant = &class_file->constant_pool[name_index - 1]; + assert(name_constant->tag == CONSTANT_Utf8); + printf("hash table entry for field: "); + print_utf8_string(name_constant); + printf("\n"); + + struct field_info * field_info = &class_file->fields[i]; + + if (field_info->access_flags & FIELD_ACC_STATIC) { + field_entry[i].static_index = static_index; + static_index += field_size(class_file, field_info); + } else { + field_entry[i].instance_index = instance_index; + instance_index += field_size(class_file, field_info); + } + field_entry[i].field_info = field_info; + + hash_table_add(fields_hash_table_length, + fields_hash_table, + name_constant->utf8.bytes, + name_constant->utf8.length, + (void *)&field_entry[i]); + } + + class_entry->fields.length = fields_hash_table_length; + class_entry->fields.entry = fields_hash_table; + + return static_index; +} + +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; + 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++) { + 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_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->methods.length = methods_hash_table_length; + class_entry->methods.entry = methods_hash_table; +} + +static void class_resolver_allocate_static_fields(struct class_entry * class_entry, int32_t static_field_count) +{ + uint32_t static_fields_size = (sizeof (int32_t)) * static_field_count; + int32_t * static_fields = malloc_class_arena(static_fields_size); + + for (int i = 0; i < static_field_count; i++) { + static_fields[i] = 0; + } + + class_entry->static_fields = static_fields; +} + +static void class_resolver_allocate_attribute_entry(struct class_entry * class_entry) +{ + struct class_file * class_file = class_entry->class_file; + uint32_t attribute_entry_size = (sizeof (union attribute_entry)) * class_file->constant_pool_count; + union attribute_entry * attribute_entry = malloc_class_arena(attribute_entry_size); + + for (int i = 0; i < class_file->constant_pool_count; i++) { + attribute_entry[i].class_entry = nullptr; + } + + class_entry->attribute_entry = attribute_entry; +} + struct hash_table_entry * class_resolver_load_from_filenames(const char * filenames[], int length, int * hash_table_length) { int class_hash_table_length = length * 2; @@ -48,80 +185,20 @@ struct hash_table_entry * class_resolver_load_from_filenames(const char * filena class_name_length, &class_entry[i]); - // make hash table for strings - int strings_hash_table_length = class_file->constant_pool_count; - uint32_t strings_hash_table_size = (sizeof (struct hash_table_entry)) * strings_hash_table_length; - struct hash_table_entry * strings_hash_table = malloc_class_arena(strings_hash_table_size); - class_entry[i].strings.length = strings_hash_table_length; - class_entry[i].strings.entry = strings_hash_table; - // make hash table for interfaces - /* - if (class_file->interfaces_count != 0) { - uint32_t interfaces_hash_table_size = (sizeof (struct hash_table_entry)) * class_file->interfaces_count * 3 / 2; - struct hash_table_entry * interfaces_hash_table = malloc_class_arena(interfaces_hash_table_size); - for (int i = 0; i < class_file->interfaces_count; i++) { + class_resolver_create_interfaces_hash_table(&class_entry[i]); - } - } - */ // make hash table for fields - if (class_file->fields_count != 0) { - 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)) * 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; - struct constant * name_constant = &class_file->constant_pool[name_index - 1]; - assert(name_constant->tag == CONSTANT_Utf8); - printf("hash table entry for field: "); - print_utf8_string(name_constant); - printf("\n"); - - field_entry[i].field_info = &class_file->fields[i]; - field_entry[i].value64 = 0; - - hash_table_add(fields_hash_table_length, - fields_hash_table, - name_constant->utf8.bytes, - name_constant->utf8.length, - (void *)&field_entry[i]); - } - - class_entry[i].fields.length = fields_hash_table_length; - class_entry[i].fields.entry = fields_hash_table; - } + int32_t static_field_count = class_resolver_create_fields_hash_table(&class_entry[i]); // make hash table for methods - if (class_file->methods_count != 0) { - int methods_hash_table_length = 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++) { - 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"); + class_resolver_create_methods_hash_table(&class_entry[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]); - } + // allocate static fields + class_resolver_allocate_static_fields(&class_entry[i], static_field_count); - class_entry[i].methods.length = methods_hash_table_length; - class_entry[i].methods.entry = methods_hash_table; - } + // allocate attribute_entry + class_resolver_allocate_attribute_entry(&class_entry[i]); }; *hash_table_length = class_hash_table_length; @@ -147,8 +224,38 @@ struct class_entry * class_resolver_lookup_class(int class_hash_table_length, return (struct class_entry *)e->value; } +struct class_entry * class_resolver_lookup_class_from_class_index(int class_hash_table_length, + struct hash_table_entry * class_hash_table, + struct class_entry * class_entry, + int32_t class_index) +{ + if (class_entry->attribute_entry[class_index - 1].class_entry != nullptr) { + printf("class_resolver_lookup_class_from_class_index %d: [cached]\n", class_index); + return class_entry->attribute_entry[class_index - 1].class_entry; + } -struct field_entry * class_resolver_lookup_field(struct class_entry * class_entry, + struct constant * class_constant = &class_entry->class_file->constant_pool[class_index - 1]; + #ifdef DEBUG + assert(class_constant->tag == CONSTANT_Class); + #endif + struct constant * class_name_constant = &class_entry->class_file->constant_pool[class_constant->class.name_index - 1]; + #ifdef DEBUG + assert(class_name_constant->tag == CONSTANT_Utf8); + #endif + + struct class_entry * _class_entry = class_resolver_lookup_class(class_hash_table_length, + class_hash_table, + class_name_constant->utf8.bytes, + class_name_constant->utf8.length); + + // cache the result + class_entry->attribute_entry[class_index - 1].class_entry = _class_entry; + + return _class_entry; +} + +struct field_entry * class_resolver_lookup_field(int fields_hash_table_length, + struct hash_table_entry * fields_hash_table, const uint8_t * field_name, int field_name_length) { @@ -156,9 +263,6 @@ struct field_entry * class_resolver_lookup_field(struct class_entry * class_entr for (int i = 0; i < field_name_length; i++) { fputc(field_name[i], stdout); } fputc('\n', stdout); - int fields_hash_table_length = class_entry->fields.length; - struct hash_table_entry * fields_hash_table = class_entry->fields.entry; - struct hash_table_entry * e = hash_table_find(fields_hash_table_length, fields_hash_table, field_name, @@ -168,7 +272,42 @@ struct field_entry * class_resolver_lookup_field(struct class_entry * class_entr return (struct field_entry *)e->value; } -struct method_info * class_resolver_lookup_method(struct class_entry * class_entry, +struct field_entry * class_resolver_lookup_field_from_fieldref_index(int fields_hash_table_length, + struct hash_table_entry * fields_hash_table, + struct class_entry * class_entry, + int fieldref_index) +{ + if (class_entry->attribute_entry[fieldref_index - 1].field_entry != nullptr) { + printf("class_resolver_lookup_method_from_fieldref_index %d: [cached]\n", fieldref_index); + return class_entry->attribute_entry[fieldref_index - 1].field_entry; + } + + struct constant * fieldref_constant = &class_entry->class_file->constant_pool[fieldref_index - 1]; + #ifdef DEBUG + assert(fieldref_constant->tag == CONSTANT_Fieldref); + #endif + struct constant * nameandtype_constant = &class_entry->class_file->constant_pool[fieldref_constant->fieldref.name_and_type_index - 1]; + #ifdef DEBUG + assert(nameandtype_constant->tag == CONSTANT_NameAndType); + #endif + struct constant * field_name_constant = &class_entry->class_file->constant_pool[nameandtype_constant->nameandtype.name_index - 1]; + #ifdef DEBUG + assert(field_name_constant->tag == CONSTANT_Utf8); + #endif + + struct field_entry * field_entry = class_resolver_lookup_field(fields_hash_table_length, + fields_hash_table, + field_name_constant->utf8.bytes, + field_name_constant->utf8.length); + + // cache the result + class_entry->attribute_entry[fieldref_index - 1].field_entry = field_entry; + + return field_entry; +} + +struct method_info * class_resolver_lookup_method(int methods_hash_table_length, + struct hash_table_entry * methods_hash_table, const uint8_t * method_name, int method_name_length, const uint8_t * method_descriptor, @@ -180,9 +319,6 @@ struct method_info * class_resolver_lookup_method(struct class_entry * class_ent 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_find2(methods_hash_table_length, methods_hash_table, method_name, @@ -195,22 +331,55 @@ struct method_info * class_resolver_lookup_method(struct class_entry * class_ent return (struct method_info *)e->value; } +struct method_info * class_resolver_lookup_method_from_methodref_index(int methods_hash_table_length, + struct hash_table_entry * methods_hash_table, + struct class_entry * class_entry, + int methodref_index) +{ + if (class_entry->attribute_entry[methodref_index - 1].method_info != nullptr) { + printf("class_resolver_lookup_method_from_methodref_index %d: [cached]\n", methodref_index); + return class_entry->attribute_entry[methodref_index - 1].method_info; + } + + struct constant * methodref_constant = &class_entry->class_file->constant_pool[methodref_index - 1]; + #ifdef DEBUG + assert(methodref_constant->tag == CONSTANT_Methodref); + #endif + struct constant * nameandtype_constant = &class_entry->class_file->constant_pool[methodref_constant->methodref.name_and_type_index - 1]; + #ifdef DEBUG + assert(nameandtype_constant->tag == CONSTANT_NameAndType); + #endif + struct constant * method_name_constant = &class_entry->class_file->constant_pool[nameandtype_constant->nameandtype.name_index - 1]; + #ifdef DEBUG + assert(method_name_constant->tag == CONSTANT_Utf8); + #endif + struct constant * method_descriptor_constant = &class_entry->class_file->constant_pool[nameandtype_constant->nameandtype.descriptor_index - 1]; + #ifdef DEBUG + assert(method_descriptor_constant->tag == CONSTANT_Utf8); + #endif + + struct method_info * method_info = class_resolver_lookup_method(methods_hash_table_length, + methods_hash_table, + method_name_constant->utf8.bytes, + method_name_constant->utf8.length, + method_descriptor_constant->utf8.bytes, + method_descriptor_constant->utf8.length); + + // cache the result + class_entry->attribute_entry[methodref_index - 1].method_info = method_info; + + return method_info; +} + int32_t * class_resolver_lookup_string(int class_hash_table_length, struct hash_table_entry * class_hash_table, struct class_entry * class_entry, const int string_index) { printf("class_resolver_lookup_string: %d\n", string_index); - - int strings_hash_table_length = class_entry->strings.length; - struct hash_table_entry * strings_hash_table = class_entry->strings.entry; - - struct hash_table_entry * e = hash_table_find_int(strings_hash_table_length, - strings_hash_table, - string_index); - if (e != nullptr) { - int32_t * objectref = (int32_t *)e->value; - return objectref; + if (class_entry->attribute_entry[string_index - 1].string_objectref != nullptr) { + printf("class_resolver_lookup_string: [cached]\n"); + return class_entry->attribute_entry[string_index - 1].string_objectref; } struct constant * utf8_constant = &class_entry->class_file->constant_pool[string_index - 1]; @@ -235,10 +404,8 @@ int32_t * class_resolver_lookup_string(int class_hash_table_length, objectref[0] = (int32_t)string_class_entry; objectref[1] = (int32_t)arrayref; - hash_table_add_int(strings_hash_table_length, - strings_hash_table, - string_index, - objectref); + // cache the result + class_entry->attribute_entry[string_index - 1].string_objectref = objectref; return objectref; } diff --git a/c/class_resolver.h b/c/class_resolver.h index c186719..fa17ea1 100644 --- a/c/class_resolver.h +++ b/c/class_resolver.h @@ -5,28 +5,32 @@ #include "class_file.h" #include "hash_table.h" -struct field_entry { - struct field_info * field_info; - union { - uint64_t value64; - uint32_t value32; - }; -}; - enum initialization_state { CLASS_UNINITIALIZED, CLASS_INITIALIZING, CLASS_INITIALIZED, }; +union attribute_entry { + struct class_entry * class_entry; + struct method_info * method_info; + struct field_entry * field_entry; + int32_t * string_objectref; +}; + +struct field_entry { + struct field_info * field_info; + union { + int32_t instance_index; + int32_t static_index; + }; +}; + struct class_entry { struct class_file * class_file; enum initialization_state initialization_state; - - struct { - int length; - struct hash_table_entry * entry; - } strings; + union attribute_entry * attribute_entry; + int32_t * static_fields; struct { int length; @@ -49,14 +53,29 @@ struct class_entry * class_resolver_lookup_class(int class_hash_table_length, struct hash_table_entry * class_hash_table, const uint8_t * class_name, int class_name_length); -struct method_info * class_resolver_lookup_method(struct class_entry * class_entry, +struct class_entry * class_resolver_lookup_class_from_class_index(int class_hash_table_length, + struct hash_table_entry * class_hash_table, + struct class_entry * class_entry, + int32_t class_index); +struct method_info * class_resolver_lookup_method(int methods_hash_table_length, + struct hash_table_entry * methods_hash_table, const uint8_t * method_name, 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, +struct method_info * class_resolver_lookup_method_from_methodref_index(int methods_hash_table_length, + struct hash_table_entry * methods_hash_table, + struct class_entry * class_entry, + int methodref_index); +struct field_entry * class_resolver_lookup_field(int fields_hash_table_length, + struct hash_table_entry * fields_hash_table, const uint8_t * field_name, - int field_name_length); + int index); +struct field_entry * class_resolver_lookup_field_from_fieldref_index(int fields_hash_table_length, + struct hash_table_entry * fields_hash_table, + struct class_entry * class_entry, + int fieldref_index); + int32_t * class_resolver_lookup_string(int class_hash_table_length, struct hash_table_entry * class_hash_table, struct class_entry * class_entry, diff --git a/c/execute.c b/c/execute.c index 234bfdc..01d297e 100644 --- a/c/execute.c +++ b/c/execute.c @@ -683,10 +683,7 @@ void op_getfield(struct vm * vm, uint32_t index) &field_entry, &field_descriptor_constant); - //assert(field_descriptor_constant->utf8.length == 1 || field_descriptor_constant->utf8.length == 2); - - uint32_t field_index = field_entry->field_info - class_entry->class_file->fields; - printf("putfield field_index %d\n", field_index); + printf("putfield instance_index %d\n", field_entry->instance_index); int32_t * objectref = (int32_t *)operand_stack_pop_u32(vm->current_frame); int32_t * objectfields = &objectref[1]; @@ -701,15 +698,15 @@ void op_getfield(struct vm * vm, uint32_t index) case 'Z': [[fallthrough]]; case '[': { - uint32_t value = objectfields[field_index]; + uint32_t value = objectfields[field_entry->instance_index]; operand_stack_push_u32(vm->current_frame, value); } break; case 'D': [[fallthrough]]; case 'J': { - uint32_t low = objectfields[field_index * 2]; - uint32_t high = objectfields[field_index * 2 + 1]; + uint32_t low = objectfields[field_entry->instance_index]; + uint32_t high = objectfields[field_entry->instance_index + 1]; operand_stack_push_u32(vm->current_frame, low); operand_stack_push_u32(vm->current_frame, high); } @@ -736,8 +733,6 @@ void op_getstatic(struct vm * vm, uint32_t index) if (!vm_initialize_class(vm, class_entry)) return; - //assert(field_descriptor_constant->utf8.length == 1 || field_descriptor_constant->utf8.length == 2); - switch (field_descriptor_constant->utf8.bytes[0]) { case 'B': [[fallthrough]]; case 'C': [[fallthrough]]; @@ -748,15 +743,17 @@ void op_getstatic(struct vm * vm, uint32_t index) case 'Z': [[fallthrough]]; case '[': { - uint32_t value = field_entry->value32; + uint32_t value = class_entry->static_fields[field_entry->static_index]; operand_stack_push_u32(vm->current_frame, value); } break; case 'D': [[fallthrough]]; case 'J': { - uint64_t value = field_entry->value64; - operand_stack_push_u64(vm->current_frame, value); + uint32_t low = class_entry->static_fields[field_entry->static_index]; + uint32_t high = class_entry->static_fields[field_entry->static_index + 1]; + operand_stack_push_u32(vm->current_frame, low); + operand_stack_push_u32(vm->current_frame, high); } break; default: @@ -1709,7 +1706,8 @@ void op_putfield(struct vm * vm, uint32_t index) struct class_entry * class_entry; struct field_entry * field_entry; struct constant * field_descriptor_constant; - class_entry_field_entry_from_constant_index(vm, index, + class_entry_field_entry_from_constant_index(vm, + index, &class_entry, &field_entry, &field_descriptor_constant); @@ -1722,10 +1720,7 @@ void op_putfield(struct vm * vm, uint32_t index) type or an array type, then the value must be a value of the field descriptor type. */ - //assert(field_descriptor_constant->utf8.length == 1 || field_descriptor_constant->utf8.length == 2); - - uint32_t field_index = field_entry->field_info - class_entry->class_file->fields; - printf("putfield field_index %d\n", field_index); + printf("putfield instance_index %d\n", field_entry->instance_index); switch (field_descriptor_constant->utf8.bytes[0]) { case 'B': [[fallthrough]]; @@ -1740,7 +1735,7 @@ void op_putfield(struct vm * vm, uint32_t index) uint32_t value = operand_stack_pop_u32(vm->current_frame); int32_t * objectref = (int32_t *)operand_stack_pop_u32(vm->current_frame); int32_t * objectfields = &objectref[1]; - objectfields[field_index] = value; + objectfields[field_entry->instance_index] = value; } break; case 'D': [[fallthrough]]; @@ -1750,8 +1745,8 @@ void op_putfield(struct vm * vm, uint32_t index) uint32_t low = operand_stack_pop_u32(vm->current_frame); int32_t * objectref = (int32_t *)operand_stack_pop_u32(vm->current_frame); int32_t * objectfields = &objectref[1]; - objectfields[field_index * 2 + 1] = high; - objectfields[field_index * 2] = low; + objectfields[field_entry->instance_index + 1] = high; + objectfields[field_entry->instance_index] = low; } break; default: @@ -1784,8 +1779,6 @@ void op_putstatic(struct vm * vm, uint32_t index) if (!vm_initialize_class(vm, class_entry)) return; - //assert(field_descriptor_constant->utf8.length == 1 || field_descriptor_constant->utf8.length == 2); - switch (field_descriptor_constant->utf8.bytes[0]) { case 'B': [[fallthrough]]; case 'C': [[fallthrough]]; @@ -1797,14 +1790,16 @@ void op_putstatic(struct vm * vm, uint32_t index) case '[': { uint32_t value = operand_stack_pop_u32(vm->current_frame); - field_entry->value32 = value; + class_entry->static_fields[field_entry->static_index] = value; } break; case 'D': [[fallthrough]]; case 'J': { - uint64_t value = operand_stack_pop_u64(vm->current_frame); - field_entry->value64 = value; + uint32_t high = operand_stack_pop_u32(vm->current_frame); + uint32_t low = operand_stack_pop_u32(vm->current_frame); + class_entry->static_fields[field_entry->static_index + 1] = high; + class_entry->static_fields[field_entry->static_index] = low; } break; default: diff --git a/c/execute_helper.h b/c/execute_helper.h index 5835838..6f37bf8 100644 --- a/c/execute_helper.h +++ b/c/execute_helper.h @@ -1,7 +1,7 @@ #include "debug_class_file.h" static inline void class_entry_field_entry_from_constant_index(struct vm * vm, - uint32_t index, + int32_t index, struct class_entry ** class_entry, struct field_entry ** field_entry, struct constant ** field_descriptor_constant) @@ -10,41 +10,35 @@ static inline void class_entry_field_entry_from_constant_index(struct vm * vm, #ifdef DEBUG assert(fieldref_constant->tag == CONSTANT_Fieldref); #endif - struct constant * class_constant = &vm->current_frame->class_entry->class_file->constant_pool[fieldref_constant->fieldref.class_index - 1]; - #ifdef DEBUG - assert(class_constant->tag == CONSTANT_Class); - #endif + + *class_entry = class_resolver_lookup_class_from_class_index(vm->class_hash_table.length, + vm->class_hash_table.entry, + vm->current_frame->class_entry, + fieldref_constant->fieldref.class_index); + + assert(*class_entry != nullptr); + + int fields_hash_table_length = (*class_entry)->fields.length; + struct hash_table_entry * fields_hash_table = (*class_entry)->fields.entry; + + *field_entry = class_resolver_lookup_field_from_fieldref_index(fields_hash_table_length, + fields_hash_table, + vm->current_frame->class_entry, + index); + assert(*field_entry != nullptr); + struct constant * nameandtype_constant = &vm->current_frame->class_entry->class_file->constant_pool[fieldref_constant->fieldref.name_and_type_index - 1]; #ifdef DEBUG assert(nameandtype_constant->tag == CONSTANT_NameAndType); #endif - struct constant * class_name_constant = &vm->current_frame->class_entry->class_file->constant_pool[class_constant->class.name_index - 1]; - #ifdef DEBUG - assert(class_name_constant->tag == CONSTANT_Utf8); - #endif - struct constant * field_name_constant = &vm->current_frame->class_entry->class_file->constant_pool[nameandtype_constant->nameandtype.name_index - 1]; - #ifdef DEBUG - assert(field_name_constant->tag == CONSTANT_Utf8); - #endif *field_descriptor_constant = &vm->current_frame->class_entry->class_file->constant_pool[nameandtype_constant->nameandtype.descriptor_index - 1]; #ifdef DEBUG assert((*field_descriptor_constant)->tag == CONSTANT_Utf8); #endif - - *class_entry = class_resolver_lookup_class(vm->class_hash_table.length, - vm->class_hash_table.entry, - class_name_constant->utf8.bytes, - class_name_constant->utf8.length); - assert(*class_entry != nullptr); - - *field_entry = class_resolver_lookup_field(*class_entry, - field_name_constant->utf8.bytes, - field_name_constant->utf8.length); - assert(*field_entry != nullptr); } static inline void class_entry_method_info_from_constant_index(struct vm * vm, - uint32_t index, + int32_t index, struct class_entry ** class_entry, struct method_info ** method_info) { @@ -52,37 +46,19 @@ static inline void class_entry_method_info_from_constant_index(struct vm * vm, #ifdef DEBUG assert(methodref_constant->tag == CONSTANT_Methodref); #endif - struct constant * class_constant = &vm->current_frame->class_entry->class_file->constant_pool[methodref_constant->methodref.class_index - 1]; - #ifdef DEBUG - assert(class_constant->tag == CONSTANT_Class); - #endif - struct constant * nameandtype_constant = &vm->current_frame->class_entry->class_file->constant_pool[methodref_constant->methodref.name_and_type_index - 1]; - #ifdef DEBUG - assert(nameandtype_constant->tag == CONSTANT_NameAndType); - #endif - struct constant * class_name_constant = &vm->current_frame->class_entry->class_file->constant_pool[class_constant->class.name_index - 1]; - #ifdef DEBUG - assert(class_name_constant->tag == CONSTANT_Utf8); - #endif - struct constant * method_name_constant = &vm->current_frame->class_entry->class_file->constant_pool[nameandtype_constant->nameandtype.name_index - 1]; - #ifdef DEBUG - assert(method_name_constant->tag == CONSTANT_Utf8); - #endif - struct constant * method_descriptor_constant = &vm->current_frame->class_entry->class_file->constant_pool[nameandtype_constant->nameandtype.descriptor_index - 1]; - #ifdef DEBUG - assert(method_descriptor_constant->tag == CONSTANT_Utf8); - #endif - *class_entry = class_resolver_lookup_class(vm->class_hash_table.length, - vm->class_hash_table.entry, - class_name_constant->utf8.bytes, - class_name_constant->utf8.length); + *class_entry = class_resolver_lookup_class_from_class_index(vm->class_hash_table.length, + vm->class_hash_table.entry, + vm->current_frame->class_entry, + methodref_constant->methodref.class_index); assert(*class_entry != nullptr); - *method_info = class_resolver_lookup_method(*class_entry, - method_name_constant->utf8.bytes, - method_name_constant->utf8.length, - method_descriptor_constant->utf8.bytes, - method_descriptor_constant->utf8.length); + int methods_hash_table_length = (*class_entry)->methods.length; + struct hash_table_entry * methods_hash_table = (*class_entry)->methods.entry; + + *method_info = class_resolver_lookup_method_from_methodref_index(methods_hash_table_length, + methods_hash_table, + vm->current_frame->class_entry, + index); assert(*method_info != nullptr); } diff --git a/c/frame.c b/c/frame.c index 87e890c..b95e584 100644 --- a/c/frame.c +++ b/c/frame.c @@ -133,13 +133,19 @@ bool vm_initialize_class(struct vm * vm, struct class_entry * class_entry) struct constant * name_constant = &class_file->constant_pool[field_info->name_index - 1]; assert(name_constant->tag == CONSTANT_Utf8); - struct field_entry * field_entry = class_resolver_lookup_field(class_entry, + + int fields_hash_table_length = class_entry->fields.length; + struct hash_table_entry * fields_hash_table = class_entry->fields.entry; + + struct field_entry * field_entry = class_resolver_lookup_field(fields_hash_table_length, + fields_hash_table, name_constant->utf8.bytes, name_constant->utf8.length); - assert(field_entry != nullptr); - field_entry->value32 = constantvalue->integer.bytes; - printf(" constantvalue: %d\n", field_entry->value32); + assert(field_info != nullptr); + class_entry->static_fields[field_entry->static_index] = constantvalue->integer.bytes; + printf(" constantvalue: %d\n", constantvalue->integer.bytes); break; + } } } @@ -152,7 +158,11 @@ bool vm_initialize_class(struct vm * vm, struct class_entry * class_entry) 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, + int methods_hash_table_length = class_entry->methods.length; + struct hash_table_entry * methods_hash_table = class_entry->methods.entry; + + struct method_info * method_info = class_resolver_lookup_method(methods_hash_table_length, + methods_hash_table, method_name, method_name_length, method_descriptor, diff --git a/c/hash_table.c b/c/hash_table.c index ccacef9..79ee5cb 100644 --- a/c/hash_table.c +++ b/c/hash_table.c @@ -1,3 +1,5 @@ +#include + #include "malloc.h" #include "hash_table.h" @@ -41,6 +43,7 @@ void hash_table_add(int hash_table_length, int key_length, void * value) { + assert(hash_table_length != 0); uint32_t hash = fnv_1(fnv_offset_basis, key, key_length) & (hash_table_length - 1); struct hash_table_entry * e = &entry[hash]; @@ -78,6 +81,7 @@ struct hash_table_entry * hash_table_find(int hash_table_length, const uint8_t * key, int key_length) { + assert(hash_table_length != 0); uint32_t hash = fnv_1(fnv_offset_basis, key, key_length) & (hash_table_length - 1); struct hash_table_entry * e = &entry[hash]; @@ -115,6 +119,7 @@ void hash_table_add2(int hash_table_length, int key2_length, void * value) { + assert(hash_table_length != 0); uint32_t hash = fnv_offset_basis; hash = fnv_1(hash, key1, key1_length); hash = fnv_1(hash, key2, key2_length); @@ -146,6 +151,7 @@ struct hash_table_entry * hash_table_find2(int hash_table_length, const uint8_t * key2, int key2_length) { + assert(hash_table_length != 0); uint32_t hash = fnv_offset_basis; hash = fnv_1(hash, key1, key1_length); hash = fnv_1(hash, key2, key2_length); @@ -167,6 +173,7 @@ struct hash_table_entry * hash_table_find2(int hash_table_length, return nullptr; } +/* void hash_table_add_int(int hash_table_length, struct hash_table_entry * entry, int key, @@ -188,3 +195,4 @@ struct hash_table_entry * hash_table_find_int(int hash_table_length, (const uint8_t *)&key, 4); } +*/ diff --git a/c/hash_table.h b/c/hash_table.h index 65be1ad..3fe36a5 100644 --- a/c/hash_table.h +++ b/c/hash_table.h @@ -38,6 +38,7 @@ struct hash_table_entry * hash_table_find2(int hash_table_length, const uint8_t * key2, int key2_length); +/* void hash_table_add_int(int hash_table_length, struct hash_table_entry * entry, int key, @@ -46,3 +47,4 @@ void hash_table_add_int(int hash_table_length, struct hash_table_entry * hash_table_find_int(int hash_table_length, struct hash_table_entry * entry, int key); +*/ diff --git a/c/main.c b/c/main.c index 10f17c3..fdcd410 100644 --- a/c/main.c +++ b/c/main.c @@ -24,7 +24,12 @@ int main(int argc, const char * argv[]) 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, + + int methods_hash_table_length = class_entry->methods.length; + struct hash_table_entry * methods_hash_table = class_entry->methods.entry; + + struct method_info * method_info = class_resolver_lookup_method(methods_hash_table_length, + methods_hash_table, (const uint8_t *)method_name, method_name_length, (const uint8_t *)method_descriptor, diff --git a/c/malloc.c b/c/malloc.c index 1f6b035..3386130 100644 --- a/c/malloc.c +++ b/c/malloc.c @@ -18,6 +18,9 @@ struct arena class_arena = { void * malloc_class_arena(uint32_t size) { + if (size == 0) + return nullptr; + assert((class_arena.ix & (~3)) == class_arena.ix); void * ptr = &class_arena.mem[class_arena.ix]; size = (size + 3) & (~3);