+static int
+inline_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoBasicBlock *bblock, MonoInst **sp,
+ guchar *ip, guint real_offset, GList *dont_inline, MonoBasicBlock **last_b)
+{
+ MonoInst *ins, *rvar = NULL;
+ MonoMethodHeader *cheader;
+ MonoBasicBlock *ebblock, *sbblock;
+ int i, costs, new_locals_offset;
+
+ if (cfg->verbose_level > 2)
+ g_print ("INLINE START %p %s\n", cmethod, mono_method_full_name (cmethod, TRUE));
+
+ cheader = ((MonoMethodNormal *)cmethod)->header;
+
+ if (!cmethod->inline_info) {
+ mono_jit_stats.inlineable_methods++;
+ cmethod->inline_info = 1;
+ }
+ /* allocate space to store the return value */
+ if (!MONO_TYPE_IS_VOID (fsig->ret)) {
+ rvar = mono_compile_create_var (cfg, fsig->ret, OP_LOCAL);
+ }
+
+ /* allocate local variables */
+ new_locals_offset = cfg->num_varinfo;
+ for (i = 0; i < cheader->num_locals; ++i)
+ mono_compile_create_var (cfg, cheader->locals [i], OP_LOCAL);
+
+ /* allocate starte and end blocks */
+ sbblock = NEW_BBLOCK (cfg);
+ sbblock->block_num = cfg->num_bblocks++;
+ sbblock->real_offset = real_offset;
+
+ ebblock = NEW_BBLOCK (cfg);
+ ebblock->block_num = cfg->num_bblocks++;
+ ebblock->real_offset = real_offset;
+
+ costs = mono_method_to_ir (cfg, cmethod, sbblock, ebblock, new_locals_offset, rvar, dont_inline, sp, real_offset, *ip == CEE_CALLVIRT);
+
+ if (costs >= 0 && costs < 60) {
+ if (cfg->verbose_level > 2)
+ g_print ("INLINE END %s\n", mono_method_full_name (cmethod, TRUE));
+
+ mono_jit_stats.inlined_methods++;
+
+ /* always add some code to avoid block split failures */
+ MONO_INST_NEW (cfg, ins, CEE_NOP);
+ MONO_ADD_INS (bblock, ins);
+ ins->cil_code = ip;
+
+ bblock->next_bb = sbblock;
+ link_bblock (cfg, bblock, sbblock);
+
+ if (rvar) {
+ NEW_TEMPLOAD (cfg, ins, rvar->inst_c0);
+ *sp++ = ins;
+ }
+ *last_b = ebblock;
+ return costs + 1;
+ } else {
+ if (cfg->verbose_level > 2)
+ g_print ("INLINE ABORTED %s\n", mono_method_full_name (cmethod, TRUE));
+ }
+ return 0;
+}
+