diff --git a/Makefile b/Makefile index 04e6d61..da83501 100644 --- a/Makefile +++ b/Makefile @@ -7,7 +7,7 @@ CC ?= gcc ARCH = -m32 CFLAGS += -Wall -Werror -Wfatal-errors -Wno-error=unused-variable -fstack-protector -std=c2x -g CFLAGS += -DDEBUG -#CFLAGS += -DDEBUG_PRINT +CFLAGS += -DDEBUG_PRINT LDFLAGS = -lm OPT ?= -O0 DEPFLAGS = -MMD -MP diff --git a/c/class_resolver.c b/c/class_resolver.c index a03d7ef..844873d 100644 --- a/c/class_resolver.c +++ b/c/class_resolver.c @@ -309,7 +309,6 @@ struct class_entry * class_resolver_lookup_class_from_class_index(int class_hash struct parse_type_ret parse_type_ret = parse_type(class_name_constant->utf8.bytes, class_name_constant->utf8.length); - struct class_entry * _class_entry = class_resolver_lookup_class(class_hash_table_length, class_hash_table, parse_type_ret.bytes, @@ -586,10 +585,10 @@ struct method_entry class_resolver_lookup_method_from_method_name_method_descrip } } -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) +struct objectref * 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) { debugf("class_resolver_lookup_string: %d\n", string_index); if (class_entry->attribute_entry[string_index - 1].string_objectref != nullptr) { @@ -605,22 +604,98 @@ int32_t * class_resolver_lookup_string(int class_hash_table_length, (const uint8_t *)"java/lang/String", 16); - int32_t size = utf8_constant->utf8.length + 4; - int32_t * arrayref = memory_allocate(size); + int32_t size = utf8_constant->utf8.length + (sizeof (struct arrayref)); + struct arrayref * 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]; + arrayref->class_entry = nullptr; // byte[] + arrayref->length = utf8_constant->utf8.length; + for (int i = 0; i < utf8_constant->utf8.length; i++) { + arrayref->u8[i] = utf8_constant->utf8.bytes[i]; + } assert(string_class_entry != nullptr); - int32_t * objectref = memory_allocate(4 + 4); + struct objectref * objectref = memory_allocate((sizeof (struct objectref)) + (sizeof (void *))); assert(objectref != nullptr); - objectref[0] = (int32_t)string_class_entry; - objectref[1] = (int32_t)arrayref; + objectref->class_entry = string_class_entry; + objectref->aref[0] = arrayref; // cache the result class_entry->attribute_entry[string_index - 1].string_objectref = objectref; return objectref; } + +bool class_resolver_instanceof(int class_hash_table_length, + struct hash_table_entry * class_hash_table, + struct class_entry * origin_class_entry, + const int class_index, + struct objectref * objectref) +{ + struct class_entry * index_class_entry = + class_resolver_lookup_class_from_class_index(class_hash_table_length, + class_hash_table, + origin_class_entry, + class_index); + assert(index_class_entry != nullptr); + + assert(objectref != nullptr); + struct class_entry * class_entry = objectref->class_entry; + while (true) { + debugf("class_entry: %p\n", class_entry); + + assert(class_entry != nullptr); + if (class_entry == index_class_entry) { + return true; + } + if (class_entry->class_file->super_class == 0) { + return false; + } + + struct constant * class_constant = &class_entry->class_file->constant_pool[class_entry->class_file->super_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]; + assert(class_name_constant->tag == CONSTANT_Utf8); + debug_print__constant__utf8_string(class_name_constant); + debugf("\n"); + + // superclass lookup + class_entry = class_resolver_lookup_class_from_class_index(class_hash_table_length, + class_hash_table, + class_entry, + class_entry->class_file->super_class); + } +} + +struct hash_table_entry * class_resolver_init_string_hash_table(int length) +{ + assert((length & (length - 1)) == 0); // length must be a power of two + int hash_table_length = length; + uint32_t hash_table_size = (sizeof (struct hash_table_entry)) * hash_table_length; + struct hash_table_entry * hash_table = malloc_class_arena(hash_table_size); + hash_table_init(hash_table_length, hash_table); + + return hash_table; +} + +void * class_resolver_memoize_string_type(int string_hash_table_length, + struct hash_table_entry * string_hash_table, + const uint8_t * type, + int length) +{ + struct hash_table_entry * e = hash_table_find(string_hash_table_length, + string_hash_table, + type, + length); + if (e != nullptr) { + assert(e->value == (void *)0x12345678); + return e; + } else { + struct hash_table_entry * e = hash_table_add(string_hash_table_length, + string_hash_table, + type, + length, + (void *)0x12345678); + assert(e != nullptr); + return e; + } +} diff --git a/c/class_resolver.h b/c/class_resolver.h index 2f01de3..33413eb 100644 --- a/c/class_resolver.h +++ b/c/class_resolver.h @@ -4,6 +4,7 @@ #include "class_file.h" #include "hash_table.h" +#include "native_types.h" enum initialization_state { CLASS_UNINITIALIZED, @@ -21,7 +22,7 @@ union attribute_entry { struct class_entry * class_entry; struct method_entry * method_entry; struct field_entry * field_entry; - int32_t * string_objectref; + struct objectref * string_objectref; }; struct field_entry { @@ -84,7 +85,20 @@ struct field_entry * class_resolver_lookup_field_from_fieldref_index(int fields_ 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, - const int string_index); +struct objectref * 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); + +bool class_resolver_instanceof(int class_hash_table_length, + struct hash_table_entry * class_hash_table, + struct class_entry * origin_class_entry, + const int class_index, + struct objectref * objectref); + +struct hash_table_entry * class_resolver_init_string_hash_table(int length); + +void * class_resolver_memoize_string_type(int string_hash_table_length, + struct hash_table_entry * string_hash_table, + const uint8_t * type, + int length); diff --git a/c/decode.inc.c b/c/decode.inc.c index 457df2b..8461613 100644 --- a/c/decode.inc.c +++ b/c/decode.inc.c @@ -3,1091 +3,1091 @@ uint32_t decode_print_instruction(const uint8_t * code, uint32_t pc) switch (code[pc]) { case 0: // nop { - debugf("%4d: nop \n", pc); + printf("%4d: nop \n", pc); return pc + 1; } case 1: // aconst_null { - debugf("%4d: aconst_null \n", pc); + printf("%4d: aconst_null \n", pc); return pc + 1; } case 2: // iconst_m1 { - debugf("%4d: iconst_m1 \n", pc); + printf("%4d: iconst_m1 \n", pc); return pc + 1; } case 3: // iconst_0 { - debugf("%4d: iconst_0 \n", pc); + printf("%4d: iconst_0 \n", pc); return pc + 1; } case 4: // iconst_1 { - debugf("%4d: iconst_1 \n", pc); + printf("%4d: iconst_1 \n", pc); return pc + 1; } case 5: // iconst_2 { - debugf("%4d: iconst_2 \n", pc); + printf("%4d: iconst_2 \n", pc); return pc + 1; } case 6: // iconst_3 { - debugf("%4d: iconst_3 \n", pc); + printf("%4d: iconst_3 \n", pc); return pc + 1; } case 7: // iconst_4 { - debugf("%4d: iconst_4 \n", pc); + printf("%4d: iconst_4 \n", pc); return pc + 1; } case 8: // iconst_5 { - debugf("%4d: iconst_5 \n", pc); + printf("%4d: iconst_5 \n", pc); return pc + 1; } case 9: // lconst_0 { - debugf("%4d: lconst_0 \n", pc); + printf("%4d: lconst_0 \n", pc); return pc + 1; } case 10: // lconst_1 { - debugf("%4d: lconst_1 \n", pc); + printf("%4d: lconst_1 \n", pc); return pc + 1; } case 11: // fconst_0 { - debugf("%4d: fconst_0 \n", pc); + printf("%4d: fconst_0 \n", pc); return pc + 1; } case 12: // fconst_1 { - debugf("%4d: fconst_1 \n", pc); + printf("%4d: fconst_1 \n", pc); return pc + 1; } case 13: // fconst_2 { - debugf("%4d: fconst_2 \n", pc); + printf("%4d: fconst_2 \n", pc); return pc + 1; } case 14: // dconst_0 { - debugf("%4d: dconst_0 \n", pc); + printf("%4d: dconst_0 \n", pc); return pc + 1; } case 15: // dconst_1 { - debugf("%4d: dconst_1 \n", pc); + printf("%4d: dconst_1 \n", pc); return pc + 1; } case 16: // bipush { int32_t byte = _s1(&code[pc + 1]); - debugf("%4d: bipush %d\n", pc, byte); + printf("%4d: bipush %d\n", pc, byte); return pc + 2; } case 17: // sipush { int32_t byte = _s2(&code[pc + 1]); - debugf("%4d: sipush %d\n", pc, byte); + printf("%4d: sipush %d\n", pc, byte); return pc + 3; } case 18: // ldc { uint32_t index = _u1(&code[pc + 1]); - debugf("%4d: ldc %u\n", pc, index); + printf("%4d: ldc %u\n", pc, index); return pc + 2; } case 19: // ldc_w { uint32_t index = _u2(&code[pc + 1]); - debugf("%4d: ldc_w %u\n", pc, index); + printf("%4d: ldc_w %u\n", pc, index); return pc + 3; } case 20: // ldc2_w { uint32_t index = _u2(&code[pc + 1]); - debugf("%4d: ldc2_w %u\n", pc, index); + printf("%4d: ldc2_w %u\n", pc, index); return pc + 3; } case 21: // iload { uint32_t index = _u1(&code[pc + 1]); - debugf("%4d: iload %u\n", pc, index); + printf("%4d: iload %u\n", pc, index); return pc + 2; } case 22: // lload { uint32_t index = _u1(&code[pc + 1]); - debugf("%4d: lload %u\n", pc, index); + printf("%4d: lload %u\n", pc, index); return pc + 2; } case 23: // fload { uint32_t index = _u1(&code[pc + 1]); - debugf("%4d: fload %u\n", pc, index); + printf("%4d: fload %u\n", pc, index); return pc + 2; } case 24: // dload { uint32_t index = _u1(&code[pc + 1]); - debugf("%4d: dload %u\n", pc, index); + printf("%4d: dload %u\n", pc, index); return pc + 2; } case 25: // aload { uint32_t index = _u1(&code[pc + 1]); - debugf("%4d: aload %u\n", pc, index); + printf("%4d: aload %u\n", pc, index); return pc + 2; } case 26: // iload_0 { - debugf("%4d: iload_0 \n", pc); + printf("%4d: iload_0 \n", pc); return pc + 1; } case 27: // iload_1 { - debugf("%4d: iload_1 \n", pc); + printf("%4d: iload_1 \n", pc); return pc + 1; } case 28: // iload_2 { - debugf("%4d: iload_2 \n", pc); + printf("%4d: iload_2 \n", pc); return pc + 1; } case 29: // iload_3 { - debugf("%4d: iload_3 \n", pc); + printf("%4d: iload_3 \n", pc); return pc + 1; } case 30: // lload_0 { - debugf("%4d: lload_0 \n", pc); + printf("%4d: lload_0 \n", pc); return pc + 1; } case 31: // lload_1 { - debugf("%4d: lload_1 \n", pc); + printf("%4d: lload_1 \n", pc); return pc + 1; } case 32: // lload_2 { - debugf("%4d: lload_2 \n", pc); + printf("%4d: lload_2 \n", pc); return pc + 1; } case 33: // lload_3 { - debugf("%4d: lload_3 \n", pc); + printf("%4d: lload_3 \n", pc); return pc + 1; } case 34: // fload_0 { - debugf("%4d: fload_0 \n", pc); + printf("%4d: fload_0 \n", pc); return pc + 1; } case 35: // fload_1 { - debugf("%4d: fload_1 \n", pc); + printf("%4d: fload_1 \n", pc); return pc + 1; } case 36: // fload_2 { - debugf("%4d: fload_2 \n", pc); + printf("%4d: fload_2 \n", pc); return pc + 1; } case 37: // fload_3 { - debugf("%4d: fload_3 \n", pc); + printf("%4d: fload_3 \n", pc); return pc + 1; } case 38: // dload_0 { - debugf("%4d: dload_0 \n", pc); + printf("%4d: dload_0 \n", pc); return pc + 1; } case 39: // dload_1 { - debugf("%4d: dload_1 \n", pc); + printf("%4d: dload_1 \n", pc); return pc + 1; } case 40: // dload_2 { - debugf("%4d: dload_2 \n", pc); + printf("%4d: dload_2 \n", pc); return pc + 1; } case 41: // dload_3 { - debugf("%4d: dload_3 \n", pc); + printf("%4d: dload_3 \n", pc); return pc + 1; } case 42: // aload_0 { - debugf("%4d: aload_0 \n", pc); + printf("%4d: aload_0 \n", pc); return pc + 1; } case 43: // aload_1 { - debugf("%4d: aload_1 \n", pc); + printf("%4d: aload_1 \n", pc); return pc + 1; } case 44: // aload_2 { - debugf("%4d: aload_2 \n", pc); + printf("%4d: aload_2 \n", pc); return pc + 1; } case 45: // aload_3 { - debugf("%4d: aload_3 \n", pc); + printf("%4d: aload_3 \n", pc); return pc + 1; } case 46: // iaload { - debugf("%4d: iaload \n", pc); + printf("%4d: iaload \n", pc); return pc + 1; } case 47: // laload { - debugf("%4d: laload \n", pc); + printf("%4d: laload \n", pc); return pc + 1; } case 48: // faload { - debugf("%4d: faload \n", pc); + printf("%4d: faload \n", pc); return pc + 1; } case 49: // daload { - debugf("%4d: daload \n", pc); + printf("%4d: daload \n", pc); return pc + 1; } case 50: // aaload { - debugf("%4d: aaload \n", pc); + printf("%4d: aaload \n", pc); return pc + 1; } case 51: // baload { - debugf("%4d: baload \n", pc); + printf("%4d: baload \n", pc); return pc + 1; } case 52: // caload { - debugf("%4d: caload \n", pc); + printf("%4d: caload \n", pc); return pc + 1; } case 53: // saload { - debugf("%4d: saload \n", pc); + printf("%4d: saload \n", pc); return pc + 1; } case 54: // istore { uint32_t index = _u1(&code[pc + 1]); - debugf("%4d: istore %u\n", pc, index); + printf("%4d: istore %u\n", pc, index); return pc + 2; } case 55: // lstore { uint32_t index = _u1(&code[pc + 1]); - debugf("%4d: lstore %u\n", pc, index); + printf("%4d: lstore %u\n", pc, index); return pc + 2; } case 56: // fstore { uint32_t index = _u1(&code[pc + 1]); - debugf("%4d: fstore %u\n", pc, index); + printf("%4d: fstore %u\n", pc, index); return pc + 2; } case 57: // dstore { uint32_t index = _u1(&code[pc + 1]); - debugf("%4d: dstore %u\n", pc, index); + printf("%4d: dstore %u\n", pc, index); return pc + 2; } case 58: // astore { uint32_t index = _u1(&code[pc + 1]); - debugf("%4d: astore %u\n", pc, index); + printf("%4d: astore %u\n", pc, index); return pc + 2; } case 59: // istore_0 { - debugf("%4d: istore_0 \n", pc); + printf("%4d: istore_0 \n", pc); return pc + 1; } case 60: // istore_1 { - debugf("%4d: istore_1 \n", pc); + printf("%4d: istore_1 \n", pc); return pc + 1; } case 61: // istore_2 { - debugf("%4d: istore_2 \n", pc); + printf("%4d: istore_2 \n", pc); return pc + 1; } case 62: // istore_3 { - debugf("%4d: istore_3 \n", pc); + printf("%4d: istore_3 \n", pc); return pc + 1; } case 63: // lstore_0 { - debugf("%4d: lstore_0 \n", pc); + printf("%4d: lstore_0 \n", pc); return pc + 1; } case 64: // lstore_1 { - debugf("%4d: lstore_1 \n", pc); + printf("%4d: lstore_1 \n", pc); return pc + 1; } case 65: // lstore_2 { - debugf("%4d: lstore_2 \n", pc); + printf("%4d: lstore_2 \n", pc); return pc + 1; } case 66: // lstore_3 { - debugf("%4d: lstore_3 \n", pc); + printf("%4d: lstore_3 \n", pc); return pc + 1; } case 67: // fstore_0 { - debugf("%4d: fstore_0 \n", pc); + printf("%4d: fstore_0 \n", pc); return pc + 1; } case 68: // fstore_1 { - debugf("%4d: fstore_1 \n", pc); + printf("%4d: fstore_1 \n", pc); return pc + 1; } case 69: // fstore_2 { - debugf("%4d: fstore_2 \n", pc); + printf("%4d: fstore_2 \n", pc); return pc + 1; } case 70: // fstore_3 { - debugf("%4d: fstore_3 \n", pc); + printf("%4d: fstore_3 \n", pc); return pc + 1; } case 71: // dstore_0 { - debugf("%4d: dstore_0 \n", pc); + printf("%4d: dstore_0 \n", pc); return pc + 1; } case 72: // dstore_1 { - debugf("%4d: dstore_1 \n", pc); + printf("%4d: dstore_1 \n", pc); return pc + 1; } case 73: // dstore_2 { - debugf("%4d: dstore_2 \n", pc); + printf("%4d: dstore_2 \n", pc); return pc + 1; } case 74: // dstore_3 { - debugf("%4d: dstore_3 \n", pc); + printf("%4d: dstore_3 \n", pc); return pc + 1; } case 75: // astore_0 { - debugf("%4d: astore_0 \n", pc); + printf("%4d: astore_0 \n", pc); return pc + 1; } case 76: // astore_1 { - debugf("%4d: astore_1 \n", pc); + printf("%4d: astore_1 \n", pc); return pc + 1; } case 77: // astore_2 { - debugf("%4d: astore_2 \n", pc); + printf("%4d: astore_2 \n", pc); return pc + 1; } case 78: // astore_3 { - debugf("%4d: astore_3 \n", pc); + printf("%4d: astore_3 \n", pc); return pc + 1; } case 79: // iastore { - debugf("%4d: iastore \n", pc); + printf("%4d: iastore \n", pc); return pc + 1; } case 80: // lastore { - debugf("%4d: lastore \n", pc); + printf("%4d: lastore \n", pc); return pc + 1; } case 81: // fastore { - debugf("%4d: fastore \n", pc); + printf("%4d: fastore \n", pc); return pc + 1; } case 82: // dastore { - debugf("%4d: dastore \n", pc); + printf("%4d: dastore \n", pc); return pc + 1; } case 83: // aastore { - debugf("%4d: aastore \n", pc); + printf("%4d: aastore \n", pc); return pc + 1; } case 84: // bastore { - debugf("%4d: bastore \n", pc); + printf("%4d: bastore \n", pc); return pc + 1; } case 85: // castore { - debugf("%4d: castore \n", pc); + printf("%4d: castore \n", pc); return pc + 1; } case 86: // sastore { - debugf("%4d: sastore \n", pc); + printf("%4d: sastore \n", pc); return pc + 1; } case 87: // pop { - debugf("%4d: pop \n", pc); + printf("%4d: pop \n", pc); return pc + 1; } case 88: // pop2 { - debugf("%4d: pop2 \n", pc); + printf("%4d: pop2 \n", pc); return pc + 1; } case 89: // dup { - debugf("%4d: dup \n", pc); + printf("%4d: dup \n", pc); return pc + 1; } case 90: // dup_x1 { - debugf("%4d: dup_x1 \n", pc); + printf("%4d: dup_x1 \n", pc); return pc + 1; } case 91: // dup_x2 { - debugf("%4d: dup_x2 \n", pc); + printf("%4d: dup_x2 \n", pc); return pc + 1; } case 92: // dup2 { - debugf("%4d: dup2 \n", pc); + printf("%4d: dup2 \n", pc); return pc + 1; } case 93: // dup2_x1 { - debugf("%4d: dup2_x1 \n", pc); + printf("%4d: dup2_x1 \n", pc); return pc + 1; } case 94: // dup2_x2 { - debugf("%4d: dup2_x2 \n", pc); + printf("%4d: dup2_x2 \n", pc); return pc + 1; } case 95: // swap { - debugf("%4d: swap \n", pc); + printf("%4d: swap \n", pc); return pc + 1; } case 96: // iadd { - debugf("%4d: iadd \n", pc); + printf("%4d: iadd \n", pc); return pc + 1; } case 97: // ladd { - debugf("%4d: ladd \n", pc); + printf("%4d: ladd \n", pc); return pc + 1; } case 98: // fadd { - debugf("%4d: fadd \n", pc); + printf("%4d: fadd \n", pc); return pc + 1; } case 99: // dadd { - debugf("%4d: dadd \n", pc); + printf("%4d: dadd \n", pc); return pc + 1; } case 100: // isub { - debugf("%4d: isub \n", pc); + printf("%4d: isub \n", pc); return pc + 1; } case 101: // lsub { - debugf("%4d: lsub \n", pc); + printf("%4d: lsub \n", pc); return pc + 1; } case 102: // fsub { - debugf("%4d: fsub \n", pc); + printf("%4d: fsub \n", pc); return pc + 1; } case 103: // dsub { - debugf("%4d: dsub \n", pc); + printf("%4d: dsub \n", pc); return pc + 1; } case 104: // imul { - debugf("%4d: imul \n", pc); + printf("%4d: imul \n", pc); return pc + 1; } case 105: // lmul { - debugf("%4d: lmul \n", pc); + printf("%4d: lmul \n", pc); return pc + 1; } case 106: // fmul { - debugf("%4d: fmul \n", pc); + printf("%4d: fmul \n", pc); return pc + 1; } case 107: // dmul { - debugf("%4d: dmul \n", pc); + printf("%4d: dmul \n", pc); return pc + 1; } case 108: // idiv { - debugf("%4d: idiv \n", pc); + printf("%4d: idiv \n", pc); return pc + 1; } case 109: // ldiv { - debugf("%4d: ldiv \n", pc); + printf("%4d: ldiv \n", pc); return pc + 1; } case 110: // fdiv { - debugf("%4d: fdiv \n", pc); + printf("%4d: fdiv \n", pc); return pc + 1; } case 111: // ddiv { - debugf("%4d: ddiv \n", pc); + printf("%4d: ddiv \n", pc); return pc + 1; } case 112: // irem { - debugf("%4d: irem \n", pc); + printf("%4d: irem \n", pc); return pc + 1; } case 113: // lrem { - debugf("%4d: lrem \n", pc); + printf("%4d: lrem \n", pc); return pc + 1; } case 114: // frem { - debugf("%4d: frem \n", pc); + printf("%4d: frem \n", pc); return pc + 1; } case 115: // drem { - debugf("%4d: drem \n", pc); + printf("%4d: drem \n", pc); return pc + 1; } case 116: // ineg { - debugf("%4d: ineg \n", pc); + printf("%4d: ineg \n", pc); return pc + 1; } case 117: // lneg { - debugf("%4d: lneg \n", pc); + printf("%4d: lneg \n", pc); return pc + 1; } case 118: // fneg { - debugf("%4d: fneg \n", pc); + printf("%4d: fneg \n", pc); return pc + 1; } case 119: // dneg { - debugf("%4d: dneg \n", pc); + printf("%4d: dneg \n", pc); return pc + 1; } case 120: // ishl { - debugf("%4d: ishl \n", pc); + printf("%4d: ishl \n", pc); return pc + 1; } case 121: // lshl { - debugf("%4d: lshl \n", pc); + printf("%4d: lshl \n", pc); return pc + 1; } case 122: // ishr { - debugf("%4d: ishr \n", pc); + printf("%4d: ishr \n", pc); return pc + 1; } case 123: // lshr { - debugf("%4d: lshr \n", pc); + printf("%4d: lshr \n", pc); return pc + 1; } case 124: // iushr { - debugf("%4d: iushr \n", pc); + printf("%4d: iushr \n", pc); return pc + 1; } case 125: // lushr { - debugf("%4d: lushr \n", pc); + printf("%4d: lushr \n", pc); return pc + 1; } case 126: // iand { - debugf("%4d: iand \n", pc); + printf("%4d: iand \n", pc); return pc + 1; } case 127: // land { - debugf("%4d: land \n", pc); + printf("%4d: land \n", pc); return pc + 1; } case 128: // ior { - debugf("%4d: ior \n", pc); + printf("%4d: ior \n", pc); return pc + 1; } case 129: // lor { - debugf("%4d: lor \n", pc); + printf("%4d: lor \n", pc); return pc + 1; } case 130: // ixor { - debugf("%4d: ixor \n", pc); + printf("%4d: ixor \n", pc); return pc + 1; } case 131: // lxor { - debugf("%4d: lxor \n", pc); + printf("%4d: lxor \n", pc); return pc + 1; } case 132: // iinc { uint32_t index = _u1(&code[pc + 1]); int32_t _const = _s1(&code[pc + 2]); - debugf("%4d: iinc %u, %d\n", pc, index, _const); + printf("%4d: iinc %u, %d\n", pc, index, _const); return pc + 3; } case 133: // i2l { - debugf("%4d: i2l \n", pc); + printf("%4d: i2l \n", pc); return pc + 1; } case 134: // i2f { - debugf("%4d: i2f \n", pc); + printf("%4d: i2f \n", pc); return pc + 1; } case 135: // i2d { - debugf("%4d: i2d \n", pc); + printf("%4d: i2d \n", pc); return pc + 1; } case 136: // l2i { - debugf("%4d: l2i \n", pc); + printf("%4d: l2i \n", pc); return pc + 1; } case 137: // l2f { - debugf("%4d: l2f \n", pc); + printf("%4d: l2f \n", pc); return pc + 1; } case 138: // l2d { - debugf("%4d: l2d \n", pc); + printf("%4d: l2d \n", pc); return pc + 1; } case 139: // f2i { - debugf("%4d: f2i \n", pc); + printf("%4d: f2i \n", pc); return pc + 1; } case 140: // f2l { - debugf("%4d: f2l \n", pc); + printf("%4d: f2l \n", pc); return pc + 1; } case 141: // f2d { - debugf("%4d: f2d \n", pc); + printf("%4d: f2d \n", pc); return pc + 1; } case 142: // d2i { - debugf("%4d: d2i \n", pc); + printf("%4d: d2i \n", pc); return pc + 1; } case 143: // d2l { - debugf("%4d: d2l \n", pc); + printf("%4d: d2l \n", pc); return pc + 1; } case 144: // d2f { - debugf("%4d: d2f \n", pc); + printf("%4d: d2f \n", pc); return pc + 1; } case 145: // i2b { - debugf("%4d: i2b \n", pc); + printf("%4d: i2b \n", pc); return pc + 1; } case 146: // i2c { - debugf("%4d: i2c \n", pc); + printf("%4d: i2c \n", pc); return pc + 1; } case 147: // i2s { - debugf("%4d: i2s \n", pc); + printf("%4d: i2s \n", pc); return pc + 1; } case 148: // lcmp { - debugf("%4d: lcmp \n", pc); + printf("%4d: lcmp \n", pc); return pc + 1; } case 149: // fcmpl { - debugf("%4d: fcmpl \n", pc); + printf("%4d: fcmpl \n", pc); return pc + 1; } case 150: // fcmpg { - debugf("%4d: fcmpg \n", pc); + printf("%4d: fcmpg \n", pc); return pc + 1; } case 151: // dcmpl { - debugf("%4d: dcmpl \n", pc); + printf("%4d: dcmpl \n", pc); return pc + 1; } case 152: // dcmpg { - debugf("%4d: dcmpg \n", pc); + printf("%4d: dcmpg \n", pc); return pc + 1; } case 153: // ifeq { int32_t branch = _s2(&code[pc + 1]); - debugf("%4d: ifeq %d\n", pc, branch); + printf("%4d: ifeq %d\n", pc, branch); return pc + 3; } case 154: // ifne { int32_t branch = _s2(&code[pc + 1]); - debugf("%4d: ifne %d\n", pc, branch); + printf("%4d: ifne %d\n", pc, branch); return pc + 3; } case 155: // iflt { int32_t branch = _s2(&code[pc + 1]); - debugf("%4d: iflt %d\n", pc, branch); + printf("%4d: iflt %d\n", pc, branch); return pc + 3; } case 156: // ifge { int32_t branch = _s2(&code[pc + 1]); - debugf("%4d: ifge %d\n", pc, branch); + printf("%4d: ifge %d\n", pc, branch); return pc + 3; } case 157: // ifgt { int32_t branch = _s2(&code[pc + 1]); - debugf("%4d: ifgt %d\n", pc, branch); + printf("%4d: ifgt %d\n", pc, branch); return pc + 3; } case 158: // ifle { int32_t branch = _s2(&code[pc + 1]); - debugf("%4d: ifle %d\n", pc, branch); + printf("%4d: ifle %d\n", pc, branch); return pc + 3; } case 159: // if_icmpeq { int32_t branch = _s2(&code[pc + 1]); - debugf("%4d: if_icmpeq %d\n", pc, branch); + printf("%4d: if_icmpeq %d\n", pc, branch); return pc + 3; } case 160: // if_icmpne { int32_t branch = _s2(&code[pc + 1]); - debugf("%4d: if_icmpne %d\n", pc, branch); + printf("%4d: if_icmpne %d\n", pc, branch); return pc + 3; } case 161: // if_icmplt { int32_t branch = _s2(&code[pc + 1]); - debugf("%4d: if_icmplt %d\n", pc, branch); + printf("%4d: if_icmplt %d\n", pc, branch); return pc + 3; } case 162: // if_icmpge { int32_t branch = _s2(&code[pc + 1]); - debugf("%4d: if_icmpge %d\n", pc, branch); + printf("%4d: if_icmpge %d\n", pc, branch); return pc + 3; } case 163: // if_icmpgt { int32_t branch = _s2(&code[pc + 1]); - debugf("%4d: if_icmpgt %d\n", pc, branch); + printf("%4d: if_icmpgt %d\n", pc, branch); return pc + 3; } case 164: // if_icmple { int32_t branch = _s2(&code[pc + 1]); - debugf("%4d: if_icmple %d\n", pc, branch); + printf("%4d: if_icmple %d\n", pc, branch); return pc + 3; } case 165: // if_acmpeq { int32_t branch = _s2(&code[pc + 1]); - debugf("%4d: if_acmpeq %d\n", pc, branch); + printf("%4d: if_acmpeq %d\n", pc, branch); return pc + 3; } case 166: // if_acmpne { int32_t branch = _s2(&code[pc + 1]); - debugf("%4d: if_acmpne %d\n", pc, branch); + printf("%4d: if_acmpne %d\n", pc, branch); return pc + 3; } case 167: // goto { int32_t branch = _s2(&code[pc + 1]); - debugf("%4d: goto %d\n", pc, branch); + printf("%4d: goto %d\n", pc, branch); return pc + 3; } case 168: // jsr { int32_t branch = _s2(&code[pc + 1]); - debugf("%4d: jsr %d\n", pc, branch); + printf("%4d: jsr %d\n", pc, branch); return pc + 3; } case 169: // ret { uint32_t index = _u1(&code[pc + 1]); - debugf("%4d: ret %u\n", pc, index); + printf("%4d: ret %u\n", pc, index); return pc + 2; } case 170: // tableswitch { TABLESWITCH_ARGS; - debugf("%4d: tableswitch {\n", pc); + printf("%4d: tableswitch {\n", pc); TABLESWITCH_PRINT_ARGS(); - debugf("}\n\n"); + printf("}\n\n"); return TABLESWITCH_NEXT_PC; } case 171: // lookupswitch { LOOKUPSWITCH_ARGS; - debugf("%4d: lookupswitch {\n", pc); + printf("%4d: lookupswitch {\n", pc); LOOKUPSWITCH_PRINT_ARGS(); - debugf("}\n\n"); + printf("}\n\n"); return LOOKUPSWITCH_NEXT_PC; } case 172: // ireturn { - debugf("%4d: ireturn \n", pc); + printf("%4d: ireturn \n", pc); return pc + 1; } case 173: // lreturn { - debugf("%4d: lreturn \n", pc); + printf("%4d: lreturn \n", pc); return pc + 1; } case 174: // freturn { - debugf("%4d: freturn \n", pc); + printf("%4d: freturn \n", pc); return pc + 1; } case 175: // dreturn { - debugf("%4d: dreturn \n", pc); + printf("%4d: dreturn \n", pc); return pc + 1; } case 176: // areturn { - debugf("%4d: areturn \n", pc); + printf("%4d: areturn \n", pc); return pc + 1; } case 177: // return { - debugf("%4d: return \n", pc); + printf("%4d: return \n", pc); return pc + 1; } case 178: // getstatic { uint32_t index = _u2(&code[pc + 1]); - debugf("%4d: getstatic %u\n", pc, index); + printf("%4d: getstatic %u\n", pc, index); return pc + 3; } case 179: // putstatic { uint32_t index = _u2(&code[pc + 1]); - debugf("%4d: putstatic %u\n", pc, index); + printf("%4d: putstatic %u\n", pc, index); return pc + 3; } case 180: // getfield { uint32_t index = _u2(&code[pc + 1]); - debugf("%4d: getfield %u\n", pc, index); + printf("%4d: getfield %u\n", pc, index); return pc + 3; } case 181: // putfield { uint32_t index = _u2(&code[pc + 1]); - debugf("%4d: putfield %u\n", pc, index); + printf("%4d: putfield %u\n", pc, index); return pc + 3; } case 182: // invokevirtual { uint32_t index = _u2(&code[pc + 1]); - debugf("%4d: invokevirtual %u\n", pc, index); + printf("%4d: invokevirtual %u\n", pc, index); return pc + 3; } case 183: // invokespecial { uint32_t index = _u2(&code[pc + 1]); - debugf("%4d: invokespecial %u\n", pc, index); + printf("%4d: invokespecial %u\n", pc, index); return pc + 3; } case 184: // invokestatic { uint32_t index = _u2(&code[pc + 1]); - debugf("%4d: invokestatic %u\n", pc, index); + printf("%4d: invokestatic %u\n", pc, index); return pc + 3; } case 185: // invokeinterface { uint32_t index = _u2(&code[pc + 1]); uint32_t count = _u1(&code[pc + 3]); - debugf("%4d: invokeinterface %u, %u\n", pc, index, count); + printf("%4d: invokeinterface %u, %u\n", pc, index, count); return pc + 5; } case 186: // invokedynamic { uint32_t index = _u2(&code[pc + 1]); - debugf("%4d: invokedynamic %u\n", pc, index); + printf("%4d: invokedynamic %u\n", pc, index); return pc + 5; } case 187: // new { uint32_t index = _u2(&code[pc + 1]); - debugf("%4d: new %u\n", pc, index); + printf("%4d: new %u\n", pc, index); return pc + 3; } case 188: // newarray { uint32_t atype = _u1(&code[pc + 1]); - debugf("%4d: newarray %u\n", pc, atype); + printf("%4d: newarray %u\n", pc, atype); return pc + 2; } case 189: // anewarray { uint32_t index = _u2(&code[pc + 1]); - debugf("%4d: anewarray %u\n", pc, index); + printf("%4d: anewarray %u\n", pc, index); return pc + 3; } case 190: // arraylength { - debugf("%4d: arraylength \n", pc); + printf("%4d: arraylength \n", pc); return pc + 1; } case 191: // athrow { - debugf("%4d: athrow \n", pc); + printf("%4d: athrow \n", pc); return pc + 1; } case 192: // checkcast { uint32_t index = _u2(&code[pc + 1]); - debugf("%4d: checkcast %u\n", pc, index); + printf("%4d: checkcast %u\n", pc, index); return pc + 3; } case 193: // instanceof { uint32_t index = _u2(&code[pc + 1]); - debugf("%4d: instanceof %u\n", pc, index); + printf("%4d: instanceof %u\n", pc, index); return pc + 3; } case 194: // monitorenter { - debugf("%4d: monitorenter \n", pc); + printf("%4d: monitorenter \n", pc); return pc + 1; } case 195: // monitorexit { - debugf("%4d: monitorexit \n", pc); + printf("%4d: monitorexit \n", pc); return pc + 1; } case 196: // wide { WIDE_ARGS; - debugf("%4d: wide {", pc); + printf("%4d: wide {", pc); WIDE_PRINT_ARGS(); - debugf("}\n"); + printf("}\n"); return WIDE_NEXT_PC; } case 197: // multianewarray { uint32_t index = _u2(&code[pc + 1]); uint32_t dimensions = _u1(&code[pc + 3]); - debugf("%4d: multianewarray %u, %u\n", pc, index, dimensions); + printf("%4d: multianewarray %u, %u\n", pc, index, dimensions); return pc + 4; } case 198: // ifnull { int32_t branch = _s2(&code[pc + 1]); - debugf("%4d: ifnull %d\n", pc, branch); + printf("%4d: ifnull %d\n", pc, branch); return pc + 3; } case 199: // ifnonnull { int32_t branch = _s2(&code[pc + 1]); - debugf("%4d: ifnonnull %d\n", pc, branch); + printf("%4d: ifnonnull %d\n", pc, branch); return pc + 3; } case 200: // goto_w { int32_t branch = _s2(&code[pc + 1]); - debugf("%4d: goto_w %d\n", pc, branch); + printf("%4d: goto_w %d\n", pc, branch); return pc + 3; } case 201: // jsr_w { int32_t branch = _s4(&code[pc + 1]); - debugf("%4d: jsr_w %d\n", pc, branch); + printf("%4d: jsr_w %d\n", pc, branch); return pc + 5; } case 202: // breakpoint { - debugf("%4d: breakpoint \n", pc); + printf("%4d: breakpoint \n", pc); return pc + 1; } case 254: // impdep1 { - debugf("%4d: impdep1 \n", pc); + printf("%4d: impdep1 \n", pc); return pc + 1; } case 255: // impdep2 { - debugf("%4d: impdep2 \n", pc); + printf("%4d: impdep2 \n", pc); return pc + 1; } default: diff --git a/c/execute.c b/c/execute.c index b117458..3e33461 100644 --- a/c/execute.c +++ b/c/execute.c @@ -6,13 +6,13 @@ #include "printf.h" #include "field_size.h" #include "debug.h" -#include "parse_type.h" #include "native_types.h" +#include "parse_type.h" void op_aaload(struct vm * vm) { int32_t index = operand_stack_pop_u32(vm->current_frame); - struct object_arrayref * arrayref = (struct object_arrayref *)operand_stack_pop_u32(vm->current_frame); + struct arrayref * arrayref = operand_stack_pop_ref(vm->current_frame); assert(arrayref->length > 0 && index >= 0 && index < arrayref->length); uint32_t value = arrayref->u32[index]; operand_stack_push_u32(vm->current_frame, value); @@ -22,7 +22,7 @@ void op_aastore(struct vm * vm) { uint32_t value = operand_stack_pop_u32(vm->current_frame); int32_t index = operand_stack_pop_u32(vm->current_frame); - struct object_arrayref * arrayref = (struct object_arrayref *)operand_stack_pop_u32(vm->current_frame); + struct arrayref * arrayref = operand_stack_pop_ref(vm->current_frame); assert(arrayref->length > 0 && index >= 0 && index < arrayref->length); arrayref->u32[index] = value; } @@ -64,20 +64,27 @@ void op_aload_3(struct vm * vm) void op_anewarray(struct vm * vm, uint32_t index) { + struct class_entry * class_entry = + class_resolver_lookup_class_from_class_index(vm->class_hash_table.length, + vm->class_hash_table.entry, + vm->current_frame->class_entry, + index); + int32_t count = operand_stack_pop_u32(vm->current_frame); int32_t element_size = (sizeof (void *)); - int32_t size = element_size * count + (sizeof (struct object_arrayref)); - struct object_arrayref * arrayref = memory_allocate(size); + int32_t size = element_size * count + (sizeof (struct arrayref)); + struct arrayref * arrayref = memory_allocate(size); assert(arrayref != nullptr); arrayref->length = count; + arrayref->class_entry = class_entry; /* All components of the new array are initialized to null, the default value for reference types */ for (int i = 0; i < count; i++) { - arrayref->a[i] = nullptr; + arrayref->oref[i] = nullptr; } - operand_stack_push_u32(vm->current_frame, (uint32_t)arrayref); + operand_stack_push_ref(vm->current_frame, arrayref); } void op_areturn(struct vm * vm) @@ -88,8 +95,8 @@ void op_areturn(struct vm * vm) void op_arraylength(struct vm * vm) { - int32_t * arrayref = (int32_t *)operand_stack_pop_u32(vm->current_frame); - int32_t length = arrayref[0]; + struct arrayref * arrayref = operand_stack_pop_ref(vm->current_frame); + int32_t length = arrayref->length; operand_stack_push_u32(vm->current_frame, length); } @@ -125,14 +132,14 @@ void op_astore_3(struct vm * vm) void op_athrow(struct vm * vm) { - int32_t * objectref = (int32_t *)operand_stack_pop_u32(vm->current_frame); + struct objectref * objectref = operand_stack_pop_ref(vm->current_frame); vm_exception(vm, objectref); } void op_baload(struct vm * vm) { int32_t index = operand_stack_pop_u32(vm->current_frame); - struct primitive_arrayref * arrayref = (struct primitive_arrayref *)operand_stack_pop_u32(vm->current_frame); + struct arrayref * arrayref = operand_stack_pop_ref(vm->current_frame); assert(arrayref->length > 0 && index >= 0 && index < arrayref->length); int8_t value = arrayref->u8[index]; operand_stack_push_u32(vm->current_frame, value); @@ -142,7 +149,7 @@ void op_bastore(struct vm * vm) { uint8_t value = operand_stack_pop_u32(vm->current_frame); int32_t index = operand_stack_pop_u32(vm->current_frame); - struct primitive_arrayref * arrayref = (struct primitive_arrayref *)operand_stack_pop_u32(vm->current_frame); + struct arrayref * arrayref = operand_stack_pop_ref(vm->current_frame); assert(arrayref->length > 0 && index >= 0 && index < arrayref->length); arrayref->u8[index] = value; } @@ -160,7 +167,7 @@ void op_breakpoint(struct vm * vm) void op_caload(struct vm * vm) { int32_t index = operand_stack_pop_u32(vm->current_frame); - struct primitive_arrayref * arrayref = (struct primitive_arrayref *)operand_stack_pop_u32(vm->current_frame); + struct arrayref * arrayref = operand_stack_pop_ref(vm->current_frame); assert(arrayref->length > 0 && index >= 0 && index < arrayref->length); uint16_t value = arrayref->u16[index]; operand_stack_push_u32(vm->current_frame, value); @@ -170,66 +177,25 @@ void op_castore(struct vm * vm) { uint16_t value = operand_stack_pop_u32(vm->current_frame); int32_t index = operand_stack_pop_u32(vm->current_frame); - struct primitive_arrayref * arrayref = (struct primitive_arrayref *)operand_stack_pop_u32(vm->current_frame); + struct arrayref * arrayref = operand_stack_pop_ref(vm->current_frame); assert(arrayref->length > 0 && index >= 0 && index < arrayref->length); arrayref->u16[index] = value; } void op_checkcast(struct vm * vm, uint32_t index) { - int32_t * objectref = (int32_t *)operand_stack_peek_u32(vm->current_frame, 1); - if (objectref == nullptr) { - return; - } - - struct class_entry * index_class_entry = - class_resolver_lookup_class_from_class_index(vm->class_hash_table.length, - vm->class_hash_table.entry, - vm->current_frame->class_entry, - index); - - struct constant * class_constant = &vm->current_frame->class_entry->class_file->constant_pool[index - 1]; - assert(class_constant->tag == CONSTANT_Class); - struct constant * class_name_constant = &vm->current_frame->class_entry->class_file->constant_pool[class_constant->class.name_index - 1]; - assert(class_name_constant->tag == CONSTANT_Utf8); - - int depth = parse_type_array_depth(class_name_constant->utf8.bytes, class_name_constant->utf8.length); - while (depth-- > 0) { - if (objectref == nullptr || objectref[0] == 0) - assert(!"checkcast on null or zero-length array not implemented"); - objectref = (int32_t *)objectref[1]; - } - if (objectref == nullptr) { - assert(!"checkcast on array with null elements not implemented"); - } - - struct class_entry * class_entry = (struct class_entry *)objectref[0]; - debug_print__class_file__class_name(index_class_entry->class_file); - debug_print__class_file__class_name(class_entry->class_file); - - while (true) { - assert(class_entry != nullptr); - if (class_entry == index_class_entry) { - return; + struct objectref * objectref = operand_stack_peek_ref(vm->current_frame, 1); + if (objectref != nullptr) { + bool isinstance = + class_resolver_instanceof(vm->class_hash_table.length, + vm->class_hash_table.entry, + vm->current_frame->class_entry, + index, + objectref); + if (!isinstance) { + assert(!"ClassCastException"); } - if (class_entry->class_file->super_class == 0) { - break; - } - - struct constant * class_constant = &class_entry->class_file->constant_pool[class_entry->class_file->super_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]; - assert(class_name_constant->tag == CONSTANT_Utf8); - debug_print__constant__utf8_string(class_name_constant); - debugf("\n"); - - // superclass lookup - class_entry = class_resolver_lookup_class_from_class_index(vm->class_hash_table.length, - vm->class_hash_table.entry, - class_entry, - class_entry->class_file->super_class); } - assert(!"ClassCastException"); } void op_d2f(struct vm * vm) @@ -264,7 +230,7 @@ void op_dadd(struct vm * vm) void op_daload(struct vm * vm) { int32_t index = operand_stack_pop_u32(vm->current_frame); - struct primitive_arrayref * arrayref = (struct primitive_arrayref *)operand_stack_pop_u32(vm->current_frame); + struct arrayref * arrayref = operand_stack_pop_ref(vm->current_frame); assert(arrayref->length > 0 && index >= 0 && index < arrayref->length); uint64_t value = arrayref->u64[index]; operand_stack_push_u64(vm->current_frame, value); @@ -274,7 +240,7 @@ void op_dastore(struct vm * vm) { int64_t value = operand_stack_pop_u64(vm->current_frame); int32_t index = operand_stack_pop_u32(vm->current_frame); - struct primitive_arrayref * arrayref = (struct primitive_arrayref *)operand_stack_pop_u32(vm->current_frame); + struct arrayref * arrayref = operand_stack_pop_ref(vm->current_frame); assert(arrayref->length > 0 && index >= 0 && index < arrayref->length); arrayref->u64[index] = value; } @@ -546,7 +512,7 @@ void op_fadd(struct vm * vm) void op_faload(struct vm * vm) { int32_t index = operand_stack_pop_u32(vm->current_frame); - struct primitive_arrayref * arrayref = (struct primitive_arrayref *)operand_stack_pop_u32(vm->current_frame); + struct arrayref * arrayref = operand_stack_pop_ref(vm->current_frame); assert(arrayref->length > 0 && index >= 0 && index < arrayref->length); uint32_t value = arrayref->u32[index]; operand_stack_push_u32(vm->current_frame, value); @@ -556,7 +522,7 @@ void op_fastore(struct vm * vm) { uint32_t value = operand_stack_pop_u32(vm->current_frame); int32_t index = operand_stack_pop_u32(vm->current_frame); - struct primitive_arrayref * arrayref = (struct primitive_arrayref *)operand_stack_pop_u32(vm->current_frame); + struct arrayref * arrayref = operand_stack_pop_ref(vm->current_frame); assert(arrayref->length > 0 && index >= 0 && index < arrayref->length); arrayref->u32[index] = value; } @@ -732,9 +698,8 @@ void op_getfield(struct vm * vm, uint32_t index) debugf("getfield instance_index %d\n", field_entry->instance_index); - int32_t * objectref = (int32_t *)operand_stack_pop_u32(vm->current_frame); + struct objectref * objectref = operand_stack_pop_ref(vm->current_frame); assert(objectref != nullptr); - int32_t * objectfields = &objectref[1]; switch (field_descriptor_constant->utf8.bytes[0]) { case 'B': [[fallthrough]]; @@ -746,17 +711,17 @@ void op_getfield(struct vm * vm, uint32_t index) case 'Z': [[fallthrough]]; case '[': { - uint32_t value = objectfields[field_entry->instance_index]; - operand_stack_push_u32(vm->current_frame, value); + void * value = objectref->oref[field_entry->instance_index]; + operand_stack_push_ref(vm->current_frame, value); } break; case 'D': [[fallthrough]]; case 'J': { - 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); + void * low = objectref->oref[field_entry->instance_index]; + void * high = objectref->oref[field_entry->instance_index + 1]; + operand_stack_push_ref(vm->current_frame, low); + operand_stack_push_ref(vm->current_frame, high); } break; default: @@ -872,7 +837,7 @@ void op_iadd(struct vm * vm) void op_iaload(struct vm * vm) { int32_t index = operand_stack_pop_u32(vm->current_frame); - struct primitive_arrayref * arrayref = (struct primitive_arrayref *)operand_stack_pop_u32(vm->current_frame); + struct arrayref * arrayref = operand_stack_pop_ref(vm->current_frame); assert(arrayref->length > 0 && index >= 0 && index < arrayref->length); int32_t value = arrayref->u32[index]; operand_stack_push_u32(vm->current_frame, value); @@ -890,7 +855,7 @@ void op_iastore(struct vm * vm) { uint32_t value = operand_stack_pop_u32(vm->current_frame); int32_t index = operand_stack_pop_u32(vm->current_frame); - struct primitive_arrayref * arrayref = (struct primitive_arrayref *)operand_stack_pop_u32(vm->current_frame); + struct arrayref * arrayref = operand_stack_pop_ref(vm->current_frame); assert(arrayref->length > 0 && index >= 0 && index < arrayref->length); arrayref->u32[index] = value; } @@ -1060,7 +1025,7 @@ void op_ifne(struct vm * vm, int32_t branch) void op_ifnonnull(struct vm * vm, int32_t branch) { - void * value = (void *)operand_stack_pop_u32(vm->current_frame); + void * value = operand_stack_pop_ref(vm->current_frame); if (value != nullptr) { vm->current_frame->next_pc = vm->current_frame->pc + branch; } @@ -1068,7 +1033,7 @@ void op_ifnonnull(struct vm * vm, int32_t branch) void op_ifnull(struct vm * vm, int32_t branch) { - void * value = (void *)operand_stack_pop_u32(vm->current_frame); + void * value = operand_stack_pop_ref(vm->current_frame); if (value == nullptr) { vm->current_frame->next_pc = vm->current_frame->pc + branch; } @@ -1138,61 +1103,18 @@ void op_ineg(struct vm * vm) void op_instanceof(struct vm * vm, uint32_t index) { - struct class_entry * index_class_entry = - class_resolver_lookup_class_from_class_index(vm->class_hash_table.length, - vm->class_hash_table.entry, - vm->current_frame->class_entry, - index); - assert(index_class_entry != nullptr); - - int32_t * objectref = (int32_t *)operand_stack_pop_u32(vm->current_frame); + struct objectref * objectref = operand_stack_pop_ref(vm->current_frame); if (objectref == nullptr) { - operand_stack_push_u32(vm->current_frame, (uint32_t)false); - return; + operand_stack_push_u32(vm->current_frame, false); + } else { + bool isinstance = + class_resolver_instanceof(vm->class_hash_table.length, + vm->class_hash_table.entry, + vm->current_frame->class_entry, + index, + objectref); + operand_stack_push_u32(vm->current_frame, isinstance); } - - struct constant * class_constant = &vm->current_frame->class_entry->class_file->constant_pool[index - 1]; - assert(class_constant->tag == CONSTANT_Class); - struct constant * class_name_constant = &vm->current_frame->class_entry->class_file->constant_pool[class_constant->class.name_index - 1]; - assert(class_name_constant->tag == CONSTANT_Utf8); - - int depth = parse_type_array_depth(class_name_constant->utf8.bytes, class_name_constant->utf8.length); - printf("depth: %d\n", depth); - while (depth-- > 0) { - if (objectref == nullptr || objectref[0] == 0) - assert(!"instanceof on null or zero-length array not implemented"); - objectref = (int32_t *)objectref[1]; - } - if (objectref == nullptr) { - assert(!"instanceof on array with null elements not implemented"); - } - - bool value = false; - struct class_entry * class_entry = (struct class_entry *)objectref[0]; - while (true) { - assert(class_entry != nullptr); - if (class_entry == index_class_entry) { - value = true; - break; - } - if (class_entry->class_file->super_class == 0) { - break; - } - - struct constant * class_constant = &class_entry->class_file->constant_pool[class_entry->class_file->super_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]; - assert(class_name_constant->tag == CONSTANT_Utf8); - debug_print__constant__utf8_string(class_name_constant); - debugf("\n"); - - // superclass lookup - class_entry = class_resolver_lookup_class_from_class_index(vm->class_hash_table.length, - vm->class_hash_table.entry, - class_entry, - class_entry->class_file->super_class); - } - operand_stack_push_u32(vm->current_frame, (uint32_t)value); } void op_invokedynamic(struct vm * vm, uint32_t index) @@ -1202,9 +1124,9 @@ void op_invokedynamic(struct vm * vm, uint32_t index) void op_invokeinterface(struct vm * vm, uint32_t index, uint32_t count) { - int32_t * objectref = (int32_t *)operand_stack_peek_u32(vm->current_frame, count); + struct objectref * objectref = operand_stack_peek_ref(vm->current_frame, count); assert(objectref != nullptr); - struct class_entry * class_entry = (struct class_entry *)objectref[0]; + struct class_entry * class_entry = objectref->class_entry; struct method_entry method_entry = class_resolver_lookup_method_from_interfacemethodref_index(vm->class_hash_table.length, @@ -1242,8 +1164,6 @@ void op_invokestatic(struct vm * vm, uint32_t index) vm_static_method_call(vm, method_entry->class_entry, method_entry); } -#include "debug.h" - void op_invokevirtual(struct vm * vm, uint32_t index) { struct class_entry * origin_class_entry = vm->current_frame->class_entry; @@ -1261,9 +1181,9 @@ void op_invokevirtual(struct vm * vm, uint32_t index) int nargs = descriptor_nargs(method_descriptor_constant, &return_type); (void)return_type; - int32_t * objectref = (int32_t *)operand_stack_peek_u32(vm->current_frame, nargs + 1); + struct objectref * objectref = operand_stack_peek_ref(vm->current_frame, nargs + 1); assert(objectref != nullptr); - struct class_entry * class_entry = (struct class_entry *)objectref[0]; + struct class_entry * class_entry = objectref->class_entry; debugf("class_entry: %p\n", class_entry); struct method_entry method_entry = @@ -1449,7 +1369,7 @@ void op_ladd(struct vm * vm) void op_laload(struct vm * vm) { int32_t index = operand_stack_pop_u32(vm->current_frame); - struct primitive_arrayref * arrayref = (struct primitive_arrayref *)operand_stack_pop_u32(vm->current_frame); + struct arrayref * arrayref = operand_stack_pop_ref(vm->current_frame); assert(arrayref->length > 0 && index >= 0 && index < arrayref->length); int64_t value = arrayref->u64[index]; operand_stack_push_u64(vm->current_frame, value); @@ -1467,7 +1387,7 @@ void op_lastore(struct vm * vm) { uint64_t value = operand_stack_pop_u64(vm->current_frame); int32_t index = operand_stack_pop_u32(vm->current_frame); - struct primitive_arrayref * arrayref = (struct primitive_arrayref *)operand_stack_pop_u32(vm->current_frame); + struct arrayref * arrayref = operand_stack_pop_ref(vm->current_frame); assert(arrayref->length > 0 && index >= 0 && index < arrayref->length); arrayref->u64[index] = value; } @@ -1506,11 +1426,11 @@ void op_ldc(struct vm * vm, uint32_t index) 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); + struct objectref * 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_ref(vm->current_frame, objectref); } else { assert(false); } @@ -1533,11 +1453,11 @@ void op_ldc_w(struct vm * vm, uint32_t index) 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); + struct objectref * 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_ref(vm->current_frame, objectref); } else { assert(false); } @@ -1735,22 +1655,40 @@ void op_monitorexit(struct vm * vm) assert(!"op_monitorexit"); } -static int32_t * _multiarray(int32_t * dims, int num_dimensions, int level, uint8_t * type) +static struct arrayref * _multiarray(struct vm * vm, int32_t * dims, int num_dimensions, int level, uint8_t * type, uint8_t * type_end) { int32_t count = dims[level]; int32_t element_size = field_size_array(*type); - int32_t size = element_size * count + 4; - int32_t * arrayref = memory_allocate(size); + int32_t size = element_size * count + (sizeof (struct arrayref)); + struct arrayref * arrayref = memory_allocate(size); assert(arrayref != nullptr); - arrayref[0] = count; + arrayref->length = count; + { // generate/recall unique pointer for type string + uint8_t * array_type = type - 1; + assert(*array_type == '['); + int type_length = type_end - array_type; + assert(type_length > 0); + void * type = class_resolver_memoize_string_type(vm->string_hash_table.length, + vm->string_hash_table.entry, + array_type, + type_length); + debugf("memoized string type: %d %p: ", count, type); + print_string((const char *)array_type, type_length); + debugc('\n'); + assert(type != nullptr); + arrayref->class_entry = type; + } - int32_t u32_count = (size - 4 + 3) / 4; + int32_t array_element_size = count * element_size; // bytes + int32_t u32_count = (array_element_size + 3) / 4; // u32 units + debugf("u32_count: %d\n", u32_count); for (int i = 0; i < u32_count; i++) { if (level == num_dimensions - 1) { - arrayref[i + 1] = 0; + assert(*type != '['); + arrayref->u32[1] = 0; } else { assert(*type == '['); - arrayref[1 + i] = (int32_t)_multiarray(dims, num_dimensions, level + 1, type + 1); + arrayref->aref[i] = _multiarray(vm, dims, num_dimensions, level + 1, type + 1, type_end); } } return arrayref; @@ -1763,9 +1701,14 @@ void op_multianewarray(struct vm * vm, uint32_t index, uint32_t dimensions) struct constant * type_constant = &vm->current_frame->class_entry->class_file->constant_pool[class_constant->class.name_index - 1]; assert(type_constant->tag == CONSTANT_Utf8); + debugs("type_constant: "); + debug_print__constant__utf8_string(type_constant); + debugc('\n'); + // The run-time constant pool entry at the index must be a symbolic reference // to a class, array, or interface type uint8_t * type = type_constant->utf8.bytes; + uint8_t * type_end = type + type_constant->utf8.length; assert(*type == '['); assert(dimensions > 0); @@ -1773,8 +1716,8 @@ void op_multianewarray(struct vm * vm, uint32_t index, uint32_t dimensions) for (int i = 0; i < dimensions; i++) { dims[dimensions - i - 1] = operand_stack_pop_u32(vm->current_frame); } - int32_t * arrayref = _multiarray(dims, dimensions, 0, type + 1); - operand_stack_push_u32(vm->current_frame, (uint32_t)arrayref); + struct arrayref * arrayref = _multiarray(vm, dims, dimensions, 0, type + 1, type_end); + operand_stack_push_ref(vm->current_frame, arrayref); } void op_new(struct vm * vm, uint32_t index) @@ -1800,15 +1743,14 @@ void op_new(struct vm * vm, uint32_t index) reference to the instance, is pushed onto the operand stack. */ int fields_count = class_entry->instance_fields_count; - int32_t * objectref = memory_allocate(fields_count * 4 + 4); + struct objectref * objectref = memory_allocate(fields_count * 4 + 4); assert(objectref != nullptr); - objectref[0] = (int32_t)class_entry; - int32_t * objectfields = &objectref[1]; + objectref->class_entry = class_entry; for (int i = 0; i < fields_count; i++) { - objectfields[i] = 0; + objectref->oref[i] = nullptr; } - operand_stack_push_u32(vm->current_frame, (uint32_t)objectref); + operand_stack_push_ref(vm->current_frame, objectref); } @@ -1816,10 +1758,11 @@ void op_newarray(struct vm * vm, uint32_t atype) { int32_t count = operand_stack_pop_u32(vm->current_frame); int32_t element_size = array_element_size(atype); - int32_t size = element_size * count + (sizeof (struct primitive_arrayref)); - struct primitive_arrayref * arrayref = memory_allocate(size); + int32_t size = element_size * count + (sizeof (struct arrayref)); + struct arrayref * arrayref = memory_allocate(size); assert(arrayref != nullptr); arrayref->length = count; + arrayref->class_entry = nullptr; /* Each of the elements of the new array is initialized to the default initial value (§2.3, §2.4) for the element type of the array type. */ @@ -1832,7 +1775,7 @@ void op_newarray(struct vm * vm, uint32_t atype) arrayref->u32[i] = 0; } - operand_stack_push_u32(vm->current_frame, (uint32_t)arrayref); + operand_stack_push_ref(vm->current_frame, arrayref); } void op_nop(struct vm * vm) @@ -1882,10 +1825,9 @@ void op_putfield(struct vm * vm, uint32_t index) case '[': { uint32_t value = operand_stack_pop_u32(vm->current_frame); - int32_t * objectref = (int32_t *)operand_stack_pop_u32(vm->current_frame); + struct objectref * objectref = operand_stack_pop_ref(vm->current_frame); assert(objectref != nullptr); - int32_t * objectfields = &objectref[1]; - objectfields[field_entry->instance_index] = value; + objectref->u32[field_entry->instance_index] = value; } break; case 'D': [[fallthrough]]; @@ -1893,11 +1835,10 @@ 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); + struct objectref * objectref = operand_stack_pop_ref(vm->current_frame); assert(objectref != nullptr); - int32_t * objectfields = &objectref[1]; - objectfields[field_entry->instance_index + 1] = high; - objectfields[field_entry->instance_index] = low; + objectref->u32[field_entry->instance_index + 1] = high; + objectref->u32[field_entry->instance_index] = low; } break; default: @@ -1971,7 +1912,7 @@ void op_return(struct vm * vm) void op_saload(struct vm * vm) { int32_t index = operand_stack_pop_u32(vm->current_frame); - struct primitive_arrayref * arrayref = (struct primitive_arrayref *)operand_stack_pop_u32(vm->current_frame); + struct arrayref * arrayref = operand_stack_pop_ref(vm->current_frame); assert(arrayref->length > 0 && index >= 0 && index < arrayref->length); int16_t value = arrayref->u16[index]; operand_stack_push_u32(vm->current_frame, value); @@ -1981,7 +1922,7 @@ void op_sastore(struct vm * vm) { uint16_t value = operand_stack_pop_u32(vm->current_frame); int32_t index = operand_stack_pop_u32(vm->current_frame); - struct primitive_arrayref * arrayref = (struct primitive_arrayref *)operand_stack_pop_u32(vm->current_frame); + struct arrayref * arrayref = operand_stack_pop_ref(vm->current_frame); assert(arrayref->length > 0 && index >= 0 && index < arrayref->length); arrayref->u16[index] = value; } diff --git a/c/frame.c b/c/frame.c index f3f612c..3910035 100644 --- a/c/frame.c +++ b/c/frame.c @@ -13,6 +13,7 @@ #include "debug.h" #include "find_attribute.h" #include "backtrace.h" +#include "native_types.h" int descriptor_nargs(struct constant * descriptor_constant, uint8_t * return_type) { @@ -490,15 +491,15 @@ void vm_method_return(struct vm * vm) } } -void vm_exception(struct vm * vm, int32_t * objectref) +void vm_exception(struct vm * vm, struct objectref * objectref) { // If objectref is null, athrow throws a NullPointerException instead of objectref. assert(objectref != nullptr); - struct class_entry * exception_class_entry = (struct class_entry *)objectref[0]; - if (objectref[1] == 0) { - struct backtrace * backtrace = backtrace_allocate(vm); - objectref[1] = (int32_t)backtrace; + struct class_entry * exception_class_entry = objectref->class_entry; + if (objectref->oref[0] == nullptr) { + // FIXME: make backtrace a real objectref + objectref->oref[0] = (struct objectref *)backtrace_allocate(vm); } while (vm->frame_stack.ix > 0) { @@ -533,23 +534,21 @@ void vm_exception(struct vm * vm, int32_t * objectref) print__class_file__class_name(exception_class_entry->class_file); printc('\n'); { - int32_t * string_objectref = (int32_t *)objectref[2]; + struct objectref * string_objectref = objectref->oref[1]; // message if (string_objectref != nullptr) { prints(" message: "); - struct class_entry * string_class_entry = (struct class_entry *)string_objectref[0]; + struct class_entry * string_class_entry = string_objectref->class_entry; prints("(class: "); print__class_file__class_name(string_class_entry->class_file); printc(')'); prints("\n "); - int32_t * arrayref = (int32_t *)string_objectref[1]; - int32_t length = arrayref[0]; - uint8_t * bytes = (uint8_t *)&arrayref[1]; - print__string(bytes, length); + struct arrayref * arrayref = string_objectref->aref[0]; + print__string(arrayref->u8, arrayref->length); printc('\n'); } } - assert(objectref[1] != 0); - backtrace_print((struct backtrace *)objectref[1]); + assert(objectref->oref[0] != 0); + backtrace_print((struct backtrace *)objectref->oref[0]); } static void print_vm_stack(struct vm * vm) @@ -574,7 +573,9 @@ void vm_execute(struct vm * vm) while (true) { assert(vm->current_frame->pc < vm->current_frame->code_attribute->code_length); print_vm_stack(vm); +#ifdef DEBUG_PRINT decode_print_instruction(vm->current_frame->code_attribute->code, vm->current_frame->pc); +#endif decode_execute_instruction(vm, vm->current_frame->code_attribute->code, vm->current_frame->pc); if (vm->frame_stack.ix == 0) { debugf("terminate\n"); @@ -608,8 +609,11 @@ struct vm * vm_start(int class_hash_table_length, assert(method_entry.method_info != nullptr); static struct vm vm; - vm.class_hash_table.entry = class_hash_table; vm.class_hash_table.length = class_hash_table_length; + vm.class_hash_table.entry = class_hash_table; + + vm.string_hash_table.length = 128; + vm.string_hash_table.entry = class_resolver_init_string_hash_table(vm.string_hash_table.length); vm.frame_stack.ix = 0; vm.frame_stack.capacity = 1024; diff --git a/c/frame.h b/c/frame.h index 5c02b24..f633357 100644 --- a/c/frame.h +++ b/c/frame.h @@ -3,6 +3,7 @@ #include "assert.h" #include "class_file.h" #include "class_resolver.h" +#include "native_types.h" struct frame { struct class_entry * class_entry; @@ -34,6 +35,10 @@ struct vm { int length; struct hash_table_entry * entry; } class_hash_table; + struct { + int length; + struct hash_table_entry * entry; + } string_hash_table; }; static inline struct frame * stack_push_frame(struct stack * stack, int num_frames) { @@ -96,6 +101,28 @@ static inline void operand_stack_dup_u32(struct frame * frame) frame->operand_stack_ix++; } +static inline void operand_stack_push_ref(struct frame * frame, void * value) +{ + frame->operand_stack[frame->operand_stack_ix] = (uint32_t)value; + frame->operand_stack_ix++; +} + +static inline void * operand_stack_pop_ref(struct frame * frame) +{ + frame->operand_stack_ix--; + assert(frame->operand_stack_ix >= 0); + uint32_t value = frame->operand_stack[frame->operand_stack_ix]; + frame->operand_stack[frame->operand_stack_ix] = -1; + return (void *)value; +} + +static inline void * operand_stack_peek_ref(struct frame * frame, int index) +{ + assert((frame->operand_stack_ix - index) >= 0); + uint32_t value = frame->operand_stack[frame->operand_stack_ix - index]; + return (void *)value; +} + static inline void operand_stack_push_f32(struct frame * frame, float f) { uint32_t value = *((uint32_t *)&f); @@ -165,4 +192,4 @@ struct vm * vm_start(int class_hash_table_length, const uint8_t * main_class_name, int main_class_name_length); int descriptor_nargs(struct constant * descriptor_constant, uint8_t * return_type); -void vm_exception(struct vm * vm, int32_t * objectref); +void vm_exception(struct vm * vm, struct objectref * objectref); diff --git a/c/hash_table.c b/c/hash_table.c index c211d00..95cd601 100644 --- a/c/hash_table.c +++ b/c/hash_table.c @@ -46,11 +46,11 @@ void print_key(const uint8_t * key, int key_length) debugc('\n'); } -void hash_table_add(int hash_table_length, - struct hash_table_entry * entry, - const uint8_t * key, - int key_length, - void * value) +struct hash_table_entry * hash_table_add(int hash_table_length, + struct hash_table_entry * entry, + const uint8_t * key, + int key_length, + void * value) { assert(hash_table_length != 0); assert((hash_table_length & (hash_table_length - 1)) == 0); @@ -74,6 +74,8 @@ void hash_table_add(int hash_table_length, e->key = key_copy; e->key_length = key_length; e->value = value; + + return e; } struct hash_table_entry * hash_table_find(int hash_table_length, @@ -114,13 +116,13 @@ static inline bool key_equal2(const uint8_t * a1, int a1_length, 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) +struct hash_table_entry * 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) { assert(hash_table_length != 0); assert((hash_table_length & (hash_table_length - 1)) == 0); @@ -148,6 +150,8 @@ void hash_table_add2(int hash_table_length, e->key = key_copy; e->key_length = key1_length + key2_length; e->value = value; + + return e; } struct hash_table_entry * hash_table_find2(int hash_table_length, diff --git a/c/hash_table.h b/c/hash_table.h index 62cab18..358bf1d 100644 --- a/c/hash_table.h +++ b/c/hash_table.h @@ -14,24 +14,24 @@ int32_t hash_table_next_power_of_two(int32_t n); void hash_table_init(int hash_table_length, struct hash_table_entry * entry); -void hash_table_add(int hash_table_length, - struct hash_table_entry * entry, - const uint8_t * key, - int key_length, - void * value); +struct hash_table_entry * hash_table_add(int hash_table_length, + struct hash_table_entry * entry, + const uint8_t * key, + int key_length, + void * value); 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_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, diff --git a/c/native.c b/c/native.c index 46a003e..00bd903 100644 --- a/c/native.c +++ b/c/native.c @@ -6,24 +6,17 @@ #include "class_resolver.h" #include "frame.h" -void native_java_io_printstream_write(uint32_t * arrayref) -{ - int32_t length = arrayref[0]; - char * buf = (char *)&arrayref[1]; - print_string(buf, length); -} - void native_java_io_printstream_write_1(uint32_t * args) { - uint32_t * arrayref = (uint32_t *)args[0]; - native_java_io_printstream_write(arrayref); + struct arrayref * arrayref = (struct arrayref *)args[0]; + print_string((const char *)arrayref->u8, arrayref->length); } void native_java_io_printstream_write_2(uint32_t * args) { //uint32_t this = args[0]; - uint32_t * arrayref = (uint32_t *)args[1]; - native_java_io_printstream_write(arrayref); + struct arrayref * arrayref = (struct arrayref *)args[1]; + print_string((const char *)arrayref->u8, arrayref->length); } void native_java_misc_memory_putU4_2(uint32_t * args) @@ -73,16 +66,16 @@ extern uint32_t store_queue[0x4000000] __asm("store_queue"); void native_java_misc_memory_putSQ1_2(uint32_t * args) { #if defined(__dreamcast__) - uint32_t * objectref = (uint32_t *)args[0]; + struct objectref * objectref = (struct objectref *)args[0]; uint32_t address = (uint32_t)args[1]; - store_queue[0] = objectref[1]; - store_queue[1] = objectref[2]; - store_queue[2] = objectref[3]; - store_queue[3] = objectref[4]; - store_queue[4] = objectref[5]; - store_queue[5] = objectref[6]; - store_queue[6] = objectref[7]; - store_queue[7] = objectref[8]; + 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; @@ -122,16 +115,13 @@ uint32_t native_java_lang_math_abs_1(uint32_t * args) uint32_t java_misc_resource_getresource_1(uint32_t * args) { - uint32_t * objectref = (uint32_t *)args[0]; - int32_t * arrayref = (int32_t *)objectref[1]; - int32_t name_length = (int32_t)arrayref[0]; - uint8_t * name = (uint8_t *)&arrayref[1]; + struct objectref * objectref = (struct objectref *)args[0]; + struct arrayref * arrayref = objectref->aref[0]; #if defined(__dreamcast__) - uint32_t resource = find_resource(name, name_length); + uint32_t resource = find_resource(arrayref->u8, arrayref->length); return resource; #else - (void)name; - (void)name_length; + (void)arrayref; return 0; #endif } @@ -152,9 +142,8 @@ extern struct vm vm; void native_jvm_internal_loader_load(uint32_t * args) { - uint32_t * arrayref = (uint32_t *)args[0]; - //int32_t buffers_length = (int32_t)arrayref[0]; - const uint8_t ** buffers = (const uint8_t **)&arrayref[1]; + 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]); diff --git a/c/native_types.h b/c/native_types.h index 0167dc9..6a60e26 100644 --- a/c/native_types.h +++ b/c/native_types.h @@ -1,19 +1,32 @@ +#pragma once + #include +#include #include "class_resolver.h" +struct object_arrayref; + struct objectref { + int32_t _res; struct class_entry * class_entry; union { - void * field[0]; + struct objectref * oref[0]; + struct arrayref * aref[0]; + uint32_t u32[0]; }; }; -static_assert((sizeof (struct objectref)) == 4); +static_assert((sizeof (struct objectref)) == 8); -struct primitive_arrayref { - int32_t length; +struct arrayref { + int32_t length; // length position must match primitive_arrayref + struct class_entry * class_entry; union { + // object array: + struct objectref * oref[0]; + struct arrayref * aref[0]; + // primitive array: uint8_t u8[0]; uint16_t u16[0]; uint32_t u32[0]; @@ -21,18 +34,7 @@ struct primitive_arrayref { }; }; -static_assert((sizeof (struct primitive_arrayref)) == 4); - -struct object_arrayref { - struct class_entry * class_entry; - int32_t length; - union { - struct objectref * a[0]; - uint32_t u32[0]; - }; -}; - -static_assert((sizeof (struct object_arrayref)) == 8); +static_assert((sizeof (struct arrayref)) == 8); enum ARRAY_TYPE { T_BOOLEAN = 4, // 1 byte diff --git a/c/parse_type.c b/c/parse_type.c index d92500d..65579d4 100644 --- a/c/parse_type.c +++ b/c/parse_type.c @@ -1,5 +1,6 @@ #include "assert.h" #include "parse_type.h" +#include "printf.h" struct parse_type_ret parse_type(uint8_t * bytes, uint32_t length) { diff --git a/gen_decoder.py b/gen_decoder.py index 8e4860a..50dcfc1 100644 --- a/gen_decoder.py +++ b/gen_decoder.py @@ -115,16 +115,16 @@ def generate_print_fixed_width_instruction(instruction): if argument_values: argument_values = ", " + argument_values mnemonic = instruction.mnemonic.ljust(13) - yield f'debugf("%4d: {mnemonic} {argument_format}\\n", pc{argument_values});' + yield f'printf("%4d: {mnemonic} {argument_format}\\n", pc{argument_values});' yield f"return pc + {1 + instruction.arguments_size};" def generate_print_variable_width_instruction(instruction): n = '' if instruction.mnemonic == "wide" else '\\n' mnemonic = instruction.mnemonic.ljust(13) yield f"{instruction.mnemonic.upper()}_ARGS;" - yield f'debugf("%4d: {mnemonic} {{{n}", pc);' + yield f'printf("%4d: {mnemonic} {{{n}", pc);' yield f"{instruction.mnemonic.upper()}_PRINT_ARGS();" - yield f'debugf("}}{n}\\n");' + yield f'printf("}}{n}\\n");' yield f"return {instruction.mnemonic.upper()}_NEXT_PC;" def generate_print_decoder(): diff --git a/test/TestMultiArray.java b/test/TestMultiArray.java new file mode 100644 index 0000000..11f6949 --- /dev/null +++ b/test/TestMultiArray.java @@ -0,0 +1,20 @@ +package test; + +class TestMultiArray { + static boolean testInstanceof() { + Object[][] a = new Object[2][3]; + return a instanceof Object[][]; + } + + static boolean testInstanceof2() { + TestMultiArray[][] a = new TestMultiArray[2][3]; + return a instanceof Object[][]; + } + + public static void main(String[] args) { + System.out.print("testInstanceof: "); + System.out.println(testInstanceof()); + System.out.print("testInstanceof2: "); + System.out.println(testInstanceof2()); + } +} diff --git a/test/TestObjectArray.java b/test/TestObjectArray.java new file mode 100644 index 0000000..3ba5c3e --- /dev/null +++ b/test/TestObjectArray.java @@ -0,0 +1,42 @@ +package test; + +class TestObjectArray { + static boolean testInstanceEqual() { + TestObjectArray t1 = new TestObjectArray(); + TestObjectArray t2 = new TestObjectArray(); + TestObjectArray t3 = new TestObjectArray(); + + TestObjectArray[] a = {t1, t2, t3}; + + return + a[0] == t1 && + a[1] == t2 && + a[2] == t3 && + a[0] != t2 && + a[1] != t3 && + a[2] != t1; + } + + static boolean testEmptyInstanceof() { + TestObjectArray[] a = new TestObjectArray[1]; + + return a instanceof TestObjectArray[]; + } + + static boolean testNullInstanceof() { + TestObjectArray[] a = null; + + return !(a instanceof TestObjectArray[]); + } + + public static void main() { + System.out.print("testInstanceEqual: "); + System.out.println(testInstanceEqual()); + + System.out.print("testEmptyInstanceof: "); + System.out.println(testEmptyInstanceof()); + + System.out.print("testNullInstanceof: "); + System.out.println(testNullInstanceof()); + } +} diff --git a/p/TestPrimitiveArray.java b/test/TestPrimitiveArray.java similarity index 95% rename from p/TestPrimitiveArray.java rename to test/TestPrimitiveArray.java index c2e82c6..6db65b7 100644 --- a/p/TestPrimitiveArray.java +++ b/test/TestPrimitiveArray.java @@ -1,4 +1,4 @@ -package p; +package test; class TestPrimitiveArray { static boolean testBool() { @@ -24,12 +24,13 @@ class TestPrimitiveArray { } static boolean testChar() { - char[] a = {'a', 'b', 'c', 'd'}; + char[] a = {'a', 'b', 'c', 'd', 200}; return a[0] == 'a' && a[1] == 'b' && a[2] == 'c' && - a[3] == 'd'; + a[3] == 'd' && + a[4] > 0; } static boolean testShort() {