From 4f312ad42c20f1e518f45ffb49bb062fd418356c Mon Sep 17 00:00:00 2001 From: Zack Buhman Date: Fri, 27 Dec 2024 04:08:03 -0600 Subject: [PATCH] implement wide --- c/class_resolver.c | 4 ++ c/decode.c | 95 ++++++++++++++++++++++++++++++++++++++++-- c/decode.inc.c | 9 ++-- c/execute.c | 49 ++++++++++------------ c/frame.c | 7 +++- c/hash_table.c | 3 -- gen_decoder.py | 13 ++++-- p/WideInstruction.java | 31 ++++++++++++++ 8 files changed, 167 insertions(+), 44 deletions(-) create mode 100644 p/WideInstruction.java diff --git a/c/class_resolver.c b/c/class_resolver.c index 84a24a2..1cec31a 100644 --- a/c/class_resolver.c +++ b/c/class_resolver.c @@ -170,6 +170,10 @@ struct hash_table_entry * class_resolver_load_from_buffers(const uint8_t ** buff struct constant * class_name_constant = &class_file->constant_pool[class_constant->class.name_index - 1]; assert(class_name_constant->tag == CONSTANT_Utf8); + debugf("hash table entry for class: "); + print_utf8_string(class_name_constant); + debugf("\n"); + hash_table_add(class_hash_table_length, class_hash_table, class_name_constant->utf8.bytes, diff --git a/c/decode.c b/c/decode.c index f90203b..2d0db7f 100644 --- a/c/decode.c +++ b/c/decode.c @@ -99,11 +99,100 @@ static inline int32_t aligned_s4(const void * buf) #define LOOKUPSWITCH_NEXT_PC \ (args + (2 * 4) + (npairs * 2 * 4)) -#define WIDE_ARGS assert(false); +#define WIDE_ARGS \ + uint32_t opcode = code[pc + 1]; \ + uint32_t index = _u2(&code[pc + 2]); \ + uint32_t wide_next_pc = pc + 4; \ + int32_t _const; -#define WIDE_PRINT_ARGS() +#define WIDE_IMPL() \ + switch (opcode) { \ + case 21: /* iload */ \ + op_iload(vm, index); \ + break; \ + case 22: /* lload */ \ + op_lload(vm, index); \ + break; \ + case 23: /* fload */ \ + op_fload(vm, index); \ + break; \ + case 24: /* dload */ \ + op_dload(vm, index); \ + break; \ + case 25: /* aload */ \ + op_aload(vm, index); \ + break; \ + case 54: /* istore */ \ + op_istore(vm, index); \ + break; \ + case 56: /* fstore */ \ + op_fstore(vm, index); \ + break; \ + case 58: /* astore */ \ + op_astore(vm, index); \ + break; \ + case 55: /* lstore */ \ + op_lstore(vm, index); \ + break; \ + case 57: /* dstore */ \ + op_dstore(vm, index); \ + break; \ + case 169: /* ret */ \ + op_ret(vm, index); \ + break; \ + case 132: /* iinc */ \ + { \ + _const = _s2(&code[pc + 4]); \ + op_iinc(vm, index, _const); \ + wide_next_pc = pc + 6; \ + } \ + break; \ + } \ + vm->current_frame->next_pc = wide_next_pc; -#define WIDE_NEXT_PC 0 +#define WIDE_PRINT_ARGS() \ + switch (opcode) { \ + case 21: /* iload */ \ + debugf(" iload %5d ", index); \ + break; \ + case 22: /* lload */ \ + debugf(" lload %5d ", index); \ + break; \ + case 23: /* fload */ \ + debugf(" fload %5d ", index); \ + break; \ + case 24: /* dload */ \ + debugf(" dload %5d ", index); \ + break; \ + case 25: /* aload */ \ + debugf(" aload %5d ", index); \ + break; \ + case 54: /* istore */ \ + debugf(" istore %5d ", index); \ + break; \ + case 56: /* fstore */ \ + debugf(" fstore %5d ", index); \ + break; \ + case 58: /* astore */ \ + debugf(" astore %5d ", index); \ + break; \ + case 55: /* lstore */ \ + debugf(" lstore %5d ", index); \ + break; \ + case 57: /* dstore */ \ + debugf(" dstore %5d ", index); \ + break; \ + case 169: /* ret */ \ + debugf(" ret %5d ", index); \ + break; \ + case 132: /* iinc */ \ + _const = _s2(&code[pc + 4]); \ + debugf(" iinc %5d %5d ", index, _const); \ + wide_next_pc = pc + 6; \ + break; \ + } + +#define WIDE_NEXT_PC wide_next_pc #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-variable" diff --git a/c/decode.inc.c b/c/decode.inc.c index 1841c8a..457df2b 100644 --- a/c/decode.inc.c +++ b/c/decode.inc.c @@ -890,7 +890,7 @@ uint32_t decode_print_instruction(const uint8_t * code, uint32_t pc) TABLESWITCH_ARGS; debugf("%4d: tableswitch {\n", pc); TABLESWITCH_PRINT_ARGS(); - debugf("}\n"); + debugf("}\n\n"); return TABLESWITCH_NEXT_PC; } case 171: // lookupswitch @@ -898,7 +898,7 @@ uint32_t decode_print_instruction(const uint8_t * code, uint32_t pc) LOOKUPSWITCH_ARGS; debugf("%4d: lookupswitch {\n", pc); LOOKUPSWITCH_PRINT_ARGS(); - debugf("}\n"); + debugf("}\n\n"); return LOOKUPSWITCH_NEXT_PC; } case 172: // ireturn @@ -1039,7 +1039,7 @@ uint32_t decode_print_instruction(const uint8_t * code, uint32_t pc) case 196: // wide { WIDE_ARGS; - debugf("%4d: wide {\n", pc); + debugf("%4d: wide {", pc); WIDE_PRINT_ARGS(); debugf("}\n"); return WIDE_NEXT_PC; @@ -2330,8 +2330,7 @@ void decode_execute_instruction(struct vm * vm, const uint8_t * code, uint32_t p case 196: // wide { WIDE_ARGS; - vm->current_frame->next_pc = WIDE_NEXT_PC; - op_wide(vm); + WIDE_IMPL(); break; } case 197: // multianewarray diff --git a/c/execute.c b/c/execute.c index 38c5c78..a932df9 100644 --- a/c/execute.c +++ b/c/execute.c @@ -763,12 +763,12 @@ void op_getstatic(struct vm * vm, uint32_t index) void op_goto(struct vm * vm, int32_t branch) { - vm->current_frame->pc = vm->current_frame->pc + branch; + vm->current_frame->next_pc = vm->current_frame->pc + branch; } void op_goto_w(struct vm * vm, int32_t branch) { - vm->current_frame->pc = vm->current_frame->pc + branch; + vm->current_frame->next_pc = vm->current_frame->pc + branch; } void op_i2b(struct vm * vm) @@ -897,7 +897,7 @@ void op_if_acmpeq(struct vm * vm, int32_t branch) int32_t value2 = operand_stack_pop_u32(vm->current_frame); int32_t value1 = operand_stack_pop_u32(vm->current_frame); if (value1 == value2) { - vm->current_frame->pc = vm->current_frame->pc + branch; + vm->current_frame->next_pc = vm->current_frame->pc + branch; } } @@ -906,7 +906,7 @@ void op_if_acmpne(struct vm * vm, int32_t branch) int32_t value2 = operand_stack_pop_u32(vm->current_frame); int32_t value1 = operand_stack_pop_u32(vm->current_frame); if (value1 != value2) { - vm->current_frame->pc = vm->current_frame->pc + branch; + vm->current_frame->next_pc = vm->current_frame->pc + branch; } } @@ -915,7 +915,7 @@ void op_if_icmpeq(struct vm * vm, int32_t branch) int32_t value2 = operand_stack_pop_u32(vm->current_frame); int32_t value1 = operand_stack_pop_u32(vm->current_frame); if (value1 == value2) { - vm->current_frame->pc = vm->current_frame->pc + branch; + vm->current_frame->next_pc = vm->current_frame->pc + branch; } } @@ -924,7 +924,7 @@ void op_if_icmpge(struct vm * vm, int32_t branch) int32_t value2 = operand_stack_pop_u32(vm->current_frame); int32_t value1 = operand_stack_pop_u32(vm->current_frame); if (value1 >= value2) { - vm->current_frame->pc = vm->current_frame->pc + branch; + vm->current_frame->next_pc = vm->current_frame->pc + branch; } } @@ -933,7 +933,7 @@ void op_if_icmpgt(struct vm * vm, int32_t branch) int32_t value2 = operand_stack_pop_u32(vm->current_frame); int32_t value1 = operand_stack_pop_u32(vm->current_frame); if (value1 > value2) { - vm->current_frame->pc = vm->current_frame->pc + branch; + vm->current_frame->next_pc = vm->current_frame->pc + branch; } } @@ -942,7 +942,7 @@ void op_if_icmple(struct vm * vm, int32_t branch) int32_t value2 = operand_stack_pop_u32(vm->current_frame); int32_t value1 = operand_stack_pop_u32(vm->current_frame); if (value1 <= value2) { - vm->current_frame->pc = vm->current_frame->pc + branch; + vm->current_frame->next_pc = vm->current_frame->pc + branch; } } @@ -951,7 +951,7 @@ void op_if_icmplt(struct vm * vm, int32_t branch) int32_t value2 = operand_stack_pop_u32(vm->current_frame); int32_t value1 = operand_stack_pop_u32(vm->current_frame); if (value1 < value2) { - vm->current_frame->pc = vm->current_frame->pc + branch; + vm->current_frame->next_pc = vm->current_frame->pc + branch; } } @@ -960,7 +960,7 @@ void op_if_icmpne(struct vm * vm, int32_t branch) int32_t value2 = operand_stack_pop_u32(vm->current_frame); int32_t value1 = operand_stack_pop_u32(vm->current_frame); if (value1 != value2) { - vm->current_frame->pc = vm->current_frame->pc + branch; + vm->current_frame->next_pc = vm->current_frame->pc + branch; } } @@ -968,7 +968,7 @@ void op_ifeq(struct vm * vm, int32_t branch) { int32_t value = operand_stack_pop_u32(vm->current_frame); if (value == 0) { - vm->current_frame->pc = vm->current_frame->pc + branch; + vm->current_frame->next_pc = vm->current_frame->pc + branch; } } @@ -976,7 +976,7 @@ void op_ifge(struct vm * vm, int32_t branch) { int32_t value = operand_stack_pop_u32(vm->current_frame); if (value >= 0) { - vm->current_frame->pc = vm->current_frame->pc + branch; + vm->current_frame->next_pc = vm->current_frame->pc + branch; } } @@ -984,7 +984,7 @@ void op_ifgt(struct vm * vm, int32_t branch) { int32_t value = operand_stack_pop_u32(vm->current_frame); if (value > 0) { - vm->current_frame->pc = vm->current_frame->pc + branch; + vm->current_frame->next_pc = vm->current_frame->pc + branch; } } @@ -992,7 +992,7 @@ void op_ifle(struct vm * vm, int32_t branch) { int32_t value = operand_stack_pop_u32(vm->current_frame); if (value <= 0) { - vm->current_frame->pc = vm->current_frame->pc + branch; + vm->current_frame->next_pc = vm->current_frame->pc + branch; } } @@ -1000,7 +1000,7 @@ void op_iflt(struct vm * vm, int32_t branch) { int32_t value = operand_stack_pop_u32(vm->current_frame); if (value < 0) { - vm->current_frame->pc = vm->current_frame->pc + branch; + vm->current_frame->next_pc = vm->current_frame->pc + branch; } } @@ -1008,7 +1008,7 @@ void op_ifne(struct vm * vm, int32_t branch) { int32_t value = operand_stack_pop_u32(vm->current_frame); if (value != 0) { - vm->current_frame->pc = vm->current_frame->pc + branch; + vm->current_frame->next_pc = vm->current_frame->pc + branch; } } @@ -1016,7 +1016,7 @@ void op_ifnonnull(struct vm * vm, int32_t branch) { void * value = (void *)operand_stack_pop_u32(vm->current_frame); if (value != nullptr) { - vm->current_frame->pc = vm->current_frame->pc + branch; + vm->current_frame->next_pc = vm->current_frame->pc + branch; } } @@ -1024,7 +1024,7 @@ void op_ifnull(struct vm * vm, int32_t branch) { void * value = (void *)operand_stack_pop_u32(vm->current_frame); if (value == nullptr) { - vm->current_frame->pc = vm->current_frame->pc + branch; + vm->current_frame->next_pc = vm->current_frame->pc + branch; } } @@ -1474,11 +1474,11 @@ void op_lookupswitch(struct vm * vm, int32_t defaultbyte, int32_t npairs, const int32_t match = BE_BSWAP32(table[i * 2]); if (key == match) { int32_t offset = BE_BSWAP32(table[i * 2 + 1]); - vm->current_frame->pc = vm->current_frame->pc + offset; + vm->current_frame->next_pc = vm->current_frame->pc + offset; return; } } - vm->current_frame->pc = vm->current_frame->pc + defaultbyte; + vm->current_frame->next_pc = vm->current_frame->pc + defaultbyte; } void op_lor(struct vm * vm) @@ -1868,14 +1868,9 @@ void op_tableswitch(struct vm * vm, int32_t defaultbyte, int32_t lowbyte, int32_ { int32_t index = operand_stack_pop_u32(vm->current_frame); if (index < lowbyte || index > highbyte) { - vm->current_frame->pc = vm->current_frame->pc + defaultbyte; + vm->current_frame->next_pc = vm->current_frame->pc + defaultbyte; } else { int32_t offset = BE_BSWAP32(table[index - lowbyte]); - vm->current_frame->pc = vm->current_frame->pc + offset; + vm->current_frame->next_pc = vm->current_frame->pc + offset; } } - -void op_wide(struct vm * vm) -{ - assert(!"op_wide"); -} diff --git a/c/frame.c b/c/frame.c index f84dc7e..b5fe374 100644 --- a/c/frame.c +++ b/c/frame.c @@ -451,17 +451,20 @@ void vm_execute(struct vm * vm) assert(vm->current_frame->pc < vm->current_frame->code->code_length); print_vm_stack(vm); decode_print_instruction(vm->current_frame->code->code, vm->current_frame->pc); - uint32_t old_pc = vm->current_frame->pc; - struct method_info * old_method = vm->current_frame->method; + //uint32_t old_pc = vm->current_frame->pc; + //struct method_info * old_method = vm->current_frame->method; decode_execute_instruction(vm, vm->current_frame->code->code, vm->current_frame->pc); if (vm->frame_stack.ix == 1) { debugf("terminate\n"); break; } + /* if (vm->current_frame->method == old_method && vm->current_frame->pc == old_pc) { // if the instruction did not branch, increment pc vm->current_frame->pc = vm->current_frame->next_pc; } + */ + vm->current_frame->pc = vm->current_frame->next_pc; } } diff --git a/c/hash_table.c b/c/hash_table.c index 3b1742e..05a0791 100644 --- a/c/hash_table.c +++ b/c/hash_table.c @@ -69,9 +69,6 @@ void hash_table_add(int hash_table_length, uint8_t * key_copy = malloc_class_arena(key_length); for (int i = 0; i < key_length; i++) key_copy[i] = key[i]; - debugf("key copy: %p ", key_copy); - print_key(key_copy, key_length); - e->key = key_copy; e->key_length = key_length; e->value = value; diff --git a/gen_decoder.py b/gen_decoder.py index a635ce7..8e4860a 100644 --- a/gen_decoder.py +++ b/gen_decoder.py @@ -119,11 +119,12 @@ def generate_print_fixed_width_instruction(instruction): 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'debugf("%4d: {mnemonic} {{{n}", pc);' yield f"{instruction.mnemonic.upper()}_PRINT_ARGS();" - yield 'debugf("}\\n");' + yield f'debugf("}}{n}\\n");' yield f"return {instruction.mnemonic.upper()}_NEXT_PC;" def generate_print_decoder(): @@ -167,14 +168,18 @@ def generate_execute_fixed_width_instruction(instruction): def generate_execute_variable_width_instruction(instruction): yield f"{instruction.mnemonic.upper()}_ARGS;" - yield f"vm->current_frame->next_pc = {instruction.mnemonic.upper()}_NEXT_PC;" argument_values = ", ".join( argument for argument in instruction.arguments ) + if instruction.mnemonic != "wide": + yield f"vm->current_frame->next_pc = {instruction.mnemonic.upper()}_NEXT_PC;" if argument_values: argument_values = ", " + argument_values - yield f"op_{instruction.mnemonic}(vm{argument_values});" + if instruction.mnemonic == "wide": + yield "WIDE_IMPL();" + else: + yield f"op_{instruction.mnemonic}(vm{argument_values});" def generate_execute_decoder(): yield "void decode_execute_instruction(struct vm * vm, const uint8_t * code, uint32_t pc)" diff --git a/p/WideInstruction.java b/p/WideInstruction.java new file mode 100644 index 0000000..12af047 --- /dev/null +++ b/p/WideInstruction.java @@ -0,0 +1,31 @@ +package p; + +class WideInstruction { + public static int largeVarIndex() { + int i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11, i12, i13, i14, i15, i16, i17, i18, + i19, i20, i21, i22, i23, i24, i25, i26, i27, i28, i29, i30, i31, i32, i33, i34, i35, + i36, i37, i38, i39, i40, i41, i42, i43, i44, i45, i46, i47, i48, i49, i50, i51, i52, + i53, i54, i55, i56, i57, i58, i59, i60, i61, i62, i63, i64, i65, i66, i67, i68, i69, + i70, i71, i72, i73, i74, i75, i76, i77, i78, i79, i80, i81, i82, i83, i84, i85, i86, + i87, i88, i89, i90, i91, i92, i93, i94, i95, i96, i97, i98, i99, j0, j1, j2, j3, j4, + j5, j6, j7, j8, j9, j10, j11, j12, j13, j14, j15, j16, j17, j18, j19, j20, j21, j22, + j23, j24, j25, j26, j27, j28, j29, j30, j31, j32, j33, j34, j35, j36, j37, j38, j39, + j40, j41, j42, j43, j44, j45, j46, j47, j48, j49, j50, j51, j52, j53, j54, j55, j56, + j57, j58, j59, j60, j61, j62, j63, j64, j65, j66, j67, j68, j69, j70, j71, j72, j73, + j74, j75, j76, j77, j78, j79, j80, j81, j82, j83, j84, j85, j86, j87, j88, j89, j90, + j91, j92, j93, j94, j95, j96, j97, j98, j99, k0, k1, k2, k3, k4, k5, k6, k7, k8, k9, + k10, k11, k12, k13, k14, k15, k16, k17, k18, k19, k20, k21, k22, k23, k24, k25, k26, + k27, k28, k29, k30, k31, k32, k33, k34, k35, k36, k37, k38, k39, k40, k41, k42, k43, + k44, k45, k46, k47, k48, k49, k50, k51, k52, k53, k54, k55, k56, k57 = 42; + + for (int i = 0; i < 256; i += 1024) { + k57 += 360; + } + + return k57; + } + + public static void main() { + largeVarIndex(); + } +}