2008-06-13 Mark Probst <mark.probst@gmail.com>
[mono.git] / mono / mini / mini.c
index 32221d1fb097bf7ebe980d099f0612d16bee0d98..3e124da8948ceb3c3937c069935480cbbae1ccce 100644 (file)
@@ -64,6 +64,7 @@
 #include <mono/utils/mono-counters.h>
 #include <mono/utils/mono-logger.h>
 #include <mono/utils/mono-mmap.h>
+#include <mono/utils/dtrace.h>
 
 #include "mini.h"
 #include <string.h>
                if (method->klass->valuetype)   \
                        GENERIC_SHARING_FAILURE ((opcode)); \
        } while (0)
+#define GET_RGCTX(rgctx) do {                                          \
+               MonoInst *this = NULL;                                  \
+               GENERIC_SHARING_FAILURE_IF_VALUETYPE_METHOD(*ip);       \
+               if (!(method->flags & METHOD_ATTRIBUTE_STATIC))         \
+                       NEW_ARGLOAD (cfg, this, 0);                     \
+               (rgctx) = get_runtime_generic_context (cfg, method, this, ip); \
+       } while (0)
 
 #define MONO_CHECK_THIS(ins) (mono_method_signature (cfg->method)->hasthis && (ins)->ssa_op == MONO_SSA_LOAD && (ins)->inst_left->inst_c0 == 0)
 
@@ -672,7 +680,6 @@ mono_jump_info_token_new (MonoMemPool *mp, MonoImage *image, guint32 token)
                MONO_INST_NEW (cfg, dest, OP_MEMCPY); \
         (dest)->inst_left = (dst); \
                (dest)->inst_right = (src); \
-               (dest)->cil_code = ip; \
         (dest)->backend.memcpy_args = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoMemcpyArgs)); \
                (dest)->backend.memcpy_args->size = (memcpy_size); \
                (dest)->backend.memcpy_args->align = (memcpy_align); \
@@ -682,7 +689,6 @@ mono_jump_info_token_new (MonoMemPool *mp, MonoImage *image, guint32 token)
                MONO_INST_NEW (cfg, dest, OP_MEMSET); \
         (dest)->inst_left = (dst); \
                (dest)->inst_imm = (imm); \
-               (dest)->cil_code = ip; \
         (dest)->backend.memcpy_args = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoMemcpyArgs)); \
                (dest)->backend.memcpy_args->size = (memcpy_size); \
                (dest)->backend.memcpy_args->align = (memcpy_align); \
@@ -701,7 +707,6 @@ mono_jump_info_token_new (MonoMemPool *mp, MonoImage *image, guint32 token)
 
 #define ADD_BINOP(op) do {     \
                MONO_INST_NEW (cfg, ins, (op)); \
-               ins->cil_code = ip;     \
                sp -= 2;        \
                ins->inst_i0 = sp [0];  \
                ins->inst_i1 = sp [1];  \
@@ -712,7 +717,6 @@ mono_jump_info_token_new (MonoMemPool *mp, MonoImage *image, guint32 token)
 
 #define ADD_UNOP(op) do {      \
                MONO_INST_NEW (cfg, ins, (op)); \
-               ins->cil_code = ip;     \
                sp--;   \
                ins->inst_i0 = sp [0];  \
                *sp++ = ins;    \
@@ -1807,7 +1811,7 @@ mono_get_got_var (MonoCompile *cfg)
 }
 
 static MonoInst *
-mono_get_rgctx_var (MonoCompile *cfg)
+mono_get_vtable_var (MonoCompile *cfg)
 {
        g_assert (cfg->generic_sharing_context);
 
@@ -2736,10 +2740,12 @@ mono_emit_jit_icall (MonoCompile *cfg, MonoBasicBlock *bblock, gconstpointer fun
 
 static MonoCallInst*
 mono_emit_rgctx_method_call (MonoCompile *cfg, MonoBasicBlock *bblock, MonoMethod *method, MonoMethodSignature *sig,
-               MonoInst **args, MonoInst *rgctx_arg, const guint8 *ip, MonoInst *this)
+               MonoInst **args, MonoInst *rgctx_arg, MonoInst *imt_arg, const guint8 *ip, MonoInst *this)
 {
        MonoCallInst *call = mono_emit_method_call_full (cfg, bblock, method, sig, args, ip, this, FALSE);
 
+       g_assert (!(rgctx_arg && imt_arg));
+
        if (rgctx_arg) {
                switch (call->inst.opcode) {
                case OP_CALL: call->inst.opcode = OP_CALL_RGCTX; break;
@@ -2757,6 +2763,30 @@ mono_emit_rgctx_method_call (MonoCompile *cfg, MonoBasicBlock *bblock, MonoMetho
                        g_assert (!call->inst.inst_right);
                        call->inst.inst_right = rgctx_arg;
                }
+       } else if (imt_arg) {
+               switch (call->inst.opcode) {
+               case OP_CALLVIRT: call->inst.opcode = OP_CALLVIRT_IMT; break;
+               case OP_VOIDCALLVIRT: call->inst.opcode = OP_VOIDCALLVIRT_IMT; break;
+               case OP_FCALLVIRT: call->inst.opcode = OP_FCALLVIRT_IMT; break;
+               case OP_LCALLVIRT: call->inst.opcode = OP_LCALLVIRT_IMT; break;
+               case OP_VCALLVIRT: {
+                       MonoInst *group;
+
+                       NEW_GROUP (cfg, group, call->inst.inst_left, NULL);
+                       call->inst.inst_left = group;
+                       call->inst.opcode = OP_VCALLVIRT_IMT;
+                       break;
+               }
+               default: g_assert_not_reached ();
+               }
+
+               if (call->inst.opcode != OP_VCALLVIRT_IMT) {
+                       g_assert (!call->inst.inst_right);
+                       call->inst.inst_right = imt_arg;
+               } else {
+                       g_assert (!call->inst.inst_left->inst_right);
+                       call->inst.inst_left->inst_right = imt_arg;
+               }
        }
 
        return call;
@@ -2764,10 +2794,10 @@ mono_emit_rgctx_method_call (MonoCompile *cfg, MonoBasicBlock *bblock, MonoMetho
 
 inline static int
 mono_emit_rgctx_method_call_spilled (MonoCompile *cfg, MonoBasicBlock *bblock, MonoMethod *method,  
-               MonoMethodSignature *signature, MonoInst **args, MonoInst *rgctx_arg, const guint8 *ip,
-               MonoInst *this)
+               MonoMethodSignature *signature, MonoInst **args, MonoInst *rgctx_arg, MonoInst *imt_arg,
+               const guint8 *ip, MonoInst *this)
 {
-       MonoCallInst *call = mono_emit_rgctx_method_call (cfg, bblock, method, signature, args, rgctx_arg, ip, this);
+       MonoCallInst *call = mono_emit_rgctx_method_call (cfg, bblock, method, signature, args, rgctx_arg, imt_arg, ip, this);
 
        return mono_spill_call (cfg, bblock, call, signature, method->string_ctor, ip, FALSE);
 }
@@ -3112,11 +3142,12 @@ handle_alloc (MonoCompile *cfg, MonoBasicBlock *bblock, MonoClass *klass, gboole
 }
 
 static int
-handle_alloc_from_inst (MonoCompile *cfg, MonoBasicBlock *bblock, MonoClass *klass, MonoInst *vtable_inst,
+handle_alloc_from_inst (MonoCompile *cfg, MonoBasicBlock *bblock, MonoClass *klass, MonoInst *data_inst,
                gboolean for_box, const guchar *ip)
 {
        MonoInst *iargs [2];
        MonoMethod *managed_alloc = NULL;
+       void *alloc_ftn;
        /*
          FIXME: we cannot get managed_alloc here because we can't get
          the class's vtable (because it's not a closed class)
@@ -3125,32 +3156,26 @@ handle_alloc_from_inst (MonoCompile *cfg, MonoBasicBlock *bblock, MonoClass *kla
        MonoMethod *managed_alloc = mono_gc_get_managed_allocator (vtable, for_box);
        */
 
-       g_assert (!(cfg->opt & MONO_OPT_SHARED));
-       g_assert (!cfg->compile_aot);
-
-       if (managed_alloc) {
-               iargs [0] = vtable_inst;
-               return mono_emit_method_call_spilled (cfg, bblock, managed_alloc, mono_method_signature (managed_alloc), iargs, ip, NULL);
-       }
+       if (cfg->opt & MONO_OPT_SHARED) {
+               NEW_DOMAINCONST (cfg, iargs [0]);
+               iargs [1] = data_inst;
+               alloc_ftn = mono_object_new;
+       } else {
+               g_assert (!cfg->compile_aot);
 
-       iargs [0] = vtable_inst;
+               if (managed_alloc) {
+                       iargs [0] = data_inst;
+                       return mono_emit_method_call_spilled (cfg, bblock, managed_alloc,
+                               mono_method_signature (managed_alloc), iargs, ip, NULL);
+               }
 
-       return mono_emit_jit_icall (cfg, bblock, mono_object_new_specific, iargs, ip);
-}
+               iargs [0] = data_inst;
+               alloc_ftn = mono_object_new_specific;
+       }
 
-/**
- * Handles unbox of a Nullable<T>, returning a temp variable
- * where the result is stored
- */
-static int
-handle_unbox_nullable (MonoCompile* cfg, MonoBasicBlock* bblock, MonoInst* val, const guchar *ip, MonoClass* klass)
-{
-       MonoMethod* method = mono_class_get_method_from_name (klass, "Unbox", 1);
-       return mono_emit_method_call_spilled (cfg, bblock, method, mono_method_signature (method), &val, ip, NULL);
-       
+       return mono_emit_jit_icall (cfg, bblock, alloc_ftn, iargs, ip);
 }
 
-
 static MonoInst*
 handle_box_copy (MonoCompile *cfg, MonoBasicBlock *bblock, MonoInst *val, const guchar *ip, MonoClass *klass, int temp)
 {
@@ -3203,13 +3228,13 @@ handle_box (MonoCompile *cfg, MonoBasicBlock *bblock, MonoInst *val, const gucha
 
 static MonoInst *
 handle_box_from_inst (MonoCompile *cfg, MonoBasicBlock *bblock, MonoInst *val, const guchar *ip,
-               MonoClass *klass, MonoInst *vtable_inst)
+               MonoClass *klass, MonoInst *data_inst)
 {
        int temp;
 
        g_assert (!mono_class_is_nullable (klass));
 
-       temp = handle_alloc_from_inst (cfg, bblock, klass, vtable_inst, TRUE, ip);
+       temp = handle_alloc_from_inst (cfg, bblock, klass, data_inst, TRUE, ip);
 
        return handle_box_copy (cfg, bblock, val, ip, klass, temp);
 }
@@ -3231,12 +3256,10 @@ handle_delegate_ctor (MonoCompile *cfg, MonoBasicBlock *bblock, MonoClass *klass
                NEW_TEMPLOAD (cfg, obj, temp);
                NEW_ICONST (cfg, offset_ins, G_STRUCT_OFFSET (MonoDelegate, target));
                MONO_INST_NEW (cfg, ins, OP_PADD);
-               ins->cil_code = ip;
                ins->inst_left = obj;
                ins->inst_right = offset_ins;
 
                MONO_INST_NEW (cfg, store, CEE_STIND_REF);
-               store->cil_code = ip;
                store->inst_left = ins;
                store->inst_right = target;
                mono_bblock_add_inst (bblock, store);
@@ -3246,14 +3269,12 @@ handle_delegate_ctor (MonoCompile *cfg, MonoBasicBlock *bblock, MonoClass *klass
        NEW_TEMPLOAD (cfg, obj, temp);
        NEW_ICONST (cfg, offset_ins, G_STRUCT_OFFSET (MonoDelegate, method));
        MONO_INST_NEW (cfg, ins, OP_PADD);
-       ins->cil_code = ip;
        ins->inst_left = obj;
        ins->inst_right = offset_ins;
 
        NEW_METHODCONST (cfg, method_ins, method);
 
        MONO_INST_NEW (cfg, store, CEE_STIND_I);
-       store->cil_code = ip;
        store->inst_left = ins;
        store->inst_right = method_ins;
        mono_bblock_add_inst (bblock, store);
@@ -3262,7 +3283,6 @@ handle_delegate_ctor (MonoCompile *cfg, MonoBasicBlock *bblock, MonoClass *klass
        NEW_TEMPLOAD (cfg, obj, temp);
        NEW_ICONST (cfg, offset_ins, G_STRUCT_OFFSET (MonoDelegate, invoke_impl));
        MONO_INST_NEW (cfg, ins, OP_PADD);
-       ins->cil_code = ip;
        ins->inst_left = obj;
        ins->inst_right = offset_ins;
 
@@ -3270,7 +3290,6 @@ handle_delegate_ctor (MonoCompile *cfg, MonoBasicBlock *bblock, MonoClass *klass
        NEW_AOTCONST (cfg, tramp_ins, MONO_PATCH_INFO_ABS, trampoline);
 
        MONO_INST_NEW (cfg, store, CEE_STIND_I);
-       store->cil_code = ip;
        store->inst_left = ins;
        store->inst_right = tramp_ins;
        mono_bblock_add_inst (bblock, store);
@@ -3398,6 +3417,15 @@ mono_method_check_inlining (MonoCompile *cfg, MonoMethod *method)
 #endif
        }
 
+       /* also consider num_locals? */
+       /* Do the size check early to avoid creating vtables */
+       if (getenv ("MONO_INLINELIMIT")) {
+               if (header->code_size >= atoi (getenv ("MONO_INLINELIMIT"))) {
+                       return FALSE;
+               }
+       } else if (header->code_size >= INLINE_LENGTH_LIMIT)
+               return FALSE;
+
        /*
         * if we can initialize the class of the method right away, we do,
         * otherwise we don't allow inlining if the class needs initialization,
@@ -3405,9 +3433,14 @@ mono_method_check_inlining (MonoCompile *cfg, MonoMethod *method)
         * inside the inlined code
         */
        if (!(cfg->opt & MONO_OPT_SHARED)) {
-               vtable = mono_class_vtable (cfg->domain, method->klass);
                if (method->klass->flags & TYPE_ATTRIBUTE_BEFORE_FIELD_INIT) {
                        if (cfg->run_cctors && method->klass->has_cctor) {
+                               if (!method->klass->runtime_info)
+                                       /* No vtable created yet */
+                                       return FALSE;
+                               vtable = mono_class_vtable (cfg->domain, method->klass);
+                               if (!vtable)
+                                       return FALSE;
                                /* This makes so that inline cannot trigger */
                                /* .cctors: too many apps depend on them */
                                /* running with a specific order... */
@@ -3415,9 +3448,16 @@ mono_method_check_inlining (MonoCompile *cfg, MonoMethod *method)
                                        return FALSE;
                                mono_runtime_class_init (vtable);
                        }
+               } else if (mono_class_needs_cctor_run (method->klass, NULL)) {
+                       if (!method->klass->runtime_info)
+                               /* No vtable created yet */
+                               return FALSE;
+                       vtable = mono_class_vtable (cfg->domain, method->klass);
+                       if (!vtable)
+                               return FALSE;
+                       if (!vtable->initialized)
+                               return FALSE;
                }
-               else if (!vtable->initialized && mono_class_needs_cctor_run (method->klass, NULL))
-                       return FALSE;
        } else {
                /* 
                 * If we're compiling for shared code
@@ -3436,15 +3476,7 @@ mono_method_check_inlining (MonoCompile *cfg, MonoMethod *method)
        if (mono_method_has_declsec (method))
                return FALSE;
 
-       /* also consider num_locals? */
-       if (getenv ("MONO_INLINELIMIT")) {
-               if (header->code_size < atoi (getenv ("MONO_INLINELIMIT"))) {
-                       return TRUE;
-               }
-       } else if (header->code_size < INLINE_LENGTH_LIMIT)
-               return TRUE;
-
-       return FALSE;
+       return TRUE;
 }
 
 static gboolean
@@ -3480,7 +3512,6 @@ mini_get_ldelema_ins (MonoCompile *cfg, MonoBasicBlock *bblock, MonoMethod *cmet
                MONO_INST_NEW (cfg, addr, CEE_LDELEMA);
                addr->inst_left = sp [0];
                addr->inst_right = sp [1];
-               addr->cil_code = ip;
                addr->type = STACK_MP;
                addr->klass = cmethod->klass->element_class;
                return addr;
@@ -3495,7 +3526,6 @@ mini_get_ldelema_ins (MonoCompile *cfg, MonoBasicBlock *bblock, MonoMethod *cmet
                MONO_INST_NEW (cfg, addr, OP_LDELEMA2D);
                addr->inst_left = sp [0];
                addr->inst_right = indexes;
-               addr->cil_code = ip;
                addr->type = STACK_MP;
                addr->klass = cmethod->klass->element_class;
                return addr;
@@ -3760,6 +3790,23 @@ mini_get_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSigna
                }
 #endif /* MONO_ARCH_HAVE_ATOMIC_EXCHANGE */
 
+#ifdef MONO_ARCH_HAVE_ATOMIC_CAS_IMM
+               /* 
+                * Can't implement CompareExchange methods this way since they have
+                * three arguments. We can implement one of the common cases, where the new
+                * value is a constant.
+                */
+               if ((strcmp (cmethod->name, "CompareExchange") == 0)) {
+                       if (fsig->params [1]->type == MONO_TYPE_I4 && args [2]->opcode == OP_ICONST) {
+                               MONO_INST_NEW (cfg, ins, OP_ATOMIC_CAS_IMM_I4);
+                               ins->inst_i0 = args [0];
+                               ins->inst_i1 = args [1];
+                               ins->backend.data = GINT_TO_POINTER (args [2]->inst_c0);
+                       }
+                       /* The I8 case is hard to detect, since the arg might be a conv.i8 (iconst) tree */
+               }
+#endif /* MONO_ARCH_HAVE_ATOMIC_CAS_IMM */
+
                if (ins)
                        return ins;
        } else if (cmethod->klass->image == mono_defaults.corlib) {
@@ -4145,7 +4192,7 @@ emit_tree (MonoCompile *cfg, MonoBasicBlock *bblock, MonoInst *ins, const guint8
 }
 
 static inline MonoMethod *
-mini_get_method (MonoMethod *m, guint32 token, MonoClass *klass, MonoGenericContext *context)
+mini_get_method_allow_open (MonoMethod *m, guint32 token, MonoClass *klass, MonoGenericContext *context)
 {
        MonoMethod *method;
 
@@ -4157,6 +4204,17 @@ mini_get_method (MonoMethod *m, guint32 token, MonoClass *klass, MonoGenericCont
        return method;
 }
 
+static inline MonoMethod *
+mini_get_method (MonoCompile *cfg, MonoMethod *m, guint32 token, MonoClass *klass, MonoGenericContext *context)
+{
+       MonoMethod *method = mini_get_method_allow_open (m, token, klass, context);
+
+       if (method && cfg && !cfg->generic_sharing_context && mono_class_is_open_constructed_type (&method->klass->byval_arg))
+               return NULL;
+
+       return method;
+}
+
 static inline MonoClass*
 mini_get_class (MonoMethod *method, guint32 token, MonoGenericContext *context)
 {
@@ -4316,7 +4374,7 @@ initialize_array_data (MonoMethod *method, gboolean aot, unsigned char *ip, Mono
 
                if (newarr->inst_newa_len->opcode != OP_ICONST)
                        return NULL;
-               cmethod = mini_get_method (method, token, NULL, NULL);
+               cmethod = mini_get_method (NULL, method, token, NULL, NULL);
                if (!cmethod)
                        return NULL;
                if (strcmp (cmethod->name, "InitializeArray") || strcmp (cmethod->klass->name, "RuntimeHelpers") || cmethod->klass->image != mono_defaults.corlib)
@@ -4368,62 +4426,47 @@ static void
 set_exception_type_from_invalid_il (MonoCompile *cfg, MonoMethod *method, unsigned char *ip)
 {
        char *method_fname = mono_method_full_name (method, TRUE);
-       char *method_code = mono_disasm_code_one (NULL, method, ip, NULL);
+       char *method_code;
+
+       if (mono_method_get_header (method)->code_size == 0)
+               method_code = g_strdup ("method body is empty.");
+       else
+               method_code = mono_disasm_code_one (NULL, method, ip, NULL);
        cfg->exception_type = MONO_EXCEPTION_INVALID_PROGRAM;
        cfg->exception_message = g_strdup_printf ("Invalid IL code in %s: %s\n", method_fname, method_code);
        g_free (method_fname);
        g_free (method_code);
 }
 
-/*
- * Generates this->vtable->runtime_generic_context
- */
-static MonoInst*
-get_runtime_generic_context_from_this (MonoCompile *cfg, MonoInst *this, unsigned char *ip)
-{
-       MonoInst *vtable, *rgc_ptr_addr, *rgc_ptr_offset, *rgc_ptr;
-
-       MONO_INST_NEW (cfg, vtable, CEE_LDIND_I);
-       vtable->cil_code = ip;
-       vtable->inst_left = this;
-       vtable->type = STACK_PTR;
-
-       NEW_ICONST (cfg, rgc_ptr_offset, G_STRUCT_OFFSET (MonoVTable, runtime_generic_context));
-
-       MONO_INST_NEW (cfg, rgc_ptr_addr, OP_PADD);
-       rgc_ptr_addr->cil_code = ip;
-       rgc_ptr_addr->inst_left = vtable;
-       rgc_ptr_addr->inst_right = rgc_ptr_offset;
-       rgc_ptr_addr->type = STACK_PTR;
-
-       MONO_INST_NEW (cfg, rgc_ptr, CEE_LDIND_I);
-       rgc_ptr->cil_code = ip;
-       rgc_ptr->inst_left = rgc_ptr_addr;
-       rgc_ptr->type = STACK_PTR;
-
-       return rgc_ptr;
-}
-
 static MonoInst*
 get_runtime_generic_context (MonoCompile *cfg, MonoMethod *method, MonoInst *this, unsigned char *ip)
 {
        g_assert (!method->klass->valuetype);
 
        if (method->flags & METHOD_ATTRIBUTE_STATIC) {
-               MonoInst *rgctx_loc, *rgctx_var;
+               MonoInst *vtable_loc, *vtable_var;
 
-               rgctx_loc = mono_get_rgctx_var (cfg);
-               NEW_TEMPLOAD (cfg, rgctx_var, rgctx_loc->inst_c0);
+               vtable_loc = mono_get_vtable_var (cfg);
+               NEW_TEMPLOAD (cfg, vtable_var, vtable_loc->inst_c0);
 
-               return rgctx_var;
+               return vtable_var;
        } else {
-               return get_runtime_generic_context_from_this (cfg, this, ip);
+               MonoInst *vtable;
+
+               MONO_INST_NEW (cfg, vtable, CEE_LDIND_I);
+               vtable->inst_left = this;
+               vtable->type = STACK_PTR;
+
+               return vtable;
        }
 }
 
 static gpointer
 create_rgctx_lazy_fetch_trampoline (guint32 offset)
 {
+       static gboolean inited = FALSE;
+       static int num_trampolines = 0;
+
        gpointer tramp, ptr;
 
        mono_jit_lock ();
@@ -4444,18 +4487,31 @@ create_rgctx_lazy_fetch_trampoline (guint32 offset)
        g_hash_table_insert (rgctx_lazy_fetch_trampoline_hash, GUINT_TO_POINTER (offset), ptr);
        mono_jit_unlock ();
 
+       if (!inited) {
+               mono_counters_register ("RGCTX num lazy fetch trampolines",
+                               MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &num_trampolines);
+               inited = TRUE;
+       }
+       num_trampolines++;
+
        return ptr;
-}      
+}
 
+/*
+ * Generates rgc->other_infos [index].XXX if index is non-negative, or
+ * rgc->extra_other_infos [-index + 1] if index is negative.  XXX is
+ * specified by rgctx_type;
+ */
 static MonoInst*
-lazy_fetch_rgctx_direct_field (MonoCompile *cfg, MonoBasicBlock *bblock, MonoInst *rgc_ptr, int offset, unsigned char *ip)
+get_runtime_generic_context_other_table_ptr (MonoCompile *cfg, MonoBasicBlock *bblock,
+       MonoInst *rgc_ptr, int slot, const unsigned char *ip)
 {
        MonoMethodSignature *sig = helper_sig_rgctx_lazy_fetch_trampoline;
-       guint8 *tramp = create_rgctx_lazy_fetch_trampoline (MONO_RGCTX_ENCODE_DIRECT_OFFSET (offset));
+       guint8 *tramp = create_rgctx_lazy_fetch_trampoline (slot);
        int temp;
        MonoInst *field;
 
-       temp = mono_emit_native_call (cfg, bblock, tramp, sig, &rgc_ptr, ip, FALSE, FALSE); 
+       temp = mono_emit_native_call (cfg, bblock, tramp, sig, &rgc_ptr, ip, FALSE, FALSE);
 
        NEW_TEMPLOAD (cfg, field, temp);
 
@@ -4463,182 +4519,210 @@ lazy_fetch_rgctx_direct_field (MonoCompile *cfg, MonoBasicBlock *bblock, MonoIns
 }
 
 static MonoInst*
-lazy_fetch_rgctx_indirect_field (MonoCompile *cfg, MonoBasicBlock *bblock, MonoInst *rgc_ptr, int offset, unsigned char *ip)
+get_runtime_generic_context_ptr (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *bblock,
+       MonoClass *klass, guint32 type_token, int token_source, MonoGenericContext *generic_context, MonoInst *rgctx,
+       int rgctx_type, unsigned char *ip)
 {
-       MonoMethodSignature *sig = helper_sig_rgctx_lazy_fetch_trampoline;
-       guint8 *tramp = create_rgctx_lazy_fetch_trampoline (MONO_RGCTX_ENCODE_INDIRECT_OFFSET (offset));
-       int temp;
-       MonoInst *field;
+       guint32 slot = mono_method_lookup_or_register_other_info (method,
+               FALSE, &klass->byval_arg, rgctx_type, generic_context);
 
-       temp = mono_emit_native_call (cfg, bblock, tramp, sig, &rgc_ptr, ip, FALSE, FALSE); 
+       return get_runtime_generic_context_other_table_ptr (cfg, bblock, rgctx, slot, ip);
+}
 
-       NEW_TEMPLOAD (cfg, field, temp);
+static MonoInst*
+get_runtime_generic_context_method (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *bblock,
+       MonoMethod *cmethod, MonoGenericContext *generic_context, MonoInst *rgctx, int rgctx_type, const unsigned char *ip)
+{
+       guint32 slot = mono_method_lookup_or_register_other_info (method, FALSE, cmethod, rgctx_type, generic_context);
 
-       return field;
+       return get_runtime_generic_context_other_table_ptr (cfg, bblock, rgctx, slot, ip);
 }
 
-/*
- * Generates ((MonoRuntimeGenericSuperInfo*)rgc)[-depth].XXX where XXX
- * is specified by rgctx_type.
- */
 static MonoInst*
-get_runtime_generic_context_super_ptr (MonoCompile *cfg, MonoBasicBlock *bblock,
-       MonoInst *rgc_ptr, int depth, int rgctx_type, unsigned char *ip)
+get_runtime_generic_context_field (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *bblock,
+       MonoClassField *field, MonoGenericContext *generic_context, MonoInst *rgctx, int rgctx_type,
+       const unsigned char *ip)
 {
-       int field_offset_const, offset;
-
-       g_assert (depth >= 1);
+       guint32 slot = mono_method_lookup_or_register_other_info (method, FALSE, field, rgctx_type, generic_context);
 
-       switch (rgctx_type) {
-       case MONO_RGCTX_INFO_STATIC_DATA :
-               field_offset_const = G_STRUCT_OFFSET (MonoRuntimeGenericSuperInfo, static_data);
-               break;
-       case MONO_RGCTX_INFO_KLASS :
-               field_offset_const = G_STRUCT_OFFSET (MonoRuntimeGenericSuperInfo, klass);
-               break;
-       case MONO_RGCTX_INFO_VTABLE:
-               field_offset_const = G_STRUCT_OFFSET (MonoRuntimeGenericSuperInfo, vtable);
-               break;
-       default :
-               g_assert_not_reached ();
-       }
+       return get_runtime_generic_context_other_table_ptr (cfg, bblock, rgctx, slot, ip);
+}
 
-       offset = -depth * sizeof (MonoRuntimeGenericSuperInfo) + field_offset_const;
+static gboolean
+generic_class_is_reference_type (MonoCompile *cfg, MonoClass *klass)
+{
+       MonoType *type;
 
-       return lazy_fetch_rgctx_direct_field (cfg, bblock, rgc_ptr, offset, ip);
+       if (cfg->generic_sharing_context)
+               type = mini_get_basic_type_from_generic (cfg->generic_sharing_context, &klass->byval_arg);
+       else
+               type = &klass->byval_arg;
+       return MONO_TYPE_IS_REFERENCE (type);
 }
 
+/**
+ * Handles unbox of a Nullable<T>, returning a temp variable where the
+ * result is stored.  If a rgctx is passed, then shared generic code
+ * is generated.
+ */
 static int
-get_rgctx_arg_info_field_offset (int rgctx_type)
-{
-       switch (rgctx_type) {
-       case MONO_RGCTX_INFO_STATIC_DATA :
-               return G_STRUCT_OFFSET (MonoRuntimeGenericArgInfo, static_data);
-       case MONO_RGCTX_INFO_KLASS:
-               return G_STRUCT_OFFSET (MonoRuntimeGenericArgInfo, klass);
-       case MONO_RGCTX_INFO_VTABLE :
-               return G_STRUCT_OFFSET (MonoRuntimeGenericArgInfo, vtable);
-       default:
-               g_assert_not_reached ();
+handle_unbox_nullable (MonoCompile* cfg, MonoMethod *caller_method, MonoBasicBlock* bblock, MonoInst* val,
+       guchar *ip, MonoClass* klass, MonoGenericContext *generic_context, MonoInst *rgctx)
+{
+       MonoMethod* method = mono_class_get_method_from_name (klass, "Unbox", 1);
+       MonoMethodSignature *signature = mono_method_signature (method);
+
+       if (rgctx) {
+               MonoInst *addr = get_runtime_generic_context_method (cfg, caller_method, bblock, method,
+                       generic_context, rgctx, MONO_RGCTX_INFO_GENERIC_METHOD_CODE, ip);
+
+               return mono_emit_rgctx_calli_spilled (cfg, bblock, signature, &val, addr, NULL, ip);
+       } else {
+               return mono_emit_method_call_spilled (cfg, bblock, method, signature, &val, ip, NULL);
        }
 }
 
-/*
- * Generates rgc->arg_infos [arg_num].XXX where XXX is specified by
- * rgctx_type;
- */
 static MonoInst*
-get_runtime_generic_context_arg_ptr (MonoCompile *cfg, MonoBasicBlock *bblock,
-       MonoInst *rgc_ptr, int arg_num, int rgctx_type, unsigned char *ip)
+handle_box_nullable_from_inst (MonoCompile *cfg, MonoMethod *caller_method, int context_used, MonoBasicBlock *bblock,
+       MonoInst *val, const guchar *ip, MonoClass *klass, MonoGenericContext *generic_context, MonoInst *rgctx)
 {
-       int arg_info_offset, arg_info_field_offset, offset;
+       MonoMethod* method = mono_class_get_method_from_name (klass, "Box", 1);
+       MonoInst *dest, *method_addr;
+       int temp;
 
-       g_assert (arg_num >= 0);
-       //g_assert (!lazy);
+       g_assert (mono_class_is_nullable (klass));
 
-       arg_info_offset = G_STRUCT_OFFSET (MonoRuntimeGenericContext, arg_infos) +
-               arg_num * sizeof (MonoRuntimeGenericArgInfo);
+       method_addr = get_runtime_generic_context_method (cfg, caller_method, bblock, method,
+                       generic_context, rgctx, MONO_RGCTX_INFO_GENERIC_METHOD_CODE, ip);
+       temp = mono_emit_rgctx_calli_spilled (cfg, bblock, mono_method_signature (method), &val,
+                       method_addr, NULL, ip);
+       NEW_TEMPLOAD (cfg, dest, temp);
+       return dest;
+}
 
-       arg_info_field_offset = get_rgctx_arg_info_field_offset (rgctx_type);
+static MonoObject*
+mono_object_castclass (MonoObject *obj, MonoClass *klass)
+{
+       if (!obj)
+               return NULL;
 
-       offset = arg_info_offset + arg_info_field_offset;
+       if (mono_object_isinst (obj, klass))
+               return obj;
 
-       return lazy_fetch_rgctx_direct_field (cfg, bblock, rgc_ptr, offset, ip);
+       mono_raise_exception (mono_exception_from_name (mono_defaults.corlib,
+                                       "System", "InvalidCastException"));
+
+       return NULL;
 }
 
-/*
- * Generates rgc->other_infos [index].XXX if index is non-negative, or
- * rgc->extra_other_infos [-index + 1] if index is negative.  XXX is
- * specified by rgctx_type;
- */
-static MonoInst*
-get_runtime_generic_context_other_table_ptr (MonoCompile *cfg, MonoBasicBlock *bblock,
-       MonoInst *rgc_ptr, int index, unsigned char *ip)
-{
-       if (index < MONO_RGCTX_MAX_OTHER_INFOS) {
-               int other_type_offset;
+static int
+emit_castclass (MonoClass *klass, guint32 token, gboolean shared_access, gboolean inst_is_castclass, MonoCompile *cfg,
+               MonoMethod *method, MonoInst **arg_array, MonoType **param_types, GList *dont_inline,
+               unsigned char *end, MonoMethodHeader *header, MonoGenericContext *generic_context,
+               MonoBasicBlock **_bblock, unsigned char **_ip, MonoInst ***_sp, int *_inline_costs, guint *_real_offset)
+{
+       MonoBasicBlock *bblock = *_bblock;
+       unsigned char *ip = *_ip;
+       MonoInst **sp = *_sp;
+       int inline_costs = *_inline_costs;
+       guint real_offset = *_real_offset;
+       int return_value = 0;
+
+       if (shared_access) {
+               MonoInst *this = NULL, *rgctx;
+               MonoInst *args [2];
+               int temp;
 
-               other_type_offset = G_STRUCT_OFFSET (MonoRuntimeGenericContext, other_infos) +
-                       index * sizeof (gpointer);
+               g_assert (!method->klass->valuetype);
 
-               return lazy_fetch_rgctx_direct_field (cfg, bblock, rgc_ptr, other_type_offset, ip);
-       } else {
-               int slot_offset;
+               /* obj */
+               args [0] = *sp;
 
-               slot_offset = (index - MONO_RGCTX_MAX_OTHER_INFOS) * sizeof (gpointer);
+               /* klass */
+               if (!(method->flags & METHOD_ATTRIBUTE_STATIC))
+                       NEW_ARGLOAD (cfg, this, 0);
+               rgctx = get_runtime_generic_context (cfg, method, this, ip);
+               args [1] = get_runtime_generic_context_ptr (cfg, method, bblock, klass,
+                               token, MINI_TOKEN_SOURCE_CLASS, generic_context, rgctx, MONO_RGCTX_INFO_KLASS, ip);
 
-               return lazy_fetch_rgctx_indirect_field (cfg, bblock, rgc_ptr, slot_offset, ip);
-       }
-}
+               temp = mono_emit_jit_icall (cfg, bblock, mono_object_castclass, args, ip);
+               NEW_TEMPLOAD (cfg, *sp, temp);
 
-static MonoInst*
-get_runtime_generic_context_other_ptr (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *bblock,
-       MonoInst *rgc_ptr, guint32 token, int token_source, int rgctx_type, unsigned char *ip, int index)
-{
-       MonoInst *args [6];
-       int temp;
-       MonoInst *result;
+               sp++;
+               ip += 5;
+               inline_costs += 2;
+       } else if (klass->marshalbyref || klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
 
-       g_assert (method->wrapper_type == MONO_WRAPPER_NONE);
+               MonoMethod *mono_castclass;
+               MonoInst *iargs [1];
+               MonoBasicBlock *ebblock;
+               int costs;
+               int temp;
 
-       NEW_CLASSCONST (cfg, args [0], method->klass);
-       args [1] = rgc_ptr;
-       NEW_ICONST (cfg, args [2], token);
-       NEW_ICONST (cfg, args [3], token_source);
-       NEW_ICONST (cfg, args [4], rgctx_type);
-       NEW_ICONST (cfg, args [5], index);
+               mono_castclass = mono_marshal_get_castclass (klass);
+               iargs [0] = sp [0];
 
-       temp = mono_emit_jit_icall (cfg, bblock, mono_helper_get_rgctx_other_ptr, args, ip);
-       NEW_TEMPLOAD (cfg, result, temp);
+               costs = inline_method (cfg, mono_castclass, mono_method_signature (mono_castclass), bblock,
+                               iargs, ip, real_offset, dont_inline, &ebblock, TRUE);
 
-       return result;
-}
+               g_assert (costs > 0);
 
-static MonoInst*
-get_runtime_generic_context_ptr (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *bblock,
-       MonoClass *klass, guint32 type_token, int token_source, MonoGenericContext *generic_context, MonoInst *rgctx,
-       int rgctx_type, unsigned char *ip)
-{
-       int arg_num = -1;
-       int relation = mono_class_generic_class_relation (klass, rgctx_type, method->klass, generic_context, &arg_num);
-
-       switch (relation) {
-       case MINI_GENERIC_CLASS_RELATION_SELF: {
-               int depth = klass->idepth;
-               return get_runtime_generic_context_super_ptr (cfg, bblock, rgctx, depth, rgctx_type, ip);
-       }
-       case MINI_GENERIC_CLASS_RELATION_ARGUMENT:
-               return get_runtime_generic_context_arg_ptr (cfg, bblock, rgctx, arg_num, rgctx_type, ip);
-       case MINI_GENERIC_CLASS_RELATION_OTHER_TABLE:
-               return get_runtime_generic_context_other_table_ptr (cfg, bblock, rgctx, arg_num, ip);
-       case MINI_GENERIC_CLASS_RELATION_OTHER:
-               return get_runtime_generic_context_other_ptr (cfg, method, bblock, rgctx,
-                       type_token, token_source, rgctx_type, ip, arg_num);
-       default:
-               g_assert_not_reached ();
-               return NULL;
-       }
-}
+               ip += 5;
+               real_offset += 5;
 
-static MonoInst*
-get_runtime_generic_context_method (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *bblock,
-       MonoMethod *cmethod, MonoGenericContext *generic_context, MonoInst *rgctx, int rgctx_type, unsigned char *ip)
-{
-       int arg_num = mono_class_lookup_or_register_other_info (method->klass, cmethod, rgctx_type, generic_context);
+               GET_BBLOCK (cfg, bblock, ip);
+               ebblock->next_bb = bblock;
+               link_bblock (cfg, ebblock, bblock);
+
+               temp = iargs [0]->inst_i0->inst_c0;
+               NEW_TEMPLOAD (cfg, *sp, temp);
+
+               sp++;
+               bblock = ebblock;
+               inline_costs += costs;
+       } else {
+               MonoInst *ins;
+
+               /* Needed by the code generated in inssel.brg */
+               mono_get_got_var (cfg);
 
-       return get_runtime_generic_context_other_table_ptr (cfg, bblock, rgctx, arg_num, ip);
+               MONO_INST_NEW (cfg, ins, CEE_CASTCLASS);
+               ins->type = STACK_OBJ;
+               ins->inst_left = *sp;
+               ins->klass = klass;
+               ins->inst_newa_class = klass;
+               if (inst_is_castclass)
+                       ins->backend.record_cast_details = debug_options.better_cast_details;
+               if (inst_is_castclass)
+                       *sp++ = emit_tree (cfg, bblock, ins, ip + 5);
+               else
+                       *sp++ = ins;
+               ip += 5;
+       }
+
+do_return:
+       *_bblock = bblock;
+       *_ip = ip;
+       *_sp = sp;
+       *_inline_costs = inline_costs;
+       *_real_offset = real_offset;
+       return return_value;
+unverified:
+       return_value = -1;
+       goto do_return;
 }
 
 static gboolean
-generic_class_is_reference_type (MonoCompile *cfg, MonoClass *klass)
+mini_assembly_can_skip_verification (MonoDomain *domain, MonoMethod *method)
 {
-       MonoType *type;
-
-       if (cfg->generic_sharing_context)
-               type = mini_get_basic_type_from_generic (cfg->generic_sharing_context, &klass->byval_arg);
-       else
-               type = &klass->byval_arg;
-       return MONO_TYPE_IS_REFERENCE (type);
+       MonoAssembly *assembly = method->klass->image->assembly;
+       if (method->wrapper_type != MONO_WRAPPER_NONE)
+               return FALSE;
+       if (assembly->in_gac || assembly->image == mono_defaults.corlib)
+               return FALSE;
+       if (mono_security_get_mode () != MONO_SECURITY_MODE_NONE)
+               return FALSE;
+       return mono_assembly_has_skip_verification (assembly);
 }
 
 /*
@@ -4652,9 +4736,14 @@ static gboolean
 mini_method_verify (MonoCompile *cfg, MonoMethod *method)
 {
        GSList *tmp, *res;
-       gboolean is_fulltrust = mono_verifier_is_method_full_trust (method);
+       gboolean is_fulltrust;
        MonoLoaderError *error;
 
+       if (method->verification_success)
+               return FALSE;
+
+       is_fulltrust = mono_verifier_is_method_full_trust (method);
+
        if (!mono_verifier_is_enabled_for_method (method))
                return FALSE;
 
@@ -4685,6 +4774,7 @@ mini_method_verify (MonoCompile *cfg, MonoMethod *method)
                }
                mono_free_verify_list (res);
        }
+       method->verification_success = 1;
        return FALSE;
 }
 
@@ -4699,7 +4789,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
        MonoInst *zero_int32, *zero_int64, *zero_ptr, *zero_obj, *zero_r8;
        MonoInst *ins, **sp, **stack_start;
        MonoBasicBlock *bblock, *tblock = NULL, *init_localsbb = NULL;
-       MonoMethod *cmethod;
+       MonoMethod *cmethod, *method_definition;
        MonoInst **arg_array;
        MonoMethodHeader *header;
        MonoImage *image;
@@ -4742,7 +4832,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
 
        image = method->klass->image;
        header = mono_method_get_header (method);
-       generic_container = method->generic_container;
+       generic_container = mono_method_get_generic_container (method);
        sig = mono_method_signature (method);
        num_args = sig->hasthis + sig->param_count;
        ip = (unsigned char*)header->code;
@@ -4750,7 +4840,19 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
        end = ip + header->code_size;
        mono_jit_stats.cil_code_size += header->code_size;
 
-       if (!dont_verify && mini_method_verify (cfg, method))
+       method_definition = method;
+       while (method_definition->is_inflated) {
+               MonoMethodInflated *imethod = (MonoMethodInflated *) method_definition;
+               method_definition = imethod->declaring;
+       }
+
+       /* SkipVerification is not allowed if core-clr is enabled */
+       if (!dont_verify && mini_assembly_can_skip_verification (cfg->domain, method)) {
+               dont_verify = TRUE;
+               dont_verify_stloc = TRUE;
+       }
+
+       if (!dont_verify && mini_method_verify (cfg, method_definition))
                goto exception_exit;
 
        if (sig->is_inflated)
@@ -4879,7 +4981,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                 * (for non-static methods) are live.
                                 */
                                if (method->flags & METHOD_ATTRIBUTE_STATIC) {
-                                       mono_get_rgctx_var (cfg);
+                                       mono_get_vtable_var (cfg);
                                } else {
                                        MonoInst *this, *dummy_use;
                                        MonoType *this_type;
@@ -5137,7 +5239,6 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        ins->cil_code = ip;
 
                        MONO_INST_NEW (cfg, store, CEE_STIND_I);
-                       store->cil_code = ip;
                        store->inst_left = ins;
                        store->inst_right = one;
 
@@ -5150,12 +5251,12 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                switch (*ip) {
                case CEE_NOP:
                        MONO_INST_NEW (cfg, ins, OP_NOP);
-                       ins->cil_code = ip++;
+                       ip++;
                        MONO_ADD_INS (bblock, ins);
                        break;
                case CEE_BREAK:
                        MONO_INST_NEW (cfg, ins, OP_BREAK);
-                       ins->cil_code = ip++;
+                       ip++;
                        MONO_ADD_INS (bblock, ins);
                        break;
                case CEE_LDARG_0:
@@ -5167,7 +5268,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        CHECK_ARG (n);
                        NEW_ARGLOAD (cfg, ins, n);
                        LDARG_SOFT_FLOAT (cfg, ins, n, ip);
-                       ins->cil_code = ip++;
+                       ip++;
                        *sp++ = ins;
                        break;
                case CEE_LDLOC_0:
@@ -5179,7 +5280,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        CHECK_LOCAL (n);
                        NEW_LOCLOAD (cfg, ins, n);
                        LDLOC_SOFT_FLOAT (cfg, ins, n, ip);
-                       ins->cil_code = ip++;
+                       ip++;
                        *sp++ = ins;
                        break;
                case CEE_STLOC_0:
@@ -5192,7 +5293,6 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        --sp;
                        handle_loaded_temps (cfg, bblock, stack_start, sp);
                        NEW_LOCSTORE (cfg, ins, n, *sp);
-                       ins->cil_code = ip;
                        if (!dont_verify_stloc && target_type_is_incompatible (cfg, header->locals [n], *sp))
                                UNVERIFIED;
                        STLOC_SOFT_FLOAT (cfg, ins, n, ip);
@@ -5210,7 +5310,6 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        CHECK_ARG (ip [1]);
                        NEW_ARGLOAD (cfg, ins, ip [1]);
                        LDARG_SOFT_FLOAT (cfg, ins, ip [1], ip);
-                       ins->cil_code = ip;
                        *sp++ = ins;
                        ip += 2;
                        break;
@@ -5219,7 +5318,6 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        CHECK_STACK_OVF (1);
                        CHECK_ARG (ip [1]);
                        NEW_ARGLOADA (cfg, ins, ip [1]);
-                       ins->cil_code = ip;
                        *sp++ = ins;
                        ip += 2;
                        break;
@@ -5230,7 +5328,6 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        CHECK_ARG (ip [1]);
                        NEW_ARGSTORE (cfg, ins, ip [1], *sp);
                        handle_loaded_temps (cfg, bblock, stack_start, sp);
-                       ins->cil_code = ip;
                        if (!dont_verify_stloc && target_type_is_incompatible (cfg, param_types [ip [1]], *sp))
                                UNVERIFIED;
                        STARG_SOFT_FLOAT (cfg, ins, ip [1], ip);
@@ -5247,7 +5344,6 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        CHECK_LOCAL (ip [1]);
                        NEW_LOCLOAD (cfg, ins, ip [1]);
                        LDLOC_SOFT_FLOAT (cfg, ins, ip [1], ip);
-                       ins->cil_code = ip;
                        *sp++ = ins;
                        ip += 2;
                        break;
@@ -5256,7 +5352,6 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        CHECK_STACK_OVF (1);
                        CHECK_LOCAL (ip [1]);
                        NEW_LOCLOADA (cfg, ins, ip [1]);
-                       ins->cil_code = ip;
                        *sp++ = ins;
                        ip += 2;
                        break;
@@ -5267,7 +5362,6 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        handle_loaded_temps (cfg, bblock, stack_start, sp);
                        CHECK_LOCAL (ip [1]);
                        NEW_LOCSTORE (cfg, ins, ip [1], *sp);
-                       ins->cil_code = ip;
                        if (!dont_verify_stloc && target_type_is_incompatible (cfg, header->locals [ip [1]], *sp))
                                UNVERIFIED;
                        STLOC_SOFT_FLOAT (cfg, ins, ip [1], ip);
@@ -5282,7 +5376,6 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                case CEE_LDNULL:
                        CHECK_STACK_OVF (1);
                        NEW_PCONST (cfg, ins, NULL);
-                       ins->cil_code = ip;
                        ins->type = STACK_OBJ;
                        ++ip;
                        *sp++ = ins;
@@ -5290,7 +5383,6 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                case CEE_LDC_I4_M1:
                        CHECK_STACK_OVF (1);
                        NEW_ICONST (cfg, ins, -1);
-                       ins->cil_code = ip;
                        ++ip;
                        *sp++ = ins;
                        break;
@@ -5305,7 +5397,6 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                case CEE_LDC_I4_8:
                        CHECK_STACK_OVF (1);
                        NEW_ICONST (cfg, ins, (*ip) - CEE_LDC_I4_0);
-                       ins->cil_code = ip;
                        ++ip;
                        *sp++ = ins;
                        break;
@@ -5314,7 +5405,6 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        CHECK_STACK_OVF (1);
                        ++ip;
                        NEW_ICONST (cfg, ins, *((signed char*)ip));
-                       ins->cil_code = ip;
                        ++ip;
                        *sp++ = ins;
                        break;
@@ -5322,7 +5412,6 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        CHECK_OPSIZE (5);
                        CHECK_STACK_OVF (1);
                        NEW_ICONST (cfg, ins, (gint32)read32 (ip + 1));
-                       ins->cil_code = ip;
                        ip += 5;
                        *sp++ = ins;
                        break;
@@ -5330,7 +5419,6 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        CHECK_OPSIZE (9);
                        CHECK_STACK_OVF (1);
                        MONO_INST_NEW (cfg, ins, OP_I8CONST);
-                       ins->cil_code = ip;
                        ins->type = STACK_I8;
                        ++ip;
                        ins->inst_l = (gint64)read64 (ip);
@@ -5388,14 +5476,11 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                sp++;
                                MONO_INST_NEW (cfg, temp, 0);
                                *temp = *ins;
-                               temp->cil_code = ip;
                                *sp++ = temp;
                        } else {
                                temp = mono_compile_create_var (cfg, type_from_stack_type (ins), OP_LOCAL);
                                temp->flags |= MONO_INST_IS_TEMP;
-                               temp->cil_code = ip;
                                NEW_TEMPSTORE (cfg, store, temp->inst_c0, ins);
-                               store->cil_code = ip;
                                /* FIXME: handle CEE_STIND_R4 */
                                if (store->opcode == CEE_STOBJ) {
                                        NEW_TEMPLOADA (cfg, store, temp->inst_c0);
@@ -5405,10 +5490,8 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                }
                                NEW_TEMPLOAD (cfg, ins, temp->inst_c0);
                                *sp++ = ins;
-                               ins->cil_code = ip;
                                NEW_TEMPLOAD (cfg, ins, temp->inst_c0);
                                *sp++ = ins;
-                               ins->cil_code = ip;
                        }
                        ++ip;
                        inline_costs += 2;
@@ -5418,7 +5501,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        CHECK_STACK (1);
                        MONO_INST_NEW (cfg, ins, CEE_POP);
                        MONO_ADD_INS (bblock, ins);
-                       ins->cil_code = ip++;
+                       ip++;
                        --sp;
                        ins->inst_i0 = *sp;
                        break;
@@ -5429,7 +5512,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        MONO_INST_NEW (cfg, ins, OP_JMP);
                        token = read32 (ip + 1);
                        /* FIXME: check the signature matches */
-                       cmethod = mini_get_method (method, token, NULL, generic_context);
+                       cmethod = mini_get_method (cfg, method, token, NULL, generic_context);
 
                        if (!cmethod)
                                goto load_error;
@@ -5455,10 +5538,12 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        MonoMethodSignature *fsig = NULL;
                        int temp, array_rank = 0;
                        int virtual = *ip == CEE_CALLVIRT;
-                       MonoInst *rgctx_arg = NULL;
                        gboolean no_spill;
                        int context_used = 0;
-                       gboolean pass_rgctx = FALSE;
+                       gboolean pass_imt_from_rgctx = FALSE;
+                       MonoInst *imt_arg = NULL;
+                       gboolean pass_vtable = FALSE;
+                       MonoInst *vtable_arg = NULL;
 
                        CHECK_OPSIZE (5);
                        token = read32 (ip + 1);
@@ -5484,14 +5569,21 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                        cmethod = mono_get_method_constrained (image, token, constrained_call, generic_context, &cil_method);
                                        cil_method = cmethod;
                                } else {
-                                       cmethod = mini_get_method (method, token, NULL, generic_context);
+                                       cmethod = mini_get_method (cfg, method, token, NULL, generic_context);
                                        cil_method = cmethod;
                                }
 
                                if (!cmethod)
                                        goto load_error;
-                               if (!dont_verify && !cfg->skip_visibility && !mono_method_can_access_method (method, cil_method))
-                                       METHOD_ACCESS_FAILURE;
+                               if (!dont_verify && !cfg->skip_visibility) {
+                                       MonoMethod *target_method = cil_method;
+                                       if (method->is_inflated) {
+                                               target_method = mini_get_method_allow_open (method, token, NULL, &(mono_method_get_generic_container (method_definition)->context));
+                                       }
+                                       if (!mono_method_can_access_method (method_definition, target_method) &&
+                                               !mono_method_can_access_method (method, cil_method))
+                                               METHOD_ACCESS_FAILURE;
+                               }
 
                                if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
                                        ensure_method_is_allowed_to_call_method (cfg, method, cil_method, bblock, ip);
@@ -5558,7 +5650,6 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                         */
                                        MONO_INST_NEW (cfg, load, mini_type_to_ldind (cfg, &constrained_call->byval_arg));
                                        type_to_eval_stack_type (cfg, &constrained_call->byval_arg, load);
-                                       load->cil_code = ip;
                                        load->inst_left = sp [0];
                                        sp [0] = handle_box (cfg, bblock, load, ip, constrained_call);
                                } else if (!constrained_call->valuetype) {
@@ -5571,7 +5662,6 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                         */
 
                                        MONO_INST_NEW (cfg, ins, CEE_LDIND_REF);
-                                       ins->cil_code = ip;
                                        ins->inst_i0 = sp [0];
                                        ins->type = STACK_OBJ;
                                        ins->klass = mono_class_from_mono_type (&constrained_call->byval_arg);
@@ -5591,15 +5681,14 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                gboolean context_sharable = mono_generic_context_is_sharable (context, TRUE);
 
                                /*
-                                * Pass rgctx iff target method might
+                                * Pass vtable iff target method might
                                 * be shared, which means that sharing
                                 * is enabled for its class and its
                                 * context is sharable (and it's not a
                                 * generic method).
                                 */
-                               if (sharing_enabled && context_sharable &&
-                                               !mini_method_get_context (cmethod)->method_inst)
-                                       pass_rgctx = TRUE;
+                               if (sharing_enabled && context_sharable)
+                                       pass_vtable = TRUE;
                        }
 
                        if (cfg->generic_sharing_context && cmethod) {
@@ -5609,46 +5698,48 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
 
                                if (context_used & MONO_GENERIC_CONTEXT_USED_METHOD)
                                        GENERIC_SHARING_FAILURE (*ip);
+                               if (context_used && (cmethod->klass->flags & TYPE_ATTRIBUTE_INTERFACE)) {
+                                       /* Generic method interface
+                                          calls are resolved via a
+                                          helper function and don't
+                                          need an imt. */
+                                       if (!cmethod_context || !cmethod_context->method_inst)
+                                               pass_imt_from_rgctx = TRUE;
+                               }
 
                                if (context_used &&
-                                               ((cmethod->klass->flags & TYPE_ATTRIBUTE_INTERFACE) ||
-                                               (cmethod_context && cmethod_context->method_inst && cmethod->flags & METHOD_ATTRIBUTE_VIRTUAL))) {
+                                               (cmethod_context && cmethod_context->method_inst && cmethod->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
                                        GENERIC_SHARING_FAILURE (*ip);
                                }
                        }
 
-                       if (pass_rgctx) {
+                       if (pass_vtable) {
                                if (context_used) {
-                                       MonoInst *this = NULL, *rgctx, *vtable, *field_offset, *field_addr;
+                                       MonoInst *rgctx;
 
-                                       GENERIC_SHARING_FAILURE_IF_VALUETYPE_METHOD (*ip);
-
-                                       if (!(method->flags & METHOD_ATTRIBUTE_STATIC))
-                                               NEW_ARGLOAD (cfg, this, 0);
-                                       rgctx = get_runtime_generic_context (cfg, method, this, ip);
-                                       vtable = get_runtime_generic_context_ptr (cfg, method, bblock, cmethod->klass,
+                                       GET_RGCTX (rgctx);
+                                       vtable_arg = get_runtime_generic_context_ptr (cfg, method, bblock, cmethod->klass,
                                                token, MINI_TOKEN_SOURCE_METHOD, generic_context,
                                                rgctx, MONO_RGCTX_INFO_VTABLE, ip);
-
-                                       NEW_ICONST (cfg, field_offset, G_STRUCT_OFFSET (MonoVTable, runtime_generic_context));
-
-                                       MONO_INST_NEW (cfg, field_addr, OP_PADD);
-                                       field_addr->cil_code = ip;
-                                       field_addr->inst_left = vtable;
-                                       field_addr->inst_right = field_offset;
-                                       field_addr->type = STACK_PTR;
-
-                                       MONO_INST_NEW (cfg, rgctx_arg, CEE_LDIND_I);
-                                       rgctx_arg->cil_code = ip;
-                                       rgctx_arg->inst_left = field_addr;
-                                       rgctx_arg->type = STACK_PTR;
                                } else {
                                        MonoVTable *vtable = mono_class_vtable (cfg->domain, cmethod->klass);
-
-                                       NEW_PCONST (cfg, rgctx_arg, vtable->runtime_generic_context);
+                                       
+                                       CHECK_TYPELOAD (cmethod->klass);
+                                       NEW_VTABLECONST (cfg, vtable_arg, vtable);
                                }
                        }
 
+                       if (pass_imt_from_rgctx) {
+                               MonoInst *rgctx;
+
+                               g_assert (!pass_vtable);
+                               g_assert (cmethod);
+
+                               GET_RGCTX (rgctx);
+                               imt_arg = get_runtime_generic_context_method (cfg, method, bblock, cmethod,
+                                               generic_context, rgctx, MONO_RGCTX_INFO_METHOD, ip);
+                       }
+
                        if (cmethod && virtual && 
                            (cmethod->flags & METHOD_ATTRIBUTE_VIRTUAL) && 
                            !((cmethod->flags & METHOD_ATTRIBUTE_FINAL) && 
@@ -5662,23 +5753,31 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                INLINE_FAILURE;
 
                                this_temp = mono_compile_create_var (cfg, type_from_stack_type (sp [0]), OP_LOCAL);
-                               this_temp->cil_code = ip;
                                NEW_TEMPSTORE (cfg, store, this_temp->inst_c0, sp [0]);
-
-                               store->cil_code = ip;
                                MONO_ADD_INS (bblock, store);
 
                                /* FIXME: This should be a managed pointer */
                                this_arg_temp = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_LOCAL);
-                               this_arg_temp->cil_code = ip;
 
                                /* Because of the PCONST below */
                                cfg->disable_aot = TRUE;
                                NEW_TEMPLOAD (cfg, iargs [0], this_temp->inst_c0);
-                               NEW_METHODCONST (cfg, iargs [1], cmethod);
-                               NEW_PCONST (cfg, iargs [2], mono_method_get_context (cmethod));
-                               NEW_TEMPLOADA (cfg, iargs [3], this_arg_temp->inst_c0);
-                               temp = mono_emit_jit_icall (cfg, bblock, mono_helper_compile_generic_method, iargs, ip);
+                               if (context_used) {
+                                       MonoInst *rgctx;
+
+                                       GET_RGCTX (rgctx);
+                                       iargs [1] = get_runtime_generic_context_method (cfg, method, bblock, cmethod,
+                                                       generic_context, rgctx, MONO_RGCTX_INFO_METHOD, ip);
+                                       NEW_TEMPLOADA (cfg, iargs [2], this_arg_temp->inst_c0);
+                                       temp = mono_emit_jit_icall (cfg, bblock,
+                                               mono_helper_compile_generic_method_wo_context, iargs, ip);
+                               } else {
+                                       NEW_METHODCONST (cfg, iargs [1], cmethod);
+                                       NEW_PCONST (cfg, iargs [2], mono_method_get_context (cmethod));
+                                       NEW_TEMPLOADA (cfg, iargs [3], this_arg_temp->inst_c0);
+                                       temp = mono_emit_jit_icall (cfg, bblock, mono_helper_compile_generic_method,
+                                               iargs, ip);
+                               }
 
                                NEW_TEMPLOAD (cfg, addr, temp);
                                NEW_TEMPLOAD (cfg, sp [0], this_arg_temp->inst_c0);
@@ -5694,7 +5793,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        }
 
                        /* FIXME: runtime generic context pointer for jumps? */
-                       if ((ins_flag & MONO_INST_TAILCALL) && cmethod && (*ip == CEE_CALL) &&
+                       if ((ins_flag & MONO_INST_TAILCALL) && !cfg->generic_sharing_context && !vtable_arg && cmethod && (*ip == CEE_CALL) &&
                                 (mono_metadata_signature_equal (mono_method_signature (method), mono_method_signature (cmethod)))) {
                                int i;
 
@@ -5723,7 +5822,6 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                                continue;
 
                                        NEW_ARGSTORE (cfg, ins, i, sp [i]);
-                                       ins->cil_code = ip;
                                        /* FIXME: handle CEE_STIND_R4 */
                                        if (ins->opcode == CEE_STOBJ) {
                                                NEW_ARGLOADA (cfg, ins, i);
@@ -5733,7 +5831,6 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                                MONO_ADD_INS (bblock, ins);
                                }
                                MONO_INST_NEW (cfg, ins, OP_JMP);
-                               ins->cil_code = ip;
                                ins->inst_p0 = cmethod;
                                ins->inst_p1 = arg_array [0];
                                MONO_ADD_INS (bblock, ins);
@@ -5745,8 +5842,6 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                break;
                        }
                        if (cmethod && (cfg->opt & MONO_OPT_INTRINS) && (ins = mini_get_inst_for_method (cfg, cmethod, fsig, sp))) {
-                               ins->cil_code = ip;
-
                                if (MONO_TYPE_IS_VOID (fsig->ret)) {
                                        MONO_ADD_INS (bblock, ins);
                                } else {
@@ -5803,7 +5898,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
 
                        /* tail recursion elimination */
                        if ((cfg->opt & MONO_OPT_TAILC) && *ip == CEE_CALL && cmethod == method && ip [5] == CEE_RET &&
-                                       !rgctx_arg) {
+                                       !vtable_arg) {
                                gboolean has_vtargs = FALSE;
                                int i;
                                
@@ -5819,11 +5914,9 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                        for (i = 0; i < n; ++i) {
                                                /* FIXME: handle CEE_STIND_R4 */
                                                NEW_ARGSTORE (cfg, ins, i, sp [i]);
-                                               ins->cil_code = ip;
                                                MONO_ADD_INS (bblock, ins);
                                        }
                                        MONO_INST_NEW (cfg, ins, OP_BR);
-                                       ins->cil_code = ip;
                                        MONO_ADD_INS (bblock, ins);
                                        tblock = start_bblock->out_bb [0];
                                        link_bblock (cfg, bblock, tblock);
@@ -5849,50 +5942,55 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        else
                                no_spill = FALSE;
 
+                       /* FIXME: only do this for generic methods if
+                          they are not shared! */
                        if (context_used &&
                                        (cmethod->klass->valuetype ||
                                        (cmethod->is_inflated && mono_method_get_context (cmethod)->method_inst) ||
                                        ((cmethod->flags & METHOD_ATTRIBUTE_STATIC) &&
-                                               mono_class_generic_sharing_enabled (cmethod->klass)))) {
-                               MonoInst *this = NULL, *rgctx;
+                                               mono_class_generic_sharing_enabled (cmethod->klass)) ||
+                                       (!imt_arg && !mono_method_is_generic_sharable_impl (cmethod) &&
+                                               (!virtual || cmethod->flags & METHOD_ATTRIBUTE_FINAL ||
+                                               !(cmethod->flags & METHOD_ATTRIBUTE_VIRTUAL))))) {
+                               MonoInst *rgctx;
 
                                INLINE_FAILURE;
 
                                g_assert (cfg->generic_sharing_context && cmethod);
-                               g_assert (addr == NULL);
+                               g_assert (!addr);
 
                                /*
-                                * We are compiling a call to a
-                                * generic method from shared code,
-                                * which means that we have to look up
-                                * the method in the rgctx and do an
-                                * indirect call.
+                                * We are compiling a call to
+                                * non-shared generic code from shared
+                                * code, which means that we have to
+                                * look up the method in the rgctx and
+                                * do an indirect call.
                                 */
-
-                               GENERIC_SHARING_FAILURE_IF_VALUETYPE_METHOD (*ip);
-
-                               if (!(method->flags & METHOD_ATTRIBUTE_STATIC))
-                                       NEW_ARGLOAD (cfg, this, 0);
-                               rgctx = get_runtime_generic_context (cfg, method, this, ip);
+                               GET_RGCTX (rgctx);
                                addr = get_runtime_generic_context_method (cfg, method, bblock, cmethod,
                                                generic_context, rgctx, MONO_RGCTX_INFO_GENERIC_METHOD_CODE, ip);
+
                        }
 
                        if (addr) {
-                               if (*ip == CEE_CALL)
+                               g_assert (!imt_arg);
+
+                               if (*ip == CEE_CALL) {
                                        g_assert (context_used);
-                               else if (*ip == CEE_CALLI)
-                                       g_assert (!rgctx_arg);
-                               else
-                                       g_assert_not_reached ();
+                               } else if (*ip == CEE_CALLI) {
+                                       g_assert (!vtable_arg);
+                               } else {
+                                       g_assert (cmethod->flags & METHOD_ATTRIBUTE_FINAL ||
+                                                       !(cmethod->flags & METHOD_ATTRIBUTE_FINAL));
+                               }
 
                                /* Prevent inlining of methods with indirect calls */
                                INLINE_FAILURE;
                                if (no_spill) {
-                                       ins = (MonoInst*)mono_emit_rgctx_calli (cfg, bblock, fsig, sp, addr, rgctx_arg, ip);
+                                       ins = (MonoInst*)mono_emit_rgctx_calli (cfg, bblock, fsig, sp, addr, vtable_arg, ip);
                                        *sp++ = ins;                                    
                                } else {
-                                       temp = mono_emit_rgctx_calli_spilled (cfg, bblock, fsig, sp, addr, rgctx_arg, ip);
+                                       temp = mono_emit_rgctx_calli_spilled (cfg, bblock, fsig, sp, addr, vtable_arg, ip);
                                        if (temp != -1) {
                                                NEW_TEMPLOAD (cfg, *sp, temp);
                                                sp++;
@@ -5910,14 +6008,12 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                                
                                                array = mono_compile_create_var (cfg, type_from_stack_type (sp [0]), OP_LOCAL);
                                                NEW_TEMPSTORE (cfg, store, array->inst_c0, sp [0]);
-                                               store->cil_code = ip;
                                                MONO_ADD_INS (bblock, store);
                                                NEW_TEMPLOAD (cfg, iargs [0], array->inst_c0);
 
                                                to_store = mono_compile_create_var (cfg, type_from_stack_type (sp [fsig->param_count]), OP_LOCAL);
                                                NEW_TEMPSTORE (cfg, store, to_store->inst_c0, sp [fsig->param_count]);
                                                /* FIXME: handle CEE_STIND_R4 */
-                                               store->cil_code = ip;
                                                MONO_ADD_INS (bblock, store);
                                                NEW_TEMPLOAD (cfg, iargs [1], to_store->inst_c0);
 
@@ -5935,7 +6031,6 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
 
                                        addr = mini_get_ldelema_ins (cfg, bblock, cmethod, sp, ip, TRUE);
                                        NEW_INDSTORE (cfg, ins, addr, sp [fsig->param_count], fsig->params [fsig->param_count - 1]);
-                                       ins->cil_code = ip;
                                        /* FIXME: handle CEE_STIND_R4 */
                                        if (ins->opcode == CEE_STOBJ) {
                                                handle_stobj (cfg, bblock, addr, sp [fsig->param_count], ip, mono_class_from_mono_type (fsig->params [fsig->param_count-1]), FALSE, FALSE, TRUE);
@@ -5946,7 +6041,6 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                } else if (strcmp (cmethod->name, "Get") == 0) { /* array Get */
                                        addr = mini_get_ldelema_ins (cfg, bblock, cmethod, sp, ip, FALSE);
                                        NEW_INDLOAD (cfg, ins, addr, fsig->ret);
-                                       ins->cil_code = ip;
 
                                        *sp++ = ins;
                                } else if (strcmp (cmethod->name, "Address") == 0) { /* array Address */
@@ -5956,7 +6050,6 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                                mono_get_got_var (cfg);
 
                                                MONO_INST_NEW (cfg, check, OP_CHECK_ARRAY_TYPE);
-                                               check->cil_code = ip;
                                                check->klass = cmethod->klass;
                                                check->inst_left = sp [0];
                                                check->type = STACK_OBJ;
@@ -5979,10 +6072,12 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                                sp++;
                                        }
                                } else if (no_spill) {
-                                       ins = (MonoInst*)mono_emit_rgctx_method_call (cfg, bblock, cmethod, fsig, sp, rgctx_arg, ip, virtual ? sp [0] : NULL);
+                                       ins = (MonoInst*)mono_emit_rgctx_method_call (cfg, bblock, cmethod, fsig, sp,
+                                                       vtable_arg, imt_arg, ip, virtual ? sp [0] : NULL);
                                        *sp++ = ins;
                                } else {
-                                       if ((temp = mono_emit_rgctx_method_call_spilled (cfg, bblock, cmethod, fsig, sp, rgctx_arg, ip, virtual ? sp [0] : NULL)) != -1) {
+                                       if ((temp = mono_emit_rgctx_method_call_spilled (cfg, bblock, cmethod, fsig, sp,
+                                                       vtable_arg, imt_arg, ip, virtual ? sp [0] : NULL)) != -1) {
                                                MonoInst *load;
                                                NEW_TEMPLOAD (cfg, load, temp);
 
@@ -6039,7 +6134,6 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                                handle_stobj (cfg, bblock, ins, *sp, ip, cfg->ret->klass, FALSE, FALSE, FALSE);
                                        } else {
                                                ins->opcode = OP_SETRET;
-                                               ins->cil_code = ip;
                                                ins->inst_i0 = *sp;;
                                                ins->inst_i1 = NULL;
                                                MONO_ADD_INS (bblock, ins);
@@ -6049,7 +6143,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        if (sp != stack_start)
                                UNVERIFIED;
                        MONO_INST_NEW (cfg, ins, OP_BR);
-                       ins->cil_code = ip++;
+                       ip++;
                        ins->inst_target_bb = end_bblock;
                        MONO_ADD_INS (bblock, ins);
                        link_bblock (cfg, bblock, end_bblock);
@@ -6058,7 +6152,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                case CEE_BR_S:
                        CHECK_OPSIZE (2);
                        MONO_INST_NEW (cfg, ins, OP_BR);
-                       ins->cil_code = ip++;
+                       ip++;
                        MONO_ADD_INS (bblock, ins);
                        target = ip + 1 + (signed char)(*ip);
                        ++ip;
@@ -6081,7 +6175,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        if (sp [-1]->type == STACK_VTYPE || sp [-1]->type == STACK_R8)
                                UNVERIFIED;
                        MONO_INST_NEW (cfg, ins, *ip + BIG_BRANCH_OFFSET);
-                       ins->cil_code = ip++;
+                       ip++;
                        target = ip + 1 + *(signed char*)ip;
                        ip++;
                        ADD_UNCOND (ins->opcode == CEE_BRTRUE);
@@ -6105,7 +6199,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        CHECK_OPSIZE (2);
                        CHECK_STACK (2);
                        MONO_INST_NEW (cfg, ins, *ip + BIG_BRANCH_OFFSET);
-                       ins->cil_code = ip++;
+                       ip++;
                        target = ip + 1 + *(signed char*)ip;
                        ip++;
 #ifdef MONO_ARCH_SOFT_FLOAT
@@ -6134,7 +6228,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                case CEE_BR:
                        CHECK_OPSIZE (5);
                        MONO_INST_NEW (cfg, ins, OP_BR);
-                       ins->cil_code = ip++;
+                       ip++;
                        MONO_ADD_INS (bblock, ins);
                        target = ip + 4 + (gint32)read32(ip);
                        ip += 4;
@@ -6157,7 +6251,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        if (sp [-1]->type == STACK_VTYPE || sp [-1]->type == STACK_R8)
                                UNVERIFIED;
                        MONO_INST_NEW (cfg, ins, *ip);
-                       ins->cil_code = ip++;
+                       ip++;
                        target = ip + 4 + (gint32)read32(ip);
                        ip += 4;
                        ADD_UNCOND(ins->opcode == CEE_BRTRUE);
@@ -6181,7 +6275,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        CHECK_OPSIZE (5);
                        CHECK_STACK (2);
                        MONO_INST_NEW (cfg, ins, *ip);
-                       ins->cil_code = ip++;
+                       ip++;
                        target = ip + 4 + (gint32)read32(ip);
                        ip += 4;
 #ifdef MONO_ARCH_SOFT_FLOAT
@@ -6216,7 +6310,6 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        ins->inst_left = *sp;
                        if ((ins->inst_left->type != STACK_I4) && (ins->inst_left->type != STACK_PTR)) 
                                UNVERIFIED;
-                       ins->cil_code = ip;
                        ip += 5;
                        CHECK_OPSIZE (n * sizeof (guint32));
                        target = ip + n * sizeof (guint32);
@@ -6255,7 +6348,6 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                case CEE_LDIND_REF:
                        CHECK_STACK (1);
                        MONO_INST_NEW (cfg, ins, *ip);
-                       ins->cil_code = ip;
                        --sp;
                        ins->inst_i0 = *sp;
                        *sp++ = ins;
@@ -6302,7 +6394,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        }
 #endif
                        MONO_INST_NEW (cfg, ins, *ip);
-                       ins->cil_code = ip++;
+                       ip++;
                        sp -= 2;
                        handle_loaded_temps (cfg, bblock, stack_start, sp);
                        MONO_ADD_INS (bblock, ins);
@@ -6446,13 +6538,11 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        if (generic_class_is_reference_type (cfg, klass)) {
                                MonoInst *store, *load;
                                MONO_INST_NEW (cfg, load, CEE_LDIND_REF);
-                               load->cil_code = ip;
                                load->inst_i0 = sp [1];
                                load->type = STACK_OBJ;
                                load->klass = klass;
                                load->flags |= ins_flag;
                                MONO_INST_NEW (cfg, store, CEE_STIND_REF);
-                               store->cil_code = ip;
                                handle_loaded_temps (cfg, bblock, stack_start, sp);
                                MONO_ADD_INS (bblock, store);
                                store->inst_i0 = sp [0];
@@ -6472,7 +6562,6 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                        iargs [0] = sp [0];
                                        iargs [1] = sp [1];
                                        NEW_ICONST (cfg, iargs [2], n);
-                                       iargs [2]->cil_code = ip;
 
                                        mono_emit_method_call_spilled (cfg, bblock, memcpy_method, memcpy_method->signature, iargs, ip, NULL);
                                }
@@ -6494,7 +6583,6 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        CHECK_TYPELOAD (klass);
                        if (generic_class_is_reference_type (cfg, klass)) {
                                MONO_INST_NEW (cfg, ins, CEE_LDIND_REF);
-                               ins->cil_code = ip;
                                ins->inst_i0 = sp [0];
                                ins->type = STACK_OBJ;
                                ins->klass = klass;
@@ -6529,7 +6617,6 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                /* FIXME: handle CEE_STIND_R4 */
                                if (ins->opcode == CEE_STOBJ) {
                                        handle_loaded_temps (cfg, bblock, stack_start, sp);
-                                       ins->cil_code = ip;
                                        g_assert (ins->opcode == CEE_STOBJ);
                                        NEW_LOCLOADA (cfg, ins, loc_index);
                                        handle_stobj (cfg, bblock, ins, *sp, ip, ins->klass, FALSE, FALSE, FALSE);
@@ -6550,7 +6637,6 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                MonoMethod *memcpy_method = get_memcpy_method ();
                                iargs [1] = *sp;
                                NEW_ICONST (cfg, iargs [2], n);
-                               iargs [2]->cil_code = ip;
 
                                mono_emit_method_call_spilled (cfg, bblock, memcpy_method, memcpy_method->signature, iargs, ip, NULL);
                        }
@@ -6569,7 +6655,6 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        if (method->wrapper_type == MONO_WRAPPER_DYNAMIC_METHOD) {
                                /* FIXME: moving GC */
                                NEW_PCONST (cfg, ins, mono_method_get_wrapper_data (method, n));
-                               ins->cil_code = ip;
                                ins->type = STACK_OBJ;
                                ins->klass = mono_defaults.string_class;
                                *sp = ins;
@@ -6628,7 +6713,6 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                        } 
                                        else {
                                                NEW_PCONST (cfg, ins, NULL);
-                                               ins->cil_code = ip;
                                                ins->type = STACK_OBJ;
                                                ins->inst_p0 = mono_ldstr (cfg->domain, image, mono_metadata_token_index (n));
                                                ins->klass = mono_defaults.string_class;
@@ -6648,7 +6732,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
 
                        CHECK_OPSIZE (5);
                        token = read32 (ip + 1);
-                       cmethod = mini_get_method (method, token, NULL, generic_context);
+                       cmethod = mini_get_method (cfg, method, token, NULL, generic_context);
                        if (!cmethod)
                                goto load_error;
                        fsig = mono_method_get_signature (cmethod, image, token);
@@ -6755,21 +6839,24 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                         * will be transformed into a normal call there.
                                         */
                                } else if (generic_shared) {
-                                       MonoInst *this = NULL, *rgctx, *vtable;
-
-                                       GENERIC_SHARING_FAILURE_IF_VALUETYPE_METHOD (*ip);
+                                       MonoInst *rgctx, *data;
+                                       int rgctx_info;
 
-                                       if (!(method->flags & METHOD_ATTRIBUTE_STATIC))
-                                               NEW_ARGLOAD (cfg, this, 0);
-                                       rgctx = get_runtime_generic_context (cfg, method, this, ip);
-                                       vtable = get_runtime_generic_context_ptr (cfg, method, bblock, cmethod->klass,
+                                       GET_RGCTX (rgctx);
+                                       if (cfg->opt & MONO_OPT_SHARED)
+                                               rgctx_info = MONO_RGCTX_INFO_KLASS;
+                                       else
+                                               rgctx_info = MONO_RGCTX_INFO_VTABLE;
+                                       data = get_runtime_generic_context_ptr (cfg, method, bblock, cmethod->klass,
                                                token, MINI_TOKEN_SOURCE_METHOD, generic_context,
-                                               rgctx, MONO_RGCTX_INFO_VTABLE, ip);
+                                               rgctx, rgctx_info, ip);
 
-                                       temp = handle_alloc_from_inst (cfg, bblock, cmethod->klass, vtable, FALSE, ip);
+                                       temp = handle_alloc_from_inst (cfg, bblock, cmethod->klass, data, FALSE, ip);
                                        NEW_TEMPLOAD (cfg, *sp, temp);
                                } else {
                                        MonoVTable *vtable = mono_class_vtable (cfg->domain, cmethod->klass);
+
+                                       CHECK_TYPELOAD (cmethod->klass);
                                        if (mini_field_access_needs_cctor_run (cfg, method, vtable) && !(g_slist_find (class_inits, vtable))) {
                                                guint8 *tramp = mono_create_class_init_trampoline (vtable);
                                                mono_emit_native_call (cfg, bblock, tramp, 
@@ -6817,7 +6904,9 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                                INLINE_FAILURE;
                                                mono_emit_method_call_spilled (cfg, bblock, cmethod, fsig, sp, ip, callvirt_this_arg);
                                        }
-                               } else if (generic_shared && cmethod->klass->valuetype) {
+                               } else if (generic_shared &&
+                                               (cmethod->klass->valuetype ||
+                                               !mono_method_is_generic_sharable_impl (cmethod))) {
                                        MonoInst *this = NULL, *rgctx, *cmethod_addr;
 
                                        g_assert (!callvirt_this_arg);
@@ -6930,7 +7019,6 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                ins->inst_left = *sp;
                                ins->inst_newa_class = klass;
                                ins->klass = klass;
-                               ins->cil_code = ip;
                                *sp++ = emit_tree (cfg, bblock, ins, ip + 5);
                                ip += 5;
                        }
@@ -6940,6 +7028,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        MonoInst *add, *vtoffset;
                        MonoInst *iargs [3];
                        guint32 align;
+                       int context_used = 0;
 
                        CHECK_STACK (1);
                        --sp;
@@ -6948,72 +7037,86 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        klass = mini_get_class (method, token, generic_context);
                        CHECK_TYPELOAD (klass);
 
-                       if (cfg->generic_sharing_context && mono_class_check_context_used (klass))
-                               GENERIC_SHARING_FAILURE (CEE_UNBOX_ANY);
+                       if (cfg->generic_sharing_context) {
+                               context_used = mono_class_check_context_used (klass);
+
+                               if (context_used & MONO_GENERIC_CONTEXT_USED_METHOD)
+                                       GENERIC_SHARING_FAILURE (CEE_UNBOX_ANY);
+                       }
 
                        if (generic_class_is_reference_type (cfg, klass)) {
-                               /* CASTCLASS */
-                               if (klass->marshalbyref || klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
-                                       MonoMethod *mono_castclass;
-                                       MonoInst *iargs [1];
-                                       MonoBasicBlock *ebblock;
-                                       int costs;
-                                       int temp;
-                                       
-                                       mono_castclass = mono_marshal_get_castclass (klass); 
-                                       iargs [0] = sp [0];
-                                       
-                                       costs = inline_method (cfg, mono_castclass, mono_method_signature (mono_castclass), bblock, 
-                                                       iargs, ip, real_offset, dont_inline, &ebblock, TRUE);
-                               
-                                       g_assert (costs > 0);
-                                       
-                                       ip += 5;
-                                       real_offset += 5;
-                               
-                                       GET_BBLOCK (cfg, bblock, ip);
-                                       ebblock->next_bb = bblock;
-                                       link_bblock (cfg, ebblock, bblock);
-       
-                                       temp = iargs [0]->inst_i0->inst_c0;
-                                       NEW_TEMPLOAD (cfg, *sp, temp);
-                                       
-                                       sp++;
-                                       bblock = ebblock;
-                                       inline_costs += costs;                          
-                               } else {
-                                       /* Needed by the code generated in inssel.brg */
-                                       mono_get_got_var (cfg);
-               
-                                       MONO_INST_NEW (cfg, ins, CEE_CASTCLASS);
-                                       ins->type = STACK_OBJ;
-                                       ins->inst_left = *sp;
-                                       ins->klass = klass;
-                                       ins->inst_newa_class = klass;
-                                       ins->cil_code = ip;
-                                       *sp++ = ins;
-                                       ip += 5;
+                               if (context_used)
+                                       GENERIC_SHARING_FAILURE_IF_VALUETYPE_METHOD (CEE_UNBOX_ANY);
+                               switch (emit_castclass (klass, token, context_used, FALSE,
+                                               cfg, method, arg_array, param_types, dont_inline, end, header,
+                                               generic_context, &bblock, &ip, &sp, &inline_costs, &real_offset)) {
+                               case 0: break;
+                               case -1: goto unverified;
+                               default: g_assert_not_reached ();
                                }
                                break;
                        }
 
                        if (mono_class_is_nullable (klass)) {
-                               int v = handle_unbox_nullable (cfg, bblock, *sp, ip, klass);
+                               int v;
+                               MonoInst *rgctx = NULL;
+
+                               if (context_used) {
+                                       MonoInst *this = NULL;
+
+                                       if (!(method->flags & METHOD_ATTRIBUTE_STATIC))
+                                               NEW_ARGLOAD (cfg, this, 0);
+                                       rgctx = get_runtime_generic_context (cfg, method, this, ip);
+                               }
+
+                               v = handle_unbox_nullable (cfg, method, bblock, *sp, ip, klass, generic_context, rgctx);
                                NEW_TEMPLOAD (cfg, *sp, v);
                                sp ++;
                                ip += 5;
                                break;
                        }
 
-                       /* Needed by the code generated in inssel.brg */
-                       mono_get_got_var (cfg);
+                       /* Needed by the code generated in inssel.brg */
+                       mono_get_got_var (cfg);
+
+                       if (context_used) {
+                               MonoInst *this = NULL, *rgctx;
+                               MonoInst *element_class;
+
+                               GENERIC_SHARING_FAILURE_IF_VALUETYPE_METHOD (CEE_UNBOX_ANY);
 
-                       MONO_INST_NEW (cfg, ins, OP_UNBOXCAST);
-                       ins->type = STACK_OBJ;
-                       ins->inst_left = *sp;
-                       ins->klass = klass;
-                       ins->inst_newa_class = klass;
-                       ins->cil_code = ip;
+                               /* This assertion is from the
+                                  unboxcast insn */
+                               g_assert (klass->rank == 0);
+
+                               if (!(method->flags & METHOD_ATTRIBUTE_STATIC))
+                                       NEW_ARGLOAD (cfg, this, 0);
+                               rgctx = get_runtime_generic_context (cfg, method, this, ip);
+                               /* FIXME: Passing token here is
+                                  technically not correct, because we
+                                  don't use klass but
+                                  klass->element_class.  Since it's
+                                  only used by code for debugging the
+                                  extensible runtime generic context
+                                  it's not a big deal.  To be correct
+                                  we'd have to invent a new token
+                                  source. */
+                               element_class = get_runtime_generic_context_ptr (cfg, method, bblock,
+                                       klass->element_class, token, MINI_TOKEN_SOURCE_CLASS,
+                                       generic_context, rgctx, MONO_RGCTX_INFO_KLASS, ip);
+
+                               MONO_INST_NEW (cfg, ins, OP_UNBOXCAST_REG);
+                               ins->type = STACK_OBJ;
+                               ins->inst_left = *sp;
+                               ins->inst_right = element_class;
+                               ins->klass = klass;
+                       } else {
+                               MONO_INST_NEW (cfg, ins, OP_UNBOXCAST);
+                               ins->type = STACK_OBJ;
+                               ins->inst_left = *sp;
+                               ins->klass = klass;
+                               ins->inst_newa_class = klass;
+                       }
 
                        MONO_INST_NEW (cfg, add, OP_PADD);
                        NEW_ICONST (cfg, vtoffset, sizeof (MonoObject));
@@ -7035,7 +7138,6 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                MonoMethod *memcpy_method = get_memcpy_method ();
                                iargs [1] = *sp;
                                NEW_ICONST (cfg, iargs [2], n);
-                               iargs [2]->cil_code = ip;
 
                                mono_emit_method_call_spilled (cfg, bblock, memcpy_method, memcpy_method->signature, iargs, ip, NULL);
                        }
@@ -7058,7 +7160,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                GENERIC_SHARING_FAILURE (CEE_UNBOX);
 
                        if (mono_class_is_nullable (klass)) {
-                               int v = handle_unbox_nullable (cfg, bblock, *sp, ip, klass);
+                               int v = handle_unbox_nullable (cfg, method, bblock, *sp, ip, klass, generic_context, NULL);
                                NEW_TEMPLOAD (cfg, *sp, v);
                                sp ++;
                                ip += 5;
@@ -7073,7 +7175,6 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        ins->inst_left = *sp;
                        ins->klass = klass;
                        ins->inst_newa_class = klass;
-                       ins->cil_code = ip;
 
                        MONO_INST_NEW (cfg, add, OP_PADD);
                        NEW_ICONST (cfg, vtoffset, sizeof (MonoObject));
@@ -7086,7 +7187,9 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        inline_costs += 2;
                        break;
                }
-               case CEE_CASTCLASS:
+               case CEE_CASTCLASS: {
+                       gboolean shared_access = FALSE;
+
                        CHECK_STACK (1);
                        --sp;
                        CHECK_OPSIZE (5);
@@ -7096,59 +7199,33 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        if (sp [0]->type != STACK_OBJ)
                                UNVERIFIED;
 
-                       if (cfg->generic_sharing_context && mono_class_check_context_used (klass))
-                               GENERIC_SHARING_FAILURE (CEE_CASTCLASS);
+                       if (cfg->generic_sharing_context) {
+                               int context_used = mono_class_check_context_used (klass);
 
-                       /* Needed by the code generated in inssel.brg */
-                       mono_get_got_var (cfg);
-               
-                       if (klass->marshalbyref || klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
-                               
-                               MonoMethod *mono_castclass;
-                               MonoInst *iargs [1];
-                               MonoBasicBlock *ebblock;
-                               int costs;
-                               int temp;
-                               
-                               mono_castclass = mono_marshal_get_castclass (klass); 
-                               iargs [0] = sp [0];
-                               
-                               costs = inline_method (cfg, mono_castclass, mono_method_signature (mono_castclass), bblock, 
-                                               iargs, ip, real_offset, dont_inline, &ebblock, TRUE);
-                       
-                               g_assert (costs > 0);
-                               
-                               ip += 5;
-                               real_offset += 5;
-                       
-                               GET_BBLOCK (cfg, bblock, ip);
-                               ebblock->next_bb = bblock;
-                               link_bblock (cfg, ebblock, bblock);
+                               if (context_used & MONO_GENERIC_CONTEXT_USED_METHOD)
+                                       GENERIC_SHARING_FAILURE (CEE_CASTCLASS);
 
-                               temp = iargs [0]->inst_i0->inst_c0;
-                               NEW_TEMPLOAD (cfg, *sp, temp);
-                               
-                               sp++;
-                               bblock = ebblock;
-                               inline_costs += costs;
-                       } else {
-                               MONO_INST_NEW (cfg, ins, *ip);
-                               ins->type = STACK_OBJ;
-                               ins->inst_left = *sp;
-                               ins->klass = klass;
-                               ins->inst_newa_class = klass;
-                               ins->backend.record_cast_details = debug_options.better_cast_details;
-                               ins->cil_code = ip;
-                               *sp++ = emit_tree (cfg, bblock, ins, ip + 5);
-                               ip += 5;
+                               if (context_used) {
+                                       shared_access = TRUE;
+                                       GENERIC_SHARING_FAILURE_IF_VALUETYPE_METHOD (*ip);
+                               }
+                       }
+
+                       switch (emit_castclass (klass, token, shared_access, TRUE,
+                                       cfg, method, arg_array, param_types, dont_inline, end, header,
+                                       generic_context, &bblock, &ip, &sp, &inline_costs, &real_offset)) {
+                       case 0: break;
+                       case -1: goto unverified;
+                       default: g_assert_not_reached ();
                        }
                        break;
+               }
                case CEE_THROW:
                        CHECK_STACK (1);
                        MONO_INST_NEW (cfg, ins, OP_THROW);
                        --sp;
                        ins->inst_left = *sp;
-                       ins->cil_code = ip++;
+                       ip++;
                        bblock->out_of_line = TRUE;
                        MONO_ADD_INS (bblock, ins);
                        MONO_INST_NEW (cfg, ins, OP_NOT_REACHED);
@@ -7231,13 +7308,12 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                                mono_emit_method_call_spilled (cfg, bblock, stfld_wrapper, mono_method_signature (stfld_wrapper), iargs, ip, NULL);
                                        }
 #if HAVE_WRITE_BARRIERS
-                               } else if (mini_type_to_stind (cfg, field->type) == CEE_STIND_REF) {
+                               } else if (mini_type_to_stind (cfg, field->type) == CEE_STIND_REF && !(sp [1]->opcode == OP_PCONST && sp [1]->inst_c0 == 0)) {
                                        /* insert call to write barrier */
                                        MonoMethod *write_barrier = mono_marshal_get_write_barrier ();
                                        MonoInst *iargs [2];
                                        NEW_ICONST (cfg, offset_ins, foffset);
                                        MONO_INST_NEW (cfg, ins, OP_PADD);
-                                       ins->cil_code = ip;
                                        ins->inst_left = *sp;
                                        ins->inst_right = offset_ins;
                                        ins->type = STACK_MP;
@@ -7250,7 +7326,6 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                } else if (mini_type_to_stind (cfg, field->type) == CEE_STIND_R4) {
                                        NEW_ICONST (cfg, offset_ins, foffset);
                                        MONO_INST_NEW (cfg, ins, OP_PADD);
-                                       ins->cil_code = ip;
                                        ins->inst_left = *sp;
                                        ins->inst_right = offset_ins;
                                        ins->type = STACK_MP;
@@ -7261,13 +7336,11 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                        MonoInst *store;
                                        NEW_ICONST (cfg, offset_ins, foffset);
                                        MONO_INST_NEW (cfg, ins, OP_PADD);
-                                       ins->cil_code = ip;
                                        ins->inst_left = *sp;
                                        ins->inst_right = offset_ins;
                                        ins->type = STACK_MP;
 
                                        MONO_INST_NEW (cfg, store, mini_type_to_stind (cfg, field->type));
-                                       store->cil_code = ip;
                                        store->inst_left = ins;
                                        store->inst_right = sp [1];
                                        handle_loaded_temps (cfg, bblock, stack_start, sp);
@@ -7320,7 +7393,6 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                } else {
                                        NEW_ICONST (cfg, offset_ins, foffset);
                                        MONO_INST_NEW (cfg, ins, OP_PADD);
-                                       ins->cil_code = ip;
                                        ins->inst_left = *sp;
                                        ins->inst_right = offset_ins;
                                        ins->type = STACK_MP;
@@ -7332,7 +7404,6 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                                MonoInst *load;
                                                MONO_INST_NEW (cfg, load, mini_type_to_ldind (cfg, field->type));
                                                type_to_eval_stack_type (cfg, field->type, load);
-                                               load->cil_code = ip;
                                                load->inst_left = ins;
                                                load->flags |= ins_flag;
                                                ins_flag = 0;
@@ -7357,7 +7428,6 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        MonoClassField *field;
                        gpointer addr = NULL;
                        gboolean shared_access = FALSE;
-                       int relation = 0;
 
                        CHECK_OPSIZE (5);
                        token = read32 (ip + 1);
@@ -7390,11 +7460,8 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                                klass->valuetype)
                                        GENERIC_SHARING_FAILURE (*ip);
 
-                               if (context_used) {
-                                       relation = mono_class_generic_class_relation (klass, MONO_RGCTX_INFO_VTABLE,
-                                               method->klass, generic_context, NULL);
+                               if (context_used)
                                        shared_access = TRUE;
-                               }
                        }
 
                        g_assert (!(field->type->attrs & FIELD_ATTRIBUTE_LITERAL));
@@ -7405,14 +7472,36 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        /* The special_static_fields field is init'd in mono_class_vtable, so it needs
                         * to be called here.
                         */
-                       if (!(cfg->opt & MONO_OPT_SHARED))
+                       if (!(cfg->opt & MONO_OPT_SHARED)) {
                                mono_class_vtable (cfg->domain, klass);
+                               CHECK_TYPELOAD (klass);
+                       }
                        mono_domain_lock (cfg->domain);
                        if (cfg->domain->special_static_fields)
                                addr = g_hash_table_lookup (cfg->domain->special_static_fields, field);
                        mono_domain_unlock (cfg->domain);
 
-                       if (shared_access) {
+                       if ((cfg->opt & MONO_OPT_SHARED) || (cfg->compile_aot && addr)) {
+                               int temp;
+                               MonoInst *iargs [2];
+                               MonoInst *domain_var;
+
+                               g_assert (field->parent);
+                               /* avoid depending on undefined C behavior in sequence points */
+                               domain_var = mono_get_domainvar (cfg);
+                               NEW_TEMPLOAD (cfg, iargs [0], domain_var->inst_c0);
+                               if (shared_access) {
+                                       MonoInst *rgctx;
+
+                                       GET_RGCTX (rgctx);
+                                       iargs [1] = get_runtime_generic_context_field (cfg, method, bblock, field,
+                                                       generic_context, rgctx, MONO_RGCTX_INFO_CLASS_FIELD, ip);
+                               } else {
+                                       NEW_FIELDCONST (cfg, iargs [1], field);
+                               }
+                               temp = mono_emit_jit_icall (cfg, bblock, mono_class_static_field_address, iargs, ip);
+                               NEW_TEMPLOAD (cfg, ins, temp);
+                       } else if (shared_access) {
                                MonoInst *this, *rgctx, *static_data;
 
                                GENERIC_SHARING_FAILURE_IF_VALUETYPE_METHOD (*ip);
@@ -7426,26 +7515,17 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                if (mono_class_needs_cctor_run (klass, method)) {
                                        MonoMethodSignature *sig = helper_sig_generic_class_init_trampoline;
                                        MonoCallInst *call;
-                                       MonoInst *vtable;
+                                       MonoInst *vtable, *rgctx;
 
                                        if (!(method->flags & METHOD_ATTRIBUTE_STATIC))
                                                NEW_ARGLOAD (cfg, this, 0);
                                        else
                                                this = NULL;
 
-                                       if (relation == MINI_GENERIC_CLASS_RELATION_SELF && this) {
-                                               MONO_INST_NEW (cfg, vtable, CEE_LDIND_I);
-                                               vtable->cil_code = ip;
-                                               vtable->inst_left = this;
-                                               vtable->type = STACK_PTR;
-                                               vtable->klass = klass;
-                                       } else {
-                                               MonoInst *rgctx = get_runtime_generic_context (cfg, method, this, ip);
-
-                                               vtable = get_runtime_generic_context_ptr (cfg, method, bblock, klass,
+                                       rgctx = get_runtime_generic_context (cfg, method, this, ip);
+                                       vtable = get_runtime_generic_context_ptr (cfg, method, bblock, klass,
                                                        token, MINI_TOKEN_SOURCE_FIELD, generic_context,
                                                        rgctx, MONO_RGCTX_INFO_VTABLE, ip);
-                                       }
 
                                        call = mono_emit_call_args (cfg, bblock, sig, NULL, FALSE, FALSE, ip, FALSE);
                                        call->inst.opcode = OP_TRAMPCALL_VTABLE;
@@ -7479,27 +7559,16 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                        NEW_ICONST (cfg, field_offset, field->offset);
 
                                        MONO_INST_NEW (cfg, ins, OP_PADD);
-                                       ins->cil_code = ip;
                                        ins->inst_left = static_data;
                                        ins->inst_right = field_offset;
                                        ins->type = STACK_PTR;
                                        ins->klass = klass;
                                }
-                       } else if ((cfg->opt & MONO_OPT_SHARED) || (cfg->compile_aot && addr)) {
-                               int temp;
-                               MonoInst *iargs [2];
-                               MonoInst *domain_var;
-                               
-                               g_assert (field->parent);
-                               /* avoid depending on undefined C behavior in sequence points */
-                               domain_var = mono_get_domainvar (cfg);
-                               NEW_TEMPLOAD (cfg, iargs [0], domain_var->inst_c0);
-                               NEW_FIELDCONST (cfg, iargs [1], field);
-                               temp = mono_emit_jit_icall (cfg, bblock, mono_class_static_field_address, iargs, ip);
-                               NEW_TEMPLOAD (cfg, ins, temp);
                        } else {
                                MonoVTable *vtable;
+
                                vtable = mono_class_vtable (cfg->domain, klass);
+                               CHECK_TYPELOAD (klass);
                                if (!addr) {
                                        if (mini_field_access_needs_cctor_run (cfg, method, vtable) && !(g_slist_find (class_inits, vtable))) {
                                                guint8 *tramp = mono_create_class_init_trampoline (vtable);
@@ -7525,7 +7594,6 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                                NEW_SFLDACONST (cfg, ins, field);
                                        else
                                                NEW_PCONST (cfg, ins, addr);
-                                       ins->cil_code = ip;
                                } else {
                                        /* 
                                         * insert call to mono_threads_get_static_data (GPOINTER_TO_UINT (addr)) 
@@ -7549,7 +7617,6 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                CHECK_STACK (1);
                                sp--;
                                MONO_INST_NEW (cfg, store, mini_type_to_stind (cfg, field->type));
-                               store->cil_code = ip;
                                store->inst_left = ins;
                                store->inst_right = sp [0];
                                store->flags |= ins_flag;
@@ -7567,6 +7634,8 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        } else {
                                gboolean is_const = FALSE;
                                MonoVTable *vtable = mono_class_vtable (cfg->domain, klass);
+
+                               CHECK_TYPELOAD (klass);
                                if (!shared_access && !((cfg->opt & MONO_OPT_SHARED) || cfg->compile_aot) && 
                                    vtable->initialized && (field->type->attrs & FIELD_ATTRIBUTE_INIT_ONLY)) {
                                        gpointer addr = (char*)vtable->data + field->offset;
@@ -7640,7 +7709,6 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                        CHECK_STACK_OVF (1);
                                        MONO_INST_NEW (cfg, load, mini_type_to_ldind (cfg, field->type));
                                        type_to_eval_stack_type (cfg, field->type, load);
-                                       load->cil_code = ip;
                                        load->inst_left = ins;
                                        load->flags |= ins_flag;
 #ifdef MONO_ARCH_SOFT_FLOAT
@@ -7672,7 +7740,6 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                /* FIXME: should check item at sp [1] is compatible with the type of the store. */
                                MonoInst *store;
                                MONO_INST_NEW (cfg, store, n);
-                               store->cil_code = ip;
                                store->inst_left = sp [0];
                                store->inst_right = sp [1];
                                store->flags |= ins_flag;
@@ -7684,7 +7751,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        break;
                case CEE_BOX: {
                        MonoInst *val;
-                       gboolean generic_shared = FALSE;
+                       int context_used = 0;
 
                        CHECK_STACK (1);
                        --sp;
@@ -7694,11 +7761,11 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        klass = mini_get_class (method, token, generic_context);
                        CHECK_TYPELOAD (klass);
 
-                       if (cfg->generic_sharing_context && mono_class_check_context_used (klass)) {
-                               if (mono_class_is_nullable (klass))
-                                       GENERIC_SHARING_FAILURE (CEE_BOX);
-                               else
-                                       generic_shared = TRUE;
+                       if (cfg->generic_sharing_context) {
+                               context_used = mono_class_check_context_used (klass);
+
+                               if (context_used & MONO_GENERIC_CONTEXT_USED_METHOD)
+                                       GENERIC_SHARING_FAILURE (*ip);
                        }
 
                        if (generic_class_is_reference_type (cfg, klass)) {
@@ -7716,11 +7783,10 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                /*g_print ("box-brtrue opt at 0x%04x in %s\n", real_offset, method->name);*/
                                MONO_INST_NEW (cfg, ins, CEE_POP);
                                MONO_ADD_INS (bblock, ins);
-                               ins->cil_code = ip;
                                ins->inst_i0 = *sp;
                                ip += 5;
+                               cfg->ip = ip;
                                MONO_INST_NEW (cfg, ins, OP_BR);
-                               ins->cil_code = ip;
                                MONO_ADD_INS (bblock, ins);
                                if (*ip == CEE_BRTRUE_S) {
                                        CHECK_OPSIZE (2);
@@ -7747,19 +7813,28 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                start_new_bblock = 1;
                                break;
                        }
-                       if (generic_shared) {
-                               MonoInst *this = NULL, *rgctx, *vtable;
+                       if (context_used) {
+                               MonoInst *rgctx;
 
-                               GENERIC_SHARING_FAILURE_IF_VALUETYPE_METHOD (*ip);
+                               if (mono_class_is_nullable (klass)) {
+                                       GET_RGCTX (rgctx);
+                                       *sp++ = handle_box_nullable_from_inst (cfg, method, context_used, bblock, val,
+                                                       ip, klass, generic_context, rgctx);
+                               } else {
+                                       MonoInst *data;
+                                       int rgctx_info;
 
-                               if (!(method->flags & METHOD_ATTRIBUTE_STATIC))
-                                       NEW_ARGLOAD (cfg, this, 0);
-                               rgctx = get_runtime_generic_context (cfg, method, this, ip);
-                               vtable = get_runtime_generic_context_ptr (cfg, method, bblock, klass,
-                                       token, MINI_TOKEN_SOURCE_CLASS, generic_context,
-                                       rgctx, MONO_RGCTX_INFO_VTABLE, ip);
+                                       GET_RGCTX (rgctx);
+                                       if (cfg->opt & MONO_OPT_SHARED)
+                                               rgctx_info = MONO_RGCTX_INFO_KLASS;
+                                       else
+                                               rgctx_info = MONO_RGCTX_INFO_VTABLE;
+                                       data = get_runtime_generic_context_ptr (cfg, method, bblock, klass,
+                                                       token, MINI_TOKEN_SOURCE_CLASS, generic_context,
+                                                       rgctx, rgctx_info, ip);
 
-                               *sp++ = handle_box_from_inst (cfg, bblock, val, ip, klass, vtable);
+                                       *sp++ = handle_box_from_inst (cfg, bblock, val, ip, klass, data);
+                               }
                        } else {
                                *sp++ = handle_box (cfg, bblock, val, ip, klass);
                        }
@@ -7823,7 +7898,6 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                NEW_TEMPLOAD (cfg, ins, temp);
                        } else {
                                MONO_INST_NEW (cfg, ins, *ip);
-                               ins->cil_code = ip;
                                ins->inst_newa_class = klass;
                                ins->inst_newa_len = *sp;
                                ins->type = STACK_OBJ;
@@ -7862,7 +7936,6 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                        MONO_INST_NEW (cfg, add, OP_PADD);
                                        add->inst_left = load;
                                        add->inst_right = data_offset;
-                                       add->cil_code = ip;
                                        iargs [0] = add;
                                        if (cfg->compile_aot) {
                                                NEW_AOTCONST_TOKEN (cfg, iargs [1], MONO_PATCH_INFO_RVA, method->klass->image, GPOINTER_TO_UINT(data_ptr), STACK_PTR, NULL);
@@ -7885,7 +7958,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        if (sp [0]->type != STACK_OBJ)
                                UNVERIFIED;
                        MONO_INST_NEW (cfg, ins, *ip);
-                       ins->cil_code = ip++;
+                       ip++;
                        ins->inst_left = *sp;
                        ins->type = STACK_PTR;
                        *sp++ = ins;
@@ -7910,7 +7983,6 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                mono_get_got_var (cfg);
 
                                MONO_INST_NEW (cfg, check, OP_CHECK_ARRAY_TYPE);
-                               check->cil_code = ip;
                                check->klass = mono_array_class_get (klass, 1);
                                check->inst_left = sp [0];
                                check->type = STACK_OBJ;
@@ -7920,7 +7992,6 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        readonly = FALSE;
                        mono_class_init (klass);
                        NEW_LDELEMA (cfg, ins, sp, klass);
-                       ins->cil_code = ip;
                        *sp++ = ins;
                        ip += 5;
                        break;
@@ -7936,9 +8007,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        CHECK_TYPELOAD (klass);
                        mono_class_init (klass);
                        NEW_LDELEMA (cfg, load, sp, klass);
-                       load->cil_code = ip;
                        MONO_INST_NEW (cfg, ins, mini_type_to_ldind (cfg, &klass->byval_arg));
-                       ins->cil_code = ip;
                        ins->inst_left = load;
                        *sp++ = ins;
                        type_to_eval_stack_type (cfg, &klass->byval_arg, ins);
@@ -7968,7 +8037,6 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                UNVERIFIED;
                        klass = array_access_to_klass (*ip, sp [0]);
                        NEW_LDELEMA (cfg, load, sp, klass);
-                       load->cil_code = ip;
 #ifdef MONO_ARCH_SOFT_FLOAT
                        if (*ip == CEE_LDELEM_R4) {
                                int temp;
@@ -7980,7 +8048,6 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        }
 #endif
                        MONO_INST_NEW (cfg, ins, ldelem_to_ldind [*ip - CEE_LDELEM_I1]);
-                       ins->cil_code = ip;
                        ins->inst_left = load;
                        *sp++ = ins;
                        ins->type = ldind_type [ins->opcode - CEE_LDIND_I1];
@@ -8007,7 +8074,6 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                UNVERIFIED;
                        klass = array_access_to_klass (*ip, sp [0]);
                        NEW_LDELEMA (cfg, load, sp, klass);
-                       load->cil_code = ip;
 #ifdef MONO_ARCH_SOFT_FLOAT
                        if (*ip == CEE_STELEM_R4) {
                                handle_store_float (cfg, bblock, load, sp [2], ip);
@@ -8016,7 +8082,6 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        }
 #endif
                        MONO_INST_NEW (cfg, ins, stelem_to_stind [*ip - CEE_STELEM_I]);
-                       ins->cil_code = ip;
                        ins->inst_left = load;
                        ins->inst_right = sp [2];
                        ++ip;
@@ -8046,9 +8111,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                if (sp [2]->opcode == OP_PCONST && sp [2]->inst_p0 == NULL) {
                                        MonoInst *load;
                                        NEW_LDELEMA (cfg, load, sp, mono_defaults.object_class);
-                                       load->cil_code = ip;
                                        MONO_INST_NEW (cfg, ins, stelem_to_stind [*ip - CEE_STELEM_I]);
-                                       ins->cil_code = ip;
                                        ins->inst_left = load;
                                        ins->inst_right = sp [2];
                                        MONO_ADD_INS (bblock, ins);
@@ -8065,7 +8128,6 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                }
                        } else {
                                NEW_LDELEMA (cfg, load, sp, klass);
-                               load->cil_code = ip;
 
                                n = mini_type_to_stind (cfg, &klass->byval_arg);
                                /* FIXME: CEE_STIND_R4 */
@@ -8073,7 +8135,6 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                        handle_stobj (cfg, bblock, load, sp [2], ip, klass, FALSE, FALSE, TRUE);
                                else {
                                        MONO_INST_NEW (cfg, ins, n);
-                                       ins->cil_code = ip;
                                        ins->inst_left = load;
                                        ins->inst_right = sp [2];
                                        handle_loaded_temps (cfg, bblock, stack_start, sp);
@@ -8101,9 +8162,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        if (sp [2]->opcode == OP_PCONST && sp [2]->inst_p0 == NULL) {
                                MonoInst *load;
                                NEW_LDELEMA (cfg, load, sp, mono_defaults.object_class);
-                               load->cil_code = ip;
                                MONO_INST_NEW (cfg, ins, stelem_to_stind [*ip - CEE_STELEM_I]);
-                               ins->cil_code = ip;
                                ins->inst_left = load;
                                ins->inst_right = sp [2];
                                MONO_ADD_INS (bblock, ins);
@@ -8130,12 +8189,10 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
 
                        
                        MONO_INST_NEW (cfg, ins, OP_CKFINITE);
-                       ins->cil_code = ip;
                        ins->inst_left = sp [-1];
                        temp = mono_compile_create_var (cfg, &mono_defaults.double_class->byval_arg, OP_LOCAL);
 
                        NEW_TEMPSTORE (cfg, store, temp->inst_c0, ins);
-                       store->cil_code = ip;
                        MONO_ADD_INS (bblock, store);
 
                        NEW_TEMPLOAD (cfg, sp [-1], temp->inst_c0);
@@ -8143,43 +8200,93 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        ++ip;
                        break;
                }
-               case CEE_REFANYVAL:
+               case CEE_REFANYVAL: {
+                       int context_used = 0;
+
                        CHECK_STACK (1);
-                       MONO_INST_NEW (cfg, ins, *ip);
                        --sp;
                        CHECK_OPSIZE (5);
-                       klass = mono_class_get_full (image, read32 (ip + 1), generic_context);
+                       token = read32 (ip + 1);
+                       klass = mono_class_get_full (image, token, generic_context);
                        CHECK_TYPELOAD (klass);
                        mono_class_init (klass);
-                       ins->type = STACK_MP;
-                       ins->inst_left = *sp;
-                       ins->klass = klass;
-                       ins->inst_newa_class = klass;
-                       ins->cil_code = ip;
+
+                       if (cfg->generic_sharing_context) {
+                               context_used = mono_class_check_context_used (klass);
+                               if (context_used && cfg->compile_aot)
+                                       GENERIC_SHARING_FAILURE (*ip);
+                       }
+
+                       if (context_used) {
+                               MonoInst *rgctx;
+
+                               MONO_INST_NEW (cfg, ins, OP_REFANYVAL_REG);
+                               ins->type = STACK_MP;
+                               ins->inst_left = *sp;
+                               ins->klass = klass;
+
+                               GET_RGCTX (rgctx);
+                               ins->inst_right = get_runtime_generic_context_ptr (cfg, method,
+                                               bblock, klass,
+                                               token, MINI_TOKEN_SOURCE_CLASS, generic_context,
+                                               rgctx, MONO_RGCTX_INFO_KLASS, ip);
+                       } else {
+                               MONO_INST_NEW (cfg, ins, *ip);
+                               ins->type = STACK_MP;
+                               ins->inst_left = *sp;
+                               ins->klass = klass;
+                               ins->inst_newa_class = klass;
+                       }
                        ip += 5;
                        *sp++ = ins;
                        break;
+               }
                case CEE_MKREFANY: {
-                       MonoInst *loc, *klassconst;
+                       MonoInst *loc;
+                       int context_used = 0;
 
                        CHECK_STACK (1);
-                       MONO_INST_NEW (cfg, ins, *ip);
                        --sp;
                        CHECK_OPSIZE (5);
-                       klass = mono_class_get_full (image, read32 (ip + 1), generic_context);
+                       token = read32 (ip + 1);
+                       klass = mono_class_get_full (image, token, generic_context);
                        CHECK_TYPELOAD (klass);
                        mono_class_init (klass);
-                       ins->cil_code = ip;
 
-                       if (cfg->generic_sharing_context && mono_class_check_context_used (klass))
-                               GENERIC_SHARING_FAILURE (CEE_MKREFANY);
+                       if (cfg->generic_sharing_context) {
+                               context_used = mono_class_check_context_used (klass);
+                               if (context_used && cfg->compile_aot)
+                                       GENERIC_SHARING_FAILURE (CEE_MKREFANY);
+                       }
 
                        loc = mono_compile_create_var (cfg, &mono_defaults.typed_reference_class->byval_arg, OP_LOCAL);
-                       NEW_TEMPLOADA (cfg, ins->inst_right, loc->inst_c0);
+                       if (context_used) {
+                               MonoInst *rgctx, *klass_type, *klass_klass, *loc_load;
+
+                               GET_RGCTX (rgctx);
+                               klass_klass = get_runtime_generic_context_ptr (cfg, method, bblock, klass,
+                                               token, MINI_TOKEN_SOURCE_CLASS, generic_context,
+                                               rgctx, MONO_RGCTX_INFO_KLASS, ip);
+                               GET_RGCTX (rgctx);
+                               klass_type = get_runtime_generic_context_ptr (cfg, method, bblock, klass,
+                                               token, MINI_TOKEN_SOURCE_CLASS, generic_context,
+                                               rgctx, MONO_RGCTX_INFO_TYPE, ip);
+
+                               NEW_TEMPLOADA (cfg, loc_load, loc->inst_c0);
+
+                               MONO_INST_NEW (cfg, ins, OP_MKREFANY_REGS);
+                               NEW_GROUP (cfg, ins->inst_left, klass_type, klass_klass);
+                               NEW_GROUP (cfg, ins->inst_right, *sp, loc_load);
+                       } else {
+                               MonoInst *klassconst;
+
+                               NEW_PCONST (cfg, klassconst, klass);
+
+                               MONO_INST_NEW (cfg, ins, *ip);
+                               NEW_TEMPLOADA (cfg, ins->inst_right, loc->inst_c0);
+                               NEW_GROUP (cfg, ins->inst_left, *sp, klassconst);
+                       }
 
-                       NEW_PCONST (cfg, klassconst, klass);
-                       NEW_GROUP (cfg, ins->inst_left, *sp, klassconst);
-                       
                        MONO_ADD_INS (bblock, ins);
 
                        NEW_TEMPLOAD (cfg, *sp, loc->inst_c0);
@@ -8234,15 +8341,29 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        if (cfg->opt & MONO_OPT_SHARED) {
                                int temp;
                                MonoInst *res, *store, *addr, *vtvar, *iargs [3];
+                               int method_context_used;
 
-                               GENERIC_SHARING_FAILURE (CEE_LDTOKEN);
+                               if (cfg->generic_sharing_context)
+                                       method_context_used = mono_method_check_context_used (method);
+                               else
+                                       method_context_used = 0;
 
                                vtvar = mono_compile_create_var (cfg, &handle_class->byval_arg, OP_LOCAL); 
 
                                NEW_IMAGECONST (cfg, iargs [0], image);
                                NEW_ICONST (cfg, iargs [1], n);
-                               NEW_PCONST (cfg, iargs [2], generic_context);
-                               temp = mono_emit_jit_icall (cfg, bblock, mono_ldtoken_wrapper, iargs, ip);
+                               if (method_context_used) {
+                                       MonoInst *rgctx;
+
+                                       GET_RGCTX (rgctx);
+                                       iargs [2] = get_runtime_generic_context_method (cfg, method, bblock, method,
+                                                       generic_context, rgctx, MONO_RGCTX_INFO_METHOD, ip);
+                                       temp = mono_emit_jit_icall (cfg, bblock, mono_ldtoken_wrapper_generic_shared,
+                                                       iargs, ip);
+                               } else {
+                                       NEW_PCONST (cfg, iargs [2], generic_context);
+                                       temp = mono_emit_jit_icall (cfg, bblock, mono_ldtoken_wrapper, iargs, ip);
+                               }
                                NEW_TEMPLOAD (cfg, res, temp);
                                NEW_TEMPLOADA (cfg, addr, vtvar->inst_c0);
                                NEW_INDSTORE (cfg, store, addr, res, &mono_defaults.int_class->byval_arg);
@@ -8252,7 +8373,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                if ((ip + 10 < end) && ip_in_bb (cfg, bblock, ip + 5) &&
                                        handle_class == mono_defaults.typehandle_class &&
                                        ((ip [5] == CEE_CALL) || (ip [5] == CEE_CALLVIRT)) && 
-                                       (cmethod = mini_get_method (method, read32 (ip + 6), NULL, generic_context)) &&
+                                       (cmethod = mini_get_method (cfg, method, read32 (ip + 6), NULL, generic_context)) &&
                                        (cmethod->klass == mono_defaults.monotype_class->parent) &&
                                        (strcmp (cmethod->name, "GetTypeFromHandle") == 0)) {
                                        MonoClass *tclass = mono_class_from_mono_type (handle);
@@ -8278,12 +8399,35 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                } else {
                                        MonoInst *store, *addr, *vtvar;
 
-                                       GENERIC_SHARING_FAILURE (CEE_LDTOKEN);
+                                       if (context_used) {
+                                                       MonoInst *rgctx;
 
-                                       if (cfg->compile_aot)
+                                               g_assert (!cfg->compile_aot);
+
+                                               GET_RGCTX (rgctx);
+                                               if (handle_class == mono_defaults.typehandle_class) {
+                                                       ins = get_runtime_generic_context_ptr (cfg, method,
+                                                                       bblock,
+                                                                       mono_class_from_mono_type (handle), token,
+                                                                       MINI_TOKEN_SOURCE_CLASS, generic_context,
+                                                                       rgctx, MONO_RGCTX_INFO_TYPE, ip);
+                                               } else if (handle_class == mono_defaults.methodhandle_class) {
+                                                       ins = get_runtime_generic_context_method (cfg, method,
+                                                                       bblock, handle, generic_context,
+                                                                       rgctx, MONO_RGCTX_INFO_METHOD, ip);
+                                               } else if (handle_class == mono_defaults.fieldhandle_class) {
+                                                       ins = get_runtime_generic_context_field (cfg, method,
+                                                                       bblock, handle, generic_context,
+                                                                       rgctx, MONO_RGCTX_INFO_CLASS_FIELD, ip);
+                                               } else {
+                                                       g_assert_not_reached ();
+                                               }
+                                       }
+                                       else if (cfg->compile_aot) {
                                                NEW_LDTOKENCONST (cfg, ins, image, n);
-                                       else
+                                       } else {
                                                NEW_PCONST (cfg, ins, handle);
+                                       }
                                        vtvar = mono_compile_create_var (cfg, &handle_class->byval_arg, OP_LOCAL);
                                        NEW_TEMPLOADA (cfg, addr, vtvar->inst_c0);
                                        NEW_INDSTORE (cfg, store, addr, ins, &mono_defaults.int_class->byval_arg);
@@ -8320,7 +8464,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                case CEE_ENDFINALLY:
                        MONO_INST_NEW (cfg, ins, OP_ENDFINALLY);
                        MONO_ADD_INS (bblock, ins);
-                       ins->cil_code = ip++;
+                       ip++;
                        start_new_bblock = 1;
 
                        /*
@@ -8329,7 +8473,6 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                         */
                        while (sp != stack_start) {
                                MONO_INST_NEW (cfg, ins, CEE_POP);
-                               ins->cil_code = ip;
                                sp--;
                                ins->inst_i0 = *sp;
                                MONO_ADD_INS (bblock, ins);
@@ -8350,7 +8493,6 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        /* empty the stack */
                        while (sp != stack_start) {
                                MONO_INST_NEW (cfg, ins, CEE_POP);
-                               ins->cil_code = ip;
                                sp--;
                                ins->inst_i0 = *sp;
                                MONO_ADD_INS (bblock, ins);
@@ -8374,7 +8516,6 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                        MonoInst *load;
 
                                        NEW_TEMPLOAD (cfg, load, mono_find_exvar_for_offset (cfg, clause->handler_offset)->inst_c0);
-                                       load->cil_code = ip;
 
                                        temp = mono_emit_jit_icall (cfg, bblock, mono_thread_get_undeniable_exception, NULL, ip);
                                        NEW_TEMPLOAD (cfg, *sp, temp);
@@ -8382,7 +8523,6 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                        MONO_INST_NEW (cfg, ins, OP_THROW_OR_NULL);
                                        ins->inst_left = *sp;
                                        ins->inst_right = load;
-                                       ins->cil_code = ip;
                                        MONO_ADD_INS (bblock, ins);
                                }
                        }
@@ -8393,7 +8533,6 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                        tblock = tmp->data;
                                        link_bblock (cfg, bblock, tblock);
                                        MONO_INST_NEW (cfg, ins, OP_CALL_HANDLER);
-                                       ins->cil_code = ip;
                                        ins->inst_target_bb = tblock;
                                        MONO_ADD_INS (bblock, ins);
                                }
@@ -8401,7 +8540,6 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        } 
 
                        MONO_INST_NEW (cfg, ins, OP_BR);
-                       ins->cil_code = ip;
                        MONO_ADD_INS (bblock, ins);
                        GET_BBLOCK (cfg, tblock, target);
                        link_bblock (cfg, bblock, tblock);
@@ -8422,7 +8560,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        sp -= 2;
                        handle_loaded_temps (cfg, bblock, stack_start, sp);
                        MONO_ADD_INS (bblock, ins);
-                       ins->cil_code = ip++;
+                       ip++;
                        ins->inst_i0 = sp [0];
                        ins->inst_i1 = sp [1];
                        inline_costs += 1;
@@ -8481,14 +8619,12 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
 
                                        if (wrapped && ptr != NULL && mono_lookup_internal_call (wrapped) == ptr) {
                                                NEW_AOTCONST (cfg, ins, MONO_PATCH_INFO_ICALL_ADDR, wrapped);
-                                               ins->cil_code = ip;
                                                *sp++ = ins;
                                                ip += 6;
                                                break;
                                        }
                                }
                                NEW_PCONST (cfg, ins, ptr);
-                               ins->cil_code = ip;
                                *sp++ = ins;
                                ip += 6;
                                inline_costs += 10 * num_calls++;
@@ -8500,7 +8636,6 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                CHECK_STACK (1);
                                --sp;
                                MONO_INST_NEW (cfg, ins, OP_VTADDR);
-                               ins->cil_code = ip;
                                ins->type = STACK_MP;
                                ins->inst_left = *sp;
                                *sp++ = ins;
@@ -8527,7 +8662,6 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                CHECK_STACK (1);
                                --sp;
                                MONO_INST_NEW (cfg, ins, OP_OBJADDR);
-                               ins->cil_code = ip;
                                ins->type = STACK_MP;
                                ins->inst_left = *sp;
                                *sp++ = ins;
@@ -8561,7 +8695,6 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                        UNVERIFIED;
                                
                                MONO_INST_NEW (cfg, ins, OP_BR);
-                               ins->cil_code = ip;
                                ins->inst_target_bb = end_bblock;
                                MONO_ADD_INS (bblock, ins);
                                link_bblock (cfg, bblock, end_bblock);
@@ -8583,7 +8716,6 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                ins->type = STACK_I4;
                                ins->inst_left = *sp;
                                ins->inst_newa_class = klass;
-                               ins->cil_code = ip;
                                *sp++ = emit_tree (cfg, bblock, ins, ip + 6);
                                ip += 6;
                                break;
@@ -8602,7 +8734,6 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                CHECK_OPSIZE (6);
                                token = read32 (ip + 2);
                                NEW_CLASSCONST (cfg, ins, mono_method_get_wrapper_data (method, token));
-                               ins->cil_code = ip;
                                *sp++ = ins;
                                ip += 6;
                                inline_costs += 10 * num_calls++;
@@ -8616,7 +8747,6 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                CHECK_OPSIZE (6);
                                MONO_INST_NEW (cfg, ins, OP_TLS_GET);
                                ins->inst_offset = (gint32)read32 (ip + 2);
-                               ins->cil_code = ip;
                                ins->type = STACK_PTR;
                                *sp++ = ins;
                                ip += 6;
@@ -8637,13 +8767,10 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                vtvar = mono_compile_create_var (cfg, &mono_defaults.argumenthandle_class->byval_arg, OP_LOCAL); 
 
                                NEW_TEMPLOADA (cfg, addr, vtvar->inst_c0);
-                               addr->cil_code = ip;
                                MONO_INST_NEW (cfg, ins, OP_ARGLIST);
-                               ins->cil_code = ip;
                                ins->inst_left = addr;
                                MONO_ADD_INS (bblock, ins);
                                NEW_TEMPLOAD (cfg, ins, vtvar->inst_c0);
-                               ins->cil_code = ip;
                                *sp++ = ins;
                                ip += 2;
                                break;
@@ -8669,10 +8796,8 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                sp -= 2;
                                cmp->inst_i0 = sp [0];
                                cmp->inst_i1 = sp [1];
-                               cmp->cil_code = ip;
                                type_from_op (cmp);
                                CHECK_TYPE (cmp);
-                               ins->cil_code = ip;
                                ins->type = STACK_I4;
                                ins->inst_i0 = cmp;
 #if MONO_ARCH_SOFT_FLOAT
@@ -8702,22 +8827,29 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                MonoInst *argconst;
                                MonoMethod *cil_method, *ctor_method;
                                int temp;
-                               gboolean is_shared;
+                               gboolean is_shared = FALSE;
+                               int context_used = 0;
 
                                CHECK_STACK_OVF (1);
                                CHECK_OPSIZE (6);
                                n = read32 (ip + 2);
-                               cmethod = mini_get_method (method, n, NULL, generic_context);
+                               cmethod = mini_get_method (cfg, method, n, NULL, generic_context);
                                if (!cmethod)
                                        goto load_error;
                                mono_class_init (cmethod->klass);
 
-                               if (cfg->generic_sharing_context && mono_method_check_context_used (cmethod))
-                                       GENERIC_SHARING_FAILURE (CEE_LDFTN);
+                               if (cfg->generic_sharing_context)
+                                       context_used = mono_method_check_context_used (cmethod);
 
-                               is_shared = (cmethod->flags & METHOD_ATTRIBUTE_STATIC) &&
-                                       (cmethod->klass->generic_class || cmethod->klass->generic_container) &&
-                                       mono_class_generic_sharing_enabled (cmethod->klass);
+                               if (mono_class_generic_sharing_enabled (cmethod->klass)) {
+                                       if ((cmethod->flags & METHOD_ATTRIBUTE_STATIC) &&
+                                                       (cmethod->klass->generic_class ||
+                                                       cmethod->klass->generic_container)) {
+                                               is_shared = TRUE;
+                                       }
+                                       if (cmethod->is_inflated && mono_method_get_context (cmethod)->method_inst)
+                                               is_shared = TRUE;
+                               }
 
                                cil_method = cmethod;
                                if (!dont_verify && !cfg->skip_visibility && !mono_method_can_access_method (method, cmethod))
@@ -8736,7 +8868,8 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
 #if defined(MONO_ARCH_HAVE_CREATE_DELEGATE_TRAMPOLINE) && !defined(HAVE_WRITE_BARRIERS)
                                /* FIXME: SGEN support */
                                /* FIXME: handle shared static generic methods */
-                               if (!is_shared && (sp > stack_start) && (ip + 6 + 5 < end) && ip_in_bb (cfg, bblock, ip + 6) && (ip [6] == CEE_NEWOBJ) && (ctor_method = mini_get_method (method, read32 (ip + 7), NULL, generic_context)) && (ctor_method->klass->parent == mono_defaults.multicastdelegate_class)) {
+                               /* FIXME: handle this in shared code */
+                               if (!is_shared && !context_used && (sp > stack_start) && (ip + 6 + 5 < end) && ip_in_bb (cfg, bblock, ip + 6) && (ip [6] == CEE_NEWOBJ) && (ctor_method = mini_get_method (cfg, method, read32 (ip + 7), NULL, generic_context)) && (ctor_method->klass->parent == mono_defaults.multicastdelegate_class)) {
                                        MonoInst *target_ins;
 
                                        ip += 6;
@@ -8753,10 +8886,21 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
 
                                handle_loaded_temps (cfg, bblock, stack_start, sp);
 
-                               if (is_shared)
+                               if (context_used) {
+                                       MonoInst *rgctx;
+
+                                       if (is_shared)
+                                               cmethod = mono_marshal_get_static_rgctx_invoke (cmethod);
+
+                                       GET_RGCTX (rgctx);
+                                       argconst = get_runtime_generic_context_method (cfg, method,
+                                                       bblock, cmethod,
+                                                       generic_context, rgctx, MONO_RGCTX_INFO_METHOD, ip);
+                               } else if (is_shared) {
                                        NEW_METHODCONST (cfg, argconst, mono_marshal_get_static_rgctx_invoke (cmethod));
-                               else
+                               } else {
                                        NEW_METHODCONST (cfg, argconst, cmethod);
+                               }
                                if (method->wrapper_type != MONO_WRAPPER_SYNCHRONIZED)
                                        temp = mono_emit_jit_icall (cfg, bblock, mono_ldftn, &argconst, ip);
                                else
@@ -8771,17 +8915,18 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        case CEE_LDVIRTFTN: {
                                MonoInst *args [2];
                                int temp;
+                               int context_used = 0;
 
                                CHECK_STACK (1);
                                CHECK_OPSIZE (6);
                                n = read32 (ip + 2);
-                               cmethod = mini_get_method (method, n, NULL, generic_context);
+                               cmethod = mini_get_method (cfg, method, n, NULL, generic_context);
                                if (!cmethod)
                                        goto load_error;
                                mono_class_init (cmethod->klass);
 
-                               if (cfg->generic_sharing_context && mono_method_check_context_used (cmethod))
-                                       GENERIC_SHARING_FAILURE (CEE_LDVIRTFTN);
+                               if (cfg->generic_sharing_context)
+                                       context_used = mono_method_check_context_used (cmethod);
 
                                if (mono_security_get_mode () == MONO_SECURITY_MODE_CAS) {
                                        if (check_linkdemand (cfg, method, cmethod, bblock, ip))
@@ -8795,7 +8940,16 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
 
                                --sp;
                                args [0] = *sp;
-                               NEW_METHODCONST (cfg, args [1], cmethod);
+                               if (context_used) {
+                                       MonoInst *rgctx;
+
+                                       GET_RGCTX (rgctx);
+                                       args [1] = get_runtime_generic_context_method (cfg, method,
+                                                       bblock, cmethod,
+                                                       generic_context, rgctx, MONO_RGCTX_INFO_METHOD, ip);
+                               } else {
+                                       NEW_METHODCONST (cfg, args [1], cmethod);
+                               }
                                temp = mono_emit_jit_icall (cfg, bblock, mono_ldvirtfn, args, ip);
                                NEW_TEMPLOAD (cfg, *sp, temp);
                                sp ++;
@@ -8811,7 +8965,6 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                CHECK_ARG (n);
                                NEW_ARGLOAD (cfg, ins, n);
                                LDARG_SOFT_FLOAT (cfg, ins, n, ip);
-                               ins->cil_code = ip;
                                *sp++ = ins;
                                ip += 4;
                                break;
@@ -8821,7 +8974,6 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                n = read16 (ip + 2);
                                CHECK_ARG (n);
                                NEW_ARGLOADA (cfg, ins, n);
-                               ins->cil_code = ip;
                                *sp++ = ins;
                                ip += 4;
                                break;
@@ -8833,7 +8985,6 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                n = read16 (ip + 2);
                                CHECK_ARG (n);
                                NEW_ARGSTORE (cfg, ins, n, *sp);
-                               ins->cil_code = ip;
                                if (!dont_verify_stloc && target_type_is_incompatible (cfg, param_types [n], *sp))
                                        UNVERIFIED;
                                STARG_SOFT_FLOAT (cfg, ins, n, ip);
@@ -8851,7 +9002,6 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                CHECK_LOCAL (n);
                                NEW_LOCLOAD (cfg, ins, n);
                                LDLOC_SOFT_FLOAT (cfg, ins, n, ip);
-                               ins->cil_code = ip;
                                *sp++ = ins;
                                ip += 4;
                                break;
@@ -8861,7 +9011,6 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                n = read16 (ip + 2);
                                CHECK_LOCAL (n);
                                NEW_LOCLOADA (cfg, ins, n);
-                               ins->cil_code = ip;
                                *sp++ = ins;
                                ip += 4;
                                break;
@@ -8875,7 +9024,6 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                NEW_LOCSTORE (cfg, ins, n, *sp);
                                if (!dont_verify_stloc && target_type_is_incompatible (cfg, header->locals [n], *sp))
                                        UNVERIFIED;
-                               ins->cil_code = ip;
                                STLOC_SOFT_FLOAT (cfg, ins, n, ip);
                                if (ins->opcode == CEE_STOBJ) {
                                        NEW_LOCLOADA (cfg, ins, n);
@@ -8899,7 +9047,6 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                        goto inline_failure;
                                MONO_INST_NEW (cfg, ins, OP_LOCALLOC);
                                ins->inst_left = *sp;
-                               ins->cil_code = ip;
                                ins->type = STACK_PTR;
 
                                cfg->flags |= MONO_CFG_HAS_ALLOCA;
@@ -8920,7 +9067,6 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                        UNVERIFIED;
                                MONO_INST_NEW (cfg, ins, OP_ENDFILTER);
                                ins->inst_left = *sp;
-                               ins->cil_code = ip;
                                MONO_ADD_INS (bblock, ins);
                                start_new_bblock = 1;
                                ip += 2;
@@ -8970,11 +9116,9 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                if (generic_class_is_reference_type (cfg, klass)) {
                                        MonoInst *store, *load;
                                        NEW_PCONST (cfg, load, NULL);
-                                       load->cil_code = ip;
                                        load->type = STACK_OBJ;
                                        load->klass = klass;
                                        MONO_INST_NEW (cfg, store, CEE_STIND_REF);
-                                       store->cil_code = ip;
                                        handle_loaded_temps (cfg, bblock, stack_start, sp);
                                        MONO_ADD_INS (bblock, store);
                                        store->inst_i0 = sp [0];
@@ -9047,10 +9191,8 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                g_assert (handler_offset != -1);
 
                                NEW_TEMPLOAD (cfg, load, mono_find_exvar_for_offset (cfg, handler_offset)->inst_c0);
-                               load->cil_code = ip;
                                MONO_INST_NEW (cfg, ins, OP_RETHROW);
                                ins->inst_left = load;
-                               ins->cil_code = ip;
                                MONO_ADD_INS (bblock, ins);
                                sp = stack_start;
                                link_bblock (cfg, bblock, end_bblock);
@@ -9075,7 +9217,6 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                        token = mono_class_value_size (klass, &align);
                                }
                                NEW_ICONST (cfg, ins, token);
-                               ins->cil_code = ip;
                                *sp++= ins;
                                ip += 6;
                                break;
@@ -9087,7 +9228,6 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                ins->inst_left = *sp;
                                ins->type = STACK_VTYPE;
                                ins->klass = mono_defaults.typehandle_class;
-                               ins->cil_code = ip;
                                ip += 2;
                                *sp++ = ins;
                                break;
@@ -9175,6 +9315,8 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                }
        }
 
+       cfg->ip = NULL;
+
        /* resolve backward branches in the middle of an existing basic block */
        for (tmp = bb_recheck; tmp; tmp = tmp->next) {
                bblock = tmp->data;
@@ -9478,7 +9620,7 @@ g_slist_prepend_mempool (MonoMemPool *mp, GSList   *list,
  * STACK_ALIGN is set to the alignment needed by the locals area.
  */
 gint32*
-mono_allocate_stack_slots_full (MonoCompile *m, gboolean backward, guint32 *stack_size, guint32 *stack_align)
+mono_allocate_stack_slots_full (MonoCompile *cfg, gboolean backward, guint32 *stack_size, guint32 *stack_align)
 {
        int i, slot, offset, size;
        guint32 align;
@@ -9490,17 +9632,17 @@ mono_allocate_stack_slots_full (MonoCompile *m, gboolean backward, guint32 *stac
        MonoType *t;
        int nvtypes;
 
-       scalar_stack_slots = mono_mempool_alloc0 (m->mempool, sizeof (StackSlotInfo) * MONO_TYPE_PINNED);
+       scalar_stack_slots = mono_mempool_alloc0 (cfg->mempool, sizeof (StackSlotInfo) * MONO_TYPE_PINNED);
        vtype_stack_slots = NULL;
        nvtypes = 0;
 
-       offsets = mono_mempool_alloc (m->mempool, sizeof (gint32) * m->num_varinfo);
-       for (i = 0; i < m->num_varinfo; ++i)
+       offsets = mono_mempool_alloc (cfg->mempool, sizeof (gint32) * cfg->num_varinfo);
+       for (i = 0; i < cfg->num_varinfo; ++i)
                offsets [i] = -1;
 
-       for (i = m->locals_start; i < m->num_varinfo; i++) {
-               inst = m->varinfo [i];
-               vmv = MONO_VARINFO (m, i);
+       for (i = cfg->locals_start; i < cfg->num_varinfo; i++) {
+               inst = cfg->varinfo [i];
+               vmv = MONO_VARINFO (cfg, i);
 
                if ((inst->flags & MONO_INST_IS_DEAD) || inst->opcode == OP_REGVAR || inst->opcode == OP_REGOFFSET)
                        continue;
@@ -9508,12 +9650,12 @@ mono_allocate_stack_slots_full (MonoCompile *m, gboolean backward, guint32 *stac
                vars = g_list_prepend (vars, vmv);
        }
 
-       vars = mono_varlist_sort (m, vars, 0);
+       vars = mono_varlist_sort (cfg, vars, 0);
        offset = 0;
        *stack_align = 0;
        for (l = vars; l; l = l->next) {
                vmv = l->data;
-               inst = m->varinfo [vmv->idx];
+               inst = cfg->varinfo [vmv->idx];
 
                /* inst->backend.is_pinvoke indicates native sized value types, this is used by the
                * pinvoke wrappers when they call functions returning structures */
@@ -9539,7 +9681,7 @@ mono_allocate_stack_slots_full (MonoCompile *m, gboolean backward, guint32 *stac
                                /* Fall through */
                        case MONO_TYPE_VALUETYPE:
                                if (!vtype_stack_slots)
-                                       vtype_stack_slots = mono_mempool_alloc0 (m->mempool, sizeof (StackSlotInfo) * 256);
+                                       vtype_stack_slots = mono_mempool_alloc0 (cfg->mempool, sizeof (StackSlotInfo) * 256);
                                for (i = 0; i < nvtypes; ++i)
                                        if (t->data.klass == vtype_stack_slots [i].vtype)
                                                break;
@@ -9574,7 +9716,7 @@ mono_allocate_stack_slots_full (MonoCompile *m, gboolean backward, guint32 *stac
                }
 
                slot = 0xffffff;
-               if (m->comp_done & MONO_COMP_LIVENESS) {
+               if (cfg->comp_done & MONO_COMP_LIVENESS) {
                        //printf ("START  %2d %08x %08x\n",  vmv->idx, vmv->range.first_use.abs_pos, vmv->range.last_use.abs_pos);
                        
                        /* expire old intervals in active */
@@ -9587,7 +9729,7 @@ mono_allocate_stack_slots_full (MonoCompile *m, gboolean backward, guint32 *stac
                                //printf ("EXPIR  %2d %08x %08x C%d R%d\n", amv->idx, amv->range.first_use.abs_pos, amv->range.last_use.abs_pos, amv->spill_costs, amv->reg);
 
                                slot_info->active = g_list_delete_link (slot_info->active, slot_info->active);
-                               slot_info->slots = g_slist_prepend_mempool (m->mempool, slot_info->slots, GINT_TO_POINTER (offsets [amv->idx]));
+                               slot_info->slots = g_slist_prepend_mempool (cfg->mempool, slot_info->slots, GINT_TO_POINTER (offsets [amv->idx]));
                        }
 
                        /* 
@@ -9605,7 +9747,7 @@ mono_allocate_stack_slots_full (MonoCompile *m, gboolean backward, guint32 *stac
                                        slot_info->slots = slot_info->slots->next;
                                }
 
-                               slot_info->active = mono_varlist_insert_sorted (m, slot_info->active, vmv, TRUE);
+                               slot_info->active = mono_varlist_insert_sorted (cfg, slot_info->active, vmv, TRUE);
                        }
                }
 
@@ -9615,7 +9757,7 @@ mono_allocate_stack_slots_full (MonoCompile *m, gboolean backward, guint32 *stac
 
                        /*
                        if (count == atoi (getenv ("COUNT")))
-                               printf ("LAST: %s\n", mono_method_full_name (m->method, TRUE));
+                               printf ("LAST: %s\n", mono_method_full_name (cfg->method, TRUE));
                        if (count > atoi (getenv ("COUNT")))
                                slot = 0xffffff;
                        else {
@@ -9623,6 +9765,10 @@ mono_allocate_stack_slots_full (MonoCompile *m, gboolean backward, guint32 *stac
                                }
                        */
                }
+
+               if (cfg->disable_reuse_stack_slots)
+                       slot = 0xffffff;
+
                if (slot == 0xffffff) {
                        /*
                         * Allways allocate valuetypes to sizeof (gpointer) to allow more
@@ -9733,6 +9879,7 @@ decompose_foreach (MonoInst *tree, gpointer data)
                else {
                        MonoVTable *vtable = mono_class_vtable (cfg->domain, mono_array_class_get (tree->inst_newa_class, 1));
 
+                       g_assert (vtable);
                        NEW_VTABLECONST (cfg, iargs [0], vtable);
                        iargs [1] = tree->inst_newa_len;
 
@@ -10370,15 +10517,22 @@ mono_resolve_patch_target (MonoMethod *method, MonoDomain *domain, guint8 *code,
                break;
        case MONO_PATCH_INFO_VTABLE:
                target = mono_class_vtable (domain, patch_info->data.klass);
+               g_assert (target);
                break;
-       case MONO_PATCH_INFO_CLASS_INIT:
-               target = mono_create_class_init_trampoline (mono_class_vtable (domain, patch_info->data.klass));
+       case MONO_PATCH_INFO_CLASS_INIT: {
+               MonoVTable *vtable = mono_class_vtable (domain, patch_info->data.klass);
+
+               g_assert (vtable);
+               target = mono_create_class_init_trampoline (vtable);
                break;
+       }
        case MONO_PATCH_INFO_DELEGATE_TRAMPOLINE:
                target = mono_create_delegate_trampoline (patch_info->data.klass);
                break;
        case MONO_PATCH_INFO_SFLDA: {
                MonoVTable *vtable = mono_class_vtable (domain, patch_info->data.field->parent);
+
+               g_assert (vtable);
                if (!vtable->initialized && !(vtable->klass->flags & TYPE_ATTRIBUTE_BEFORE_FIELD_INIT) && (method && mono_class_needs_cctor_run (vtable->klass, method)))
                        /* Done by the generated code */
                        ;
@@ -10700,7 +10854,7 @@ remove_block_if_useless (MonoCompile *cfg, MonoBasicBlock *bb, MonoBasicBlock *p
                int i;
 
                if (cfg->verbose_level > 1) {
-                       printf ("remove_block_if_useless %s, removed BB%d\n", mono_method_full_name (cfg->method, TRUE), bb->block_num);
+                       printf ("remove_block_if_useless, removed BB%d\n", bb->block_num);
                }
                
                /* unlink_bblock () modifies the bb->in_bb array so can't use a for loop here */
@@ -11256,8 +11410,11 @@ emit_state (MonoCompile *cfg, MBState *state, int goal)
                if (nts [1]) {
                        emit_state (cfg, kids [1], nts [1]);
                        if (nts [2]) {
-                               g_assert (!nts [3]);
                                emit_state (cfg, kids [2], nts [2]);
+                               if (nts [3]) {
+                                       g_assert (!nts [4]);
+                                       emit_state (cfg, kids [3], nts [3]);
+                               }
                        }
                }
        }
@@ -11353,6 +11510,8 @@ mini_select_instructions (MonoCompile *cfg)
                mono_mempool_empty (cfg->state_pool); 
        }
        mono_mempool_destroy (cfg->state_pool); 
+
+       cfg->ip = NULL;
 }
 
 /*
@@ -11792,11 +11951,13 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, gbool
        mono_jit_stats.methods_compiled++;
        if (mono_profiler_get_events () & MONO_PROFILE_JIT_COMPILATION)
                mono_profiler_method_jit (method);
+       if (MONO_PROBE_METHOD_COMPILE_BEGIN_ENABLED ())
+               MONO_PROBE_METHOD_COMPILE_BEGIN (method);
  
        if (compile_aot)
                /* We are passed the original generic method definition */
                try_generic_shared = mono_class_generic_sharing_enabled (method->klass) &&
-                       (opts & MONO_OPT_GSHARED) && (method->generic_container || method->klass->generic_container);
+                       (opts & MONO_OPT_GSHARED) && (method->is_generic || method->klass->generic_container);
        else
                try_generic_shared = mono_class_generic_sharing_enabled (method->klass) &&
                        (opts & MONO_OPT_GSHARED) && mono_method_is_generic_sharable_impl (method);
@@ -11820,8 +11981,8 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, gbool
                        g_assert (method->klass->generic_class->container_class == declaring_method->klass);
                }
 
-               if (declaring_method->generic_container)
-                       shared_context = &declaring_method->generic_container->context;
+               if (declaring_method->is_generic)
+                       shared_context = &(mono_method_get_generic_container (declaring_method)->context);
                else
                        shared_context = &declaring_method->klass->generic_container->context;
 
@@ -11845,10 +12006,32 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, gbool
                cfg->generic_sharing_context = (MonoGenericSharingContext*)&cfg->generic_sharing_context;
        cfg->token_info_hash = g_hash_table_new (NULL, NULL);
 
+       /* The debugger has no liveness information, so avoid sharing registers/stack slots */
+       if (mono_debug_using_mono_debugger () || debug_options.mdb_optimizations) {
+               cfg->disable_reuse_registers = TRUE;
+               cfg->disable_reuse_stack_slots = TRUE;
+               /* 
+                * This decreases the change the debugger will read registers/stack slots which are
+                * not yet initialized.
+                */
+               cfg->disable_initlocals_opt = TRUE;
+
+               /* Temporarily disable this when running in the debugger until we have support
+                * for this in the debugger. */
+               cfg->disable_omit_fp = TRUE;
+
+               // cfg->opt |= MONO_OPT_SHARED;
+               cfg->opt &= ~MONO_OPT_INLINE;
+               cfg->opt &= ~MONO_OPT_COPYPROP;
+               cfg->opt &= ~MONO_OPT_CONSPROP;
+       }
+
        header = mono_method_get_header (method_to_compile);
        if (!header) {
                cfg->exception_type = MONO_EXCEPTION_INVALID_PROGRAM;
                cfg->exception_message = g_strdup_printf ("Missing or incorrect header for method %s", cfg->method->name);
+               if (MONO_PROBE_METHOD_COMPILE_END_ENABLED ())
+                       MONO_PROBE_METHOD_COMPILE_END (method, FALSE);
                if (cfg->prof_options & MONO_PROFILE_JIT_COMPILATION)
                        mono_profiler_method_end_jit (method, NULL, MONO_PROFILE_FAILED);
                return cfg;
@@ -11870,14 +12053,19 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, gbool
 
        if ((i = mono_method_to_ir (cfg, method_to_compile, NULL, NULL, cfg->locals_start, NULL, NULL, NULL, 0, FALSE)) < 0) {
                if (try_generic_shared && cfg->exception_type == MONO_EXCEPTION_GENERIC_SHARING_FAILED) {
-                       if (compile_aot)
+                       if (compile_aot) {
+                               if (MONO_PROBE_METHOD_COMPILE_END_ENABLED ())
+                                       MONO_PROBE_METHOD_COMPILE_END (method, FALSE);
                                return cfg;
+                       }
                        mono_destroy_compile (cfg);
                        try_generic_shared = FALSE;
                        goto restart_compile;
                }
                g_assert (cfg->exception_type != MONO_EXCEPTION_GENERIC_SHARING_FAILED);
 
+               if (MONO_PROBE_METHOD_COMPILE_END_ENABLED ())
+                       MONO_PROBE_METHOD_COMPILE_END (method, FALSE);
                if (cfg->prof_options & MONO_PROFILE_JIT_COMPILATION)
                        mono_profiler_method_end_jit (method, NULL, MONO_PROFILE_FAILED);
                /* cfg contains the details of the failure, so let the caller cleanup */
@@ -11939,8 +12127,11 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, gbool
        }
 
        /* after method_to_ir */
-       if (parts == 1)
+       if (parts == 1) {
+               if (MONO_PROBE_METHOD_COMPILE_END_ENABLED ())
+                       MONO_PROBE_METHOD_COMPILE_END (method, TRUE);
                return cfg;
+       }
 
 //#define DEBUGSSA "logic_run"
 #define DEBUGSSA_CLASS "Tests"
@@ -11970,8 +12161,11 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, gbool
 #endif
 
        /* after SSA translation */
-       if (parts == 2)
+       if (parts == 2) {
+               if (MONO_PROBE_METHOD_COMPILE_END_ENABLED ())
+                       MONO_PROBE_METHOD_COMPILE_END (method, TRUE);
                return cfg;
+       }
 
        if ((cfg->opt & MONO_OPT_CONSPROP) || (cfg->opt & MONO_OPT_COPYPROP)) {
                if (cfg->comp_done & MONO_COMP_SSA) {
@@ -12010,8 +12204,11 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, gbool
 #endif
 
        /* after SSA removal */
-       if (parts == 3)
+       if (parts == 3) {
+               if (MONO_PROBE_METHOD_COMPILE_END_ENABLED ())
+                       MONO_PROBE_METHOD_COMPILE_END (method, TRUE);
                return cfg;
+       }
 
        if (cfg->verbose_level > 4) {
                printf ("BEFORE DECOMPSE START\n");
@@ -12147,7 +12344,7 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, gbool
                        inst = cfg->rgctx_var;
                        g_assert (inst->opcode == OP_REGOFFSET);
                } else {
-                       inst = cfg->varinfo [0];
+                       inst = cfg->args [0];
                }
 
                if (inst->opcode == OP_REGVAR) {
@@ -12234,6 +12431,8 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, gbool
        }
        mono_jit_stats.native_code_size += cfg->code_len;
 
+       if (MONO_PROBE_METHOD_COMPILE_END_ENABLED ())
+               MONO_PROBE_METHOD_COMPILE_END (method, TRUE);
        if (cfg->prof_options & MONO_PROFILE_JIT_COMPILATION)
                mono_profiler_method_end_jit (method, jinfo, MONO_PROFILE_OK);
 
@@ -12270,6 +12469,7 @@ mono_jit_compile_method_inner (MonoMethod *method, MonoDomain *target_domain, in
        MonoCompile *cfg;
        gpointer code = NULL;
        MonoJitInfo *info;
+       MonoVTable *vtable;
 
 #ifdef MONO_USE_AOT_COMPILER
        if ((opt & MONO_OPT_AOT) && !(mono_profiler_get_events () & MONO_PROFILE_JIT_COMPILATION)) {
@@ -12280,7 +12480,9 @@ mono_jit_compile_method_inner (MonoMethod *method, MonoDomain *target_domain, in
                mono_domain_lock (domain);
                if ((code = mono_aot_get_method (domain, method))) {
                        mono_domain_unlock (domain);
-                       mono_runtime_class_init (mono_class_vtable (domain, method->klass));
+                       vtable = mono_class_vtable (domain, method->klass);
+                       g_assert (vtable);
+                       mono_runtime_class_init (vtable);
                        return code;
                }
 
@@ -12293,15 +12495,17 @@ mono_jit_compile_method_inner (MonoMethod *method, MonoDomain *target_domain, in
                MonoMethod *nm;
                MonoMethodPInvoke* piinfo = (MonoMethodPInvoke *) method;
 
-               if (method->iflags & METHOD_IMPL_ATTRIBUTE_NATIVE && !MONO_CLASS_IS_IMPORT(method->klass))
-                       g_error ("Method '%s' in assembly '%s' contains native code and mono can't run it. The assembly was probably created by Managed C++.\n", mono_method_full_name (method, TRUE), method->klass->image->name);
-
                if (!piinfo->addr) {
                        if (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL)
                                piinfo->addr = mono_lookup_internal_call (method);
+                       else if (method->iflags & METHOD_IMPL_ATTRIBUTE_NATIVE)
+#ifdef PLATFORM_WIN32
+                               g_warning ("Method '%s' in assembly '%s' contains native code that cannot be executed by Mono in modules loaded from byte arrays. The assembly was probably created using C++/CLI.\n", mono_method_full_name (method, TRUE), method->klass->image->name);
+#else
+                               g_warning ("Method '%s' in assembly '%s' contains native code that cannot be executed by Mono on this platform. The assembly was probably created using C++/CLI.\n", mono_method_full_name (method, TRUE), method->klass->image->name);
+#endif
                        else
-                               if (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)
-                                       mono_lookup_pinvoke_call (method, NULL, NULL);
+                               mono_lookup_pinvoke_call (method, NULL, NULL);
                }
                        nm = mono_marshal_get_native_wrapper (method, check_for_pending_exc);
                        return mono_get_addr_from_ftnptr (mono_compile_method (nm));
@@ -12457,7 +12661,14 @@ mono_jit_compile_method_inner (MonoMethod *method, MonoDomain *target_domain, in
 
        mono_domain_unlock (target_domain);
 
-       mono_runtime_class_init (mono_class_vtable (target_domain, method->klass));
+       vtable = mono_class_vtable (target_domain, method->klass);
+       if (!vtable) {
+               MonoException *exc;
+               exc = mono_class_get_exception_for_failure (method->klass);
+               g_assert (exc);
+               mono_raise_exception (exc);
+       }
+       mono_runtime_class_init (vtable);
        return code;
 }
 
@@ -12495,9 +12706,12 @@ mono_jit_compile_method_with_opt (MonoMethod *method, guint32 opt)
        if ((info = lookup_method (target_domain, method))) {
                /* We can't use a domain specific method in another domain */
                if (! ((domain != target_domain) && !info->domain_neutral)) {
+                       MonoVTable *vtable;
+
                        mono_domain_unlock (target_domain);
                        mono_jit_stats.methods_lookups++;
-                       mono_runtime_class_init (mono_class_vtable (domain, method->klass));
+                       vtable = mono_class_vtable (domain, method->klass);
+                       mono_runtime_class_init (vtable);
                        return mono_create_ftnptr (target_domain, info->code_start);
                }
        }
@@ -12581,7 +12795,6 @@ mono_jit_free_method (MonoDomain *domain, MonoMethod *method)
 
        if (destroy)
                mono_code_manager_destroy (ji->code_mp);
-       mono_thread_hazardous_free_or_queue (ji->ji, g_free);
        g_free (ji);
 }
 
@@ -12626,6 +12839,7 @@ mono_jit_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObjec
        MonoMethod *invoke;
        MonoObject *(*runtime_invoke) (MonoObject *this, void **params, MonoObject **exc, void* compiled_method);
        void* compiled_method;
+       MonoVTable *vtable;
 
        if (obj == NULL && !(method->flags & METHOD_ATTRIBUTE_STATIC) && !method->string_ctor && (method->wrapper_type == 0)) {
                g_warning ("Ignoring invocation of an instance method on a NULL instance.\n");
@@ -12646,7 +12860,9 @@ mono_jit_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObjec
        /* We need this here becuase mono_marshal_get_runtime_invoke can be place 
         * the helper method in System.Object and not the target class
         */
-       mono_runtime_class_init (mono_class_vtable (mono_domain_get (), method->klass));
+       vtable = mono_class_vtable (mono_domain_get (), method->klass);
+       g_assert (vtable);
+       mono_runtime_class_init (vtable);
 
        if (method->klass->rank && (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) &&
                (method->iflags & METHOD_IMPL_ATTRIBUTE_NATIVE)) {
@@ -12849,14 +13065,97 @@ SIG_HANDLER_SIGNATURE (sigusr1_signal_handler)
        mono_arch_handle_exception (ctx, exc, FALSE);
 }
 
+#if defined(__i386__) || defined(__x86_64__)
+#define FULL_STAT_PROFILER_BACKTRACE 1
+#define CURRENT_FRAME_GET_BASE_POINTER(f) (* (gpointer*)(f))
+#define CURRENT_FRAME_GET_RETURN_ADDRESS(f) (* (((gpointer*)(f)) + 1))
+#if MONO_ARCH_STACK_GROWS_UP
+#define IS_BEFORE_ON_STACK <
+#define IS_AFTER_ON_STACK >
+#else
+#define IS_BEFORE_ON_STACK >
+#define IS_AFTER_ON_STACK <
+#endif
+#else
+#define FULL_STAT_PROFILER_BACKTRACE 0
+#endif
+
+#if defined(__ia64__) || defined(__sparc__) || defined(sparc) || defined(__s390__) || defined(s390)
+
+static void
+SIG_HANDLER_SIGNATURE (sigprof_signal_handler)
+{
+       NOT_IMPLEMENTED;
+}
+
+#else
+
 static void
 SIG_HANDLER_SIGNATURE (sigprof_signal_handler)
 {
+       int call_chain_depth = mono_profiler_stat_get_call_chain_depth ();
        GET_CONTEXT;
+       
+       if (call_chain_depth == 0) {
+               mono_profiler_stat_hit (mono_arch_ip_from_context (ctx), ctx);
+       } else {
+               MonoJitTlsData *jit_tls = TlsGetValue (mono_jit_tls_id);
+               int current_frame_index = 1;
+               MonoContext mono_context;
+#if FULL_STAT_PROFILER_BACKTRACE
+               guchar *current_frame;
+               guchar *stack_bottom;
+               guchar *stack_top;
+#else
+               MonoDomain *domain;
+#endif
+               guchar *ips [call_chain_depth + 1];
 
-       mono_profiler_stat_hit (mono_arch_ip_from_context (ctx), ctx);
+               mono_arch_sigctx_to_monoctx (ctx, &mono_context);
+               ips [0] = MONO_CONTEXT_GET_IP (&mono_context);
+               
+               if (jit_tls != NULL) {
+#if FULL_STAT_PROFILER_BACKTRACE
+                       stack_bottom = jit_tls->end_of_stack;
+                       stack_top = MONO_CONTEXT_GET_SP (&mono_context);
+                       current_frame = MONO_CONTEXT_GET_BP (&mono_context);
+                       
+                       while ((current_frame_index <= call_chain_depth) &&
+                                       (stack_bottom IS_BEFORE_ON_STACK (guchar*) current_frame) &&
+                                       ((guchar*) current_frame IS_BEFORE_ON_STACK stack_top)) {
+                               ips [current_frame_index] = CURRENT_FRAME_GET_RETURN_ADDRESS (current_frame);
+                               current_frame_index ++;
+                               stack_top = current_frame;
+                               current_frame = CURRENT_FRAME_GET_BASE_POINTER (current_frame);
+                       }
+#else
+                       domain = mono_domain_get ();
+                       if (domain != NULL) {
+                               MonoLMF *lmf = NULL;
+                               MonoJitInfo *ji;
+                               MonoJitInfo res;
+                               MonoContext new_mono_context;
+                               int native_offset;
+                               ji = mono_arch_find_jit_info (domain, jit_tls, &res, NULL, &mono_context,
+                                               &new_mono_context, NULL, &lmf, &native_offset, NULL);
+                               while ((ji != NULL) && (current_frame_index <= call_chain_depth)) {
+                                       ips [current_frame_index] = MONO_CONTEXT_GET_IP (&new_mono_context);
+                                       current_frame_index ++;
+                                       mono_context = new_mono_context;
+                                       ji = mono_arch_find_jit_info (domain, jit_tls, &res, NULL, &mono_context,
+                                                       &new_mono_context, NULL, &lmf, &native_offset, NULL);
+                               }
+                       }
+#endif
+               }
+               
+               
+               mono_profiler_stat_call_chain (current_frame_index, & ips [0], ctx);
+       }
 }
 
+#endif
+
 static void
 SIG_HANDLER_SIGNATURE (sigquit_signal_handler)
 {
@@ -13306,9 +13605,11 @@ mini_parse_debug_options (void)
                        debug_options.collect_pagefault_stats = TRUE;
                else if (!strcmp (arg, "break-on-unverified"))
                        debug_options.break_on_unverified = TRUE;
+               else if (!strcmp (arg, "no-gdb-backtrace"))
+                       debug_options.no_gdb_backtrace = TRUE;
                else {
                        fprintf (stderr, "Invalid option for the MONO_DEBUG env variable: %s\n", arg);
-                       fprintf (stderr, "Available options: 'handle-sigint', 'keep-delegates', 'collect-pagefault-stats', 'break-on-unverified'\n");
+                       fprintf (stderr, "Available options: 'handle-sigint', 'keep-delegates', 'collect-pagefault-stats', 'break-on-unverified', 'no-gdb-backtrace'\n");
                        exit (1);
                }
        }
@@ -13325,6 +13626,8 @@ mini_init (const char *filename, const char *runtime_version)
 {
        MonoDomain *domain;
 
+       MONO_PROBE_VES_INIT_BEGIN ();
+
 #ifdef __linux__
        if (access ("/proc/self/maps", F_OK) != 0) {
                g_print ("Mono requires /proc to be mounted.\n");
@@ -13394,7 +13697,6 @@ mini_init (const char *filename, const char *runtime_version)
        mono_install_handler (mono_arch_get_throw_exception ());
 #endif
        mono_install_stack_walk (mono_jit_walk_stack);
-       mono_install_init_vtable (mono_aot_init_vtable);
        mono_install_get_cached_class_info (mono_aot_get_cached_class_info);
        mono_install_get_class_from_name (mono_aot_get_class_from_name);
        mono_install_jit_info_find_in_aot (mono_aot_find_jit_info);
@@ -13566,6 +13868,8 @@ mini_init (const char *filename, const char *runtime_version)
        register_icall (mono_class_static_field_address , "mono_class_static_field_address", 
                                 "ptr ptr ptr", FALSE);
        register_icall (mono_ldtoken_wrapper, "mono_ldtoken_wrapper", "ptr ptr ptr ptr", FALSE);
+       register_icall (mono_ldtoken_wrapper_generic_shared, "mono_ldtoken_wrapper_generic_shared",
+               "ptr ptr ptr ptr", FALSE);
        register_icall (mono_get_special_static_data, "mono_get_special_static_data", "ptr int", FALSE);
        register_icall (mono_ldstr, "mono_ldstr", "object ptr ptr int32", FALSE);
        register_icall (mono_helper_stelem_ref_check, "helper_stelem_ref_check", "void object object", FALSE);
@@ -13578,11 +13882,13 @@ mini_init (const char *filename, const char *runtime_version)
        register_icall (mono_ldftn_nosync, "mono_ldftn_nosync", "ptr ptr", FALSE);
        register_icall (mono_ldvirtfn, "mono_ldvirtfn", "ptr object ptr", FALSE);
        register_icall (mono_helper_compile_generic_method, "compile_generic_method", "ptr object ptr ptr ptr", FALSE);
+       register_icall (mono_helper_compile_generic_method_wo_context, "compile_generic_method_wo_context",
+               "ptr object ptr ptr", FALSE);
        register_icall (mono_helper_ldstr, "helper_ldstr", "object ptr int", FALSE);
        register_icall (mono_helper_ldstr_mscorlib, "helper_ldstr_mscorlib", "object int", FALSE);
        register_icall (mono_helper_newobj_mscorlib, "helper_newobj_mscorlib", "object int", FALSE);
        register_icall (mono_value_copy, "mono_value_copy", "void ptr ptr ptr", FALSE);
-       register_icall (mono_helper_get_rgctx_other_ptr, "get_rgctx_other_ptr", "ptr ptr ptr int32 int32 int32 int32", FALSE);
+       register_icall (mono_object_castclass, "mono_object_castclass", "object object ptr", FALSE);
        register_icall (mono_break, "mono_break", NULL, TRUE);
        register_icall (mono_create_corlib_exception_0, "mono_create_corlib_exception_0", "object int", TRUE);
        register_icall (mono_create_corlib_exception_1, "mono_create_corlib_exception_1", "object int object", TRUE);
@@ -13598,6 +13904,9 @@ mini_init (const char *filename, const char *runtime_version)
        mono_generic_sharing_init ();
 
        mono_thread_attach (domain);
+       
+       MONO_PROBE_VES_INIT_END ();
+       
        return domain;
 }