[sdb] Keep the exception object alive during debugger suspensions. Fixes #12494.
[mono.git] / mono / mini / mini.c
index a65f7f16af41b04f925d81ceda1a2574a47a1dcc..d43a63823b3975d51a06a6957acf6344db0d80bd 100644 (file)
@@ -54,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-path.h>
 #include <mono/utils/mono-tls.h>
 #include <mono/utils/dtrace.h>
 
@@ -155,6 +156,7 @@ mono_realloc_native_code (MonoCompile *cfg)
 
        /* Save the old alignment offset so we can re-align after the realloc. */
        old_padding = (guint)(cfg->native_code - cfg->native_code_alloc);
+       cfg->code_size = NACL_BUNDLE_ALIGN_UP (cfg->code_size);
 
        cfg->native_code_alloc = g_realloc ( cfg->native_code_alloc,
                                                                                 cfg->code_size + kNaClAlignment );
@@ -242,12 +244,14 @@ guint8 *mono_nacl_align(guint8 *code) {
 
 void mono_nacl_fix_patches(const guint8 *code, MonoJumpInfo *ji)
 {
+#ifndef USE_JUMP_TABLES
   MonoJumpInfo *patch_info;
   for (patch_info = ji; patch_info; patch_info = patch_info->next) {
     unsigned char *ip = patch_info->ip.i + code;
     ip = mono_arch_nacl_skip_nops(ip);
     patch_info->ip.i = ip - code;
   }
+#endif
 }
 #endif  /* __native_client_codegen__ */
 
@@ -462,6 +466,14 @@ void *mono_global_codeman_reserve (int size)
 }
 
 #if defined(__native_client_codegen__) && defined(__native_client__)
+void
+mono_nacl_gc()
+{
+#ifdef __native_client_gc__
+       __nacl_suspend_thread_if_needed();
+#endif
+}
+
 /* 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
@@ -962,6 +974,8 @@ mini_type_to_ldind (MonoCompile* cfg, MonoType *type)
        return mono_type_to_ldind (type);
 }
 
+#ifndef DISABLE_JIT
+
 guint
 mini_type_to_stind (MonoCompile* cfg, MonoType *type)
 {
@@ -976,8 +990,6 @@ mini_type_to_stind (MonoCompile* cfg, MonoType *type)
        return mono_type_to_stind (type);
 }
 
-#ifndef DISABLE_JIT
-
 int
 mono_op_imm_to_op (int opcode)
 {
@@ -1517,7 +1529,7 @@ mini_assembly_can_skip_verification (MonoDomain *domain, MonoMethod *method)
                return FALSE;
        if (assembly->in_gac || assembly->image == mono_defaults.corlib)
                return FALSE;
-       if (mono_security_get_mode () != MONO_SECURITY_MODE_NONE)
+       if (mono_security_enabled ())
                return FALSE;
        return mono_assembly_has_skip_verification (assembly);
 }
@@ -2292,8 +2304,8 @@ mono_find_jit_opcode_emulation (int opcode)
        return NULL;
 }
 
-void
-mono_register_opcode_emulation (int opcode, const char *name, const char *sigstr, gpointer func, gboolean no_throw)
+static void
+register_opcode_emulation (int opcode, const char *name, const char *sigstr, gpointer func, const char *symbol, gboolean no_throw)
 {
        MonoJitICallInfo *info;
        MonoMethodSignature *sig = mono_create_icall_signature (sigstr);
@@ -2301,7 +2313,7 @@ mono_register_opcode_emulation (int opcode, const char *name, const char *sigstr
        g_assert (!sig->hasthis);
        g_assert (sig->param_count < 3);
 
-       info = mono_register_jit_icall (func, name, sig, no_throw);
+       info = mono_register_jit_icall_full (func, name, sig, no_throw, symbol);
 
        if (emul_opcode_num >= emul_opcode_alloced) {
                int incr = emul_opcode_alloced? emul_opcode_alloced/2: 16;
@@ -2315,11 +2327,28 @@ mono_register_opcode_emulation (int opcode, const char *name, const char *sigstr
        emul_opcode_hit_cache [opcode >> (EMUL_HIT_SHIFT + 3)] |= (1 << (opcode & EMUL_HIT_MASK));
 }
 
+/*
+ * For JIT icalls implemented in C.
+ * NAME should be the same as the name of the C function whose address is FUNC.
+ */
 static void
 register_icall (gpointer func, const char *name, const char *sigstr, gboolean save)
 {
        MonoMethodSignature *sig;
 
+       if (sigstr)
+               sig = mono_create_icall_signature (sigstr);
+       else
+               sig = NULL;
+
+       mono_register_jit_icall_full (func, name, sig, save, save ? name : NULL);
+}
+
+static void
+register_dyn_icall (gpointer func, const char *name, const char *sigstr, gboolean save)
+{
+       MonoMethodSignature *sig;
+
        if (sigstr)
                sig = mono_create_icall_signature (sigstr);
        else
@@ -2582,7 +2611,8 @@ mono_get_lmf_addr (void)
 #else
        MonoJitTlsData *jit_tls;
 
-       if ((jit_tls = mono_native_tls_get_value (mono_jit_tls_id)))
+       jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
+       if (G_LIKELY (jit_tls))
                return &jit_tls->lmf;
 
        /*
@@ -2730,6 +2760,10 @@ setup_jit_tls_data (gpointer stack_start, gpointer abort_func)
        jit_tls->lmf = lmf;
 #endif
 
+#ifdef MONO_ARCH_HAVE_TLS_INIT
+       mono_arch_tls_init ();
+#endif
+
        mono_setup_altstack (jit_tls);
 
        return jit_tls;
@@ -2957,19 +2991,42 @@ mono_patch_info_hash (gconstpointer data)
        case MONO_PATCH_INFO_IID:
        case MONO_PATCH_INFO_ADJUSTED_IID:
        case MONO_PATCH_INFO_CLASS_INIT:
+       case MONO_PATCH_INFO_GENERIC_CLASS_INIT:
        case MONO_PATCH_INFO_METHODCONST:
        case MONO_PATCH_INFO_METHOD:
        case MONO_PATCH_INFO_METHOD_JUMP:
        case MONO_PATCH_INFO_IMAGE:
        case MONO_PATCH_INFO_JIT_ICALL_ADDR:
+       case MONO_PATCH_INFO_ICALL_ADDR:
        case MONO_PATCH_INFO_FIELD:
        case MONO_PATCH_INFO_SFLDA:
        case MONO_PATCH_INFO_SEQ_POINT_INFO:
+       case MONO_PATCH_INFO_METHOD_RGCTX:
+       case MONO_PATCH_INFO_DELEGATE_TRAMPOLINE:
+       case MONO_PATCH_INFO_SIGNATURE:
                return (ji->type << 8) | (gssize)ji->data.target;
        case MONO_PATCH_INFO_GSHAREDVT_CALL:
                return (ji->type << 8) | (gssize)ji->data.gsharedvt->method;
-       default:
+       case MONO_PATCH_INFO_RGCTX_FETCH: {
+               MonoJumpInfoRgctxEntry *e = ji->data.rgctx_entry;
+
+               return (ji->type << 8) | (gssize)e->method | (e->in_mrgctx) | e->info_type | mono_patch_info_hash (e->data);
+       }
+       case MONO_PATCH_INFO_INTERRUPTION_REQUEST_FLAG:
+       case MONO_PATCH_INFO_MSCORLIB_GOT_ADDR:
+       case MONO_PATCH_INFO_GC_CARD_TABLE_ADDR:
+       case MONO_PATCH_INFO_JIT_TLS_ID:
+       case MONO_PATCH_INFO_MONITOR_ENTER:
+       case MONO_PATCH_INFO_MONITOR_EXIT:
+       case MONO_PATCH_INFO_CASTCLASS_CACHE:
                return (ji->type << 8);
+       case MONO_PATCH_INFO_SWITCH:
+               return (ji->type << 8) | ji->data.table->table_size;
+       default:
+               printf ("info type: %d\n", ji->type);
+               mono_print_ji (ji); printf ("\n");
+               g_assert_not_reached ();
+               return 0;
        }
 }
 
@@ -3067,28 +3124,45 @@ mono_resolve_patch_target (MonoMethod *method, MonoDomain *domain, guint8 *code,
                target = mono_icall_get_wrapper (mi);
                break;
        }
+       case MONO_PATCH_INFO_JIT_ICALL_ADDR: {
+               MonoJitICallInfo *mi = mono_find_jit_icall_by_name (patch_info->data.name);
+               if (!mi) {
+                       g_warning ("unknown MONO_PATCH_INFO_JIT_ICALL_ADDR %s", patch_info->data.name);
+                       g_assert_not_reached ();
+               }
+               target = mi->func;
+               break;
+       }
        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)
+# 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
 #endif
                break;
        case MONO_PATCH_INFO_METHOD:
+#if defined(__native_client_codegen__) && defined(USE_JUMP_TABLES)
+               /*
+                * If we use jumptables, for recursive calls we cannot
+                * avoid trampoline, as we not yet know where we will
+                * be installed.
+                */
+               target = mono_create_jit_trampoline_in_domain (domain, patch_info->data.method);
+#else
                if (patch_info->data.method == method) {
                        target = code;
                } else {
                        /* get the trampoline to the method from the domain */
                        target = mono_create_jit_trampoline_in_domain (domain, patch_info->data.method);
                }
+#endif
                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                 */
@@ -3218,7 +3292,7 @@ mono_resolve_patch_target (MonoMethod *method, MonoDomain *domain, guint8 *code,
                MonoClass *handle_class;
                
                handle = mono_ldtoken (patch_info->data.token->image,
-                                      patch_info->data.token->token, &handle_class, NULL);
+                                                          patch_info->data.token->token, &handle_class, patch_info->data.token->has_context ? &patch_info->data.token->context : NULL);
                mono_class_init (handle_class);
                
                target = handle;
@@ -3250,15 +3324,6 @@ mono_resolve_patch_target (MonoMethod *method, MonoDomain *domain, guint8 *code,
                                g_error ("Unregistered icall '%s'\n", mono_method_full_name (patch_info->data.method, TRUE));
                }
                break;
-       case MONO_PATCH_INFO_JIT_ICALL_ADDR: {
-               MonoJitICallInfo *mi = mono_find_jit_icall_by_name (patch_info->data.name);
-               if (!mi) {
-                       g_warning ("unknown MONO_PATCH_INFO_JIT_ICALL_ADDR %s", patch_info->data.name);
-                       g_assert_not_reached ();
-               }
-               target = mi->func;
-               break;
-       }
        case MONO_PATCH_INFO_INTERRUPTION_REQUEST_FLAG:
                target = mono_thread_interruption_request_flag ();
                break;
@@ -3344,6 +3409,10 @@ mono_resolve_patch_target (MonoMethod *method, MonoDomain *domain, guint8 *code,
                target = mono_domain_alloc0 (domain, sizeof (gpointer));
                break;
        }
+       case MONO_PATCH_INFO_JIT_TLS_ID: {
+               target = (gpointer) (size_t) mono_jit_tls_id;
+               break;
+       }
        default:
                g_assert_not_reached ();
        }
@@ -3356,8 +3425,10 @@ mono_add_seq_point (MonoCompile *cfg, MonoBasicBlock *bb, MonoInst *ins, int nat
 {
        ins->inst_offset = native_offset;
        g_ptr_array_add (cfg->seq_points, ins);
-       bb->seq_points = g_slist_prepend_mempool (cfg->mempool, bb->seq_points, ins);
-       bb->last_seq_point = ins;
+       if (bb) {
+               bb->seq_points = g_slist_prepend_mempool (cfg->mempool, bb->seq_points, ins);
+               bb->last_seq_point = ins;
+       }
 }
 
 void
@@ -3468,27 +3539,14 @@ mono_postprocess_patches (MonoCompile *cfg)
                         */
                        if (info) {
                                //printf ("TEST %s %p\n", info->name, patch_info->data.target);
-                               // FIXME: CLEAN UP THIS MESS.
-                               if ((cfg->method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE) && 
-                                       strstr (cfg->method->name, info->name)) {
-                                       /*
-                                        * This is an icall wrapper, and this is a call to the
-                                        * wrapped function.
-                                        */
-                                       if (cfg->compile_aot) {
-                                               patch_info->type = MONO_PATCH_INFO_JIT_ICALL_ADDR;
-                                               patch_info->data.name = info->name;
-                                       }
-                               } else {
-                                       /* for these array methods we currently register the same function pointer
-                                        * since it's a vararg function. But this means that mono_find_jit_icall_by_addr ()
-                                        * will return the incorrect one depending on the order they are registered.
-                                        * See tests/test-arr.cs
-                                        */
-                                       if (strstr (info->name, "ves_array_new_va_") == NULL && strstr (info->name, "ves_array_element_address_") == NULL) {
-                                               patch_info->type = MONO_PATCH_INFO_INTERNAL_METHOD;
-                                               patch_info->data.name = info->name;
-                                       }
+                               /* for these array methods we currently register the same function pointer
+                                * since it's a vararg function. But this means that mono_find_jit_icall_by_addr ()
+                                * will return the incorrect one depending on the order they are registered.
+                                * See tests/test-arr.cs
+                                */
+                               if (strstr (info->name, "ves_array_new_va_") == NULL && strstr (info->name, "ves_array_element_address_") == NULL) {
+                                       patch_info->type = MONO_PATCH_INFO_INTERNAL_METHOD;
+                                       patch_info->data.name = info->name;
                                }
                        }
 
@@ -3628,6 +3686,8 @@ mono_save_seq_point_info (MonoCompile *cfg)
                        if (ins->inst_imm == METHOD_ENTRY_IL_OFFSET || ins->inst_imm == METHOD_EXIT_IL_OFFSET)
                                /* Used to implement method entry/exit events */
                                continue;
+                       if (ins->inst_offset == SEQ_POINT_NATIVE_OFFSET_DEAD_CODE)
+                               continue;
 
                        if (last != NULL) {
                                /* Link with the previous seq point in the same bb */
@@ -3795,6 +3855,9 @@ mono_codegen (MonoCompile *cfg)
 
        /* we always allocate code in cfg->domain->code_mp to increase locality */
        cfg->code_size = cfg->code_len + max_epilog_size;
+#ifdef __native_client_codegen__
+       cfg->code_size = NACL_BUNDLE_ALIGN_UP (cfg->code_size);
+#endif
        /* fixme: align to MONO_ARCH_CODE_ALIGNMENT */
 
        if (cfg->method->dynamic) {
@@ -4020,7 +4083,7 @@ create_jit_info (MonoCompile *cfg, MonoMethod *method_to_compile)
                        printf ("Number of try block holes %d\n", num_holes);
        }
 
-       if (mono_method_has_declsec (cfg->method_to_register)) {
+       if (mono_security_method_has_declsec (cfg->method_to_register)) {
                cas_size = sizeof (MonoMethodCasInfo);
        }
 
@@ -4337,6 +4400,21 @@ is_gsharedvt_method (MonoMethod *method)
        return FALSE;
 }
 
+static gboolean
+is_open_method (MonoMethod *method)
+{
+       MonoGenericContext *context;
+
+       if (!method->is_inflated)
+               return FALSE;
+       context = mono_method_get_context (method);
+       if (context->class_inst && context->class_inst->is_open)
+               return TRUE;
+       if (context->method_inst && context->method_inst->is_open)
+               return TRUE;
+       return FALSE;
+}
+
 static gboolean
 has_ref_constraint (MonoGenericParamInfo *info)
 {
@@ -4402,7 +4480,7 @@ mini_get_shared_method_full (MonoMethod *method, gboolean all_vt, gboolean is_gs
        gboolean gsharedvt = FALSE;
        MonoGenericContainer *class_container, *method_container = NULL;
 
-       if (method->is_generic || method->klass->generic_container) {
+       if (method->is_generic || (method->klass->generic_container && !method->is_inflated)) {
                declaring_method = method;
        } else {
                declaring_method = mono_method_get_declaring_generic_method (method);
@@ -4414,12 +4492,14 @@ mini_get_shared_method_full (MonoMethod *method, gboolean all_vt, gboolean is_gs
                shared_context = declaring_method->klass->generic_container->context;
 
        /* Handle gsharedvt/partial sharing */
-       if ((method != declaring_method && method->is_inflated && !mono_method_is_generic_sharable_impl_full (method, FALSE, FALSE, TRUE)) ||
+       if ((method != declaring_method && method->is_inflated && !mono_method_is_generic_sharable_full (method, FALSE, FALSE, TRUE)) ||
                is_gsharedvt || mini_is_gsharedvt_sharable_method (method)) {
                MonoGenericContext *context = mono_method_get_context (method);
                MonoGenericInst *inst;
 
-               gsharedvt = is_gsharedvt || mini_is_gsharedvt_sharable_method (method);
+               partial = mono_method_is_generic_sharable_full (method, FALSE, TRUE, FALSE);
+
+               gsharedvt = is_gsharedvt || (!partial && mini_is_gsharedvt_sharable_method (method));
 
                class_container = declaring_method->klass->generic_container;
                method_container = mono_method_get_generic_container (declaring_method);
@@ -4428,7 +4508,6 @@ mini_get_shared_method_full (MonoMethod *method, gboolean all_vt, gboolean is_gs
                 * Create the shared context by replacing the ref type arguments with
                 * type parameters, and keeping the rest.
                 */
-               partial = TRUE;
                if (context)
                        inst = context->class_inst;
                else
@@ -4442,6 +4521,8 @@ mini_get_shared_method_full (MonoMethod *method, gboolean all_vt, gboolean is_gs
                        inst = shared_context.method_inst;
                if (inst)
                        shared_context.method_inst = get_shared_inst (inst, shared_context.method_inst, method_container, all_vt, gsharedvt);
+
+               partial = TRUE;
        }
 
     res = mono_class_inflate_generic_method (declaring_method, &shared_context);
@@ -4530,10 +4611,10 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, gbool
                 * FIXME: Remove the method->klass->generic_class limitation.
                 */
                try_generic_shared = mono_class_generic_sharing_enabled (method->klass) &&
-                       (opts & MONO_OPT_GSHARED) && ((method->is_generic || method->klass->generic_container) || (!method->klass->generic_class && mono_method_is_generic_sharable_impl_full (method, TRUE, FALSE, FALSE)));
+                       (opts & MONO_OPT_GSHARED) && ((method->is_generic || method->klass->generic_container) || (!method->klass->generic_class && mono_method_is_generic_sharable_full (method, TRUE, FALSE, FALSE)));
        else
                try_generic_shared = mono_class_generic_sharing_enabled (method->klass) &&
-                       (opts & MONO_OPT_GSHARED) && mono_method_is_generic_sharable_impl_full (method, FALSE, FALSE, TRUE);
+                       (opts & MONO_OPT_GSHARED) && mono_method_is_generic_sharable (method, FALSE);
 
        if (opts & MONO_OPT_GSHARED) {
                if (try_generic_shared)
@@ -4549,7 +4630,7 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, gbool
                        try_generic_shared = FALSE;
        }
 
-       if (is_gsharedvt_method (method)) {
+       if (is_gsharedvt_method (method) || (compile_aot && is_open_method (method))) {
                /* We are AOTing a gshared method directly */
                method_is_gshared = TRUE;
                g_assert (compile_aot);
@@ -5401,7 +5482,7 @@ lookup_method_inner (MonoDomain *domain, MonoMethod *method)
        if (ji)
                return ji;
 
-       if (!mono_method_is_generic_sharable_impl_full (method, FALSE, FALSE, TRUE))
+       if (!mono_method_is_generic_sharable (method, FALSE))
                return NULL;
        return mono_domain_lookup_shared_generic (domain, method);
 }
@@ -5657,6 +5738,7 @@ mono_jit_compile_method_inner (MonoMethod *method, MonoDomain *target_domain, in
        case MONO_EXCEPTION_FIELD_ACCESS:
                ex = mono_exception_from_name_msg (mono_defaults.corlib, "System", "FieldAccessException", cfg->exception_message);
                break;
+#ifndef DISABLE_SECURITY
        /* this can only be set if the security manager is active */
        case MONO_EXCEPTION_SECURITY_LINKDEMAND: {
                MonoSecurityManager* secman = mono_security_manager_get_methods ();
@@ -5670,6 +5752,7 @@ mono_jit_compile_method_inner (MonoMethod *method, MonoDomain *target_domain, in
                ex = (MonoException*)exc;
                break;
        }
+#endif
        case MONO_EXCEPTION_OBJECT_SUPPLIED: {
                MonoException *exp = cfg->exception_ptr;
                MONO_GC_UNREGISTER_ROOT (cfg->exception_ptr);
@@ -5716,7 +5799,7 @@ mono_jit_compile_method_inner (MonoMethod *method, MonoDomain *target_domain, in
                mono_domain_jit_code_hash_unlock (target_domain);
                code = cfg->native_code;
 
-               if (cfg->generic_sharing_context && mono_method_is_generic_sharable_impl_full (method, FALSE, FALSE, TRUE))
+               if (cfg->generic_sharing_context && mono_method_is_generic_sharable (method, FALSE))
                        mono_stats.generics_shared_methods++;
                if (cfg->gsharedvt)
                        mono_stats.gsharedvt_methods++;
@@ -5758,8 +5841,15 @@ mono_jit_compile_method_inner (MonoMethod *method, MonoDomain *target_domain, in
                        patch_info.data.method = method;
                        g_hash_table_remove (domain_jit_info (target_domain)->jump_target_hash, method);
 
+#if defined(__native_client_codegen__) && defined(__native_client__)
+                       /* These patches are applied after a method has been installed, no target munging is needed. */
+                       nacl_allow_target_modification (FALSE);
+#endif
                        for (tmp = jlist->list; tmp; tmp = tmp->next)
                                mono_arch_patch_code (NULL, target_domain, tmp->data, &patch_info, NULL, TRUE);
+#if defined(__native_client_codegen__) && defined(__native_client__)
+                       nacl_allow_target_modification (TRUE);
+#endif
                }
        }
 
@@ -5805,17 +5895,16 @@ mono_jit_compile_method_with_opt (MonoMethod *method, guint32 opt, MonoException
        MonoJitInfo *info;
        gpointer code, p;
        MonoJitICallInfo *callinfo = NULL;
+       WrapperInfo *winfo = NULL;
 
        /*
         * ICALL wrappers are handled specially, since there is only one copy of them
         * shared by all appdomains.
         */
-       if ((method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE) && (strstr (method->name, "__icall_wrapper_") == method->name)) {
-               const char *icall_name;
-
-               icall_name = method->name + strlen ("__icall_wrapper_");
-               g_assert (icall_name);
-               callinfo = mono_find_jit_icall_by_name (icall_name);
+       if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE)
+               winfo = mono_marshal_get_wrapper_info (method);
+       if (winfo && winfo->subtype == WRAPPER_SUBTYPE_ICALL_WRAPPER) {
+               callinfo = mono_find_jit_icall_by_addr (winfo->d.icall.func);
                g_assert (callinfo);
 
                /* Must be domain neutral since there is only one copy */
@@ -6055,7 +6144,7 @@ mono_jit_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObjec
        mono_domain_unlock (domain);            
 
        if (!info) {
-               if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR) {
+               if (mono_security_core_clr_enabled ()) {
                        /* 
                         * This might be redundant since mono_class_vtable () already does this,
                         * but keep it just in case for moonlight.
@@ -6098,7 +6187,7 @@ mono_jit_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObjec
                                }
                        }
 
-                       info->compiled_method = mini_add_method_trampoline (NULL, method, info->compiled_method, NULL, mono_method_needs_static_rgctx_invoke (method, FALSE));
+                       info->compiled_method = mini_add_method_trampoline (NULL, method, info->compiled_method, mono_method_needs_static_rgctx_invoke (method, FALSE), FALSE);
                }
 
                /*
@@ -6122,7 +6211,7 @@ mono_jit_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObjec
                                        supported = FALSE;
                        }
 
-                       if (method->klass->contextbound || !info->compiled_method)
+                       if (mono_class_is_contextbound (method->klass) || !info->compiled_method)
                                supported = FALSE;
 
                        if (supported)
@@ -6394,6 +6483,7 @@ SIG_HANDLER_SIGNATURE (mono_sigint_signal_handler)
        mono_arch_handle_exception (ctx, exc);
 }
 
+#ifndef DISABLE_REMOTING
 /* mono_jit_create_remoting_trampoline:
  * @method: pointer to the method info
  *
@@ -6414,14 +6504,16 @@ mono_jit_create_remoting_trampoline (MonoDomain *domain, MonoMethod *method, Mon
        }
 
        if ((method->flags & METHOD_ATTRIBUTE_ABSTRACT) || 
-           (mono_method_signature (method)->hasthis && (method->klass->marshalbyref || method->klass == mono_defaults.object_class))) {
+           (mono_method_signature (method)->hasthis && (mono_class_is_marshalbyref (method->klass) || method->klass == mono_defaults.object_class))) {
                nm = mono_marshal_get_remoting_invoke_for_target (method, target);
                addr = mono_compile_method (nm);
-       } else {
+       } else
+       {
                addr = mono_compile_method (method);
        }
        return mono_get_addr_from_ftnptr (addr);
 }
+#endif
 
 static gpointer *vtable_trampolines;
 static int vtable_trampolines_size;
@@ -6748,7 +6840,9 @@ mini_init (const char *filename, const char *runtime_version)
 
        if (getenv ("MONO_DEBUG") != NULL)
                mini_parse_debug_options ();
-       
+
+       mono_code_manager_init ();
+
        mono_arch_cpu_init ();
 
        mono_arch_init ();
@@ -6815,7 +6909,9 @@ mini_init (const char *filename, const char *runtime_version)
        mono_install_free_method (mono_jit_free_method);
        mono_install_trampoline (mono_create_jit_trampoline);
        mono_install_jump_trampoline (mono_create_jump_trampoline);
+#ifndef DISABLE_REMOTING
        mono_install_remoting_trampoline (mono_jit_create_remoting_trampoline);
+#endif
        mono_install_delegate_trampoline (mono_create_delegate_trampoline);
        mono_install_create_domain_hook (mini_create_jit_domain_info);
        mono_install_free_domain_hook (mini_free_jit_domain_info);
@@ -6851,9 +6947,9 @@ mini_init (const char *filename, const char *runtime_version)
                        mono_install_imt_thunk_builder (mono_arch_build_imt_thunk);
        }
 #endif
+
        /*Init arch tls information only after the metadata side is inited to make sure we see dynamic appdomain tls keys*/
        mono_arch_finish_init ();
-       
 
        /* This must come after mono_init () in the aot-only case */
        mono_exceptions_init ();
@@ -6902,15 +6998,16 @@ mini_init (const char *filename, const char *runtime_version)
        register_icall (mono_jit_set_domain, "mono_jit_set_domain", "void ptr", TRUE);
        register_icall (mono_domain_get, "mono_domain_get", "ptr", TRUE);
 
-       register_icall (mono_get_throw_exception (), "mono_arch_throw_exception", "void object", TRUE);
-       register_icall (mono_get_rethrow_exception (), "mono_arch_rethrow_exception", "void object", TRUE);
-       register_icall (mono_get_throw_corlib_exception (), "mono_arch_throw_corlib_exception", 
-                                "void ptr", TRUE);
+       register_dyn_icall (mono_get_throw_exception (), "mono_arch_throw_exception", "void object", TRUE);
+       register_dyn_icall (mono_get_rethrow_exception (), "mono_arch_rethrow_exception", "void object", TRUE);
+       register_dyn_icall (mono_get_throw_corlib_exception (), "mono_arch_throw_corlib_exception", "void ptr", TRUE);
        register_icall (mono_thread_get_undeniable_exception, "mono_thread_get_undeniable_exception", "object", FALSE);
        register_icall (mono_thread_interruption_checkpoint, "mono_thread_interruption_checkpoint", "void", FALSE);
        register_icall (mono_thread_force_interruption_checkpoint, "mono_thread_force_interruption_checkpoint", "void", FALSE);
+#ifndef DISABLE_REMOTING
        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);
+#endif
 
 #if defined(__native_client__) || defined(__native_client_codegen__)
        register_icall (mono_nacl_gc, "mono_nacl_gc", "void", TRUE);
@@ -6921,102 +7018,102 @@ mini_init (const char *filename, const char *runtime_version)
         * rule to the burg files, because we need the arity information to be correct.
         */
 #ifndef MONO_ARCH_NO_EMULATE_LONG_MUL_OPTS
-       mono_register_opcode_emulation (OP_LMUL, "__emul_lmul", "long long long", mono_llmult, TRUE);
-       mono_register_opcode_emulation (OP_LDIV, "__emul_ldiv", "long long long", mono_lldiv, FALSE);
-       mono_register_opcode_emulation (OP_LDIV_UN, "__emul_ldiv_un", "long long long", mono_lldiv_un, FALSE);
-       mono_register_opcode_emulation (OP_LREM, "__emul_lrem", "long long long", mono_llrem, FALSE);
-       mono_register_opcode_emulation (OP_LREM_UN, "__emul_lrem_un", "long long long", mono_llrem_un, FALSE);
-       mono_register_opcode_emulation (OP_LMUL_OVF_UN, "__emul_lmul_ovf_un", "long long long", mono_llmult_ovf_un, FALSE);
-       mono_register_opcode_emulation (OP_LMUL_OVF, "__emul_lmul_ovf", "long long long", mono_llmult_ovf, FALSE);
+       register_opcode_emulation (OP_LMUL, "__emul_lmul", "long long long", mono_llmult, "mono_llmult", TRUE);
+       register_opcode_emulation (OP_LDIV, "__emul_ldiv", "long long long", mono_lldiv, "mono_lldiv", FALSE);
+       register_opcode_emulation (OP_LDIV_UN, "__emul_ldiv_un", "long long long", mono_lldiv_un, "mono_lldiv_un", FALSE);
+       register_opcode_emulation (OP_LREM, "__emul_lrem", "long long long", mono_llrem, "mono_llrem", FALSE);
+       register_opcode_emulation (OP_LREM_UN, "__emul_lrem_un", "long long long", mono_llrem_un, "mono_llrem_un", FALSE);
+       register_opcode_emulation (OP_LMUL_OVF_UN, "__emul_lmul_ovf_un", "long long long", mono_llmult_ovf_un, "mono_llmult_ovf_un", FALSE);
+       register_opcode_emulation (OP_LMUL_OVF, "__emul_lmul_ovf", "long long long", mono_llmult_ovf, "mono_llmult_ovf", FALSE);
 #endif
 
 #ifndef MONO_ARCH_NO_EMULATE_LONG_SHIFT_OPS
-       mono_register_opcode_emulation (OP_LSHL, "__emul_lshl", "long long int32", mono_lshl, TRUE);
-       mono_register_opcode_emulation (OP_LSHR, "__emul_lshr", "long long int32", mono_lshr, TRUE);
-       mono_register_opcode_emulation (OP_LSHR_UN, "__emul_lshr_un", "long long int32", mono_lshr_un, TRUE);
+       register_opcode_emulation (OP_LSHL, "__emul_lshl", "long long int32", mono_lshl, "mono_lshl", TRUE);
+       register_opcode_emulation (OP_LSHR, "__emul_lshr", "long long int32", mono_lshr, "mono_lshr", TRUE);
+       register_opcode_emulation (OP_LSHR_UN, "__emul_lshr_un", "long long int32", mono_lshr_un, "mono_lshr_un", TRUE);
 #endif
 
 #if defined(MONO_ARCH_EMULATE_MUL_DIV) || defined(MONO_ARCH_EMULATE_DIV)
-       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);
-       mono_register_opcode_emulation (OP_IREM_UN, "__emul_op_irem_un", "int32 int32 int32", mono_irem_un, FALSE);
+       register_opcode_emulation (OP_IDIV, "__emul_op_idiv", "int32 int32 int32", mono_idiv, "mono_idiv", FALSE);
+       register_opcode_emulation (OP_IDIV_UN, "__emul_op_idiv_un", "int32 int32 int32", mono_idiv_un, "mono_idiv_un", FALSE);
+       register_opcode_emulation (OP_IREM, "__emul_op_irem", "int32 int32 int32", mono_irem, "mono_irem", FALSE);
+       register_opcode_emulation (OP_IREM_UN, "__emul_op_irem_un", "int32 int32 int32", mono_irem_un, "mono_irem_un", FALSE);
 #endif
 
 #ifdef MONO_ARCH_EMULATE_MUL_DIV
-       mono_register_opcode_emulation (OP_IMUL, "__emul_op_imul", "int32 int32 int32", mono_imul, TRUE);
+       register_opcode_emulation (OP_IMUL, "__emul_op_imul", "int32 int32 int32", mono_imul, "mono_imul", TRUE);
 #endif
 
 #if defined(MONO_ARCH_EMULATE_MUL_DIV) || defined(MONO_ARCH_EMULATE_MUL_OVF)
-       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);
+       register_opcode_emulation (OP_IMUL_OVF, "__emul_op_imul_ovf", "int32 int32 int32", mono_imul_ovf, "mono_imul_ovf", FALSE);
+       register_opcode_emulation (OP_IMUL_OVF_UN, "__emul_op_imul_ovf_un", "int32 int32 int32", mono_imul_ovf_un, "mono_imul_ovf_un", FALSE);
 #endif
 
 #if defined(MONO_ARCH_EMULATE_MUL_DIV) || defined(MONO_ARCH_SOFT_FLOAT)
-       mono_register_opcode_emulation (OP_FDIV, "__emul_fdiv", "double double double", mono_fdiv, FALSE);
+       register_opcode_emulation (OP_FDIV, "__emul_fdiv", "double double double", mono_fdiv, "mono_fdiv", FALSE);
 #endif
 
-       mono_register_opcode_emulation (OP_FCONV_TO_U8, "__emul_fconv_to_u8", "ulong double", mono_fconv_u8, FALSE);
-       mono_register_opcode_emulation (OP_FCONV_TO_U4, "__emul_fconv_to_u4", "uint32 double", mono_fconv_u4, FALSE);
-       mono_register_opcode_emulation (OP_FCONV_TO_OVF_I8, "__emul_fconv_to_ovf_i8", "long double", mono_fconv_ovf_i8, FALSE);
-       mono_register_opcode_emulation (OP_FCONV_TO_OVF_U8, "__emul_fconv_to_ovf_u8", "ulong double", mono_fconv_ovf_u8, FALSE);
+       register_opcode_emulation (OP_FCONV_TO_U8, "__emul_fconv_to_u8", "ulong double", mono_fconv_u8, "mono_fconv_u8", FALSE);
+       register_opcode_emulation (OP_FCONV_TO_U4, "__emul_fconv_to_u4", "uint32 double", mono_fconv_u4, "mono_fconv_u4", FALSE);
+       register_opcode_emulation (OP_FCONV_TO_OVF_I8, "__emul_fconv_to_ovf_i8", "long double", mono_fconv_ovf_i8, "mono_fconv_ovf_i8", FALSE);
+       register_opcode_emulation (OP_FCONV_TO_OVF_U8, "__emul_fconv_to_ovf_u8", "ulong double", mono_fconv_ovf_u8, "mono_fconv_ovf_u8", FALSE);
 
 #ifdef MONO_ARCH_EMULATE_FCONV_TO_I8
-       mono_register_opcode_emulation (OP_FCONV_TO_I8, "__emul_fconv_to_i8", "long double", mono_fconv_i8, FALSE);
+       register_opcode_emulation (OP_FCONV_TO_I8, "__emul_fconv_to_i8", "long double", mono_fconv_i8, "mono_fconv_i8", FALSE);
 #endif
 #ifdef MONO_ARCH_EMULATE_CONV_R8_UN
-       mono_register_opcode_emulation (OP_ICONV_TO_R_UN, "__emul_iconv_to_r_un", "double int32", mono_conv_to_r8_un, FALSE);
+       register_opcode_emulation (OP_ICONV_TO_R_UN, "__emul_iconv_to_r_un", "double int32", mono_conv_to_r8_un, "mono_conv_to_r8_un", FALSE);
 #endif
 #ifdef MONO_ARCH_EMULATE_LCONV_TO_R8
-       mono_register_opcode_emulation (OP_LCONV_TO_R8, "__emul_lconv_to_r8", "double long", mono_lconv_to_r8, FALSE);
+       register_opcode_emulation (OP_LCONV_TO_R8, "__emul_lconv_to_r8", "double long", mono_lconv_to_r8, "mono_lconv_to_r8", FALSE);
 #endif
 #ifdef MONO_ARCH_EMULATE_LCONV_TO_R4
-       mono_register_opcode_emulation (OP_LCONV_TO_R4, "__emul_lconv_to_r4", "float long", mono_lconv_to_r4, FALSE);
+       register_opcode_emulation (OP_LCONV_TO_R4, "__emul_lconv_to_r4", "float long", mono_lconv_to_r4, "mono_lconv_to_r4", FALSE);
 #endif
 #ifdef MONO_ARCH_EMULATE_LCONV_TO_R8_UN
-       mono_register_opcode_emulation (OP_LCONV_TO_R_UN, "__emul_lconv_to_r8_un", "double long", mono_lconv_to_r8_un, FALSE);
+       register_opcode_emulation (OP_LCONV_TO_R_UN, "__emul_lconv_to_r8_un", "double long", mono_lconv_to_r8_un, "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);
+       register_opcode_emulation (OP_FREM, "__emul_frem", "double double double", fmod, "fmod", FALSE);
 #elif defined(__native_client_codegen__)
-       mono_register_opcode_emulation (OP_FREM, "__emul_frem", "double double double", mono_fmod, FALSE);
+       register_opcode_emulation (OP_FREM, "__emul_frem", "double double double", mono_fmod, "mono_fmod", FALSE);
 #endif
 #endif
 
 #ifdef MONO_ARCH_SOFT_FLOAT
-       mono_register_opcode_emulation (OP_FSUB, "__emul_fsub", "double double double", mono_fsub, FALSE);
-       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 (OP_ICONV_TO_R8, "__emul_iconv_to_r8", "double int32", mono_conv_to_r8, 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);
-       mono_register_opcode_emulation (OP_FCONV_TO_I2, "__emul_fconv_to_i2", "int16 double", mono_fconv_i2, FALSE);
-       mono_register_opcode_emulation (OP_FCONV_TO_I4, "__emul_fconv_to_i4", "int32 double", mono_fconv_i4, FALSE);
-       mono_register_opcode_emulation (OP_FCONV_TO_U1, "__emul_fconv_to_u1", "uint8 double", mono_fconv_u1, FALSE);
-       mono_register_opcode_emulation (OP_FCONV_TO_U2, "__emul_fconv_to_u2", "uint16 double", mono_fconv_u2, FALSE);
+       register_opcode_emulation (OP_FSUB, "__emul_fsub", "double double double", mono_fsub, "mono_fsub", FALSE);
+       register_opcode_emulation (OP_FADD, "__emul_fadd", "double double double", mono_fadd, "mono_fadd", FALSE);
+       register_opcode_emulation (OP_FMUL, "__emul_fmul", "double double double", mono_fmul, "mono_fmul", FALSE);
+       register_opcode_emulation (OP_FNEG, "__emul_fneg", "double double", mono_fneg, "mono_fneg", FALSE);
+       register_opcode_emulation (OP_ICONV_TO_R8, "__emul_iconv_to_r8", "double int32", mono_conv_to_r8, "mono_conv_to_r8", FALSE);
+       register_opcode_emulation (OP_ICONV_TO_R4, "__emul_iconv_to_r4", "double int32", mono_conv_to_r4, "mono_conv_to_r4", FALSE);
+       register_opcode_emulation (OP_FCONV_TO_R4, "__emul_fconv_to_r4", "double double", mono_fconv_r4, "mono_fconv_r4", FALSE);
+       register_opcode_emulation (OP_FCONV_TO_I1, "__emul_fconv_to_i1", "int8 double", mono_fconv_i1, "mono_fconv_i1", FALSE);
+       register_opcode_emulation (OP_FCONV_TO_I2, "__emul_fconv_to_i2", "int16 double", mono_fconv_i2, "mono_fconv_i2", FALSE);
+       register_opcode_emulation (OP_FCONV_TO_I4, "__emul_fconv_to_i4", "int32 double", mono_fconv_i4, "mono_fconv_i4", FALSE);
+       register_opcode_emulation (OP_FCONV_TO_U1, "__emul_fconv_to_u1", "uint8 double", mono_fconv_u1, "mono_fconv_u1", FALSE);
+       register_opcode_emulation (OP_FCONV_TO_U2, "__emul_fconv_to_u2", "uint16 double", mono_fconv_u2, "mono_fconv_u2", FALSE);
 #if SIZEOF_VOID_P == 4
-       mono_register_opcode_emulation (OP_FCONV_TO_I, "__emul_fconv_to_i", "int32 double", mono_fconv_i4, FALSE);
-#endif
-
-       mono_register_opcode_emulation (OP_FBEQ, "__emul_fcmp_eq", "uint32 double double", mono_fcmp_eq, FALSE);
-       mono_register_opcode_emulation (OP_FBLT, "__emul_fcmp_lt", "uint32 double double", mono_fcmp_lt, FALSE);
-       mono_register_opcode_emulation (OP_FBGT, "__emul_fcmp_gt", "uint32 double double", mono_fcmp_gt, FALSE);
-       mono_register_opcode_emulation (OP_FBLE, "__emul_fcmp_le", "uint32 double double", mono_fcmp_le, FALSE);
-       mono_register_opcode_emulation (OP_FBGE, "__emul_fcmp_ge", "uint32 double double", mono_fcmp_ge, FALSE);
-       mono_register_opcode_emulation (OP_FBNE_UN, "__emul_fcmp_ne_un", "uint32 double double", mono_fcmp_ne_un, FALSE);
-       mono_register_opcode_emulation (OP_FBLT_UN, "__emul_fcmp_lt_un", "uint32 double double", mono_fcmp_lt_un, FALSE);
-       mono_register_opcode_emulation (OP_FBGT_UN, "__emul_fcmp_gt_un", "uint32 double double", mono_fcmp_gt_un, FALSE);
-       mono_register_opcode_emulation (OP_FBLE_UN, "__emul_fcmp_le_un", "uint32 double double", mono_fcmp_le_un, FALSE);
-       mono_register_opcode_emulation (OP_FBGE_UN, "__emul_fcmp_ge_un", "uint32 double double", mono_fcmp_ge_un, FALSE);
-
-       mono_register_opcode_emulation (OP_FCEQ, "__emul_fcmp_ceq", "uint32 double double", mono_fceq, FALSE);
-       mono_register_opcode_emulation (OP_FCGT, "__emul_fcmp_cgt", "uint32 double double", mono_fcgt, FALSE);
-       mono_register_opcode_emulation (OP_FCGT_UN, "__emul_fcmp_cgt_un", "uint32 double double", mono_fcgt_un, FALSE);
-       mono_register_opcode_emulation (OP_FCLT, "__emul_fcmp_clt", "uint32 double double", mono_fclt, FALSE);
-       mono_register_opcode_emulation (OP_FCLT_UN, "__emul_fcmp_clt_un", "uint32 double double", mono_fclt_un, FALSE);
+       register_opcode_emulation (OP_FCONV_TO_I, "__emul_fconv_to_i", "int32 double", mono_fconv_i4, "mono_fconv_i4", FALSE);
+#endif
+
+       register_opcode_emulation (OP_FBEQ, "__emul_fcmp_eq", "uint32 double double", mono_fcmp_eq, "mono_fcmp_eq", FALSE);
+       register_opcode_emulation (OP_FBLT, "__emul_fcmp_lt", "uint32 double double", mono_fcmp_lt, "mono_fcmp_lt", FALSE);
+       register_opcode_emulation (OP_FBGT, "__emul_fcmp_gt", "uint32 double double", mono_fcmp_gt, "mono_fcmp_gt", FALSE);
+       register_opcode_emulation (OP_FBLE, "__emul_fcmp_le", "uint32 double double", mono_fcmp_le, "mono_fcmp_le", FALSE);
+       register_opcode_emulation (OP_FBGE, "__emul_fcmp_ge", "uint32 double double", mono_fcmp_ge, "mono_fcmp_ge", FALSE);
+       register_opcode_emulation (OP_FBNE_UN, "__emul_fcmp_ne_un", "uint32 double double", mono_fcmp_ne_un, "mono_fcmp_ne_un", FALSE);
+       register_opcode_emulation (OP_FBLT_UN, "__emul_fcmp_lt_un", "uint32 double double", mono_fcmp_lt_un, "mono_fcmp_lt_un", FALSE);
+       register_opcode_emulation (OP_FBGT_UN, "__emul_fcmp_gt_un", "uint32 double double", mono_fcmp_gt_un, "mono_fcmp_gt_un", FALSE);
+       register_opcode_emulation (OP_FBLE_UN, "__emul_fcmp_le_un", "uint32 double double", mono_fcmp_le_un, "mono_fcmp_le_un", FALSE);
+       register_opcode_emulation (OP_FBGE_UN, "__emul_fcmp_ge_un", "uint32 double double", mono_fcmp_ge_un, "mono_fcmp_ge_un", FALSE);
+
+       register_opcode_emulation (OP_FCEQ, "__emul_fcmp_ceq", "uint32 double double", mono_fceq, "mono_fceq", FALSE);
+       register_opcode_emulation (OP_FCGT, "__emul_fcmp_cgt", "uint32 double double", mono_fcgt, "mono_fcgt", FALSE);
+       register_opcode_emulation (OP_FCGT_UN, "__emul_fcmp_cgt_un", "uint32 double double", mono_fcgt_un, "mono_fcgt_un", FALSE);
+       register_opcode_emulation (OP_FCLT, "__emul_fcmp_clt", "uint32 double double", mono_fclt, "mono_fclt", FALSE);
+       register_opcode_emulation (OP_FCLT_UN, "__emul_fcmp_clt_un", "uint32 double double", mono_fclt_un, "mono_fclt_un", FALSE);
 
        register_icall (mono_fload_r4, "mono_fload_r4", "double ptr", FALSE);
        register_icall (mono_fstore_r4, "mono_fstore_r4", "void double ptr", FALSE);
@@ -7029,7 +7126,7 @@ mini_init (const char *filename, const char *runtime_version)
 #endif
 
 #if SIZEOF_REGISTER == 4
-       mono_register_opcode_emulation (OP_FCONV_TO_U, "__emul_fconv_to_u", "uint32 double", mono_fconv_u4, TRUE);
+       register_opcode_emulation (OP_FCONV_TO_U, "__emul_fconv_to_u", "uint32 double", mono_fconv_u4, "mono_fconv_u4", TRUE);
 #endif
 
        /* other jit icalls */
@@ -7041,7 +7138,7 @@ mini_init (const char *filename, const char *runtime_version)
                "ptr ptr ptr ptr", FALSE);
        register_icall (mono_get_special_static_data, "mono_get_special_static_data", "ptr int", FALSE);
        register_icall (mono_ldstr, "mono_ldstr", "object ptr ptr int32", FALSE);
-       register_icall (mono_helper_stelem_ref_check, "helper_stelem_ref_check", "void object object", FALSE);
+       register_icall (mono_helper_stelem_ref_check, "mono_helper_stelem_ref_check", "void object object", FALSE);
        register_icall (mono_object_new, "mono_object_new", "object ptr ptr", FALSE);
        register_icall (mono_object_new_specific, "mono_object_new_specific", "object ptr", FALSE);
        register_icall (mono_array_new, "mono_array_new", "object ptr ptr int32", FALSE);
@@ -7050,10 +7147,10 @@ mini_init (const char *filename, const char *runtime_version)
        register_icall (mono_ldftn, "mono_ldftn", "ptr ptr", FALSE);
        register_icall (mono_ldvirtfn, "mono_ldvirtfn", "ptr object ptr", FALSE);
        register_icall (mono_ldvirtfn_gshared, "mono_ldvirtfn_gshared", "ptr object ptr", FALSE);
-       register_icall (mono_helper_compile_generic_method, "compile_generic_method", "ptr object ptr ptr", FALSE);
-       register_icall (mono_helper_ldstr, "helper_ldstr", "object ptr int", FALSE);
-       register_icall (mono_helper_ldstr_mscorlib, "helper_ldstr_mscorlib", "object int", FALSE);
-       register_icall (mono_helper_newobj_mscorlib, "helper_newobj_mscorlib", "object int", FALSE);
+       register_icall (mono_helper_compile_generic_method, "mono_helper_compile_generic_method", "ptr object ptr ptr", FALSE);
+       register_icall (mono_helper_ldstr, "mono_helper_ldstr", "object ptr int", FALSE);
+       register_icall (mono_helper_ldstr_mscorlib, "mono_helper_ldstr_mscorlib", "object int", FALSE);
+       register_icall (mono_helper_newobj_mscorlib, "mono_helper_newobj_mscorlib", "object int", FALSE);
        register_icall (mono_value_copy, "mono_value_copy", "void ptr ptr ptr", FALSE);
        register_icall (mono_object_castclass, "mono_object_castclass", "object object ptr", FALSE);
        register_icall (mono_break, "mono_break", NULL, TRUE);
@@ -7068,6 +7165,8 @@ mini_init (const char *filename, const char *runtime_version)
        register_icall (mono_resume_unwind, "mono_resume_unwind", "void", TRUE);
        register_icall (mono_object_tostring_gsharedvt, "mono_object_tostring_gsharedvt", "object ptr ptr ptr", TRUE);
        register_icall (mono_object_gethashcode_gsharedvt, "mono_object_gethashcode_gsharedvt", "int ptr ptr ptr", TRUE);
+       register_icall (mono_object_equals_gsharedvt, "mono_object_equals_gsharedvt", "int ptr ptr ptr object", TRUE);
+       register_icall (mono_gsharedvt_value_copy, "mono_gsharedvt_value_copy", "void ptr ptr ptr", TRUE);
 
        register_icall (mono_gc_wbarrier_value_copy_bitmap, "mono_gc_wbarrier_value_copy_bitmap", "void ptr ptr int int", FALSE);
 
@@ -7075,7 +7174,10 @@ mini_init (const char *filename, const char *runtime_version)
        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
 
+#ifdef TARGET_IOS
+       register_icall (pthread_getspecific, "pthread_getspecific", NULL, TRUE);
 #endif
 
        mono_generic_sharing_init ();
@@ -7121,7 +7223,6 @@ print_jit_stats (void)
                g_print ("Biggest method:         %ld (%s)\n", mono_jit_stats.biggest_method_size,
                                 mono_jit_stats.biggest_method);
 
-               g_print ("\nCreated object count:   %ld\n", mono_stats.new_object_count);
                g_print ("Delegates created:      %ld\n", mono_stats.delegate_creations);
                g_print ("Initialized classes:    %ld\n", mono_stats.initialized_class_count);
                g_print ("Used classes:           %ld\n", mono_stats.used_class_count);
@@ -7158,7 +7259,7 @@ print_jit_stats (void)
                g_print ("JIT info table lookups: %ld\n", mono_stats.jit_info_table_lookup_count);
 
                g_print ("Hazardous pointers:     %ld\n", mono_stats.hazardous_pointer_count);
-               if (mono_security_get_mode () == MONO_SECURITY_MODE_CAS) {
+               if (mono_security_cas_enabled ()) {
                        g_print ("\nDecl security check   : %ld\n", mono_jit_stats.cas_declsec_check);
                        g_print ("LinkDemand (user)     : %ld\n", mono_jit_stats.cas_linkdemand);
                        g_print ("LinkDemand (icall)    : %ld\n", mono_jit_stats.cas_linkdemand_icall);
@@ -7184,12 +7285,9 @@ mini_cleanup (MonoDomain *domain)
 #endif
 
 #ifndef MONO_CROSS_COMPILE     
-       mono_runtime_shutdown ();
        /* 
-        * mono_runtime_cleanup() and mono_domain_finalize () need to
-        * be called early since they need the execution engine still
-        * fully working (mono_domain_finalize may invoke managed finalizers
-        * and mono_runtime_cleanup will wait for other threads to finish).
+        * mono_domain_finalize () needs to be called early since it needs the
+        * execution engine still fully working (it may invoke managed finalizers).
         */
        mono_domain_finalize (domain, 2000);
 #endif
@@ -7249,6 +7347,12 @@ mini_cleanup (MonoDomain *domain)
        DeleteCriticalSection (&jit_mutex);
 
        DeleteCriticalSection (&mono_delegate_section);
+
+       mono_code_manager_cleanup ();
+
+#ifdef USE_JUMP_TABLES
+       mono_jumptable_cleanup ();
+#endif
 }
 
 void
@@ -7328,10 +7432,12 @@ mono_precompile_assembly (MonoAssembly *ass, void *user_data)
                        invoke = mono_marshal_get_runtime_invoke (method, FALSE);
                        mono_compile_method (invoke);
                }
-               if (method->klass->marshalbyref && mono_method_signature (method)->hasthis) {
+#ifndef DISABLE_REMOTING
+               if (mono_class_is_marshalbyref (method->klass) && mono_method_signature (method)->hasthis) {
                        invoke = mono_marshal_get_remoting_invoke_with_check (method);
                        mono_compile_method (invoke);
                }
+#endif
        }
 
        /* Load and precompile referenced assemblies as well */
@@ -7410,37 +7516,114 @@ mono_arch_get_gsharedvt_trampoline (MonoTrampInfo **info, gboolean aot)
 
 #endif
 
-#ifdef DISABLE_JIT
+#if defined(MONO_ARCH_GSHAREDVT_SUPPORTED) && !defined(MONOTOUCH) && !defined(MONO_EXTENSIONS)
 
-gpointer
-mono_arch_get_gsharedvt_arg_trampoline (MonoDomain *domain, gpointer arg, gpointer addr)
+gboolean
+mono_arch_gsharedvt_sig_supported (MonoMethodSignature *sig)
 {
-       g_assert_not_reached ();
-       return NULL;
+       return FALSE;
 }
 
 gpointer
-mono_arch_get_gsharedvt_trampoline (MonoTrampInfo **info, gboolean aot)
+mono_arch_get_gsharedvt_call_info (gpointer addr, MonoMethodSignature *normal_sig, MonoMethodSignature *gsharedvt_sig, MonoGenericSharingContext *gsctx, gboolean gsharedvt_in, gint32 vcall_offset, gboolean calli)
 {
-       g_assert_not_reached ();
-       return NULL;
+       NOT_IMPLEMENTED;
+       return NULL;
 }
 
 #endif
 
-#if defined(MONO_ARCH_GSHAREDVT_SUPPORTED) && !defined(MONOTOUCH) && !defined(MONO_EXTENSIONS)
+#ifdef USE_JUMP_TABLES
+#define DEFAULT_JUMPTABLE_CHUNK_ELEMENTS 128
 
-gboolean
-mono_arch_gsharedvt_sig_supported (MonoMethodSignature *sig)
+typedef struct MonoJumpTableChunk {
+       guint32 total;
+       guint32 active;
+       struct MonoJumpTableChunk *previous;
+       /* gpointer entries[total]; */
+} MonoJumpTableChunk;
+
+static MonoJumpTableChunk* g_jumptable = NULL;
+#define mono_jumptable_lock() EnterCriticalSection (&jumptable_mutex)
+#define mono_jumptable_unlock() LeaveCriticalSection (&jumptable_mutex)
+static CRITICAL_SECTION jumptable_mutex;
+
+static  MonoJumpTableChunk*
+mono_create_jumptable_chunk (guint32 max_entries)
 {
-       return FALSE;
+       guint32 size = sizeof (MonoJumpTableChunk) + max_entries * sizeof(gpointer);
+       MonoJumpTableChunk *chunk = (MonoJumpTableChunk*) g_new0 (guchar, size);
+       chunk->total = max_entries;
+       return chunk;
 }
 
-gpointer
-mono_arch_get_gsharedvt_call_info (gpointer addr, MonoMethodSignature *normal_sig, MonoMethodSignature *gsharedvt_sig, MonoGenericSharingContext *gsctx, gboolean gsharedvt_in, gint32 vcall_offset, gboolean calli)
+void
+mono_jumptable_init (void)
 {
-       NOT_IMPLEMENTED;
-       return NULL;
+       if (g_jumptable == NULL) {
+               InitializeCriticalSection (&jumptable_mutex);
+               g_jumptable = mono_create_jumptable_chunk (DEFAULT_JUMPTABLE_CHUNK_ELEMENTS);
+       }
 }
 
+gpointer*
+mono_jumptable_add_entry (void)
+{
+       return mono_jumptable_add_entries (1);
+}
+
+gpointer*
+mono_jumptable_add_entries (guint32 entries)
+{
+       guint32 index;
+       gpointer *result;
+
+       mono_jumptable_init ();
+       mono_jumptable_lock ();
+       index = g_jumptable->active;
+       if (index + entries >= g_jumptable->total) {
+               /*
+                * Grow jumptable, by adding one more chunk.
+                * We cannot realloc jumptable, as there could be pointers
+                * to existing jump table entries in the code, so instead
+                * we just add one more chunk.
+                */
+               guint32 max_entries = entries;
+               MonoJumpTableChunk *new_chunk;
+
+               if (max_entries < DEFAULT_JUMPTABLE_CHUNK_ELEMENTS)
+                       max_entries = DEFAULT_JUMPTABLE_CHUNK_ELEMENTS;
+               new_chunk = mono_create_jumptable_chunk (max_entries);
+               /* Link old jumptable, so that we could free it up later. */
+               new_chunk->previous = g_jumptable;
+               g_jumptable = new_chunk;
+               index = 0;
+       }
+       g_jumptable->active = index + entries;
+       result = (gpointer*)((guchar*)g_jumptable + sizeof(MonoJumpTableChunk)) + index;
+       mono_jumptable_unlock();
+
+       return result;
+}
+
+void
+mono_jumptable_cleanup (void)
+{
+       if (g_jumptable) {
+               MonoJumpTableChunk *current = g_jumptable, *prev;
+               while (current != NULL) {
+                       prev = current->previous;
+                       g_free (current);
+                       current = prev;
+               }
+               g_jumptable = NULL;
+               DeleteCriticalSection (&jumptable_mutex);
+       }
+}
+
+gpointer*
+mono_jumptable_get_entry (guint8 *code_ptr)
+{
+       return mono_arch_jumptable_entry_from_code (code_ptr);
+}
 #endif