Motivation: Exception manager will need to translate native instruction pointers to bytecode offsets to select appropriate exception handler from exception_table.
Signed-off-by: Tomek Grabiec <[email protected]> --- Makefile | 3 +- arch/x86/include/arch/instruction.h | 1 + arch/x86/insn-selector_32.brg | 294 ++++++++++++++++++----------------- arch/x86/instruction.c | 3 + include/jit/bc-offset-mapping.h | 19 +++ include/jit/expression.h | 2 + include/jit/statement.h | 1 + jit/args.c | 9 +- jit/bc-offset-mapping.c | 112 +++++++++++++ jit/bytecode-to-ir.c | 29 ++++ jit/compiler.c | 3 + jit/expression.c | 2 + jit/invoke-bc.c | 11 +- jit/spill-reload.c | 4 + jit/statement.c | 2 + test/arch-x86/Makefile | 1 + test/include/arch/instruction.h | 3 + test/jit/Makefile | 1 + 18 files changed, 353 insertions(+), 147 deletions(-) create mode 100644 include/jit/bc-offset-mapping.h create mode 100644 jit/bc-offset-mapping.c diff --git a/Makefile b/Makefile index 9dd15c9..6b2a12d 100644 --- a/Makefile +++ b/Makefile @@ -79,7 +79,8 @@ JIT_OBJS = \ jit/typeconv-bc.o \ jit/vtable.o \ jit/fixup-site.o \ - jit/exception.o + jit/exception.o \ + jit/bc-offset-mapping.o VM_OBJS = \ vm/bitset.o \ diff --git a/arch/x86/include/arch/instruction.h b/arch/x86/include/arch/instruction.h index ec5f4cb..cbeaad9 100644 --- a/arch/x86/include/arch/instruction.h +++ b/arch/x86/include/arch/instruction.h @@ -120,6 +120,7 @@ struct insn { /* Position of this instruction in LIR. */ unsigned long lir_pos; bool escaped; + unsigned long bytecode_offset; }; static inline unsigned long lir_position(struct use_position *reg) diff --git a/arch/x86/insn-selector_32.brg b/arch/x86/insn-selector_32.brg index 9dcc26c..61430a0 100644 --- a/arch/x86/insn-selector_32.brg +++ b/arch/x86/insn-selector_32.brg @@ -13,6 +13,7 @@ #include <jit/emulate.h> #include <jit/expression.h> #include <jit/statement.h> +#include <jit/bc-offset-mapping.h> #include <arch/instruction.h> #include <arch/stack-frame.h> @@ -40,6 +41,9 @@ #define MONOBURG_LOG 1 #define HAVE_ARRAY_ELEM_INIT 1 +static void select_insn(struct basic_block *bb, struct tree_node *tree, + struct insn *instruction); + static unsigned char type_to_scale(enum vm_type vm_type) { unsigned char scale; @@ -63,7 +67,8 @@ static unsigned char type_to_scale(enum vm_type vm_type) return scale; } -static void method_args_cleanup(struct basic_block *bb, unsigned long args_count) +static void method_args_cleanup(struct basic_block *bb, struct tree_node *tree, + unsigned long args_count) { struct var_info *stack_ptr; unsigned long args_size; @@ -71,7 +76,7 @@ static void method_args_cleanup(struct basic_block *bb, unsigned long args_count stack_ptr = bb->b_parent->stack_ptr; args_size = args_count * sizeof(uint32_t); - bb_add_insn(bb, imm_reg_insn(INSN_ADD_IMM_REG, args_size, stack_ptr)); + select_insn(bb, tree, imm_reg_insn(INSN_ADD_IMM_REG, args_size, stack_ptr)); } struct _MBState; @@ -128,12 +133,12 @@ reg: EXPR_VALUE 0 result = get_var(s->b_parent); state->reg1 = result; - bb_add_insn(s, imm_reg_insn(INSN_MOV_IMM_REG, expr->value & ~0UL, result)); + select_insn(s, tree, imm_reg_insn(INSN_MOV_IMM_REG, expr->value & ~0UL, result)); if (expr->vm_type == J_LONG) { result = get_var(s->b_parent); state->reg2 = result; - bb_add_insn(s, imm_reg_insn(INSN_MOV_IMM_REG, expr->value >> 32, state->reg2)); + select_insn(s, tree, imm_reg_insn(INSN_MOV_IMM_REG, expr->value >> 32, state->reg2)); } } @@ -150,7 +155,7 @@ reg: EXPR_LOCAL 1 result = get_var(s->b_parent); state->reg1 = result; - bb_add_insn(s, memlocal_reg_insn(INSN_MOV_MEMLOCAL_REG, slot, result)); + select_insn(s, tree, memlocal_reg_insn(INSN_MOV_MEMLOCAL_REG, slot, result)); if (expr->vm_type == J_LONG) { slot = get_local_slot(cu->stack_frame, expr->local_index + 1); @@ -158,7 +163,7 @@ reg: EXPR_LOCAL 1 result = get_var(s->b_parent); state->reg2 = result; - bb_add_insn(s, memlocal_reg_insn(INSN_MOV_MEMLOCAL_REG, slot, result)); + select_insn(s, tree, memlocal_reg_insn(INSN_MOV_MEMLOCAL_REG, slot, result)); } } @@ -237,7 +242,7 @@ reg: OP_MUL(reg, EXPR_LOCAL) 1 state->reg1 = eax; - bb_add_insn(s, reg_reg_insn(INSN_MOV_REG_REG, state->left->reg1, eax)); + select_insn(s, tree, reg_reg_insn(INSN_MOV_REG_REG, state->left->reg1, eax)); __binop_reg_local(state, s, tree, INSN_MUL_MEMBASE_EAX, eax, 0); } @@ -252,16 +257,16 @@ reg: OP_MUL_64(reg, reg) 1 state->reg2 = get_var(s->b_parent); tmp1 = get_var(s->b_parent); - bb_add_insn(s, reg_reg_insn(INSN_MOV_REG_REG, state->right->reg2, tmp1)); - bb_add_insn(s, reg_reg_insn(INSN_MUL_REG_REG, state->left->reg1, tmp1)); - bb_add_insn(s, reg_reg_insn(INSN_MOV_REG_REG, state->left->reg2, state->reg2)); - bb_add_insn(s, reg_reg_insn(INSN_MUL_REG_REG, state->right->reg1, state->reg2)); - bb_add_insn(s, reg_reg_insn(INSN_ADD_REG_REG, tmp1, state->reg2)); + select_insn(s, tree, reg_reg_insn(INSN_MOV_REG_REG, state->right->reg2, tmp1)); + select_insn(s, tree, reg_reg_insn(INSN_MUL_REG_REG, state->left->reg1, tmp1)); + select_insn(s, tree, reg_reg_insn(INSN_MOV_REG_REG, state->left->reg2, state->reg2)); + select_insn(s, tree, reg_reg_insn(INSN_MUL_REG_REG, state->right->reg1, state->reg2)); + select_insn(s, tree, reg_reg_insn(INSN_ADD_REG_REG, tmp1, state->reg2)); - bb_add_insn(s, reg_reg_insn(INSN_MOV_REG_REG, state->right->reg1, eax)); - bb_add_insn(s, reg_reg_insn(INSN_MUL_REG_EAX, state->left->reg1, eax)); + select_insn(s, tree, reg_reg_insn(INSN_MOV_REG_REG, state->right->reg1, eax)); + select_insn(s, tree, reg_reg_insn(INSN_MUL_REG_EAX, state->left->reg1, eax)); - bb_add_insn(s, reg_reg_insn(INSN_ADD_REG_REG, edx, state->reg2)); + select_insn(s, tree, reg_reg_insn(INSN_ADD_REG_REG, edx, state->reg2)); } reg: OP_DIV(reg, EXPR_LOCAL) 1 @@ -271,7 +276,7 @@ reg: OP_DIV(reg, EXPR_LOCAL) 1 reg: OP_DIV_64(reg, reg) 1 { - emulate_op_64(state, s, emulate_ldiv, J_LONG); + emulate_op_64(state, s, tree, emulate_ldiv, J_LONG); } reg: OP_REM(reg, EXPR_LOCAL) 1 @@ -283,12 +288,12 @@ reg: OP_REM(reg, EXPR_LOCAL) 1 result = get_fixed_var(s->b_parent, REG_EAX); remainder = get_fixed_var(s->b_parent, REG_EDX); - bb_add_insn(s, reg_reg_insn(INSN_MOV_REG_REG, remainder, result)); + select_insn(s, tree, reg_reg_insn(INSN_MOV_REG_REG, remainder, result)); } reg: OP_REM_64(reg, reg) 1 { - emulate_op_64(state, s, emulate_lrem, J_LONG); + emulate_op_64(state, s, tree, emulate_lrem, J_LONG); } reg: OP_NEG(reg) 1 @@ -301,14 +306,14 @@ reg: OP_NEG(reg) 1 result = state->left->reg1; state->reg1 = result; - bb_add_insn(s, reg_insn(INSN_NEG_REG, result)); + select_insn(s, tree, reg_insn(INSN_NEG_REG, result)); if (expr->vm_type == J_LONG) { result = state->left->reg2; state->reg2 = result; - bb_add_insn(s, imm_reg_insn(INSN_ADC_IMM_REG, 0, result)); - bb_add_insn(s, reg_insn(INSN_NEG_REG, result)); + select_insn(s, tree, imm_reg_insn(INSN_ADC_IMM_REG, 0, result)); + select_insn(s, tree, reg_insn(INSN_NEG_REG, result)); } } @@ -320,8 +325,8 @@ reg: OP_SHL(reg, reg) 1 state->reg1 = state->left->reg1; - bb_add_insn(s, reg_reg_insn(INSN_MOV_REG_REG, state->right->reg1, ecx)); - bb_add_insn(s, reg_reg_insn(INSN_SHL_REG_REG, ecx, state->left->reg1)); + select_insn(s, tree, reg_reg_insn(INSN_MOV_REG_REG, state->right->reg1, ecx)); + select_insn(s, tree, reg_reg_insn(INSN_SHL_REG_REG, ecx, state->left->reg1)); } reg: OP_SHL(reg, EXPR_LOCAL) 1 @@ -426,7 +431,7 @@ reg: EXPR_INVOKE(arg) 1 } call_insn = rel_insn(INSN_CALL_REL, (unsigned long) target); - bb_add_insn(s, call_insn); + select_insn(s, tree, call_insn); if (!is_compiled) { struct fixup_site *fixup; @@ -439,7 +444,7 @@ reg: EXPR_INVOKE(arg) 1 } if (method->args_count) - method_args_cleanup(s, method->args_count); + method_args_cleanup(s, tree, method->args_count); } reg: EXPR_INVOKEVIRTUAL(arg) 1 @@ -461,28 +466,28 @@ reg: EXPR_INVOKEVIRTUAL(arg) 1 stack_ptr = get_fixed_var(s->b_parent, REG_ESP); /* object reference */ - bb_add_insn(s, membase_reg_insn(INSN_MOV_MEMBASE_REG, stack_ptr, 0, call_target)); + select_insn(s, tree, membase_reg_insn(INSN_MOV_MEMBASE_REG, stack_ptr, 0, call_target)); /* object class */ - bb_add_insn(s, membase_reg_insn(INSN_MOV_MEMBASE_REG, call_target, offsetof(struct object, class), call_target)); + select_insn(s, tree, membase_reg_insn(INSN_MOV_MEMBASE_REG, call_target, offsetof(struct object, class), call_target)); /* vtable */ - bb_add_insn(s, membase_reg_insn(INSN_MOV_MEMBASE_REG, call_target, sizeof(struct object), call_target)); + select_insn(s, tree, membase_reg_insn(INSN_MOV_MEMBASE_REG, call_target, sizeof(struct object), call_target)); /* native ptr */ - bb_add_insn(s, imm_reg_insn(INSN_ADD_IMM_REG, method_offset, call_target)); + select_insn(s, tree, imm_reg_insn(INSN_ADD_IMM_REG, method_offset, call_target)); /* invoke method */ - bb_add_insn(s, reg_insn(INSN_CALL_REG, call_target)); + select_insn(s, tree, reg_insn(INSN_CALL_REG, call_target)); args_count = nr_args(to_expr(expr->args_list)); if (args_count) - method_args_cleanup(s, args_count); + method_args_cleanup(s, tree, args_count); } reg: OP_CMP(reg, reg) 1 { - emulate_op_64(state, s, emulate_lcmp, J_INT); + emulate_op_64(state, s, tree, emulate_lcmp, J_INT); } reg: OP_CMP(reg, EXPR_VALUE) 1 @@ -500,16 +505,16 @@ reg: OP_CMP(reg, EXPR_VALUE) 1 assert(!"OP_CMP implemented for J_LONG only"); } - bb_add_insn(s, imm_insn(INSN_PUSH_IMM, (unsigned long) (right->value >> 32))); - bb_add_insn(s, imm_insn(INSN_PUSH_IMM, (unsigned long) (right->value & ~0UL))); + select_insn(s, tree, imm_insn(INSN_PUSH_IMM, (unsigned long) (right->value >> 32))); + select_insn(s, tree, imm_insn(INSN_PUSH_IMM, (unsigned long) (right->value & ~0UL))); - bb_add_insn(s, reg_insn(INSN_PUSH_REG, state->left->reg2)); - bb_add_insn(s, reg_insn(INSN_PUSH_REG, state->left->reg1)); + select_insn(s, tree, reg_insn(INSN_PUSH_REG, state->left->reg2)); + select_insn(s, tree, reg_insn(INSN_PUSH_REG, state->left->reg1)); - bb_add_insn(s, rel_insn(INSN_CALL_REL, (unsigned long) emulate_lcmp)); - method_args_cleanup(s, 4); + select_insn(s, tree, rel_insn(INSN_CALL_REL, (unsigned long) emulate_lcmp)); + method_args_cleanup(s, tree, 4); - bb_add_insn(s, reg_reg_insn(INSN_MOV_REG_REG, eax, state->reg1)); + select_insn(s, tree, reg_reg_insn(INSN_MOV_REG_REG, eax, state->reg1)); } reg: OP_EQ(reg, EXPR_LOCAL) 1 @@ -614,13 +619,13 @@ reg: EXPR_CLASS_FIELD 1 state->reg1 = get_var(s->b_parent); field = get_var(s->b_parent); - bb_add_insn(s, imm_reg_insn(INSN_MOV_IMM_REG, (unsigned long) expr->class_field, field)); - bb_add_insn(s, membase_reg_insn(INSN_MOV_MEMBASE_REG, field, offset, state->reg1)); + select_insn(s, tree, imm_reg_insn(INSN_MOV_IMM_REG, (unsigned long) expr->class_field, field)); + select_insn(s, tree, membase_reg_insn(INSN_MOV_MEMBASE_REG, field, offset, state->reg1)); if (expr->vm_type == J_LONG) { state->reg2 = get_var(s->b_parent); - bb_add_insn(s, membase_reg_insn(INSN_MOV_MEMBASE_REG, field, offset+4, state->reg2)); + select_insn(s, tree, membase_reg_insn(INSN_MOV_MEMBASE_REG, field, offset+4, state->reg2)); } } @@ -635,15 +640,15 @@ reg: EXPR_INSTANCE_FIELD(reg) 1 index = get_var(s->b_parent); state->reg1 = get_var(s->b_parent); - bb_add_insn(s, imm_reg_insn(INSN_ADD_IMM_REG, sizeof(struct object), base)); - bb_add_insn(s, imm_reg_insn(INSN_MOV_IMM_REG, expr->instance_field->offset, index)); - bb_add_insn(s, memindex_reg_insn(INSN_MOV_MEMINDEX_REG, base, index, 2, state->reg1)); + select_insn(s, tree, imm_reg_insn(INSN_ADD_IMM_REG, sizeof(struct object), base)); + select_insn(s, tree, imm_reg_insn(INSN_MOV_IMM_REG, expr->instance_field->offset, index)); + select_insn(s, tree, memindex_reg_insn(INSN_MOV_MEMINDEX_REG, base, index, 2, state->reg1)); if (expr->vm_type == J_LONG) { state->reg2 = get_var(s->b_parent); - bb_add_insn(s, imm_reg_insn(INSN_ADD_IMM_REG, 1, index)); - bb_add_insn(s, memindex_reg_insn(INSN_MOV_MEMINDEX_REG, base, index, 2, state->reg2)); + select_insn(s, tree, imm_reg_insn(INSN_ADD_IMM_REG, 1, index)); + select_insn(s, tree, memindex_reg_insn(INSN_MOV_MEMINDEX_REG, base, index, 2, state->reg2)); } } @@ -657,9 +662,9 @@ reg: EXPR_NEW var = get_fixed_var(s->b_parent, REG_EAX); state->reg1 = var; - bb_add_insn(s, imm_insn(INSN_PUSH_IMM, (unsigned long) expr->class)); - bb_add_insn(s, rel_insn(INSN_CALL_REL, (unsigned long) allocObject)); - method_args_cleanup(s, 1); + select_insn(s, tree, imm_insn(INSN_PUSH_IMM, (unsigned long) expr->class)); + select_insn(s, tree, rel_insn(INSN_CALL_REL, (unsigned long) allocObject)); + method_args_cleanup(s, tree, 1); } reg: EXPR_NEWARRAY(reg) @@ -674,11 +679,11 @@ reg: EXPR_NEWARRAY(reg) size = state->left->reg1; - bb_add_insn(s, reg_insn(INSN_PUSH_REG, size)); - bb_add_insn(s, imm_insn(INSN_PUSH_IMM, expr->array_type)); - bb_add_insn(s, rel_insn(INSN_CALL_REL, (unsigned long) allocTypeArray)); + select_insn(s, tree, reg_insn(INSN_PUSH_REG, size)); + select_insn(s, tree, imm_insn(INSN_PUSH_IMM, expr->array_type)); + select_insn(s, tree, rel_insn(INSN_CALL_REL, (unsigned long) allocTypeArray)); - method_args_cleanup(s, 2); + method_args_cleanup(s, tree, 2); } reg: EXPR_MULTIANEWARRAY(arg) @@ -697,12 +702,12 @@ reg: EXPR_MULTIANEWARRAY(arg) dimension = nr_args(to_expr(expr->multianewarray_dimensions)); - bb_add_insn(s, reg_insn(INSN_PUSH_REG, stack_ptr)); - bb_add_insn(s, imm_insn(INSN_PUSH_IMM, dimension)); - bb_add_insn(s, imm_insn(INSN_PUSH_IMM, (unsigned long) expr->multianewarray_ref_type)); - bb_add_insn(s, rel_insn(INSN_CALL_REL, (unsigned long) allocMultiArray)); + select_insn(s, tree, reg_insn(INSN_PUSH_REG, stack_ptr)); + select_insn(s, tree, imm_insn(INSN_PUSH_IMM, dimension)); + select_insn(s, tree, imm_insn(INSN_PUSH_IMM, (unsigned long) expr->multianewarray_ref_type)); + select_insn(s, tree, rel_insn(INSN_CALL_REL, (unsigned long) allocMultiArray)); - method_args_cleanup(s, dimension + 3); + method_args_cleanup(s, tree, dimension + 3); } reg: EXPR_ANEWARRAY(reg) @@ -717,12 +722,12 @@ reg: EXPR_ANEWARRAY(reg) size = state->left->reg1; - bb_add_insn(s, imm_insn(INSN_PUSH_IMM, sizeof(struct object *))); - bb_add_insn(s, reg_insn(INSN_PUSH_REG, size)); - bb_add_insn(s, imm_insn(INSN_PUSH_IMM, (unsigned long) expr->anewarray_ref_type)); - bb_add_insn(s, rel_insn(INSN_CALL_REL, (unsigned long) allocArray)); + select_insn(s, tree, imm_insn(INSN_PUSH_IMM, sizeof(struct object *))); + select_insn(s, tree, reg_insn(INSN_PUSH_REG, size)); + select_insn(s, tree, imm_insn(INSN_PUSH_IMM, (unsigned long) expr->anewarray_ref_type)); + select_insn(s, tree, rel_insn(INSN_CALL_REL, (unsigned long) allocArray)); - method_args_cleanup(s, 3); + method_args_cleanup(s, tree, 3); } reg: EXPR_ARRAYLENGTH(reg) @@ -734,7 +739,7 @@ reg: EXPR_ARRAYLENGTH(reg) arraylength = get_fixed_var(s->b_parent, REG_EAX); state->reg1 = arraylength; - bb_add_insn(s, membase_reg_insn(INSN_MOV_MEMBASE_REG, arrayref, sizeof(struct object), arraylength)); + select_insn(s, tree, membase_reg_insn(INSN_MOV_MEMBASE_REG, arrayref, sizeof(struct object), arraylength)); } reg: EXPR_INSTANCEOF(reg) @@ -749,11 +754,11 @@ reg: EXPR_INSTANCEOF(reg) instanceof_result = get_fixed_var(s->b_parent, REG_EAX); state->reg1 = instanceof_result; - bb_add_insn(s, imm_insn(INSN_PUSH_IMM, (unsigned long) expr->instanceof_class)); - bb_add_insn(s, reg_insn(INSN_PUSH_REG, ref)); - bb_add_insn(s, rel_insn(INSN_CALL_REL, (unsigned long) is_object_instance_of)); + select_insn(s, tree, imm_insn(INSN_PUSH_IMM, (unsigned long) expr->instanceof_class)); + select_insn(s, tree, reg_insn(INSN_PUSH_REG, ref)); + select_insn(s, tree, rel_insn(INSN_CALL_REL, (unsigned long) is_object_instance_of)); - method_args_cleanup(s, 2); + method_args_cleanup(s, tree, 2); } reg: EXPR_CONVERSION(reg) @@ -767,9 +772,9 @@ reg: EXPR_CONVERSION(reg) state->reg1 = get_var(s->b_parent); state->reg2 = get_var(s->b_parent); - bb_add_insn(s, reg_reg_insn(INSN_MOV_REG_REG, state->left->reg1, state->reg1)); - bb_add_insn(s, reg_reg_insn(INSN_MOV_REG_REG, state->left->reg1, state->reg2)); - bb_add_insn(s, imm_reg_insn(INSN_SAR_IMM_REG, 0x1f, state->reg2)); + select_insn(s, tree, reg_reg_insn(INSN_MOV_REG_REG, state->left->reg1, state->reg1)); + select_insn(s, tree, reg_reg_insn(INSN_MOV_REG_REG, state->left->reg1, state->reg2)); + select_insn(s, tree, imm_reg_insn(INSN_SAR_IMM_REG, 0x1f, state->reg2)); } else if (src->vm_type == J_LONG && expr->vm_type == J_INT) { state->reg1 = state->left->reg1; } else { @@ -791,10 +796,10 @@ arg: EXPR_ARG(EXPR_VALUE) imm = arg_expr->value; if (arg_expr->vm_type == J_LONG) { - bb_add_insn(s, imm_insn(INSN_PUSH_IMM, imm >> 32)); + select_insn(s, tree, imm_insn(INSN_PUSH_IMM, imm >> 32)); } - bb_add_insn(s, imm_insn(INSN_PUSH_IMM, imm & ~0UL)); + select_insn(s, tree, imm_insn(INSN_PUSH_IMM, imm & ~0UL)); } arg: EXPR_ARG(reg) @@ -807,11 +812,11 @@ arg: EXPR_ARG(reg) if (arg_expr->vm_type == J_LONG) { src = state->left->reg2; - bb_add_insn(s, reg_insn(INSN_PUSH_REG, src)); + select_insn(s, tree, reg_insn(INSN_PUSH_REG, src)); } src = state->left->reg1; - bb_add_insn(s, reg_insn(INSN_PUSH_REG, src)); + select_insn(s, tree, reg_insn(INSN_PUSH_REG, src)); } arg: EXPR_ARGS_LIST(arg, arg) @@ -825,7 +830,7 @@ reg: EXPR_EXCEPTION_REF result = get_var(s->b_parent); state->reg1 = result; - bb_add_insn(s, reg_insn(INSN_POP_REG, result)); + select_insn(s, tree, reg_insn(INSN_POP_REG, result)); } stmt: STMT_RETURN(reg) @@ -839,21 +844,21 @@ stmt: STMT_RETURN(reg) eax = get_fixed_var(s->b_parent, REG_EAX); src = state->left->reg1; - bb_add_insn(s, reg_reg_insn(INSN_MOV_REG_REG, src, eax)); + select_insn(s, tree, reg_reg_insn(INSN_MOV_REG_REG, src, eax)); if (expr->vm_type == J_LONG) { edx = get_fixed_var(s->b_parent, REG_EDX); src = state->left->reg2; - bb_add_insn(s, reg_reg_insn(INSN_MOV_REG_REG, src, edx)); + select_insn(s, tree, reg_reg_insn(INSN_MOV_REG_REG, src, edx)); } - bb_add_insn(s, branch_insn(INSN_JMP_BRANCH, s->b_parent->exit_bb)); + select_insn(s, tree, branch_insn(INSN_JMP_BRANCH, s->b_parent->exit_bb)); } stmt: STMT_VOID_RETURN { - bb_add_insn(s, branch_insn(INSN_JMP_BRANCH, s->b_parent->exit_bb)); + select_insn(s, tree, branch_insn(INSN_JMP_BRANCH, s->b_parent->exit_bb)); } stmt: STMT_EXPRESSION(reg) @@ -878,13 +883,13 @@ stmt: STMT_STORE(EXPR_CLASS_FIELD, reg) offset = get_var(s->b_parent); - bb_add_insn(s, imm_reg_insn(INSN_MOV_IMM_REG, (unsigned long) store_dest->class_field, offset)); - bb_add_insn(s, reg_membase_insn(INSN_MOV_REG_MEMBASE, src, offset, field_offset)); + select_insn(s, tree, imm_reg_insn(INSN_MOV_IMM_REG, (unsigned long) store_dest->class_field, offset)); + select_insn(s, tree, reg_membase_insn(INSN_MOV_REG_MEMBASE, src, offset, field_offset)); if (store_src->vm_type == J_LONG) { src = state->right->reg2; - bb_add_insn(s, imm_reg_insn(INSN_ADD_IMM_REG, 4, offset)); - bb_add_insn(s, reg_membase_insn(INSN_MOV_REG_MEMBASE, src, offset, field_offset)); + select_insn(s, tree, imm_reg_insn(INSN_ADD_IMM_REG, 4, offset)); + select_insn(s, tree, reg_membase_insn(INSN_MOV_REG_MEMBASE, src, offset, field_offset)); } } @@ -903,9 +908,9 @@ inst_field: EXPR_INSTANCE_FIELD(reg) 1 index = get_var(s->b_parent); state->reg2 = index; - bb_add_insn(s, reg_reg_insn(INSN_MOV_REG_REG, src, base)); - bb_add_insn(s, imm_reg_insn(INSN_ADD_IMM_REG, sizeof(struct object), base)); - bb_add_insn(s, imm_reg_insn(INSN_MOV_IMM_REG, expr->instance_field->offset, index)); + select_insn(s, tree, reg_reg_insn(INSN_MOV_REG_REG, src, base)); + select_insn(s, tree, imm_reg_insn(INSN_ADD_IMM_REG, sizeof(struct object), base)); + select_insn(s, tree, imm_reg_insn(INSN_MOV_IMM_REG, expr->instance_field->offset, index)); } stmt: STMT_STORE(inst_field, reg) @@ -921,12 +926,12 @@ stmt: STMT_STORE(inst_field, reg) base = state->left->reg1; index = state->left->reg2; - bb_add_insn(s, reg_memindex_insn(INSN_MOV_REG_MEMINDEX, src, base, index, 2)); + select_insn(s, tree, reg_memindex_insn(INSN_MOV_REG_MEMINDEX, src, base, index, 2)); if (store_src->vm_type == J_LONG) { src = state->right->reg2; - bb_add_insn(s, imm_reg_insn(INSN_ADD_IMM_REG, 1, index)); - bb_add_insn(s, reg_memindex_insn(INSN_MOV_REG_MEMINDEX, src, base, index, 2)); + select_insn(s, tree, imm_reg_insn(INSN_ADD_IMM_REG, 1, index)); + select_insn(s, tree, reg_memindex_insn(INSN_MOV_REG_MEMINDEX, src, base, index, 2)); } } @@ -944,14 +949,14 @@ stmt: STMT_STORE(EXPR_LOCAL, reg) local = to_expr(stmt->store_dest); slot = get_local_slot(cu->stack_frame, local->local_index); - bb_add_insn(s, reg_memlocal_insn(INSN_MOV_REG_MEMLOCAL, src, slot)); + select_insn(s, tree, reg_memlocal_insn(INSN_MOV_REG_MEMLOCAL, src, slot)); if (local->vm_type == J_LONG) { src = state->right->reg2; slot = get_local_slot(cu->stack_frame, local->local_index+1); - bb_add_insn(s, reg_memlocal_insn(INSN_MOV_REG_MEMLOCAL, src, slot)); + select_insn(s, tree, reg_memlocal_insn(INSN_MOV_REG_MEMLOCAL, src, slot)); } } @@ -967,12 +972,12 @@ stmt: STMT_STORE(EXPR_TEMPORARY, reg) dest = temp->tmp_low; src = state->right->reg1; - bb_add_insn(s, reg_reg_insn(INSN_MOV_REG_REG, src, dest)); + select_insn(s, tree, reg_reg_insn(INSN_MOV_REG_REG, src, dest)); if (temp->vm_type == J_LONG) { dest = temp->tmp_high; src = state->right->reg2; - bb_add_insn(s, reg_reg_insn(INSN_MOV_REG_REG, src, dest)); + select_insn(s, tree, reg_reg_insn(INSN_MOV_REG_REG, src, dest)); } } @@ -992,9 +997,9 @@ array_deref: EXPR_ARRAY_DEREF(reg, reg) 2 index = get_var(s->b_parent); state->reg2 = index; - bb_add_insn(s, reg_reg_insn(INSN_MOV_REG_REG, state_base, base)); - bb_add_insn(s, imm_reg_insn(INSN_ADD_IMM_REG, sizeof(struct object) + sizeof(uint32_t), base)); - bb_add_insn(s, reg_reg_insn(INSN_MOV_REG_REG, state_index, index)); + select_insn(s, tree, reg_reg_insn(INSN_MOV_REG_REG, state_base, base)); + select_insn(s, tree, imm_reg_insn(INSN_ADD_IMM_REG, sizeof(struct object) + sizeof(uint32_t), base)); + select_insn(s, tree, reg_reg_insn(INSN_MOV_REG_REG, state_index, index)); } stmt: STMT_STORE(array_deref, reg) @@ -1013,7 +1018,7 @@ stmt: STMT_STORE(array_deref, reg) index = state->left->reg2; src = state->right->reg1; - bb_add_insn(s, reg_memindex_insn(INSN_MOV_REG_MEMINDEX, src, base, index, scale)); + select_insn(s, tree, reg_memindex_insn(INSN_MOV_REG_MEMINDEX, src, base, index, scale)); } stmt: STMT_STORE(reg, array_deref) @@ -1034,7 +1039,7 @@ stmt: STMT_STORE(reg, array_deref) state->reg1 = dest; - bb_add_insn(s, memindex_reg_insn(INSN_MOV_MEMINDEX_REG, base, index, scale, dest)); + select_insn(s, tree, memindex_reg_insn(INSN_MOV_MEMINDEX_REG, base, index, scale, dest)); } stmt: STMT_ATHROW(reg) @@ -1048,10 +1053,10 @@ stmt: STMT_NULL_CHECK(reg) ref = state->left->reg1; - bb_add_insn(s, reg_insn(INSN_PUSH_REG, ref)); - bb_add_insn(s, rel_insn(INSN_CALL_REL, (unsigned long) check_null)); + select_insn(s, tree, reg_insn(INSN_PUSH_REG, ref)); + select_insn(s, tree, rel_insn(INSN_CALL_REL, (unsigned long) check_null)); - method_args_cleanup(s, 1); + method_args_cleanup(s, tree, 1); } array_check: EXPR_ARRAY_DEREF(reg, reg) 2 @@ -1070,8 +1075,8 @@ array_check: EXPR_ARRAY_DEREF(reg, reg) 2 index = get_var(s->b_parent); state->reg2 = index; - bb_add_insn(s, reg_reg_insn(INSN_MOV_REG_REG, state_base, base)); - bb_add_insn(s, reg_reg_insn(INSN_MOV_REG_REG, state_index, index)); + select_insn(s, tree, reg_reg_insn(INSN_MOV_REG_REG, state_base, base)); + select_insn(s, tree, reg_reg_insn(INSN_MOV_REG_REG, state_index, index)); } stmt: STMT_ARRAY_CHECK(array_check) @@ -1081,11 +1086,11 @@ stmt: STMT_ARRAY_CHECK(array_check) ref = state->left->reg1; index = state->left->reg2; - bb_add_insn(s, reg_insn(INSN_PUSH_REG, index)); - bb_add_insn(s, reg_insn(INSN_PUSH_REG, ref)); - bb_add_insn(s, rel_insn(INSN_CALL_REL, (unsigned long) check_array)); + select_insn(s, tree, reg_insn(INSN_PUSH_REG, index)); + select_insn(s, tree, reg_insn(INSN_PUSH_REG, ref)); + select_insn(s, tree, rel_insn(INSN_CALL_REL, (unsigned long) check_array)); - method_args_cleanup(s, 2); + method_args_cleanup(s, tree, 2); } stmt: STMT_IF(reg) @@ -1098,7 +1103,7 @@ stmt: STMT_IF(reg) if_conditional = to_expr(stmt->if_conditional); insn_type = br_binop_to_insn_type(expr_bin_op(if_conditional)); - bb_add_insn(s, branch_insn(insn_type, stmt->if_true)); + select_insn(s, tree, branch_insn(insn_type, stmt->if_true)); } stmt: STMT_GOTO @@ -1107,7 +1112,7 @@ stmt: STMT_GOTO stmt = to_stmt(tree); - bb_add_insn(s, branch_insn(INSN_JMP_BRANCH, stmt->goto_target)); + select_insn(s, tree, branch_insn(INSN_JMP_BRANCH, stmt->goto_target)); } stmt: STMT_MONITOR_ENTER(reg) @@ -1115,10 +1120,10 @@ stmt: STMT_MONITOR_ENTER(reg) struct var_info *ref; ref = state->left->reg1; - bb_add_insn(s, reg_insn(INSN_PUSH_REG, ref)); - bb_add_insn(s, rel_insn(INSN_CALL_REL, (unsigned long) objectLock)); + select_insn(s, tree, reg_insn(INSN_PUSH_REG, ref)); + select_insn(s, tree, rel_insn(INSN_CALL_REL, (unsigned long) objectLock)); - method_args_cleanup(s, 1); + method_args_cleanup(s, tree, 1); } stmt: STMT_MONITOR_EXIT(reg) @@ -1126,10 +1131,10 @@ stmt: STMT_MONITOR_EXIT(reg) struct var_info *ref; ref = state->left->reg1; - bb_add_insn(s, reg_insn(INSN_PUSH_REG, ref)); - bb_add_insn(s, rel_insn(INSN_CALL_REL, (unsigned long) objectUnlock)); + select_insn(s, tree, reg_insn(INSN_PUSH_REG, ref)); + select_insn(s, tree, rel_insn(INSN_CALL_REL, (unsigned long) objectUnlock)); - method_args_cleanup(s, 1); + method_args_cleanup(s, tree, 1); } stmt: STMT_CHECKCAST(reg) @@ -1141,15 +1146,22 @@ stmt: STMT_CHECKCAST(reg) stmt = to_stmt(tree); - bb_add_insn(s, imm_insn(INSN_PUSH_IMM, (unsigned long) stmt->checkcast_class)); - bb_add_insn(s, reg_insn(INSN_PUSH_REG, ref)); - bb_add_insn(s, rel_insn(INSN_CALL_REL, (unsigned long)check_cast)); + select_insn(s, tree, imm_insn(INSN_PUSH_IMM, (unsigned long) stmt->checkcast_class)); + select_insn(s, tree, reg_insn(INSN_PUSH_REG, ref)); + select_insn(s, tree, rel_insn(INSN_CALL_REL, (unsigned long)check_cast)); - method_args_cleanup(s, 2); + method_args_cleanup(s, tree, 2); } %% +static void select_insn(struct basic_block *bb, struct tree_node *tree, + struct insn *instruction) +{ + instruction->bytecode_offset = tree_bytecode_offset(tree); + bb_add_insn(bb, instruction); +} + static void __binop_reg_local(struct _MBState *state, struct basic_block *bb, struct tree_node *tree, enum insn_type insn_type, struct var_info *result, long disp_offset) @@ -1164,7 +1176,7 @@ static void __binop_reg_local(struct _MBState *state, struct basic_block *bb, frame_ptr = bb->b_parent->frame_ptr; - bb_add_insn(bb, membase_reg_insn(insn_type, frame_ptr, disp, result)); + select_insn(bb, tree, membase_reg_insn(insn_type, frame_ptr, disp, result)); } static void binop_reg_local_low(struct _MBState *state, struct basic_block *bb, @@ -1193,7 +1205,7 @@ static void binop_reg_value_low(struct _MBState *state, struct basic_block *bb, expr = to_expr(tree); right = to_expr(expr->binary_right); - bb_add_insn(bb, imm_reg_insn(insn_type, right->value & ~0UL, state->reg1)); + select_insn(bb, tree, imm_reg_insn(insn_type, right->value & ~0UL, state->reg1)); } static void binop_reg_value_high(struct _MBState *state, struct basic_block *bb, @@ -1206,7 +1218,7 @@ static void binop_reg_value_high(struct _MBState *state, struct basic_block *bb, expr = to_expr(tree); right = to_expr(expr->binary_right); - bb_add_insn(bb, imm_reg_insn(insn_type, right->value >> 32, state->reg2)); + select_insn(bb, tree, imm_reg_insn(insn_type, right->value >> 32, state->reg2)); } static void binop_reg_reg_low(struct _MBState *state, struct basic_block *bb, @@ -1217,7 +1229,7 @@ static void binop_reg_reg_low(struct _MBState *state, struct basic_block *bb, src = state->right->reg1; dst = state->left->reg1; - bb_add_insn(bb, reg_reg_insn(insn_type, src, dst)); + select_insn(bb, tree, reg_reg_insn(insn_type, src, dst)); } static void binop_reg_reg_high(struct _MBState *state, struct basic_block *bb, @@ -1228,7 +1240,7 @@ static void binop_reg_reg_high(struct _MBState *state, struct basic_block *bb, src = state->right->reg2; dst = state->left->reg2; - bb_add_insn(bb, reg_reg_insn(insn_type, src, dst)); + select_insn(bb, tree, reg_reg_insn(insn_type, src, dst)); } static void shift_reg_local(struct _MBState *state, struct basic_block *bb, @@ -1247,8 +1259,8 @@ static void shift_reg_local(struct _MBState *state, struct basic_block *bb, frame_ptr = bb->b_parent->frame_ptr; shift_count = get_fixed_var(bb->b_parent, REG_ECX); - bb_add_insn(bb, membase_reg_insn(INSN_MOV_MEMBASE_REG, frame_ptr, disp, shift_count)); - bb_add_insn(bb, reg_reg_insn(insn_type, shift_count, result)); + select_insn(bb, tree, membase_reg_insn(INSN_MOV_MEMBASE_REG, frame_ptr, disp, shift_count)); + select_insn(bb, tree, reg_reg_insn(insn_type, shift_count, result)); } static void div_reg_local(struct _MBState *state, struct basic_block *bb, @@ -1267,15 +1279,15 @@ static void div_reg_local(struct _MBState *state, struct basic_block *bb, frame_ptr = bb->b_parent->frame_ptr; - bb_add_insn(bb, reg_reg_insn(INSN_MOV_REG_REG, state->left->reg1, result)); - bb_add_insn(bb, reg_reg_insn(INSN_CLTD_REG_REG, result, edx)); - bb_add_insn(bb, membase_reg_insn(INSN_DIV_MEMBASE_REG, frame_ptr, disp, result)); + select_insn(bb, tree, reg_reg_insn(INSN_MOV_REG_REG, state->left->reg1, result)); + select_insn(bb, tree, reg_reg_insn(INSN_CLTD_REG_REG, result, edx)); + select_insn(bb, tree, membase_reg_insn(INSN_DIV_MEMBASE_REG, frame_ptr, disp, result)); } static void -emulate_op_64(struct _MBState *state, struct basic_block *s, void *func, - enum vm_type return_type) +emulate_op_64(struct _MBState *state, struct basic_block *s, + struct tree_node *tree, void *func, enum vm_type return_type) { struct var_info *eax, *edx = NULL; @@ -1286,17 +1298,17 @@ emulate_op_64(struct _MBState *state, struct basic_block *s, void *func, edx = get_fixed_var(s->b_parent, REG_EDX); state->reg2 = get_var(s->b_parent); } - bb_add_insn(s, reg_insn(INSN_PUSH_REG, state->right->reg2)); - bb_add_insn(s, reg_insn(INSN_PUSH_REG, state->right->reg1)); - bb_add_insn(s, reg_insn(INSN_PUSH_REG, state->left->reg2)); - bb_add_insn(s, reg_insn(INSN_PUSH_REG, state->left->reg1)); + select_insn(s, tree, reg_insn(INSN_PUSH_REG, state->right->reg2)); + select_insn(s, tree, reg_insn(INSN_PUSH_REG, state->right->reg1)); + select_insn(s, tree, reg_insn(INSN_PUSH_REG, state->left->reg2)); + select_insn(s, tree, reg_insn(INSN_PUSH_REG, state->left->reg1)); - bb_add_insn(s, rel_insn(INSN_CALL_REL, (unsigned long) func)); - method_args_cleanup(s, 4); + select_insn(s, tree, rel_insn(INSN_CALL_REL, (unsigned long) func)); + method_args_cleanup(s, tree, 4); - bb_add_insn(s, reg_reg_insn(INSN_MOV_REG_REG, eax, state->reg1)); + select_insn(s, tree, reg_reg_insn(INSN_MOV_REG_REG, eax, state->reg1)); if (edx) - bb_add_insn(s, reg_reg_insn(INSN_MOV_REG_REG, edx, state->reg2)); + select_insn(s, tree, reg_reg_insn(INSN_MOV_REG_REG, edx, state->reg2)); } static void emit_code(struct basic_block *bb, MBState *state, int goal) diff --git a/arch/x86/instruction.c b/arch/x86/instruction.c index 624651a..467bb74 100644 --- a/arch/x86/instruction.c +++ b/arch/x86/instruction.c @@ -24,6 +24,8 @@ * Please refer to the file LICENSE for details. */ +#include <jit/bc-offset-mapping.h> + #include <arch/instruction.h> #include <stdlib.h> @@ -37,6 +39,7 @@ struct insn *alloc_insn(enum insn_type type) INIT_LIST_HEAD(&insn->insn_list_node); INIT_LIST_HEAD(&insn->branch_list_node); insn->type = type; + insn->bytecode_offset = BC_OFFSET_UNKNOWN; } return insn; } diff --git a/include/jit/bc-offset-mapping.h b/include/jit/bc-offset-mapping.h new file mode 100644 index 0000000..21ec6df --- /dev/null +++ b/include/jit/bc-offset-mapping.h @@ -0,0 +1,19 @@ +#ifndef _BC_OFFSET_MAPPING +#define _BC_OFFSET_MAPPING + +#include <jit/compilation-unit.h> +#include <jit/tree-node.h> +#include <vm/string.h> +#include <limits.h> + +#define BC_OFFSET_UNKNOWN ULONG_MAX + +unsigned long native_ptr_to_bytecode_offset(struct compilation_unit *cu, + unsigned char *native_ptr); +void print_bytecode_offset(unsigned long bc_offset, struct string *str); + +unsigned long tree_bytecode_offset(struct tree_node *node); +void tree_patch_bc_offset(struct tree_node *node, unsigned long bc_offset); +bool all_insn_have_bytecode_offset(struct compilation_unit *cu); + +#endif diff --git a/include/jit/expression.h b/include/jit/expression.h index cba8209..f57bb38 100644 --- a/include/jit/expression.h +++ b/include/jit/expression.h @@ -76,6 +76,8 @@ enum unary_operator { struct expression { unsigned long refcount; enum vm_type vm_type; + unsigned long bytecode_offset; + union { struct tree_node node; diff --git a/include/jit/statement.h b/include/jit/statement.h index f87abc0..793e62d 100644 --- a/include/jit/statement.h +++ b/include/jit/statement.h @@ -50,6 +50,7 @@ struct statement { struct tree_node *expression; }; struct list_head stmt_list_node; + unsigned long bytecode_offset; }; static inline struct statement *to_stmt(struct tree_node *node) diff --git a/jit/args.c b/jit/args.c index c8b6c33..9ccac87 100644 --- a/jit/args.c +++ b/jit/args.c @@ -31,10 +31,15 @@ struct expression * insert_arg(struct expression *root, struct expression *expr) { + struct expression *_expr; + + _expr = arg_expr(expr); + _expr->bytecode_offset = expr->bytecode_offset; + if (!root) - return arg_expr(expr); + return _expr; - return args_list_expr(root, arg_expr(expr)); + return args_list_expr(root, _expr); } struct expression * diff --git a/jit/bc-offset-mapping.c b/jit/bc-offset-mapping.c new file mode 100644 index 0000000..707394e --- /dev/null +++ b/jit/bc-offset-mapping.c @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2009 Tomasz Grabiec + * + * This file is released under the GPL version 2 with the following + * clarification and special exception: + * + * Linking this library statically or dynamically with other modules is + * making a combined work based on this library. Thus, the terms and + * conditions of the GNU General Public License cover the whole + * combination. + * + * As a special exception, the copyright holders of this library give you + * permission to link this library with independent modules to produce an + * executable, regardless of the license terms of these independent + * modules, and to copy and distribute the resulting executable under terms + * of your choice, provided that you also meet, for each linked independent + * module, the terms and conditions of the license of that module. An + * independent module is a module which is not derived from or based on + * this library. If you modify this library, you may extend this exception + * to your version of the library, but you are not obligated to do so. If + * you do not wish to do so, delete this exception statement from your + * version. + * + * Please refer to the file LICENSE for details. + */ + +#include <jit/bc-offset-mapping.h> +#include <jit/statement.h> +#include <jit/expression.h> + +#include <arch/instruction.h> + +#include <vm/buffer.h> + +/** + * tree_patch_bc_offset - sets bytecode_offset field of a tree node container + * unless it is already set. + * @node: a tree node + * @offset: bytecode offset to set. + */ +void tree_patch_bc_offset(struct tree_node *node, unsigned long bc_offset) +{ + if (node_is_stmt(node)) { + struct statement *stmt = to_stmt(node); + + if (stmt->bytecode_offset == BC_OFFSET_UNKNOWN) + stmt->bytecode_offset = bc_offset; + } else { + struct expression *expr = to_expr(node); + + if (expr->bytecode_offset == BC_OFFSET_UNKNOWN) + expr->bytecode_offset = bc_offset; + } +} + +/** + * native_ptr_to_bytecode_offset - translates native instruction pointer + * to bytecode offset from which given + * instruction originates. + * @cu: compilation unit of method containing @native_ptr. + * @native_ptr: native instruction pointer to be translated. + */ +unsigned long native_ptr_to_bytecode_offset(struct compilation_unit *cu, + unsigned char *native_ptr) +{ + unsigned char *method_ptr = buffer_ptr(cu->objcode); + struct basic_block *bb; + struct insn *insn; + + for_each_basic_block(bb, &cu->bb_list) { + for_each_insn(insn, &bb->insn_list) { + if (method_ptr + insn->mach_offset == native_ptr) + return insn->bytecode_offset; + } + } + + return BC_OFFSET_UNKNOWN; +} + +void print_bytecode_offset(unsigned long bytecode_offset, struct string *str) +{ + if (bytecode_offset == BC_OFFSET_UNKNOWN) + str_append(str, "?"); + else { + static char buf[32]; + sprintf(buf, "%ld", bytecode_offset); + str_append(str, buf); + } +} + +unsigned long tree_bytecode_offset(struct tree_node *node) +{ + if (node_is_stmt(node)) + return to_stmt(node)->bytecode_offset; + + return to_expr(node)->bytecode_offset; +} + +bool all_insn_have_bytecode_offset(struct compilation_unit *cu) +{ + struct basic_block *bb; + struct insn *insn; + + for_each_basic_block(bb, &cu->bb_list) { + for_each_insn(insn, &bb->insn_list) { + if (insn->bytecode_offset == BC_OFFSET_UNKNOWN) + return false; + } + } + + return true; +} diff --git a/jit/bytecode-to-ir.c b/jit/bytecode-to-ir.c index 07714f7..e6e0640 100644 --- a/jit/bytecode-to-ir.c +++ b/jit/bytecode-to-ir.c @@ -11,6 +11,8 @@ #include <jit/compiler.h> #include <jit/statement.h> #include <jit/expression.h> +#include <jit/bc-offset-mapping.h> +#include <jit/tree-node.h> #include <vm/bytecode.h> #include <vm/bytecodes.h> @@ -227,11 +229,38 @@ static convert_fn_t converters[] = { void convert_expression(struct parse_context *ctx, struct expression *expr) { + expr->bytecode_offset = ctx->offset; stack_push(ctx->bb->mimic_stack, expr); } void convert_statement(struct parse_context *ctx, struct statement *stmt) { + unsigned long bc_offset = ctx->offset; + + /* + * Some expressions do not go through convert_expression() + * so we need to set their bytecode_offset here if it is not set. + */ + switch (stmt_type(stmt)) { + case STMT_STORE: + tree_patch_bc_offset(stmt->store_dest, bc_offset); + tree_patch_bc_offset(stmt->store_src, bc_offset); + break; + case STMT_IF: + tree_patch_bc_offset(stmt->if_conditional, bc_offset); + break; + case STMT_RETURN: + tree_patch_bc_offset(stmt->return_value, bc_offset); + break; + case STMT_EXPRESSION: + case STMT_NULL_CHECK: + case STMT_ARRAY_CHECK: + tree_patch_bc_offset(stmt->expression, bc_offset); + break; + default: ; + } + + stmt->bytecode_offset = bc_offset; bb_add_stmt(ctx->bb, stmt); } diff --git a/jit/compiler.c b/jit/compiler.c index d39ac00..4d7a71e 100644 --- a/jit/compiler.c +++ b/jit/compiler.c @@ -10,6 +10,7 @@ #include <jit/compilation-unit.h> #include <jit/compiler.h> #include <jit/statement.h> +#include <jit/bc-offset-mapping.h> #include <errno.h> #include <stdlib.h> @@ -76,6 +77,8 @@ int compile(struct compilation_unit *cu) if (err) goto out; + assert(all_insn_have_bytecode_offset(cu)); + err = emit_machine_code(cu); if (err) goto out; diff --git a/jit/expression.c b/jit/expression.c index 8a37502..6b776f6 100644 --- a/jit/expression.c +++ b/jit/expression.c @@ -6,6 +6,7 @@ */ #include <jit/expression.h> +#include <jit/bc-offset-mapping.h> #include <vm/vm.h> #include <vm/method.h> #include <stdlib.h> @@ -21,6 +22,7 @@ struct expression *alloc_expression(enum expression_type type, expr->node.op = type << EXPR_TYPE_SHIFT; expr->vm_type = vm_type; expr->refcount = 1; + expr->bytecode_offset = BC_OFFSET_UNKNOWN; } return expr; } diff --git a/jit/invoke-bc.c b/jit/invoke-bc.c index 9162832..406d380 100644 --- a/jit/invoke-bc.c +++ b/jit/invoke-bc.c @@ -58,10 +58,15 @@ static unsigned int method_real_argument_count(struct methodblock *invoke_target static struct expression *insert_arg(struct expression *root, struct expression *expr) { + struct expression *_expr; + + _expr = arg_expr(expr); + _expr->bytecode_offset = expr->bytecode_offset; + if (!root) - return arg_expr(expr); + return _expr; - return args_list_expr(root, arg_expr(expr)); + return args_list_expr(root, _expr); } static struct expression *convert_args(struct stack *mimic_stack, @@ -119,7 +124,7 @@ static int insert_invoke_expr(struct parse_context *ctx, static struct methodblock *resolve_invoke_target(struct parse_context *ctx) { - unsigned long idx; + unsigned long idx; idx = bytecode_read_u16(ctx->buffer); diff --git a/jit/spill-reload.c b/jit/spill-reload.c index 14e1758..f8d3230 100644 --- a/jit/spill-reload.c +++ b/jit/spill-reload.c @@ -63,6 +63,8 @@ static int insert_spill_insn(struct live_interval *interval, struct compilation_ interval->spill_slot = slot; + spill->bytecode_offset = last->bytecode_offset; + list_add(&spill->insn_list_node, &last->insn_list_node); return 0; @@ -89,6 +91,8 @@ static int insert_reload_insn(struct live_interval *interval, struct compilation if (!reload) return -ENOMEM; + reload->bytecode_offset = first->bytecode_offset; + list_add_tail(&reload->insn_list_node, &first->insn_list_node); return 0; diff --git a/jit/statement.c b/jit/statement.c index 0c8ecf4..60805e1 100644 --- a/jit/statement.c +++ b/jit/statement.c @@ -9,6 +9,7 @@ #include <assert.h> #include <jit/expression.h> #include <jit/statement.h> +#include <jit/bc-offset-mapping.h> #include <stdlib.h> #include <string.h> @@ -19,6 +20,7 @@ struct statement *alloc_statement(enum statement_type type) memset(stmt, 0, sizeof *stmt); INIT_LIST_HEAD(&stmt->stmt_list_node); stmt->node.op = type << STMT_TYPE_SHIFT; + stmt->bytecode_offset = BC_OFFSET_UNKNOWN; } return stmt; diff --git a/test/arch-x86/Makefile b/test/arch-x86/Makefile index 5014de5..8ab76d4 100644 --- a/test/arch-x86/Makefile +++ b/test/arch-x86/Makefile @@ -43,6 +43,7 @@ OBJS = \ ../../jit/statement.o \ ../../jit/tree-printer.o \ ../../jit/fixup-site.o \ + ../../jit/bc-offset-mapping.o \ ../../arch/x86/emit-code$(ARCH_POSTFIX).o \ ../../arch/x86/instruction.o \ ../../arch/x86/insn-selector$(ARCH_POSTFIX).o \ diff --git a/test/include/arch/instruction.h b/test/include/arch/instruction.h index d9776ca..2821986 100644 --- a/test/include/arch/instruction.h +++ b/test/include/arch/instruction.h @@ -54,6 +54,9 @@ struct insn { struct list_head insn_list_node; /* Position of this instruction in LIR. */ unsigned long lir_pos; + /* Offset in machine code. */ + unsigned long mach_offset; + unsigned long bytecode_offset; }; static inline unsigned long lir_position(struct use_position *reg) diff --git a/test/jit/Makefile b/test/jit/Makefile index 1fb21d9..89d1489 100644 --- a/test/jit/Makefile +++ b/test/jit/Makefile @@ -34,6 +34,7 @@ OBJS = \ ../../jit/tree-printer.o \ ../../jit/args.o \ ../../jit/exception.o \ + ../../jit/bc-offset-mapping.o \ ../libharness/libharness.o \ ../jamvm/alloc-stub.o \ ../jamvm/resolve-stub.o \ -- 1.6.0.6 ------------------------------------------------------------------------------ Register Now & Save for Velocity, the Web Performance & Operations Conference from O'Reilly Media. Velocity features a full day of expert-led, hands-on workshops and two days of sessions from industry leaders in dedicated Performance & Operations tracks. Use code vel09scf and Save an extra 15% before 5/3. http://p.sf.net/sfu/velocityconf _______________________________________________ Jatovm-devel mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/jatovm-devel
