Mon Oct 15 10:37:15 CEST 2007 Paolo Molaro <lupus@ximian.com>
[mono.git] / mono / mini / mini.c
index 1db8a21ae4de51d80bee53b7566fe6a3598c47bd..40cbaa816f944c9d6a530720526358db085474dd 100644 (file)
@@ -36,7 +36,6 @@
 
 #include <mono/metadata/assembly.h>
 #include <mono/metadata/loader.h>
-#include <mono/metadata/cil-coff.h>
 #include <mono/metadata/tabledefs.h>
 #include <mono/metadata/class.h>
 #include <mono/metadata/object.h>
 #include <mono/metadata/environment.h>
 #include <mono/metadata/mono-debug.h>
 #include <mono/metadata/monitor.h>
+#include <mono/metadata/gc-internal.h>
 #include <mono/metadata/security-manager.h>
 #include <mono/metadata/threads-types.h>
 #include <mono/metadata/rawbuffer.h>
+#include <mono/metadata/security-core-clr.h>
 #include <mono/utils/mono-math.h>
 #include <mono/utils/mono-compiler.h>
 #include <mono/utils/mono-counters.h>
 #include <mono/utils/mono-logger.h>
+#include <mono/utils/mono-mmap.h>
 #include <mono/os/gc_wrapper.h>
 
 #include "mini.h"
 
 #include "aliasing.h"
 
+#include "debug-mini.h"
+
 #define BRANCH_COST 100
 #define INLINE_LENGTH_LIMIT 20
 #define INLINE_FAILURE do {\
                if ((cfg->method != method) && (method->wrapper_type == MONO_WRAPPER_NONE))\
                        goto inline_failure;\
        } while (0)
+#define CHECK_CFG_EXCEPTION do {\
+               if (cfg->exception_type != MONO_EXCEPTION_NONE)\
+                       goto exception_exit;\
+       } while (0)
+#define METHOD_ACCESS_FAILURE do {     \
+               char *method_fname = mono_method_full_name (method, TRUE);      \
+               char *cil_method_fname = mono_method_full_name (cil_method, TRUE);      \
+               cfg->exception_type = MONO_EXCEPTION_METHOD_ACCESS;     \
+               cfg->exception_message = g_strdup_printf ("Method `%s' is inaccessible from method `%s'\n", cil_method_fname, method_fname);    \
+               g_free (method_fname);  \
+               g_free (cil_method_fname);      \
+               goto exception_exit;    \
+       } while (0)
+#define FIELD_ACCESS_FAILURE do {      \
+               char *method_fname = mono_method_full_name (method, TRUE);      \
+               char *field_fname = mono_field_full_name (field);       \
+               cfg->exception_type = MONO_EXCEPTION_FIELD_ACCESS;      \
+               cfg->exception_message = g_strdup_printf ("Field `%s' is inaccessible from method `%s'\n", field_fname, method_fname);  \
+               g_free (method_fname);  \
+               g_free (field_fname);   \
+               goto exception_exit;    \
+       } while (0)
+#define GENERIC_SHARING_FAILURE do {   \
+               if (cfg->generic_sharing_context) {     \
+                       /* g_print ("sharing failed for method %s.%s in %s:%d\n", method->klass->name, method->name, __FILE__, __LINE__); */ \
+                       cfg->exception_type = MONO_EXCEPTION_GENERIC_SHARING_FAILED;    \
+                       goto exception_exit;    \
+               }                       \
+       } while (0)
 
 /* 
  * this is used to determine when some branch optimizations are possible: we exclude FP compares
@@ -109,7 +142,7 @@ static void dec_foreach (MonoInst *tree, MonoCompile *cfg);
 
 static int mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_bblock, MonoBasicBlock *end_bblock, 
                   int locals_offset, MonoInst *return_var, GList *dont_inline, MonoInst **inline_args, 
-                  guint inline_offset, gboolean is_virtual_call);
+                  guint inline_offset, gboolean is_virtual_call, MonoGenericContext *shared_context);
 
 /* helper methods signature */
 static MonoMethodSignature *helper_sig_class_init_trampoline = NULL;
@@ -124,7 +157,8 @@ gboolean mono_break_on_exc = FALSE;
 #ifndef DISABLE_AOT
 gboolean mono_compile_aot = FALSE;
 #endif
-gboolean mono_use_security_manager = FALSE;
+MonoMethodDesc *mono_inject_async_exc_method = NULL;
+int mono_inject_async_exc_pos;
 
 static int mini_verbose = 0;
 
@@ -140,7 +174,9 @@ static GHashTable *jit_icall_name_hash = NULL;
 
 static MonoDebugOptions debug_options;
 
+#ifdef VALGRIND_JIT_REGISTER_MAP
 static int valgrind_register = 0;
+#endif
 
 /*
  * Address of the trampoline code.  This is used by the debugger to check
@@ -524,8 +560,8 @@ mono_jump_info_token_new (MonoMemPool *mp, MonoImage *image, guint32 token)
                (dest) = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst));       \
                (dest)->ssa_op = MONO_SSA_LOAD; \
                (dest)->inst_i0 = arg_array [(num)];    \
-               (dest)->opcode = mono_type_to_ldind ((dest)->inst_i0->inst_vtype);      \
-               type_to_eval_stack_type (param_types [(num)], (dest));  \
+               (dest)->opcode = mini_type_to_ldind ((cfg), (dest)->inst_i0->inst_vtype); \
+               type_to_eval_stack_type ((cfg), param_types [(num)], (dest));   \
                (dest)->klass = (dest)->inst_i0->klass; \
        }} while (0)
 
@@ -533,8 +569,8 @@ mono_jump_info_token_new (MonoMemPool *mp, MonoImage *image, guint32 token)
                (dest) = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst));       \
                (dest)->ssa_op = MONO_SSA_LOAD; \
                (dest)->inst_i0 = (cfg)->varinfo [locals_offset + (num)];       \
-               (dest)->opcode = mono_type_to_ldind ((dest)->inst_i0->inst_vtype);      \
-               type_to_eval_stack_type (header->locals [(num)], (dest));       \
+               (dest)->opcode = mini_type_to_ldind ((cfg), (dest)->inst_i0->inst_vtype); \
+               type_to_eval_stack_type ((cfg), header->locals [(num)], (dest));        \
                (dest)->klass = (dest)->inst_i0->klass; \
        } while (0)
 
@@ -577,8 +613,8 @@ mono_jump_info_token_new (MonoMemPool *mp, MonoImage *image, guint32 token)
                (dest) = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst));       \
                (dest)->ssa_op = MONO_SSA_LOAD; \
                (dest)->inst_i0 = (cfg)->varinfo [(num)];       \
-               (dest)->opcode = mono_type_to_ldind ((dest)->inst_i0->inst_vtype);      \
-               type_to_eval_stack_type ((dest)->inst_i0->inst_vtype, (dest));  \
+               (dest)->opcode = mini_type_to_ldind ((cfg), (dest)->inst_i0->inst_vtype); \
+               type_to_eval_stack_type ((cfg), (dest)->inst_i0->inst_vtype, (dest));   \
                (dest)->klass = (dest)->inst_i0->klass; \
        } while (0)
 
@@ -598,15 +634,15 @@ mono_jump_info_token_new (MonoMemPool *mp, MonoImage *image, guint32 token)
 #define NEW_INDLOAD(cfg,dest,addr,vtype) do {  \
                (dest) = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst));       \
                (dest)->inst_left = addr;       \
-               (dest)->opcode = mono_type_to_ldind (vtype);    \
-               type_to_eval_stack_type (vtype, (dest));        \
+               (dest)->opcode = mini_type_to_ldind ((cfg), vtype);     \
+               type_to_eval_stack_type ((cfg), vtype, (dest)); \
                /* FIXME: (dest)->klass = (dest)->inst_i0->klass;*/     \
        } while (0)
 
 #define NEW_INDSTORE(cfg,dest,addr,value,vtype) do {   \
                (dest) = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst));       \
                (dest)->inst_i0 = addr; \
-               (dest)->opcode = mono_type_to_stind (vtype);    \
+               (dest)->opcode = mini_type_to_stind ((cfg), vtype);     \
                (dest)->inst_i1 = (value);      \
                /* FIXME: (dest)->klass = (dest)->inst_i0->klass;*/     \
        } while (0)
@@ -615,14 +651,14 @@ mono_jump_info_token_new (MonoMemPool *mp, MonoImage *image, guint32 token)
                (dest) = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst));       \
                (dest)->ssa_op = MONO_SSA_STORE;        \
                (dest)->inst_i0 = (cfg)->varinfo [(num)];       \
-               (dest)->opcode = mono_type_to_stind ((dest)->inst_i0->inst_vtype);      \
+               (dest)->opcode = mini_type_to_stind ((cfg), (dest)->inst_i0->inst_vtype); \
                (dest)->inst_i1 = (inst);       \
                (dest)->klass = (dest)->inst_i0->klass; \
        } while (0)
 
 #define NEW_LOCSTORE(cfg,dest,num,inst) do {   \
                (dest) = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst));       \
-               (dest)->opcode = mono_type_to_stind (header->locals [(num)]);   \
+               (dest)->opcode = mini_type_to_stind ((cfg), header->locals [(num)]); \
                (dest)->ssa_op = MONO_SSA_STORE;        \
                (dest)->inst_i0 = (cfg)->varinfo [locals_offset + (num)];       \
                (dest)->inst_i1 = (inst);       \
@@ -632,13 +668,33 @@ mono_jump_info_token_new (MonoMemPool *mp, MonoImage *image, guint32 token)
 #define NEW_ARGSTORE(cfg,dest,num,inst) do {   \
                 if (arg_array [(num)]->opcode == OP_ICONST) goto inline_failure; \
                (dest) = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst));       \
-               (dest)->opcode = mono_type_to_stind (param_types [(num)]);      \
+               (dest)->opcode = mini_type_to_stind ((cfg), param_types [(num)]); \
                (dest)->ssa_op = MONO_SSA_STORE;        \
                (dest)->inst_i0 = arg_array [(num)];    \
                (dest)->inst_i1 = (inst);       \
                (dest)->klass = (dest)->inst_i0->klass; \
        } while (0)
 
+#define NEW_MEMCPY(cfg,dest,dst,src,memcpy_size,memcpy_align) do { \
+               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); \
+    } while (0)
+
+#define NEW_MEMSET(cfg,dest,dst,imm,memcpy_size,memcpy_align) do { \
+               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); \
+    } while (0)
+
 #define NEW_DUMMY_USE(cfg,dest,load) do { \
                (dest) = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst));       \
                (dest)->opcode = OP_DUMMY_USE; \
@@ -1137,7 +1193,7 @@ condbr_to_fp_br (int opcode)
  * FIXME: return a MonoType/MonoClass for the byref and VALUETYPE cases.
  */
 static void
-type_to_eval_stack_type (MonoType *type, MonoInst *inst)
+type_to_eval_stack_type (MonoCompile *cfg, MonoType *type, MonoInst *inst)
 {
        MonoClass *klass;
 
@@ -1199,6 +1255,15 @@ handle_enum:
        case MONO_TYPE_GENERICINST:
                type = &type->data.generic_class->container_class->byval_arg;
                goto handle_enum;
+       case MONO_TYPE_VAR :
+       case MONO_TYPE_MVAR :
+               /* FIXME: all the arguments must be references for now,
+                * later look inside cfg and see if the arg num is
+                * really a reference
+                */
+               g_assert (cfg->generic_sharing_context);
+               inst->type = STACK_OBJ;
+               return;
        default:
                g_error ("unknown type 0x%02x in eval stack type", type->type);
        }
@@ -1575,6 +1640,34 @@ check_values_to_signature (MonoInst *args, MonoType *this, MonoMethodSignature *
 }
 #endif
 
+static guint
+mini_type_to_ldind (MonoCompile* cfg, MonoType *type)
+{
+       if (cfg->generic_sharing_context && !type->byref) {
+               /* FIXME: all the arguments must be references for now,
+                * later look inside cfg and see if the arg num is
+                * really a reference
+                */
+               if (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR)
+                       return CEE_LDIND_REF;
+       }
+       return mono_type_to_ldind (type);
+}
+
+static guint
+mini_type_to_stind (MonoCompile* cfg, MonoType *type)
+{
+       if (cfg->generic_sharing_context && !type->byref) {
+               /* FIXME: all the arguments must be references for now,
+                * later look inside cfg and see if the arg num is
+                * really a reference
+                */
+               if (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR)
+                       return CEE_STIND_REF;
+       }
+       return mono_type_to_stind (type);
+}
+
 /*
  * When we need a pointer to the current domain many times in a method, we
  * call mono_domain_get() once and we store the result in a local variable.
@@ -1648,8 +1741,8 @@ mono_compile_make_var_load (MonoCompile *cfg, MonoInst *dest, gssize var_index)
        memset (dest, 0, sizeof (MonoInst));
        dest->ssa_op = MONO_SSA_LOAD;
        dest->inst_i0 = cfg->varinfo [var_index];
-       dest->opcode = mono_type_to_ldind (dest->inst_i0->inst_vtype);
-       type_to_eval_stack_type (dest->inst_i0->inst_vtype, dest);
+       dest->opcode = mini_type_to_ldind (cfg, dest->inst_i0->inst_vtype);
+       type_to_eval_stack_type (cfg, dest->inst_i0->inst_vtype, dest);
        dest->klass = dest->inst_i0->klass;
 }
 
@@ -1806,6 +1899,7 @@ mono_add_varcopy_to_end (MonoCompile *cfg, MonoBasicBlock *bb, int src, int dest
        NEW_TEMPLOAD (cfg, load, src);
 
        NEW_TEMPSTORE (cfg, inst, dest, load);
+       /* FIXME: handle CEE_STIND_R4 */
        if (inst->opcode == CEE_STOBJ) {
                NEW_TEMPLOADA (cfg, inst, dest);
                handle_stobj (cfg, bb, inst, load, NULL, inst->klass, TRUE, FALSE, FALSE);
@@ -2006,6 +2100,7 @@ handle_stack_args (MonoCompile *cfg, MonoBasicBlock *bb, MonoInst **sp, int coun
        for (i = 0; i < count; ++i) {
                /* add store ops at the end of the bb, before the branch */
                NEW_TEMPSTORE (cfg, inst, locals [i]->inst_c0, sp [i]);
+               /* FIXME: handle CEE_STIND_R4 */
                if (inst->opcode == CEE_STOBJ) {
                        NEW_TEMPLOADA (cfg, inst, locals [i]->inst_c0);
                        handle_stobj (cfg, bb, inst, sp [i], sp [i]->cil_code, inst->klass, TRUE, FALSE, FALSE);
@@ -2158,6 +2253,7 @@ handle_loaded_temps (MonoCompile *cfg, MonoBasicBlock *bblock, MonoInst **stack,
                        temp->flags |= MONO_INST_IS_TEMP;
                        NEW_TEMPSTORE (cfg, store, temp->inst_c0, ins);
                        store->cil_code = ins->cil_code;
+                       /* FIXME: handle CEE_STIND_R4 */
                        if (store->opcode == CEE_STOBJ) {
                                NEW_TEMPLOADA (cfg, store, temp->inst_c0);
                                handle_stobj (cfg, bblock, store, ins, ins->cil_code, temp->klass, FALSE, FALSE, FALSE);
@@ -2282,6 +2378,16 @@ target_type_is_incompatible (MonoCompile *cfg, MonoType *target, MonoInst *arg)
                        /* FIXME: check type compatibility */
                        return 0;
                }
+       case MONO_TYPE_VAR:
+       case MONO_TYPE_MVAR:
+               /* FIXME: all the arguments must be references for now,
+                * later look inside cfg and see if the arg num is
+                * really a reference
+                */
+               g_assert (cfg->generic_sharing_context);
+               if (arg->type != STACK_OBJ)
+                       return 1;
+               return 0;
        default:
                g_error ("unknown type 0x%02x in target_type_is_incompatible", simple_type->type);
        }
@@ -2393,7 +2499,7 @@ mono_spill_call (MonoCompile *cfg, MonoBasicBlock *bblock, MonoCallInst *call, M
                        call->inst.opcode = CEE_CALL;
                        temp = mono_compile_create_var (cfg, &mono_defaults.string_class->byval_arg, OP_LOCAL);
                } else {
-                       type_to_eval_stack_type (ret, ins);
+                       type_to_eval_stack_type (cfg, ret, ins);
                        temp = mono_compile_create_var (cfg, ret, OP_LOCAL);
                }
                
@@ -2427,6 +2533,7 @@ mono_spill_call (MonoCompile *cfg, MonoBasicBlock *bblock, MonoCallInst *call, M
                                MONO_ADD_INS (bblock, ins);
                } else {
                        NEW_TEMPSTORE (cfg, store, temp->inst_c0, ins);
+                       /* FIXME: handle CEE_STIND_R4 */
                        store->cil_code = ip;
                        if (to_end)
                                mono_add_ins_to_end (bblock, store);
@@ -2474,7 +2581,7 @@ mono_emit_call_args (MonoCompile *cfg, MonoBasicBlock *bblock, MonoMethodSignatu
        call->args = args;
        call->signature = sig;
        call = mono_arch_call_opcode (cfg, bblock, call, virtual);
-       type_to_eval_stack_type (sig->ret, &call->inst);
+       type_to_eval_stack_type (cfg, sig->ret, &call->inst);
 
        for (arg = call->out_args; arg;) {
                MonoInst *narg = arg->next;
@@ -2603,6 +2710,7 @@ mono_emulate_opcode (MonoCompile *cfg, MonoInst *tree, MonoInst **iargs, MonoJit
                temp = mono_compile_create_var (cfg, info->sig->ret, OP_LOCAL);
                temp->flags |= MONO_INST_IS_TEMP;
                NEW_TEMPSTORE (cfg, store, temp->inst_c0, ins);
+               /* FIXME: handle CEE_STIND_R4 */
                store->cil_code = tree->cil_code;
        } else {
                store = ins;
@@ -2641,6 +2749,32 @@ mono_emulate_opcode (MonoCompile *cfg, MonoInst *tree, MonoInst **iargs, MonoJit
        }
 }
 
+/*
+ * This entry point could be used later for arbitrary method
+ * redirection.
+ */
+inline static int
+mini_redirect_call (int *temp, MonoCompile *cfg, MonoBasicBlock *bblock, MonoMethod *method,  
+                      MonoMethodSignature *signature, MonoInst **args, const guint8 *ip, MonoInst *this)
+{
+
+       if (method->klass == mono_defaults.string_class) {
+               /* managed string allocation support */
+               if (strcmp (method->name, "InternalAllocateStr") == 0) {
+                       MonoInst *iargs [2];
+                       MonoVTable *vtable = mono_class_vtable (cfg->domain, method->klass);
+                       MonoMethod *managed_alloc = mono_gc_get_managed_allocator (vtable, FALSE);
+                       if (!managed_alloc)
+                               return FALSE;
+                       NEW_VTABLECONST (cfg, iargs [0], vtable);
+                       iargs [1] = args [0];
+                       *temp = mono_emit_method_call_spilled (cfg, bblock, managed_alloc, mono_method_signature (managed_alloc), iargs, ip, this);
+                       return TRUE;
+               }
+       }
+       return FALSE;
+}
+
 static MonoMethodSignature *
 mono_get_array_new_va_signature (int arity)
 {
@@ -2790,11 +2924,7 @@ handle_stobj (MonoCompile *cfg, MonoBasicBlock *bblock, MonoInst *dest, MonoInst
                        NEW_DUMMY_STORE (cfg, inst, dest->inst_i0->inst_c0);
                        MONO_ADD_INS (bblock, inst);
                }
-               MONO_INST_NEW (cfg, inst, OP_MEMCPY);
-               inst->inst_left = dest;
-               inst->inst_right = src;
-               inst->cil_code = ip;
-               inst->backend.size = n;
+               NEW_MEMCPY (cfg, inst, dest, src, n, align);
                MONO_ADD_INS (bblock, inst);
                return;
        }
@@ -2824,44 +2954,36 @@ handle_initobj (MonoCompile *cfg, MonoBasicBlock *bblock, MonoInst *dest, const
        MonoInst *iargs [3];
        MonoInst *ins, *zero_int32;
        int n;
+       guint32 align;
        MonoMethod *memset_method;
 
        NEW_ICONST (cfg, zero_int32, 0);
 
        mono_class_init (klass);
-       n = mono_class_value_size (klass, NULL);
+       n = mono_class_value_size (klass, &align);
        MONO_INST_NEW (cfg, ins, 0);
        ins->cil_code = ip;
        ins->inst_left = dest;
        ins->inst_right = zero_int32;
-       switch (n) {
-       case 1:
+       if (n == 1) {
                ins->opcode = CEE_STIND_I1;
                MONO_ADD_INS (bblock, ins);
-               break;
-       case 2:
+       } else if ((n == 2) && (align >= 2)) {
                ins->opcode = CEE_STIND_I2;
                MONO_ADD_INS (bblock, ins);
-               break;
-       case 4:
+       } else if ((n == 2) && (align >= 4)) {
                ins->opcode = CEE_STIND_I4;
                MONO_ADD_INS (bblock, ins);
-               break;
-       default:
-               if (n <= sizeof (gpointer) * 5) {
-                       ins->opcode = OP_MEMSET;
-                       ins->inst_imm = 0;
-                       ins->backend.size = n;
-                       MONO_ADD_INS (bblock, ins);
-                       break;
-               }
+       } else if (n <= sizeof (gpointer) * 5) {
+               NEW_MEMSET (cfg, ins, dest, 0, n, align);
+               MONO_ADD_INS (bblock, ins);
+       } else {
                memset_method = get_memset_method ();
                handle_loaded_temps (cfg, bblock, stack_start, sp);
                iargs [0] = dest;
                NEW_ICONST (cfg, iargs [1], 0);
                NEW_ICONST (cfg, iargs [2], n);
                mono_emit_method_call_spilled (cfg, bblock, memset_method, memset_method->signature, iargs, ip, NULL);
-               break;
        }
 }
 
@@ -2883,8 +3005,13 @@ handle_alloc (MonoCompile *cfg, MonoBasicBlock *bblock, MonoClass *klass, gboole
                return mono_emit_jit_icall (cfg, bblock, mono_helper_newobj_mscorlib, iargs, ip);
        } else {
                MonoVTable *vtable = mono_class_vtable (cfg->domain, klass);
+               MonoMethod *managed_alloc = mono_gc_get_managed_allocator (vtable, for_box);
                gboolean pass_lw;
 
+               if (managed_alloc) {
+                       NEW_VTABLECONST (cfg, iargs [0], vtable);
+                       return mono_emit_method_call_spilled (cfg, bblock, managed_alloc, mono_method_signature (managed_alloc), iargs, ip, NULL);
+               }
                alloc_ftn = mono_class_get_allocation_ftn (vtable, for_box, &pass_lw);
                if (pass_lw) {
                        guint32 lw = vtable->klass->instance_size;
@@ -2936,7 +3063,7 @@ handle_box (MonoCompile *cfg, MonoBasicBlock *bblock, MonoInst *val, const gucha
        add->cil_code = ip;
        add->klass = klass;
        MONO_INST_NEW (cfg, vstore, CEE_STIND_I);
-       vstore->opcode = mono_type_to_stind (&klass->byval_arg);
+       vstore->opcode = mini_type_to_stind (cfg, &klass->byval_arg);
        vstore->cil_code = ip;
        vstore->inst_left = add;
        vstore->inst_right = val;
@@ -3195,14 +3322,14 @@ mono_find_jit_opcode_emulation (int opcode)
 }
 
 static int
-is_signed_regsize_type (MonoType *type)
+is_unsigned_regsize_type (MonoType *type)
 {
        switch (type->type) {
-       case MONO_TYPE_I1:
-       case MONO_TYPE_I2:
-       case MONO_TYPE_I4:
+       case MONO_TYPE_U1:
+       case MONO_TYPE_U2:
+       case MONO_TYPE_U4:
 #if SIZEOF_VOID_P == 8
-       /*case MONO_TYPE_I8: this requires different opcodes in inssel.brg */
+       /*case MONO_TYPE_U8: this requires different opcodes in inssel.brg */
 #endif
                return TRUE;
        default:
@@ -3287,7 +3414,7 @@ mini_get_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSigna
                MonoInst *ldelem, *store, *load;
                MonoClass *eklass = mono_class_from_mono_type (fsig->params [1]);
                int n;
-               n = mono_type_to_stind (&eklass->byval_arg);
+               n = mini_type_to_stind (cfg, &eklass->byval_arg);
                if (n == CEE_STOBJ)
                        return NULL;
                sp [0] = args [0];
@@ -3295,23 +3422,22 @@ mini_get_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSigna
                NEW_LDELEMA (cfg, ldelem, sp, eklass);
                ldelem->flags |= MONO_INST_NORANGECHECK;
                MONO_INST_NEW (cfg, store, n);
-               n = mono_type_to_ldind (&eklass->byval_arg);
-               MONO_INST_NEW (cfg, load, mono_type_to_ldind (&eklass->byval_arg));
-               type_to_eval_stack_type (&eklass->byval_arg, load);
+               MONO_INST_NEW (cfg, load, mini_type_to_ldind (cfg, &eklass->byval_arg));
+               type_to_eval_stack_type (cfg, &eklass->byval_arg, load);
                load->inst_left = ldelem;
                store->inst_left = args [2];
                store->inst_right = load;
                return store;
        } else if (cmethod->klass == mono_defaults.math_class) {
                if (strcmp (cmethod->name, "Min") == 0) {
-                       if (is_signed_regsize_type (fsig->params [0])) {
+                       if (is_unsigned_regsize_type (fsig->params [0])) {
                                MONO_INST_NEW (cfg, ins, OP_MIN);
                                ins->inst_i0 = args [0];
                                ins->inst_i1 = args [1];
                                return ins;
                        }
                } else if (strcmp (cmethod->name, "Max") == 0) {
-                       if (is_signed_regsize_type (fsig->params [0])) {
+                       if (is_unsigned_regsize_type (fsig->params [0])) {
                                MONO_INST_NEW (cfg, ins, OP_MAX);
                                ins->inst_i0 = args [0];
                                ins->inst_i1 = args [1];
@@ -3356,6 +3482,7 @@ mono_save_args (MonoCompile *cfg, MonoBasicBlock *bblock, MonoMethodSignature *s
                        temp = mono_compile_create_var (cfg, type_from_stack_type (*sp), OP_LOCAL);
                        *args++ = temp;
                        NEW_TEMPSTORE (cfg, store, temp->inst_c0, *sp);
+                       /* FIXME: handle CEE_STIND_R4 */
                        store->cil_code = sp [0]->cil_code;
                        MONO_ADD_INS (bblock, store);
                }
@@ -3370,6 +3497,7 @@ mono_save_args (MonoCompile *cfg, MonoBasicBlock *bblock, MonoMethodSignature *s
                        *args++ = temp;
                        NEW_TEMPSTORE (cfg, store, temp->inst_c0, *sp);
                        store->cil_code = sp [0]->cil_code;
+                       /* FIXME: handle CEE_STIND_R4 */
                        if (store->opcode == CEE_STOBJ) {
                                NEW_TEMPLOADA (cfg, store, temp->inst_c0);
                                handle_stobj (cfg, bblock, store, *sp, sp [0]->cil_code, temp->klass, FALSE, FALSE, FALSE);
@@ -3433,7 +3561,7 @@ static gboolean check_inline_caller_method_name_limit (MonoMethod *caller_method
 
 static int
 inline_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoBasicBlock *bblock, MonoInst **sp,
-               guchar *ip, guint real_offset, GList *dont_inline, MonoBasicBlock **last_b, gboolean inline_allways)
+               guchar *ip, guint real_offset, GList *dont_inline, MonoBasicBlock **last_b, gboolean inline_allways, MonoGenericContext *shared_context)
 {
        MonoInst *ins, *rvar = NULL;
        MonoMethodHeader *cheader;
@@ -3444,6 +3572,8 @@ inline_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig,
        unsigned char* prev_cil_start;
        guint32 prev_cil_offset_to_bb_len;
 
+       g_assert (cfg->exception_type == MONO_EXCEPTION_NONE);
+
 #if (MONO_INLINE_CALLED_LIMITED_METHODS)
        if ((! inline_allways) && ! check_inline_called_method_name_limit (cmethod))
                return 0;
@@ -3473,7 +3603,7 @@ inline_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig,
        new_locals_offset = cfg->num_varinfo;
        for (i = 0; i < cheader->num_locals; ++i)
                mono_compile_create_var (cfg, cheader->locals [i], OP_LOCAL);
-       
+
        /* allocate starte and end blocks */
        sbblock = NEW_BBLOCK (cfg);
        sbblock->block_num = cfg->num_bblocks++;
@@ -3489,7 +3619,7 @@ inline_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig,
        prev_cil_offset_to_bb_len = cfg->cil_offset_to_bb_len;
        prev_cil_start = cfg->cil_start;
 
-       costs = mono_method_to_ir (cfg, cmethod, sbblock, ebblock, new_locals_offset, rvar, dont_inline, sp, real_offset, *ip == CEE_CALLVIRT);
+       costs = mono_method_to_ir (cfg, cmethod, sbblock, ebblock, new_locals_offset, rvar, dont_inline, sp, real_offset, *ip == CEE_CALLVIRT, shared_context);
 
        cfg->inlined_method = prev_inlined_method;
        cfg->cil_offset_to_bb = prev_cil_offset_to_bb;
@@ -3519,6 +3649,7 @@ inline_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig,
        } else {
                if (cfg->verbose_level > 2)
                        g_print ("INLINE ABORTED %s\n", mono_method_full_name (cmethod, TRUE));
+               cfg->exception_type = MONO_EXCEPTION_NONE;
        }
        return 0;
 }
@@ -3672,6 +3803,7 @@ emit_tree (MonoCompile *cfg, MonoBasicBlock *bblock, MonoInst *ins, const guint8
        temp = mono_compile_create_var (cfg, type_from_stack_type (ins), OP_LOCAL);
        temp->flags |= MONO_INST_IS_TEMP;
        NEW_TEMPSTORE (cfg, store, temp->inst_c0, ins);
+       /* FIXME: handle CEE_STIND_R4 */
        store->cil_code = ins->cil_code;
        MONO_ADD_INS (bblock, store);
        NEW_TEMPLOAD (cfg, load, temp->inst_c0);
@@ -3689,9 +3821,6 @@ mini_get_method (MonoMethod *m, guint32 token, MonoClass *klass, MonoGenericCont
 
        method = mono_get_method_full (m->klass->image, token, klass, context);
 
-       if (method && method->is_inflated)
-               method = mono_get_inflated_method (method);
-
        return method;
 }
 
@@ -3728,131 +3857,99 @@ gboolean check_linkdemand (MonoCompile *cfg, MonoMethod *caller, MonoMethod *cal
 
        if (result == MONO_JIT_LINKDEMAND_ECMA) {
                /* Generate code to throw a SecurityException before the actual call/link */
-               MonoAssembly *assembly = mono_image_get_assembly (caller->klass->image);
-               MonoReflectionAssembly *refass = (MonoReflectionAssembly*) mono_assembly_get_object (cfg->domain, assembly);
-               MonoReflectionMethod *refmet = mono_method_get_object (cfg->domain, caller, NULL);
                MonoSecurityManager *secman = mono_security_manager_get_methods ();
-               MonoInst *args [3];
+               MonoInst *args [2];
 
                NEW_ICONST (cfg, args [0], 4);
-               NEW_PCONST (cfg, args [1], refass);
-               NEW_PCONST (cfg, args [2], refmet);
+               NEW_METHODCONST (cfg, args [1], caller);
                mono_emit_method_call_spilled (cfg, bblock, secman->linkdemandsecurityexception, mono_method_signature (secman->linkdemandsecurityexception), args, ip, NULL);
        } else if (cfg->exception_type == MONO_EXCEPTION_NONE) {
                 /* don't hide previous results */
                cfg->exception_type = MONO_EXCEPTION_SECURITY_LINKDEMAND;
                cfg->exception_data = result;
+               return TRUE;
        }
        
        return FALSE;
 }
 
-static gboolean
-can_access_internals (MonoAssembly *accessing, MonoAssembly* accessed)
+static MonoMethod*
+method_access_exception (void)
 {
-       GSList *tmp;
-       if (accessing == accessed)
-               return TRUE;
-       if (!accessed || !accessing)
-               return FALSE;
-       for (tmp = accessed->friend_assembly_names; tmp; tmp = tmp->next) {
-               MonoAssemblyName *friend = tmp->data;
-               /* Be conservative with checks */
-               if (!friend->name)
-                       continue;
-               if (strcmp (accessing->aname.name, friend->name))
-                       continue;
-               if (friend->public_key_token [0]) {
-                       if (!accessing->aname.public_key_token [0])
-                               continue;
-                       if (strcmp ((char*)friend->public_key_token, (char*)accessing->aname.public_key_token))
-                               continue;
-               }
-               return TRUE;
+       static MonoMethod *method = NULL;
+
+       if (!method) {
+               MonoSecurityManager *secman = mono_security_manager_get_methods ();
+               method = mono_class_get_method_from_name (secman->securitymanager,
+                                                         "MethodAccessException", 2);
        }
-       return FALSE;
+       g_assert (method);
+       return method;
 }
 
-/* FIXME: check visibility of type, too */
-static gboolean
-can_access_member (MonoClass *access_klass, MonoClass *member_klass, int access_level)
+static void
+emit_throw_method_access_exception (MonoCompile *cfg, MonoMethod *caller, MonoMethod *callee,
+                                   MonoBasicBlock *bblock, unsigned char *ip)
 {
-       if (access_klass->generic_class && member_klass->generic_class &&
-           access_klass->generic_class->container_class && member_klass->generic_class->container_class) {
-               if (can_access_member (access_klass->generic_class->container_class,
-                                      member_klass->generic_class->container_class, access_level))
-                       return TRUE;
-       }
+       MonoMethod *thrower = method_access_exception ();
+       MonoInst *args [2];
 
-       /* Partition I 8.5.3.2 */
-       /* the access level values are the same for fields and methods */
-       switch (access_level) {
-       case FIELD_ATTRIBUTE_COMPILER_CONTROLLED:
-               /* same compilation unit */
-               return access_klass->image == member_klass->image;
-       case FIELD_ATTRIBUTE_PRIVATE:
-               return access_klass == member_klass;
-       case FIELD_ATTRIBUTE_FAM_AND_ASSEM:
-               if (mono_class_has_parent (access_klass, member_klass) &&
-                   can_access_internals (access_klass->image->assembly, member_klass->image->assembly))
-                       return TRUE;
-               return FALSE;
-       case FIELD_ATTRIBUTE_ASSEMBLY:
-               return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
-       case FIELD_ATTRIBUTE_FAMILY:
-               if (mono_class_has_parent (access_klass, member_klass))
-                       return TRUE;
-               return FALSE;
-       case FIELD_ATTRIBUTE_FAM_OR_ASSEM:
-               if (mono_class_has_parent (access_klass, member_klass))
-                       return TRUE;
-               return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
-       case FIELD_ATTRIBUTE_PUBLIC:
-               return TRUE;
+       NEW_METHODCONST (cfg, args [0], caller);
+       NEW_METHODCONST (cfg, args [1], callee);
+       mono_emit_method_call_spilled (cfg, bblock, thrower,
+               mono_method_signature (thrower), args, ip, NULL);
+}
+
+static MonoMethod*
+verification_exception (void)
+{
+       static MonoMethod *method = NULL;
+
+       if (!method) {
+               MonoSecurityManager *secman = mono_security_manager_get_methods ();
+               method = mono_class_get_method_from_name (secman->securitymanager,
+                                                         "VerificationException", 0);
        }
-       return FALSE;
+       g_assert (method);
+       return method;
 }
 
-static gboolean
-can_access_field (MonoMethod *method, MonoClassField *field)
+static void
+emit_throw_verification_exception (MonoCompile *cfg, MonoBasicBlock *bblock, unsigned char *ip)
 {
-       /* FIXME: check all overlapping fields */
-       int can = can_access_member (method->klass, field->parent, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
-       if (!can) {
-               MonoClass *nested = method->klass->nested_in;
-               while (nested) {
-                       can = can_access_member (nested, field->parent, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
-                       if (can)
-                               return TRUE;
-                       nested = nested->nested_in;
-               }
+       MonoMethod *thrower = verification_exception ();
+
+       mono_emit_method_call_spilled (cfg, bblock, thrower,
+               mono_method_signature (thrower),
+               NULL, ip, NULL);
+}
+
+static void
+ensure_method_is_allowed_to_call_method (MonoCompile *cfg, MonoMethod *caller, MonoMethod *callee,
+                                        MonoBasicBlock *bblock, unsigned char *ip)
+{
+       MonoSecurityCoreCLRLevel caller_level = mono_security_core_clr_method_level (caller, TRUE);
+       MonoSecurityCoreCLRLevel callee_level = mono_security_core_clr_method_level (callee, TRUE);
+       gboolean is_safe = TRUE;
+
+       if (!(caller_level >= callee_level ||
+                       caller_level == MONO_SECURITY_CORE_CLR_SAFE_CRITICAL ||
+                       callee_level == MONO_SECURITY_CORE_CLR_SAFE_CRITICAL)) {
+               is_safe = FALSE;
        }
-       return can;
+
+       if (!is_safe)
+               emit_throw_method_access_exception (cfg, caller, callee, bblock, ip);
 }
 
 static gboolean
-can_access_method (MonoMethod *method, MonoMethod *called)
+method_is_safe (MonoMethod *method)
 {
-       int can = can_access_member (method->klass, called->klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
-       if (!can) {
-               MonoClass *nested = method->klass->nested_in;
-               while (nested) {
-                       can = can_access_member (nested, called->klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
-                       if (can)
-                               return TRUE;
-                       nested = nested->nested_in;
-               }
-       }
-       /* 
-        * FIXME:
-        * with generics calls to explicit interface implementations can be expressed
-        * directly: the method is private, but we must allow it. This may be opening
-        * a hole or the generics code should handle this differently.
-        * Maybe just ensure the interface type is public.
-        */
-       if ((called->flags & METHOD_ATTRIBUTE_VIRTUAL) && (called->flags & METHOD_ATTRIBUTE_FINAL))
-               return TRUE;
-       return can;
+       /*
+       if (strcmp (method->name, "unsafeMethod") == 0)
+               return FALSE;
+       */
+       return TRUE;
 }
 
 /*
@@ -3924,13 +4021,24 @@ initialize_array_data (MonoMethod *method, gboolean aot, unsigned char *ip, Mono
        return NULL;
 }
 
+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);
+       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);
+}
+
 /*
  * mono_method_to_ir: translates IL into basic blocks containing trees
  */
 static int
 mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_bblock, MonoBasicBlock *end_bblock, 
                   int locals_offset, MonoInst *return_var, GList *dont_inline, MonoInst **inline_args, 
-                  guint inline_offset, gboolean is_virtual_call)
+                  guint inline_offset, gboolean is_virtual_call, MonoGenericContext *shared_context)
 {
        MonoInst *zero_int32, *zero_int64, *zero_ptr, *zero_obj, *zero_r8;
        MonoInst *ins, **sp, **stack_start;
@@ -3968,6 +4076,9 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
        dont_verify |= method->wrapper_type == MONO_WRAPPER_COMINTEROP;
        dont_verify |= method->wrapper_type == MONO_WRAPPER_COMINTEROP_INVOKE;
 
+       /* turn off visibility checks for smcs */
+       dont_verify |= mono_security_get_mode () == MONO_SECURITY_MODE_SMCS_HACK;
+
        /* still some type unsafety issues in marshal wrappers... (unknown is PtrToStructure) */
        dont_verify_stloc = method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE;
        dont_verify_stloc |= method->wrapper_type == MONO_WRAPPER_UNKNOWN;
@@ -3986,7 +4097,10 @@ 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 (sig->is_inflated)
+       if (cfg->generic_sharing_context) {
+               g_assert (shared_context);
+               generic_context = shared_context;
+       } else if (sig->is_inflated)
                generic_context = mono_method_get_context (method);
        else if (generic_container)
                generic_context = &generic_container->context;
@@ -4121,7 +4235,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                }
        }
 
-       if (mono_use_security_manager)
+       if (mono_security_get_mode () == MONO_SECURITY_MODE_CAS)
                secman = mono_security_manager_get_methods ();
 
        security = (secman && mono_method_has_declsec (method));
@@ -4144,12 +4258,16 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        if (custom && mono_custom_attrs_has_attr (custom, secman->suppressunmanagedcodesecurity)) {
                                pinvoke = FALSE;
                        }
+                       if (custom)
+                               mono_custom_attrs_free (custom);
 
                        if (pinvoke) {
                                custom = mono_custom_attrs_from_class (wrapped->klass);
                                if (custom && mono_custom_attrs_has_attr (custom, secman->suppressunmanagedcodesecurity)) {
                                        pinvoke = FALSE;
                                }
+                               if (custom)
+                                       mono_custom_attrs_free (custom);
                        }
                } else {
                        /* not a P/Invoke after all */
@@ -4206,6 +4324,20 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                mono_emit_method_call_spilled (cfg, init_localsbb, secman->demandunmanaged, mono_method_signature (secman->demandunmanaged), NULL, ip, NULL);
        }
 
+       if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR) {
+               if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE) {
+                       MonoMethod *wrapped = mono_marshal_method_from_wrapper (method);
+                       if (wrapped && (wrapped->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)) {
+                               if (!(method->klass && method->klass->image &&
+                                               mono_security_core_clr_is_platform_image (method->klass->image))) {
+                                       emit_throw_method_access_exception (cfg, method, wrapped, bblock, ip);
+                               }
+                       }
+               }
+               if (!method_is_safe (method))
+                       emit_throw_verification_exception (cfg, bblock, ip);
+       }
+
        if (get_basic_blocks (cfg, header, real_offset, ip, end, &err_pos)) {
                ip = err_pos;
                UNVERIFIED;
@@ -4570,6 +4702,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                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);
                                        handle_stobj (cfg, bblock, store, sp [0], sp [0]->cil_code, store->klass, TRUE, FALSE, FALSE);
@@ -4607,9 +4740,13 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        if (!cmethod)
                                goto load_error;
 
-                       if (mono_use_security_manager) {
+                       if (cfg->generic_sharing_context && mono_method_check_context_used (cmethod, generic_context))
+                               GENERIC_SHARING_FAILURE;
+
+                       if (mono_security_get_mode () == MONO_SECURITY_MODE_CAS) {
                                if (check_linkdemand (cfg, method, cmethod, bblock, ip))
                                        INLINE_FAILURE;
+                               CHECK_CFG_EXCEPTION;
                        }
 
                        ins->inst_p0 = cmethod;
@@ -4647,7 +4784,6 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                        cil_method = cmethod;
                                } else if (constrained_call) {
                                        cmethod = mono_get_method_constrained (image, token, constrained_call, generic_context, &cil_method);
-                                       cmethod = mono_get_inflated_method (cmethod);
                                        cil_method = cmethod;
                                } else {
                                        cmethod = mini_get_method (method, token, NULL, generic_context);
@@ -4656,8 +4792,11 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
 
                                if (!cmethod)
                                        goto load_error;
-                               if (!dont_verify && !cfg->skip_visibility && !can_access_method (method, cil_method))
-                                       UNVERIFIED;
+                               if (!dont_verify && !cfg->skip_visibility && !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);
 
                                if (!virtual && (cmethod->flags & METHOD_ATTRIBUTE_ABSTRACT))
                                        /* MS.NET seems to silently convert this to a callvirt */
@@ -4681,9 +4820,10 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
 
                                n = fsig->param_count + fsig->hasthis;
 
-                               if (mono_use_security_manager) {
+                               if (mono_security_get_mode () == MONO_SECURITY_MODE_CAS) {
                                        if (check_linkdemand (cfg, method, cmethod, bblock, ip))
                                                INLINE_FAILURE;
+                                       CHECK_CFG_EXCEPTION;
                                }
 
                                if (cmethod->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL &&
@@ -4699,6 +4839,9 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        if (cmethod && cmethod->klass->generic_container)
                                UNVERIFIED;
 
+                       if (cfg->generic_sharing_context && cmethod && mono_method_check_context_used (cmethod, generic_context))
+                               GENERIC_SHARING_FAILURE;
+
                        CHECK_STACK (n);
 
                        //g_assert (!virtual || fsig->hasthis);
@@ -4718,8 +4861,8 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                         * sp [0] is a pointer to the data: we need the value
                                         * in handle_box (), so load it here.
                                         */
-                                       MONO_INST_NEW (cfg, load, mono_type_to_ldind (&constrained_call->byval_arg));
-                                       type_to_eval_stack_type (&constrained_call->byval_arg, load);
+                                       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);
@@ -4818,6 +4961,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
 
                                        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);
                                                handle_stobj (cfg, bblock, ins, sp [i], sp [i]->cil_code, ins->klass, FALSE, FALSE, FALSE);
@@ -4843,7 +4987,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                if (MONO_TYPE_IS_VOID (fsig->ret)) {
                                        MONO_ADD_INS (bblock, ins);
                                } else {
-                                       type_to_eval_stack_type (fsig->ret, ins);
+                                       type_to_eval_stack_type (cfg, fsig->ret, ins);
                                        *sp = ins;
                                        sp++;
                                }
@@ -4871,7 +5015,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                        allways = TRUE;
                                }
 
-                               if ((costs = inline_method (cfg, cmethod, fsig, bblock, sp, ip, real_offset, dont_inline, &ebblock, allways))) {
+                               if ((costs = inline_method (cfg, cmethod, fsig, bblock, sp, ip, real_offset, dont_inline, &ebblock, allways, shared_context))) {
                                        ip += 5;
                                        real_offset += 5;
 
@@ -4909,6 +5053,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
 
                                if (!has_vtargs) {
                                        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);
@@ -4956,6 +5101,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
 
                                                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);
@@ -4975,6 +5121,7 @@ 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);
                                        } else {
@@ -4997,7 +5144,12 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        } else {
                                /* Prevent inlining of methods which call other methods */
                                INLINE_FAILURE;
-                               if (ip_in_bb (cfg, bblock, ip + 5) 
+                               if (mini_redirect_call (&temp, cfg, bblock, cmethod, fsig, sp, ip, virtual ? sp [0] : NULL)) {
+                                       if (temp != -1) {
+                                               NEW_TEMPLOAD (cfg, *sp, temp);
+                                               sp++;
+                                       }
+                               } else if (ip_in_bb (cfg, bblock, ip + 5) 
                                    && (!MONO_TYPE_ISSTRUCT (fsig->ret))
                                    && (!MONO_TYPE_IS_VOID (fsig->ret) || cmethod->string_ctor)
                                    && (CODE_IS_STLOC (ip + 5) || ip [5] == CEE_POP || ip [5] == CEE_RET)) {
@@ -5026,6 +5178,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                        //g_assert (returnvar != -1);
                                        NEW_TEMPSTORE (cfg, store, return_var->inst_c0, *sp);
                                        store->cil_code = sp [0]->cil_code;
+                                       /* FIXME: handle CEE_STIND_R4 */
                                        if (store->opcode == CEE_STOBJ) {
                                                g_assert_not_reached ();
                                                NEW_TEMPLOADA (cfg, store, return_var->inst_c0);
@@ -5040,7 +5193,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                        CHECK_STACK (1);
                                        --sp;
                                        MONO_INST_NEW (cfg, ins, OP_NOP);
-                                       ins->opcode = mono_type_to_stind (mono_method_signature (method)->ret);
+                                       ins->opcode = mini_type_to_stind (cfg, mono_method_signature (method)->ret);
                                        if (ins->opcode == CEE_STOBJ) {
                                                NEW_RETLOADA (cfg, ins);
                                                /* FIXME: it is possible some optimization will pass the a heap pointer for the struct address, so we'll need the write barrier */
@@ -5467,14 +5620,12 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                store->inst_i1 = load;
                                store->flags |= ins_flag;
                        } else {
-                               n = mono_class_value_size (klass, NULL);
+                               guint32 align;
+
+                               n = mono_class_value_size (klass, &align);
                                if ((cfg->opt & MONO_OPT_INTRINS) && n <= sizeof (gpointer) * 5) {
                                        MonoInst *copy;
-                                       MONO_INST_NEW (cfg, copy, OP_MEMCPY);
-                                       copy->inst_left = sp [0];
-                                       copy->inst_right = sp [1];
-                                       copy->cil_code = ip;
-                                       copy->backend.size = n;
+                                       NEW_MEMCPY (cfg, copy, sp [0], sp [1], n, align);
                                        MONO_ADD_INS (bblock, copy);
                                } else {
                                        MonoMethod *memcpy_method = get_memcpy_method ();
@@ -5494,6 +5645,8 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        MonoInst *iargs [3];
                        int loc_index = -1;
                        int stloc_len = 0;
+                       guint32 align;
+
                        CHECK_OPSIZE (5);
                        CHECK_STACK (1);
                        --sp;
@@ -5534,6 +5687,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                CHECK_LOCAL (loc_index);
                                NEW_LOCSTORE (cfg, ins, loc_index, *sp);
 
+                               /* FIXME: handle CEE_STIND_R4 */
                                if (ins->opcode == CEE_STOBJ) {
                                        handle_loaded_temps (cfg, bblock, stack_start, sp);
                                        ins->cil_code = ip;
@@ -5546,16 +5700,12 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                }
                        }
 
-                       n = mono_class_value_size (klass, NULL);
+                       n = mono_class_value_size (klass, &align);
                        ins = mono_compile_create_var (cfg, &klass->byval_arg, OP_LOCAL);
                        NEW_TEMPLOADA (cfg, iargs [0], ins->inst_c0);
                        if ((cfg->opt & MONO_OPT_INTRINS) && n <= sizeof (gpointer) * 5) {
                                MonoInst *copy;
-                               MONO_INST_NEW (cfg, copy, OP_MEMCPY);
-                               copy->inst_left = iargs [0];
-                               copy->inst_right = *sp;
-                               copy->cil_code = ip;
-                               copy->backend.size = n;
+                               NEW_MEMCPY (cfg, copy, iargs [0], *sp, n, align);
                                MONO_ADD_INS (bblock, copy);
                        } else {
                                MonoMethod *memcpy_method = get_memcpy_method ();
@@ -5655,7 +5805,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        MonoInst *iargs [2];
                        MonoMethodSignature *fsig;
                        int temp;
-                       
+
                        CHECK_OPSIZE (5);
                        token = read32 (ip + 1);
                        cmethod = mini_get_method (method, token, NULL, generic_context);
@@ -5668,9 +5818,15 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        if (!mono_class_init (cmethod->klass))
                                goto load_error;
 
-                       if (mono_use_security_manager) {
+                       if (cfg->generic_sharing_context && mono_method_check_context_used (cmethod, generic_context))
+                               GENERIC_SHARING_FAILURE;
+
+                       if (mono_security_get_mode () == MONO_SECURITY_MODE_CAS) {
                                if (check_linkdemand (cfg, method, cmethod, bblock, ip))
                                        INLINE_FAILURE;
+                               CHECK_CFG_EXCEPTION;
+                       } else if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR) {
+                               ensure_method_is_allowed_to_call_method (cfg, method, cmethod, bblock, ip);
                        }
 
                        n = fsig->param_count;
@@ -5725,7 +5881,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                    !g_list_find (dont_inline, cmethod)) {
                                        int costs;
                                        MonoBasicBlock *ebblock;
-                                       if ((costs = inline_method (cfg, cmethod, fsig, bblock, sp, ip, real_offset, dont_inline, &ebblock, FALSE))) {
+                                       if ((costs = inline_method (cfg, cmethod, fsig, bblock, sp, ip, real_offset, dont_inline, &ebblock, FALSE, shared_context))) {
 
                                                ip += 5;
                                                real_offset += 5;
@@ -5774,6 +5930,9 @@ 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_context))
+                               GENERIC_SHARING_FAILURE;
+
                        /* Needed by the code generated in inssel.brg */
                        mono_get_got_var (cfg);
 
@@ -5789,7 +5948,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                iargs [0] = sp [0];
                                
                                costs = inline_method (cfg, mono_isinst, mono_method_signature (mono_isinst), bblock, 
-                                                          iargs, ip, real_offset, dont_inline, &ebblock, TRUE);
+                                                      iargs, ip, real_offset, dont_inline, &ebblock, TRUE, shared_context);
                        
                                g_assert (costs > 0);
                                
@@ -5820,6 +5979,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                case CEE_UNBOX_ANY: {
                        MonoInst *add, *vtoffset;
                        MonoInst *iargs [3];
+                       guint32 align;
 
                        CHECK_STACK (1);
                        --sp;
@@ -5828,6 +5988,9 @@ 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_context))
+                               GENERIC_SHARING_FAILURE;
+
                        if (MONO_TYPE_IS_REFERENCE (&klass->byval_arg)) {
                                /* CASTCLASS */
                                if (klass->marshalbyref || klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
@@ -5841,7 +6004,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                        iargs [0] = sp [0];
                                        
                                        costs = inline_method (cfg, mono_castclass, mono_method_signature (mono_castclass), bblock, 
-                                                                  iargs, ip, real_offset, dont_inline, &ebblock, TRUE);
+                                                       iargs, ip, real_offset, dont_inline, &ebblock, TRUE, shared_context);
                                
                                        g_assert (costs > 0);
                                        
@@ -5895,16 +6058,12 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        *sp = add;
                        ip += 5;
                        /* LDOBJ impl */
-                       n = mono_class_value_size (klass, NULL);
+                       n = mono_class_value_size (klass, &align);
                        ins = mono_compile_create_var (cfg, &klass->byval_arg, OP_LOCAL);
                        NEW_TEMPLOADA (cfg, iargs [0], ins->inst_c0);
                        if ((cfg->opt & MONO_OPT_INTRINS) && n <= sizeof (gpointer) * 5) {
                                MonoInst *copy;
-                               MONO_INST_NEW (cfg, copy, OP_MEMCPY);
-                               copy->inst_left = iargs [0];
-                               copy->inst_right = *sp;
-                               copy->cil_code = ip;
-                               copy->backend.size = n;
+                               NEW_MEMCPY (cfg, copy, iargs [0], *sp, n, align);
                                MONO_ADD_INS (bblock, copy);
                        } else {
                                MonoMethod *memcpy_method = get_memcpy_method ();
@@ -5929,6 +6088,9 @@ 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_context))
+                               GENERIC_SHARING_FAILURE;
+
                        if (mono_class_is_nullable (klass)) {
                                int v = handle_unbox_nullable (cfg, bblock, *sp, ip, klass);
                                NEW_TEMPLOAD (cfg, *sp, v);
@@ -5968,6 +6130,9 @@ 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_context))
+                               GENERIC_SHARING_FAILURE;
+
                        /* Needed by the code generated in inssel.brg */
                        mono_get_got_var (cfg);
                
@@ -5983,7 +6148,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                iargs [0] = sp [0];
                                
                                costs = inline_method (cfg, mono_castclass, mono_method_signature (mono_castclass), bblock, 
-                                                          iargs, ip, real_offset, dont_inline, &ebblock, TRUE);
+                                               iargs, ip, real_offset, dont_inline, &ebblock, TRUE, shared_context);
                        
                                g_assert (costs > 0);
                                
@@ -6058,8 +6223,8 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        if (!field)
                                goto load_error;
                        mono_class_init (klass);
-                       if (!dont_verify && !cfg->skip_visibility && !can_access_field (method, field))
-                               UNVERIFIED;
+                       if (!dont_verify && !cfg->skip_visibility && !mono_method_can_access_field (method, field))
+                               FIELD_ACCESS_FAILURE;
 
                        foffset = klass->valuetype? field->offset - sizeof (MonoObject): field->offset;
                        /* FIXME: mark instructions for use in SSA */
@@ -6079,7 +6244,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
 
                                        if (cfg->opt & MONO_OPT_INLINE) {
                                                costs = inline_method (cfg, stfld_wrapper, mono_method_signature (stfld_wrapper), bblock, 
-                                                                      iargs, ip, real_offset, dont_inline, &ebblock, TRUE);
+                                                               iargs, ip, real_offset, dont_inline, &ebblock, TRUE, shared_context);
                                                g_assert (costs > 0);
                                                      
                                                ip += 5;
@@ -6099,7 +6264,7 @@ 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 (mono_type_to_stind (field->type) == CEE_STIND_REF) {
+                               } else if (mini_type_to_stind (cfg, field->type) == CEE_STIND_REF) {
                                        /* insert call to write barrier */
                                        MonoMethod *write_barrier = mono_marshal_get_write_barrier ();
                                        MonoInst *iargs [2];
@@ -6115,7 +6280,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                        mono_emit_method_call_spilled (cfg, bblock, write_barrier, mono_method_signature (write_barrier), iargs, ip, NULL);
 #endif
 #ifdef MONO_ARCH_SOFT_FLOAT
-                               } else if (mono_type_to_stind (field->type) == CEE_STIND_R4) {
+                               } 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;
@@ -6134,7 +6299,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                        ins->inst_right = offset_ins;
                                        ins->type = STACK_MP;
 
-                                       MONO_INST_NEW (cfg, store, mono_type_to_stind (field->type));
+                                       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];
@@ -6159,7 +6324,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                        NEW_ICONST (cfg, iargs [3], klass->valuetype ? field->offset - sizeof (MonoObject) : field->offset);
                                        if ((cfg->opt & MONO_OPT_INLINE) && !MONO_TYPE_ISSTRUCT (mono_method_signature (wrapper)->ret)) {
                                                costs = inline_method (cfg, wrapper, mono_method_signature (wrapper), bblock, 
-                                                                      iargs, ip, real_offset, dont_inline, &ebblock, TRUE);
+                                                               iargs, ip, real_offset, dont_inline, &ebblock, TRUE, shared_context);
                                                g_assert (costs > 0);
                                                      
                                                ip += 5;
@@ -6198,14 +6363,14 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                                *sp++ = ins;
                                        } else {
                                                MonoInst *load;
-                                               MONO_INST_NEW (cfg, load, mono_type_to_ldind (field->type));
-                                               type_to_eval_stack_type (field->type, 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;
 #ifdef MONO_ARCH_SOFT_FLOAT
-                                               if (mono_type_to_ldind (field->type) == CEE_LDIND_R4) {
+                                               if (mini_type_to_ldind (cfg, field->type) == CEE_LDIND_R4) {
                                                        int temp;
                                                        temp = handle_load_float (cfg, bblock, ins, ip);
                                                        NEW_TEMPLOAD (cfg, *sp, temp);
@@ -6236,6 +6401,11 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        if (!field)
                                goto load_error;
                        mono_class_init (klass);
+                       if (!dont_verify && !cfg->skip_visibility && !mono_method_can_access_field (method, field))
+                               FIELD_ACCESS_FAILURE;
+
+                       if (cfg->generic_sharing_context && mono_class_check_context_used (klass, generic_context))
+                               GENERIC_SHARING_FAILURE;
 
                        g_assert (!(field->type->attrs & FIELD_ATTRIBUTE_LITERAL));
 
@@ -6315,13 +6485,14 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                MonoInst *store;
                                CHECK_STACK (1);
                                sp--;
-                               MONO_INST_NEW (cfg, store, mono_type_to_stind (field->type));
+                               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;
                                ins_flag = 0;
 
+                               /* FIXME: handle CEE_STIND_R4 */
                                if (store->opcode == CEE_STOBJ) {
                                        handle_stobj (cfg, bblock, ins, sp [0], ip, mono_class_from_mono_type (field->type), FALSE, FALSE, FALSE);
                                } else
@@ -6377,7 +6548,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                        case MONO_TYPE_FNPTR:
                                        case MONO_TYPE_ARRAY:
                                                NEW_PCONST (cfg, *sp, *((gpointer *)addr));
-                                               type_to_eval_stack_type (field->type, *sp);
+                                               type_to_eval_stack_type (cfg, field->type, *sp);
                                                sp++;
                                                break;
 #endif
@@ -6400,8 +6571,8 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                if (!is_const) {
                                        MonoInst *load;
                                        CHECK_STACK_OVF (1);
-                                       MONO_INST_NEW (cfg, load, mono_type_to_ldind (field->type));
-                                       type_to_eval_stack_type (field->type, 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;
                                        *sp++ = load;
@@ -6421,7 +6592,8 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        token = read32 (ip + 1);
                        klass = mini_get_class (method, token, generic_context);
                        CHECK_TYPELOAD (klass);
-                       n = mono_type_to_stind (&klass->byval_arg);
+                       n = mini_type_to_stind (cfg, &klass->byval_arg);
+                       /* FIXME: handle CEE_STIND_R4 */
                        if (n == CEE_STOBJ) {
                                handle_stobj (cfg, bblock, sp [0], sp [1], ip, klass, FALSE, FALSE, TRUE);
                        } else {
@@ -6440,6 +6612,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        break;
                case CEE_BOX: {
                        MonoInst *val;
+
                        CHECK_STACK (1);
                        --sp;
                        val = *sp;
@@ -6448,6 +6621,9 @@ 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_context))
+                               GENERIC_SHARING_FAILURE;
+
                        if (MONO_TYPE_IS_REFERENCE (&klass->byval_arg)) {
                                *sp++ = val;
                                ip += 5;
@@ -6499,7 +6675,9 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        inline_costs += 1;
                        break;
                }
-               case CEE_NEWARR:
+               case CEE_NEWARR: {
+                       int context_used;
+
                        CHECK_STACK (1);
                        MONO_INST_NEW (cfg, ins, *ip);
                        ins->cil_code = ip;
@@ -6520,6 +6698,15 @@ 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)
+                               context_used = mono_class_check_context_used (klass, generic_context);
+                       else
+                               context_used = 0;
+
+                       if (context_used)
+                               GENERIC_SHARING_FAILURE;
+
                        ins->inst_newa_class = klass;
                        ins->inst_newa_len = *sp;
                        ins->type = STACK_OBJ;
@@ -6572,6 +6759,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        }
                        inline_costs += 1;
                        break;
+               }
                case CEE_LDLEN:
                        CHECK_STACK (1);
                        --sp;
@@ -6625,16 +6813,16 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                UNVERIFIED;
                        CHECK_OPSIZE (5);
                        token = read32 (ip + 1);
-                       klass = mono_class_get_full (image, token, generic_context);
+                       klass = mini_get_class (method, token, generic_context);
                        CHECK_TYPELOAD (klass);
                        mono_class_init (klass);
                        NEW_LDELEMA (cfg, load, sp, klass);
                        load->cil_code = ip;
-                       MONO_INST_NEW (cfg, ins, mono_type_to_ldind (&klass->byval_arg));
+                       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 (&klass->byval_arg, ins);
+                       type_to_eval_stack_type (cfg, &klass->byval_arg, ins);
                        ip += 5;
                        break;
                }
@@ -6731,7 +6919,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                UNVERIFIED;
                        CHECK_OPSIZE (5);
                        token = read32 (ip + 1);
-                       klass = mono_class_get_full (image, token, generic_context);
+                       klass = mini_get_class (method, token, generic_context);
                        CHECK_TYPELOAD (klass);
                        mono_class_init (klass);
                        if (MONO_TYPE_IS_REFERENCE (&klass->byval_arg)) {
@@ -6760,7 +6948,8 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                NEW_LDELEMA (cfg, load, sp, klass);
                                load->cil_code = ip;
 
-                               n = mono_type_to_stind (&klass->byval_arg);
+                               n = mini_type_to_stind (cfg, &klass->byval_arg);
+                               /* FIXME: CEE_STIND_R4 */
                                if (n == CEE_STOBJ)
                                        handle_stobj (cfg, bblock, load, sp [2], ip, klass, FALSE, FALSE, TRUE);
                                else {
@@ -6863,6 +7052,9 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        mono_class_init (klass);
                        ins->cil_code = ip;
 
+                       if (cfg->generic_sharing_context && mono_class_check_context_used (klass, generic_context))
+                               GENERIC_SHARING_FAILURE;
+
                        loc = mono_compile_create_var (cfg, &mono_defaults.typed_reference_class->byval_arg, OP_LOCAL);
                        NEW_TEMPLOADA (cfg, ins->inst_right, loc->inst_c0);
 
@@ -6893,6 +7085,9 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        }
                        else {
                                handle = mono_ldtoken (image, n, &handle_class, generic_context);
+                               if (cfg->generic_sharing_context &&
+                                               mono_class_check_context_used (handle_class, generic_context))
+                                       GENERIC_SHARING_FAILURE;
                        }
                        if (!handle)
                                goto load_error;
@@ -6902,6 +7097,8 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                int temp;
                                MonoInst *res, *store, *addr, *vtvar, *iargs [3];
 
+                               GENERIC_SHARING_FAILURE;
+
                                vtvar = mono_compile_create_var (cfg, &handle_class->byval_arg, OP_LOCAL); 
 
                                NEW_IMAGECONST (cfg, iargs [0], image);
@@ -7241,6 +7438,16 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                bblock->out_of_line = TRUE;
                                ip += 2;
                                break;
+                       case CEE_MONO_TLS:
+                               CHECK_STACK_OVF (1);
+                               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;
+                               break;
                        default:
                                g_error ("opcode 0x%02x 0x%02x not handled", MONO_CUSTOM_PREFIX, ip [1]);
                                break;
@@ -7320,6 +7527,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        }
                        case CEE_LDFTN: {
                                MonoInst *argconst;
+                               MonoMethod *cil_method;
                                int temp;
 
                                CHECK_STACK_OVF (1);
@@ -7330,9 +7538,18 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                        goto load_error;
                                mono_class_init (cmethod->klass);
 
-                               if (mono_use_security_manager) {
+                               if (cfg->generic_sharing_context && mono_method_check_context_used (cmethod, generic_context))
+                                       GENERIC_SHARING_FAILURE;
+
+                               cil_method = cmethod;
+                               if (!dont_verify && !cfg->skip_visibility && !mono_method_can_access_method (method, cmethod))
+                                       METHOD_ACCESS_FAILURE;
+                               if (mono_security_get_mode () == MONO_SECURITY_MODE_CAS) {
                                        if (check_linkdemand (cfg, method, cmethod, bblock, ip))
                                                INLINE_FAILURE;
+                                       CHECK_CFG_EXCEPTION;
+                               } else if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR) {
+                                       ensure_method_is_allowed_to_call_method (cfg, method, cmethod, bblock, ip);
                                }
 
                                handle_loaded_temps (cfg, bblock, stack_start, sp);
@@ -7361,9 +7578,15 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                        goto load_error;
                                mono_class_init (cmethod->klass);
 
-                               if (mono_use_security_manager) {
+                               if (cfg->generic_sharing_context && mono_method_check_context_used (cmethod, generic_context))
+                                       GENERIC_SHARING_FAILURE;
+
+                               if (mono_security_get_mode () == MONO_SECURITY_MODE_CAS) {
                                        if (check_linkdemand (cfg, method, cmethod, bblock, ip))
                                                INLINE_FAILURE;
+                                       CHECK_CFG_EXCEPTION;
+                               } else if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR) {
+                                       ensure_method_is_allowed_to_call_method (cfg, method, cmethod, bblock, ip);
                                }
 
                                handle_loaded_temps (cfg, bblock, stack_start, sp);
@@ -7541,6 +7764,10 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                token = read32 (ip + 2);
                                klass = mini_get_class (method, token, generic_context);
                                CHECK_TYPELOAD (klass);
+
+                               if (cfg->generic_sharing_context && mono_class_check_context_used (klass, generic_context))
+                                       GENERIC_SHARING_FAILURE;
+
                                if (MONO_TYPE_IS_REFERENCE (&klass->byval_arg)) {
                                        MonoInst *store, *load;
                                        NEW_PCONST (cfg, load, NULL);
@@ -7574,11 +7801,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                sp -= 3;
                                if ((cfg->opt & MONO_OPT_INTRINS) && (ip [1] == CEE_CPBLK) && (sp [2]->opcode == OP_ICONST) && ((n = sp [2]->inst_c0) <= sizeof (gpointer) * 5)) {
                                        MonoInst *copy;
-                                       MONO_INST_NEW (cfg, copy, OP_MEMCPY);
-                                       copy->inst_left = sp [0];
-                                       copy->inst_right = sp [1];
-                                       copy->cil_code = ip;
-                                       copy->backend.size = n;
+                                       NEW_MEMCPY (cfg, copy, sp [0], sp [1], n, 0);
                                        MONO_ADD_INS (bblock, copy);
                                        ip += 2;
                                        break;
@@ -7636,6 +7859,8 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                break;
                        }
                        case CEE_SIZEOF:
+                               GENERIC_SHARING_FAILURE;
+
                                CHECK_STACK_OVF (1);
                                CHECK_OPSIZE (6);
                                token = read32 (ip + 2);
@@ -7791,6 +8016,12 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
 
        return inline_costs;
 
+ exception_exit:
+       g_assert (cfg->exception_type != MONO_EXCEPTION_NONE);
+       g_slist_free (class_inits);
+       dont_inline = g_list_remove (dont_inline, method);
+       return -1;
+
  inline_failure:
        g_slist_free (class_inits);
        dont_inline = g_list_remove (dont_inline, method);
@@ -7805,9 +8036,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
  unverified:
        g_slist_free (class_inits);
        dont_inline = g_list_remove (dont_inline, method);
-       cfg->exception_type = MONO_EXCEPTION_INVALID_PROGRAM;
-       cfg->exception_message = g_strdup_printf ("Invalid IL code in %s: %s\n",
-                mono_method_full_name (method, TRUE), mono_disasm_code_one (NULL, method, ip, NULL));
+       set_exception_type_from_invalid_il (cfg, method, ip);
        return -1;
 }
 
@@ -8814,7 +9043,12 @@ mono_thread_abort (MonoObject *obj)
        /* handle_remove should be eventually called for this thread, too
        g_free (jit_tls);*/
 
-       mono_thread_exit ();
+       if ((mono_runtime_unhandled_exception_policy_get () == MONO_UNHANLED_POLICY_LEGACY) ||
+                       (obj->vtable->klass == mono_defaults.threadabortexception_class)) {
+               mono_thread_exit ();
+       } else {
+               exit (mono_environment_exitcode_get ());
+       }
 }
 
 static void*
@@ -8852,10 +9086,7 @@ setup_jit_tls_data (gpointer stack_start, gpointer abort_func)
 #endif
 
        mono_arch_setup_jit_tls_data (jit_tls);
-
-#ifdef MONO_ARCH_SIGSEGV_ON_ALTSTACK
        mono_setup_altstack (jit_tls);
-#endif
 
        return jit_tls;
 }
@@ -8865,6 +9096,7 @@ mono_thread_start_cb (gsize tid, gpointer stack_start, gpointer func)
 {
        MonoThread *thread;
        void *jit_tls = setup_jit_tls_data (stack_start, mono_thread_abort);
+       mono_debugger_thread_created (tid, jit_tls);
        thread = mono_thread_current ();
        if (thread)
                thread->jit_data = jit_tls;
@@ -8886,6 +9118,7 @@ mono_thread_attach_cb (gsize tid, gpointer stack_start)
 {
        MonoThread *thread;
        void *jit_tls = setup_jit_tls_data (stack_start, mono_thread_abort_dummy);
+       mono_debugger_thread_created (tid, (MonoJitTlsData *) jit_tls);
        thread = mono_thread_current ();
        if (thread)
                thread->jit_data = jit_tls;
@@ -8899,11 +9132,10 @@ mini_thread_cleanup (MonoThread *thread)
        MonoJitTlsData *jit_tls = thread->jit_data;
 
        if (jit_tls) {
+               mono_debugger_thread_cleanup (jit_tls);
                mono_arch_free_jit_tls_data (jit_tls);
 
-#ifdef MONO_ARCH_SIGSEGV_ON_ALTSTACK
                mono_free_altstack (jit_tls);
-#endif
                g_free (jit_tls->first_lmf);
                g_free (jit_tls);
                thread->jit_data = NULL;
@@ -8980,6 +9212,20 @@ mono_patch_info_hash (gconstpointer data)
        case MONO_PATCH_INFO_LDTOKEN:
        case MONO_PATCH_INFO_DECLSEC:
                return (ji->type << 8) | ji->data.token->token;
+       case MONO_PATCH_INFO_VTABLE:
+       case MONO_PATCH_INFO_CLASS:
+       case MONO_PATCH_INFO_IID:
+       case MONO_PATCH_INFO_ADJUSTED_IID:
+               return (ji->type << 8) | (gssize)ji->data.klass;
+       case MONO_PATCH_INFO_FIELD:
+       case MONO_PATCH_INFO_SFLDA:
+               return (ji->type << 8) | (gssize)ji->data.field;
+       case MONO_PATCH_INFO_METHODCONST:
+       case MONO_PATCH_INFO_METHOD:
+       case MONO_PATCH_INFO_METHOD_JUMP:
+               return (ji->type << 8) | (gssize)ji->data.method;
+       case MONO_PATCH_INFO_IMAGE:
+               return (ji->type << 8) | (gssize)ji->data.image;                
        default:
                return (ji->type << 8);
        }
@@ -9890,6 +10136,7 @@ mono_compile_create_vars (MonoCompile *cfg)
 
        if (cfg->verbose_level > 2)
                g_print ("creating locals\n");
+
        for (i = 0; i < header->num_locals; ++i)
                mono_compile_create_var (cfg, header->locals [i], OP_LOCAL);
        if (cfg->verbose_level > 2)
@@ -10120,6 +10367,7 @@ mono_codegen (MonoCompile *cfg)
                                code = cfg->native_code + cfg->code_len;
                                code = mono_arch_instrument_epilog (cfg, mono_profiler_method_leave, code, FALSE);
                                cfg->code_len = code - cfg->native_code;
+                               g_assert (cfg->code_len < cfg->code_size);
                        }
 
                        mono_arch_emit_epilog (cfg);
@@ -10402,11 +10650,21 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, gbool
        MonoJitInfo *jinfo;
        int dfn = 0, i, code_size_ratio;
        gboolean deadce_has_run = FALSE;
+       gboolean try_generic_shared = (opts & MONO_OPT_GSHARED) && mono_method_is_generic_sharable_impl (method);
+       MonoGenericContext *shared_context;
 
        mono_jit_stats.methods_compiled++;
        if (mono_profiler_get_events () & MONO_PROFILE_JIT_COMPILATION)
                mono_profiler_method_jit (method);
 
+       if (opts & MONO_OPT_GSHARED) {
+               if (try_generic_shared)
+                       mono_stats.generics_sharable_methods++;
+               else if (mono_method_is_generic_impl (method))
+                       mono_stats.generics_unsharable_methods++;
+       }
+
+ restart_compile:
        cfg = g_new0 (MonoCompile, 1);
        cfg->method = method;
        cfg->mempool = mono_mempool_new ();
@@ -10417,6 +10675,8 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, gbool
        cfg->verbose_level = mini_verbose;
        cfg->compile_aot = compile_aot;
        cfg->skip_visibility = method->skip_visibility;
+       if (try_generic_shared)
+               cfg->generic_sharing_context = (MonoGenericSharingContext*)&cfg->generic_sharing_context;
        cfg->token_info_hash = g_hash_table_new (NULL, NULL);
        if (!header) {
                cfg->exception_type = MONO_EXCEPTION_INVALID_PROGRAM;
@@ -10439,7 +10699,19 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, gbool
         */
        mono_compile_create_vars (cfg);
 
-       if ((i = mono_method_to_ir (cfg, method, NULL, NULL, cfg->locals_start, NULL, NULL, NULL, 0, FALSE)) < 0) {
+       if (try_generic_shared)
+               shared_context = mono_make_shared_context (cfg, mono_method_get_context (method));
+       else
+               shared_context = NULL;
+
+       if ((i = mono_method_to_ir (cfg, method, NULL, NULL, cfg->locals_start, NULL, NULL, NULL, 0, FALSE, shared_context)) < 0) {
+               if (try_generic_shared && cfg->exception_type == MONO_EXCEPTION_GENERIC_SHARING_FAILED) {
+                       mono_destroy_compile (cfg);
+                       try_generic_shared = FALSE;
+                       goto restart_compile;
+               }
+               g_assert (cfg->exception_type != MONO_EXCEPTION_GENERIC_SHARING_FAILED);
+
                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 */
@@ -10670,6 +10942,7 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, gbool
        jinfo->used_regs = cfg->used_int_regs;
        jinfo->domain_neutral = (cfg->opt & MONO_OPT_SHARED) != 0;
        jinfo->cas_inited = FALSE; /* initialization delayed at the first stalk walk using this method */
+       jinfo->generic_shared = cfg->generic_sharing_context ? 1 : 0;
 
        if (header->num_clauses) {
                int i;
@@ -10741,6 +11014,42 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, gbool
        return cfg;
 }
 
+static MonoMethod*
+method_get_declaring_generic_method (MonoMethod *method)
+{
+       MonoMethodInflated *inflated;
+
+       g_assert (method->is_inflated);
+
+       inflated = (MonoMethodInflated*)method;
+
+       return inflated->declaring;
+}
+
+static MonoJitInfo*
+lookup_generic_method (MonoDomain *domain, MonoMethod *method)
+{
+       MonoMethod *open_method;
+
+       if (!mono_method_is_generic_sharable_impl (method))
+               return NULL;
+
+       open_method = method_get_declaring_generic_method (method);
+
+       return mono_domain_lookup_shared_generic (domain, open_method);
+}
+
+static MonoJitInfo*
+lookup_method (MonoDomain *domain, MonoMethod *method)
+{
+       MonoJitInfo *ji = mono_internal_hash_table_lookup (&domain->jit_code_hash, method);
+
+       if (ji != NULL)
+               return ji;
+
+       return lookup_generic_method (domain, method);
+}
+
 static gpointer
 mono_jit_compile_method_inner (MonoMethod *method, MonoDomain *target_domain, int opt)
 {
@@ -10748,8 +11057,6 @@ mono_jit_compile_method_inner (MonoMethod *method, MonoDomain *target_domain, in
        gpointer code = NULL;
        MonoJitInfo *info;
 
-       method = mono_get_inflated_method (method);
-
 #ifdef MONO_USE_AOT_COMPILER
        if ((opt & MONO_OPT_AOT) && !(mono_profiler_get_events () & MONO_PROFILE_JIT_COMPILATION)) {
                MonoDomain *domain = mono_domain_get ();
@@ -10816,22 +11123,33 @@ mono_jit_compile_method_inner (MonoMethod *method, MonoDomain *target_domain, in
        case MONO_EXCEPTION_NONE: break;
        case MONO_EXCEPTION_TYPE_LOAD:
        case MONO_EXCEPTION_MISSING_FIELD:
-       case MONO_EXCEPTION_MISSING_METHOD: {
+       case MONO_EXCEPTION_MISSING_METHOD:
+       case MONO_EXCEPTION_FILE_NOT_FOUND: {
                /* Throw a type load exception if needed */
                MonoLoaderError *error = mono_loader_get_last_error ();
+               MonoException *ex;
 
                if (error) {
-                       MonoException *ex = mono_loader_error_prepare_exception (error);
-                       mono_destroy_compile (cfg);
-                       mono_raise_exception (ex);
+                       ex = mono_loader_error_prepare_exception (error);
                } else {
                        if (cfg->exception_ptr) {
-                               MonoException *ex = mono_class_get_exception_for_failure (cfg->exception_ptr);
-                               mono_destroy_compile (cfg);
-                               mono_raise_exception (ex);
+                               ex = mono_class_get_exception_for_failure (cfg->exception_ptr);
+                       } else {
+                               if (cfg->exception_type == MONO_EXCEPTION_MISSING_FIELD)
+                                       ex = mono_exception_from_name_msg (mono_defaults.corlib, "System", "MissingFieldException", cfg->exception_message);
+                               else if (cfg->exception_type == MONO_EXCEPTION_MISSING_METHOD)
+                                       ex = mono_exception_from_name_msg (mono_defaults.corlib, "System", "MissingMethodException", cfg->exception_message);
+                               else if (cfg->exception_type == MONO_EXCEPTION_TYPE_LOAD)
+                                       ex = mono_exception_from_name_msg (mono_defaults.corlib, "System", "TypeLoadException", cfg->exception_message);
+                               else if (cfg->exception_type == MONO_EXCEPTION_FILE_NOT_FOUND)
+                                       ex = mono_exception_from_name_msg (mono_defaults.corlib, "System", "FileNotFoundException", cfg->exception_message);
+                               else
+                                       g_assert_not_reached ();
                        }
-                       g_assert_not_reached ();
                }
+               mono_destroy_compile (cfg);
+               mono_raise_exception (ex);
+               break;
        }
        case MONO_EXCEPTION_INVALID_PROGRAM: {
                MonoException *ex = mono_exception_from_name_msg (mono_defaults.corlib, "System", "InvalidProgramException", cfg->exception_message);
@@ -10845,18 +11163,26 @@ mono_jit_compile_method_inner (MonoMethod *method, MonoDomain *target_domain, in
                mono_raise_exception (ex);
                break;
        }
+       case MONO_EXCEPTION_METHOD_ACCESS: {
+               MonoException *ex = mono_exception_from_name_msg (mono_defaults.corlib, "System", "MethodAccessException", cfg->exception_message);
+               mono_destroy_compile (cfg);
+               mono_raise_exception (ex);
+               break;
+       }
+       case MONO_EXCEPTION_FIELD_ACCESS: {
+               MonoException *ex = mono_exception_from_name_msg (mono_defaults.corlib, "System", "FieldAccessException", cfg->exception_message);
+               mono_destroy_compile (cfg);
+               mono_raise_exception (ex);
+               break;
+       }
        /* this can only be set if the security manager is active */
        case MONO_EXCEPTION_SECURITY_LINKDEMAND: {
-               MonoAssembly *assembly = mono_image_get_assembly (method->klass->image);
-               MonoReflectionAssembly *refass = (MonoReflectionAssembly*) mono_assembly_get_object (target_domain, assembly);
-               MonoReflectionMethod *refmet = mono_method_get_object (target_domain, method, NULL);
                MonoSecurityManager* secman = mono_security_manager_get_methods ();
                MonoObject *exc = NULL;
-               gpointer args [3];
+               gpointer args [2];
 
                args [0] = &cfg->exception_data;
-               args [1] = refass;
-               args [2] = refmet;
+               args [1] = &method;
                mono_runtime_invoke (secman->linkdemandsecurityexception, NULL, args, &exc);
 
                mono_destroy_compile (cfg);
@@ -10873,7 +11199,7 @@ mono_jit_compile_method_inner (MonoMethod *method, MonoDomain *target_domain, in
        /* Check if some other thread already did the job. In this case, we can
        discard the code this thread generated. */
 
-       if ((info = mono_internal_hash_table_lookup (&target_domain->jit_code_hash, method))) {
+       if ((info = lookup_method (target_domain, method))) {
                /* We can't use a domain specific method in another domain */
                if ((target_domain == mono_domain_get ()) || info->domain_neutral) {
                        code = info->code_start;
@@ -10884,6 +11210,13 @@ mono_jit_compile_method_inner (MonoMethod *method, MonoDomain *target_domain, in
        if (code == NULL) {
                mono_internal_hash_table_insert (&target_domain->jit_code_hash, method, cfg->jit_info);
                code = cfg->native_code;
+
+               if (cfg->generic_sharing_context && mono_method_is_generic_sharable_impl (method)) {
+                       /* g_print ("inserting method %s.%s.%s\n", method->klass->name_space, method->klass->name, method->name); */
+                       mono_domain_register_shared_generic (target_domain, 
+                               method_get_declaring_generic_method (method), cfg->jit_info);
+                       mono_stats.generics_shared_methods++;
+               }
        }
 
        mono_destroy_compile (cfg);
@@ -10941,7 +11274,7 @@ mono_jit_compile_method_with_opt (MonoMethod *method, guint32 opt)
 
        mono_domain_lock (target_domain);
 
-       if ((info = mono_internal_hash_table_lookup (&target_domain->jit_code_hash, method))) {
+       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)) {
                        mono_domain_unlock (target_domain);
@@ -11023,14 +11356,14 @@ mono_jit_free_method (MonoDomain *domain, MonoMethod *method)
 
        /* 
         * This needs to be done before freeing code_mp, since the code address is the
-        * key in the table, so if we the code_mp first, another thread can grab the
+        * key in the table, so if we free the code_mp first, another thread can grab the
         * same code address and replace our entry in the table.
         */
        mono_jit_info_table_remove (domain, ji->ji);
 
        if (destroy)
                mono_code_manager_destroy (ji->code_mp);
-       g_free (ji->ji);
+       mono_thread_hazardous_free_or_queue (ji->ji, g_free);
        g_free (ji);
 }
 
@@ -11047,7 +11380,7 @@ mono_jit_find_compiled_method (MonoDomain *domain, MonoMethod *method)
 
        mono_domain_lock (target_domain);
 
-       if ((info = mono_internal_hash_table_lookup (&target_domain->jit_code_hash, method))) {
+       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)) {
                        mono_domain_unlock (target_domain);
@@ -11080,7 +11413,6 @@ mono_jit_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObjec
                return NULL;
        }
 
-       method = mono_get_inflated_method (method);
        invoke = mono_marshal_get_runtime_invoke (method);
        runtime_invoke = mono_jit_compile_method (invoke);
        
@@ -11156,18 +11488,12 @@ SIG_HANDLER_SIGNATURE (sigill_signal_handler)
        mono_arch_handle_exception (ctx, exc, FALSE);
 }
 
-#ifdef MONO_ARCH_SIGSEGV_ON_ALTSTACK
-
-#ifndef MONO_ARCH_USE_SIGACTION
-#error "Can't use sigaltstack without sigaction"
-#endif
-
-#endif
-
 static void
 SIG_HANDLER_SIGNATURE (sigsegv_signal_handler)
 {
+#ifndef MONO_ARCH_SIGSEGV_ON_ALTSTACK
        MonoException *exc = NULL;
+#endif
        MonoJitInfo *ji;
 
 #ifdef MONO_ARCH_SIGSEGV_ON_ALTSTACK
@@ -11188,22 +11514,58 @@ SIG_HANDLER_SIGNATURE (sigsegv_signal_handler)
        }
 #endif
 
+       ji = mono_jit_info_table_find (mono_domain_get (), mono_arch_ip_from_context (ctx));
+
 #ifdef MONO_ARCH_SIGSEGV_ON_ALTSTACK
-       /* Can't allocate memory using Boehm GC on altstack */
+       /* we got a stack overflow in the soft-guard pages
+        * There are two cases:
+        * 1) managed code caused the overflow: we unprotect the soft-guard page
+        * and let the arch-specific code trigger the exception handling mechanism
+        * in the thread stack. The soft-guard pages will be protected again as the stack is unwound.
+        * 2) unmanaged code caused the overflow: we unprotect the soft-guard page
+        * and hope we can continue with those enabled, at least until the hard-guard page
+        * is hit. The alternative to continuing here is to just print a message and abort.
+        * We may add in the future the code to protect the pages again in the codepath
+        * when we return from unmanaged to managed code.
+        */
+       if (jit_tls->stack_ovf_guard_size && (guint8*)info->si_addr >= (guint8*)jit_tls->stack_ovf_guard_base &&
+                       (guint8*)info->si_addr < (guint8*)jit_tls->stack_ovf_guard_base + jit_tls->stack_ovf_guard_size) {
+               mono_mprotect (jit_tls->stack_ovf_guard_base, jit_tls->stack_ovf_guard_size, MONO_MMAP_READ|MONO_MMAP_WRITE|MONO_MMAP_EXEC);
+               if (ji) {
+                       mono_arch_handle_altstack_exception (ctx, info->si_addr, TRUE);
+               } else {
+                       /* We print a message: after this even managed stack overflows
+                        * may crash the runtime
+                        */
+                       fprintf (stderr, "Stack overflow in unmanaged: IP: %p, fault addr: %p\n", mono_arch_ip_from_context (ctx), (gpointer)info->si_addr);
+               }
+               return;
+       }
+       /* The hard-guard page has been hit: there is not much we can do anymore
+        * Print a hopefully clear message and abort.
+        */
        if (jit_tls->stack_size && 
-               ((guint8*)info->si_addr >= (guint8*)jit_tls->end_of_stack - jit_tls->stack_size) &&
-               ((guint8*)info->si_addr < (guint8*)jit_tls->end_of_stack))
-               exc = mono_domain_get ()->stack_overflow_ex;
-       else
-               exc = mono_domain_get ()->null_reference_ex;
-#endif
+                       ABS ((guint8*)info->si_addr - ((guint8*)jit_tls->end_of_stack - jit_tls->stack_size)) < 32768) {
+               const char *method;
+               /* we don't do much now, but we can warn the user with a useful message */
+               fprintf (stderr, "Stack overflow: IP: %p, fault addr: %p\n", mono_arch_ip_from_context (ctx), (gpointer)info->si_addr);
+               if (ji && ji->method)
+                       method = mono_method_full_name (ji->method, TRUE);
+               else
+                       method = "Unmanaged";
+               fprintf (stderr, "At %s\n", method);
+               abort ();
+       } else {
+               mono_arch_handle_altstack_exception (ctx, info->si_addr, FALSE);
+       }
+#else
 
-       ji = mono_jit_info_table_find (mono_domain_get (), mono_arch_ip_from_context(ctx));
        if (!ji) {
                mono_handle_native_sigsegv (SIGSEGV, ctx);
        }
                        
        mono_arch_handle_exception (ctx, exc, FALSE);
+#endif
 }
 
 #ifndef PLATFORM_WIN32
@@ -11429,6 +11791,10 @@ add_signal_handler (int signo, gpointer handler)
        sa.sa_sigaction = handler;
        sigemptyset (&sa.sa_mask);
        sa.sa_flags = SA_SIGINFO;
+#ifdef MONO_ARCH_SIGSEGV_ON_ALTSTACK
+       if (signo == SIGSEGV)
+               sa.sa_flags |= SA_ONSTACK;
+#endif
 #else
        sa.sa_handler = handler;
        sigemptyset (&sa.sa_mask);
@@ -11453,10 +11819,6 @@ remove_signal_handler (int signo)
 static void
 mono_runtime_install_handlers (void)
 {
-#ifdef MONO_ARCH_SIGSEGV_ON_ALTSTACK
-       struct sigaction sa;
-#endif
-
 #ifdef PLATFORM_WIN32
        win32_seh_init();
        win32_seh_set_handler(SIGFPE, sigfpe_signal_handler);
@@ -11488,14 +11850,7 @@ mono_runtime_install_handlers (void)
        add_signal_handler (SIGABRT, sigabrt_signal_handler);
 
        /* catch SIGSEGV */
-#ifdef MONO_ARCH_SIGSEGV_ON_ALTSTACK
-       sa.sa_sigaction = sigsegv_signal_handler;
-       sigemptyset (&sa.sa_mask);
-       sa.sa_flags = SA_SIGINFO | SA_ONSTACK;
-       g_assert (sigaction (SIGSEGV, &sa, NULL) != -1);
-#else
        add_signal_handler (SIGSEGV, sigsegv_signal_handler);
-#endif
 #endif /* PLATFORM_WIN32 */
 }
 
@@ -11671,6 +12026,28 @@ mono_jit_create_remoting_trampoline (MonoMethod *method, MonoRemotingTarget targ
        return mono_get_addr_from_ftnptr (addr);
 }
 
+#ifdef MONO_ARCH_HAVE_IMT
+static gpointer
+mini_get_imt_trampoline (void)
+{
+       static gpointer tramp = NULL;
+       if (!tramp)
+               tramp =  mono_arch_create_specific_trampoline (MONO_FAKE_IMT_METHOD, MONO_TRAMPOLINE_GENERIC, mono_get_root_domain (), NULL);
+       return tramp;
+}
+#endif
+
+#ifdef MONO_ARCH_COMMON_VTABLE_TRAMPOLINE
+static gpointer
+mini_get_vtable_trampoline (void)
+{
+       static gpointer tramp = NULL;
+       if (!tramp)
+               tramp =  mono_arch_create_specific_trampoline (MONO_FAKE_VTABLE_METHOD, MONO_TRAMPOLINE_GENERIC, mono_get_root_domain (), NULL);
+       return tramp;
+}
+#endif
+
 static void
 mini_parse_debug_options (void)
 {
@@ -11719,11 +12096,14 @@ mini_init (const char *filename, const char *runtime_version)
 
        InitializeCriticalSection (&jit_mutex);
 
-       global_codeman = mono_code_manager_new ();
+       if (!global_codeman)
+               global_codeman = mono_code_manager_new ();
        jit_icall_name_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
 
        mono_arch_cpu_init ();
 
+       mono_arch_init ();
+
        mono_init_trampolines ();
 
        mono_init_exceptions ();
@@ -11824,6 +12204,13 @@ mini_init (const char *filename, const char *runtime_version)
                domain = mono_init_version (filename, runtime_version);
        else
                domain = mono_init_from_assembly (filename, filename);
+#ifdef MONO_ARCH_HAVE_IMT
+       mono_install_imt_thunk_builder (mono_arch_build_imt_thunk);
+       mono_install_imt_trampoline (mini_get_imt_trampoline ());
+#if MONO_ARCH_COMMON_VTABLE_TRAMPOLINE
+       mono_install_vtable_trampoline (mini_get_vtable_trampoline ());
+#endif
+#endif
        mono_icall_init ();
 
        mono_add_internal_call ("System.Diagnostics.StackFrame::get_frame_info", 
@@ -12031,6 +12418,7 @@ print_jit_stats (void)
                g_print ("Locals stack size:      %ld\n", mono_jit_stats.locals_stack_size);
 
                g_print ("\nCreated object count:   %ld\n", mono_stats.new_object_count);
+               g_print ("Delegates created:      %ld\n", mono_stats.delegate_creations);
                g_print ("Initialized classes:    %ld\n", mono_stats.initialized_class_count);
                g_print ("Used classes:           %ld\n", mono_stats.used_class_count);
                g_print ("Generic vtables:        %ld\n", mono_stats.generic_vtable_count);
@@ -12047,11 +12435,30 @@ print_jit_stats (void)
                g_print ("Generics metadata size: %ld\n", mono_stats.generics_metadata_size);
                g_print ("Generics virtual invokes: %ld\n", mono_jit_stats.generic_virtual_invocations);
 
+               g_print ("Sharable generic methods: %ld\n", mono_stats.generics_sharable_methods);
+               g_print ("Unsharable generic methods: %ld\n", mono_stats.generics_unsharable_methods);
+               g_print ("Shared generic methods: %ld\n", mono_stats.generics_shared_methods);
+
                g_print ("Dynamic code allocs:    %ld\n", mono_stats.dynamic_code_alloc_count);
                g_print ("Dynamic code bytes:     %ld\n", mono_stats.dynamic_code_bytes_count);
                g_print ("Dynamic code frees:     %ld\n", mono_stats.dynamic_code_frees_count);
 
-               if (mono_use_security_manager) {
+               g_print ("IMT tables size:        %ld\n", mono_stats.imt_tables_size);
+               g_print ("IMT number of tables:   %ld\n", mono_stats.imt_number_of_tables);
+               g_print ("IMT number of methods:  %ld\n", mono_stats.imt_number_of_methods);
+               g_print ("IMT used slots:         %ld\n", mono_stats.imt_used_slots);
+               g_print ("IMT colliding slots:    %ld\n", mono_stats.imt_slots_with_collisions);
+               g_print ("IMT max collisions:     %ld\n", mono_stats.imt_max_collisions_in_slot);
+               g_print ("IMT methods at max col: %ld\n", mono_stats.imt_method_count_when_max_collisions);
+               g_print ("IMT thunks size:        %ld\n", mono_stats.imt_thunks_size);
+
+               g_print ("JIT info table inserts: %ld\n", mono_stats.jit_info_table_insert_count);
+               g_print ("JIT info table removes: %ld\n", mono_stats.jit_info_table_remove_count);
+               g_print ("JIT info table lookups: %ld\n", mono_stats.jit_info_table_lookup_count);
+
+               g_print ("Hazardous pointers:     %ld\n", mono_stats.hazardous_pointer_count);
+
+               if (mono_security_get_mode () == MONO_SECURITY_MODE_CAS) {
                        g_print ("\nDecl security check   : %ld\n", mono_jit_stats.cas_declsec_check);
                        g_print ("LinkDemand (user)     : %ld\n", mono_jit_stats.cas_linkdemand);
                        g_print ("LinkDemand (icall)    : %ld\n", mono_jit_stats.cas_linkdemand_icall);
@@ -12089,26 +12496,31 @@ mini_cleanup (MonoDomain *domain)
 
        mono_profiler_shutdown ();
 
-       mono_debug_cleanup ();
-
        mono_icall_cleanup ();
 
        mono_runtime_cleanup_handlers ();
 
        mono_domain_free (domain, TRUE);
 
+       mono_debugger_cleanup ();
+
        mono_code_manager_destroy (global_codeman);
        g_hash_table_destroy (jit_icall_name_hash);
        if (class_init_hash_addr)
                g_hash_table_destroy (class_init_hash_addr);
        g_free (emul_opcode_map);
 
+       mono_arch_cleanup ();
+
        mono_cleanup ();
 
        mono_trace_cleanup ();
 
        mono_counters_dump (-1, stdout);
 
+       if (mono_inject_async_exc_method)
+               mono_method_desc_free (mono_inject_async_exc_method);
+
        TlsFree(mono_jit_tls_id);
 
        DeleteCriticalSection (&jit_mutex);