Call mono_create_jit_trampoline_in_domain () in mono_resolve_patch_target () so share...
[mono.git] / mono / mini / mini.c
index 19aa735e0acaa8a361d33caf302bf90ba535a827..f5e831d770e0aaa1087fc372353265ec0b8e1a2d 100644 (file)
@@ -6,7 +6,8 @@
  *   Dietmar Maurer (dietmar@ximian.com)
  *
  * Copyright 2002-2003 Ximian, Inc.
- * Coprygith 2003-2010 Novell, 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"
 #include "mini-gc.h"
 #include "debugger-agent.h"
 
-#if defined(HAVE_KW_THREAD)
-#define MINI_FAST_TLS_SET(x,y) x = y
-#define MINI_FAST_TLS_GET(x) x
-#define MINI_FAST_TLS_INIT(x)
-#define MINI_FAST_TLS_DECLARE(x) static __thread gpointer x MONO_TLS_FAST;
-#define MINI_HAVE_FAST_TLS
-#define MINI_THREAD_VAR_OFFSET(x,y) MONO_THREAD_VAR_OFFSET(x,y)
-#elif (defined(__APPLE__) && defined(__i386__))
-#define MINI_FAST_TLS_SET(x,y) pthread_setspecific(x, y)
-#define MINI_FAST_TLS_GET(x) pthread_getspecific(x)
-#define MINI_FAST_TLS_INIT(x) pthread_key_create(&x, NULL)
-#define MINI_FAST_TLS_DECLARE(x) static pthread_key_t x;
-#define MINI_HAVE_FAST_TLS
-#define MINI_THREAD_VAR_OFFSET(x,y) y = (gint32) x
-#else
-#define MINI_THREAD_VAR_OFFSET(x,y) MONO_THREAD_VAR_OFFSET(x,y)
-#endif
-
 static gpointer mono_jit_compile_method_with_opt (MonoMethod *method, guint32 opt, MonoException **ex);
 
-#ifdef __native_client_codegen__
-/* Default alignment for Native Client is 32-byte. */
-guint8 nacl_align_byte = 0xe0;
-#endif
 
 static guint32 default_opt = 0;
 static gboolean default_opt_set = FALSE;
 
-guint32 mono_jit_tls_id = -1;
+MonoNativeTlsKey mono_jit_tls_id;
 
-#ifdef MINI_HAVE_FAST_TLS
-MINI_FAST_TLS_DECLARE(mono_jit_tls);
+#ifdef MONO_HAVE_FAST_TLS
+MONO_FAST_TLS_DECLARE(mono_jit_tls);
 #endif
 
 #ifndef MONO_ARCH_MONITOR_ENTER_ADJUSTMENT
@@ -108,7 +88,6 @@ MINI_FAST_TLS_DECLARE(mono_jit_tls);
 #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;
@@ -164,6 +143,38 @@ gboolean disable_vtypes_in_regs = FALSE;
 
 gboolean mono_dont_free_global_codeman;
 
+gpointer
+mono_realloc_native_code (MonoCompile *cfg)
+{
+#if defined(__default_codegen__)
+       return g_realloc (cfg->native_code, cfg->code_size);
+#elif defined(__native_client_codegen__)
+       guint old_padding;
+       gpointer native_code;
+       guint alignment_check;
+
+       /* Save the old alignment offset so we can re-align after the realloc. */
+       old_padding = (guint)(cfg->native_code - cfg->native_code_alloc);
+
+       cfg->native_code_alloc = g_realloc ( cfg->native_code_alloc,
+                                                                                cfg->code_size + kNaClAlignment );
+
+       /* Align native_code to next nearest kNaClAlignment byte. */
+       native_code = (guint)cfg->native_code_alloc + kNaClAlignment;
+       native_code = (guint)native_code & ~kNaClAlignmentMask;
+
+       /* Shift the data to be 32-byte aligned again. */
+       memmove (native_code, cfg->native_code_alloc + old_padding, cfg->code_size);
+
+       alignment_check = (guint)native_code & kNaClAlignmentMask;
+       g_assert (alignment_check == 0);
+       return native_code;
+#else
+       g_assert_not_reached ();
+       return cfg->native_code;
+#endif
+}
+
 #ifdef __native_client_codegen__
 
 /* Prevent instructions from straddling a 32-byte alignment boundary.   */
@@ -340,6 +351,10 @@ mono_pmip (void *ip)
  * output.  Unlike mono_pmip which returns a string, this routine
  * prints the value on the standard output. 
  */
+#ifdef __GNUC__
+/* Prevent the linker from optimizing this away in embedding setups to help debugging */
+ __attribute__((used))
+#endif
 void
 mono_print_method_from_ip (void *ip)
 {
@@ -364,6 +379,7 @@ mono_print_method_from_ip (void *ip)
                }
                else
                        g_print ("No method at %p\n", ip);
+               fflush (stdout);
                return;
        }
        method = mono_method_full_name (ji->method, TRUE);
@@ -373,6 +389,7 @@ mono_print_method_from_ip (void *ip)
 
        if (source)
                g_print ("%s:%d\n", source->source_file, source->row);
+       fflush (stdout);
 
        mono_debug_free_source_location (source);
        g_free (method);
@@ -430,6 +447,67 @@ void *mono_global_codeman_reserve (int size)
        }
 }
 
+#if defined(__native_client_codegen__) && defined(__native_client__)
+/* Given the temporary buffer (allocated by mono_global_codeman_reserve) into
+ * which we are generating code, return a pointer to the destination in the
+ * dynamic code segment into which the code will be copied when
+ * mono_global_codeman_commit is called.
+ * LOCKING: Acquires the jit lock.
+ */
+void*
+nacl_global_codeman_get_dest (void *data)
+{
+       void *dest;
+       mono_jit_lock ();
+       dest = nacl_code_manager_get_code_dest (global_codeman, data);
+       mono_jit_unlock ();
+       return dest;
+}
+
+void
+mono_global_codeman_commit (void *data, int size, int newsize)
+{
+       mono_jit_lock ();
+       mono_code_manager_commit (global_codeman, data, size, newsize);
+       mono_jit_unlock ();
+}
+
+/* 
+ * Convenience function which calls mono_global_codeman_commit to validate and
+ * copy the code. The caller sets *buf_base and *buf_size to the start and size
+ * of the buffer (allocated by mono_global_codeman_reserve), and *code_end to
+ * the byte after the last instruction byte. On return, *buf_base will point to
+ * the start of the copied in the code segment, and *code_end will point after
+ * the end of the copied code.
+ */
+void
+nacl_global_codeman_validate (guint8 **buf_base, int buf_size, guint8 **code_end)
+{
+       guint8 *tmp = nacl_global_codeman_get_dest (*buf_base);
+       mono_global_codeman_commit (*buf_base, buf_size, *code_end - *buf_base);
+       *code_end = tmp + (*code_end - *buf_base);
+       *buf_base = tmp;
+}
+#else
+/* no-op versions of Native Client functions */
+void*
+nacl_global_codeman_get_dest (void *data)
+{
+       return data;
+}
+
+void
+mono_global_codeman_commit (void *data, int size, int newsize)
+{
+}
+
+void
+nacl_global_codeman_validate (guint8 **buf_base, int buf_size, guint8 **code_end)
+{
+}
+
+#endif /* __native_client__ */
+
 /**
  * mono_create_unwind_op:
  *
@@ -1032,7 +1110,7 @@ mono_compile_create_var_for_vreg (MonoCompile *cfg, MonoType *type, int opcode,
                memset (&cfg->vars [orig_count], 0, (cfg->varinfo_count - orig_count) * sizeof (MonoMethodVar));
        }
 
-       mono_jit_stats.allocate_var++;
+       cfg->stat_allocate_var++;
 
        MONO_INST_NEW (cfg, inst, opcode);
        inst->inst_c0 = num;
@@ -1048,7 +1126,7 @@ mono_compile_create_var_for_vreg (MonoCompile *cfg, MonoType *type, int opcode,
                        mono_mark_vreg_as_mp (cfg, vreg);
                } else {
                        MonoType *t = mini_type_get_underlying_type (NULL, type);
-                       if ((MONO_TYPE_ISSTRUCT (t) && inst->klass->has_references) || MONO_TYPE_IS_REFERENCE (t)) {
+                       if ((MONO_TYPE_ISSTRUCT (t) && inst->klass->has_references) || mini_type_is_reference (cfg, t)) {
                                inst->flags |= MONO_INST_GC_TRACK;
                                mono_mark_vreg_as_ref (cfg, vreg);
                        }
@@ -1145,6 +1223,20 @@ mono_compile_create_var (MonoCompile *cfg, MonoType *type, int opcode)
        return mono_compile_create_var_for_vreg (cfg, type, opcode, dreg);
 }
 
+/*
+ * Transform a MonoInst into a load from the variable of index var_index.
+ */
+void
+mono_compile_make_var_load (MonoCompile *cfg, MonoInst *dest, gssize var_index) {
+       memset (dest, 0, sizeof (MonoInst));
+       dest->inst_i0 = cfg->varinfo [var_index];
+       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;
+}
+
+#endif
+
 void
 mono_mark_vreg_as_ref (MonoCompile *cfg, int vreg)
 {
@@ -1177,20 +1269,6 @@ mono_mark_vreg_as_mp (MonoCompile *cfg, int vreg)
        cfg->vreg_is_mp [vreg] = TRUE;
 }      
 
-/*
- * Transform a MonoInst into a load from the variable of index var_index.
- */
-void
-mono_compile_make_var_load (MonoCompile *cfg, MonoInst *dest, gssize var_index) {
-       memset (dest, 0, sizeof (MonoInst));
-       dest->inst_i0 = cfg->varinfo [var_index];
-       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;
-}
-
-#endif
-
 static MonoType*
 type_from_stack_type (MonoInst *ins) {
        switch (ins->type) {
@@ -1414,12 +1492,13 @@ mini_method_verify (MonoCompile *cfg, MonoMethod *method, gboolean fail_compile)
        if (method->verification_success)
                return FALSE;
 
-       is_fulltrust = mono_verifier_is_method_full_trust (method);
-
        if (!mono_verifier_is_enabled_for_method (method))
                return FALSE;
 
-       res = mono_method_verify_with_current_settings (method, cfg->skip_visibility);
+       /*skip verification implies the assembly must be */
+       is_fulltrust = mono_verifier_is_method_full_trust (method) ||  mini_assembly_can_skip_verification (cfg->domain, method);
+
+       res = mono_method_verify_with_current_settings (method, cfg->skip_visibility, is_fulltrust);
 
        if ((error = mono_loader_get_last_error ())) {
                if (fail_compile)
@@ -1466,8 +1545,7 @@ gboolean
 mono_compile_is_broken (MonoCompile *cfg, MonoMethod *method, gboolean fail_compile)
 {
        MonoMethod *method_definition = method;
-       gboolean dont_verify = mini_assembly_can_skip_verification (cfg->domain, method);
-       dont_verify |= method->klass->image->assembly->corlib_internal;
+       gboolean dont_verify = method->klass->image->assembly->corlib_internal;
 
        while (method_definition->is_inflated) {
                MonoMethodInflated *imethod = (MonoMethodInflated *) method_definition;
@@ -1580,7 +1658,7 @@ compare_by_interval_start_pos_func (gconstpointer a, gconstpointer b)
 #endif
 
 static gint32*
-mono_allocate_stack_slots_full2 (MonoCompile *cfg, gboolean backward, guint32 *stack_size, guint32 *stack_align)
+mono_allocate_stack_slots2 (MonoCompile *cfg, gboolean backward, guint32 *stack_size, guint32 *stack_align)
 {
        int i, slot, offset, size;
        guint32 align;
@@ -1684,7 +1762,7 @@ mono_allocate_stack_slots_full2 (MonoCompile *cfg, gboolean backward, guint32 *s
                case MONO_TYPE_PTR:
                case MONO_TYPE_I:
                case MONO_TYPE_U:
-#if SIZEOF_REGISTER == 4
+#if SIZEOF_VOID_P == 4
                case MONO_TYPE_I4:
 #else
                case MONO_TYPE_I8:
@@ -1823,6 +1901,12 @@ mono_allocate_stack_slots_full2 (MonoCompile *cfg, gboolean backward, guint32 *s
 
                LSCAN_DEBUG (printf ("R%d %s -> 0x%x\n", inst->dreg, mono_type_full_name (t), slot));
 
+               if (inst->flags & MONO_INST_LMF) {
+                       size = sizeof (MonoLMF);
+                       align = sizeof (mgreg_t);
+                       reuse_slot = FALSE;
+               }
+
                if (!reuse_slot)
                        slot = 0xffffff;
 
@@ -1866,14 +1950,14 @@ mono_allocate_stack_slots_full2 (MonoCompile *cfg, gboolean backward, guint32 *s
                        g_list_free (vtype_stack_slots [i].active);
        }
 
-       mono_jit_stats.locals_stack_size += offset;
+       cfg->stat_locals_stack_size += offset;
 
        *stack_size = offset;
        return offsets;
 }
 
 /*
- *  mono_allocate_stack_slots_full:
+ *  mono_allocate_stack_slots:
  *
  *  Allocate stack slots for all non register allocated variables using a
  * linear scan algorithm.
@@ -1882,7 +1966,7 @@ mono_allocate_stack_slots_full2 (MonoCompile *cfg, gboolean backward, guint32 *s
  * STACK_ALIGN is set to the alignment needed by the locals area.
  */
 gint32*
-mono_allocate_stack_slots_full (MonoCompile *cfg, gboolean backward, guint32 *stack_size, guint32 *stack_align)
+mono_allocate_stack_slots (MonoCompile *cfg, gboolean backward, guint32 *stack_size, guint32 *stack_align)
 {
        int i, slot, offset, size;
        guint32 align;
@@ -1896,7 +1980,7 @@ mono_allocate_stack_slots_full (MonoCompile *cfg, gboolean backward, guint32 *st
        gboolean reuse_slot;
 
        if ((cfg->num_varinfo > 0) && MONO_VARINFO (cfg, 0)->interval)
-               return mono_allocate_stack_slots_full2 (cfg, backward, stack_size, stack_align);
+               return mono_allocate_stack_slots2 (cfg, backward, stack_size, stack_align);
 
        scalar_stack_slots = mono_mempool_alloc0 (cfg->mempool, sizeof (StackSlotInfo) * MONO_TYPE_PINNED);
        vtype_stack_slots = NULL;
@@ -1918,7 +2002,7 @@ mono_allocate_stack_slots_full (MonoCompile *cfg, gboolean backward, guint32 *st
 
        vars = mono_varlist_sort (cfg, vars, 0);
        offset = 0;
-       *stack_align = sizeof (gpointer);
+       *stack_align = sizeof(mgreg_t);
        for (l = vars; l; l = l->next) {
                vmv = l->data;
                inst = cfg->varinfo [vmv->idx];
@@ -1973,7 +2057,7 @@ mono_allocate_stack_slots_full (MonoCompile *cfg, gboolean backward, guint32 *st
                        case MONO_TYPE_PTR:
                        case MONO_TYPE_I:
                        case MONO_TYPE_U:
-#if SIZEOF_REGISTER == 4
+#if SIZEOF_VOID_P == 4
                        case MONO_TYPE_I4:
 #else
                        case MONO_TYPE_I8:
@@ -2051,6 +2135,16 @@ mono_allocate_stack_slots_full (MonoCompile *cfg, gboolean backward, guint32 *st
                        */
                }
 
+               if (inst->flags & MONO_INST_LMF) {
+                       /*
+                        * This variable represents a MonoLMF structure, which has no corresponding
+                        * CLR type, so hard-code its size/alignment.
+                        */
+                       size = sizeof (MonoLMF);
+                       align = sizeof (mgreg_t);
+                       reuse_slot = FALSE;
+               }
+
                if (!reuse_slot)
                        slot = 0xffffff;
 
@@ -2098,7 +2192,7 @@ mono_allocate_stack_slots_full (MonoCompile *cfg, gboolean backward, guint32 *st
                        g_list_free (vtype_stack_slots [i].active);
        }
 
-       mono_jit_stats.locals_stack_size += offset;
+       cfg->stat_locals_stack_size += offset;
 
        *stack_size = offset;
        return offsets;
@@ -2107,7 +2201,7 @@ mono_allocate_stack_slots_full (MonoCompile *cfg, gboolean backward, guint32 *st
 #else
 
 gint32*
-mono_allocate_stack_slots_full (MonoCompile *cfg, gboolean backward, guint32 *stack_size, guint32 *stack_align)
+mono_allocate_stack_slots (MonoCompile *cfg, gboolean backward, guint32 *stack_size, guint32 *stack_align)
 {
        g_assert_not_reached ();
        return NULL;
@@ -2115,12 +2209,6 @@ mono_allocate_stack_slots_full (MonoCompile *cfg, gboolean backward, guint32 *st
 
 #endif /* DISABLE_JIT */
 
-gint32*
-mono_allocate_stack_slots (MonoCompile *m, guint32 *stack_size, guint32 *stack_align)
-{
-       return mono_allocate_stack_slots_full (m, TRUE, stack_size, stack_align);
-}
-
 #define EMUL_HIT_SHIFT 3
 #define EMUL_HIT_MASK ((1 << EMUL_HIT_SHIFT) - 1)
 /* small hit bitmap cache */
@@ -2277,6 +2365,8 @@ mono_bblock_insert_before_ins (MonoBasicBlock *bb, MonoInst *ins, MonoInst *ins_
 {
        if (ins == NULL) {
                ins = bb->code;
+               if (ins)
+                       ins->prev = ins_to_insert;
                bb->code = ins_to_insert;
                ins_to_insert->next = ins;
                if (bb->last_ins == NULL)
@@ -2360,18 +2450,18 @@ mono_destroy_compile (MonoCompile *cfg)
        g_free (cfg);
 }
 
-#ifdef MINI_HAVE_FAST_TLS
-MINI_FAST_TLS_DECLARE(mono_lmf_addr);
+#ifdef MONO_HAVE_FAST_TLS
+MONO_FAST_TLS_DECLARE(mono_lmf_addr);
 #ifdef MONO_ARCH_ENABLE_MONO_LMF_VAR
 /* 
  * When this is defined, the current lmf is stored in this tls variable instead of in 
  * jit_tls->lmf.
  */
-MINI_FAST_TLS_DECLARE(mono_lmf);
+MONO_FAST_TLS_DECLARE(mono_lmf);
 #endif
 #endif
 
-guint32
+MonoNativeTlsKey
 mono_get_jit_tls_key (void)
 {
        return mono_jit_tls_id;
@@ -2380,21 +2470,17 @@ mono_get_jit_tls_key (void)
 gint32
 mono_get_jit_tls_offset (void)
 {
-#ifdef MINI_HAVE_FAST_TLS
        int offset;
-       MINI_THREAD_VAR_OFFSET (mono_jit_tls, offset);
+       MONO_THREAD_VAR_OFFSET (mono_jit_tls, offset);
        return offset;
-#else
-       return -1;
-#endif
 }
 
 gint32
 mono_get_lmf_tls_offset (void)
 {
-#if defined(MINI_HAVE_FAST_TLS) && defined(MONO_ARCH_ENABLE_MONO_LMF_VAR)
+#if defined(MONO_ARCH_ENABLE_MONO_LMF_VAR)
        int offset;
-       MINI_THREAD_VAR_OFFSET(mono_lmf,offset);
+       MONO_THREAD_VAR_OFFSET(mono_lmf,offset);
        return offset;
 #else
        return -1;
@@ -2405,22 +2491,25 @@ gint32
 mono_get_lmf_addr_tls_offset (void)
 {
        int offset;
-       MINI_THREAD_VAR_OFFSET(mono_lmf_addr,offset);
+       MONO_THREAD_VAR_OFFSET(mono_lmf_addr,offset);
        return offset;
 }
 
 MonoLMF *
 mono_get_lmf (void)
 {
-#if defined(MINI_HAVE_FAST_TLS) && defined(MONO_ARCH_ENABLE_MONO_LMF_VAR)
-       return MINI_FAST_TLS_GET (mono_lmf);
+#if defined(MONO_HAVE_FAST_TLS) && defined(MONO_ARCH_ENABLE_MONO_LMF_VAR)
+       return MONO_FAST_TLS_GET (mono_lmf);
 #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;
-
-       g_assert_not_reached ();
+       /*
+        * We do not assert here because this function can be called from
+        * mini-gc.c on a thread that has not executed any managed code, yet
+        * (the thread object allocation can trigger a collection).
+        */
        return NULL;
 #endif
 }
@@ -2428,12 +2517,12 @@ mono_get_lmf (void)
 MonoLMF **
 mono_get_lmf_addr (void)
 {
-#ifdef MINI_HAVE_FAST_TLS
-       return MINI_FAST_TLS_GET (mono_lmf_addr);
+#ifdef MONO_HAVE_FAST_TLS
+       return MONO_FAST_TLS_GET (mono_lmf_addr);
 #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;
 
        /*
@@ -2446,7 +2535,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 ();
@@ -2457,8 +2546,8 @@ mono_get_lmf_addr (void)
 void
 mono_set_lmf (MonoLMF *lmf)
 {
-#if defined(MINI_HAVE_FAST_TLS) && defined(MONO_ARCH_ENABLE_MONO_LMF_VAR)
-       MINI_FAST_TLS_SET (mono_lmf, lmf);
+#if defined(MONO_HAVE_FAST_TLS) && defined(MONO_ARCH_ENABLE_MONO_LMF_VAR)
+       MONO_FAST_TLS_SET (mono_lmf, lmf);
 #endif
 
        (*mono_get_lmf_addr ()) = lmf;
@@ -2467,18 +2556,18 @@ 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 MINI_HAVE_FAST_TLS
-       MINI_FAST_TLS_SET (mono_jit_tls, jit_tls);
+#ifdef MONO_HAVE_FAST_TLS
+       MONO_FAST_TLS_SET (mono_jit_tls, jit_tls);
 #endif
 }
 
 static void
 mono_set_lmf_addr (gpointer lmf_addr)
 {
-#ifdef MINI_HAVE_FAST_TLS
-       MINI_FAST_TLS_SET (mono_lmf_addr, lmf_addr);
+#ifdef MONO_HAVE_FAST_TLS
+       MONO_FAST_TLS_SET (mono_lmf_addr, lmf_addr);
 #endif
 }
 
@@ -2493,13 +2582,17 @@ mono_jit_thread_attach (MonoDomain *domain)
                 */
                domain = mono_get_root_domain ();
 
-#ifdef MINI_HAVE_FAST_TLS
-       if (!MINI_FAST_TLS_GET (mono_lmf_addr)) {
+#ifdef MONO_HAVE_FAST_TLS
+       if (!MONO_FAST_TLS_GET (mono_lmf_addr)) {
                mono_thread_attach (domain);
+               // #678164
+               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);
@@ -2514,7 +2607,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);*/
@@ -2523,6 +2616,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 ());
        }
 }
@@ -2533,7 +2635,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;
 
@@ -2549,9 +2651,9 @@ setup_jit_tls_data (gpointer stack_start, gpointer abort_func)
 
        jit_tls->first_lmf = lmf;
 
-#if defined(MINI_HAVE_FAST_TLS) && defined(MONO_ARCH_ENABLE_MONO_LMF_VAR)
+#if defined(MONO_HAVE_FAST_TLS) && defined(MONO_ARCH_ENABLE_MONO_LMF_VAR)
        /* jit_tls->lmf is unused */
-       MINI_FAST_TLS_SET (mono_lmf, lmf);
+       MONO_FAST_TLS_SET (mono_lmf, lmf);
        mono_set_lmf_addr (&mono_lmf);
 #else
        mono_set_lmf_addr (&jit_tls->lmf);
@@ -2628,9 +2730,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);
                }
 
@@ -2762,10 +2867,11 @@ mono_patch_info_hash (gconstpointer data)
        switch (ji->type) {
        case MONO_PATCH_INFO_RVA:
        case MONO_PATCH_INFO_LDSTR:
-       case MONO_PATCH_INFO_TYPE_FROM_HANDLE:
        case MONO_PATCH_INFO_LDTOKEN:
        case MONO_PATCH_INFO_DECLSEC:
                return (ji->type << 8) | ji->data.token->token;
+       case MONO_PATCH_INFO_TYPE_FROM_HANDLE:
+               return (ji->type << 8) | ji->data.token->token | (ji->data.token->has_context ? (gsize)ji->data.token->context.class_inst : 0);
        case MONO_PATCH_INFO_INTERNAL_METHOD:
                return (ji->type << 8) | g_str_hash (ji->data.name);
        case MONO_PATCH_INFO_VTABLE:
@@ -2856,7 +2962,13 @@ mono_resolve_patch_target (MonoMethod *method, MonoDomain *domain, guint8 *code,
                target = patch_info->data.inst->inst_c0 + code;
                break;
        case MONO_PATCH_INFO_IP:
+#if defined(__native_client__) && defined(__native_client_codegen__)
+               /* Need to transform to the destination address, it's */
+               /* emitted as an immediate in the code. */
+               target = nacl_inverse_modify_patch_target(ip);
+#else
                target = ip;
+#endif
                break;
        case MONO_PATCH_INFO_METHOD_REL:
                target = code + patch_info->data.offset;
@@ -2872,19 +2984,31 @@ mono_resolve_patch_target (MonoMethod *method, MonoDomain *domain, guint8 *code,
        }
        case MONO_PATCH_INFO_METHOD_JUMP:
                target = mono_create_jump_trampoline (domain, patch_info->data.method, FALSE);
+#if defined(__native_client__) && defined(__native_client_codegen__)
+#if defined(TARGET_AMD64)
+               /* This target is an absolute address, not relative to the */
+               /* current code being emitted on AMD64. */
+               target = nacl_inverse_modify_patch_target(target);
+#endif
+#endif
                break;
        case MONO_PATCH_INFO_METHOD:
                if (patch_info->data.method == method) {
                        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: {
                gpointer *jump_table;
                int i;
 
+#if defined(__native_client__) && defined(__native_client_codegen__)
+               /* This memory will leak, but we don't care if we're */
+               /* not deleting JIT'd methods anyway                 */
+               jump_table = g_malloc0 (sizeof(gpointer) * patch_info->data.table->table_size);
+#else
                if (method && method->dynamic) {
                        jump_table = mono_code_manager_reserve (mono_dynamic_code_hash_lookup (domain, method)->code_mp, sizeof (gpointer) * patch_info->data.table->table_size);
                } else {
@@ -2894,16 +3018,34 @@ mono_resolve_patch_target (MonoMethod *method, MonoDomain *domain, guint8 *code,
                                jump_table = mono_domain_code_reserve (domain, sizeof (gpointer) * patch_info->data.table->table_size);
                        }
                }
+#endif
 
-               for (i = 0; i < patch_info->data.table->table_size; i++)
+               for (i = 0; i < patch_info->data.table->table_size; i++) {
+#if defined(__native_client__) && defined(__native_client_codegen__)
+                       /* 'code' is relative to the current code blob, we */
+                       /* need to do this transform on it to make the     */
+                       /* pointers in this table absolute                 */
+                       jump_table [i] = nacl_inverse_modify_patch_target (code) + GPOINTER_TO_INT (patch_info->data.table->table [i]);
+#else
                        jump_table [i] = code + GPOINTER_TO_INT (patch_info->data.table->table [i]);
+#endif
+               }
+
+#if defined(__native_client__) && defined(__native_client_codegen__)
+               /* jump_table is in the data section, we need to transform */
+               /* it here so when it gets modified in amd64_patch it will */
+               /* then point back to the absolute data address            */
+               target = nacl_inverse_modify_patch_target (jump_table);
+#else
                target = jump_table;
+#endif
                break;
        }
        case MONO_PATCH_INFO_METHODCONST:
        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:
@@ -2950,7 +3092,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: {
@@ -3097,6 +3239,10 @@ mono_resolve_patch_target (MonoMethod *method, MonoDomain *domain, guint8 *code,
                target = mono_gc_get_card_table (&card_table_shift_bits, &card_table_mask);
                break;
        }
+       case MONO_PATCH_INFO_CASTCLASS_CACHE: {
+               target = mono_domain_alloc0 (domain, sizeof (gpointer));
+               break;
+       }
        default:
                g_assert_not_reached ();
        }
@@ -3243,11 +3389,18 @@ mono_postprocess_patches (MonoCompile *cfg)
                }
                case MONO_PATCH_INFO_SWITCH: {
                        gpointer *table;
+#if defined(__native_client__) && defined(__native_client_codegen__)
+                       /* This memory will leak.  */
+                       /* TODO: can we free this when  */
+                       /* making the final jump table? */
+                       table = g_malloc0 (sizeof(gpointer) * patch_info->data.table->table_size);
+#else
                        if (cfg->method->dynamic) {
                                table = mono_code_manager_reserve (cfg->dynamic_info->code_mp, sizeof (gpointer) * patch_info->data.table->table_size);
                        } else {
                                table = mono_domain_code_reserve (cfg->domain, sizeof (gpointer) * patch_info->data.table->table_size);
                        }
+#endif
 
                        for (i = 0; i < patch_info->data.table->table_size; i++) {
                                /* Might be NULL if the switch is eliminated */
@@ -3262,16 +3415,23 @@ mono_postprocess_patches (MonoCompile *cfg)
                        break;
                }
                case MONO_PATCH_INFO_METHOD_JUMP: {
-                       GSList *list;
+                       MonoJumpList *jlist;
                        MonoDomain *domain = cfg->domain;
                        unsigned char *ip = cfg->native_code + patch_info->ip.i;
+#if defined(__native_client__) && defined(__native_client_codegen__)
+                       /* When this jump target gets evaluated, the method */
+                       /* will be installed in the dynamic code section,   */
+                       /* not at the location of cfg->native_code.         */
+                       ip = nacl_inverse_modify_patch_target (cfg->native_code) + patch_info->ip.i;
+#endif
 
                        mono_domain_lock (domain);
-                       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_jit_info (domain)->jump_target_hash, patch_info->data.method, list);
+                       jlist = g_hash_table_lookup (domain_jit_info (domain)->jump_target_hash, patch_info->data.method);
+                       if (!jlist) {
+                               jlist = mono_domain_alloc0 (domain, sizeof (MonoJumpList));
+                               g_hash_table_insert (domain_jit_info (domain)->jump_target_hash, patch_info->data.method, jlist);
+                       }
+                       jlist->list = g_slist_prepend (jlist->list, ip);
                        mono_domain_unlock (domain);
                        break;
                }
@@ -3287,12 +3447,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)
@@ -3339,7 +3508,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) {
@@ -3403,6 +3573,26 @@ mono_codegen (MonoCompile *cfg)
        MonoBasicBlock *bb;
        int max_epilog_size;
        guint8 *code;
+       MonoDomain *code_domain;
+
+       if (mono_using_xdebug)
+               /*
+                * Recent gdb versions have trouble processing symbol files containing
+                * overlapping address ranges, so allocate all code from the code manager
+                * of the root domain. (#666152).
+                */
+               code_domain = mono_get_root_domain ();
+       else
+               code_domain = cfg->domain;
+
+#if defined(__native_client_codegen__) && defined(__native_client__)
+       void *code_dest;
+
+       /* This keeps patch targets from being transformed during
+        * ordinary method compilation, for local branches and jumps.
+        */
+       nacl_allow_target_modification (FALSE);
+#endif
 
        for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
                cfg->spill_count = 0;
@@ -3456,12 +3646,13 @@ mono_codegen (MonoCompile *cfg)
                }
        }
 
+#ifdef __native_client_codegen__
+       mono_nacl_fix_patches (cfg->native_code, cfg->patch_info);
+#endif
        mono_arch_emit_exceptions (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 */
@@ -3478,17 +3669,27 @@ mono_codegen (MonoCompile *cfg)
                mono_dynamic_code_hash_insert (cfg->domain, cfg->method, cfg->dynamic_info);
                mono_domain_unlock (cfg->domain);
 
-               code = mono_code_manager_reserve (cfg->dynamic_info->code_mp, cfg->code_size + unwindlen);
+               if (mono_using_xdebug)
+                       /* See the comment for cfg->code_domain */
+                       code = mono_domain_code_reserve (code_domain, cfg->code_size + unwindlen);
+               else
+                       code = mono_code_manager_reserve (cfg->dynamic_info->code_mp, cfg->code_size + unwindlen);
        } else {
                guint unwindlen = 0;
 #ifdef MONO_ARCH_HAVE_UNWIND_TABLE
                unwindlen = mono_arch_unwindinfo_get_size (cfg->arch.unwindinfo);
 #endif
-               code = mono_domain_code_reserve (cfg->domain, cfg->code_size + unwindlen);
+               code = mono_domain_code_reserve (code_domain, cfg->code_size + unwindlen);
        }
+#if defined(__native_client_codegen__) && defined(__native_client__)
+       nacl_allow_target_modification (TRUE);
+#endif
 
+       g_assert (code);
        memcpy (code, cfg->native_code, cfg->code_len);
-#ifdef __native_client_codegen__
+#if defined(__default_codegen__)
+       g_free (cfg->native_code);
+#elif defined(__native_client_codegen__)
        if (cfg->native_code_alloc) {
                g_free (cfg->native_code_alloc);
                cfg->native_code_alloc = 0;
@@ -3496,9 +3697,7 @@ mono_codegen (MonoCompile *cfg)
        else if (cfg->native_code) {
                g_free (cfg->native_code);
        }
-#else
-       g_free (cfg->native_code);
-#endif
+#endif /* __native_client_codegen__ */
        cfg->native_code = code;
        code = cfg->native_code + cfg->code_len;
   
@@ -3536,18 +3735,34 @@ if (valgrind_register){
 #ifdef MONO_ARCH_HAVE_SAVE_UNWIND_INFO
        mono_arch_save_unwind_info (cfg);
 #endif
-       
-#ifdef __native_client_codegen__
+
+#if defined(__native_client_codegen__) && defined(__native_client__)
+       if (!cfg->compile_aot) {
+               if (cfg->method->dynamic) {
+                       code_dest = nacl_code_manager_get_code_dest(cfg->dynamic_info->code_mp, cfg->native_code);
+               } else {
+                       code_dest = nacl_domain_get_code_dest(cfg->domain, cfg->native_code);
+               }
+       }
+#endif
+
+#if defined(__native_client_codegen__)
        mono_nacl_fix_patches (cfg->native_code, cfg->patch_info);
 #endif
 
-       mono_arch_patch_code (cfg->method, cfg->domain, cfg->native_code, cfg->patch_info, cfg->run_cctors);
+       mono_arch_patch_code (cfg->method, cfg->domain, cfg->native_code, cfg->patch_info, cfg->dynamic_info ? cfg->dynamic_info->code_mp : NULL, cfg->run_cctors);
 
        if (cfg->method->dynamic) {
-               mono_code_manager_commit (cfg->dynamic_info->code_mp, cfg->native_code, cfg->code_size, cfg->code_len);
+               if (mono_using_xdebug)
+                       mono_domain_code_commit (code_domain, cfg->native_code, cfg->code_size, cfg->code_len);
+               else
+                       mono_code_manager_commit (cfg->dynamic_info->code_mp, cfg->native_code, cfg->code_size, cfg->code_len);
        } else {
-               mono_domain_code_commit (cfg->domain, cfg->native_code, cfg->code_size, cfg->code_len);
+               mono_domain_code_commit (code_domain, cfg->native_code, cfg->code_size, cfg->code_len);
        }
+#if defined(__native_client_codegen__) && defined(__native_client__)
+       cfg->native_code = code_dest;
+#endif
        mono_profiler_code_buffer_new (cfg->native_code, cfg->code_len, MONO_PROFILER_CODE_BUFFER_METHOD, cfg->method);
        
        mono_arch_flush_icache (cfg->native_code, cfg->code_len);
@@ -3592,8 +3807,9 @@ create_jit_info (MonoCompile *cfg, MonoMethod *method_to_compile)
        MonoMethodHeader *header;
        MonoJitInfo *jinfo;
        int num_clauses;
-       int generic_info_size;
+       int generic_info_size, arch_eh_info_size = 0;
        int holes_size = 0, num_holes = 0;
+       guint32 stack_size = 0;
 
        g_assert (method_to_compile == cfg->method);
        header = cfg->header;
@@ -3603,6 +3819,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;
@@ -3628,11 +3859,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);
        } 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);
        }
 
        jinfo->method = cfg->method_to_register;
@@ -3730,6 +3961,15 @@ 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 (COMPILE_LLVM (cfg)) {
                if (num_clauses)
                        memcpy (&jinfo->clauses [0], &cfg->llvm_ex_info [0], num_clauses * sizeof (MonoJitExceptionInfo));
@@ -3940,7 +4180,7 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, gbool
        gboolean try_generic_shared, try_llvm = FALSE;
        MonoMethod *method_to_compile, *method_to_register;
 
-       mono_jit_stats.methods_compiled++;
+       InterlockedIncrement (&mono_jit_stats.methods_compiled);
        if (mono_profiler_get_events () & MONO_PROFILE_JIT_COMPILATION)
                mono_profiler_method_jit (method);
        if (MONO_PROBE_METHOD_COMPILE_BEGIN_ENABLED ())
@@ -3991,6 +4231,7 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, gbool
        cfg->orig_method = method;
        cfg->gen_seq_points = debug_options.gen_seq_points;
        cfg->explicit_null_checks = debug_options.explicit_null_checks;
+       cfg->soft_breakpoints = debug_options.soft_breakpoints;
        if (try_generic_shared)
                cfg->generic_sharing_context = (MonoGenericSharingContext*)&cfg->generic_sharing_context;
        cfg->compile_llvm = try_llvm;
@@ -4251,8 +4492,7 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, gbool
                return cfg;
        }
 
-       mono_jit_stats.basic_blocks += cfg->num_bblocks;
-       mono_jit_stats.max_basic_blocks = MAX (cfg->num_bblocks, mono_jit_stats.max_basic_blocks);
+       cfg->stat_basic_blocks += cfg->num_bblocks;
 
        if (COMPILE_LLVM (cfg)) {
                MonoInst *ins;
@@ -5057,23 +5297,39 @@ mono_jit_compile_method_inner (MonoMethod *method, MonoDomain *target_domain, in
 
        prof_options = cfg->prof_options;
 
+       /*
+        * Update global stats while holding a lock, instead of doing many
+        * InterlockedIncrement operations during JITting.
+        */
+       mono_jit_stats.allocate_var += cfg->stat_allocate_var;
+       mono_jit_stats.locals_stack_size += cfg->stat_locals_stack_size;
+       mono_jit_stats.basic_blocks += cfg->stat_basic_blocks;
+       mono_jit_stats.max_basic_blocks = MAX (cfg->stat_basic_blocks, mono_jit_stats.max_basic_blocks);
+       mono_jit_stats.cil_code_size += cfg->stat_cil_code_size;
+       mono_jit_stats.regvars += cfg->stat_n_regvars;
+       mono_jit_stats.inlineable_methods += cfg->stat_inlineable_methods;
+       mono_jit_stats.inlined_methods += cfg->stat_inlined_methods;
+       mono_jit_stats.cas_demand_generation += cfg->stat_cas_demand_generation;
+       mono_jit_stats.code_reallocs += cfg->stat_code_reallocs;
+
        mono_destroy_compile (cfg);
 
 #ifndef DISABLE_JIT
        if (domain_jit_info (target_domain)->jump_target_hash) {
                MonoJumpInfo patch_info;
-               GSList *list, *tmp;
-               list = g_hash_table_lookup (domain_jit_info (target_domain)->jump_target_hash, method);
-               if (list) {
+               MonoJumpList *jlist;
+               GSList *tmp;
+               jlist = g_hash_table_lookup (domain_jit_info (target_domain)->jump_target_hash, method);
+               if (jlist) {
                        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 (domain_jit_info (target_domain)->jump_target_hash, method);
+
+                       for (tmp = jlist->list; tmp; tmp = tmp->next)
+                               mono_arch_patch_code (NULL, target_domain, tmp->data, &patch_info, NULL, TRUE);
                }
-               for (tmp = list; tmp; tmp = tmp->next)
-                       mono_arch_patch_code (NULL, target_domain, tmp->data, &patch_info, TRUE);
-               g_slist_free (list);
        }
 
        mono_emit_jit_map (jinfo);
@@ -5166,6 +5422,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;
@@ -5173,6 +5431,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;
@@ -5213,6 +5472,8 @@ mono_jit_free_method (MonoDomain *domain, MonoMethod *method)
 {
        MonoJitDynamicMethodInfo *ji;
        gboolean destroy = TRUE;
+       GHashTableIter iter;
+       MonoJumpList *jlist;
 
        g_assert (method->dynamic);
 
@@ -5222,11 +5483,33 @@ 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);
        g_hash_table_remove (domain_jit_info (domain)->jump_trampoline_hash, method);
        g_hash_table_remove (domain_jit_info (domain)->runtime_invoke_hash, method);
+
+       /* Remove jump targets in this method */
+       g_hash_table_iter_init (&iter, domain_jit_info (domain)->jump_target_hash);
+       while (g_hash_table_iter_next (&iter, NULL, (void**)&jlist)) {
+               GSList *tmp, *remove;
+
+               remove = NULL;
+               for (tmp = jlist->list; tmp; tmp = tmp->next) {
+                       guint8 *ip = tmp->data;
+
+                       if (ip >= (guint8*)ji->ji->code_start && ip < (guint8*)ji->ji->code_start + ji->ji->code_size)
+                               remove = g_slist_prepend (remove, tmp);
+               }
+               for (tmp = remove; tmp; tmp = tmp->next) {
+                       jlist->list = g_slist_delete_link (jlist->list, tmp->data);
+               }
+               g_slist_free (remove);
+       }
+
        mono_domain_unlock (domain);
 
 #ifdef MONO_ARCH_HAVE_INVALIDATE_METHOD
@@ -5557,7 +5840,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
@@ -5568,7 +5851,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)
@@ -5579,7 +5862,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;
@@ -5627,20 +5910,14 @@ SIG_HANDLER_SIGNATURE (mono_sigsegv_signal_handler)
        }
 #endif
 
-       /* The hard-guard page has been hit: there is not much we can do anymore
-        * Print a hopefully clear message and abort.
-        */
        if (jit_tls->stack_size && 
                ABS ((guint8*)fault_addr - ((guint8*)jit_tls->end_of_stack - jit_tls->stack_size)) < 8192 * sizeof (gpointer)) {
-               const char *method;
-               /* we don't do much now, but we can warn the user with a useful message */
-               fprintf (stderr, "Stack overflow: IP: %p, fault addr: %p\n", mono_arch_ip_from_context (ctx), (gpointer)info->si_addr);
-               if (ji && ji->method)
-                       method = mono_method_full_name (ji->method, TRUE);
-               else
-                       method = "Unmanaged";
-               fprintf (stderr, "At %s\n", method);
-               _exit (1);
+               /*
+                * The hard-guard page has been hit: there is not much we can do anymore
+                * Print a hopefully clear message and abort.
+                */
+               mono_handle_hard_stack_ovf (jit_tls, ji, ctx, (guint8*)info->si_addr);
+               g_assert_not_reached ();
        } else {
                /* The original handler might not like that it is executed on an altstack... */
                if (!ji && mono_chain_signal (SIG_HANDLER_PARAMS))
@@ -5657,7 +5934,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
 }
 
@@ -5669,7 +5946,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:
@@ -5770,6 +6047,8 @@ mini_parse_debug_options (void)
                        debug_options.no_gdb_backtrace = TRUE;
                else if (!strcmp (arg, "suspend-on-sigsegv"))
                        debug_options.suspend_on_sigsegv = TRUE;
+               else if (!strcmp (arg, "suspend-on-unhandled"))
+                       debug_options.suspend_on_unhandled = TRUE;
                else if (!strcmp (arg, "dont-free-domains"))
                        mono_dont_free_domains = TRUE;
                else if (!strcmp (arg, "dyn-runtime-invoke"))
@@ -5784,9 +6063,11 @@ mini_parse_debug_options (void)
                        debug_options.init_stacks = TRUE;
                else if (!strcmp (arg, "casts"))
                        debug_options.better_cast_details = TRUE;
+               else if (!strcmp (arg, "soft-breakpoints"))
+                       debug_options.soft_breakpoints = TRUE;
                else {
                        fprintf (stderr, "Invalid option for the MONO_DEBUG env variable: %s\n", arg);
-                       fprintf (stderr, "Available options: 'handle-sigint', 'keep-delegates', 'reverse-pinvoke-exceptions', 'collect-pagefault-stats', 'break-on-unverified', 'no-gdb-backtrace', 'dont-free-domains', 'suspend-on-sigsegv', 'dyn-runtime-invoke', 'gdb', 'explicit-null-checks', 'init-stacks'\n");
+                       fprintf (stderr, "Available options: 'handle-sigint', 'keep-delegates', 'reverse-pinvoke-exceptions', 'collect-pagefault-stats', 'break-on-unverified', 'no-gdb-backtrace', 'dont-free-domains', 'suspend-on-sigsegv', 'suspend-on-unhandled', 'dyn-runtime-invoke', 'gdb', 'explicit-null-checks', 'init-stacks'\n");
                        exit (1);
                }
        }
@@ -5803,16 +6084,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));
@@ -5820,10 +6105,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
 }
 
@@ -5842,9 +6126,21 @@ register_jit_stats (void)
 {
        mono_counters_register ("Compiled methods", MONO_COUNTER_JIT | MONO_COUNTER_WORD, &mono_jit_stats.methods_compiled);
        mono_counters_register ("Methods from AOT", MONO_COUNTER_JIT | MONO_COUNTER_WORD, &mono_jit_stats.methods_aot);
-       mono_counters_register ("Methods JITted using LLVM", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.methods_with_llvm);   
        mono_counters_register ("Methods JITted using mono JIT", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.methods_without_llvm);
+       mono_counters_register ("Methods JITted using LLVM", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.methods_with_llvm);   
        mono_counters_register ("Total time spent JITting (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_time);
+       mono_counters_register ("Basic blocks", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.basic_blocks);
+       mono_counters_register ("Max basic blocks", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.max_basic_blocks);
+       mono_counters_register ("Allocated vars", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.allocate_var);
+       mono_counters_register ("Code reallocs", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.code_reallocs);
+       mono_counters_register ("Allocated code size", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.allocated_code_size);
+       mono_counters_register ("Inlineable methods", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.inlineable_methods);
+       mono_counters_register ("Inlined methods", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.inlined_methods);
+       mono_counters_register ("Regvars", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.regvars);
+       mono_counters_register ("Locals stack size", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.locals_stack_size);
+       mono_counters_register ("Method cache lookups", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.methods_lookups);
+       mono_counters_register ("Compiled CIL code size", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.cil_code_size);
+       mono_counters_register ("Native code size", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.native_code_size);
 }
 
 static void runtime_invoke_info_free (gpointer value);
@@ -5862,6 +6158,7 @@ mini_create_jit_domain_info (MonoDomain *domain)
        info->runtime_invoke_hash = g_hash_table_new_full (mono_aligned_addr_hash, NULL, NULL, runtime_invoke_info_free);
        info->seq_points = g_hash_table_new_full (mono_aligned_addr_hash, NULL, NULL, g_free);
        info->arch_seq_points = g_hash_table_new (mono_aligned_addr_hash, NULL);
+       info->jump_target_hash = g_hash_table_new (NULL, NULL);
 
        domain->runtime_info = info;
 }
@@ -5869,7 +6166,8 @@ mini_create_jit_domain_info (MonoDomain *domain)
 static void
 delete_jump_list (gpointer key, gpointer value, gpointer user_data)
 {
-       g_slist_free (value);
+       MonoJumpList *jlist = value;
+       g_slist_free (jlist->list);
 }
 
 static void
@@ -5897,10 +6195,8 @@ mini_free_jit_domain_info (MonoDomain *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);
-       }
+       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);
@@ -5934,6 +6230,7 @@ mini_init (const char *filename, const char *runtime_version)
 {
        MonoDomain *domain;
        MonoRuntimeCallbacks callbacks;
+       MonoThreadInfoRuntimeCallbacks ticallbacks;
 
        MONO_PROBE_VES_INIT_BEGIN ();
 
@@ -5955,11 +6252,11 @@ mini_init (const char *filename, const char *runtime_version)
                mini_debugger_init ();
 #endif
 
-#ifdef MINI_HAVE_FAST_TLS
-       MINI_FAST_TLS_INIT (mono_jit_tls);
-       MINI_FAST_TLS_INIT (mono_lmf_addr);
+#ifdef MONO_HAVE_FAST_TLS
+       MONO_FAST_TLS_INIT (mono_jit_tls);
+       MONO_FAST_TLS_INIT (mono_lmf_addr);
 #ifdef MONO_ARCH_ENABLE_MONO_LMF_VAR
-       MINI_FAST_TLS_INIT (mono_lmf);
+       MONO_FAST_TLS_INIT (mono_lmf);
 #endif
 #endif
 
@@ -5977,6 +6274,9 @@ mini_init (const char *filename, const char *runtime_version)
        callbacks.create_ftnptr = mini_create_ftnptr;
        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) {
@@ -5987,6 +6287,14 @@ mini_init (const char *filename, const char *runtime_version)
 
        mono_install_callbacks (&callbacks);
 
+       memset (&ticallbacks, 0, sizeof (ticallbacks));
+       ticallbacks.setup_async_callback = mono_setup_async_callback;
+       ticallbacks.thread_state_init_from_sigctx = mono_thread_state_init_from_sigctx;
+       ticallbacks.thread_state_init_from_handle = mono_thread_state_init_from_handle;
+
+       mono_threads_runtime_init (&ticallbacks);
+
+
        if (getenv ("MONO_DEBUG") != NULL)
                mini_parse_debug_options ();
        
@@ -5996,8 +6304,6 @@ mini_init (const char *filename, const char *runtime_version)
 
        mono_unwind_init ();
 
-       mini_gc_init ();
-
        if (getenv ("MONO_XDEBUG")) {
                char *xdebug_opts = getenv ("MONO_XDEBUG");
                mono_xdebug_init (xdebug_opts);
@@ -6026,7 +6332,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)
@@ -6068,7 +6374,6 @@ mini_init (const char *filename, const char *runtime_version)
 #ifdef JIT_INVOKE_WORKS
        mono_install_runtime_invoke (mono_jit_runtime_invoke);
 #endif
-       mono_install_stack_walk (mono_jit_walk_stack);
        mono_install_get_cached_class_info (mono_aot_get_cached_class_info);
        mono_install_get_class_from_name (mono_aot_get_class_from_name);
        mono_install_jit_info_find_in_aot (mono_aot_find_jit_info);
@@ -6098,7 +6403,6 @@ mini_init (const char *filename, const char *runtime_version)
 
        /* This must come after mono_init () in the aot-only case */
        mono_exceptions_init ();
-       mono_install_handler (mono_get_throw_exception ());
 
        mono_icall_init ();
 
@@ -6146,6 +6450,9 @@ mini_init (const char *filename, const char *runtime_version)
        register_icall (mono_load_remote_field_new, "mono_load_remote_field_new", "object object ptr ptr", FALSE);
        register_icall (mono_store_remote_field_new, "mono_store_remote_field_new", "void object ptr ptr object", FALSE);
 
+#if defined(__native_client__) || defined(__native_client_codegen__)
+       register_icall (mono_nacl_gc, "mono_nacl_gc", "void", TRUE);
+#endif
        /* 
         * NOTE, NOTE, NOTE, NOTE:
         * when adding emulation for some opcodes, remember to also add a dummy
@@ -6168,10 +6475,6 @@ mini_init (const char *filename, const char *runtime_version)
 #endif
 
 #if defined(MONO_ARCH_EMULATE_MUL_DIV) || defined(MONO_ARCH_EMULATE_DIV)
-       mono_register_opcode_emulation (CEE_DIV, "__emul_idiv", "int32 int32 int32", mono_idiv, FALSE);
-       mono_register_opcode_emulation (CEE_DIV_UN, "__emul_idiv_un", "int32 int32 int32", mono_idiv_un, FALSE);
-       mono_register_opcode_emulation (CEE_REM, "__emul_irem", "int32 int32 int32", mono_irem, FALSE);
-       mono_register_opcode_emulation (CEE_REM_UN, "__emul_irem_un", "int32 int32 int32", mono_irem_un, FALSE);
        mono_register_opcode_emulation (OP_IDIV, "__emul_op_idiv", "int32 int32 int32", mono_idiv, FALSE);
        mono_register_opcode_emulation (OP_IDIV_UN, "__emul_op_idiv_un", "int32 int32 int32", mono_idiv_un, FALSE);
        mono_register_opcode_emulation (OP_IREM, "__emul_op_irem", "int32 int32 int32", mono_irem, FALSE);
@@ -6179,13 +6482,10 @@ mini_init (const char *filename, const char *runtime_version)
 #endif
 
 #ifdef MONO_ARCH_EMULATE_MUL_DIV
-       mono_register_opcode_emulation (CEE_MUL, "__emul_imul", "int32 int32 int32", mono_imul, TRUE);
        mono_register_opcode_emulation (OP_IMUL, "__emul_op_imul", "int32 int32 int32", mono_imul, TRUE);
 #endif
 
 #if defined(MONO_ARCH_EMULATE_MUL_DIV) || defined(MONO_ARCH_EMULATE_MUL_OVF)
-       mono_register_opcode_emulation (CEE_MUL_OVF, "__emul_imul_ovf", "int32 int32 int32", mono_imul_ovf, FALSE);
-       mono_register_opcode_emulation (CEE_MUL_OVF_UN, "__emul_imul_ovf_un", "int32 int32 int32", mono_imul_ovf_un, FALSE);
        mono_register_opcode_emulation (OP_IMUL_OVF, "__emul_op_imul_ovf", "int32 int32 int32", mono_imul_ovf, FALSE);
        mono_register_opcode_emulation (OP_IMUL_OVF_UN, "__emul_op_imul_ovf_un", "int32 int32 int32", mono_imul_ovf_un, FALSE);
 #endif
@@ -6203,7 +6503,6 @@ mini_init (const char *filename, const char *runtime_version)
        mono_register_opcode_emulation (OP_FCONV_TO_I8, "__emul_fconv_to_i8", "long double", mono_fconv_i8, FALSE);
 #endif
 #ifdef MONO_ARCH_EMULATE_CONV_R8_UN
-       mono_register_opcode_emulation (CEE_CONV_R_UN, "__emul_conv_r_un", "double int32", mono_conv_to_r8_un, FALSE);
        mono_register_opcode_emulation (OP_ICONV_TO_R_UN, "__emul_iconv_to_r_un", "double int32", mono_conv_to_r8_un, FALSE);
 #endif
 #ifdef MONO_ARCH_EMULATE_LCONV_TO_R8
@@ -6216,7 +6515,11 @@ mini_init (const char *filename, const char *runtime_version)
        mono_register_opcode_emulation (OP_LCONV_TO_R_UN, "__emul_lconv_to_r8_un", "double long", mono_lconv_to_r8_un, FALSE);
 #endif
 #ifdef MONO_ARCH_EMULATE_FREM
+#if defined(__default_codegen__)
        mono_register_opcode_emulation (OP_FREM, "__emul_frem", "double double double", fmod, FALSE);
+#elif defined(__native_client_codegen__)
+       mono_register_opcode_emulation (OP_FREM, "__emul_frem", "double double double", mono_fmod, FALSE);
+#endif
 #endif
 
 #ifdef MONO_ARCH_SOFT_FLOAT
@@ -6224,9 +6527,7 @@ mini_init (const char *filename, const char *runtime_version)
        mono_register_opcode_emulation (OP_FADD, "__emul_fadd", "double double double", mono_fadd, FALSE);
        mono_register_opcode_emulation (OP_FMUL, "__emul_fmul", "double double double", mono_fmul, FALSE);
        mono_register_opcode_emulation (OP_FNEG, "__emul_fneg", "double double", mono_fneg, FALSE);
-       mono_register_opcode_emulation (CEE_CONV_R8, "__emul_conv_r8", "double int32", mono_conv_to_r8, FALSE);
        mono_register_opcode_emulation (OP_ICONV_TO_R8, "__emul_iconv_to_r8", "double int32", mono_conv_to_r8, FALSE);
-       mono_register_opcode_emulation (CEE_CONV_R4, "__emul_conv_r4", "double int32", mono_conv_to_r4, FALSE);
        mono_register_opcode_emulation (OP_ICONV_TO_R4, "__emul_iconv_to_r4", "double int32", mono_conv_to_r4, FALSE);
        mono_register_opcode_emulation (OP_FCONV_TO_R4, "__emul_fconv_to_r4", "double double", mono_fconv_r4, FALSE);
        mono_register_opcode_emulation (OP_FCONV_TO_I1, "__emul_fconv_to_i1", "int8 double", mono_fconv_i1, FALSE);
@@ -6308,6 +6609,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 ();
@@ -6348,22 +6651,10 @@ print_jit_stats (void)
 {
        if (mono_jit_stats.enabled) {
                g_print ("Mono Jit statistics\n");
-               g_print ("Methods cache lookup:   %ld\n", mono_jit_stats.methods_lookups);
-               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 ("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,
                                 mono_jit_stats.max_ratio_method);
                g_print ("Biggest method:         %ld (%s)\n", mono_jit_stats.biggest_method_size,
                                 mono_jit_stats.biggest_method);
-               g_print ("Code reallocs:          %ld\n", mono_jit_stats.code_reallocs);
-               g_print ("Allocated code size:    %ld\n", mono_jit_stats.allocated_code_size);
-               g_print ("Inlineable methods:     %ld\n", mono_jit_stats.inlineable_methods);
-               g_print ("Inlined methods:        %ld\n", mono_jit_stats.inlined_methods);
-               g_print ("Regvars:                %ld\n", mono_jit_stats.regvars);
-               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);
@@ -6450,7 +6741,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 ();
 
@@ -6491,7 +6782,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);
 
@@ -6512,6 +6803,19 @@ 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:
  *