* mini-codegen.c (mono_local_regalloc): Make free mask
[mono.git] / mono / mini / mini.c
index e9a5ca2101f4ec5caedf466613dd494ba25cd9ec..b074740dc7456833ac2c336b2d7cab922a15acdc 100644 (file)
@@ -60,6 +60,7 @@
 #include <mono/metadata/verify.h>
 #include <mono/metadata/verify-internals.h>
 #include <mono/metadata/mempool-internals.h>
+#include <mono/metadata/attach.h>
 #include <mono/utils/mono-math.h>
 #include <mono/utils/mono-compiler.h>
 #include <mono/utils/mono-counters.h>
                        goto exception_exit;    \
                }                       \
        } while (0)
-#define GENERIC_SHARING_FAILURE_IF_VALUETYPE_METHOD(opcode) do {                       \
-               if (method->klass->valuetype)   \
-                       GENERIC_SHARING_FAILURE ((opcode)); \
-       } while (0)
 #define GET_RGCTX(rgctx, context_used) do {                                            \
                MonoInst *this = NULL;                                  \
                g_assert (context_used);                                \
-               GENERIC_SHARING_FAILURE_IF_VALUETYPE_METHOD(*ip);       \
                if (!(method->flags & METHOD_ATTRIBUTE_STATIC) &&       \
-                               !((context_used) & MONO_GENERIC_CONTEXT_USED_METHOD)) \
+                               !((context_used) & MONO_GENERIC_CONTEXT_USED_METHOD) && \
+                               !method->klass->valuetype)              \
                        NEW_ARGLOAD (cfg, this, 0);                     \
                (rgctx) = get_runtime_generic_context (cfg, method, (context_used), this, ip); \
        } while (0)
@@ -174,9 +171,7 @@ static __thread gpointer mono_jit_tls MONO_TLS_FAST;
 
 MonoTraceSpec *mono_jit_trace_calls = NULL;
 gboolean mono_break_on_exc = FALSE;
-#ifndef DISABLE_AOT
 gboolean mono_compile_aot = FALSE;
-#endif
 /* If this is set, no code is generated dynamically, everything is taken from AOT files */
 gboolean mono_aot_only = FALSE;
 /* Whenever to use IMT */
@@ -221,6 +216,14 @@ gboolean check_for_pending_exc = TRUE;
 /* Whenever to disable passing/returning small valuetypes in registers for managed methods */
 gboolean disable_vtypes_in_regs = FALSE;
 
+gboolean mono_dont_free_global_codeman;
+
+#ifdef DISABLE_JIT
+/* Define this here, since many files reference it */
+const guint8 mono_burg_arity [MBMAX_OPCODES] = {
+};
+#endif
+
 gboolean
 mono_running_on_valgrind (void)
 {
@@ -267,7 +270,7 @@ get_method_from_ip (void *ip)
                user_data.ip = ip;
                user_data.method = NULL;
                mono_domain_lock (domain);
-               g_hash_table_foreach (domain->jit_trampoline_hash, find_tramp, &user_data);
+               g_hash_table_foreach (domain_jit_info (domain)->jit_trampoline_hash, find_tramp, &user_data);
                mono_domain_unlock (domain);
                if (user_data.method) {
                        char *mname = mono_method_full_name (user_data.method, TRUE);
@@ -333,7 +336,7 @@ mono_print_method_from_ip (void *ip)
                user_data.ip = ip;
                user_data.method = NULL;
                mono_domain_lock (domain);
-               g_hash_table_foreach (domain->jit_trampoline_hash, find_tramp, &user_data);
+               g_hash_table_foreach (domain_jit_info (domain)->jit_trampoline_hash, find_tramp, &user_data);
                mono_domain_unlock (domain);
                if (user_data.method) {
                        char *mname = mono_method_full_name (user_data.method, TRUE);
@@ -1346,87 +1349,6 @@ condbr_to_fp_br (int opcode)
 }
 #endif
 
-/*
- * Returns the type used in the eval stack when @type is loaded.
- * FIXME: return a MonoType/MonoClass for the byref and VALUETYPE cases.
- */
-static void
-type_to_eval_stack_type (MonoCompile *cfg, MonoType *type, MonoInst *inst)
-{
-       MonoClass *klass;
-
-       inst->klass = klass = mono_class_from_mono_type (type);
-       if (type->byref) {
-               inst->type = STACK_MP;
-               return;
-       }
-
-handle_enum:
-       switch (type->type) {
-       case MONO_TYPE_VOID:
-               inst->type = STACK_INV;
-               return;
-       case MONO_TYPE_I1:
-       case MONO_TYPE_U1:
-       case MONO_TYPE_BOOLEAN:
-       case MONO_TYPE_I2:
-       case MONO_TYPE_U2:
-       case MONO_TYPE_CHAR:
-       case MONO_TYPE_I4:
-       case MONO_TYPE_U4:
-               inst->type = STACK_I4;
-               return;
-       case MONO_TYPE_I:
-       case MONO_TYPE_U:
-       case MONO_TYPE_PTR:
-       case MONO_TYPE_FNPTR:
-               inst->type = STACK_PTR;
-               return;
-       case MONO_TYPE_CLASS:
-       case MONO_TYPE_STRING:
-       case MONO_TYPE_OBJECT:
-       case MONO_TYPE_SZARRAY:
-       case MONO_TYPE_ARRAY:    
-               inst->type = STACK_OBJ;
-               return;
-       case MONO_TYPE_I8:
-       case MONO_TYPE_U8:
-               inst->type = STACK_I8;
-               return;
-       case MONO_TYPE_R4:
-       case MONO_TYPE_R8:
-               inst->type = STACK_R8;
-               return;
-       case MONO_TYPE_VALUETYPE:
-               if (type->data.klass->enumtype) {
-                       type = type->data.klass->enum_basetype;
-                       goto handle_enum;
-               } else {
-                       inst->klass = klass;
-                       inst->type = STACK_VTYPE;
-                       return;
-               }
-       case MONO_TYPE_TYPEDBYREF:
-               inst->klass = mono_defaults.typed_reference_class;
-               inst->type = STACK_VTYPE;
-               return;
-       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);
-       }
-}
-
 /*
  * The following tables are used to quickly validate the IL code in type_from_op ().
  */
@@ -2151,6 +2073,13 @@ mono_compile_create_var_for_vreg (MonoCompile *cfg, MonoType *type, int opcode,
                        printf ("  Create LVAR R%d (R%d, R%d)\n", inst->dreg, inst->dreg + 1, inst->dreg + 2);
                }
 
+#ifdef MONO_ARCH_SOFT_FLOAT
+               if (cfg->opt & MONO_OPT_SSA) {
+                       if (mono_type_is_float (type))
+                               inst->flags = MONO_INST_VOLATILE;
+               }
+#endif
+
                /* Allocate a dummy MonoInst for the first vreg */
                MONO_INST_NEW (cfg, tree, OP_LOCAL);
                tree->dreg = inst->dreg + 1;
@@ -4091,6 +4020,10 @@ mini_get_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSigna
                        MONO_INST_NEW (cfg, ins, OP_MEMORY_BARRIER);
                        return ins;
                }
+               if (strcmp (cmethod->name, "SpinWait_nop") == 0) {
+                       MONO_INST_NEW (cfg, ins, OP_RELAXED_NOP);
+                       return ins;
+               }
        } else if (mini_class_is_system_array (cmethod->klass) &&
                        strcmp (cmethod->name, "GetGenericValueImpl") == 0) {
                MonoInst *sp [2];
@@ -4880,7 +4813,10 @@ set_exception_object (MonoCompile *cfg, MonoException *exception)
 static MonoInst*
 get_runtime_generic_context (MonoCompile *cfg, MonoMethod *method, int context_used, MonoInst *this, unsigned char *ip)
 {
-       g_assert (!method->klass->valuetype);
+       g_assert (cfg->generic_sharing_context);
+
+       if (method->klass->valuetype)
+               g_assert (!this);
 
        if (context_used & MONO_GENERIC_CONTEXT_USED_METHOD) {
                MonoInst *mrgctx_loc, *mrgctx_var;
@@ -4892,7 +4828,7 @@ get_runtime_generic_context (MonoCompile *cfg, MonoMethod *method, int context_u
                NEW_TEMPLOAD (cfg, mrgctx_var, mrgctx_loc->inst_c0);
 
                return mrgctx_var;
-       } else if (method->flags & METHOD_ATTRIBUTE_STATIC) {
+       } else if ((method->flags & METHOD_ATTRIBUTE_STATIC) || method->klass->valuetype) {
                MonoInst *vtable_loc, *vtable_var;
 
                g_assert (!this);
@@ -5008,6 +4944,9 @@ handle_unbox_nullable (MonoCompile* cfg, MonoMethod *caller_method, int context_
        MonoMethodSignature *signature = mono_method_signature (method);
 
        if (rgctx) {
+               /* FIXME: What if the class is shared?  We might not
+                  have to get the address of the method from the
+                  RGCTX. */
                MonoInst *addr = get_runtime_generic_context_method (cfg, caller_method, context_used, bblock, method,
                        generic_context, rgctx, MONO_RGCTX_INFO_GENERIC_METHOD_CODE, ip);
 
@@ -5027,6 +4966,8 @@ handle_box_nullable_from_inst (MonoCompile *cfg, MonoMethod *caller_method, int
 
        g_assert (mono_class_is_nullable (klass));
 
+       /* FIXME: What if the class is shared?  We might not have to
+          get the method address from the RGCTX. */
        method_addr = get_runtime_generic_context_method (cfg, caller_method, context_used, bblock, method,
                        generic_context, rgctx, MONO_RGCTX_INFO_GENERIC_METHOD_CODE, ip);
        temp = mono_emit_rgctx_calli_spilled (cfg, bblock, mono_method_signature (method), &val,
@@ -5124,9 +5065,6 @@ do_return:
        *_inline_costs = inline_costs;
        *_real_offset = real_offset;
        return return_value;
-exception_exit:
-       return_value = -2;
-       goto do_return;
 unverified:
        return_value = -1;
        goto do_return;
@@ -5183,16 +5121,12 @@ emit_unbox (MonoClass *klass, guint32 token, int context_used,
        add->klass = klass;
        *sp = add;
 
-do_return:
        *_bblock = bblock;
        *_ip = ip;
        *_sp = sp;
        *_inline_costs = inline_costs;
        *_real_offset = real_offset;
        return return_value;
-exception_exit:
-       return_value = -2;
-       goto do_return;
 }
 
 gboolean
@@ -5474,7 +5408,8 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                 * methods) are live.
                                 */
                                if ((method->flags & METHOD_ATTRIBUTE_STATIC) ||
-                                               mini_method_get_context (method)->method_inst) {
+                                               mini_method_get_context (method)->method_inst ||
+                                               method->klass->valuetype) {
                                        mono_get_vtable_var (cfg);
                                } else {
                                        MonoInst *this, *dummy_use;
@@ -5924,7 +5859,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        float *f;
                        /* we should really allocate this only late in the compilation process */
                        mono_domain_lock (cfg->domain);
-                       f = mono_mempool_alloc (cfg->domain->mp, sizeof (float));
+                       f = mono_domain_alloc (cfg->domain, sizeof (float));
                        mono_domain_unlock (cfg->domain);
                        CHECK_OPSIZE (5);
                        CHECK_STACK_OVF (1);
@@ -5941,7 +5876,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                case CEE_LDC_R8: {
                        double *d;
                        mono_domain_lock (cfg->domain);
-                       d = mono_mempool_alloc (cfg->domain->mp, sizeof (double));
+                       d = mono_domain_alloc (cfg->domain, sizeof (double));
                        mono_domain_unlock (cfg->domain);
                        CHECK_OPSIZE (9);
                        CHECK_STACK_OVF (1);
@@ -6173,7 +6108,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        if (*ip != CEE_CALLI && check_call_signature (cfg, fsig, sp))
                                UNVERIFIED;
 
-                       if (cmethod && (cmethod->flags & METHOD_ATTRIBUTE_STATIC) &&
+                       if (cmethod && ((cmethod->flags & METHOD_ATTRIBUTE_STATIC) || cmethod->klass->valuetype) &&
                                        (cmethod->klass->generic_class || cmethod->klass->generic_container)) {
                                gboolean sharing_enabled = mono_class_generic_sharing_enabled (cmethod->klass);
                                MonoGenericContext *context = mini_class_get_context (cmethod->klass);
@@ -6228,7 +6163,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                 * should be a flag in the cfg to
                                 * request a generic sharing context.
                                 */
-                               if (context_used && method->flags & METHOD_ATTRIBUTE_STATIC)
+                               if (context_used && ((method->flags & METHOD_ATTRIBUTE_STATIC) || method->klass->valuetype))
                                        mono_get_vtable_var (cfg);
                        }
 
@@ -6496,16 +6431,11 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        else
                                no_spill = FALSE;
 
-                       /* FIXME: only do this for generic methods if
-                          they are not shared! */
-                       if (context_used &&
-                                       (cmethod->klass->valuetype ||
-                                       (cmethod->is_inflated && mono_method_get_context (cmethod)->method_inst && !pass_mrgctx) ||
-                                       ((cmethod->flags & METHOD_ATTRIBUTE_STATIC) &&
-                                               mono_class_generic_sharing_enabled (cmethod->klass)) ||
-                                       (!imt_arg && !mono_method_is_generic_sharable_impl (cmethod, TRUE) &&
-                                               (!virtual || cmethod->flags & METHOD_ATTRIBUTE_FINAL ||
-                                               !(cmethod->flags & METHOD_ATTRIBUTE_VIRTUAL))))) {
+                       if (context_used && !imt_arg &&
+                                       (!mono_method_is_generic_sharable_impl (cmethod, TRUE) ||
+                                               !mono_class_generic_sharing_enabled (cmethod->klass)) &&
+                                       (!virtual || cmethod->flags & METHOD_ATTRIBUTE_FINAL ||
+                                               !(cmethod->flags & METHOD_ATTRIBUTE_VIRTUAL))) {
                                MonoInst *rgctx;
 
                                INLINE_FAILURE;
@@ -7308,6 +7238,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        MonoMethodSignature *fsig;
                        MonoInst this_ins;
                        int temp;
+                       MonoInst *vtable_arg = NULL;
 
                        CHECK_OPSIZE (5);
                        token = read32 (ip + 1);
@@ -7332,6 +7263,41 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                ensure_method_is_allowed_to_call_method (cfg, method, cmethod, bblock, ip);
                        }
 
+                       if (cmethod->klass->valuetype && mono_class_generic_sharing_enabled (cmethod->klass) &&
+                                       mono_method_is_generic_sharable_impl (cmethod, TRUE)) {
+                               if (cmethod->is_inflated && mono_method_get_context (cmethod)->method_inst) {
+                                       if (context_used) {
+                                               MonoInst *rgctx;
+
+                                               GET_RGCTX (rgctx, context_used);
+                                               vtable_arg = get_runtime_generic_context_method_rgctx (cfg, method,
+                                                       context_used, bblock, cmethod, generic_context, rgctx, ip);
+                                       } else {
+                                               MonoVTable *vtable = mono_class_vtable (cfg->domain, cmethod->klass);
+                                               MonoMethodRuntimeGenericContext *mrgctx;
+
+                                               mrgctx = mono_method_lookup_rgctx (vtable,
+                                                       mini_method_get_context (cmethod)->method_inst);
+
+                                               NEW_PCONST (cfg, vtable_arg, mrgctx);
+                                       }
+                               } else {
+                                       if (context_used) {
+                                               MonoInst *rgctx;
+
+                                               GET_RGCTX (rgctx, context_used);
+                                               vtable_arg = get_runtime_generic_context_ptr (cfg, method, context_used,
+                                                       bblock, cmethod->klass, generic_context,
+                                                       rgctx, MONO_RGCTX_INFO_VTABLE, ip);
+                                       } else {
+                                               MonoVTable *vtable = mono_class_vtable (cfg->domain, cmethod->klass);
+
+                                               CHECK_TYPELOAD (cmethod->klass);
+                                               NEW_VTABLECONST (cfg, vtable_arg, vtable);
+                                       }
+                               }
+                       }
+
                        n = fsig->param_count;
                        CHECK_STACK (n);
  
@@ -7344,7 +7310,9 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                ((n < 2) || (!fsig->params [1]->byref && fsig->params [1]->type == MONO_TYPE_STRING))) {
                                MonoInst *iargs [3];
                                int temp;
-                               
+
+                               g_assert (!vtable_arg);
+
                                sp -= n;
 
                                NEW_ICONST (cfg, iargs [0], cmethod->klass->type_token);
@@ -7388,6 +7356,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
 
                        if (mini_class_is_system_array (cmethod->klass)) {
                                g_assert (!context_used);
+                               g_assert (!vtable_arg);
 
                                NEW_METHODCONST (cfg, *sp, cmethod);
 
@@ -7398,6 +7367,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                        temp = handle_array_new (cfg, bblock, fsig->param_count, sp, ip);
                        } else if (cmethod->string_ctor) {
                                g_assert (!context_used);
+                               g_assert (!vtable_arg);
 
                                /* we simply pass a null pointer */
                                NEW_PCONST (cfg, *sp, NULL); 
@@ -7456,7 +7426,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                if (cmethod->klass->marshalbyref)
                                        callvirt_this_arg = sp [0];
                                
-                               if ((cfg->opt & MONO_OPT_INLINE) && cmethod && !context_used &&
+                               if ((cfg->opt & MONO_OPT_INLINE) && cmethod && !context_used && !vtable_arg &&
                                    mono_method_check_inlining (cfg, cmethod) &&
                                    !mono_class_is_subclass_of (cmethod->klass, mono_defaults.exception_class, FALSE) &&
                                    !g_list_find (dont_inline, cmethod)) {
@@ -7487,8 +7457,8 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                                mono_emit_method_call_spilled (cfg, bblock, cmethod, fsig, sp, ip, callvirt_this_arg);
                                        }
                                } else if (context_used &&
-                                               (cmethod->klass->valuetype ||
-                                               !mono_method_is_generic_sharable_impl (cmethod, TRUE))) {
+                                               (!mono_method_is_generic_sharable_impl (cmethod, TRUE) ||
+                                                       !mono_class_generic_sharing_enabled (cmethod->klass))) {
                                        MonoInst *rgctx, *cmethod_addr;
 
                                        g_assert (!callvirt_this_arg);
@@ -7498,12 +7468,13 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                                        bblock, cmethod,
                                                        generic_context, rgctx, MONO_RGCTX_INFO_GENERIC_METHOD_CODE, ip);
 
-                                       mono_emit_calli_spilled (cfg, bblock, fsig, sp, cmethod_addr, ip);
+                                       mono_emit_rgctx_calli_spilled (cfg, bblock, fsig, sp, cmethod_addr, vtable_arg, ip);
                                } else {
                                        /* Prevent inlining of methods which call other methods */
                                        INLINE_FAILURE;
                                        /* now call the actual ctor */
-                                       mono_emit_method_call_spilled (cfg, bblock, cmethod, fsig, sp, ip, callvirt_this_arg);
+                                       mono_emit_rgctx_method_call_spilled (cfg, bblock, cmethod, fsig, sp,
+                                               vtable_arg, NULL, ip, callvirt_this_arg);
                                }
                        }
 
@@ -9349,7 +9320,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                MonoInst *argconst;
                                MonoMethod *cil_method, *ctor_method;
                                int temp;
-                               gboolean is_shared = FALSE;
+                               gboolean needs_static_rgctx_invoke;
 
                                CHECK_STACK_OVF (1);
                                CHECK_OPSIZE (6);
@@ -9362,15 +9333,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                if (cfg->generic_sharing_context)
                                        context_used = mono_method_check_context_used (cmethod);
 
-                               if (mono_class_generic_sharing_enabled (cmethod->klass)) {
-                                       if ((cmethod->flags & METHOD_ATTRIBUTE_STATIC) &&
-                                                       (cmethod->klass->generic_class ||
-                                                       cmethod->klass->generic_container)) {
-                                               is_shared = TRUE;
-                                       }
-                                       if (cmethod->is_inflated && mono_method_get_context (cmethod)->method_inst)
-                                               is_shared = TRUE;
-                               }
+                               needs_static_rgctx_invoke = mono_method_needs_static_rgctx_invoke (cmethod, TRUE);
 
                                cil_method = cmethod;
                                if (!dont_verify && !cfg->skip_visibility && !mono_method_can_access_method (method, cmethod))
@@ -9390,7 +9353,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                /* FIXME: SGEN support */
                                /* FIXME: handle shared static generic methods */
                                /* FIXME: handle this in shared code */
-                               if (!is_shared && !context_used && (sp > stack_start) && (ip + 6 + 5 < end) && ip_in_bb (cfg, bblock, ip + 6) && (ip [6] == CEE_NEWOBJ) && (ctor_method = mini_get_method (cfg, method, read32 (ip + 7), NULL, generic_context)) && (ctor_method->klass->parent == mono_defaults.multicastdelegate_class)) {
+                               if (!needs_static_rgctx_invoke && !context_used && (sp > stack_start) && (ip + 6 + 5 < end) && ip_in_bb (cfg, bblock, ip + 6) && (ip [6] == CEE_NEWOBJ) && (ctor_method = mini_get_method (cfg, method, read32 (ip + 7), NULL, generic_context)) && (ctor_method->klass->parent == mono_defaults.multicastdelegate_class)) {
                                        MonoInst *target_ins;
 
                                        ip += 6;
@@ -9410,14 +9373,14 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                if (context_used) {
                                        MonoInst *rgctx;
 
-                                       if (is_shared)
+                                       if (needs_static_rgctx_invoke)
                                                cmethod = mono_marshal_get_static_rgctx_invoke (cmethod);
 
                                        GET_RGCTX (rgctx, context_used);
                                        argconst = get_runtime_generic_context_method (cfg, method, context_used,
                                                        bblock, cmethod,
                                                        generic_context, rgctx, MONO_RGCTX_INFO_METHOD, ip);
-                               } else if (is_shared) {
+                               } else if (needs_static_rgctx_invoke) {
                                        NEW_METHODCONST (cfg, argconst, mono_marshal_get_static_rgctx_invoke (cmethod));
                                } else {
                                        NEW_METHODCONST (cfg, argconst, cmethod);
@@ -9699,8 +9662,10 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
 
                                for (i = 0; i < header->num_clauses; ++i) {
                                        MonoExceptionClause *clause = &header->clauses [i];
-                                       if (MONO_OFFSET_IN_HANDLER (clause, ip - header->code) && !(clause->flags & MONO_EXCEPTION_CLAUSE_FINALLY))
+                                       if (MONO_OFFSET_IN_HANDLER (clause, ip - header->code) && !(clause->flags & MONO_EXCEPTION_CLAUSE_FINALLY)) {
                                                handler_offset = clause->handler_offset;
+                                               break;
+                                       }
                                }
 
                                bblock->flags |= BB_EXCEPTION_UNSAFE;
@@ -10046,8 +10011,8 @@ create_helper_signature (void)
        helper_sig_rgctx_lazy_fetch_trampoline = mono_create_icall_signature ("ptr ptr");
 }
 
-gconstpointer
-mono_icall_get_wrapper (MonoJitICallInfo* callinfo)
+static gconstpointer
+mono_icall_get_wrapper_full (MonoJitICallInfo* callinfo, gboolean do_compile)
 {
        char *name;
        MonoMethod *wrapper;
@@ -10076,7 +10041,10 @@ mono_icall_get_wrapper (MonoJitICallInfo* callinfo)
        wrapper = mono_marshal_get_icall_wrapper (callinfo->sig, name, callinfo->func, check_for_pending_exc);
        g_free (name);
 
-       trampoline = mono_create_ftnptr (domain, mono_create_jit_trampoline_in_domain (domain, wrapper));
+       if (do_compile)
+               trampoline = mono_compile_method (wrapper);
+       else
+               trampoline = mono_create_ftnptr (domain, mono_create_jit_trampoline_in_domain (domain, wrapper));
        mono_register_jit_icall_wrapper (callinfo, trampoline);
 
        callinfo->trampoline = trampoline;
@@ -10086,12 +10054,18 @@ mono_icall_get_wrapper (MonoJitICallInfo* callinfo)
        return callinfo->trampoline;
 }
 
+gconstpointer
+mono_icall_get_wrapper (MonoJitICallInfo* callinfo)
+{
+       return mono_icall_get_wrapper_full (callinfo, FALSE);
+}
+
 static void
 mono_dynamic_code_hash_insert (MonoDomain *domain, MonoMethod *method, MonoJitDynamicMethodInfo *ji)
 {
-       if (!domain->dynamic_code_hash)
-               domain->dynamic_code_hash = g_hash_table_new (NULL, NULL);
-       g_hash_table_insert (domain->dynamic_code_hash, method, ji);
+       if (!domain_jit_info (domain)->dynamic_code_hash)
+               domain_jit_info (domain)->dynamic_code_hash = g_hash_table_new (NULL, NULL);
+       g_hash_table_insert (domain_jit_info (domain)->dynamic_code_hash, method, ji);
 }
 
 static MonoJitDynamicMethodInfo*
@@ -10099,8 +10073,8 @@ mono_dynamic_code_hash_lookup (MonoDomain *domain, MonoMethod *method)
 {
        MonoJitDynamicMethodInfo *res;
 
-       if (domain->dynamic_code_hash)
-               res = g_hash_table_lookup (domain->dynamic_code_hash, method);
+       if (domain_jit_info (domain)->dynamic_code_hash)
+               res = g_hash_table_lookup (domain_jit_info (domain)->dynamic_code_hash, method);
        else
                res = NULL;
        return res;
@@ -10128,6 +10102,8 @@ compare_by_interval_start_pos_func (gconstpointer a, gconstpointer b)
                return 1;
 }
 
+#ifndef DISABLE_JIT
+
 #if 0
 #define LSCAN_DEBUG(a) do { a; } while (0)
 #else
@@ -10613,6 +10589,17 @@ mono_allocate_stack_slots (MonoCompile *m, guint32 *stack_size, guint32 *stack_a
        return mono_allocate_stack_slots_full (m, TRUE, stack_size, stack_align);
 }
 
+#else
+
+gint32*
+mono_allocate_stack_slots_full (MonoCompile *cfg, gboolean backward, guint32 *stack_size, guint32 *stack_align)
+{
+       g_assert_not_reached ();
+       return NULL;
+}
+
+#endif /* DISABLE_JIT */
+
 void
 mono_register_opcode_emulation (int opcode, const char *name, const char *sigstr, gpointer func, gboolean no_throw)
 {
@@ -11178,7 +11165,7 @@ mono_create_tls_get (MonoCompile *cfg, int offset)
                return NULL;
        
        MONO_INST_NEW (cfg, ins, OP_TLS_GET);
-       ins->dreg = mono_regstate_next_int (cfg->rs);
+       ins->dreg = cfg->new_ir ? mono_alloc_preg (cfg) : mono_regstate_next_int (cfg->rs);
        ins->inst_offset = offset;
        return ins;
 #else
@@ -11390,7 +11377,7 @@ mono_resolve_patch_target (MonoMethod *method, MonoDomain *domain, guint8 *code,
                } else {
                        mono_domain_lock (domain);
                        if (mono_aot_only)
-                               jump_table = mono_mempool_alloc (domain->mp, sizeof (gpointer) * patch_info->data.table->table_size);
+                               jump_table = mono_domain_alloc (domain, sizeof (gpointer) * patch_info->data.table->table_size);
                        else
                                jump_table = mono_code_manager_reserve (domain->code_mp, sizeof (gpointer) * patch_info->data.table->table_size);
                        mono_domain_unlock (domain);
@@ -11712,6 +11699,8 @@ mono_print_code (MonoCompile *cfg, const char* msg)
        }
 }
 
+#ifndef DISABLE_JIT
+
 extern const char * const mono_burg_rule_string [];
 
 static void
@@ -12150,11 +12139,11 @@ mono_codegen (MonoCompile *cfg)
                        unsigned char *ip = cfg->native_code + patch_info->ip.i;
 
                        mono_domain_lock (domain);
-                       if (!domain->jump_target_hash)
-                               domain->jump_target_hash = g_hash_table_new (NULL, NULL);
-                       list = g_hash_table_lookup (domain->jump_target_hash, patch_info->data.method);
+                       if (!domain_jit_info (domain)->jump_target_hash)
+                               domain_jit_info (domain)->jump_target_hash = g_hash_table_new (NULL, NULL);
+                       list = g_hash_table_lookup (domain_jit_info (domain)->jump_target_hash, patch_info->data.method);
                        list = g_slist_prepend (list, ip);
-                       g_hash_table_insert (domain->jump_target_hash, patch_info->data.method, list);
+                       g_hash_table_insert (domain_jit_info (domain)->jump_target_hash, patch_info->data.method, list);
                        mono_domain_unlock (domain);
                        break;
                }
@@ -12334,6 +12323,9 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, gbool
                 * for this in the debugger. */
                cfg->disable_omit_fp = TRUE;
 
+               /* The debugger needs all locals to be on the stack or in a global register */
+               cfg->disable_vreg_to_lvreg = TRUE;
+
                // cfg->opt |= MONO_OPT_SHARED;
                cfg->opt &= ~MONO_OPT_INLINE;
                cfg->opt &= ~MONO_OPT_COPYPROP;
@@ -12538,8 +12530,9 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, gbool
                         * FIXME: Can't use the second case in methods with clauses, since the 
                         * bblocks inside the clauses are not processed during dfn computation.
                         */
-                       if ((header->clauses && (bbn && bbn->region == -1 && bbn->in_count == 0)) ||
-                               (!header->clauses && (bbn && bbn->region == -1 && !bbn->dfn))) {
+                       if (((header->clauses && (bbn && bbn->region == -1 && bbn->in_count == 0)) ||
+                                (!header->clauses && (bbn && bbn->region == -1 && !bbn->dfn))) &&
+                               bbn != cfg->bb_exit) {
                                if (cfg->verbose_level > 1)
                                        g_print ("found unreachable code in BB%d\n", bbn->block_num);
                                /* There may exist unreachable branches to this bb */
@@ -12863,7 +12856,7 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, gbool
        } else {
                /* we access cfg->domain->mp */
                mono_domain_lock (cfg->domain);
-               jinfo = mono_mempool_alloc0 (cfg->domain->mp, sizeof (MonoJitInfo) +
+               jinfo = mono_domain_alloc0 (cfg->domain, sizeof (MonoJitInfo) +
                                (header->num_clauses * sizeof (MonoJitExceptionInfo)) +
                                generic_info_size);
                mono_domain_unlock (cfg->domain);
@@ -12923,11 +12916,13 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, gbool
                 */
                if (cfg->rgctx_var ||
                                (!(method_to_compile->flags & METHOD_ATTRIBUTE_STATIC) &&
-                               !mini_method_get_context (method_to_compile)->method_inst)) {
+                               !mini_method_get_context (method_to_compile)->method_inst &&
+                               !method_to_compile->klass->valuetype)) {
                        gi->has_this = 1;
 
                        if ((method_to_compile->flags & METHOD_ATTRIBUTE_STATIC) ||
-                                       mini_method_get_context (method_to_compile)->method_inst) {
+                                       mini_method_get_context (method_to_compile)->method_inst ||
+                                       method_to_compile->klass->valuetype) {
                                inst = cfg->rgctx_var;
                                g_assert (inst->opcode == OP_REGOFFSET);
                        } else {
@@ -13035,6 +13030,17 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, gbool
        return cfg;
 }
 
+#else
+
+MonoCompile*
+mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, gboolean run_cctors, gboolean compile_aot, int parts)
+{
+       g_assert_not_reached ();
+       return NULL;
+}
+
+#endif /* DISABLE_JIT */
+
 static MonoJitInfo*
 lookup_generic_method (MonoDomain *domain, MonoMethod *method)
 {
@@ -13131,7 +13137,17 @@ mono_jit_compile_method_inner (MonoMethod *method, MonoDomain *target_domain, in
                        if (*name == '.' && (strcmp (name, ".ctor") == 0)) {
                                MonoJitICallInfo *mi = mono_find_jit_icall_by_name ("mono_delegate_ctor");
                                g_assert (mi);
-                               return mono_get_addr_from_ftnptr ((gpointer)mono_icall_get_wrapper (mi));
+                               /*
+                                * We need to make sure this wrapper
+                                * is compiled because it might end up
+                                * in an (M)RGCTX if generic sharing
+                                * is enabled, and would be called
+                                * indirectly.  If it were a
+                                * trampoline we'd try to patch that
+                                * indirect call, which is not
+                                * possible.
+                                */
+                               return mono_get_addr_from_ftnptr ((gpointer)mono_icall_get_wrapper_full (mi, TRUE));
                        } else if (*name == 'I' && (strcmp (name, "Invoke") == 0)) {
 #ifdef MONO_ARCH_HAVE_CREATE_DELEGATE_TRAMPOLINE
                                return mono_create_delegate_trampoline (method->klass);
@@ -13274,16 +13290,16 @@ mono_jit_compile_method_inner (MonoMethod *method, MonoDomain *target_domain, in
 
        mono_destroy_compile (cfg);
 
-       if (target_domain->jump_target_hash) {
+       if (domain_jit_info (target_domain)->jump_target_hash) {
                MonoJumpInfo patch_info;
                GSList *list, *tmp;
-               list = g_hash_table_lookup (target_domain->jump_target_hash, method);
+               list = g_hash_table_lookup (domain_jit_info (target_domain)->jump_target_hash, method);
                if (list) {
                        patch_info.next = NULL;
                        patch_info.ip.i = 0;
                        patch_info.type = MONO_PATCH_INFO_METHOD_JUMP;
                        patch_info.data.method = method;
-                       g_hash_table_remove (target_domain->jump_target_hash, method);
+                       g_hash_table_remove (domain_jit_info (target_domain)->jump_target_hash, method);
                }
                for (tmp = list; tmp; tmp = tmp->next)
                        mono_arch_patch_code (NULL, target_domain, tmp->data, &patch_info, TRUE);
@@ -13396,9 +13412,9 @@ mono_jit_free_method (MonoDomain *domain, MonoMethod *method)
        if (!ji)
                return;
        mono_domain_lock (domain);
-       g_hash_table_remove (domain->dynamic_code_hash, method);
+       g_hash_table_remove (domain_jit_info (domain)->dynamic_code_hash, method);
        mono_internal_hash_table_remove (&domain->jit_code_hash, method);
-       g_hash_table_remove (domain->jump_trampoline_hash, method);
+       g_hash_table_remove (domain_jit_info (domain)->jump_trampoline_hash, method);
        mono_domain_unlock (domain);
 
 #ifdef MONO_ARCH_HAVE_INVALIDATE_METHOD
@@ -13472,14 +13488,10 @@ mono_jit_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObjec
                return NULL;
        }
 
-       if (((method->flags & METHOD_ATTRIBUTE_STATIC) ||
-                               (method->is_inflated && mono_method_get_context (method)->method_inst)) &&
-                       mono_class_generic_sharing_enabled (method->klass) &&
-                       mono_method_is_generic_sharable_impl (method, FALSE)) {
+       if (mono_method_needs_static_rgctx_invoke (method, FALSE))
                to_compile = mono_marshal_get_static_rgctx_invoke (method);
-       } else {
+       else
                to_compile = method;
-       }
 
        invoke = mono_marshal_get_runtime_invoke (method);
        runtime_invoke = mono_jit_compile_method (invoke);
@@ -13598,30 +13610,9 @@ SIG_HANDLER_SIGNATURE (sigsegv_signal_handler)
        ji = mono_jit_info_table_find (mono_domain_get (), mono_arch_ip_from_context (ctx));
 
 #ifdef MONO_ARCH_SIGSEGV_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);
-               }
+       if (mono_handle_soft_stack_ovf (jit_tls, ji, ctx, (guint8*)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.
         */
@@ -13635,7 +13626,7 @@ SIG_HANDLER_SIGNATURE (sigsegv_signal_handler)
                else
                        method = "Unmanaged";
                fprintf (stderr, "At %s\n", method);
-               abort ();
+               _exit (1);
        } else {
                mono_arch_handle_altstack_exception (ctx, info->si_addr, FALSE);
        }
@@ -13788,8 +13779,15 @@ SIG_HANDLER_SIGNATURE (sigprof_signal_handler)
 static void
 SIG_HANDLER_SIGNATURE (sigquit_signal_handler)
 {
+       gboolean res;
+
        GET_CONTEXT;
 
+       /* We use this signal to start the attach agent too */
+       res = mono_attach_start ();
+       if (res)
+               return;
+
        printf ("Full thread dump:\n");
 
        mono_threads_request_thread_dump ();
@@ -13994,7 +13992,7 @@ mono_runtime_install_handlers (void)
 #else /* !PLATFORM_WIN32 */
 
 
-#ifdef PLATFORM_MACOSX
+#if defined(PLATFORM_MACOSX) && !defined(__arm__)
        macosx_register_exception_handler ();
 #endif
 
@@ -14259,6 +14257,11 @@ mini_create_jit_domain_info (MonoDomain *domain)
 {
        MonoJitDomainInfo *info = g_new0 (MonoJitDomainInfo, 1);
 
+       info->class_init_trampoline_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
+       info->jump_trampoline_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
+       info->jit_trampoline_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
+       info->delegate_trampoline_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
+
        domain->runtime_info = info;
 }
 
@@ -14268,16 +14271,40 @@ delete_jump_list (gpointer key, gpointer value, gpointer user_data)
        g_slist_free (value);
 }
 
+static void
+dynamic_method_info_free (gpointer key, gpointer value, gpointer user_data)
+{
+       MonoJitDynamicMethodInfo *di = value;
+       mono_code_manager_destroy (di->code_mp);
+       g_free (di);
+}
+
 static void
 mini_free_jit_domain_info (MonoDomain *domain)
 {
-       MonoJitDomainInfo *info = jit_domain_info (domain);
+       MonoJitDomainInfo *info = domain_jit_info (domain);
 
+       if (info->jump_target_hash) {
+               g_hash_table_foreach (info->jump_target_hash, delete_jump_list, NULL);
+               g_hash_table_destroy (info->jump_target_hash);
+       }
        if (info->jump_target_got_slot_hash) {
                g_hash_table_foreach (info->jump_target_got_slot_hash, delete_jump_list, NULL);
                g_hash_table_destroy (info->jump_target_got_slot_hash);
        }
+       if (info->dynamic_code_hash) {
+               g_hash_table_foreach (info->dynamic_code_hash, dynamic_method_info_free, NULL);
+               g_hash_table_destroy (info->dynamic_code_hash);
+       }
+       if (info->method_code_hash)
+               g_hash_table_destroy (info->method_code_hash);
+       g_hash_table_destroy (info->class_init_trampoline_hash);
+       g_hash_table_destroy (info->jump_trampoline_hash);
+       g_hash_table_destroy (info->jit_trampoline_hash);
+       g_hash_table_destroy (info->delegate_trampoline_hash);
+
        g_free (domain->runtime_info);
+       domain->runtime_info = NULL;
 }
 
 MonoDomain *
@@ -14321,7 +14348,9 @@ mini_init (const char *filename, const char *runtime_version)
        mono_jit_tls_id = TlsAlloc ();
        setup_jit_tls_data ((gpointer)-1, mono_thread_abort);
 
+#ifndef DISABLE_JIT
        mono_burg_init ();
+#endif
 
        if (default_opt & MONO_OPT_AOT)
                mono_aot_init ();
@@ -14578,16 +14607,22 @@ mini_init (const char *filename, const char *runtime_version)
        register_icall (mono_array_new_2, "mono_array_new_2", "object ptr int int", FALSE);
 #endif
 
+       mono_generic_sharing_init ();
+
+       if (mono_compile_aot)
+               /* 
+                * Avoid running managed code when AOT compiling, since the platform
+                * might only support aot-only execution.
+                */
+               mono_runtime_set_no_exec (TRUE);
+
 #define JIT_RUNTIME_WORKS
 #ifdef JIT_RUNTIME_WORKS
        mono_install_runtime_cleanup ((MonoDomainFunc)mini_cleanup);
        mono_runtime_init (domain, mono_thread_start_cb, mono_thread_attach_cb);
+       mono_thread_attach (domain);
 #endif
 
-       mono_generic_sharing_init ();
-
-       mono_thread_attach (domain);
-       
        mono_profiler_runtime_initialized ();
        
        MONO_PROBE_VES_INIT_END ();
@@ -14609,7 +14644,6 @@ print_jit_stats (void)
                g_print ("Basic blocks:           %ld\n", mono_jit_stats.basic_blocks);
                g_print ("Max basic blocks:       %ld\n", mono_jit_stats.max_basic_blocks);
                g_print ("Allocated vars:         %ld\n", mono_jit_stats.allocate_var);
-               g_print ("Analyze stack repeat:   %ld\n", mono_jit_stats.analyze_stack_repeat);
                g_print ("Compiled CIL code size: %ld\n", mono_jit_stats.cil_code_size);
                g_print ("Native code size:       %ld\n", mono_jit_stats.native_code_size);
                g_print ("Max code size ratio:    %.2f (%s)\n", mono_jit_stats.max_code_size_ratio/100.0,
@@ -14722,7 +14756,8 @@ mini_cleanup (MonoDomain *domain)
 
        mono_trampolines_cleanup ();
 
-       mono_code_manager_destroy (global_codeman);
+       if (!mono_dont_free_global_codeman)
+               mono_code_manager_destroy (global_codeman);
        g_hash_table_destroy (jit_icall_name_hash);
        g_free (emul_opcode_map);