implement wide

This commit is contained in:
Zack Buhman 2024-12-27 04:08:03 -06:00
parent f10429927b
commit 4f312ad42c
8 changed files with 167 additions and 44 deletions

View File

@ -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,

View File

@ -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"

View File

@ -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

View File

@ -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");
}

View File

@ -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;
}
}

View File

@ -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;

View File

@ -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)"

31
p/WideInstruction.java Normal file
View File

@ -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();
}
}