Mon Oct 15 10:37:15 CEST 2007 Paolo Molaro <lupus@ximian.com>
[mono.git] / mono / mini / mini.c
index 75fb952bd72fcbeb1c0b84751b3392f50826e3c9..40cbaa816f944c9d6a530720526358db085474dd 100644 (file)
                goto exception_exit;    \
        } while (0)
 #define GENERIC_SHARING_FAILURE do {   \
-               if (cfg->generic_shared) {      \
+               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;    \
@@ -560,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)
 
@@ -569,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)
 
@@ -613,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)
 
@@ -634,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)
@@ -651,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);       \
@@ -668,7 +668,7 @@ 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);       \
@@ -1193,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;
 
@@ -1255,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);
        }
@@ -1631,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.
@@ -1704,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;
 }
 
@@ -2341,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);
        }
@@ -2452,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);
                }
                
@@ -2534,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;
@@ -3016,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;
@@ -3367,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];
@@ -3375,9 +3422,8 @@ 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;
@@ -4051,7 +4097,7 @@ 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 (cfg->generic_shared) {
+       if (cfg->generic_sharing_context) {
                g_assert (shared_context);
                generic_context = shared_context;
        } else if (sig->is_inflated)
@@ -4694,7 +4740,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        if (!cmethod)
                                goto load_error;
 
-                       if (cfg->generic_shared && mono_method_check_context_used (cmethod, generic_context))
+                       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) {
@@ -4793,7 +4839,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        if (cmethod && cmethod->klass->generic_container)
                                UNVERIFIED;
 
-                       if (cfg->generic_shared && cmethod && mono_method_check_context_used (cmethod, generic_context))
+                       if (cfg->generic_sharing_context && cmethod && mono_method_check_context_used (cmethod, generic_context))
                                GENERIC_SHARING_FAILURE;
 
                        CHECK_STACK (n);
@@ -4815,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);
@@ -4941,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++;
                                }
@@ -5147,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 */
@@ -5772,7 +5818,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        if (!mono_class_init (cmethod->klass))
                                goto load_error;
 
-                       if (cfg->generic_shared && mono_method_check_context_used (cmethod, generic_context))
+                       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) {
@@ -5884,7 +5930,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        if (sp [0]->type != STACK_OBJ)
                                UNVERIFIED;
 
-                       if (cfg->generic_shared && mono_class_check_context_used (klass, generic_context))
+                       if (cfg->generic_sharing_context && mono_class_check_context_used (klass, generic_context))
                                GENERIC_SHARING_FAILURE;
 
                        /* Needed by the code generated in inssel.brg */
@@ -5942,7 +5988,7 @@ 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_shared && mono_class_check_context_used (klass, generic_context))
+                       if (cfg->generic_sharing_context && mono_class_check_context_used (klass, generic_context))
                                GENERIC_SHARING_FAILURE;
 
                        if (MONO_TYPE_IS_REFERENCE (&klass->byval_arg)) {
@@ -6042,7 +6088,7 @@ 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_shared && mono_class_check_context_used (klass, generic_context))
+                       if (cfg->generic_sharing_context && mono_class_check_context_used (klass, generic_context))
                                GENERIC_SHARING_FAILURE;
 
                        if (mono_class_is_nullable (klass)) {
@@ -6084,7 +6130,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        if (sp [0]->type != STACK_OBJ)
                                UNVERIFIED;
 
-                       if (cfg->generic_shared && mono_class_check_context_used (klass, generic_context))
+                       if (cfg->generic_sharing_context && mono_class_check_context_used (klass, generic_context))
                                GENERIC_SHARING_FAILURE;
 
                        /* Needed by the code generated in inssel.brg */
@@ -6218,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];
@@ -6234,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;
@@ -6253,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];
@@ -6317,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);
@@ -6358,7 +6404,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        if (!dont_verify && !cfg->skip_visibility && !mono_method_can_access_field (method, field))
                                FIELD_ACCESS_FAILURE;
 
-                       if (cfg->generic_shared && mono_class_check_context_used (klass, generic_context))
+                       if (cfg->generic_sharing_context && mono_class_check_context_used (klass, generic_context))
                                GENERIC_SHARING_FAILURE;
 
                        g_assert (!(field->type->attrs & FIELD_ATTRIBUTE_LITERAL));
@@ -6439,7 +6485,7 @@ 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];
@@ -6502,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
@@ -6525,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;
@@ -6546,7 +6592,7 @@ 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);
@@ -6575,7 +6621,7 @@ 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_shared && mono_class_check_context_used (klass, generic_context))
+                       if (cfg->generic_sharing_context && mono_class_check_context_used (klass, generic_context))
                                GENERIC_SHARING_FAILURE;
 
                        if (MONO_TYPE_IS_REFERENCE (&klass->byval_arg)) {
@@ -6653,7 +6699,7 @@ 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_shared)
+                       if (cfg->generic_sharing_context)
                                context_used = mono_class_check_context_used (klass, generic_context);
                        else
                                context_used = 0;
@@ -6767,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;
                }
@@ -6873,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)) {
@@ -6902,7 +6948,7 @@ 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);
@@ -7006,7 +7052,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        mono_class_init (klass);
                        ins->cil_code = ip;
 
-                       if (cfg->generic_shared && mono_class_check_context_used (klass, generic_context))
+                       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);
@@ -7039,7 +7085,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        }
                        else {
                                handle = mono_ldtoken (image, n, &handle_class, generic_context);
-                               if (cfg->generic_shared &&
+                               if (cfg->generic_sharing_context &&
                                                mono_class_check_context_used (handle_class, generic_context))
                                        GENERIC_SHARING_FAILURE;
                        }
@@ -7492,7 +7538,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                        goto load_error;
                                mono_class_init (cmethod->klass);
 
-                               if (cfg->generic_shared && mono_method_check_context_used (cmethod, generic_context))
+                               if (cfg->generic_sharing_context && mono_method_check_context_used (cmethod, generic_context))
                                        GENERIC_SHARING_FAILURE;
 
                                cil_method = cmethod;
@@ -7532,7 +7578,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                        goto load_error;
                                mono_class_init (cmethod->klass);
 
-                               if (cfg->generic_shared && mono_method_check_context_used (cmethod, generic_context))
+                               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) {
@@ -7719,7 +7765,7 @@ 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_shared && mono_class_check_context_used (klass, generic_context))
+                               if (cfg->generic_sharing_context && mono_class_check_context_used (klass, generic_context))
                                        GENERIC_SHARING_FAILURE;
 
                                if (MONO_TYPE_IS_REFERENCE (&klass->byval_arg)) {
@@ -10629,7 +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;
-       cfg->generic_shared = try_generic_shared;
+       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;
@@ -10895,7 +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_shared;
+       jinfo->generic_shared = cfg->generic_sharing_context ? 1 : 0;
 
        if (header->num_clauses) {
                int i;
@@ -11164,7 +11211,7 @@ mono_jit_compile_method_inner (MonoMethod *method, MonoDomain *target_domain, in
                mono_internal_hash_table_insert (&target_domain->jit_code_hash, method, cfg->jit_info);
                code = cfg->native_code;
 
-               if (cfg->generic_shared && mono_method_is_generic_sharable_impl (method)) {
+               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);
@@ -11979,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)
 {
@@ -12126,9 +12195,6 @@ mini_init (const char *filename, const char *runtime_version)
        mono_install_get_class_from_name (mono_aot_get_class_from_name);
        mono_install_jit_info_find_in_aot (mono_aot_find_jit_info);
 
-#ifdef MONO_ARCH_HAVE_IMT
-       mono_install_imt_thunk_builder (mono_arch_build_imt_thunk);
-#endif
        if (debug_options.collect_pagefault_stats) {
                mono_raw_buffer_set_make_unreadable (TRUE);
                mono_aot_set_make_unreadable (TRUE);
@@ -12138,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", 
@@ -12345,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);