diff --git a/Makefile b/Makefile index 786a7f1..e0e2f48 100644 --- a/Makefile +++ b/Makefile @@ -4,6 +4,9 @@ %.class: %.java javac $< +java/lang/%.class: java/lang/%.java + javac --source 8 --target 8 --boot-class-path . $< + OBJ = \ c/decode.o \ c/class_file.o \ diff --git a/c/class_resolver.c b/c/class_resolver.c index 1cebaa8..cde445a 100644 --- a/c/class_resolver.c +++ b/c/class_resolver.c @@ -10,6 +10,7 @@ #include "class_resolver.h" #include "string.h" #include "debug_class_file.h" +#include "memory_allocator.h" struct hash_table_entry * class_resolver_load_from_filenames(const char * filenames[], int length, int * hash_table_length) { @@ -47,6 +48,13 @@ 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) { @@ -186,3 +194,51 @@ struct method_info * class_resolver_lookup_method(struct class_entry * class_ent return (struct method_info *)e->value; } + +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; + } + + struct constant * utf8_constant = &class_entry->class_file->constant_pool[string_index - 1]; + assert(utf8_constant->tag == CONSTANT_Utf8); + + struct class_entry * string_class_entry = class_resolver_lookup_class(class_hash_table_length, + class_hash_table, + (const uint8_t *)"java/lang/String", + 16); + + int32_t size = utf8_constant->utf8.length + 4; + int32_t * arrayref = memory_allocate(size); + assert(arrayref != nullptr); + arrayref[0] = utf8_constant->utf8.length; + uint8_t * bytearray = (uint8_t *)&arrayref[1]; + for (int i = 0; i < utf8_constant->utf8.length; i++) + bytearray[i] = utf8_constant->utf8.bytes[i]; + + assert(string_class_entry != nullptr); + int32_t * objectref = memory_allocate(4 + 4); + assert(objectref != nullptr); + 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); + + return objectref; +} diff --git a/c/class_resolver.h b/c/class_resolver.h index 239f10d..c186719 100644 --- a/c/class_resolver.h +++ b/c/class_resolver.h @@ -23,6 +23,11 @@ struct class_entry { struct class_file * class_file; enum initialization_state initialization_state; + struct { + int length; + struct hash_table_entry * entry; + } strings; + struct { int length; struct hash_table_entry * entry; @@ -52,3 +57,7 @@ struct method_info * class_resolver_lookup_method(struct class_entry * class_ent struct field_entry * class_resolver_lookup_field(struct class_entry * class_entry, const uint8_t * field_name, int field_name_length); +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); diff --git a/c/execute.c b/c/execute.c index c9c8366..a3f2910 100644 --- a/c/execute.c +++ b/c/execute.c @@ -131,8 +131,8 @@ void op_baload(struct vm * vm) int32_t index = operand_stack_pop_u32(vm->current_frame); int32_t * arrayref = (int32_t *)operand_stack_pop_u32(vm->current_frame); assert(arrayref[0] > 0 && index < arrayref[0]); - int8_t * chararray = (int8_t *)&arrayref[1]; - int8_t value = chararray[index]; + int8_t * bytearray = (int8_t *)&arrayref[1]; + int8_t value = bytearray[index]; operand_stack_push_u32(vm->current_frame, value); } @@ -142,8 +142,8 @@ void op_bastore(struct vm * vm) int32_t index = operand_stack_pop_u32(vm->current_frame); int32_t * arrayref = (int32_t *)operand_stack_pop_u32(vm->current_frame); assert(arrayref[0] > 0 && index < arrayref[0]); - int8_t * chararray = (int8_t *)&arrayref[1]; - chararray[index] = value; + int8_t * bytearray = (int8_t *)&arrayref[1]; + bytearray[index] = value; } void op_bipush(struct vm * vm, int32_t byte) @@ -682,30 +682,34 @@ void op_getfield(struct vm * vm, uint32_t index) &class_entry, &field_entry, &field_descriptor_constant); - assert(field_descriptor_constant->utf8.length == 1); + // could be an array + 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); int32_t * objectref = (int32_t *)operand_stack_pop_u32(vm->current_frame); + int32_t * objectfields = &objectref[1]; switch (field_descriptor_constant->utf8.bytes[0]) { - case 'Z': [[fallthrough]]; case 'B': [[fallthrough]]; case 'C': [[fallthrough]]; - case 'S': [[fallthrough]]; + case 'F': [[fallthrough]]; case 'I': [[fallthrough]]; - case 'F': + case 'L': [[fallthrough]]; + case 'S': [[fallthrough]]; + case 'Z': [[fallthrough]]; + case '[': { - uint32_t value = objectref[field_index]; + uint32_t value = objectfields[field_index]; operand_stack_push_u32(vm->current_frame, value); } break; case 'D': [[fallthrough]]; case 'J': { - uint32_t low = objectref[field_index * 2]; - uint32_t high = objectref[field_index * 2 + 1]; + uint32_t low = objectfields[field_index * 2]; + uint32_t high = objectfields[field_index * 2 + 1]; operand_stack_push_u32(vm->current_frame, low); operand_stack_push_u32(vm->current_frame, high); } @@ -732,15 +736,17 @@ void op_getstatic(struct vm * vm, uint32_t index) if (!vm_initialize_class(vm, class_entry)) return; - assert(field_descriptor_constant->utf8.length == 1); + assert(field_descriptor_constant->utf8.length == 1 || field_descriptor_constant->utf8.length == 2); switch (field_descriptor_constant->utf8.bytes[0]) { - case 'Z': [[fallthrough]]; case 'B': [[fallthrough]]; case 'C': [[fallthrough]]; - case 'S': [[fallthrough]]; + case 'F': [[fallthrough]]; case 'I': [[fallthrough]]; - case 'F': + case 'L': [[fallthrough]]; + case 'S': [[fallthrough]]; + case 'Z': [[fallthrough]]; + case '[': { uint32_t value = field_entry->value32; operand_stack_push_u32(vm->current_frame, value); @@ -1110,7 +1116,7 @@ void op_invokespecial(struct vm * vm, uint32_t index) &class_entry, &method_info); - vm_special_method_call(vm, class_entry->class_file, method_info); + vm_special_method_call(vm, class_entry, method_info); } void op_invokestatic(struct vm * vm, uint32_t index) @@ -1125,7 +1131,7 @@ void op_invokestatic(struct vm * vm, uint32_t index) declared the resolved method is initialized if that class or interface has not already been initialized (ยง5.5). */ - vm_static_method_call(vm, class_entry->class_file, method_info); + vm_static_method_call(vm, class_entry, method_info); } void op_invokevirtual(struct vm * vm, uint32_t index) @@ -1136,7 +1142,7 @@ void op_invokevirtual(struct vm * vm, uint32_t index) &class_entry, &method_info); - vm_special_method_call(vm, class_entry->class_file, method_info); + vm_special_method_call(vm, class_entry, method_info); } void op_ior(struct vm * vm) @@ -1361,17 +1367,24 @@ void op_lconst_1(struct vm * vm) void op_ldc(struct vm * vm, uint32_t index) { - struct constant * constant = &vm->current_frame->class->constant_pool[index - 1]; - #ifdef DEBUG - assert(constant->tag == CONSTANT_Integer || constant->tag == CONSTANT_Float); - #endif - int32_t value = constant->integer.bytes; - operand_stack_push_u32(vm->current_frame, value); + struct constant * constant = &vm->current_frame->class_entry->class_file->constant_pool[index - 1]; + if (constant->tag == CONSTANT_Integer || constant->tag == CONSTANT_Float) { + int32_t value = constant->integer.bytes; + operand_stack_push_u32(vm->current_frame, value); + } else if (constant->tag == CONSTANT_String) { + int32_t * objectref = class_resolver_lookup_string(vm->class_hash_table.length, + vm->class_hash_table.entry, + vm->current_frame->class_entry, + constant->string.string_index); + operand_stack_push_u32(vm->current_frame, (uint32_t)objectref); + } else { + assert(false); + } } void op_ldc2_w(struct vm * vm, uint32_t index) { - struct constant * constant = &vm->current_frame->class->constant_pool[index - 1]; + struct constant * constant = &vm->current_frame->class_entry->class_file->constant_pool[index - 1]; #ifdef DEBUG assert(constant->tag == CONSTANT_Long || constant->tag == CONSTANT_Double); #endif @@ -1381,7 +1394,7 @@ void op_ldc2_w(struct vm * vm, uint32_t index) void op_ldc_w(struct vm * vm, uint32_t index) { - struct constant * constant = &vm->current_frame->class->constant_pool[index - 1]; + struct constant * constant = &vm->current_frame->class_entry->class_file->constant_pool[index - 1]; #ifdef DEBUG assert(constant->tag == CONSTANT_Integer || constant->tag == CONSTANT_Float); #endif @@ -1579,11 +1592,11 @@ void op_multianewarray(struct vm * vm, uint32_t index, uint32_t dimensions) void op_new(struct vm * vm, uint32_t index) { - struct constant * class_constant = &vm->current_frame->class->constant_pool[index - 1]; + struct constant * class_constant = &vm->current_frame->class_entry->class_file->constant_pool[index - 1]; #ifdef DEBUG assert(class_constant->tag == CONSTANT_Class); #endif - struct constant * class_name_constant = &vm->current_frame->class->constant_pool[class_constant->class.name_index - 1]; + 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 @@ -1609,13 +1622,13 @@ void op_new(struct vm * vm, uint32_t index) reference to the instance, is pushed onto the operand stack. */ int fields_count = class_entry->class_file->fields_count; - int32_t * objectref = (int32_t *)-1; - if (fields_count > 0) { - objectref = memory_allocate(fields_count * 2 * 4); - for (int i = 0; i < fields_count; i++) { - objectref[i * 2] = 0; - objectref[i * 2 + 1] = 0; - } + int32_t * objectref = memory_allocate(fields_count * 2 * 4 + 4); + assert(objectref != nullptr); + objectref[0] = (int32_t)class_entry; + int32_t * objectfields = &objectref[1]; + for (int i = 0; i < fields_count; i++) { + objectfields[i * 2] = 0; + objectfields[i * 2 + 1] = 0; } operand_stack_push_u32(vm->current_frame, (uint32_t)objectref); @@ -1709,22 +1722,25 @@ 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); + 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); switch (field_descriptor_constant->utf8.bytes[0]) { - case 'Z': [[fallthrough]]; case 'B': [[fallthrough]]; case 'C': [[fallthrough]]; - case 'S': [[fallthrough]]; + case 'F': [[fallthrough]]; case 'I': [[fallthrough]]; - case 'F': + case 'L': [[fallthrough]]; + case 'S': [[fallthrough]]; + case 'Z': [[fallthrough]]; + case '[': { uint32_t value = operand_stack_pop_u32(vm->current_frame); int32_t * objectref = (int32_t *)operand_stack_pop_u32(vm->current_frame); - objectref[field_index] = value; + int32_t * objectfields = &objectref[1]; + objectfields[field_index] = value; } break; case 'D': [[fallthrough]]; @@ -1733,8 +1749,9 @@ void op_putfield(struct vm * vm, uint32_t index) uint32_t high = operand_stack_pop_u32(vm->current_frame); uint32_t low = operand_stack_pop_u32(vm->current_frame); int32_t * objectref = (int32_t *)operand_stack_pop_u32(vm->current_frame); - objectref[field_index * 2 + 1] = high; - objectref[field_index * 2] = low; + int32_t * objectfields = &objectref[1]; + objectfields[field_index * 2 + 1] = high; + objectfields[field_index * 2] = low; } break; default: @@ -1767,15 +1784,17 @@ void op_putstatic(struct vm * vm, uint32_t index) if (!vm_initialize_class(vm, class_entry)) return; - assert(field_descriptor_constant->utf8.length == 1); + assert(field_descriptor_constant->utf8.length == 1 || field_descriptor_constant->utf8.length == 2); switch (field_descriptor_constant->utf8.bytes[0]) { - case 'Z': [[fallthrough]]; case 'B': [[fallthrough]]; case 'C': [[fallthrough]]; - case 'S': [[fallthrough]]; + case 'F': [[fallthrough]]; case 'I': [[fallthrough]]; - case 'F': + case 'L': [[fallthrough]]; + case 'S': [[fallthrough]]; + case 'Z': [[fallthrough]]; + case '[': { uint32_t value = operand_stack_pop_u32(vm->current_frame); field_entry->value32 = value; diff --git a/c/execute_helper.h b/c/execute_helper.h index a42595c..5835838 100644 --- a/c/execute_helper.h +++ b/c/execute_helper.h @@ -6,27 +6,27 @@ static inline void class_entry_field_entry_from_constant_index(struct vm * vm, struct field_entry ** field_entry, struct constant ** field_descriptor_constant) { - struct constant * fieldref_constant = &vm->current_frame->class->constant_pool[index - 1]; + struct constant * fieldref_constant = &vm->current_frame->class_entry->class_file->constant_pool[index - 1]; #ifdef DEBUG assert(fieldref_constant->tag == CONSTANT_Fieldref); #endif - struct constant * class_constant = &vm->current_frame->class->constant_pool[fieldref_constant->fieldref.class_index - 1]; + 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 - struct constant * nameandtype_constant = &vm->current_frame->class->constant_pool[fieldref_constant->fieldref.name_and_type_index - 1]; + 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->constant_pool[class_constant->class.name_index - 1]; + 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->constant_pool[nameandtype_constant->nameandtype.name_index - 1]; + 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->constant_pool[nameandtype_constant->nameandtype.descriptor_index - 1]; + *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 @@ -48,27 +48,27 @@ static inline void class_entry_method_info_from_constant_index(struct vm * vm, struct class_entry ** class_entry, struct method_info ** method_info) { - struct constant * methodref_constant = &vm->current_frame->class->constant_pool[index - 1]; + struct constant * methodref_constant = &vm->current_frame->class_entry->class_file->constant_pool[index - 1]; #ifdef DEBUG assert(methodref_constant->tag == CONSTANT_Methodref); #endif - struct constant * class_constant = &vm->current_frame->class->constant_pool[methodref_constant->methodref.class_index - 1]; + 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->constant_pool[methodref_constant->methodref.name_and_type_index - 1]; + 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->constant_pool[class_constant->class.name_index - 1]; + 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->constant_pool[nameandtype_constant->nameandtype.name_index - 1]; + 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->constant_pool[nameandtype_constant->nameandtype.descriptor_index - 1]; + 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 diff --git a/c/frame.c b/c/frame.c index 2e50dab..87e890c 100644 --- a/c/frame.c +++ b/c/frame.c @@ -56,7 +56,6 @@ static int descriptor_nargs(struct constant * descriptor_constant, uint8_t * ret printf("method descriptor: "); print_utf8_string(descriptor_constant); printf("\n"); - printf("args: `"); int i = 1; int nargs = 0; @@ -81,7 +80,6 @@ static int descriptor_nargs(struct constant * descriptor_constant, uint8_t * ret } i += 1; } - printf("\n"); *return_type = descriptor_constant->utf8.bytes[i + 1]; @@ -106,7 +104,7 @@ bool vm_initialize_class(struct vm * vm, struct class_entry * class_entry) return true; if (class_entry->initialization_state == CLASS_INITIALIZING) { - if (vm->current_frame->class == class_entry->class_file) + if (vm->current_frame->class_entry->class_file == class_entry->class_file) return true; else assert(false); // possible infinite initialization loop @@ -166,10 +164,9 @@ bool vm_initialize_class(struct vm * vm, struct class_entry * class_entry) // tamper with next_pc vm->current_frame->next_pc = vm->current_frame->pc; - vm_static_method_call(vm, class_file, method_info); + vm_static_method_call(vm, class_entry, method_info); - // tamper with initialization_frame - vm->current_frame->initialization_frame = class_entry; + vm->current_frame->initialization_frame = 1; return false; } else { class_entry->initialization_state = CLASS_INITIALIZED; @@ -179,7 +176,7 @@ bool vm_initialize_class(struct vm * vm, struct class_entry * class_entry) return true; } -void vm_special_method_call(struct vm * vm, struct class_file * class_file, struct method_info * method_info) +void vm_special_method_call(struct vm * vm, struct class_entry * class_entry, struct method_info * method_info) { /* If the method is not native, the nargs argument values are popped from the operand stack. A new frame is created on the Java Virtual Machine stack for @@ -191,7 +188,7 @@ void vm_special_method_call(struct vm * vm, struct class_file * class_file, stru invoked. Execution continues with the first instruction of the method. */ - int code_name_index = find_code_name_index(class_file); + int code_name_index = find_code_name_index(class_entry->class_file); assert(code_name_index > 0); struct Code_attribute * code = get_code_attribute(code_name_index, @@ -206,9 +203,9 @@ void vm_special_method_call(struct vm * vm, struct class_file * class_file, stru vm->current_frame->local_variable = stack_push_data(&vm->data_stack, code->max_locals); vm->current_frame->operand_stack = stack_push_data(&vm->data_stack, code->max_stack); vm->current_frame->operand_stack_ix = 0; - vm->current_frame->initialization_frame = nullptr; + vm->current_frame->initialization_frame = 0; - struct constant * descriptor_constant = &class_file->constant_pool[method_info->descriptor_index - 1]; + struct constant * descriptor_constant = &class_entry->class_file->constant_pool[method_info->descriptor_index - 1]; int nargs = descriptor_nargs(descriptor_constant, &vm->current_frame->return_type); nargs += 1; printf("nargs+1: %d\n", nargs); @@ -219,13 +216,13 @@ void vm_special_method_call(struct vm * vm, struct class_file * class_file, stru } vm->current_frame->pc = 0; - vm->current_frame->class = class_file; + vm->current_frame->class_entry = class_entry; vm->current_frame->method = method_info; printf("operand_stack_ix: %d\n", vm->current_frame->operand_stack_ix); } -void vm_static_method_call(struct vm * vm, struct class_file * class_file, struct method_info * method_info) +void vm_static_method_call(struct vm * vm, struct class_entry * class_entry, struct method_info * method_info) { /* If the method is not native, the nargs argument values are popped from the operand stack. A new frame is created on the Java Virtual Machine stack for @@ -237,7 +234,7 @@ void vm_static_method_call(struct vm * vm, struct class_file * class_file, struc invoked. Execution continues with the first instruction of the method. */ - int code_name_index = find_code_name_index(class_file); + int code_name_index = find_code_name_index(class_entry->class_file); assert(code_name_index > 0); struct Code_attribute * code = get_code_attribute(code_name_index, @@ -252,9 +249,9 @@ void vm_static_method_call(struct vm * vm, struct class_file * class_file, struc vm->current_frame->local_variable = stack_push_data(&vm->data_stack, code->max_locals); vm->current_frame->operand_stack = stack_push_data(&vm->data_stack, code->max_stack); vm->current_frame->operand_stack_ix = 0; - vm->current_frame->initialization_frame = nullptr; + vm->current_frame->initialization_frame = 0; - struct constant * descriptor_constant = &class_file->constant_pool[method_info->descriptor_index - 1]; + struct constant * descriptor_constant = &class_entry->class_file->constant_pool[method_info->descriptor_index - 1]; int nargs = descriptor_nargs(descriptor_constant, &vm->current_frame->return_type); printf("nargs %d\n", nargs); for (int i = 0; i < nargs; i++) { @@ -265,7 +262,7 @@ void vm_static_method_call(struct vm * vm, struct class_file * class_file, struc ; vm->current_frame->pc = 0; - vm->current_frame->class = class_file; + vm->current_frame->class_entry = class_entry; vm->current_frame->method = method_info; printf("operand_stack_ix: %d\n", vm->current_frame->operand_stack_ix); @@ -273,10 +270,9 @@ void vm_static_method_call(struct vm * vm, struct class_file * class_file, struc void vm_method_return(struct vm * vm) { - if (vm->current_frame->initialization_frame != nullptr) { - printf("vm_method_return: initialization_frame!=nullptr\n"); - struct class_entry * class_entry = vm->current_frame->initialization_frame; - class_entry->initialization_state = CLASS_INITIALIZED; + if (vm->current_frame->initialization_frame != 0) { + printf("vm_method_return: initialization_frame!=0\n"); + vm->current_frame->class_entry->initialization_state = CLASS_INITIALIZED; vm->current_frame->initialization_frame = 0; } diff --git a/c/frame.h b/c/frame.h index 984911e..e885e29 100644 --- a/c/frame.h +++ b/c/frame.h @@ -6,7 +6,7 @@ #include "class_resolver.h" struct frame { - struct class_file * class; + struct class_entry * class_entry; struct method_info * method; struct Code_attribute * code; uint32_t * local_variable; @@ -14,7 +14,7 @@ struct frame { uint32_t pc; uint32_t next_pc; int32_t operand_stack_ix; - struct class_entry * initialization_frame; + uint8_t initialization_frame; uint8_t return_type; }; @@ -150,7 +150,7 @@ static inline double operand_stack_pop_f64(struct frame * frame) } bool vm_initialize_class(struct vm * vm, struct class_entry * class_entry); -void vm_special_method_call(struct vm * vm, struct class_file * class_file, struct method_info * method_info); -void vm_static_method_call(struct vm * vm, struct class_file * class_file, struct method_info * method_info); +void vm_special_method_call(struct vm * vm, struct class_entry * class_entry, struct method_info * method_info); +void vm_static_method_call(struct vm * vm, struct class_entry * class_entry, struct method_info * method_info); void vm_method_return(struct vm * vm); void vm_execute(struct vm * vm); diff --git a/c/hash_table.c b/c/hash_table.c index 1456ba3..ccacef9 100644 --- a/c/hash_table.c +++ b/c/hash_table.c @@ -166,3 +166,25 @@ 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, + void * value) +{ + hash_table_add(hash_table_length, + entry, + (const uint8_t *)&key, + 4, + value); +} + +struct hash_table_entry * hash_table_find_int(int hash_table_length, + struct hash_table_entry * entry, + int key) +{ + return hash_table_find(hash_table_length, + entry, + (const uint8_t *)&key, + 4); +} diff --git a/c/hash_table.h b/c/hash_table.h index 8cd76d6..65be1ad 100644 --- a/c/hash_table.h +++ b/c/hash_table.h @@ -37,3 +37,12 @@ struct hash_table_entry * hash_table_find2(int hash_table_length, int key1_length, const uint8_t * key2, int key2_length); + +void hash_table_add_int(int hash_table_length, + struct hash_table_entry * entry, + int key, + void * value); + +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 2891208..10f17c3 100644 --- a/c/main.c +++ b/c/main.c @@ -54,6 +54,6 @@ int main(int argc, const char * argv[]) entry_frame->operand_stack = 0; entry_frame->operand_stack_ix = 0; - vm_static_method_call(&vm, class_entry->class_file, method_info); + vm_static_method_call(&vm, class_entry, method_info); vm_execute(&vm); } diff --git a/java/lang/String.java b/java/lang/String.java new file mode 100644 index 0000000..533a522 --- /dev/null +++ b/java/lang/String.java @@ -0,0 +1,21 @@ +package java.lang; + +class String { + private final byte[] value; + + public String() { + this.value = new byte[0]; + } + + public String(String original) { + this.value = original.value; + } + + public String(byte[] value) { + this.value = value; + } + + public byte[] getBytes() { + return this.value; + } +} diff --git a/p/TestString.java b/p/TestString.java new file mode 100644 index 0000000..7871cc0 --- /dev/null +++ b/p/TestString.java @@ -0,0 +1,18 @@ +package p; + +class TestString { + static int test() { + String s = new String("asdf"); + byte[] b = s.getBytes(); + int sum = 0; + for (int i = 0; i < b.length; i++) { + sum += b[i]; + } + return sum; + } + + + public static void main() { + test(); + } +}