[profiler] Implement call context introspection for enter/leave events.
[mono.git] / mono / mini / method-to-ir.c
index 5ce249f7f43d86e8a9ef71088b08702322186729..84c019460517374d6282b9245232d5c246680b22 100644 (file)
@@ -1264,7 +1264,7 @@ mono_get_domainvar (MonoCompile *cfg)
 MonoInst *
 mono_get_got_var (MonoCompile *cfg)
 {
-       if (!cfg->compile_aot || !cfg->backend->need_got_var)
+       if (!cfg->compile_aot || !cfg->backend->need_got_var || cfg->llvm_only)
                return NULL;
        if (!cfg->got_var) {
                cfg->got_var = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_LOCAL);
@@ -1764,24 +1764,6 @@ emit_pop_lmf (MonoCompile *cfg)
        EMIT_NEW_STORE_MEMBASE (cfg, ins, OP_STORE_MEMBASE_REG, lmf_addr_reg, 0, prev_lmf_reg);
 }
 
-static void
-emit_instrumentation_call (MonoCompile *cfg, void *func)
-{
-       MonoInst *iargs [1];
-
-       /*
-        * Avoid instrumenting inlined methods since it can
-        * distort profiling results.
-        */
-       if (cfg->method != cfg->current_method)
-               return;
-
-       if (cfg->prof_options & MONO_PROFILE_ENTER_LEAVE) {
-               EMIT_NEW_METHODCONST (cfg, iargs [0], cfg->method);
-               mono_emit_jit_icall (cfg, func, iargs);
-       }
-}
-
 static int
 ret_type_to_call_opcode (MonoCompile *cfg, MonoType *type, int calli, int virt)
 {
@@ -2247,7 +2229,7 @@ mono_emit_call_args (MonoCompile *cfg, MonoMethodSignature *sig,
                tail = FALSE;
 
        if (tail) {
-               emit_instrumentation_call (cfg, mono_profiler_method_leave);
+               mini_profiler_emit_instrumentation_call (cfg, mono_profiler_raise_method_leave, FALSE, NULL, NULL);
 
                MONO_INST_NEW_CALL (cfg, call, OP_TAILCALL);
        } else
@@ -4362,6 +4344,9 @@ mono_method_check_inlining (MonoCompile *cfg, MonoMethod *method)
        if (g_list_find (cfg->dont_inline, method))
                return FALSE;
 
+       if (mono_profiler_get_call_instrumentation_flags (method))
+               return FALSE;
+
        return TRUE;
 }
 
@@ -4571,54 +4556,6 @@ mini_emit_ldelema_ins (MonoCompile *cfg, MonoMethod *cmethod, MonoInst **sp, uns
        return addr;
 }
 
-static MonoBreakPolicy
-always_insert_breakpoint (MonoMethod *method)
-{
-       return MONO_BREAK_POLICY_ALWAYS;
-}
-
-static MonoBreakPolicyFunc break_policy_func = always_insert_breakpoint;
-
-/**
- * mono_set_break_policy:
- * \param policy_callback the new callback function
- *
- * Allow embedders to decide wherther to actually obey breakpoint instructions
- * (both break IL instructions and \c Debugger.Break method calls), for example
- * to not allow an app to be aborted by a perfectly valid IL opcode when executing
- * untrusted or semi-trusted code.
- *
- * \p policy_callback will be called every time a break point instruction needs to
- * be inserted with the method argument being the method that calls \c Debugger.Break
- * or has the IL \c break instruction. The callback should return \c MONO_BREAK_POLICY_NEVER
- * if it wants the breakpoint to not be effective in the given method.
- * \c MONO_BREAK_POLICY_ALWAYS is the default.
- */
-void
-mono_set_break_policy (MonoBreakPolicyFunc policy_callback)
-{
-       if (policy_callback)
-               break_policy_func = policy_callback;
-       else
-               break_policy_func = always_insert_breakpoint;
-}
-
-static gboolean
-should_insert_brekpoint (MonoMethod *method) {
-       switch (break_policy_func (method)) {
-       case MONO_BREAK_POLICY_ALWAYS:
-               return TRUE;
-       case MONO_BREAK_POLICY_NEVER:
-               return FALSE;
-       case MONO_BREAK_POLICY_ON_DBG:
-               g_warning ("mdb no longer supported");
-               return FALSE;
-       default:
-               g_warning ("Incorrect value returned from break policy callback");
-               return FALSE;
-       }
-}
-
 /* optimize the simple GetGenericValueImpl/SetGenericValueImpl generic icalls */
 static MonoInst*
 emit_array_generic_access (MonoCompile *cfg, MonoMethodSignature *fsig, MonoInst **args, int is_set)
@@ -4922,6 +4859,31 @@ mini_emit_inst_for_sharable_method (MonoCompile *cfg, MonoMethod *cmethod, MonoM
        return NULL;
 }
 
+
+static gboolean
+mono_type_is_native_blittable (MonoType *t)
+{
+       if (MONO_TYPE_IS_REFERENCE (t))
+               return FALSE;
+
+       if (MONO_TYPE_IS_PRIMITIVE_SCALAR (t))
+               return TRUE;
+
+       MonoClass *klass = mono_class_from_mono_type (t);
+
+       //MonoClass::blitable depends on mono_class_setup_fields being done.
+       mono_class_setup_fields (klass);
+       if (!klass->blittable)
+               return FALSE;
+
+       // If the native marshal size is different we can't convert PtrToStructure to a type load
+       if (mono_class_native_size (klass, NULL) != mono_class_value_size (klass, NULL))
+               return FALSE;
+
+       return TRUE;
+}
+
+
 static MonoInst*
 mini_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args)
 {
@@ -5078,11 +5040,15 @@ mini_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSign
                        g_assert (ctx);
                        g_assert (ctx->method_inst);
                        g_assert (ctx->method_inst->type_argc == 1);
-                       MonoType *t = mini_get_underlying_type (ctx->method_inst->type_argv [0]);
-                       MonoClass *klass = mono_class_from_mono_type (t);
+                       MonoType *arg_type = ctx->method_inst->type_argv [0];
+                       MonoType *t;
+                       MonoClass *klass;
 
                        ins = NULL;
 
+                       /* Resolve the argument class as possible so we can handle common cases fast */
+                       t = mini_get_underlying_type (arg_type);
+                       klass = mono_class_from_mono_type (t);
                        mono_class_init (klass);
                        if (MONO_TYPE_IS_REFERENCE (t))
                                EMIT_NEW_ICONST (cfg, ins, 1);
@@ -5095,10 +5061,12 @@ mini_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSign
                        else {
                                g_assert (cfg->gshared);
 
-                               int context_used = mini_class_check_context_used (cfg, klass);
+                               /* Have to use the original argument class here */
+                               MonoClass *arg_class = mono_class_from_mono_type (arg_type);
+                               int context_used = mini_class_check_context_used (cfg, arg_class);
 
                                /* This returns 1 or 2 */
-                               MonoInst *info = mini_emit_get_rgctx_klass (cfg, context_used, klass,   MONO_RGCTX_INFO_CLASS_IS_REF_OR_CONTAINS_REFS);
+                               MonoInst *info = mini_emit_get_rgctx_klass (cfg, context_used, arg_class, MONO_RGCTX_INFO_CLASS_IS_REF_OR_CONTAINS_REFS);
                                int dreg = alloc_ireg (cfg);
                                EMIT_NEW_BIALU_IMM (cfg, ins, OP_ISUB_IMM, dreg, info->dreg, 1);
                        }
@@ -5738,7 +5706,7 @@ mini_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSign
                           (strcmp (cmethod->klass->name_space, "System.Diagnostics") == 0) &&
                           (strcmp (cmethod->klass->name, "Debugger") == 0)) {
                if (!strcmp (cmethod->name, "Break") && fsig->param_count == 0) {
-                       if (should_insert_brekpoint (cfg->method)) {
+                       if (mini_should_insert_breakpoint (cfg->method)) {
                                ins = mono_emit_jit_icall (cfg, mono_debugger_agent_user_break, NULL);
                        } else {
                                MONO_INST_NEW (cfg, ins, OP_NOP);
@@ -5837,6 +5805,20 @@ mini_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSign
                        MONO_ADD_INS (cfg->cbb, ins);
                        return ins;
                }
+       } else if (cmethod->klass->image == mono_defaults.corlib &&
+                       (strcmp (cmethod->klass->name_space, "System.Runtime.InteropServices") == 0) &&
+                       (strcmp (cmethod->klass->name, "Marshal") == 0)) {
+               //Convert Marshal.PtrToStructure<T> of blittable T to direct loads
+               if (strcmp (cmethod->name, "PtrToStructure") == 0 &&
+                               cmethod->is_inflated &&
+                               fsig->param_count == 1 &&
+                               !mini_method_check_context_used (cfg, cmethod)) {
+
+                       MonoGenericContext *method_context = mono_method_get_context (cmethod);
+                       MonoType *arg0 = method_context->method_inst->type_argv [0];
+                       if (mono_type_is_native_blittable (arg0))
+                               return mini_emit_memory_load (cfg, arg0, args [0], 0, 0);
+               }
        }
 
 #ifdef MONO_ARCH_SIMD_INTRINSICS
@@ -5870,7 +5852,7 @@ mini_redirect_call (MonoCompile *cfg, MonoMethod *method,
 {
        if (method->klass == mono_defaults.string_class) {
                /* managed string allocation support */
-               if (strcmp (method->name, "InternalAllocateStr") == 0 && !(mono_profiler_events & MONO_PROFILE_ALLOCATIONS) && !(cfg->opt & MONO_OPT_SHARED)) {
+               if (strcmp (method->name, "InternalAllocateStr") == 0 && !(cfg->opt & MONO_OPT_SHARED)) {
                        MonoInst *iargs [2];
                        MonoVTable *vtable = mono_class_vtable (cfg->domain, method->klass);
                        MonoMethod *managed_alloc = NULL;
@@ -6454,27 +6436,6 @@ mini_get_method (MonoCompile *cfg, MonoMethod *m, guint32 token, MonoClass *klas
        return method;
 }
 
-MonoClass*
-mini_get_class (MonoMethod *method, guint32 token, MonoGenericContext *context)
-{
-       MonoError error;
-       MonoClass *klass;
-
-       if (method->wrapper_type != MONO_WRAPPER_NONE) {
-               klass = (MonoClass *)mono_method_get_wrapper_data (method, token);
-               if (context) {
-                       klass = mono_class_inflate_generic_class_checked (klass, context, &error);
-                       mono_error_cleanup (&error); /* FIXME don't swallow the error */
-               }
-       } else {
-               klass = mono_class_get_and_inflate_typespec_checked (method->klass->image, token, context, &error);
-               mono_error_cleanup (&error); /* FIXME don't swallow the error */
-       }
-       if (klass)
-               mono_class_init (klass);
-       return klass;
-}
-
 static inline MonoMethodSignature*
 mini_get_signature (MonoMethod *method, guint32 token, MonoGenericContext *context, MonoError *error)
 {
@@ -7334,8 +7295,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
        cfg->dont_inline = g_list_prepend (cfg->dont_inline, method);
        if (cfg->method == method) {
 
-               if (cfg->prof_options & MONO_PROFILE_INS_COVERAGE)
-                       cfg->coverage_info = mono_profiler_coverage_alloc (cfg->method, header->code_size);
+               cfg->coverage_info = mono_profiler_coverage_alloc (cfg->method, header->code_size);
 
                /* ENTRY BLOCK */
                NEW_BBLOCK (cfg, start_bblock);
@@ -7370,6 +7330,8 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        tblock->real_offset = clause->handler_offset;
                        tblock->flags |= BB_EXCEPTION_HANDLER;
 
+                       if (clause->flags == MONO_EXCEPTION_CLAUSE_FINALLY)
+                               mono_create_exvar_for_offset (cfg, clause->handler_offset);
                        /*
                         * Linking the try block with the EH block hinders inlining as we won't be able to 
                         * merge the bblocks from inlining and produce an artificial hole for no good reason.
@@ -7731,18 +7693,25 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
 
                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;
 
-                       /* TODO: Use an increment here */
-#if defined(TARGET_X86)
-                       MONO_INST_NEW (cfg, ins, OP_STORE_MEM_IMM);
-                       ins->inst_p0 = &(cfg->coverage_info->data [cil_offset].count);
-                       ins->inst_imm = 1;
-                       MONO_ADD_INS (cfg->cbb, ins);
-#else
-                       EMIT_NEW_PCONST (cfg, ins, &(cfg->coverage_info->data [cil_offset].count));
-                       MONO_EMIT_NEW_STORE_MEMBASE_IMM (cfg, OP_STORE_MEMBASE_IMM, ins->dreg, 0, 1);
-#endif
+                       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);
+                       }
                }
 
                if (cfg->verbose_level > 3)
@@ -7766,7 +7735,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        MONO_ADD_INS (cfg->cbb, ins);
                        break;
                case CEE_BREAK:
-                       if (should_insert_brekpoint (cfg->method)) {
+                       if (mini_should_insert_breakpoint (cfg->method)) {
                                ins = mono_emit_jit_icall (cfg, mono_debugger_agent_user_break, NULL);
                        } else {
                                MONO_INST_NEW (cfg, ins, OP_NOP);
@@ -7846,7 +7815,12 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        CHECK_STACK_OVF (1);
                        n = ip [1];
                        CHECK_LOCAL (n);
-                       EMIT_NEW_LOCLOAD (cfg, ins, n);
+                       if ((ip [2] == CEE_LDFLD) && ip_in_bb (cfg, cfg->cbb, ip + 2) && MONO_TYPE_ISSTRUCT (header->locals [n])) {
+                               /* Avoid loading a struct just to load one of its fields */
+                               EMIT_NEW_LOCLOADA (cfg, ins, n);
+                       } else {
+                               EMIT_NEW_LOCLOAD (cfg, ins, n);
+                       }
                        *sp++ = ins;
                        ip += 2;
                        break;
@@ -8056,7 +8030,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        if (cfg->gshared && mono_method_check_context_used (cmethod))
                                GENERIC_SHARING_FAILURE (CEE_JMP);
 
-                       emit_instrumentation_call (cfg, mono_profiler_method_leave);
+                       mini_profiler_emit_instrumentation_call (cfg, mono_profiler_raise_method_leave, FALSE, NULL, NULL);
 
                        fsig = mono_method_signature (cmethod);
                        n = fsig->param_count + fsig->hasthis;
@@ -8998,7 +8972,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                        /* Handle tail calls similarly to normal calls */
                                        tail_call = TRUE;
                                } else {
-                                       emit_instrumentation_call (cfg, mono_profiler_method_leave);
+                                       mini_profiler_emit_instrumentation_call (cfg, mono_profiler_raise_method_leave, FALSE, NULL, NULL);
 
                                        MONO_INST_NEW_CALL (cfg, call, OP_JMP);
                                        call->tail_call = TRUE;
@@ -9109,6 +9083,8 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        break;
                }
                case CEE_RET:
+                       mini_profiler_emit_instrumentation_call (cfg, mono_profiler_raise_method_leave, FALSE, sp - 1, sig->ret);
+
                        if (cfg->method != method) {
                                /* return from inlined method */
                                /* 
@@ -9132,8 +9108,6 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                        cfg->ret_var_set = TRUE;
                                } 
                        } else {
-                               emit_instrumentation_call (cfg, mono_profiler_method_leave);
-
                                if (cfg->lmf_var && cfg->cbb->in_count && !cfg->llvm_only)
                                        emit_pop_lmf (cfg);
 
@@ -11421,18 +11395,35 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
 
                        if ((handlers = mono_find_final_block (cfg, ip, target, MONO_EXCEPTION_CLAUSE_FINALLY))) {
                                GList *tmp;
-                               MonoExceptionClause *clause;
 
                                for (tmp = handlers; tmp; tmp = tmp->next) {
-                                       clause = (MonoExceptionClause *)tmp->data;
+                                       MonoExceptionClause *clause = (MonoExceptionClause *)tmp->data;
+                                       MonoInst *abort_exc = (MonoInst *)mono_find_exvar_for_offset (cfg, clause->handler_offset);
+                                       MonoBasicBlock *dont_throw;
+
                                        tblock = cfg->cil_offset_to_bb [clause->handler_offset];
                                        g_assert (tblock);
                                        link_bblock (cfg, cfg->cbb, tblock);
+
+                                       MONO_EMIT_NEW_PCONST (cfg, abort_exc->dreg, 0);
+
                                        MONO_INST_NEW (cfg, ins, OP_CALL_HANDLER);
                                        ins->inst_target_bb = tblock;
                                        ins->inst_eh_block = clause;
                                        MONO_ADD_INS (cfg->cbb, ins);
                                        cfg->cbb->has_call_handler = 1;
+
+                                       /* Throw exception if exvar is set */
+                                       /* FIXME Do we need this for calls from catch/filter ? */
+                                       NEW_BBLOCK (cfg, dont_throw);
+                                       MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, abort_exc->dreg, 0);
+                                       MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_PBEQ, dont_throw);
+                                       mono_emit_jit_icall (cfg, mono_thread_self_abort, NULL);
+                                       cfg->cbb->clause_hole = clause;
+
+                                       MONO_START_BB (cfg, dont_throw);
+                                       cfg->cbb->clause_hole = clause;
+
                                        if (COMPILE_LLVM (cfg)) {
                                                MonoBasicBlock *target_bb;
 
@@ -11487,7 +11478,20 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                CHECK_STACK (info->sig->param_count);
                                sp -= info->sig->param_count;
 
-                               ins = mono_emit_jit_icall (cfg, info->func, sp);
+                               if (cfg->compile_aot && !strcmp (info->name, "mono_threads_attach_coop")) {
+                                       MonoInst *addr;
+
+                                       /*
+                                        * This is called on unattached threads, so it cannot go through the trampoline
+                                        * infrastructure. Use an indirect call through a got slot initialized at load time
+                                        * instead.
+                                        */
+                                       EMIT_NEW_AOTCONST (cfg, addr, MONO_PATCH_INFO_JIT_ICALL_ADDR_NOCALL, (char*)info->name);
+                                       ins = mini_emit_calli (cfg, info->sig, sp, addr, NULL, NULL);
+                               } else {
+                                       ins = mono_emit_jit_icall (cfg, info->func, sp);
+                               }
+
                                if (!MONO_TYPE_IS_VOID (info->sig->ret))
                                        *sp++ = ins;
 
@@ -11499,22 +11503,29 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        case CEE_MONO_LDPTR_CARD_TABLE:
                        case CEE_MONO_LDPTR_NURSERY_START:
                        case CEE_MONO_LDPTR_NURSERY_BITS:
-                       case CEE_MONO_LDPTR_INT_REQ_FLAG: {
+                       case CEE_MONO_LDPTR_INT_REQ_FLAG:
+                       case CEE_MONO_LDPTR_PROFILER_ALLOCATION_COUNT: {
                                CHECK_STACK_OVF (1);
 
                                switch (ip [1]) {
-                                       case CEE_MONO_LDPTR_CARD_TABLE:
-                                               ins = mini_emit_runtime_constant (cfg, MONO_PATCH_INFO_GC_CARD_TABLE_ADDR, NULL);
-                                               break;
-                                       case CEE_MONO_LDPTR_NURSERY_START:
-                                               ins = mini_emit_runtime_constant (cfg, MONO_PATCH_INFO_GC_NURSERY_START, NULL);
-                                               break;
-                                       case CEE_MONO_LDPTR_NURSERY_BITS:
-                                               ins = mini_emit_runtime_constant (cfg, MONO_PATCH_INFO_GC_NURSERY_BITS, NULL);
-                                               break;
-                                       case CEE_MONO_LDPTR_INT_REQ_FLAG:
-                                               ins = mini_emit_runtime_constant (cfg, MONO_PATCH_INFO_INTERRUPTION_REQUEST_FLAG, NULL);
-                                               break;
+                               case CEE_MONO_LDPTR_CARD_TABLE:
+                                       ins = mini_emit_runtime_constant (cfg, MONO_PATCH_INFO_GC_CARD_TABLE_ADDR, NULL);
+                                       break;
+                               case CEE_MONO_LDPTR_NURSERY_START:
+                                       ins = mini_emit_runtime_constant (cfg, MONO_PATCH_INFO_GC_NURSERY_START, NULL);
+                                       break;
+                               case CEE_MONO_LDPTR_NURSERY_BITS:
+                                       ins = mini_emit_runtime_constant (cfg, MONO_PATCH_INFO_GC_NURSERY_BITS, NULL);
+                                       break;
+                               case CEE_MONO_LDPTR_INT_REQ_FLAG:
+                                       ins = mini_emit_runtime_constant (cfg, MONO_PATCH_INFO_INTERRUPTION_REQUEST_FLAG, NULL);
+                                       break;
+                               case CEE_MONO_LDPTR_PROFILER_ALLOCATION_COUNT:
+                                       ins = mini_emit_runtime_constant (cfg, MONO_PATCH_INFO_PROFILER_ALLOCATION_COUNT, NULL);
+                                       break;
+                               default:
+                                       g_assert_not_reached ();
+                                       break;
                                }
 
                                *sp++ = ins;
@@ -11779,7 +11790,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                MonoInst *ad_ins, *jit_tls_ins;
                                MonoBasicBlock *next_bb = NULL, *call_bb = NULL;
 
-                               g_assert (!mono_threads_is_coop_enabled ());
+                               g_assert (!mono_threads_is_blocking_transition_enabled ());
 
                                cfg->orig_domain_var = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_LOCAL);
 
@@ -12285,7 +12296,12 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                CHECK_OPSIZE (4);
                                n = read16 (ip + 2);
                                CHECK_LOCAL (n);
-                               EMIT_NEW_LOCLOAD (cfg, ins, n);
+                               if ((ip [4] == CEE_LDFLD) && ip_in_bb (cfg, cfg->cbb, ip + 4) && header->locals [n]->type == MONO_TYPE_VALUETYPE) {
+                                       /* Avoid loading a struct just to load one of its fields */
+                                       EMIT_NEW_LOCLOADA (cfg, ins, n);
+                               } else {
+                                       EMIT_NEW_LOCLOAD (cfg, ins, n);
+                               }
                                *sp++ = ins;
                                ip += 4;
                                break;
@@ -12619,7 +12635,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
        }
 
        cfg->cbb = init_localsbb;
-       emit_instrumentation_call (cfg, mono_profiler_method_enter);
+       mini_profiler_emit_instrumentation_call (cfg, mono_profiler_raise_method_enter, TRUE, NULL, NULL);
 
        if (seq_points) {
                MonoBasicBlock *bb;
@@ -14196,11 +14212,4 @@ NOTES
   the values on the stack before emitting the last instruction of the bb.
 */
 
-#else /* !DISABLE_JIT */
-
-void
-mono_set_break_policy (MonoBreakPolicyFunc policy_callback)
-{
-}
-
 #endif /* !DISABLE_JIT */