Merge pull request #4710 from Unity-Technologies/additional-config-checks
[mono.git] / mono / mini / method-to-ir.c
index cca01c3dbb5a9a4f8ac01584434d704079176181..c47792226c4e983bd2eb1332ff5495c43292e7a1 100644 (file)
@@ -1,5 +1,6 @@
-/*
- * method-to-ir.c: Convert CIL to the JIT internal representation
+/**
+ * \file
+ * Convert CIL to the JIT internal representation
  *
  * Author:
  *   Paolo Molaro (lupus@ximian.com)
@@ -13,6 +14,7 @@
 
 #include <config.h>
 #include <mono/utils/mono-compiler.h>
+#include "mini.h"
 
 #ifndef DISABLE_JIT
 
@@ -35,7 +37,6 @@
 #endif
 
 #include <mono/utils/memcheck.h>
-#include "mini.h"
 #include <mono/metadata/abi-details.h>
 #include <mono/metadata/assembly.h>
 #include <mono/metadata/attrdefs.h>
@@ -50,8 +51,7 @@
 #include <mono/metadata/tabledefs.h>
 #include <mono/metadata/marshal.h>
 #include <mono/metadata/debug-helpers.h>
-#include <mono/metadata/mono-debug.h>
-#include <mono/metadata/mono-debug-debugger.h>
+#include <mono/metadata/debug-internals.h>
 #include <mono/metadata/gc-internals.h>
 #include <mono/metadata/security-manager.h>
 #include <mono/metadata/threads-types.h>
@@ -59,8 +59,6 @@
 #include <mono/metadata/profiler-private.h>
 #include <mono/metadata/profiler.h>
 #include <mono/metadata/monitor.h>
-#include <mono/metadata/debug-mono-symfile.h>
-#include <mono/utils/mono-compiler.h>
 #include <mono/utils/mono-memory-model.h>
 #include <mono/utils/mono-error-internals.h>
 #include <mono/metadata/mono-basic-block.h>
@@ -145,22 +143,25 @@ static int stind_to_store_membase (int opcode);
 int mono_op_to_op_imm (int opcode);
 int mono_op_to_op_imm_noemul (int opcode);
 
-MONO_API MonoInst* mono_emit_native_call (MonoCompile *cfg, gconstpointer func, MonoMethodSignature *sig, MonoInst **args);
-
 static int inline_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **sp,
                                                  guchar *ip, guint real_offset, gboolean inline_always);
 static MonoInst*
 emit_llvmonly_virtual_call (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, int context_used, MonoInst **sp);
 
+inline static MonoInst*
+mono_emit_calli (MonoCompile *cfg, MonoMethodSignature *sig, MonoInst **args, MonoInst *addr, MonoInst *imt_arg, MonoInst *rgctx_arg);
+
 /* helper methods signatures */
 static MonoMethodSignature *helper_sig_domain_get;
 static MonoMethodSignature *helper_sig_rgctx_lazy_fetch_trampoline;
 static MonoMethodSignature *helper_sig_llvmonly_imt_trampoline;
 static MonoMethodSignature *helper_sig_jit_thread_attach;
+static MonoMethodSignature *helper_sig_get_tls_tramp;
+static MonoMethodSignature *helper_sig_set_tls_tramp;
 
 /* type loading helpers */
-static GENERATE_GET_CLASS_WITH_CACHE (runtime_helpers, System.Runtime.CompilerServices, RuntimeHelpers)
-static GENERATE_TRY_GET_CLASS_WITH_CACHE (debuggable_attribute, System.Diagnostics, DebuggableAttribute)
+static GENERATE_GET_CLASS_WITH_CACHE (runtime_helpers, "System.Runtime.CompilerServices", "RuntimeHelpers")
+static GENERATE_TRY_GET_CLASS_WITH_CACHE (debuggable_attribute, "System.Diagnostics", "DebuggableAttribute")
 
 /*
  * Instruction metadata
@@ -203,12 +204,6 @@ const gint8 ins_sreg_counts[] = {
 #undef MINI_OP
 #undef MINI_OP3
 
-#define MONO_INIT_VARINFO(vi,id) do { \
-       (vi)->range.first_use.pos.bid = 0xffff; \
-       (vi)->reg = -1; \
-       (vi)->idx = (id); \
-} while (0)
-
 guint32
 mono_alloc_ireg (MonoCompile *cfg)
 {
@@ -350,14 +345,19 @@ mono_print_bb (MonoBasicBlock *bb, const char *msg)
 {
        int i;
        MonoInst *tree;
+       GString *str = g_string_new ("");
 
-       printf ("\n%s %d: [IN: ", msg, bb->block_num);
+       g_string_append_printf (str, "%s %d: [IN: ", msg, bb->block_num);
        for (i = 0; i < bb->in_count; ++i)
-               printf (" BB%d(%d)", bb->in_bb [i]->block_num, bb->in_bb [i]->dfn);
-       printf (", OUT: ");
+               g_string_append_printf (str, " BB%d(%d)", bb->in_bb [i]->block_num, bb->in_bb [i]->dfn);
+       g_string_append_printf (str, ", OUT: ");
        for (i = 0; i < bb->out_count; ++i)
-               printf (" BB%d(%d)", bb->out_bb [i]->block_num, bb->out_bb [i]->dfn);
-       printf (" ]\n");
+               g_string_append_printf (str, " BB%d(%d)", bb->out_bb [i]->block_num, bb->out_bb [i]->dfn);
+       g_string_append_printf (str, " ]\n");
+
+       g_print ("%s", str->str);
+       g_string_free (str, TRUE);
+
        for (tree = bb->code; tree; tree = tree->next)
                mono_print_ins_index (-1, tree);
 }
@@ -369,6 +369,8 @@ mono_create_helper_signatures (void)
        helper_sig_rgctx_lazy_fetch_trampoline = mono_create_icall_signature ("ptr ptr");
        helper_sig_llvmonly_imt_trampoline = mono_create_icall_signature ("ptr ptr ptr");
        helper_sig_jit_thread_attach = mono_create_icall_signature ("ptr ptr");
+       helper_sig_get_tls_tramp = mono_create_icall_signature ("ptr");
+       helper_sig_set_tls_tramp = mono_create_icall_signature ("void ptr");
 }
 
 static MONO_NEVER_INLINE void
@@ -1259,16 +1261,22 @@ mono_get_got_var (MonoCompile *cfg)
        return cfg->got_var;
 }
 
-static MonoInst *
-mono_get_vtable_var (MonoCompile *cfg)
+static void
+mono_create_rgctx_var (MonoCompile *cfg)
 {
-       g_assert (cfg->gshared);
-
        if (!cfg->rgctx_var) {
                cfg->rgctx_var = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_LOCAL);
                /* force the var to be stack allocated */
                cfg->rgctx_var->flags |= MONO_INST_VOLATILE;
        }
+}
+
+static MonoInst *
+mono_get_vtable_var (MonoCompile *cfg)
+{
+       g_assert (cfg->gshared);
+
+       mono_create_rgctx_var (cfg);
 
        return cfg->rgctx_var;
 }
@@ -1716,22 +1724,91 @@ mini_emit_memcpy (MonoCompile *cfg, int destreg, int doffset, int srcreg, int so
        }
 }
 
-static void
-emit_tls_set (MonoCompile *cfg, int sreg1, MonoTlsKey tls_key)
+static MonoInst*
+mono_create_fast_tls_getter (MonoCompile *cfg, MonoTlsKey key)
+{
+       int tls_offset = mono_tls_get_tls_offset (key);
+
+       if (cfg->compile_aot)
+               return NULL;
+
+       if (tls_offset != -1 && mono_arch_have_fast_tls ()) {
+               MonoInst *ins;
+               MONO_INST_NEW (cfg, ins, OP_TLS_GET);
+               ins->dreg = mono_alloc_preg (cfg);
+               ins->inst_offset = tls_offset;
+               return ins;
+       }
+       return NULL;
+}
+
+static MonoInst*
+mono_create_fast_tls_setter (MonoCompile *cfg, MonoInst* value, MonoTlsKey key)
 {
-       MonoInst *ins, *c;
+       int tls_offset = mono_tls_get_tls_offset (key);
+
+       if (cfg->compile_aot)
+               return NULL;
+
+       if (tls_offset != -1 && mono_arch_have_fast_tls ()) {
+               MonoInst *ins;
+               MONO_INST_NEW (cfg, ins, OP_TLS_SET);
+               ins->sreg1 = value->dreg;
+               ins->inst_offset = tls_offset;
+               return ins;
+       }
+       return NULL;
+}
+
+
+MonoInst*
+mono_create_tls_get (MonoCompile *cfg, MonoTlsKey key)
+{
+       MonoInst *fast_tls = NULL;
+
+       if (!mini_get_debug_options ()->use_fallback_tls)
+               fast_tls = mono_create_fast_tls_getter (cfg, key);
+
+       if (fast_tls) {
+               MONO_ADD_INS (cfg->cbb, fast_tls);
+               return fast_tls;
+       }
 
        if (cfg->compile_aot) {
-               EMIT_NEW_TLS_OFFSETCONST (cfg, c, tls_key);
-               MONO_INST_NEW (cfg, ins, OP_TLS_SET_REG);
-               ins->sreg1 = sreg1;
-               ins->sreg2 = c->dreg;
-               MONO_ADD_INS (cfg->cbb, ins);
+               MonoInst *addr;
+               /*
+                * tls getters are critical pieces of code and we don't want to resolve them
+                * through the standard plt/tramp mechanism since we might expose ourselves
+                * to crashes and infinite recursions.
+                */
+               EMIT_NEW_AOTCONST (cfg, addr, MONO_PATCH_INFO_GET_TLS_TRAMP, (void*)key);
+               return mono_emit_calli (cfg, helper_sig_get_tls_tramp, NULL, addr, NULL, NULL);
        } else {
-               MONO_INST_NEW (cfg, ins, OP_TLS_SET);
-               ins->sreg1 = sreg1;
-               ins->inst_offset = mini_get_tls_offset (tls_key);
-               MONO_ADD_INS (cfg->cbb, ins);
+               gpointer getter = mono_tls_get_tls_getter (key, FALSE);
+               return mono_emit_jit_icall (cfg, getter, NULL);
+       }
+}
+
+static MonoInst*
+mono_create_tls_set (MonoCompile *cfg, MonoInst *value, MonoTlsKey key)
+{
+       MonoInst *fast_tls = NULL;
+
+       if (!mini_get_debug_options ()->use_fallback_tls)
+               fast_tls = mono_create_fast_tls_setter (cfg, value, key);
+
+       if (fast_tls) {
+               MONO_ADD_INS (cfg->cbb, fast_tls);
+               return fast_tls;
+       }
+
+       if (cfg->compile_aot) {
+               MonoInst *addr;
+               EMIT_NEW_AOTCONST (cfg, addr, MONO_PATCH_INFO_SET_TLS_TRAMP, (void*)key);
+               return mono_emit_calli (cfg, helper_sig_set_tls_tramp, &value, addr, NULL, NULL);
+       } else {
+               gpointer setter = mono_tls_get_tls_setter (key, FALSE);
+               return mono_emit_jit_icall (cfg, setter, &value);
        }
 }
 
@@ -1750,79 +1827,40 @@ emit_push_lmf (MonoCompile *cfg)
         * lmf->prev_lmf = *lmf_addr
         * *lmf_addr = lmf
         */
-       int lmf_reg, prev_lmf_reg;
        MonoInst *ins, *lmf_ins;
 
        if (!cfg->lmf_ir)
                return;
 
-       if (cfg->lmf_ir_mono_lmf && mini_tls_get_supported (cfg, TLS_KEY_LMF)) {
-               /* Load current lmf */
-               lmf_ins = mono_get_lmf_intrinsic (cfg);
-               g_assert (lmf_ins);
-               MONO_ADD_INS (cfg->cbb, lmf_ins);
-               EMIT_NEW_VARLOADA (cfg, ins, cfg->lmf_var, NULL);
-               lmf_reg = ins->dreg;
-               /* Save previous_lmf */
-               EMIT_NEW_STORE_MEMBASE (cfg, ins, OP_STORE_MEMBASE_REG, lmf_reg, MONO_STRUCT_OFFSET (MonoLMF, previous_lmf), lmf_ins->dreg);
-               /* Set new LMF */
-               emit_tls_set (cfg, lmf_reg, TLS_KEY_LMF);
-       } else {
-               /*
-                * Store lmf_addr in a variable, so it can be allocated to a global register.
-                */
-               if (!cfg->lmf_addr_var)
-                       cfg->lmf_addr_var = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_LOCAL);
+       int lmf_reg, prev_lmf_reg;
+       /*
+        * Store lmf_addr in a variable, so it can be allocated to a global register.
+        */
+       if (!cfg->lmf_addr_var)
+               cfg->lmf_addr_var = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_LOCAL);
 
 #ifdef HOST_WIN32
-               ins = mono_get_jit_tls_intrinsic (cfg);
-               if (ins) {
-                       int jit_tls_dreg = ins->dreg;
+       ins = mono_create_tls_get (cfg, TLS_KEY_JIT_TLS);
+       g_assert (ins);
+       int jit_tls_dreg = ins->dreg;
 
-                       MONO_ADD_INS (cfg->cbb, ins);
-                       lmf_reg = alloc_preg (cfg);
-                       EMIT_NEW_BIALU_IMM (cfg, lmf_ins, OP_PADD_IMM, lmf_reg, jit_tls_dreg, MONO_STRUCT_OFFSET (MonoJitTlsData, lmf));
-               } else {
-                       lmf_ins = mono_emit_jit_icall (cfg, mono_get_lmf_addr, NULL);
-               }
-#else
-               lmf_ins = mono_get_lmf_addr_intrinsic (cfg);
-               if (lmf_ins) {
-                       MONO_ADD_INS (cfg->cbb, lmf_ins);
-               } else {
-#ifdef TARGET_IOS
-                       MonoInst *args [16], *jit_tls_ins, *ins;
-
-                       /* Inline mono_get_lmf_addr () */
-                       /* jit_tls = pthread_getspecific (mono_jit_tls_id); lmf_addr = &jit_tls->lmf; */
-
-                       /* Load mono_jit_tls_id */
-                       if (cfg->compile_aot)
-                               EMIT_NEW_AOTCONST (cfg, args [0], MONO_PATCH_INFO_JIT_TLS_ID, NULL);
-                       else
-                               EMIT_NEW_ICONST (cfg, args [0], mono_jit_tls_id);
-                       /* call pthread_getspecific () */
-                       jit_tls_ins = mono_emit_jit_icall (cfg, pthread_getspecific, args);
-                       /* lmf_addr = &jit_tls->lmf */
-                       EMIT_NEW_BIALU_IMM (cfg, ins, OP_PADD_IMM, cfg->lmf_addr_var->dreg, jit_tls_ins->dreg, MONO_STRUCT_OFFSET (MonoJitTlsData, lmf));
-                       lmf_ins = ins;
+       lmf_reg = alloc_preg (cfg);
+       EMIT_NEW_BIALU_IMM (cfg, lmf_ins, OP_PADD_IMM, lmf_reg, jit_tls_dreg, MONO_STRUCT_OFFSET (MonoJitTlsData, lmf));
 #else
-                       lmf_ins = mono_emit_jit_icall (cfg, mono_get_lmf_addr, NULL);
+       lmf_ins = mono_create_tls_get (cfg, TLS_KEY_LMF_ADDR);
+       g_assert (lmf_ins);
 #endif
-               }
-#endif
-               lmf_ins->dreg = cfg->lmf_addr_var->dreg;
+       lmf_ins->dreg = cfg->lmf_addr_var->dreg;
 
-               EMIT_NEW_VARLOADA (cfg, ins, cfg->lmf_var, NULL);
-               lmf_reg = ins->dreg;
+       EMIT_NEW_VARLOADA (cfg, ins, cfg->lmf_var, NULL);
+       lmf_reg = ins->dreg;
 
-               prev_lmf_reg = alloc_preg (cfg);
-               /* Save previous_lmf */
-               EMIT_NEW_LOAD_MEMBASE (cfg, ins, OP_LOAD_MEMBASE, prev_lmf_reg, cfg->lmf_addr_var->dreg, 0);
-               EMIT_NEW_STORE_MEMBASE (cfg, ins, OP_STORE_MEMBASE_REG, lmf_reg, MONO_STRUCT_OFFSET (MonoLMF, previous_lmf), prev_lmf_reg);
-               /* Set new lmf */
-               EMIT_NEW_STORE_MEMBASE (cfg, ins, OP_STORE_MEMBASE_REG, cfg->lmf_addr_var->dreg, 0, lmf_reg);
-       }
+       prev_lmf_reg = alloc_preg (cfg);
+       /* Save previous_lmf */
+       EMIT_NEW_LOAD_MEMBASE (cfg, ins, OP_LOAD_MEMBASE, prev_lmf_reg, cfg->lmf_addr_var->dreg, 0);
+       EMIT_NEW_STORE_MEMBASE (cfg, ins, OP_STORE_MEMBASE_REG, lmf_reg, MONO_STRUCT_OFFSET (MonoLMF, previous_lmf), prev_lmf_reg);
+       /* Set new lmf */
+       EMIT_NEW_STORE_MEMBASE (cfg, ins, OP_STORE_MEMBASE_REG, cfg->lmf_addr_var->dreg, 0, lmf_reg);
 }
 
 /*
@@ -1833,7 +1871,7 @@ emit_push_lmf (MonoCompile *cfg)
 static void
 emit_pop_lmf (MonoCompile *cfg)
 {
-       int lmf_reg, lmf_addr_reg, prev_lmf_reg;
+       int lmf_reg, lmf_addr_reg;
        MonoInst *ins;
 
        if (!cfg->lmf_ir)
@@ -1842,26 +1880,19 @@ emit_pop_lmf (MonoCompile *cfg)
        EMIT_NEW_VARLOADA (cfg, ins, cfg->lmf_var, NULL);
        lmf_reg = ins->dreg;
 
-       if (cfg->lmf_ir_mono_lmf && mini_tls_get_supported (cfg, TLS_KEY_LMF)) {
-               /* Load previous_lmf */
-               prev_lmf_reg = alloc_preg (cfg);
-               EMIT_NEW_LOAD_MEMBASE (cfg, ins, OP_LOAD_MEMBASE, prev_lmf_reg, lmf_reg, MONO_STRUCT_OFFSET (MonoLMF, previous_lmf));
-               /* Set new LMF */
-               emit_tls_set (cfg, prev_lmf_reg, TLS_KEY_LMF);
-       } else {
-               /*
-                * Emit IR to pop the LMF:
-                * *(lmf->lmf_addr) = lmf->prev_lmf
-                */
-               /* This could be called before emit_push_lmf () */
-               if (!cfg->lmf_addr_var)
-                       cfg->lmf_addr_var = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_LOCAL);
-               lmf_addr_reg = cfg->lmf_addr_var->dreg;
+       int prev_lmf_reg;
+       /*
+        * Emit IR to pop the LMF:
+        * *(lmf->lmf_addr) = lmf->prev_lmf
+        */
+       /* This could be called before emit_push_lmf () */
+       if (!cfg->lmf_addr_var)
+               cfg->lmf_addr_var = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_LOCAL);
+       lmf_addr_reg = cfg->lmf_addr_var->dreg;
 
-               prev_lmf_reg = alloc_preg (cfg);
-               EMIT_NEW_LOAD_MEMBASE (cfg, ins, OP_LOAD_MEMBASE, prev_lmf_reg, lmf_reg, MONO_STRUCT_OFFSET (MonoLMF, previous_lmf));
-               EMIT_NEW_STORE_MEMBASE (cfg, ins, OP_STORE_MEMBASE_REG, lmf_addr_reg, 0, prev_lmf_reg);
-       }
+       prev_lmf_reg = alloc_preg (cfg);
+       EMIT_NEW_LOAD_MEMBASE (cfg, ins, OP_LOAD_MEMBASE, prev_lmf_reg, lmf_reg, MONO_STRUCT_OFFSET (MonoLMF, previous_lmf));
+       EMIT_NEW_STORE_MEMBASE (cfg, ins, OP_STORE_MEMBASE_REG, lmf_addr_reg, 0, prev_lmf_reg);
 }
 
 static void
@@ -2814,6 +2845,8 @@ emit_llvmonly_calli (MonoCompile *cfg, MonoMethodSignature *fsig, MonoInst **arg
 static gboolean
 direct_icalls_enabled (MonoCompile *cfg)
 {
+       return FALSE;
+
        /* LLVM on amd64 can't handle calls to non-32 bit addresses */
 #ifdef TARGET_AMD64
        if (cfg->compile_llvm && !cfg->llvm_only)
@@ -2906,12 +2939,12 @@ mono_emit_widen_call_res (MonoCompile *cfg, MonoInst *ins, MonoMethodSignature *
 
 
 static void
-emit_method_access_failure (MonoCompile *cfg, MonoMethod *method, MonoMethod *cil_method)
+emit_method_access_failure (MonoCompile *cfg, MonoMethod *caller, MonoMethod *callee)
 {
        MonoInst *args [16];
 
-       args [0] = emit_get_rgctx_method (cfg, mono_method_check_context_used (method), method, MONO_RGCTX_INFO_METHOD);
-       args [1] = emit_get_rgctx_method (cfg, mono_method_check_context_used (cil_method), cil_method, MONO_RGCTX_INFO_METHOD);
+       args [0] = emit_get_rgctx_method (cfg, mono_method_check_context_used (caller), caller, MONO_RGCTX_INFO_METHOD);
+       args [1] = emit_get_rgctx_method (cfg, mono_method_check_context_used (callee), callee, MONO_RGCTX_INFO_METHOD);
 
        mono_emit_jit_icall (cfg, mono_throw_method_access, args);
 }
@@ -2975,11 +3008,18 @@ emit_write_barrier (MonoCompile *cfg, MonoInst *ptr, MonoInst *value)
                wbarrier->sreg1 = ptr->dreg;
                wbarrier->sreg2 = value->dreg;
                MONO_ADD_INS (cfg->cbb, wbarrier);
-       } else if (card_table && !cfg->compile_aot && !mono_gc_card_table_nursery_check ()) {
+       } else if (card_table) {
                int offset_reg = alloc_preg (cfg);
                int card_reg;
                MonoInst *ins;
 
+               /*
+                * We emit a fast light weight write barrier. This always marks cards as in the concurrent
+                * collector case, so, for the serial collector, it might slightly slow down nursery
+                * collections. We also expect that the host system and the target system have the same card
+                * table configuration, which is the case if they have the same pointer size.
+                */
+
                MONO_EMIT_NEW_BIALU_IMM (cfg, OP_SHR_UN_IMM, offset_reg, ptr->dreg, card_table_shift_bits);
                if (card_table_mask)
                        MONO_EMIT_NEW_BIALU_IMM (cfg, OP_PAND_IMM, offset_reg, offset_reg, card_table_mask);
@@ -3013,24 +3053,11 @@ mono_emit_wb_aware_memcpy (MonoCompile *cfg, MonoClass *klass, MonoInst *iargs[4
        if (align < SIZEOF_VOID_P)
                return FALSE;
 
-       /*This value cannot be bigger than 32 due to the way we calculate the required wb bitmap.*/
-       if (size > 32 * SIZEOF_VOID_P)
+       if (size > 5 * SIZEOF_VOID_P)
                return FALSE;
 
        create_write_barrier_bitmap (cfg, klass, &need_wb, 0);
 
-       /* We don't unroll more than 5 stores to avoid code bloat. */
-       if (size > 5 * SIZEOF_VOID_P) {
-               /*This is harmless and simplify mono_gc_wbarrier_value_copy_bitmap */
-               size += (SIZEOF_VOID_P - 1);
-               size &= ~(SIZEOF_VOID_P - 1);
-
-               EMIT_NEW_ICONST (cfg, iargs [2], size);
-               EMIT_NEW_ICONST (cfg, iargs [3], need_wb);
-               mono_emit_jit_icall (cfg, mono_gc_wbarrier_value_copy_bitmap, iargs);
-               return TRUE;
-       }
-
        destreg = iargs [0]->dreg;
        srcreg = iargs [1]->dreg;
        offset = 0;
@@ -3124,6 +3151,8 @@ mini_emit_stobj (MonoCompile *cfg, MonoInst *dest, MonoInst *src, MonoClass *kla
        else
                n = mono_class_value_size (klass, &align);
 
+       if (!align)
+               align = SIZEOF_VOID_P;
        /* if native is true there should be no references in the struct */
        if (cfg->gen_write_barriers && (klass->has_references || size_ins) && !native) {
                /* Avoid barriers when storing to the stack */
@@ -3139,19 +3168,27 @@ mini_emit_stobj (MonoCompile *cfg, MonoInst *dest, MonoInst *src, MonoClass *kla
                        /* It's ok to intrinsify under gsharing since shared code types are layout stable. */
                        if (!size_ins && (cfg->opt & MONO_OPT_INTRINS) && mono_emit_wb_aware_memcpy (cfg, klass, iargs, n, align)) {
                                return;
-                       } else if (context_used) {
-                               iargs [2] = mini_emit_get_rgctx_klass (cfg, context_used, klass, MONO_RGCTX_INFO_KLASS);
-                       }  else {
-                               iargs [2] = emit_runtime_constant (cfg, MONO_PATCH_INFO_CLASS, klass);
-                               if (!cfg->compile_aot)
-                                       mono_class_compute_gc_descriptor (klass);
-                       }
+                       } else if (size_ins || align < SIZEOF_VOID_P) {
+                               if (context_used) {
+                                       iargs [2] = mini_emit_get_rgctx_klass (cfg, context_used, klass, MONO_RGCTX_INFO_KLASS);
+                               }  else {
+                                       iargs [2] = emit_runtime_constant (cfg, MONO_PATCH_INFO_CLASS, klass);
+                                       if (!cfg->compile_aot)
+                                               mono_class_compute_gc_descriptor (klass);
+                               }
+                               if (size_ins)
+                                       mono_emit_jit_icall (cfg, mono_gsharedvt_value_copy, iargs);
+                               else
+                                       mono_emit_jit_icall (cfg, mono_value_copy, iargs);
+                       } else {
+                               /* We don't unroll more than 5 stores to avoid code bloat. */
+                               /*This is harmless and simplify mono_gc_get_range_copy_func */
+                               n += (SIZEOF_VOID_P - 1);
+                               n &= ~(SIZEOF_VOID_P - 1);
 
-                       if (size_ins)
-                               mono_emit_jit_icall (cfg, mono_gsharedvt_value_copy, iargs);
-                       else
-                               mono_emit_jit_icall (cfg, mono_value_copy, iargs);
-                       return;
+                               EMIT_NEW_ICONST (cfg, iargs [2], n);
+                               mono_emit_jit_icall (cfg, mono_gc_get_range_copy_func (), iargs);
+                       }
                }
        }
 
@@ -3254,6 +3291,16 @@ emit_get_rgctx (MonoCompile *cfg, MonoMethod *method, int context_used)
                mrgctx_loc = mono_get_vtable_var (cfg);
                EMIT_NEW_TEMPLOAD (cfg, mrgctx_var, mrgctx_loc->inst_c0);
 
+               return mrgctx_var;
+       } else if (MONO_CLASS_IS_INTERFACE (cfg->method->klass)) {
+               MonoInst *mrgctx_loc, *mrgctx_var;
+
+               /* Default interface methods need an mrgctx since the vtabke at runtime points at an implementing class */
+               mrgctx_loc = mono_get_vtable_var (cfg);
+               EMIT_NEW_TEMPLOAD (cfg, mrgctx_var, mrgctx_loc->inst_c0);
+
+               g_assert (mono_method_needs_static_rgctx_invoke (cfg->method, TRUE));
+
                return mrgctx_var;
        } else if (method->flags & METHOD_ATTRIBUTE_STATIC || method->klass->valuetype) {
                MonoInst *vtable_loc, *vtable_var;
@@ -3680,13 +3727,12 @@ mini_save_cast_details (MonoCompile *cfg, MonoClass *klass, int obj_reg, gboolea
                        MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_PBEQ, is_null_bb);
                }
 
-               tls_get = mono_get_jit_tls_intrinsic (cfg);
+               tls_get = mono_create_tls_get (cfg, TLS_KEY_JIT_TLS);
                if (!tls_get) {
                        fprintf (stderr, "error: --debug=casts not supported on this platform.\n.");
                        exit (1);
                }
 
-               MONO_ADD_INS (cfg->cbb, tls_get);
                MONO_EMIT_NEW_LOAD_MEMBASE (cfg, vtable_reg, obj_reg, MONO_STRUCT_OFFSET (MonoObject, vtable));
                MONO_EMIT_NEW_LOAD_MEMBASE (cfg, klass_reg, vtable_reg, MONO_STRUCT_OFFSET (MonoVTable, klass));
 
@@ -3714,9 +3760,7 @@ mini_reset_cast_details (MonoCompile *cfg)
 {
        /* Reset the variables holding the cast details */
        if (mini_get_debug_options ()->better_cast_details) {
-               MonoInst *tls_get = mono_get_jit_tls_intrinsic (cfg);
-
-               MONO_ADD_INS (cfg->cbb, tls_get);
+               MonoInst *tls_get = mono_create_tls_get (cfg, TLS_KEY_JIT_TLS);
                /* It is enough to reset the from field */
                MONO_EMIT_NEW_STORE_MEMBASE_IMM (cfg, OP_STORE_MEMBASE_IMM, tls_get->dreg, MONO_STRUCT_OFFSET (MonoJitTlsData, class_cast_from), 0);
        }
@@ -4411,7 +4455,7 @@ handle_constrained_gsharedvt_call (MonoCompile *cfg, MonoMethod *cmethod, MonoMe
         * pack the arguments into an array, and do the rest of the work in in an icall.
         */
        if (((cmethod->klass == mono_defaults.object_class) || mono_class_is_interface (cmethod->klass) || (!cmethod->klass->valuetype && cmethod->klass->image != mono_defaults.corlib)) &&
-               (MONO_TYPE_IS_VOID (fsig->ret) || MONO_TYPE_IS_PRIMITIVE (fsig->ret) || MONO_TYPE_IS_REFERENCE (fsig->ret) || MONO_TYPE_ISSTRUCT (fsig->ret) || mini_is_gsharedvt_type (fsig->ret)) &&
+               (MONO_TYPE_IS_VOID (fsig->ret) || MONO_TYPE_IS_PRIMITIVE (fsig->ret) || MONO_TYPE_IS_REFERENCE (fsig->ret) || MONO_TYPE_ISSTRUCT (fsig->ret) || mono_class_is_enum (mono_class_from_mono_type (fsig->ret)) || mini_is_gsharedvt_type (fsig->ret)) &&
                (fsig->param_count == 0 || (!fsig->hasthis && fsig->param_count == 1) || (fsig->param_count == 1 && (MONO_TYPE_IS_REFERENCE (fsig->params [0]) || fsig->params [0]->byref || mini_is_gsharedvt_type (fsig->params [0]))))) {
                MonoInst *args [16];
 
@@ -4463,7 +4507,7 @@ handle_constrained_gsharedvt_call (MonoCompile *cfg, MonoMethod *cmethod, MonoMe
 
                if (mini_is_gsharedvt_type (fsig->ret)) {
                        ins = handle_unbox_gsharedvt (cfg, mono_class_from_mono_type (fsig->ret), ins);
-               } else if (MONO_TYPE_IS_PRIMITIVE (fsig->ret) || MONO_TYPE_ISSTRUCT (fsig->ret)) {
+               } else if (MONO_TYPE_IS_PRIMITIVE (fsig->ret) || MONO_TYPE_ISSTRUCT (fsig->ret) || mono_class_is_enum (mono_class_from_mono_type (fsig->ret))) {
                        MonoInst *add;
 
                        /* Unbox */
@@ -4555,9 +4599,11 @@ mono_method_check_inlining (MonoCompile *cfg, MonoMethod *method)
        /* also consider num_locals? */
        /* Do the size check early to avoid creating vtables */
        if (!inline_limit_inited) {
-               if (g_getenv ("MONO_INLINELIMIT"))
-                       inline_limit = atoi (g_getenv ("MONO_INLINELIMIT"));
-               else
+               char *inlinelimit;
+               if ((inlinelimit = g_getenv ("MONO_INLINELIMIT"))) {
+                       inline_limit = atoi (inlinelimit);
+                       g_free (inlinelimit);
+               } else
                        inline_limit = INLINE_LENGTH_LIMIT;
                inline_limit_inited = TRUE;
        }
@@ -4691,7 +4737,11 @@ mini_emit_ldelema_1_ins (MonoCompile *cfg, MonoClass *klass, MonoInst *arr, Mono
 #if SIZEOF_REGISTER == 8
        /* The array reg is 64 bits but the index reg is only 32 */
        if (COMPILE_LLVM (cfg)) {
-               /* Not needed */
+               /*
+                * abcrem can't handle the OP_SEXT_I4, so add this after abcrem,
+                * during OP_BOUNDS_CHECK decomposition, and in the implementation
+                * of OP_X86_LEA for llvm.
+                */
                index2_reg = index_reg;
        } else {
                index2_reg = alloc_preg (cfg);
@@ -4857,18 +4907,18 @@ static MonoBreakPolicyFunc break_policy_func = always_insert_breakpoint;
 
 /**
  * mono_set_break_policy:
- * policy_callback: the new callback function
+ * \param policy_callback the new callback function
  *
  * Allow embedders to decide wherther to actually obey breakpoint instructions
- * (both break IL instructions and Debugger.Break () method calls), for example
+ * (both break IL instructions and \c Debugger.Break method calls), for example
  * to not allow an app to be aborted by a perfectly valid IL opcode when executing
  * untrusted or semi-trusted code.
  *
- * @policy_callback will be called every time a break point instruction needs to
- * be inserted with the method argument being the method that calls Debugger.Break()
- * or has the IL break instruction. The callback should return #MONO_BREAK_POLICY_NEVER
+ * \p policy_callback will be called every time a break point instruction needs to
+ * be inserted with the method argument being the method that calls \c Debugger.Break
+ * or has the IL \c break instruction. The callback should return \c MONO_BREAK_POLICY_NEVER
  * if it wants the breakpoint to not be effective in the given method.
- * #MONO_BREAK_POLICY_ALWAYS is the default.
+ * \c MONO_BREAK_POLICY_ALWAYS is the default.
  */
 void
 mono_set_break_policy (MonoBreakPolicyFunc policy_callback)
@@ -5202,8 +5252,7 @@ static MonoInst*
 mini_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args)
 {
        MonoInst *ins = NULL;
-
-        MonoClass *runtime_helpers_class = mono_class_get_runtime_helpers_class ();
+       MonoClass *runtime_helpers_class = mono_class_get_runtime_helpers_class ();
 
        if (cmethod->klass == mono_defaults.string_class) {
                if (strcmp (cmethod->name, "get_Chars") == 0 && fsig->param_count + fsig->hasthis == 2) {
@@ -5349,6 +5398,37 @@ mini_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSign
        } else if (cmethod->klass == runtime_helpers_class) {
                if (strcmp (cmethod->name, "get_OffsetToStringData") == 0 && fsig->param_count == 0) {
                        EMIT_NEW_ICONST (cfg, ins, MONO_STRUCT_OFFSET (MonoString, chars));
+                       return ins;
+               } else if (strcmp (cmethod->name, "IsReferenceOrContainsReferences") == 0 && fsig->param_count == 0) {
+                       MonoGenericContext *ctx = mono_method_get_context (cmethod);
+                       g_assert (ctx);
+                       g_assert (ctx->method_inst);
+                       g_assert (ctx->method_inst->type_argc == 1);
+                       MonoType *t = mini_get_underlying_type (ctx->method_inst->type_argv [0]);
+                       MonoClass *klass = mono_class_from_mono_type (t);
+
+                       ins = NULL;
+
+                       mono_class_init (klass);
+                       if (MONO_TYPE_IS_REFERENCE (t))
+                               EMIT_NEW_ICONST (cfg, ins, 1);
+                       else if (MONO_TYPE_IS_PRIMITIVE (t))
+                               EMIT_NEW_ICONST (cfg, ins, 0);
+                       else if (cfg->gshared && (t->type == MONO_TYPE_VAR || t->type == MONO_TYPE_MVAR) && !mini_type_var_is_vt (t))
+                               EMIT_NEW_ICONST (cfg, ins, 1);
+                       else if (!cfg->gshared || !mini_class_check_context_used (cfg, klass))
+                               EMIT_NEW_ICONST (cfg, ins, klass->has_references ? 1 : 0);
+                       else {
+                               g_assert (cfg->gshared);
+
+                               int context_used = mini_class_check_context_used (cfg, klass);
+
+                               /* This returns 1 or 2 */
+                               MonoInst *info = mini_emit_get_rgctx_klass (cfg, context_used, klass,   MONO_RGCTX_INFO_CLASS_IS_REF_OR_CONTAINS_REFS);
+                               int dreg = alloc_ireg (cfg);
+                               EMIT_NEW_BIALU_IMM (cfg, ins, OP_ISUB_IMM, dreg, info->dreg, 1);
+                       }
+
                        return ins;
                } else
                        return NULL;
@@ -5375,7 +5455,7 @@ mini_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSign
                        ins = mono_emit_jit_icall (cfg, is_v4 ? (gpointer)mono_monitor_enter_v4_fast : (gpointer)mono_monitor_enter_fast, args);
                        MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ICOMPARE_IMM, -1, ins->dreg, 0);
                        MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_IBNE_UN, end_bb);
-                       ins = mono_emit_jit_icall (cfg, is_v4 ? (gpointer)mono_monitor_enter_v4 : (gpointer)mono_monitor_enter, args);
+                       ins = mono_emit_jit_icall (cfg, is_v4 ? (gpointer)mono_monitor_enter_v4_internal : (gpointer)mono_monitor_enter_internal, args);
                        MONO_START_BB (cfg, end_bb);
                        return ins;
                }
@@ -6460,7 +6540,8 @@ inline_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig,
                 * Get rid of the begin and end bblocks if possible to aid local
                 * optimizations.
                 */
-               mono_merge_basic_blocks (cfg, prev_cbb, sbblock);
+               if (prev_cbb->out_count == 1)
+                       mono_merge_basic_blocks (cfg, prev_cbb, sbblock);
 
                if ((prev_cbb->out_count == 1) && (prev_cbb->out_bb [0]->in_count == 1) && (prev_cbb->out_bb [0] != ebblock))
                        mono_merge_basic_blocks (cfg, prev_cbb, prev_cbb->out_bb [0]);
@@ -6668,7 +6749,7 @@ mini_get_method_allow_open (MonoMethod *m, guint32 token, MonoClass *klass, Mono
 {
        MonoMethod *method;
 
-       mono_error_init (error);
+       error_init (error);
 
        if (m->wrapper_type != MONO_WRAPPER_NONE) {
                method = (MonoMethod *)mono_method_get_wrapper_data (m, token);
@@ -6725,7 +6806,7 @@ mini_get_signature (MonoMethod *method, guint32 token, MonoGenericContext *conte
 {
        MonoMethodSignature *fsig;
 
-       mono_error_init (error);
+       error_init (error);
        if (method->wrapper_type != MONO_WRAPPER_NONE) {
                fsig = (MonoMethodSignature *)mono_method_get_wrapper_data (method, token);
        } else {
@@ -6835,14 +6916,12 @@ initialize_array_data (MonoMethod *method, gboolean aot, unsigned char *ip, Mono
                        return NULL;
                if (strcmp (cmethod->name, "InitializeArray") || strcmp (cmethod->klass->name, "RuntimeHelpers") || cmethod->klass->image != mono_defaults.corlib)
                        return NULL;
-               switch (mono_type_get_underlying_type (&klass->byval_arg)->type) {
-               case MONO_TYPE_BOOLEAN:
+               switch (mini_get_underlying_type (&klass->byval_arg)->type) {
                case MONO_TYPE_I1:
                case MONO_TYPE_U1:
                        size = 1; break;
                /* we need to swap on big endian, so punt. Should we handle R4 and R8 as well? */
 #if TARGET_BYTE_ORDER == G_LITTLE_ENDIAN
-               case MONO_TYPE_CHAR:
                case MONO_TYPE_I2:
                case MONO_TYPE_U2:
                        size = 2; break;
@@ -6963,6 +7042,7 @@ emit_llvmonly_virtual_call (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSig
        gboolean variant_iface = FALSE;
        guint32 slot;
        int offset;
+       gboolean special_array_interface = cmethod->klass->is_array_special_interface;
 
        /*
         * In llvm-only mode, vtables contain function descriptors instead of
@@ -7021,7 +7101,7 @@ emit_llvmonly_virtual_call (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSig
                return emit_extra_arg_calli (cfg, fsig, sp, arg_reg, call_target);
        }
 
-       if (!fsig->generic_param_count && is_iface && !variant_iface && !is_gsharedvt) {
+       if (!fsig->generic_param_count && is_iface && !variant_iface && !is_gsharedvt && !special_array_interface) {
                /*
                 * A simple interface call
                 *
@@ -7060,7 +7140,7 @@ emit_llvmonly_virtual_call (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSig
                return emit_llvmonly_calli (cfg, fsig, sp, ftndesc_ins);
        }
 
-       if ((fsig->generic_param_count || variant_iface) && !is_gsharedvt) {
+       if ((fsig->generic_param_count || variant_iface || special_array_interface) && !is_gsharedvt) {
                /*
                 * This is similar to the interface case, the vtable slot points to an imt thunk which is
                 * dynamically extended as more instantiations are discovered.
@@ -7499,6 +7579,16 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                        mono_bitset_set_fast (seq_point_locs, sps [i].il_offset);
                        }
                        g_free (sps);
+
+                       MonoDebugMethodAsyncInfo* asyncMethod = mono_debug_lookup_method_async_debug_info (method);
+                       if (asyncMethod) {
+                               for (i = 0; asyncMethod != NULL && i < asyncMethod->num_awaits; i++)
+                               {
+                                       mono_bitset_set_fast (seq_point_locs, asyncMethod->resume_offsets[i]);
+                                       mono_bitset_set_fast (seq_point_locs, asyncMethod->yield_offsets[i]);
+                               }
+                               mono_debug_free_method_async_debug_info (asyncMethod);
+                       }
                } else if (!method->wrapper_type && !method->dynamic && mono_debug_image_has_debug_info (method->klass->image)) {
                        /* Methods without line number info like auto-generated property accessors */
                        seq_point_locs = mono_bitset_mem_new (mono_mempool_alloc0 (cfg->mempool, mono_bitset_alloc_size (header->code_size, 0)), header->code_size, 0);
@@ -8534,6 +8624,15 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                                CHECK_CFG_ERROR;
                                        }
                                }
+
+                               if (constrained_class->enumtype && !strcmp (cmethod->name, "GetHashCode")) {
+                                       /* Use the corresponding method from the base type to avoid boxing */
+                                       MonoType *base_type = mono_class_enum_basetype (constrained_class);
+                                       g_assert (base_type);
+                                       constrained_class = mono_class_from_mono_type (base_type);
+                                       cmethod = mono_class_get_method_from_name (constrained_class, cmethod->name, 0);
+                                       g_assert (cmethod);
+                               }
                        }
                                        
                        if (!dont_verify && !cfg->skip_visibility) {
@@ -8824,7 +8923,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                 * request a generic sharing context.
                                 */
                                if (context_used &&
-                                               ((method->flags & METHOD_ATTRIBUTE_STATIC) || method->klass->valuetype))
+                                               ((cfg->method->flags & METHOD_ATTRIBUTE_STATIC) || cfg->method->klass->valuetype))
                                        mono_get_vtable_var (cfg);
                        }
 
@@ -10802,7 +10901,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        is_special_static = mono_class_field_is_special_static (field);
 
                        if (is_special_static && ((gsize)addr & 0x80000000) == 0)
-                               thread_ins = mono_get_thread_intrinsic (cfg);
+                               thread_ins = mono_create_tls_get (cfg, TLS_KEY_THREAD);
                        else
                                thread_ins = NULL;
 
@@ -10816,9 +10915,9 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                guint32 offset;
                                int idx, static_data_reg, array_reg, dreg;
 
-                               GSHAREDVT_FAILURE (op);
+                               if (context_used && cfg->gsharedvt && mini_is_gsharedvt_klass (klass))
+                                       GSHAREDVT_FAILURE (op);
 
-                               MONO_ADD_INS (cfg->cbb, thread_ins);
                                static_data_reg = alloc_ireg (cfg);
                                MONO_EMIT_NEW_LOAD_MEMBASE (cfg, static_data_reg, thread_ins->dreg, MONO_STRUCT_OFFSET (MonoInternalThread, static_data));
 
@@ -11111,6 +11210,8 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
 
                        klass = mini_get_class (method, token, generic_context);
                        CHECK_TYPELOAD (klass);
+                       if (klass->byval_arg.type == MONO_TYPE_VOID)
+                               UNVERIFIED;
 
                        context_used = mini_class_check_context_used (cfg, klass);
 
@@ -11525,7 +11626,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                                        tclass, MONO_RGCTX_INFO_REFLECTION_TYPE);
                                        } else if (cfg->compile_aot) {
                                                if (method->wrapper_type) {
-                                                       mono_error_init (&error); //got to do it since there are multiple conditionals below
+                                                       error_init (&error); //got to do it since there are multiple conditionals below
                                                        if (mono_class_get_checked (tclass->image, tclass->type_token, &error) == tclass && !generic_context) {
                                                                /* Special case for static synchronized wrappers */
                                                                EMIT_NEW_TYPE_FROM_HANDLE_CONST (cfg, ins, tclass->image, tclass->type_token, generic_context);
@@ -11982,18 +12083,8 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                g_assert (key < TLS_KEY_NUM);
 
                                ins = mono_create_tls_get (cfg, key);
-                               if (!ins) {
-                                       if (cfg->compile_aot) {
-                                               DISABLE_AOT (cfg);
-                                               MONO_INST_NEW (cfg, ins, OP_TLS_GET);
-                                               ins->dreg = alloc_preg (cfg);
-                                               ins->type = STACK_PTR;
-                                       } else {
-                                               g_assert_not_reached ();
-                                       }
-                               }
+                               g_assert (ins);
                                ins->type = STACK_PTR;
-                               MONO_ADD_INS (cfg->cbb, ins);
                                *sp++ = ins;
                                ip += 6;
                                break;
@@ -12061,10 +12152,10 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                EMIT_NEW_PCONST (cfg, ins, NULL);
                                MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, cfg->orig_domain_var->dreg, ins->dreg);
 
-                               ad_ins = mono_get_domain_intrinsic (cfg);
-                               jit_tls_ins = mono_get_jit_tls_intrinsic (cfg);
+                               ad_ins = mono_create_tls_get (cfg, TLS_KEY_DOMAIN);
+                               jit_tls_ins = mono_create_tls_get (cfg, TLS_KEY_JIT_TLS);
 
-                               if (cfg->backend->have_tls_get && ad_ins && jit_tls_ins) {
+                               if (ad_ins && jit_tls_ins) {
                                        NEW_BBLOCK (cfg, next_bb);
                                        NEW_BBLOCK (cfg, call_bb);
 
@@ -12074,11 +12165,9 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                        } else {
                                                EMIT_NEW_PCONST (cfg, domain_ins, cfg->domain);
                                        }
-                                       MONO_ADD_INS (cfg->cbb, ad_ins);
                                        MONO_EMIT_NEW_BIALU (cfg, OP_COMPARE, -1, ad_ins->dreg, domain_ins->dreg);
                                        MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_PBNE_UN, call_bb);
 
-                                       MONO_ADD_INS (cfg->cbb, jit_tls_ins);
                                        MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, jit_tls_ins->dreg, 0);
                                        MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_PBEQ, call_bb);
 
@@ -12279,6 +12368,21 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                ins->type = STACK_I4;
                                MONO_ADD_INS (cfg->cbb, ins);
 
+                               ip += 2;
+                               *sp++ = ins;
+                               break;
+                       case CEE_MONO_GET_RGCTX_ARG:
+                               CHECK_OPSIZE (2);
+                               CHECK_STACK_OVF (1);
+
+                               mono_create_rgctx_var (cfg);
+
+                               MONO_INST_NEW (cfg, ins, OP_MOVE);
+                               ins->dreg = alloc_dreg (cfg, STACK_PTR);
+                               ins->sreg1 = cfg->rgctx_var->dreg;
+                               ins->type = STACK_PTR;
+                               MONO_ADD_INS (cfg->cbb, ins);
+
                                ip += 2;
                                *sp++ = ins;
                                break;
@@ -12877,11 +12981,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
 
                cfg->cbb = init_localsbb;
 
-               if ((get_domain = mono_get_domain_intrinsic (cfg))) {
-                       MONO_ADD_INS (cfg->cbb, get_domain);
-               } else {
-                       get_domain = mono_emit_jit_icall (cfg, mono_domain_get, NULL);
-               }
+               get_domain = mono_create_tls_get (cfg, TLS_KEY_DOMAIN);
                NEW_TEMPSTORE (cfg, store, cfg->domainvar->inst_c0, get_domain);
                MONO_ADD_INS (cfg->cbb, store);
        }
@@ -13771,7 +13871,7 @@ mono_spill_global_vars (MonoCompile *cfg, gboolean *need_local_opts)
        int orig_next_vreg;
        guint32 *vreg_to_lvreg;
        guint32 *lvregs;
-       guint32 i, lvregs_len;
+       guint32 i, lvregs_len, lvregs_size;
        gboolean dest_has_lvreg = FALSE;
        MonoStackType stacktypes [128];
        MonoInst **live_range_start, **live_range_end;
@@ -13844,7 +13944,8 @@ mono_spill_global_vars (MonoCompile *cfg, gboolean *need_local_opts)
         */
        orig_next_vreg = cfg->next_vreg;
        vreg_to_lvreg = (guint32 *)mono_mempool_alloc0 (cfg->mempool, sizeof (guint32) * cfg->next_vreg);
-       lvregs = (guint32 *)mono_mempool_alloc (cfg->mempool, sizeof (guint32) * 1024);
+       lvregs_size = 1024;
+       lvregs = (guint32 *)mono_mempool_alloc (cfg->mempool, sizeof (guint32) * lvregs_size);
        lvregs_len = 0;
 
        /* 
@@ -14227,7 +14328,12 @@ mono_spill_global_vars (MonoCompile *cfg, gboolean *need_local_opts)
                                                                }
                                                                g_assert (sreg != -1);
                                                                vreg_to_lvreg [var->dreg] = sreg;
-                                                               g_assert (lvregs_len < 1024);
+                                                               if (lvregs_len >= lvregs_size) {
+                                                                       guint32 *new_lvregs = mono_mempool_alloc0 (cfg->mempool, sizeof (guint32) * lvregs_size * 2);
+                                                                       memcpy (new_lvregs, lvregs, sizeof (guint32) * lvregs_size);
+                                                                       lvregs = new_lvregs;
+                                                                       lvregs_size *= 2;
+                                                               }
                                                                lvregs [lvregs_len ++] = var->dreg;
                                                        }
                                                }
@@ -14274,7 +14380,12 @@ mono_spill_global_vars (MonoCompile *cfg, gboolean *need_local_opts)
                        if (dest_has_lvreg) {
                                g_assert (ins->dreg != -1);
                                vreg_to_lvreg [prev_dreg] = ins->dreg;
-                               g_assert (lvregs_len < 1024);
+                               if (lvregs_len >= lvregs_size) {
+                                       guint32 *new_lvregs = mono_mempool_alloc0 (cfg->mempool, sizeof (guint32) * lvregs_size * 2);
+                                       memcpy (new_lvregs, lvregs, sizeof (guint32) * lvregs_size);
+                                       lvregs = new_lvregs;
+                                       lvregs_size *= 2;
+                               }
                                lvregs [lvregs_len ++] = prev_dreg;
                                dest_has_lvreg = FALSE;
                        }
@@ -14489,6 +14600,9 @@ NOTES
 
 #else /* !DISABLE_JIT */
 
-MONO_EMPTY_SOURCE_FILE (method_to_ir);
+void
+mono_set_break_policy (MonoBreakPolicyFunc policy_callback)
+{
+}
 
 #endif /* !DISABLE_JIT */