Merge pull request #5439 from alexrp/master
authorAlex Rønne Petersen <alex@alexrp.com>
Thu, 24 Aug 2017 17:21:47 +0000 (19:21 +0200)
committerGitHub <noreply@github.com>
Thu, 24 Aug 2017 17:21:47 +0000 (19:21 +0200)
[profiler] Fix some stack imbalance issues due to missing method leave events.

1  2 
mono/mini/method-to-ir.c

diff --combined mono/mini/method-to-ir.c
index 2c30d87a59f34b5949e339e963a638bf63fe324b,104df90ad0f418f99f369a69af2442111fe7006e..442ec3c0a5c9005eab5da957140d8c8851189215
@@@ -3972,8 -3972,6 +3972,8 @@@ handle_delegate_ctor (MonoCompile *cfg
        /* 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);
@@@ -6609,78 -6607,10 +6609,78 @@@ set_exception_type_from_invalid_il (Mon
        cfg->headers_to_free = g_slist_prepend_mempool (cfg->mempool, cfg->headers_to_free, header);
  }
  
 +static guint32
 +mono_type_to_stloc_coerce (MonoType *type)
 +{
 +      if (type->byref)
 +              return 0;
 +
 +      type = mini_get_underlying_type (type);
 +handle_enum:
 +      switch (type->type) {
 +      case MONO_TYPE_I1:
 +              return OP_ICONV_TO_I1;
 +      case MONO_TYPE_U1:
 +              return OP_ICONV_TO_U1;
 +      case MONO_TYPE_I2:
 +              return OP_ICONV_TO_I2;
 +      case MONO_TYPE_U2:
 +              return OP_ICONV_TO_U2;
 +      case MONO_TYPE_I4:
 +      case MONO_TYPE_U4:
 +      case MONO_TYPE_I:
 +      case MONO_TYPE_U:
 +      case MONO_TYPE_PTR:
 +      case MONO_TYPE_FNPTR:
 +      case MONO_TYPE_CLASS:
 +      case MONO_TYPE_STRING:
 +      case MONO_TYPE_OBJECT:
 +      case MONO_TYPE_SZARRAY:
 +      case MONO_TYPE_ARRAY:
 +      case MONO_TYPE_I8:
 +      case MONO_TYPE_U8:
 +      case MONO_TYPE_R4:
 +      case MONO_TYPE_R8:
 +      case MONO_TYPE_TYPEDBYREF:
 +      case MONO_TYPE_GENERICINST:
 +              return 0;
 +      case MONO_TYPE_VALUETYPE:
 +              if (type->data.klass->enumtype) {
 +                      type = mono_class_enum_basetype (type->data.klass);
 +                      goto handle_enum;
 +              }
 +              return 0;
 +      case MONO_TYPE_VAR:
 +      case MONO_TYPE_MVAR: //TODO I believe we don't need to handle gsharedvt as there won't be match and, for example, u1 is not covariant to u32
 +              return 0;
 +      default:
 +              g_error ("unknown type 0x%02x in mono_type_to_stloc_coerce", type->type);
 +      }
 +      return -1;
 +}
 +
  static void
  emit_stloc_ir (MonoCompile *cfg, MonoInst **sp, MonoMethodHeader *header, int n)
  {
        MonoInst *ins;
 +      guint32 coerce_op = mono_type_to_stloc_coerce (header->locals [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 stloc\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 (header->locals [n]);
 +                      MONO_ADD_INS (cfg->cbb, ins);
 +                      *sp = mono_decompose_opcode (cfg, ins);
 +              }
 +      }
 +
 +
        guint32 opcode = mono_type_to_regmove (cfg, header->locals [n]);
        if ((opcode == OP_MOVE) && cfg->cbb->last_ins == sp [0]  &&
                        ((sp [0]->opcode == OP_ICONST) || (sp [0]->opcode == OP_I8CONST))) {
        }
  }
  
 +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.
@@@ -7892,7 -7798,7 +7892,7 @@@ mono_method_to_ir (MonoCompile *cfg, Mo
                        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);
                                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: