We do not have to load object reference from stack with this instruction: mov 0(%esp), %reg
Before we select the code for EXPR_INVOKEVIRTUAL code for call arguments is selected so we know what register was allocated to the argument representing object reference before it was pushed. Signed-off-by: Tomek Grabiec <tgrab...@gmail.com> --- arch/x86/insn-selector_32.brg | 32 +++++++++++++++++++++++++++----- 1 files changed, 27 insertions(+), 5 deletions(-) diff --git a/arch/x86/insn-selector_32.brg b/arch/x86/insn-selector_32.brg index ffd31c5..7c380d9 100644 --- a/arch/x86/insn-selector_32.brg +++ b/arch/x86/insn-selector_32.brg @@ -84,6 +84,20 @@ static void method_args_cleanup(struct basic_block *bb, struct tree_node *tree, select_insn(bb, tree, imm_reg_insn(INSN_ADD_IMM_REG, args_size, stack_ptr)); } +/* + * Returns the right-most expression in argument list. It's the first + * argument passed to method. + */ +static struct expression *get_first_arg(struct tree_node *args) +{ + while (expr_type(to_expr(args)) == EXPR_ARGS_LIST) + args = to_expr(args)->args_right; + + assert(expr_type(to_expr(args)) == EXPR_ARG); + + return to_expr(to_expr(args)->arg_expression); +} + struct _MBState; static void __binop_reg_local(struct _MBState *, struct basic_block *, struct tree_node *, enum insn_type, struct var_info *, long); @@ -612,11 +626,11 @@ reg: EXPR_INVOKE(arg) 1 reg: EXPR_INVOKEVIRTUAL(arg) 1 { struct var_info *eax, *edx = NULL; + struct expression *objectref_expr; struct var_info *call_target; struct compilation_unit *cu; unsigned long method_offset; struct vm_method *method; - struct var_info *stack_ptr; unsigned long args_count; struct expression *expr; @@ -634,11 +648,15 @@ reg: EXPR_INVOKEVIRTUAL(arg) 1 state->reg2 = get_var(s->b_parent); } - call_target = get_var(s->b_parent); - stack_ptr = get_fixed_var(s->b_parent, REG_ESP); - /* object reference */ - select_insn(s, tree, membase_reg_insn(INSN_MOV_MEMBASE_REG, stack_ptr, 0, call_target)); + objectref_expr = get_first_arg(expr->args_list); + + if (expr_type(objectref_expr) == EXPR_VALUE) { + call_target = get_var(s->b_parent); + select_insn(s, tree, imm_reg_insn(INSN_MOV_IMM_REG, objectref_expr->value, call_target)); + } else { + call_target = state->left->reg1; + } /* object class */ select_insn(s, tree, membase_reg_insn(INSN_MOV_MEMBASE_REG, call_target, offsetof(struct vm_object, class), call_target)); @@ -1047,6 +1065,7 @@ reg: EXPR_CONVERSION(reg) arg: EXPR_NO_ARGS { + state->reg1 = NULL; } arg: EXPR_ARG(EXPR_VALUE) @@ -1080,10 +1099,13 @@ arg: EXPR_ARG(reg) src = state->left->reg1; select_insn(s, tree, reg_insn(INSN_PUSH_REG, src)); + + state->reg1 = src; } arg: EXPR_ARGS_LIST(arg, arg) { + state->reg1 = state->right->reg1; } reg: EXPR_EXCEPTION_REF -- 1.6.0.6 ------------------------------------------------------------------------------ _______________________________________________ Jatovm-devel mailing list Jatovm-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/jatovm-devel