Put the cas flags in MonoJitInfo into a separate structure to free up a free bits.
[mono.git] / mono / mini / mini.c
index 9aad4e2a18368ab8a0805225337e6583522d9d58..81794f7db748d0d9fcee93c4ee2e634cecaad575 100644 (file)
@@ -7,6 +7,7 @@
  *
  * Copyright 2002-2003 Ximian, Inc.
  * Copyright 2003-2010 Novell, Inc.
+ * Copyright 2011 Xamarin, Inc (http://www.xamarin.com)
  */
 
 #define MONO_LLVM_IN_MINI 1
@@ -53,6 +54,7 @@
 #include <mono/utils/mono-counters.h>
 #include <mono/utils/mono-logger-internal.h>
 #include <mono/utils/mono-mmap.h>
+#include <mono/utils/mono-tls.h>
 #include <mono/utils/dtrace.h>
 
 #include "mini.h"
@@ -75,16 +77,17 @@ static gpointer mono_jit_compile_method_with_opt (MonoMethod *method, guint32 op
 static guint32 default_opt = 0;
 static gboolean default_opt_set = FALSE;
 
-guint32 mono_jit_tls_id = -1;
+MonoNativeTlsKey mono_jit_tls_id;
 
+#ifdef MONO_HAVE_FAST_TLS
 MONO_FAST_TLS_DECLARE(mono_jit_tls);
+#endif
 
 #ifndef MONO_ARCH_MONITOR_ENTER_ADJUSTMENT
 #define MONO_ARCH_MONITOR_ENTER_ADJUSTMENT 1
 #endif
 
 MonoTraceSpec *mono_jit_trace_calls = NULL;
-gboolean mono_break_on_exc = FALSE;
 gboolean mono_compile_aot = FALSE;
 /* If this is set, no code is generated dynamically, everything is taken from AOT files */
 gboolean mono_aot_only = FALSE;
@@ -290,7 +293,10 @@ get_method_from_ip (void *ip)
        MonoDomain *domain = mono_domain_get ();
        MonoDebugSourceLocation *location;
        FindTrampUserData user_data;
-       
+
+       if (!domain)
+               domain = mono_get_root_domain ();
+
        ji = mono_jit_info_table_find (domain, ip);
        if (!ji) {
                user_data.ip = ip;
@@ -2458,7 +2464,7 @@ MONO_FAST_TLS_DECLARE(mono_lmf);
 #endif
 #endif
 
-guint32
+MonoNativeTlsKey
 mono_get_jit_tls_key (void)
 {
        return mono_jit_tls_id;
@@ -2500,7 +2506,7 @@ mono_get_lmf (void)
 #else
        MonoJitTlsData *jit_tls;
 
-       if ((jit_tls = TlsGetValue (mono_jit_tls_id)))
+       if ((jit_tls = mono_native_tls_get_value (mono_jit_tls_id)))
                return jit_tls->lmf;
        /*
         * We do not assert here because this function can be called from
@@ -2519,7 +2525,7 @@ mono_get_lmf_addr (void)
 #else
        MonoJitTlsData *jit_tls;
 
-       if ((jit_tls = TlsGetValue (mono_jit_tls_id)))
+       if ((jit_tls = mono_native_tls_get_value (mono_jit_tls_id)))
                return &jit_tls->lmf;
 
        /*
@@ -2532,7 +2538,7 @@ mono_get_lmf_addr (void)
 
        mono_jit_thread_attach (NULL);
        
-       if ((jit_tls = TlsGetValue (mono_jit_tls_id)))
+       if ((jit_tls = mono_native_tls_get_value (mono_jit_tls_id)))
                return &jit_tls->lmf;
 
        g_assert_not_reached ();
@@ -2553,7 +2559,7 @@ mono_set_lmf (MonoLMF *lmf)
 static void
 mono_set_jit_tls (MonoJitTlsData *jit_tls)
 {
-       TlsSetValue (mono_jit_tls_id, jit_tls);
+       mono_native_tls_set_value (mono_jit_tls_id, jit_tls);
 
 #ifdef MONO_HAVE_FAST_TLS
        MONO_FAST_TLS_SET (mono_jit_tls, jit_tls);
@@ -2568,10 +2574,17 @@ mono_set_lmf_addr (gpointer lmf_addr)
 #endif
 }
 
-/* Called by native->managed wrappers */
-void
+/*
+ * mono_jit_thread_attach:
+ *
+ * Called by native->managed wrappers. Returns the original domain which needs to be
+ * restored, or NULL.
+ */
+MonoDomain*
 mono_jit_thread_attach (MonoDomain *domain)
 {
+       MonoDomain *orig;
+
        if (!domain)
                /* 
                 * Happens when called from AOTed code which is only used in the root
@@ -2586,15 +2599,26 @@ mono_jit_thread_attach (MonoDomain *domain)
                mono_thread_set_state (mono_thread_internal_current (), ThreadState_Background);
        }
 #else
-       if (!TlsGetValue (mono_jit_tls_id)) {
+       if (!mono_native_tls_get_value (mono_jit_tls_id)) {
                mono_thread_attach (domain);
                mono_thread_set_state (mono_thread_internal_current (), ThreadState_Background);
        }
 #endif
-       if (mono_domain_get () != domain)
-               mono_domain_set (domain, TRUE);
+       orig = mono_domain_get ();
+       if (orig != domain)
+               mono_domain_set (domain, TRUE);
+
+       return orig != domain ? orig : NULL;
 }      
 
+/* Called by native->managed wrappers */
+void
+mono_jit_set_domain (MonoDomain *domain)
+{
+       if (domain)
+               mono_domain_set (domain, TRUE);
+}
+
 /**
  * mono_thread_abort:
  * @obj: exception object
@@ -2604,7 +2628,7 @@ mono_jit_thread_attach (MonoDomain *domain)
 static void
 mono_thread_abort (MonoObject *obj)
 {
-       /* MonoJitTlsData *jit_tls = TlsGetValue (mono_jit_tls_id); */
+       /* MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id); */
        
        /* handle_remove should be eventually called for this thread, too
        g_free (jit_tls);*/
@@ -2613,6 +2637,15 @@ mono_thread_abort (MonoObject *obj)
                        (obj->vtable->klass == mono_defaults.threadabortexception_class)) {
                mono_thread_exit ();
        } else {
+               MonoObject *other = NULL;
+               MonoString *str = mono_object_to_string (obj, &other);
+               if (str) {
+                       char *msg = mono_string_to_utf8 (str);
+                       fprintf (stderr, "[ERROR] FATAL UNHANDLED EXCEPTION: %s\n", msg);
+                       fflush (stderr);
+                       g_free (msg);
+               }
+
                exit (mono_environment_exitcode_get ());
        }
 }
@@ -2623,7 +2656,7 @@ setup_jit_tls_data (gpointer stack_start, gpointer abort_func)
        MonoJitTlsData *jit_tls;
        MonoLMF *lmf;
 
-       jit_tls = TlsGetValue (mono_jit_tls_id);
+       jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
        if (jit_tls)
                return jit_tls;
 
@@ -2642,14 +2675,13 @@ setup_jit_tls_data (gpointer stack_start, gpointer abort_func)
 #if defined(MONO_HAVE_FAST_TLS) && defined(MONO_ARCH_ENABLE_MONO_LMF_VAR)
        /* jit_tls->lmf is unused */
        MONO_FAST_TLS_SET (mono_lmf, lmf);
-       mono_set_lmf_addr (&mono_lmf);
+       mono_set_lmf_addr (MONO_FAST_TLS_ADDR (mono_lmf));
 #else
        mono_set_lmf_addr (&jit_tls->lmf);
 
        jit_tls->lmf = lmf;
 #endif
 
-       mono_arch_setup_jit_tls_data (jit_tls);
        mono_setup_altstack (jit_tls);
 
        return jit_tls;
@@ -2718,9 +2750,12 @@ mini_thread_cleanup (MonoInternalThread *thread)
                 *
                 * The current offender is mono_thread_manage which cleanup threads from the outside.
                 */
-               if (thread == mono_thread_internal_current ()) {
-                       mono_set_lmf (NULL);
+               if (thread == mono_thread_internal_current ())
                        mono_set_jit_tls (NULL);
+
+               /* If we attach a thread but never call into managed land, we might never get an lmf.*/
+               if (mono_get_lmf ()) {
+                       mono_set_lmf (NULL);
                        mono_set_lmf_addr (NULL);
                }
 
@@ -2767,6 +2802,12 @@ mono_get_thread_intrinsic (MonoCompile* cfg)
        return mono_create_tls_get (cfg, mono_thread_get_tls_offset ());
 }
 
+MonoInst*
+mono_get_lmf_intrinsic (MonoCompile* cfg)
+{
+       return mono_create_tls_get (cfg, mono_get_lmf_tls_offset ());
+}
+
 void
 mono_add_patch_info (MonoCompile *cfg, int ip, MonoJumpInfoType type, gconstpointer target)
 {
@@ -2982,7 +3023,7 @@ mono_resolve_patch_target (MonoMethod *method, MonoDomain *domain, guint8 *code,
                        target = code;
                } else {
                        /* get the trampoline to the method from the domain */
-                       target = mono_create_jit_trampoline (patch_info->data.method);
+                       target = mono_create_jit_trampoline_in_domain (domain, patch_info->data.method);
                }
                break;
        case MONO_PATCH_INFO_SWITCH: {
@@ -3030,6 +3071,7 @@ mono_resolve_patch_target (MonoMethod *method, MonoDomain *domain, guint8 *code,
        case MONO_PATCH_INFO_CLASS:
        case MONO_PATCH_INFO_IMAGE:
        case MONO_PATCH_INFO_FIELD:
+       case MONO_PATCH_INFO_SIGNATURE:
                target = patch_info->data.target;
                break;
        case MONO_PATCH_INFO_IID:
@@ -3052,7 +3094,7 @@ mono_resolve_patch_target (MonoMethod *method, MonoDomain *domain, guint8 *code,
                break;
        }
        case MONO_PATCH_INFO_DELEGATE_TRAMPOLINE:
-               target = mono_create_delegate_trampoline (patch_info->data.klass);
+               target = mono_create_delegate_trampoline (domain, patch_info->data.klass);
                break;
        case MONO_PATCH_INFO_SFLDA: {
                MonoVTable *vtable = mono_class_vtable (domain, patch_info->data.field->parent);
@@ -3076,7 +3118,7 @@ mono_resolve_patch_target (MonoMethod *method, MonoDomain *domain, guint8 *code,
                        if (run_cctors)
                                mono_runtime_class_init (vtable);
                }
-               target = (char*)vtable->data + patch_info->data.field->offset;
+               target = (char*)mono_vtable_get_static_field_data (vtable) + patch_info->data.field->offset;
                break;
        }
        case MONO_PATCH_INFO_RVA: {
@@ -3129,10 +3171,16 @@ mono_resolve_patch_target (MonoMethod *method, MonoDomain *domain, guint8 *code,
        case MONO_PATCH_INFO_ICALL_ADDR:
                /* run_cctors == 0 -> AOT */
                if (patch_info->data.method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
+                       const char *exc_class;
+                       const char *exc_arg;
+
                        if (run_cctors) {
-                               target = mono_lookup_pinvoke_call (patch_info->data.method, NULL, NULL);
-                               if (!target)
+                               target = mono_lookup_pinvoke_call (patch_info->data.method, &exc_class, &exc_arg);
+                               if (!target) {
+                                       if (mono_aot_only)
+                                               mono_raise_exception (mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg));
                                        g_error ("Unable to resolve pinvoke method '%s' Re-run with MONO_LOG_LEVEL=debug for more information.\n", mono_method_full_name (patch_info->data.method, TRUE));
+                               }
                        } else {
                                target = NULL;
                        }
@@ -3243,6 +3291,26 @@ mono_add_seq_point (MonoCompile *cfg, MonoBasicBlock *bb, MonoInst *ins, int nat
        bb->last_seq_point = ins;
 }
 
+void
+mono_add_var_location (MonoCompile *cfg, MonoInst *var, gboolean is_reg, int reg, int offset, int from, int to)
+{
+       MonoDwarfLocListEntry *entry = mono_mempool_alloc0 (cfg->mempool, sizeof (MonoDwarfLocListEntry));
+
+       if (is_reg)
+               g_assert (offset == 0);
+
+       entry->is_reg = is_reg;
+       entry->reg = reg;
+       entry->offset = offset;
+       entry->from = from;
+       entry->to = to;
+
+       if (var == cfg->args [0])
+               cfg->this_loclist = g_slist_append_mempool (cfg->mempool, cfg->this_loclist, entry);
+       else if (var == cfg->rgctx_var)
+               cfg->rgctx_loclist = g_slist_append_mempool (cfg->mempool, cfg->rgctx_loclist, entry);
+}
+
 #ifndef DISABLE_JIT
 
 static void
@@ -3431,12 +3499,21 @@ collect_pred_seq_points (MonoBasicBlock *bb, MonoInst *ins, GSList **next, int d
 {
        int i;
        MonoBasicBlock *in_bb;
+       GSList *l;
 
        for (i = 0; i < bb->in_count; ++i) {
                in_bb = bb->in_bb [i];
 
                if (in_bb->last_seq_point) {
-                       next [in_bb->last_seq_point->backend.size] = g_slist_append (next [in_bb->last_seq_point->backend.size], GUINT_TO_POINTER (ins->backend.size));
+                       int src_index = in_bb->last_seq_point->backend.size;
+                       int dst_index = ins->backend.size;
+
+                       /* bb->in_bb might contain duplicates */
+                       for (l = next [src_index]; l; l = l->next)
+                               if (GPOINTER_TO_UINT (l->data) == dst_index)
+                                       break;
+                       if (!l)
+                               next [src_index] = g_slist_append (next [src_index], GUINT_TO_POINTER (dst_index));
                } else {
                        /* Have to look at its predecessors */
                        if (depth < 5)
@@ -3483,7 +3560,8 @@ mono_save_seq_point_info (MonoCompile *cfg)
                for (l = bb_seq_points; l; l = l->next) {
                        MonoInst *ins = l->data;
 
-                       if (!(ins->flags & MONO_INST_SINGLE_STEP_LOC))
+                       if (ins->inst_imm == METHOD_ENTRY_IL_OFFSET || ins->inst_imm == METHOD_EXIT_IL_OFFSET)
+                               /* Used to implement method entry/exit events */
                                continue;
 
                        if (last != NULL) {
@@ -3496,6 +3574,29 @@ mono_save_seq_point_info (MonoCompile *cfg)
 
                        last = ins;
                }
+
+               if (bb->last_ins && bb->last_ins->opcode == OP_ENDFINALLY) {
+                       MonoBasicBlock *bb2;
+                       MonoInst *endfinally_seq_point = NULL;
+
+                       /*
+                        * The ENDFINALLY branches are not represented in the cfg, so link it with all seq points starting bbs.
+                        */
+                       l = g_slist_last (bb->seq_points);
+                       g_assert (l);
+                       endfinally_seq_point = l->data;
+
+                       for (bb2 = cfg->bb_entry; bb2; bb2 = bb2->next_bb) {
+                               GSList *l = g_slist_last (bb2->seq_points);
+
+                               if (l) {
+                                       MonoInst *ins = l->data;
+
+                                       if (!(ins->inst_imm == METHOD_ENTRY_IL_OFFSET || ins->inst_imm == METHOD_EXIT_IL_OFFSET) && ins != endfinally_seq_point)
+                                               next [endfinally_seq_point->backend.size] = g_slist_append (next [endfinally_seq_point->backend.size], GUINT_TO_POINTER (ins->backend.size));
+                               }
+                       }
+               }
        }
 
        if (cfg->verbose_level > 2) {
@@ -3511,10 +3612,10 @@ mono_save_seq_point_info (MonoCompile *cfg)
                sp->next = g_new (int, sp->next_len);
                j = 0;
                if (cfg->verbose_level > 2 && next [i]) {
-                       printf ("\t0x%x ->", sp->il_offset);
+                       printf ("\tIL0x%x ->", sp->il_offset);
                        for (l = next [i]; l; l = l->next) {
                                next_index = GPOINTER_TO_UINT (l->data);
-                               printf (" 0x%x", info->seq_points [next_index].il_offset);
+                               printf (" IL0x%x", info->seq_points [next_index].il_offset);
                        }
                        printf ("\n");
                }
@@ -3627,8 +3728,6 @@ mono_codegen (MonoCompile *cfg)
 
        max_epilog_size = 0;
 
-       code = cfg->native_code + cfg->code_len;
-
        /* we always allocate code in cfg->domain->code_mp to increase locality */
        cfg->code_size = cfg->code_len + max_epilog_size;
        /* fixme: align to MONO_ARCH_CODE_ALIGNMENT */
@@ -3661,6 +3760,7 @@ mono_codegen (MonoCompile *cfg)
        nacl_allow_target_modification (TRUE);
 #endif
 
+       g_assert (code);
        memcpy (code, cfg->native_code, cfg->code_len);
 #if defined(__default_codegen__)
        g_free (cfg->native_code);
@@ -3782,8 +3882,9 @@ create_jit_info (MonoCompile *cfg, MonoMethod *method_to_compile)
        MonoMethodHeader *header;
        MonoJitInfo *jinfo;
        int num_clauses;
-       int generic_info_size;
-       int holes_size = 0, num_holes = 0;
+       int generic_info_size, arch_eh_info_size = 0;
+       int holes_size = 0, num_holes = 0, cas_size = 0;
+       guint32 stack_size = 0;
 
        g_assert (method_to_compile == cfg->method);
        header = cfg->header;
@@ -3793,6 +3894,21 @@ create_jit_info (MonoCompile *cfg, MonoMethod *method_to_compile)
        else
                generic_info_size = 0;
 
+       if (cfg->arch_eh_jit_info) {
+               MonoJitArgumentInfo *arg_info;
+               MonoMethodSignature *sig = mono_method_signature (cfg->method_to_register);
+
+               /*
+                * This cannot be computed during stack walking, as
+                * mono_arch_get_argument_info () is not signal safe.
+                */
+               arg_info = g_newa (MonoJitArgumentInfo, sig->param_count + 1);
+               stack_size = mono_arch_get_argument_info (sig, sig->param_count, arg_info);
+
+               if (stack_size)
+                       arch_eh_info_size = sizeof (MonoArchEHJitInfo);
+       }
+               
        if (cfg->try_block_holes) {
                for (tmp = cfg->try_block_holes; tmp; tmp = tmp->next) {
                        TryBlockHole *hole = tmp->data;
@@ -3811,6 +3927,10 @@ create_jit_info (MonoCompile *cfg, MonoMethod *method_to_compile)
                        printf ("Number of try block holes %d\n", num_holes);
        }
 
+       if (mono_method_has_declsec (cfg->method_to_register)) {
+               cas_size = sizeof (MonoMethodCasInfo);
+       }
+
        if (COMPILE_LLVM (cfg))
                num_clauses = cfg->llvm_ex_info_len;
        else
@@ -3818,11 +3938,11 @@ create_jit_info (MonoCompile *cfg, MonoMethod *method_to_compile)
 
        if (cfg->method->dynamic) {
                jinfo = g_malloc0 (MONO_SIZEOF_JIT_INFO + (num_clauses * sizeof (MonoJitExceptionInfo)) +
-                               generic_info_size + holes_size);
+                               generic_info_size + holes_size + arch_eh_info_size + cas_size);
        } else {
                jinfo = mono_domain_alloc0 (cfg->domain, MONO_SIZEOF_JIT_INFO +
                                (num_clauses * sizeof (MonoJitExceptionInfo)) +
-                               generic_info_size + holes_size);
+                               generic_info_size + holes_size + arch_eh_info_size + cas_size);
        }
 
        jinfo->method = cfg->method_to_register;
@@ -3830,14 +3950,15 @@ create_jit_info (MonoCompile *cfg, MonoMethod *method_to_compile)
        jinfo->code_size = cfg->code_len;
        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->num_clauses = num_clauses;
+
        if (COMPILE_LLVM (cfg))
                jinfo->from_llvm = TRUE;
 
        if (cfg->generic_sharing_context) {
                MonoInst *inst;
                MonoGenericJitInfo *gi;
+               GSList *loclist = NULL;
 
                jinfo->has_generic_jit_info = 1;
 
@@ -3860,8 +3981,27 @@ create_jit_info (MonoCompile *cfg, MonoMethod *method_to_compile)
                        inst = cfg->rgctx_var;
                        if (!COMPILE_LLVM (cfg))
                                g_assert (inst->opcode == OP_REGOFFSET);
+                       loclist = cfg->rgctx_loclist;
                } else {
                        inst = cfg->args [0];
+                       loclist = cfg->this_loclist;
+               }
+
+               if (loclist) {
+                       /* Needed to handle async exceptions */
+                       GSList *l;
+                       int i;
+
+                       gi->nlocs = g_slist_length (loclist);
+                       if (cfg->method->dynamic)
+                               gi->locations = g_malloc0 (gi->nlocs * sizeof (MonoDwarfLocListEntry));
+                       else
+                               gi->locations = mono_domain_alloc0 (cfg->domain, gi->nlocs * sizeof (MonoDwarfLocListEntry));
+                       i = 0;
+                       for (l = loclist; l; l = l->next) {
+                               memcpy (&(gi->locations [i]), l->data, sizeof (MonoDwarfLocListEntry));
+                               i ++;
+                       }
                }
 
                if (COMPILE_LLVM (cfg)) {
@@ -3920,6 +4060,19 @@ create_jit_info (MonoCompile *cfg, MonoMethod *method_to_compile)
                g_assert (i == num_holes);
        }
 
+       if (arch_eh_info_size) {
+               MonoArchEHJitInfo *info;
+
+               jinfo->has_arch_eh_info = 1;
+               info = mono_jit_info_get_arch_eh_info (jinfo);
+
+               info->stack_size = stack_size;
+       }
+
+       if (cas_size) {
+               jinfo->has_cas_info = 1;
+       }
+
        if (COMPILE_LLVM (cfg)) {
                if (num_clauses)
                        memcpy (&jinfo->clauses [0], &cfg->llvm_ex_info [0], num_clauses * sizeof (MonoJitExceptionInfo));
@@ -4271,7 +4424,8 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, gbool
 
                /* Temporarily disable this when running in the debugger until we have support
                 * for this in the debugger. */
-               cfg->disable_omit_fp = TRUE;
+               /* This is no longer needed with sdb */
+               //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;
@@ -4285,7 +4439,8 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, gbool
                cfg->opt &= ~MONO_OPT_INLINE;
                cfg->opt &= ~MONO_OPT_COPYPROP;
                cfg->opt &= ~MONO_OPT_CONSPROP;
-               cfg->opt &= ~MONO_OPT_GSHARED;
+               /* This is no longer needed with sdb */
+               //cfg->opt &= ~MONO_OPT_GSHARED;
 
                /* This is needed for the soft debugger, which doesn't like code after the epilog */
                cfg->disable_out_of_line_bblocks = TRUE;
@@ -5091,7 +5246,7 @@ mono_jit_compile_method_inner (MonoMethod *method, MonoDomain *target_domain, in
                                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);
+                               return mono_create_delegate_trampoline (target_domain, method->klass);
 #else
                                nm = mono_marshal_get_delegate_invoke (method, NULL);
                                return mono_get_addr_from_ftnptr (mono_compile_method (nm));
@@ -5341,11 +5496,26 @@ mono_jit_compile_method_with_opt (MonoMethod *method, guint32 opt, MonoException
                opt |= MONO_OPT_SHARED;
        }
 
+       if (method->dynamic)
+               opt &= ~MONO_OPT_SHARED;
+
+       /* These methods can become invalid when a domain is unloaded */
+       if (method->klass->image != mono_get_corlib () || method->is_inflated)
+               opt &= ~MONO_OPT_SHARED;
+
        if (opt & MONO_OPT_SHARED)
                target_domain = mono_get_root_domain ();
        else 
                target_domain = domain;
 
+       if (method->wrapper_type == MONO_WRAPPER_UNKNOWN) {
+               WrapperInfo *info = mono_marshal_get_wrapper_info (method);
+
+               g_assert (info);
+               if (info->subtype == WRAPPER_SUBTYPE_SYNCHRONIZED_INNER)
+                       method = info->d.synchronized_inner.method;
+       }
+
        info = lookup_method (target_domain, method);
        if (info) {
                /* We can't use a domain specific method in another domain */
@@ -5372,6 +5542,8 @@ mono_jit_compile_method_with_opt (MonoMethod *method, guint32 opt, MonoException
        p = mono_create_ftnptr (target_domain, code);
 
        if (callinfo) {
+               /*mono_register_jit_icall_wrapper takes the loader lock, so we take it on the outside. */
+               mono_loader_lock ();
                mono_jit_lock ();
                if (!callinfo->wrapper) {
                        callinfo->wrapper = p;
@@ -5379,6 +5551,7 @@ mono_jit_compile_method_with_opt (MonoMethod *method, guint32 opt, MonoException
                        mono_debug_add_icall_wrapper (method, callinfo);
                }
                mono_jit_unlock ();
+               mono_loader_unlock ();
        }
 
        return p;
@@ -5431,6 +5604,8 @@ mono_jit_free_method (MonoDomain *domain, MonoMethod *method)
        if (!ji)
                return;
 
+       mono_debug_remove_method (method, domain);
+
        mono_domain_lock (domain);
        g_hash_table_remove (domain_jit_info (domain)->dynamic_code_hash, method);
        mono_internal_hash_table_remove (&domain->jit_code_hash, method);
@@ -5785,7 +5960,7 @@ SIG_HANDLER_SIGNATURE (mono_sigfpe_signal_handler)
                mono_handle_native_sigsegv (SIGSEGV, ctx);
        }
        
-       mono_arch_handle_exception (ctx, exc, FALSE);
+       mono_arch_handle_exception (ctx, exc);
 }
 
 void
@@ -5796,7 +5971,7 @@ SIG_HANDLER_SIGNATURE (mono_sigill_signal_handler)
 
        exc = mono_get_exception_execution_engine ("SIGILL");
        
-       mono_arch_handle_exception (ctx, exc, FALSE);
+       mono_arch_handle_exception (ctx, exc);
 }
 
 #if defined(MONO_ARCH_USE_SIGACTION) || defined(HOST_WIN32)
@@ -5807,7 +5982,7 @@ void
 SIG_HANDLER_SIGNATURE (mono_sigsegv_signal_handler)
 {
        MonoJitInfo *ji;
-       MonoJitTlsData *jit_tls = TlsGetValue (mono_jit_tls_id);
+       MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
        gpointer fault_addr = NULL;
 
        GET_CONTEXT;
@@ -5879,7 +6054,7 @@ SIG_HANDLER_SIGNATURE (mono_sigsegv_signal_handler)
                mono_handle_native_sigsegv (SIGSEGV, ctx);
        }
                        
-       mono_arch_handle_exception (ctx, NULL, FALSE);
+       mono_arch_handle_exception (ctx, NULL);
 #endif
 }
 
@@ -5891,7 +6066,7 @@ SIG_HANDLER_SIGNATURE (mono_sigint_signal_handler)
 
        exc = mono_get_exception_execution_engine ("Interrupted (SIGINT).");
        
-       mono_arch_handle_exception (ctx, exc, FALSE);
+       mono_arch_handle_exception (ctx, exc);
 }
 
 /* mono_jit_create_remoting_trampoline:
@@ -6029,16 +6204,20 @@ mini_get_debug_options (void)
 static gpointer
 mini_create_ftnptr (MonoDomain *domain, gpointer addr)
 {
-#ifdef __ia64__
-       gpointer *desc;
+#if !defined(__ia64__) && !defined(__ppc64__) && !defined(__powerpc64__)
+       return addr;
+#else
+
+       gpointer* desc = NULL;
 
+       if ((desc = g_hash_table_lookup (domain->ftnptrs_hash, addr)))
+               return desc;
+#      ifdef __ia64__
        desc = mono_domain_code_reserve (domain, 2 * sizeof (gpointer));
 
        desc [0] = addr;
        desc [1] = NULL;
-
-       return desc;
-#elif defined(__ppc64__) || defined(__powerpc64__)
+#      elif defined(__ppc64__) || defined(__powerpc64__)
        gpointer *desc;
 
        desc = mono_domain_alloc0 (domain, 3 * sizeof (gpointer));
@@ -6046,10 +6225,9 @@ mini_create_ftnptr (MonoDomain *domain, gpointer addr)
        desc [0] = addr;
        desc [1] = NULL;
        desc [2] = NULL;
-
+#      endif
+       g_hash_table_insert (domain->ftnptrs_hash, addr, desc);
        return desc;
-#else
-       return addr;
 #endif
 }
 
@@ -6217,6 +6395,8 @@ mini_init (const char *filename, const char *runtime_version)
        callbacks.get_addr_from_ftnptr = mini_get_addr_from_ftnptr;
        callbacks.get_runtime_build_info = mono_get_runtime_build_info;
        callbacks.set_cast_details = mono_set_cast_details;
+       callbacks.debug_log = mono_debugger_agent_debug_log;
+       callbacks.debug_log_is_enabled = mono_debugger_agent_debug_log_is_enabled;
 
 #ifdef MONO_ARCH_HAVE_IMT
        if (mono_use_imt) {
@@ -6272,7 +6452,7 @@ mini_init (const char *filename, const char *runtime_version)
        if (!g_thread_supported ())
                g_thread_init (NULL);
 
-       mono_jit_tls_id = TlsAlloc ();
+       mono_native_tls_alloc (&mono_jit_tls_id, NULL);
        setup_jit_tls_data ((gpointer)-1, mono_thread_abort);
 
        if (default_opt & MONO_OPT_AOT)
@@ -6330,6 +6510,7 @@ mini_init (const char *filename, const char *runtime_version)
        if (mono_aot_only) {
                /* This helps catch code allocation requests */
                mono_code_manager_set_read_only (domain->code_mp);
+               mono_marshal_use_aot_wrappers (TRUE);
        }
 
 #ifdef MONO_ARCH_HAVE_IMT
@@ -6340,6 +6521,9 @@ mini_init (const char *filename, const char *runtime_version)
                        mono_install_imt_thunk_builder (mono_arch_build_imt_thunk);
        }
 #endif
+       /*Init arch tls information only after the metadata side is inited to make sure we see dynamic appdomain tls keys*/
+       mono_arch_finish_init ();
+       
 
        /* This must come after mono_init () in the aot-only case */
        mono_exceptions_init ();
@@ -6377,7 +6561,8 @@ mini_init (const char *filename, const char *runtime_version)
        register_icall (mono_trace_enter_method, "mono_trace_enter_method", NULL, TRUE);
        register_icall (mono_trace_leave_method, "mono_trace_leave_method", NULL, TRUE);
        register_icall (mono_get_lmf_addr, "mono_get_lmf_addr", "ptr", TRUE);
-       register_icall (mono_jit_thread_attach, "mono_jit_thread_attach", "void", TRUE);
+       register_icall (mono_jit_thread_attach, "mono_jit_thread_attach", "ptr ptr", TRUE);
+       register_icall (mono_jit_set_domain, "mono_jit_set_domain", "void ptr", TRUE);
        register_icall (mono_domain_get, "mono_domain_get", "ptr", TRUE);
 
        register_icall (mono_get_throw_exception (), "mono_arch_throw_exception", "void object", TRUE);
@@ -6549,6 +6734,8 @@ mini_init (const char *filename, const char *runtime_version)
        register_icall (mono_object_castclass_with_cache, "mono_object_castclass_with_cache", "object object ptr ptr", FALSE);
        register_icall (mono_object_isinst_with_cache, "mono_object_isinst_with_cache", "object object ptr ptr", FALSE);
 
+       register_icall (mono_debugger_agent_user_break, "mono_debugger_agent_user_break", "void", FALSE);
+
 #endif
 
        mono_generic_sharing_init ();
@@ -6679,7 +6866,7 @@ mini_cleanup (MonoDomain *domain)
        mono_runtime_cleanup (domain);
 #endif
 
-       free_jit_tls_data (TlsGetValue (mono_jit_tls_id));
+       free_jit_tls_data (mono_native_tls_get_value (mono_jit_tls_id));
 
        mono_icall_cleanup ();
 
@@ -6720,7 +6907,7 @@ mini_cleanup (MonoDomain *domain)
        if (mono_inject_async_exc_method)
                mono_method_desc_free (mono_inject_async_exc_method);
 
-       TlsFree(mono_jit_tls_id);
+       mono_native_tls_free (mono_jit_tls_id);
 
        DeleteCriticalSection (&jit_mutex);
 
@@ -6741,11 +6928,25 @@ mono_disable_optimizations (guint32 opts)
        default_opt &= ~opts;
 }
 
-/*
+void
+mono_set_optimizations (guint32 opts)
+{
+       default_opt = opts;
+       default_opt_set = TRUE;
+}
+
+void
+mono_set_verbose_level (guint32 level)
+{
+       mini_verbose = level;
+}
+
+/**
  * mono_get_runtime_build_info:
  *
- *   Return the runtime version + build date in string format.
- * The returned string is owned by the caller.
+ * Return the runtime version + build date in string format.
+ * The returned string is owned by the caller. The returned string
+ * format is "VERSION (FULL_VERSION BUILD_DATE)" and build date is optional.
  */
 char*
 mono_get_runtime_build_info (void)