break;
case STACK_PTR:
case STACK_MP:
+ case STACK_OBJ:
#if SIZEOF_VOID_P == 8
ins->opcode = OP_LCONV_TO_U;
#else
/* Set target field */
/* Optimize away setting of NULL target */
if (!MONO_INS_IS_PCONST_NULL (target)) {
+ MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, target->dreg, 0);
+ MONO_EMIT_NEW_COND_EXC (cfg, EQ, "NullReferenceException");
MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, obj->dreg, MONO_STRUCT_OFFSET (MonoDelegate, target), target->dreg);
if (cfg->gen_write_barriers) {
dreg = alloc_preg (cfg);
prev_args = cfg->args;
prev_arg_types = cfg->arg_types;
prev_inlined_method = cfg->inlined_method;
- cfg->inlined_method = cmethod;
- cfg->ret_var_set = FALSE;
- cfg->inline_depth ++;
+ prev_ret_var_set = cfg->ret_var_set;
prev_real_offset = cfg->real_offset;
prev_cbb_hash = cfg->cbb_hash;
prev_cil_offset_to_bb = cfg->cil_offset_to_bb;
prev_cbb = cfg->cbb;
prev_current_method = cfg->current_method;
prev_generic_context = cfg->generic_context;
- prev_ret_var_set = cfg->ret_var_set;
prev_disable_inline = cfg->disable_inline;
+ cfg->inlined_method = cmethod;
+ cfg->ret_var_set = FALSE;
+ cfg->inline_depth ++;
+
if (ip && *ip == CEE_CALLVIRT && !(cmethod->flags & METHOD_ATTRIBUTE_STATIC))
virtual_ = TRUE;
if (coerce_op) {
if (cfg->cbb->last_ins == sp [0] && sp [0]->opcode == coerce_op) {
if (cfg->verbose_level > 2)
- printf ("Found existing coercing that is enough\n");
+ printf ("Found existing coercing is enough for stloc\n");
} else {
MONO_INST_NEW (cfg, ins, coerce_op);
ins->dreg = alloc_ireg (cfg);
}
}
+static void
+emit_starg_ir (MonoCompile *cfg, MonoInst **sp, int n)
+{
+ MonoInst *ins;
+ guint32 coerce_op = mono_type_to_stloc_coerce (cfg->arg_types [n]);
+
+ if (coerce_op) {
+ if (cfg->cbb->last_ins == sp [0] && sp [0]->opcode == coerce_op) {
+ if (cfg->verbose_level > 2)
+ printf ("Found existing coercing is enough for starg\n");
+ } else {
+ MONO_INST_NEW (cfg, ins, coerce_op);
+ ins->dreg = alloc_ireg (cfg);
+ ins->sreg1 = sp [0]->dreg;
+ ins->type = STACK_I4;
+ ins->klass = mono_class_from_mono_type (cfg->arg_types [n]);
+ MONO_ADD_INS (cfg->cbb, ins);
+ *sp = mono_decompose_opcode (cfg, ins);
+ }
+ }
+
+ EMIT_NEW_ARGSTORE (cfg, ins, n, *sp);
+}
+
/*
* ldloca inhibits many optimizations so try to get rid of it in common
* cases.
seq_points = FALSE;
}
- if (cfg->gen_sdb_seq_points && cfg->method == method) {
+ if (cfg->method == method)
+ cfg->coverage_info = mono_profiler_coverage_alloc (cfg->method, header->code_size);
+
+ if ((cfg->gen_sdb_seq_points && cfg->method == method) || cfg->coverage_info) {
minfo = mono_debug_lookup_method (method);
if (minfo) {
MonoSymSeqPoint *sps;
cfg->dont_inline = g_list_prepend (cfg->dont_inline, method);
if (cfg->method == method) {
-
- cfg->coverage_info = mono_profiler_coverage_alloc (cfg->method, header->code_size);
-
/* ENTRY BLOCK */
NEW_BBLOCK (cfg, start_bblock);
cfg->bb_entry = start_bblock;
if (sym_seq_points)
mono_bitset_set_fast (seq_point_set_locs, ip - header->code);
- }
-
- cfg->cbb->real_offset = cfg->real_offset;
- if ((cfg->method == method) && cfg->coverage_info) {
- guint32 cil_offset = ip - header->code;
- gpointer counter = &cfg->coverage_info->data [cil_offset].count;
- cfg->coverage_info->data [cil_offset].cil_code = ip;
+ if ((cfg->method == method) && cfg->coverage_info) {
+ guint32 cil_offset = ip - header->code;
+ gpointer counter = &cfg->coverage_info->data [cil_offset].count;
+ cfg->coverage_info->data [cil_offset].cil_code = ip;
- if (mono_arch_opcode_supported (OP_ATOMIC_ADD_I4)) {
- MonoInst *one_ins, *load_ins;
+ if (mono_arch_opcode_supported (OP_ATOMIC_ADD_I4)) {
+ MonoInst *one_ins, *load_ins;
- EMIT_NEW_PCONST (cfg, load_ins, counter);
- EMIT_NEW_ICONST (cfg, one_ins, 1);
- MONO_INST_NEW (cfg, ins, OP_ATOMIC_ADD_I4);
- ins->dreg = mono_alloc_ireg (cfg);
- ins->inst_basereg = load_ins->dreg;
- ins->inst_offset = 0;
- ins->sreg2 = one_ins->dreg;
- ins->type = STACK_I4;
- MONO_ADD_INS (cfg->cbb, ins);
- } else {
- EMIT_NEW_PCONST (cfg, ins, counter);
- MONO_EMIT_NEW_STORE_MEMBASE_IMM (cfg, OP_STORE_MEMBASE_IMM, ins->dreg, 0, 1);
+ EMIT_NEW_PCONST (cfg, load_ins, counter);
+ EMIT_NEW_ICONST (cfg, one_ins, 1);
+ MONO_INST_NEW (cfg, ins, OP_ATOMIC_ADD_I4);
+ ins->dreg = mono_alloc_ireg (cfg);
+ ins->inst_basereg = load_ins->dreg;
+ ins->inst_offset = 0;
+ ins->sreg2 = one_ins->dreg;
+ ins->type = STACK_I4;
+ MONO_ADD_INS (cfg->cbb, ins);
+ } else {
+ EMIT_NEW_PCONST (cfg, ins, counter);
+ MONO_EMIT_NEW_STORE_MEMBASE_IMM (cfg, OP_STORE_MEMBASE_IMM, ins->dreg, 0, 1);
+ }
}
}
+ cfg->cbb->real_offset = cfg->real_offset;
+
if (cfg->verbose_level > 3)
printf ("converting (in B%d: stack: %d) %s", cfg->cbb->block_num, (int)(sp - stack_start), mono_disasm_code_one (NULL, method, ip, NULL));
CHECK_ARG (n);
if (!dont_verify_stloc && target_type_is_incompatible (cfg, param_types [ip [1]], *sp))
UNVERIFIED;
- EMIT_NEW_ARGSTORE (cfg, ins, n, *sp);
+ emit_starg_ir (cfg, sp, n);
ip += 2;
break;
case CEE_LDLOC_S:
}
for (i = 0; i < n; ++i)
EMIT_NEW_ARGSTORE (cfg, ins, i, sp [i]);
+
+ mini_profiler_emit_tail_call (cfg, cmethod);
+
MONO_INST_NEW (cfg, ins, OP_BR);
MONO_ADD_INS (cfg->cbb, ins);
tblock = start_bblock->out_bb [0];
if (sp != stack_start)
UNVERIFIED;
+ mini_profiler_emit_leave (cfg, sp [0]);
+
MONO_INST_NEW (cfg, ins, OP_BR);
ins->inst_target_bb = end_bblock;
MONO_ADD_INS (cfg->cbb, ins);
cfg->dyn_call_var->flags |= MONO_INST_VOLATILE;
}
- /* Has to use a call inst since it local regalloc expects it */
+ /* Has to use a call inst since local regalloc expects it */
MONO_INST_NEW_CALL (cfg, call, OP_DYN_CALL);
ins = (MonoInst*)call;
sp -= 2;
MONO_ADD_INS (cfg->cbb, ins);
cfg->param_area = MAX (cfg->param_area, cfg->backend->dyn_call_param_area);
+ /* OP_DYN_CALL might need to allocate a dynamically sized param area */
+ cfg->flags |= MONO_CFG_HAS_ALLOCA;
ip += 2;
inline_costs += 10 * num_calls++;
CHECK_ARG (n);
if (!dont_verify_stloc && target_type_is_incompatible (cfg, param_types [n], *sp))
UNVERIFIED;
- EMIT_NEW_ARGSTORE (cfg, ins, n, *sp);
+ emit_starg_ir (cfg, sp, n);
ip += 4;
break;
case CEE_LDLOC: