Merge pull request #637 from LogosBible/enetdown
[mono.git] / mono / mini / method-to-ir.c
index 104c54a7ab62684ada8a2516248144adf491baf0..51b5e52937d2184c2c2cc76757257756d05190ad 100644 (file)
@@ -11,6 +11,9 @@
  */
 
 #include <config.h>
+
+#ifndef DISABLE_JIT
+
 #include <signal.h>
 
 #ifdef HAVE_UNISTD_H
@@ -154,7 +157,7 @@ static MonoMethodSignature *helper_sig_monitor_enter_exit_trampoline_llvm = NULL
 #define FREG 'f'
 #define VREG 'v'
 #define XREG 'x'
-#if SIZEOF_REGISTER == 8
+#if SIZEOF_REGISTER == 8 && SIZEOF_REGISTER == SIZEOF_VOID_P
 #define LREG IREG
 #else
 #define LREG 'l'
@@ -351,12 +354,6 @@ mono_create_helper_signatures (void)
        helper_sig_monitor_enter_exit_trampoline_llvm = mono_create_icall_signature ("void object");
 }
 
-/* 
- * Can't put this at the beginning, since other files reference stuff from this
- * file.
- */
-#ifndef DISABLE_JIT
-
 /*
  * When using gsharedvt, some instatiations might be verifiable, and some might be not. i.e. 
  * foo<T> (int i) { ldarg.0; box T; }
@@ -2416,7 +2413,9 @@ static MonoInst*
 mono_emit_method_call_full (MonoCompile *cfg, MonoMethod *method, MonoMethodSignature *sig,
                                                        MonoInst **args, MonoInst *this, MonoInst *imt_arg, MonoInst *rgctx_arg)
 {
-       gboolean might_be_remote;
+#ifndef DISABLE_REMOTING
+       gboolean might_be_remote = FALSE;
+#endif
        gboolean virtual = this != NULL;
        gboolean enable_for_aot = TRUE;
        int context_used;
@@ -2440,8 +2439,9 @@ mono_emit_method_call_full (MonoCompile *cfg, MonoMethod *method, MonoMethodSign
 
        context_used = mini_method_check_context_used (cfg, method);
 
+#ifndef DISABLE_REMOTING
        might_be_remote = this && sig->hasthis &&
-               (method->klass->marshalbyref || method->klass == mono_defaults.object_class) &&
+               (mono_class_is_marshalbyref (method->klass) || method->klass == mono_defaults.object_class) &&
                !(method->flags & METHOD_ATTRIBUTE_VIRTUAL) && (!MONO_CHECK_THIS (this) || context_used);
 
        if (might_be_remote && context_used) {
@@ -2453,14 +2453,17 @@ mono_emit_method_call_full (MonoCompile *cfg, MonoMethod *method, MonoMethodSign
 
                return mono_emit_calli (cfg, sig, args, addr, NULL, NULL);
        }
+#endif
 
        need_unbox_trampoline = method->klass == mono_defaults.object_class || (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE);
 
        call = mono_emit_call_args (cfg, sig, args, FALSE, virtual, FALSE, rgctx_arg ? TRUE : FALSE, need_unbox_trampoline);
 
+#ifndef DISABLE_REMOTING
        if (might_be_remote)
                call->method = mono_marshal_get_remoting_invoke_with_check (method);
        else
+#endif
                call->method = method;
        call->inst.flags |= MONO_INST_HAS_METHOD;
        call->inst.inst_left = this;
@@ -2504,18 +2507,20 @@ mono_emit_method_call_full (MonoCompile *cfg, MonoMethod *method, MonoMethodSign
                        (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) || 
                         (MONO_METHOD_IS_FINAL (method) &&
                          method->wrapper_type != MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK)) &&
-                       !(method->klass->marshalbyref && context_used)) {
+                       !(mono_class_is_marshalbyref (method->klass) && context_used)) {
                        /* 
                         * the method is not virtual, we just need to ensure this is not null
                         * and then we can call the method directly.
                         */
-                       if (method->klass->marshalbyref || method->klass == mono_defaults.object_class) {
+#ifndef DISABLE_REMOTING
+                       if (mono_class_is_marshalbyref (method->klass) || method->klass == mono_defaults.object_class) {
                                /* 
                                 * The check above ensures method is not gshared, this is needed since
                                 * gshared methods can't have wrappers.
                                 */
                                method = call->method = mono_marshal_get_remoting_invoke_with_check (method);
                        }
+#endif
 
                        if (!method->string_ctor)
                                MONO_EMIT_NEW_CHECK_THIS (cfg, this_reg);
@@ -2892,7 +2897,7 @@ mini_emit_stobj (MonoCompile *cfg, MonoInst *dest, MonoInst *src, MonoClass *kla
                n = mono_class_value_size (klass, &align);
 
        /* if native is true there should be no references in the struct */
-       if (cfg->gen_write_barriers && klass->has_references && !native) {
+       if (cfg->gen_write_barriers && (klass->has_references || size_ins) && !native) {
                /* Avoid barriers when storing to the stack */
                if (!((dest->opcode == OP_ADD_IMM && dest->sreg1 == cfg->frame_reg) ||
                          (dest->opcode == OP_LDADDR))) {
@@ -3534,7 +3539,7 @@ mini_class_has_reference_variant_generic_argument (MonoCompile *cfg, MonoClass *
 }
 
 // FIXME: This doesn't work yet (class libs tests fail?)
-#define is_complex_isinst(klass) (TRUE || (klass->flags & TYPE_ATTRIBUTE_INTERFACE) || klass->rank || mono_class_is_nullable (klass) || klass->marshalbyref || (klass->flags & TYPE_ATTRIBUTE_SEALED) || klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR)
+#define is_complex_isinst(klass) (TRUE || (klass->flags & TYPE_ATTRIBUTE_INTERFACE) || klass->rank || mono_class_is_nullable (klass) || mono_class_is_marshalbyref (klass) || (klass->flags & TYPE_ATTRIBUTE_SEALED) || klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR)
 
 /*
  * Returns NULL and set the cfg exception on error.
@@ -3789,26 +3794,37 @@ handle_cisinst (MonoCompile *cfg, MonoClass *klass, MonoInst *src)
        2) if the object is a proxy whose type cannot be determined */
 
        MonoInst *ins;
+#ifndef DISABLE_REMOTING
        MonoBasicBlock *true_bb, *false_bb, *false2_bb, *end_bb, *no_proxy_bb, *interface_fail_bb;
+#else
+       MonoBasicBlock *true_bb, *false_bb, *end_bb;
+#endif
        int obj_reg = src->dreg;
        int dreg = alloc_ireg (cfg);
        int tmp_reg;
+#ifndef DISABLE_REMOTING
        int klass_reg = alloc_preg (cfg);
+#endif
 
        NEW_BBLOCK (cfg, true_bb);
        NEW_BBLOCK (cfg, false_bb);
-       NEW_BBLOCK (cfg, false2_bb);
        NEW_BBLOCK (cfg, end_bb);
+#ifndef DISABLE_REMOTING
+       NEW_BBLOCK (cfg, false2_bb);
        NEW_BBLOCK (cfg, no_proxy_bb);
+#endif
 
        MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, obj_reg, 0);
        MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_PBEQ, false_bb);
 
        if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
+#ifndef DISABLE_REMOTING
                NEW_BBLOCK (cfg, interface_fail_bb);
+#endif
 
                tmp_reg = alloc_preg (cfg);
                MONO_EMIT_NEW_LOAD_MEMBASE (cfg, tmp_reg, obj_reg, G_STRUCT_OFFSET (MonoObject, vtable));
+#ifndef DISABLE_REMOTING
                mini_emit_iface_cast (cfg, tmp_reg, klass, interface_fail_bb, true_bb);
                MONO_START_BB (cfg, interface_fail_bb);
                MONO_EMIT_NEW_LOAD_MEMBASE (cfg, klass_reg, tmp_reg, G_STRUCT_OFFSET (MonoVTable, klass));
@@ -3819,7 +3835,11 @@ handle_cisinst (MonoCompile *cfg, MonoClass *klass, MonoInst *src)
                MONO_EMIT_NEW_LOAD_MEMBASE (cfg, tmp_reg, obj_reg, G_STRUCT_OFFSET (MonoTransparentProxy, custom_type_info));
                MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, tmp_reg, 0);
                MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_PBNE_UN, false2_bb);                
+#else
+               mini_emit_iface_cast (cfg, tmp_reg, klass, false_bb, true_bb);
+#endif
        } else {
+#ifndef DISABLE_REMOTING
                tmp_reg = alloc_preg (cfg);
                MONO_EMIT_NEW_LOAD_MEMBASE (cfg, tmp_reg, obj_reg, G_STRUCT_OFFSET (MonoObject, vtable));
                MONO_EMIT_NEW_LOAD_MEMBASE (cfg, klass_reg, tmp_reg, G_STRUCT_OFFSET (MonoVTable, klass));
@@ -3840,6 +3860,9 @@ handle_cisinst (MonoCompile *cfg, MonoClass *klass, MonoInst *src)
                MONO_START_BB (cfg, no_proxy_bb);
 
                mini_emit_isninst_cast (cfg, klass_reg, klass, false_bb, true_bb);
+#else
+               g_error ("transparent proxy support is disabled while trying to JIT code that uses it");
+#endif
        }
 
        MONO_START_BB (cfg, false_bb);
@@ -3847,10 +3870,12 @@ handle_cisinst (MonoCompile *cfg, MonoClass *klass, MonoInst *src)
        MONO_EMIT_NEW_ICONST (cfg, dreg, 1);
        MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_BR, end_bb);
 
+#ifndef DISABLE_REMOTING
        MONO_START_BB (cfg, false2_bb);
 
        MONO_EMIT_NEW_ICONST (cfg, dreg, 2);
        MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_BR, end_bb);
+#endif
 
        MONO_START_BB (cfg, true_bb);
 
@@ -3875,13 +3900,20 @@ handle_ccastclass (MonoCompile *cfg, MonoClass *klass, MonoInst *src)
        an InvalidCastException exception is thrown otherwhise*/
        
        MonoInst *ins;
+#ifndef DISABLE_REMOTING
        MonoBasicBlock *end_bb, *ok_result_bb, *no_proxy_bb, *interface_fail_bb, *fail_1_bb;
+#else
+       MonoBasicBlock *ok_result_bb;
+#endif
        int obj_reg = src->dreg;
        int dreg = alloc_ireg (cfg);
        int tmp_reg = alloc_preg (cfg);
-       int klass_reg = alloc_preg (cfg);
 
+#ifndef DISABLE_REMOTING
+       int klass_reg = alloc_preg (cfg);
        NEW_BBLOCK (cfg, end_bb);
+#endif
+
        NEW_BBLOCK (cfg, ok_result_bb);
 
        MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, obj_reg, 0);
@@ -3890,6 +3922,7 @@ handle_ccastclass (MonoCompile *cfg, MonoClass *klass, MonoInst *src)
        save_cast_details (cfg, klass, obj_reg);
 
        if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
+#ifndef DISABLE_REMOTING
                NEW_BBLOCK (cfg, interface_fail_bb);
        
                MONO_EMIT_NEW_LOAD_MEMBASE (cfg, tmp_reg, obj_reg, G_STRUCT_OFFSET (MonoObject, vtable));
@@ -3906,8 +3939,13 @@ handle_ccastclass (MonoCompile *cfg, MonoClass *klass, MonoInst *src)
                
                MONO_EMIT_NEW_ICONST (cfg, dreg, 1);
                MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_BR, end_bb);
-               
+#else
+               MONO_EMIT_NEW_LOAD_MEMBASE (cfg, tmp_reg, obj_reg, G_STRUCT_OFFSET (MonoObject, vtable));
+               mini_emit_iface_cast (cfg, tmp_reg, klass, NULL, NULL);
+               MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_BR, ok_result_bb);
+#endif
        } else {
+#ifndef DISABLE_REMOTING
                NEW_BBLOCK (cfg, no_proxy_bb);
 
                MONO_EMIT_NEW_LOAD_MEMBASE (cfg, tmp_reg, obj_reg, G_STRUCT_OFFSET (MonoObject, vtable));
@@ -3935,13 +3973,18 @@ handle_ccastclass (MonoCompile *cfg, MonoClass *klass, MonoInst *src)
                MONO_START_BB (cfg, no_proxy_bb);
 
                mini_emit_castclass (cfg, obj_reg, klass_reg, klass, ok_result_bb);
+#else
+               g_error ("Transparent proxy support is disabled while trying to JIT code that uses it");
+#endif
        }
 
        MONO_START_BB (cfg, ok_result_bb);
 
        MONO_EMIT_NEW_ICONST (cfg, dreg, 0);
 
+#ifndef DISABLE_REMOTING
        MONO_START_BB (cfg, end_bb);
+#endif
 
        /* FIXME: */
        MONO_INST_NEW (cfg, ins, OP_ICONST);
@@ -4115,7 +4158,7 @@ mono_method_check_inlining (MonoCompile *cfg, MonoMethod *method)
        /*runtime, icall and pinvoke are checked by summary call*/
        if ((method->iflags & METHOD_IMPL_ATTRIBUTE_NOINLINING) ||
            (method->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED) ||
-           (method->klass->marshalbyref) ||
+           (mono_class_is_marshalbyref (method->klass)) ||
            header.has_clauses)
                return FALSE;
 
@@ -4178,7 +4221,7 @@ mono_method_check_inlining (MonoCompile *cfg, MonoMethod *method)
         * CAS - do not inline methods with declarative security
         * Note: this has to be before any possible return TRUE;
         */
-       if (mono_method_has_declsec (method))
+       if (mono_security_method_has_declsec (method))
                return FALSE;
 
 #ifdef MONO_ARCH_SOFT_FLOAT
@@ -5045,6 +5088,9 @@ mini_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSign
                }
 #endif /* MONO_ARCH_HAVE_ATOMIC_CAS */
 
+               if (strcmp (cmethod->name, "MemoryBarrier") == 0)
+                       ins = emit_memory_barrier (cfg, FullBarrier);
+
                if (ins)
                        return ins;
        } else if (cmethod->klass->image == mono_defaults.corlib) {
@@ -5607,10 +5653,13 @@ mini_get_class (MonoMethod *method, guint32 token, MonoGenericContext *context)
 {
        MonoClass *klass;
 
-       if (method->wrapper_type != MONO_WRAPPER_NONE)
+       if (method->wrapper_type != MONO_WRAPPER_NONE) {
                klass = mono_method_get_wrapper_data (method, token);
-       else
+               if (context)
+                       klass = mono_class_inflate_generic_class (klass, context);
+       } else {
                klass = mono_class_get_full (method->klass->image, token, context);
+       }
        if (klass)
                mono_class_init (klass);
        return klass;
@@ -5645,7 +5694,7 @@ gboolean check_linkdemand (MonoCompile *cfg, MonoMethod *caller, MonoMethod *cal
 {
        guint32 result;
        
-       if ((cfg->method != caller) && mono_method_has_declsec (callee)) {
+       if ((cfg->method != caller) && mono_security_method_has_declsec (callee)) {
                return TRUE;
        }
        
@@ -6133,6 +6182,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
        MonoInst *cached_tls_addr = NULL;
        MonoDebugMethodInfo *minfo;
        MonoBitSet *seq_point_locs = NULL;
+       MonoBitSet *seq_point_set_locs = NULL;
 
        disable_inline = is_jit_optimizer_disabled (method);
 
@@ -6144,7 +6194,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
        dont_verify |= method->wrapper_type == MONO_WRAPPER_COMINTEROP;
        dont_verify |= method->wrapper_type == MONO_WRAPPER_COMINTEROP_INVOKE;
 
-       dont_verify |= mono_security_get_mode () == MONO_SECURITY_MODE_SMCS_HACK;
+       dont_verify |= mono_security_smcs_hack_enabled ();
 
        /* still some type unsafety issues in marshal wrappers... (unknown is PtrToStructure) */
        dont_verify_stloc = method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE;
@@ -6193,6 +6243,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
 
                        mono_debug_symfile_get_line_numbers_full (minfo, NULL, NULL, &n_il_offsets, &il_offsets, &line_numbers, NULL, NULL);
                        seq_point_locs = mono_bitset_mem_new (mono_mempool_alloc0 (cfg->mempool, mono_bitset_alloc_size (header->code_size, 0)), header->code_size, 0);
+                       seq_point_set_locs = mono_bitset_mem_new (mono_mempool_alloc0 (cfg->mempool, mono_bitset_alloc_size (header->code_size, 0)), header->code_size, 0);
                        sym_seq_points = TRUE;
                        for (i = 0; i < n_il_offsets; ++i) {
                                if (il_offsets [i] < header->code_size)
@@ -6409,10 +6460,10 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                }
        }
 
-       if (mono_security_get_mode () == MONO_SECURITY_MODE_CAS)
+       if (mono_security_cas_enabled ())
                secman = mono_security_manager_get_methods ();
 
-       security = (secman && mono_method_has_declsec (method));
+       security = (secman && mono_security_method_has_declsec (method));
        /* at this point having security doesn't mean we have any code to generate */
        if (security && (cfg->method == method)) {
                /* Only Demand, NonCasDemand and DemandChoice requires code generation.
@@ -6500,7 +6551,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                mono_emit_method_call (cfg, secman->demandunmanaged, NULL, NULL);
        }
 
-       if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR) {
+       if (mono_security_core_clr_enabled ()) {
                /* check if this is native code, e.g. an icall or a p/invoke */
                if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE) {
                        MonoMethod *wrapped = mono_marshal_method_from_wrapper (method);
@@ -6672,6 +6723,9 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        //if (!(cfg->cbb->last_ins && cfg->cbb->last_ins->opcode == OP_SEQ_POINT)) {
                        NEW_SEQ_POINT (cfg, ins, ip - header->code, intr_loc);
                        MONO_ADD_INS (cfg->cbb, ins);
+
+                       if (sym_seq_points)
+                               mono_bitset_set_fast (seq_point_set_locs, ip - header->code);
                }
 
                bblock->real_offset = cfg->real_offset;
@@ -7003,7 +7057,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        if (cfg->generic_sharing_context && mono_method_check_context_used (cmethod))
                                GENERIC_SHARING_FAILURE (CEE_JMP);
 
-                       if (mono_security_get_mode () == MONO_SECURITY_MODE_CAS)
+                       if (mono_security_cas_enabled ())
                                CHECK_CFG_EXCEPTION;
 
 #ifdef MONO_ARCH_USE_OP_TAIL_CALL
@@ -7051,6 +7105,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        int calli = *ip == CEE_CALLI;
                        gboolean pass_imt_from_rgctx = FALSE;
                        MonoInst *imt_arg = NULL;
+                       MonoInst *keep_this_alive = NULL;
                        gboolean pass_vtable = FALSE;
                        gboolean pass_mrgctx = FALSE;
                        MonoInst *vtable_arg = NULL;
@@ -7061,6 +7116,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        gboolean emit_widen = TRUE;
                        gboolean push_res = TRUE;
                        gboolean skip_ret = FALSE;
+                       gboolean delegate_invoke = FALSE;
 
                        CHECK_OPSIZE (5);
                        token = read32 (ip + 1);
@@ -7136,7 +7192,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                                METHOD_ACCESS_FAILURE;
                                }
 
-                               if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
+                               if (mono_security_core_clr_enabled ())
                                        ensure_method_is_allowed_to_call_method (cfg, method, cil_method, bblock, ip);
 
                                if (!virtual && (cmethod->flags & METHOD_ATTRIBUTE_ABSTRACT))
@@ -7152,7 +7208,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                         */
                                        const int test_flags = METHOD_ATTRIBUTE_VIRTUAL | METHOD_ATTRIBUTE_FINAL | METHOD_ATTRIBUTE_STATIC;
                                        const int expected_flags = METHOD_ATTRIBUTE_VIRTUAL | METHOD_ATTRIBUTE_FINAL;
-                                       if (!virtual && cmethod->klass->marshalbyref && (cmethod->flags & test_flags) == expected_flags && cfg->method->wrapper_type == MONO_WRAPPER_NONE)
+                                       if (!virtual && mono_class_is_marshalbyref (cmethod->klass) && (cmethod->flags & test_flags) == expected_flags && cfg->method->wrapper_type == MONO_WRAPPER_NONE)
                                                virtual = 1;
                                }
 
@@ -7208,7 +7264,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                }
                                */
 
-                               if (mono_security_get_mode () == MONO_SECURITY_MODE_CAS) {
+                               if (mono_security_cas_enabled ()) {
                                        if (check_linkdemand (cfg, method, cmethod))
                                                INLINE_FAILURE ("linkdemand");
                                        CHECK_CFG_EXCEPTION;
@@ -7244,6 +7300,16 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                                args [2] = emit_get_rgctx_klass (cfg, mono_class_check_context_used (constrained_call), constrained_call, MONO_RGCTX_INFO_KLASS);
                                                ins = mono_emit_jit_icall (cfg, mono_object_tostring_gsharedvt, args);
                                                goto call_end;
+                                       } else if (cmethod->klass == mono_defaults.object_class && !strcmp (cmethod->name, "GetHashCode")) {
+                                               MonoInst *args [3];
+
+                                               args [0] = sp [0];
+                                               EMIT_NEW_METHODCONST (cfg, args [1], cmethod);
+                                               args [2] = emit_get_rgctx_klass (cfg, mono_class_check_context_used (constrained_call), constrained_call, MONO_RGCTX_INFO_KLASS);
+                                               ins = mono_emit_jit_icall (cfg, mono_object_gethashcode_gsharedvt, args);
+                                               goto call_end;
+                                       } else if (constrained_call->valuetype && cmethod->klass->valuetype) {
+                                               /* The 'Own method' case below */
                                        } else {
                                                GSHAREDVT_FAILURE (*ip);
                                        }
@@ -7307,6 +7373,11 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        if (!calli && check_call_signature (cfg, fsig, sp))
                                UNVERIFIED;
 
+#ifdef MONO_ARCH_HAVE_CREATE_DELEGATE_TRAMPOLINE
+                       if (cmethod && (cmethod->klass->parent == mono_defaults.multicastdelegate_class) && !strcmp (cmethod->name, "Invoke"))
+                               delegate_invoke = TRUE;
+#endif
+
                        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)) {
@@ -7321,7 +7392,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                         * If the callee is a shared method, then its static cctor
                         * might not get called after the call was patched.
                         */
-                       if (cfg->generic_sharing_context && cmethod && cmethod->klass != method->klass && cmethod->klass->generic_class && mono_method_is_generic_sharable_impl (cmethod, TRUE) && mono_class_needs_cctor_run (cmethod->klass, method)) {
+                       if (cfg->generic_sharing_context && cmethod && cmethod->klass != method->klass && cmethod->klass->generic_class && mono_method_is_generic_sharable (cmethod, TRUE) && mono_class_needs_cctor_run (cmethod->klass, method)) {
                                emit_generic_class_init (cfg, cmethod->klass);
                                CHECK_TYPELOAD (cmethod->klass);
                        }
@@ -7330,7 +7401,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                        (cmethod->klass->generic_class || cmethod->klass->generic_container)) {
                                gboolean sharable = FALSE;
 
-                               if (mono_method_is_generic_sharable_impl (cmethod, TRUE)) {
+                               if (mono_method_is_generic_sharable (cmethod, TRUE)) {
                                        sharable = TRUE;
                                } else {
                                        gboolean sharing_enabled = mono_class_generic_sharing_enabled (cmethod->klass);
@@ -7355,7 +7426,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                        mini_method_get_context (cmethod)->method_inst) {
                                g_assert (!pass_vtable);
 
-                               if (mono_method_is_generic_sharable_impl (cmethod, TRUE)) {
+                               if (mono_method_is_generic_sharable (cmethod, TRUE)) {
                                        pass_mrgctx = TRUE;
                                } else {
                                        gboolean sharing_enabled = mono_class_generic_sharing_enabled (cmethod->klass);
@@ -7427,7 +7498,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                /* !marshalbyref is needed to properly handle generic methods + remoting */
                                if ((!(cmethod->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
                                         MONO_METHOD_IS_FINAL (cmethod)) &&
-                                       !cmethod->klass->marshalbyref) {
+                                       !mono_class_is_marshalbyref (cmethod->klass)) {
                                        if (virtual)
                                                check_this = TRUE;
                                        virtual = 0;
@@ -7613,7 +7684,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                        //if (cmethod->klass->flags & TYPE_ATTRIBUTE_INTERFACE)
                                                //GSHAREDVT_FAILURE (*ip);
                                        // disable for possible remoting calls
-                                       if (fsig->hasthis && (method->klass->marshalbyref || method->klass == mono_defaults.object_class))
+                                       if (fsig->hasthis && (mono_class_is_marshalbyref (method->klass) || method->klass == mono_defaults.object_class))
                                                GSHAREDVT_FAILURE (*ip);
                                        if (fsig->generic_param_count) {
                                                /* virtual generic call */
@@ -7631,6 +7702,9 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                        /* test_0_multi_dim_arrays () in gshared.cs */
                                        GSHAREDVT_FAILURE (*ip);
 
+                               if ((cmethod->klass->parent == mono_defaults.multicastdelegate_class) && (!strcmp (cmethod->name, "Invoke")))
+                                       keep_this_alive = sp [0];
+
                                if (virtual && (cmethod->flags & METHOD_ATTRIBUTE_VIRTUAL))
                                        info_type = MONO_RGCTX_INFO_METHOD_GSHAREDVT_OUT_TRAMPOLINE_VIRT;
                                else
@@ -7658,8 +7732,8 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        /* Generic sharing */
                        /* FIXME: only do this for generic methods if
                           they are not shared! */
-                       if (context_used && !imt_arg && !array_rank &&
-                               (!mono_method_is_generic_sharable_impl (cmethod, TRUE) ||
+                       if (context_used && !imt_arg && !array_rank && !delegate_invoke &&
+                               (!mono_method_is_generic_sharable (cmethod, TRUE) ||
                                 !mono_class_generic_sharing_enabled (cmethod->klass)) &&
                                (!virtual || MONO_METHOD_IS_FINAL (cmethod) ||
                                 !(cmethod->flags & METHOD_ATTRIBUTE_VIRTUAL))) {
@@ -7675,6 +7749,9 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                 * the method in the rgctx and do an
                                 * indirect call.
                                 */
+                               if (fsig->hasthis)
+                                       MONO_EMIT_NEW_CHECK_THIS (cfg, sp [0]->dreg);
+
                                addr = emit_get_rgctx_method (cfg, context_used, cmethod, MONO_RGCTX_INFO_GENERIC_METHOD_CODE);
                                ins = (MonoInst*)mono_emit_calli (cfg, fsig, sp, addr, imt_arg, vtable_arg);
                                goto call_end;
@@ -7694,20 +7771,29 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                /* Prevent inlining of methods with indirect calls */
                                INLINE_FAILURE ("indirect call");
 
-                               if (addr->opcode == OP_AOTCONST && addr->inst_c1 == MONO_PATCH_INFO_ICALL_ADDR) {
+                               if (addr->opcode == OP_PCONST || addr->opcode == OP_AOTCONST || addr->opcode == OP_GOT_ENTRY) {
+                                       int info_type;
+                                       gpointer info_data;
+
                                        /* 
                                         * Instead of emitting an indirect call, emit a direct call
                                         * with the contents of the aotconst as the patch info.
                                         */
-                                       ins = (MonoInst*)mono_emit_abs_call (cfg, MONO_PATCH_INFO_ICALL_ADDR, addr->inst_p0, fsig, sp);
-                                       NULLIFY_INS (addr);
-                               } else if (addr->opcode == OP_GOT_ENTRY && addr->inst_right->inst_c1 == MONO_PATCH_INFO_ICALL_ADDR) {
-                                       ins = (MonoInst*)mono_emit_abs_call (cfg, MONO_PATCH_INFO_ICALL_ADDR, addr->inst_right->inst_left, fsig, sp);
-                                       NULLIFY_INS (addr);
-                               } else {
-                                       ins = (MonoInst*)mono_emit_calli (cfg, fsig, sp, addr, imt_arg, vtable_arg);
+                                       if (addr->opcode == OP_PCONST || addr->opcode == OP_AOTCONST) {
+                                               info_type = addr->inst_c1;
+                                               info_data = addr->inst_p0;
+                                       } else {
+                                               info_type = addr->inst_right->inst_c1;
+                                               info_data = addr->inst_right->inst_left;
+                                       }
+                                       
+                                       if (info_type == MONO_PATCH_INFO_ICALL_ADDR || info_type == MONO_PATCH_INFO_JIT_ICALL_ADDR) {
+                                               ins = (MonoInst*)mono_emit_abs_call (cfg, info_type, info_data, fsig, sp);
+                                               NULLIFY_INS (addr);
+                                               goto call_end;
+                                       }
                                }
-
+                               ins = (MonoInst*)mono_emit_calli (cfg, fsig, sp, addr, imt_arg, vtable_arg);
                                goto call_end;
                        }
                                        
@@ -7842,6 +7928,13 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                        *sp++ = ins;
                        }
 
+                       if (keep_this_alive) {
+                               MonoInst *dummy_use;
+
+                               /* See mono_emit_method_call_full () */
+                               EMIT_NEW_DUMMY_USE (cfg, dummy_use, keep_this_alive);
+                       }
+
                        CHECK_CFG_EXCEPTION;
 
                        ip += 5;
@@ -8325,6 +8418,12 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                int imm_opcode;
 
                                imm_opcode = mono_op_to_op_imm_noemul (ins->opcode);
+#if defined(MONO_ARCH_EMULATE_MUL_DIV) || defined(MONO_ARCH_EMULATE_DIV)
+                               /* Keep emulated opcodes which are optimized away later */
+                               if ((ins->opcode == OP_IREM_UN || ins->opcode == OP_IDIV_UN_IMM) && (cfg->opt & (MONO_OPT_CONSPROP | MONO_OPT_COPYPROP)) && sp [1]->opcode == OP_ICONST && mono_is_power_of_two (sp [1]->inst_c0) >= 0) {
+                                       imm_opcode = mono_op_to_op_imm (ins->opcode);
+                               }
+#endif
                                if (imm_opcode != -1) {
                                        ins->opcode = imm_opcode;
                                        if (sp [1]->opcode == OP_I8CONST) {
@@ -8623,15 +8722,15 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
 
                        context_used = mini_method_check_context_used (cfg, cmethod);
 
-                       if (mono_security_get_mode () == MONO_SECURITY_MODE_CAS) {
+                       if (mono_security_cas_enabled ()) {
                                if (check_linkdemand (cfg, method, cmethod))
                                        INLINE_FAILURE ("linkdemand");
                                CHECK_CFG_EXCEPTION;
-                       } else if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR) {
+                       } else if (mono_security_core_clr_enabled ()) {
                                ensure_method_is_allowed_to_call_method (cfg, method, cmethod, bblock, ip);
                        }
 
-                       if (cfg->generic_sharing_context && cmethod && cmethod->klass != method->klass && cmethod->klass->generic_class && mono_method_is_generic_sharable_impl (cmethod, TRUE) && mono_class_needs_cctor_run (cmethod->klass, method)) {
+                       if (cfg->generic_sharing_context && cmethod && cmethod->klass != method->klass && cmethod->klass->generic_class && mono_method_is_generic_sharable (cmethod, TRUE) && mono_class_needs_cctor_run (cmethod->klass, method)) {
                                emit_generic_class_init (cfg, cmethod->klass);
                                CHECK_TYPELOAD (cmethod->klass);
                        }
@@ -8644,7 +8743,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        */
 
                        if (cmethod->klass->valuetype && mono_class_generic_sharing_enabled (cmethod->klass) &&
-                                       mono_method_is_generic_sharable_impl (cmethod, TRUE)) {
+                                       mono_method_is_generic_sharable (cmethod, TRUE)) {
                                if (cmethod->is_inflated && mono_method_get_context (cmethod)->method_inst) {
                                        mono_class_vtable (cfg->domain, cmethod->klass);
                                        CHECK_TYPELOAD (cmethod->klass);
@@ -8731,6 +8830,8 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                        alloc = mono_emit_jit_icall (cfg, mono_array_new_2, sp);
                                else if (fsig->param_count == 3)
                                        alloc = mono_emit_jit_icall (cfg, mono_array_new_3, sp);
+                               else if (fsig->param_count == 4)
+                                       alloc = mono_emit_jit_icall (cfg, mono_array_new_4, sp);
                                else
                                        alloc = handle_array_new (cfg, fsig->param_count, sp, ip);
                        } else if (cmethod->string_ctor) {
@@ -8785,7 +8886,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
 
                                /* Now call the actual ctor */
                                /* Avoid virtual calls to ctors if possible */
-                               if (cmethod->klass->marshalbyref)
+                               if (mono_class_is_marshalbyref (cmethod->klass))
                                        callvirt_this_arg = sp [0];
 
 
@@ -8821,7 +8922,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                        addr = emit_get_rgctx_gsharedvt_call (cfg, context_used, fsig, cmethod, MONO_RGCTX_INFO_METHOD_GSHAREDVT_OUT_TRAMPOLINE);
                                        mono_emit_calli (cfg, fsig, sp, addr, NULL, vtable_arg);
                                } else if (context_used &&
-                                               (!mono_method_is_generic_sharable_impl (cmethod, TRUE) ||
+                                               (!mono_method_is_generic_sharable (cmethod, TRUE) ||
                                                        !mono_class_generic_sharing_enabled (cmethod->klass))) {
                                        MonoInst *cmethod_addr;
 
@@ -8881,7 +8982,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                *sp++ = mono_emit_method_call (cfg, mono_castclass, args, NULL);
                                ip += 5;
                                inline_costs += 2;
-                       } else if (!context_used && (klass->marshalbyref || klass->flags & TYPE_ATTRIBUTE_INTERFACE)) {
+                       } else if (!context_used && (mono_class_is_marshalbyref (klass) || klass->flags & TYPE_ATTRIBUTE_INTERFACE)) {
                                MonoMethod *mono_castclass;
                                MonoInst *iargs [1];
                                int costs;
@@ -8941,7 +9042,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                *sp++ = mono_emit_method_call (cfg, mono_isinst, args, NULL);
                                ip += 5;
                                inline_costs += 2;
-                       } else if (!context_used && (klass->marshalbyref || klass->flags & TYPE_ATTRIBUTE_INTERFACE)) {
+                       } else if (!context_used && (mono_class_is_marshalbyref (klass) || klass->flags & TYPE_ATTRIBUTE_INTERFACE)) {
                                MonoMethod *mono_isinst;
                                MonoInst *iargs [1];
                                int costs;
@@ -8983,9 +9084,66 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
 
                        context_used = mini_class_check_context_used (cfg, klass);
 
-                       if (mini_is_gsharedvt_klass (cfg, klass))
-                               /* Need to check for nullable types at runtime */
-                               GSHAREDVT_FAILURE (*ip);
+                       if (mini_is_gsharedvt_klass (cfg, klass)) {
+                               MonoInst *obj, *addr, *klass_inst, *is_ref, *args[16];
+                               MonoBasicBlock *is_ref_bb, *end_bb;
+                               int dreg, addr_reg;
+
+                               /* Need to check for nullable types at runtime, but those are disabled in mini_is_gsharedvt_sharable_method*/
+                               if (mono_class_is_nullable (klass))
+                                       GSHAREDVT_FAILURE (*ip);
+
+                               obj = *sp;
+
+                               klass_inst = emit_get_rgctx_klass (cfg, context_used, klass, MONO_RGCTX_INFO_KLASS);
+
+                               /* obj */
+                               args [0] = obj;
+
+                               /* klass */
+                               args [1] = klass_inst;
+
+                               /* CASTCLASS */
+                               obj = mono_emit_jit_icall (cfg, mono_object_castclass, args);
+
+                               NEW_BBLOCK (cfg, is_ref_bb);
+                               NEW_BBLOCK (cfg, end_bb);
+                               is_ref = emit_get_rgctx_klass (cfg, context_used, klass,
+                                                                                          MONO_RGCTX_INFO_CLASS_IS_REF);
+                               MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, is_ref->dreg, 1);
+                               MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_IBEQ, is_ref_bb);
+
+                               /* This will contain either the address of the unboxed vtype, or an address of the temporary where the ref is stored */
+                               addr_reg = alloc_dreg (cfg, STACK_MP);
+
+                               /* Non-ref case */
+                               /* UNBOX */
+                               NEW_BIALU_IMM (cfg, addr, OP_ADD_IMM, addr_reg, obj->dreg, sizeof (MonoObject));
+                               MONO_ADD_INS (cfg->cbb, addr);
+
+                               MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_BR, end_bb);
+
+                               /* Ref case */
+                               MONO_START_BB (cfg, is_ref_bb);
+
+                               /* Save the ref to a temporary */
+                               dreg = alloc_ireg (cfg);
+                               EMIT_NEW_VARLOADA_VREG (cfg, addr, dreg, &klass->byval_arg);
+                               addr->dreg = addr_reg;
+                               MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, addr->dreg, 0, obj->dreg);
+                               MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_BR, end_bb);
+
+                               MONO_START_BB (cfg, end_bb);
+                               bblock = cfg->cbb;
+
+                               /* LDOBJ */
+                               EMIT_NEW_LOAD_MEMBASE_TYPE (cfg, ins, &klass->byval_arg, addr_reg, 0);
+                               *sp++ = ins;
+
+                               ip += 5;
+                               inline_costs += 2;
+                               break;
+                       }
 
                        if (generic_class_is_reference_type (cfg, klass)) {
                                /* CASTCLASS FIXME kill this huge slice of duplicated code*/
@@ -9010,7 +9168,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                        *sp++ = mono_emit_method_call (cfg, mono_castclass, args, NULL);
                                        ip += 5;
                                        inline_costs += 2;
-                               } else if (!context_used && (klass->marshalbyref || klass->flags & TYPE_ATTRIBUTE_INTERFACE)) {
+                               } else if (!context_used && (mono_class_is_marshalbyref (klass) || klass->flags & TYPE_ATTRIBUTE_INTERFACE)) {
                                        MonoMethod *mono_castclass;
                                        MonoInst *iargs [1];
                                        int costs;
@@ -9200,7 +9358,9 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                case CEE_LDSFLDA:
                case CEE_STSFLD: {
                        MonoClassField *field;
+#ifndef DISABLE_REMOTING
                        int costs;
+#endif
                        guint foffset;
                        gboolean is_instance;
                        int op;
@@ -9251,12 +9411,12 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                UNVERIFIED;
 
                        /* if the class is Critical then transparent code cannot access it's fields */
-                       if (!is_instance && mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
+                       if (!is_instance && mono_security_core_clr_enabled ())
                                ensure_method_is_allowed_to_access_field (cfg, method, field, bblock, ip);
 
                        /* XXX this is technically required but, so far (SL2), no [SecurityCritical] types (not many exists) have
                           any visible *instance* field  (in fact there's a single case for a static field in Marshal) XXX
-                       if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
+                       if (mono_security_core_clr_enabled ())
                                ensure_method_is_allowed_to_access_field (cfg, method, field, bblock, ip);
                        */
 
@@ -9289,7 +9449,8 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        if (op == CEE_STFLD) {
                                if (target_type_is_incompatible (cfg, field->type, sp [1]))
                                        UNVERIFIED;
-                               if ((klass->marshalbyref && !MONO_CHECK_THIS (sp [0])) || klass->contextbound || klass == mono_defaults.marshalbyrefobject_class) {
+#ifndef DISABLE_REMOTING
+                               if ((mono_class_is_marshalbyref (klass) && !MONO_CHECK_THIS (sp [0])) || mono_class_is_contextbound (klass) || klass == mono_defaults.marshalbyrefobject_class) {
                                        MonoMethod *stfld_wrapper = mono_marshal_get_stfld_wrapper (field->type); 
                                        MonoInst *iargs [5];
 
@@ -9315,7 +9476,9 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                        } else {
                                                mono_emit_method_call (cfg, stfld_wrapper, iargs, NULL);
                                        }
-                               } else {
+                               } else
+#endif
+                               {
                                        MonoInst *store;
 
                                        MONO_EMIT_NULL_CHECK (cfg, sp [0]->dreg);
@@ -9328,8 +9491,8 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                                offset_ins = emit_get_rgctx_field (cfg, context_used, field, MONO_RGCTX_INFO_FIELD_OFFSET);
                                                dreg = alloc_ireg_mp (cfg);
                                                EMIT_NEW_BIALU (cfg, ins, OP_PADD, dreg, sp [0]->dreg, offset_ins->dreg);
+                                               /* The decomposition will call mini_emit_stobj () which will emit a wbarrier if needed */
                                                EMIT_NEW_STORE_MEMBASE_TYPE (cfg, store, field->type, dreg, 0, sp [1]->dreg);
-                                               // FIXME-VT: wbarriers ?
                                        } else {
                                                EMIT_NEW_STORE_MEMBASE_TYPE (cfg, store, field->type, sp [0]->dreg, foffset, sp [1]->dreg);
                                        }
@@ -9353,7 +9516,8 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                break;
                        }
 
-                       if (is_instance && ((klass->marshalbyref && !MONO_CHECK_THIS (sp [0])) || klass->contextbound || klass == mono_defaults.marshalbyrefobject_class)) {
+#ifndef DISABLE_REMOTING
+                       if (is_instance && ((mono_class_is_marshalbyref (klass) && !MONO_CHECK_THIS (sp [0])) || mono_class_is_contextbound (klass) || klass == mono_defaults.marshalbyrefobject_class)) {
                                MonoMethod *wrapper = (op == CEE_LDFLDA) ? mono_marshal_get_ldflda_wrapper (field->type) : mono_marshal_get_ldfld_wrapper (field->type); 
                                MonoInst *iargs [4];
 
@@ -9379,7 +9543,9 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                        ins = mono_emit_method_call (cfg, wrapper, iargs, NULL);
                                        *sp++ = ins;
                                }
-                       } else if (is_instance) {
+                       } else 
+#endif
+                       if (is_instance) {
                                if (sp [0]->type == STACK_VTYPE) {
                                        MonoInst *var;
 
@@ -9785,21 +9951,9 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        if (context_used) {
                                MonoInst *args [3];
                                MonoClass *array_class = mono_array_class_get (klass, 1);
-                               /* FIXME: we cannot get a managed
-                                  allocator because we can't get the
-                                  open generic class's vtable.  We
-                                  have the same problem in
-                                  handle_alloc().  This
-                                  needs to be solved so that we can
-                                  have managed allocs of shared
-                                  generic classes. */
-                               /*
-                               MonoVTable *array_class_vtable = mono_class_vtable (cfg->domain, array_class);
-                               MonoMethod *managed_alloc = mono_gc_get_managed_array_allocator (array_class_vtable, 1);
-                               */
-                               MonoMethod *managed_alloc = NULL;
+                               MonoMethod *managed_alloc = mono_gc_get_managed_array_allocator (array_class);
 
-                               /* FIXME: Decompose later to help abcrem */
+                               /* FIXME: Use OP_NEWARR and decompose later to help abcrem */
 
                                /* vtable */
                                args [0] = emit_get_rgctx_klass (cfg, context_used,
@@ -10233,7 +10387,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                                        g_assert_not_reached ();
                                                }
                                        } else if (cfg->compile_aot) {
-                                               EMIT_NEW_LDTOKENCONST (cfg, ins, image, n);
+                                               EMIT_NEW_LDTOKENCONST (cfg, ins, image, n, generic_context);
                                        } else {
                                                EMIT_NEW_PCONST (cfg, ins, handle);
                                        }
@@ -10424,23 +10578,6 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                token = read32 (ip + 2);
 
                                ptr = mono_method_get_wrapper_data (method, token);
-                               if (cfg->compile_aot && (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE) && (strstr (method->name, "__icall_wrapper_") == method->name)) {
-                                       MonoJitICallInfo *callinfo;
-                                       const char *icall_name;
-
-                                       icall_name = method->name + strlen ("__icall_wrapper_");
-                                       g_assert (icall_name);
-                                       callinfo = mono_find_jit_icall_by_name (icall_name);
-                                       g_assert (callinfo);
-                                               
-                                       if (ptr == callinfo->func) {
-                                               /* Will be transformed into an AOTCONST later */
-                                               EMIT_NEW_PCONST (cfg, ins, ptr);
-                                               *sp++ = ins;
-                                               ip += 6;
-                                               break;
-                                       }
-                               }
                                /* FIXME: Generalize this */
                                if (cfg->compile_aot && ptr == mono_thread_interruption_request_flag ()) {
                                        EMIT_NEW_AOTCONST (cfg, ins, MONO_PATCH_INFO_INTERRUPTION_REQUEST_FLAG, NULL);
@@ -10456,6 +10593,23 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                cfg->disable_aot = 1;
                                break;
                        }
+                       case CEE_MONO_JIT_ICALL_ADDR: {
+                               MonoJitICallInfo *callinfo;
+                               gpointer ptr;
+
+                               CHECK_STACK_OVF (1);
+                               CHECK_OPSIZE (6);
+                               token = read32 (ip + 2);
+
+                               ptr = mono_method_get_wrapper_data (method, token);
+                               callinfo = mono_find_jit_icall_by_addr (ptr);
+                               g_assert (callinfo);
+                               EMIT_NEW_JIT_ICALL_ADDRCONST (cfg, ins, (char*)callinfo->name);
+                               *sp++ = ins;
+                               ip += 6;
+                               inline_costs += 10 * num_calls++;
+                               break;
+                       }
                        case CEE_MONO_ICALL_ADDR: {
                                MonoMethod *cmethod;
                                gpointer ptr;
@@ -10821,13 +10975,13 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                if (!dont_verify && !cfg->skip_visibility && !mono_method_can_access_method (method, cmethod))
                                        METHOD_ACCESS_FAILURE;
 
-                               if (mono_security_get_mode () == MONO_SECURITY_MODE_CAS) {
+                               if (mono_security_cas_enabled ()) {
                                        if (check_linkdemand (cfg, method, cmethod))
                                                INLINE_FAILURE ("linkdemand");
                                        CHECK_CFG_EXCEPTION;
-                               } else if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR) {
+                               } else if (mono_security_core_clr_enabled ()) {
                                        ensure_method_is_allowed_to_call_method (cfg, method, cmethod, bblock, ip);
-                               }
+                               }
 
                                /* 
                                 * Optimize the common case of ldftn+delegate creation
@@ -10847,7 +11001,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
 
                                                target_ins = sp [-1];
 
-                                               if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
+                                               if (mono_security_core_clr_enabled ())
                                                        ensure_method_is_allowed_to_call_method (cfg, method, ctor_method, bblock, ip);
 
                                                if (!(cmethod->flags & METHOD_ATTRIBUTE_STATIC)) {
@@ -10886,8 +11040,6 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        case CEE_LDVIRTFTN: {
                                MonoInst *args [2];
 
-                               GSHAREDVT_FAILURE (*ip);
-
                                CHECK_STACK (1);
                                CHECK_OPSIZE (6);
                                n = read32 (ip + 2);
@@ -10898,11 +11050,11 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
  
                                context_used = mini_method_check_context_used (cfg, cmethod);
 
-                               if (mono_security_get_mode () == MONO_SECURITY_MODE_CAS) {
+                               if (mono_security_cas_enabled ()) {
                                        if (check_linkdemand (cfg, method, cmethod))
                                                INLINE_FAILURE ("linkdemand");
                                        CHECK_CFG_EXCEPTION;
-                               } else if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR) {
+                               } else if (mono_security_core_clr_enabled ()) {
                                        ensure_method_is_allowed_to_call_method (cfg, method, cmethod, bblock, ip);
                                }
 
@@ -11328,6 +11480,21 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                MONO_ADD_INS (cfg->bb_exit, ins);
        }
 
+       /*
+        * Add seq points for IL offsets which have line number info, but wasn't generated a seq point during JITting because
+        * the code they refer to was dead (#11880).
+        */
+       if (sym_seq_points) {
+               for (i = 0; i < header->code_size; ++i) {
+                       if (mono_bitset_test_fast (seq_point_locs, i) && !mono_bitset_test_fast (seq_point_set_locs, i)) {
+                               MonoInst *ins;
+
+                               NEW_SEQ_POINT (cfg, ins, i, FALSE);
+                               mono_add_seq_point (cfg, NULL, ins, SEQ_POINT_NATIVE_OFFSET_DEAD_CODE);
+                       }
+               }
+       }
+
        cfg->ip = NULL;
 
        if (cfg->method == method) {
@@ -11408,8 +11575,6 @@ store_membase_reg_to_store_membase_imm (int opcode)
        return -1;
 }              
 
-#endif /* DISABLE_JIT */
-
 int
 mono_op_to_op_imm (int opcode)
 {
@@ -11865,8 +12030,6 @@ mono_op_to_op_imm_noemul (int opcode)
        }
 }
 
-#ifndef DISABLE_JIT
-
 /**
  * mono_handle_global_vregs:
  *
@@ -12355,6 +12518,7 @@ mono_spill_global_vars (MonoCompile *cfg, gboolean *need_local_opts)
 
                                        ins->dreg = alloc_dreg (cfg, stacktypes [regtype]);
 
+#if SIZEOF_REGISTER != 8
                                        if (regtype == 'l') {
                                                NEW_STORE_MEMBASE (cfg, store_ins, OP_STOREI4_MEMBASE_REG, var->inst_basereg, var->inst_offset + MINI_LS_WORD_OFFSET, ins->dreg + 1);
                                                mono_bblock_insert_after_ins (bb, ins, store_ins);
@@ -12362,7 +12526,9 @@ mono_spill_global_vars (MonoCompile *cfg, gboolean *need_local_opts)
                                                mono_bblock_insert_after_ins (bb, ins, store_ins);
                                                def_ins = store_ins;
                                        }
-                                       else {
+                                       else
+#endif
+                                       {
                                                g_assert (store_opcode != OP_STOREV_MEMBASE);
 
                                                /* Try to fuse the store into the instruction itself */
@@ -12521,6 +12687,7 @@ mono_spill_global_vars (MonoCompile *cfg, gboolean *need_local_opts)
                                                sregs [srcindex] = sreg;
                                                //mono_inst_set_src_registers (ins, sregs);
 
+#if SIZEOF_REGISTER != 8
                                                if (regtype == 'l') {
                                                        NEW_LOAD_MEMBASE (cfg, load_ins, OP_LOADI4_MEMBASE, sreg + 2, var->inst_basereg, var->inst_offset + MINI_MS_WORD_OFFSET);
                                                        mono_bblock_insert_before_ins (bb, ins, load_ins);
@@ -12528,7 +12695,9 @@ mono_spill_global_vars (MonoCompile *cfg, gboolean *need_local_opts)
                                                        mono_bblock_insert_before_ins (bb, ins, load_ins);
                                                        use_ins = load_ins;
                                                }
-                                               else {
+                                               else
+#endif
+                                               {
 #if SIZEOF_REGISTER == 4
                                                        g_assert (load_opcode != OP_LOADI8_MEMBASE);
 #endif