From 7ca90f152d8ee9f0f7b6e5a574bd79b2f9fd1e49 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Fri, 25 Jan 2013 14:59:22 +0100 Subject: [PATCH] Rework the call handling code in mono_method_to_ir () to remove some code duplication. --- mono/mini/method-to-ir.c | 156 ++++++++++++++------------------------- 1 file changed, 55 insertions(+), 101 deletions(-) diff --git a/mono/mini/method-to-ir.c b/mono/mini/method-to-ir.c index bada06a103e..146e3c2a79d 100644 --- a/mono/mini/method-to-ir.c +++ b/mono/mini/method-to-ir.c @@ -6972,10 +6972,16 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b gboolean check_this = FALSE; gboolean supported_tail_call = FALSE; gboolean need_seq_point = FALSE; + guint32 call_opcode = *ip; + gboolean emit_widen = TRUE; + gboolean push_res = TRUE; + gboolean skip_ret = FALSE; CHECK_OPSIZE (5); token = read32 (ip + 1); + ins = NULL; + if (calli) { GSHAREDVT_FAILURE (*ip); cmethod = NULL; @@ -7201,24 +7207,17 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b constrained_call = NULL; } - if (*ip != CEE_CALLI && check_call_signature (cfg, fsig, sp)) + if (!calli && check_call_signature (cfg, fsig, sp)) UNVERIFIED; if (cmethod && (cfg->opt & MONO_OPT_INTRINS) && (ins = mini_emit_inst_for_sharable_method (cfg, cmethod, fsig, sp))) { bblock = cfg->cbb; if (!MONO_TYPE_IS_VOID (fsig->ret)) { type_to_eval_stack_type ((cfg), fsig->ret, ins); - *sp = ins; - sp++; + emit_widen = FALSE; } - CHECK_CFG_EXCEPTION; - - ip += 5; - ins_flag = 0; - if (need_seq_point) - emit_seq_point (cfg, method, ip, FALSE); - break; + goto call_end; } /* @@ -7396,16 +7395,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b ins = (MonoInst*)mono_emit_calli (cfg, fsig, sp, addr, NULL); } - if (!MONO_TYPE_IS_VOID (fsig->ret)) - *sp++ = mono_emit_widen_call_res (cfg, ins, fsig); - - CHECK_CFG_EXCEPTION; - - ip += 5; - ins_flag = 0; - if (need_seq_point) - emit_seq_point (cfg, method, ip, FALSE); - break; + goto call_end; } /* @@ -7440,17 +7430,9 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b bblock = cfg->cbb; if (!MONO_TYPE_IS_VOID (fsig->ret)) { type_to_eval_stack_type ((cfg), fsig->ret, ins); - *sp = ins; - sp++; + emit_widen = FALSE; } - - CHECK_CFG_EXCEPTION; - - ip += 5; - ins_flag = 0; - if (need_seq_point) - emit_seq_point (cfg, method, ip, FALSE); - break; + goto call_end; } /* Inlining */ @@ -7469,21 +7451,20 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b always = TRUE; } - if ((costs = inline_method (cfg, cmethod, fsig, sp, ip, cfg->real_offset, dont_inline, always))) { - ip += 5; + costs = inline_method (cfg, cmethod, fsig, sp, ip, cfg->real_offset, dont_inline, always); + if (costs) { cfg->real_offset += 5; bblock = cfg->cbb; if (!MONO_TYPE_IS_VOID (fsig->ret)) { /* *sp is already set by inline_method */ sp++; + push_res = FALSE; } inline_costs += costs; - ins_flag = 0; - if (need_seq_point) - emit_seq_point (cfg, method, ip, FALSE); - break; + + goto call_end; } } @@ -7514,16 +7495,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b cmethod, MONO_RGCTX_INFO_METHOD_GSHAREDVT_OUT_TRAMPOLINE); ins = emit_gsharedvt_call (cfg, fsig, sp, addr, cmethod, imt_arg, vtable_arg); - if (!MONO_TYPE_IS_VOID (fsig->ret)) - *sp++ = mono_emit_widen_call_res (cfg, ins, fsig); - - CHECK_CFG_EXCEPTION; - - ip += 5; - ins_flag = 0; - if (need_seq_point) - emit_seq_point (cfg, method, ip, FALSE); - break; + goto call_end; } if (virtual && cmethod && cfg->gsharedvt && cmethod->slot == -1) { @@ -7536,7 +7508,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b inline_costs += 10 * num_calls++; /* Tail recursion elimination */ - if ((cfg->opt & MONO_OPT_TAILC) && *ip == CEE_CALL && cmethod == method && ip [5] == CEE_RET && !vtable_arg) { + if ((cfg->opt & MONO_OPT_TAILC) && call_opcode == CEE_CALL && cmethod == method && ip [5] == CEE_RET && !vtable_arg) { gboolean has_vtargs = FALSE; int i; @@ -7561,12 +7533,9 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b /* skip the CEE_RET, too */ if (ip_in_bb (cfg, bblock, ip + 5)) - ip += 6; - else - ip += 5; - - ins_flag = 0; - break; + skip_ret = TRUE; + push_res = FALSE; + goto call_end; } } @@ -7597,9 +7566,9 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b if (addr) { g_assert (!imt_arg); - if (*ip == CEE_CALL) + if (call_opcode == CEE_CALL) g_assert (context_used); - else if (*ip == CEE_CALLI) + else if (call_opcode == CEE_CALLI) g_assert (!vtable_arg); else /* FIXME: what the hell is this??? */ @@ -7626,16 +7595,8 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b ins = (MonoInst*)mono_emit_calli (cfg, fsig, sp, addr, NULL); } } - if (!MONO_TYPE_IS_VOID (fsig->ret)) - *sp++ = mono_emit_widen_call_res (cfg, ins, fsig); - - CHECK_CFG_EXCEPTION; - ip += 5; - ins_flag = 0; - if (need_seq_point) - emit_seq_point (cfg, method, ip, FALSE); - break; + goto call_end; } /* Array methods */ @@ -7662,8 +7623,6 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b addr = mini_emit_ldelema_ins (cfg, cmethod, sp, ip, FALSE); EMIT_NEW_LOAD_MEMBASE_TYPE (cfg, ins, fsig->ret, addr->dreg, 0); - - *sp++ = ins; } else if (strcmp (cmethod->name, "Address") == 0) { /* array Address */ if (!cmethod->klass->element_class->valuetype && !readonly) mini_emit_check_array_type (cfg, sp [0], cmethod->klass); @@ -7671,43 +7630,29 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b readonly = FALSE; addr = mini_emit_ldelema_ins (cfg, cmethod, sp, ip, FALSE); - *sp++ = addr; + ins = addr; } else { g_assert_not_reached (); } - CHECK_CFG_EXCEPTION; - - ip += 5; - ins_flag = 0; - emit_seq_point (cfg, method, ip, FALSE); - break; + emit_widen = FALSE; + goto call_end; } ins = mini_redirect_call (cfg, cmethod, fsig, sp, virtual ? sp [0] : NULL); - if (ins) { - if (!MONO_TYPE_IS_VOID (fsig->ret)) - *sp++ = mono_emit_widen_call_res (cfg, ins, fsig); - - CHECK_CFG_EXCEPTION; - - ip += 5; - ins_flag = 0; - if (need_seq_point) - emit_seq_point (cfg, method, ip, FALSE); - break; - } + if (ins) + goto call_end; /* Tail prefix / tail call optimization */ /* FIXME: Enabling TAILC breaks some inlining/stack trace/etc tests */ /* FIXME: runtime generic context pointer for jumps? */ /* FIXME: handle this for generic sharing eventually */ - supported_tail_call = cmethod && - ((((ins_flag & MONO_INST_TAILCALL) && (*ip == CEE_CALL)) + if (cmethod && + ((((ins_flag & MONO_INST_TAILCALL) && (call_opcode == CEE_CALL)) ))//|| ((cfg->opt & MONO_OPT_TAILC) && *ip == CEE_CALL && ip [5] == CEE_RET)) - && !vtable_arg && !cfg->generic_sharing_context && is_supported_tail_call (cfg, method, cmethod, fsig); - + && !vtable_arg && !cfg->generic_sharing_context && is_supported_tail_call (cfg, method, cmethod, fsig)) + supported_tail_call = TRUE; if (supported_tail_call) { MonoCallInst *call; @@ -7743,21 +7688,18 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b link_bblock (cfg, bblock, end_bblock); start_new_bblock = 1; - CHECK_CFG_EXCEPTION; - - ip += 5; - ins_flag = 0; - // FIXME: Eliminate unreachable epilogs /* * OP_TAILCALL has no return value, so skip the CEE_RET if it is * only reachable from this call. */ - GET_BBLOCK (cfg, tblock, ip); + GET_BBLOCK (cfg, tblock, ip + 5); if (tblock == bblock || tblock->in_count == 0) - ip += 1; - break; + skip_ret = TRUE; + push_res = TRUE; + + goto call_end; } /* @@ -7768,21 +7710,33 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b * change the called method to a dummy wrapper, and resolve that wrapper * to the real method in mono_jit_compile_method (). */ - if (cfg->method->wrapper_type == MONO_WRAPPER_SYNCHRONIZED && mono_marshal_method_from_wrapper (cfg->method) == cmethod) { + if (cfg->method->wrapper_type == MONO_WRAPPER_SYNCHRONIZED && mono_marshal_method_from_wrapper (cfg->method) == cmethod) cmethod = mono_marshal_get_synchronized_inner_wrapper (cmethod); - } /* Common call */ INLINE_FAILURE ("call"); ins = mono_emit_method_call_full (cfg, cmethod, fsig, sp, virtual ? sp [0] : NULL, imt_arg, vtable_arg); - if (!MONO_TYPE_IS_VOID (fsig->ret)) - *sp++ = mono_emit_widen_call_res (cfg, ins, fsig); + call_end: + + /* End of call, INS should contain the result of the call, if any */ + + if (push_res && !MONO_TYPE_IS_VOID (fsig->ret)) { + g_assert (ins); + if (emit_widen) + *sp++ = mono_emit_widen_call_res (cfg, ins, fsig); + else + *sp++ = ins; + } CHECK_CFG_EXCEPTION; ip += 5; + if (skip_ret) { + g_assert (*ip == CEE_RET); + ip += 1; + } ins_flag = 0; if (need_seq_point) emit_seq_point (cfg, method, ip, FALSE); -- 2.25.1