Revert "Revert "Merge branch 'master' of https://github.com/mono/mono""
[mono.git] / mono / mini / mini.c
index 45a4fad5e0598d5752611b629c658f6912115cb3..3a9ff6b7c2765f9c91d810df2d9cca58f980cf2b 100644 (file)
@@ -101,6 +101,7 @@ int mono_break_at_bb_bb_num;
 gboolean mono_do_x86_stack_align = TRUE;
 const char *mono_build_date;
 gboolean mono_do_signal_chaining;
+gboolean mono_do_crash_chaining;
 static gboolean        mono_using_xdebug;
 static int mini_verbose = 0;
 
@@ -683,6 +684,19 @@ mono_tramp_info_register (MonoTrampInfo *info)
        mono_tramp_info_free (info);
 }
 
+static void
+mono_tramp_info_cleanup (void)
+{
+       GSList *l;
+
+       for (l = tramp_infos; l; l = l->next) {
+               MonoTrampInfo *info = l->data;
+
+               mono_tramp_info_free (info);
+       }
+       g_slist_free (tramp_infos);
+}
+
 G_GNUC_UNUSED static void
 break_count (void)
 {
@@ -2391,6 +2405,8 @@ register_opcode_emulation (int opcode, const char *name, const char *sigstr, gpo
 /*
  * For JIT icalls implemented in C.
  * NAME should be the same as the name of the C function whose address is FUNC.
+ * If SAVE is TRUE, no wrapper is generated. This is for perf critical icalls which
+ * can't throw exceptions.
  */
 static void
 register_icall (gpointer func, const char *name, const char *sigstr, gboolean save)
@@ -2704,6 +2720,12 @@ mono_set_lmf (MonoLMF *lmf)
        (*mono_get_lmf_addr ()) = lmf;
 }
 
+MonoJitTlsData*
+mono_get_jit_tls (void)
+{
+       return mono_native_tls_get_value (mono_jit_tls_id);
+}
+
 static void
 mono_set_jit_tls (MonoJitTlsData *jit_tls)
 {
@@ -2928,7 +2950,14 @@ mini_get_tls_offset (MonoTlsKey key)
                offset = mono_thread_get_tls_offset ();
                break;
        case TLS_KEY_JIT_TLS:
+#ifdef HOST_WIN32
+               offset = mono_get_jit_tls_key ();
+               /* Only 64 tls entries can be accessed using inline code */
+               if (offset >= 64)
+                       offset = -1;
+#else
                offset = mono_get_jit_tls_offset ();
+#endif
                break;
        case TLS_KEY_DOMAIN:
                offset = mono_domain_get_tls_offset ();
@@ -3119,6 +3148,10 @@ mono_patch_info_dup_mp (MonoMemPool *mp, MonoJumpInfo *patch_info)
                memcpy (res->data.rgctx_entry, patch_info->data.rgctx_entry, sizeof (MonoJumpInfoRgctxEntry));
                res->data.rgctx_entry->data = mono_patch_info_dup_mp (mp, res->data.rgctx_entry->data);
                break;
+       case MONO_PATCH_INFO_DELEGATE_TRAMPOLINE:
+               res->data.del_tramp = mono_mempool_alloc0 (mp, sizeof (MonoClassMethodPair));
+               memcpy (res->data.del_tramp, patch_info->data.del_tramp, sizeof (MonoClassMethodPair));
+               break;
        case MONO_PATCH_INFO_GSHAREDVT_CALL:
                res->data.gsharedvt = mono_mempool_alloc (mp, sizeof (MonoJumpInfoGSharedVtCall));
                memcpy (res->data.gsharedvt, patch_info->data.gsharedvt, sizeof (MonoJumpInfoGSharedVtCall));
@@ -3132,15 +3165,12 @@ mono_patch_info_dup_mp (MonoMemPool *mp, MonoJumpInfo *patch_info)
                info = mono_mempool_alloc (mp, sizeof (MonoGSharedVtMethodInfo));
                res->data.gsharedvt_method = info;
                memcpy (info, oinfo, sizeof (MonoGSharedVtMethodInfo));
-               info->entries = g_ptr_array_new ();
-               if (oinfo->entries) {
-                       for (i = 0; i < oinfo->entries->len; ++i) {
-                               MonoRuntimeGenericContextInfoTemplate *otemplate = g_ptr_array_index (oinfo->entries, i);
-                               MonoRuntimeGenericContextInfoTemplate *template = mono_mempool_alloc0 (mp, sizeof (MonoRuntimeGenericContextInfoTemplate));
+               info->entries = mono_mempool_alloc (mp, sizeof (MonoRuntimeGenericContextInfoTemplate) * info->count_entries);
+               for (i = 0; i < oinfo->num_entries; ++i) {
+                       MonoRuntimeGenericContextInfoTemplate *otemplate = &oinfo->entries [i];
+                       MonoRuntimeGenericContextInfoTemplate *template = &info->entries [i];
 
-                               memcpy (template, otemplate, sizeof (MonoRuntimeGenericContextInfoTemplate));
-                               g_ptr_array_add (info->entries, template);
-                       }
+                       memcpy (template, otemplate, sizeof (MonoRuntimeGenericContextInfoTemplate));
                }
                //info->locals_types = mono_mempool_alloc0 (mp, info->nlocals * sizeof (MonoType*));
                //memcpy (info->locals_types, oinfo->locals_types, info->nlocals * sizeof (MonoType*));
@@ -3184,7 +3214,6 @@ mono_patch_info_hash (gconstpointer data)
        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:
        case MONO_PATCH_INFO_TLS_OFFSET:
        case MONO_PATCH_INFO_METHOD_CODE_SLOT:
@@ -3212,6 +3241,8 @@ mono_patch_info_hash (gconstpointer data)
        case MONO_PATCH_INFO_OBJC_SELECTOR_REF:
                /* Hash on the selector name */
                return g_str_hash (ji->data.target);
+       case MONO_PATCH_INFO_DELEGATE_TRAMPOLINE:
+               return (ji->type << 8) | (gsize)ji->data.del_tramp->klass | (gsize)ji->data.del_tramp->method;
        default:
                printf ("info type: %d\n", ji->type);
                mono_print_ji (ji); printf ("\n");
@@ -3265,6 +3296,8 @@ mono_patch_info_equal (gconstpointer ka, gconstpointer kb)
        }
        case MONO_PATCH_INFO_GSHAREDVT_METHOD:
                return ji1->data.gsharedvt_method->method == ji2->data.gsharedvt_method->method;
+       case MONO_PATCH_INFO_DELEGATE_TRAMPOLINE:
+               return ji1->data.del_tramp->klass == ji2->data.del_tramp->klass && ji1->data.del_tramp->method == ji2->data.del_tramp->method;
        default:
                if (ji1->data.target != ji2->data.target)
                        return 0;
@@ -3433,9 +3466,12 @@ mono_resolve_patch_target (MonoMethod *method, MonoDomain *domain, guint8 *code,
                target = mono_create_class_init_trampoline (vtable);
                break;
        }
-       case MONO_PATCH_INFO_DELEGATE_TRAMPOLINE:
-               target = mono_create_delegate_trampoline (domain, patch_info->data.klass);
+       case MONO_PATCH_INFO_DELEGATE_TRAMPOLINE: {
+               MonoClassMethodPair *del_tramp = patch_info->data.del_tramp;
+
+               target = mono_create_delegate_trampoline_with_method (domain, del_tramp->klass, del_tramp->method);
                break;
+       }
        case MONO_PATCH_INFO_SFLDA: {
                MonoVTable *vtable = mono_class_vtable (domain, patch_info->data.field->parent);
 
@@ -3579,13 +3615,13 @@ mono_resolve_patch_target (MonoMethod *method, MonoDomain *domain, guint8 *code,
                        /* Make a copy into the domain mempool */
                        info = g_malloc0 (sizeof (MonoGSharedVtMethodInfo)); //mono_domain_alloc0 (domain, sizeof (MonoGSharedVtMethodInfo));
                        info->method = oinfo->method;
-                       info->entries = g_ptr_array_new ();
-                       for (i = 0; i < oinfo->entries->len; ++i) {
-                               MonoRuntimeGenericContextInfoTemplate *otemplate = g_ptr_array_index (oinfo->entries, i);
-                               MonoRuntimeGenericContextInfoTemplate *template = g_malloc0 (sizeof (MonoRuntimeGenericContextInfoTemplate));
+                       info->num_entries = oinfo->num_entries;
+                       info->entries = g_malloc0 (sizeof (MonoRuntimeGenericContextInfoTemplate) * info->num_entries);
+                       for (i = 0; i < oinfo->num_entries; ++i) {
+                               MonoRuntimeGenericContextInfoTemplate *otemplate = &oinfo->entries [i];
+                               MonoRuntimeGenericContextInfoTemplate *template = &info->entries [i];
 
                                memcpy (template, otemplate, sizeof (MonoRuntimeGenericContextInfoTemplate));
-                               g_ptr_array_add (info->entries, template);
                        }
                        slot = mono_method_lookup_or_register_info (entry->method, entry->in_mrgctx, info, entry->info_type, mono_method_get_context (entry->method));
                        break;
@@ -4276,6 +4312,9 @@ create_jit_info_for_trampoline (MonoMethod *wrapper, MonoTrampInfo *info)
        jinfo->code_size = info->code_size;
        jinfo->used_regs = mono_cache_unwind_info (uw_info, info_len);
 
+       if (!info->uw_info)
+               g_free (uw_info);
+
        return jinfo;
 }
 
@@ -4375,7 +4414,7 @@ create_jit_info (MonoCompile *cfg, MonoMethod *method_to_compile)
                        gi->generic_sharing_context = g_new0 (MonoGenericSharingContext, 1);
                else
                        gi->generic_sharing_context = mono_domain_alloc0 (cfg->domain, sizeof (MonoGenericSharingContext));
-               memcpy (gi->generic_sharing_context, cfg->generic_sharing_context, sizeof (MonoGenericSharingContext));
+               mini_init_gsctx (cfg->method->dynamic ? NULL : cfg->domain, NULL, cfg->gsctx_context, gi->generic_sharing_context);
 
                if ((method_to_compile->flags & METHOD_ATTRIBUTE_STATIC) ||
                                mini_method_get_context (method_to_compile)->method_inst ||
@@ -4493,12 +4532,24 @@ create_jit_info (MonoCompile *cfg, MonoMethod *method_to_compile)
                        MonoExceptionClause *ec = &header->clauses [i];
                        MonoJitExceptionInfo *ei = &jinfo->clauses [i];
                        MonoBasicBlock *tblock;
-                       MonoInst *exvar;
+                       MonoInst *exvar, *spvar;
 
                        ei->flags = ec->flags;
 
-                       exvar = mono_find_exvar_for_offset (cfg, ec->handler_offset);
-                       ei->exvar_offset = exvar ? exvar->inst_offset : 0;
+                       /*
+                        * The spvars are needed by mono_arch_install_handler_block_guard ().
+                        */
+                       if (ei->flags == MONO_EXCEPTION_CLAUSE_FINALLY) {
+                               int region;
+
+                               region = ((i + 1) << 8) | MONO_REGION_FINALLY | ec->flags;
+                               spvar = mono_find_spvar_for_region (cfg, region);
+                               g_assert (spvar);
+                               ei->exvar_offset = spvar->inst_offset;
+                       } else {
+                               exvar = mono_find_exvar_for_offset (cfg, ec->handler_offset);
+                               ei->exvar_offset = exvar ? exvar->inst_offset : 0;
+                       }
 
                        if (ei->flags == MONO_EXCEPTION_CLAUSE_FILTER) {
                                tblock = cfg->cil_offset_to_bb [ec->data.filter_offset];
@@ -4801,16 +4852,21 @@ mini_get_shared_method (MonoMethod *method)
 }
 
 void
-mini_init_gsctx (MonoGenericContext *context, MonoGenericSharingContext *gsctx)
+mini_init_gsctx (MonoDomain *domain, MonoMemPool *mp, MonoGenericContext *context, MonoGenericSharingContext *gsctx)
 {
        MonoGenericInst *inst;
        int i;
 
        memset (gsctx, 0, sizeof (MonoGenericSharingContext));
 
-       if (context->class_inst) {
+       if (context && context->class_inst) {
                inst = context->class_inst;
-               gsctx->var_is_vt = g_new0 (gboolean, inst->type_argc);
+               if (domain)
+                       gsctx->var_is_vt = mono_domain_alloc0 (domain, sizeof (gboolean) * inst->type_argc);
+               else if (mp)
+                       gsctx->var_is_vt = mono_mempool_alloc0 (mp, sizeof (gboolean) * inst->type_argc);
+               else
+                       gsctx->var_is_vt = g_new0 (gboolean, inst->type_argc);
 
                for (i = 0; i < inst->type_argc; ++i) {
                        MonoType *type = inst->type_argv [i];
@@ -4819,9 +4875,14 @@ mini_init_gsctx (MonoGenericContext *context, MonoGenericSharingContext *gsctx)
                                gsctx->var_is_vt [i] = TRUE;
                }
        }
-       if (context->method_inst) {
+       if (context && context->method_inst) {
                inst = context->method_inst;
-               gsctx->mvar_is_vt = g_new0 (gboolean, inst->type_argc);
+               if (domain)
+                       gsctx->mvar_is_vt = mono_domain_alloc0 (domain, sizeof (gboolean) * inst->type_argc);
+               else if (mp)
+                       gsctx->mvar_is_vt = mono_mempool_alloc0 (mp, sizeof (gboolean) * inst->type_argc);
+               else
+                       gsctx->mvar_is_vt = g_new0 (gboolean, inst->type_argc);
 
                for (i = 0; i < inst->type_argc; ++i) {
                        MonoType *type = inst->type_argv [i];
@@ -4932,6 +4993,7 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, JitFl
        cfg->gen_seq_points = debug_options.gen_seq_points;
        cfg->explicit_null_checks = debug_options.explicit_null_checks;
        cfg->soft_breakpoints = debug_options.soft_breakpoints;
+       cfg->check_pinvoke_callconv = debug_options.check_pinvoke_callconv;
        if (try_generic_shared)
                cfg->generic_sharing_context = (MonoGenericSharingContext*)&cfg->gsctx;
        cfg->compile_llvm = try_llvm;
@@ -4949,7 +5011,6 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, JitFl
                MonoMethodInflated *inflated;
                MonoGenericContext *context;
 
-               // FIXME: Free the contents of gsctx if compilation fails
                if (method_is_gshared) {
                        g_assert (method->is_inflated);
                        inflated = (MonoMethodInflated*)method;
@@ -4963,7 +5024,8 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, JitFl
                        context = &inflated->context;
                }
 
-               mini_init_gsctx (context, &cfg->gsctx);
+               mini_init_gsctx (NULL, cfg->mempool, context, &cfg->gsctx);
+               cfg->gsctx_context = context;
 
                cfg->gsharedvt = TRUE;
                // FIXME:
@@ -5715,59 +5777,55 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, JitFl
 
 #endif /* DISABLE_JIT */
 
-MonoJitInfo*
-mono_domain_lookup_shared_generic (MonoDomain *domain, MonoMethod *method)
+/*
+ * LOCKING: Acquires the jit code hash lock.
+ */
+static MonoJitInfo*
+lookup_method_inner (MonoDomain *domain, MonoMethod *method, MonoMethod *shared)
 {
+       MonoJitInfo *ji;
        static gboolean inited = FALSE;
        static int lookups = 0;
        static int failed_lookups = 0;
-       MonoJitInfo *ji;
 
-       ji = mono_internal_hash_table_lookup (&domain->jit_code_hash, mini_get_shared_method (method));
-       if (ji && !ji->has_generic_jit_info)
-               ji = NULL;
+       mono_domain_jit_code_hash_lock (domain);
+       ji = mono_internal_hash_table_lookup (&domain->jit_code_hash, method);
+       if (!ji && shared) {
+               /* Try generic sharing */
+               ji = mono_internal_hash_table_lookup (&domain->jit_code_hash, shared);
+               if (ji && !ji->has_generic_jit_info)
+                       ji = NULL;
+               if (!inited) {
+                       mono_counters_register ("Shared generic lookups", MONO_COUNTER_INT|MONO_COUNTER_GENERICS, &lookups);
+                       mono_counters_register ("Failed shared generic lookups", MONO_COUNTER_INT|MONO_COUNTER_GENERICS, &failed_lookups);
+                       inited = TRUE;
+               }
 
-       if (!inited) {
-               mono_counters_register ("Shared generic lookups", MONO_COUNTER_INT|MONO_COUNTER_GENERICS, &lookups);
-               mono_counters_register ("Failed shared generic lookups", MONO_COUNTER_INT|MONO_COUNTER_GENERICS, &failed_lookups);
-               inited = TRUE;
+               ++lookups;
+               if (!ji)
+                       ++failed_lookups;
        }
-
-       ++lookups;
-       if (!ji)
-               ++failed_lookups;
+       mono_domain_jit_code_hash_unlock (domain);
 
        return ji;
 }
 
-/*
- * LOCKING: Assumes domain->jit_code_hash_lock is held.
- */
-static MonoJitInfo*
-lookup_method_inner (MonoDomain *domain, MonoMethod *method)
-{
-       MonoJitInfo *ji = mono_internal_hash_table_lookup (&domain->jit_code_hash, method);
-
-       if (ji)
-               return ji;
-
-       if (!mono_method_is_generic_sharable (method, FALSE))
-               return NULL;
-       return mono_domain_lookup_shared_generic (domain, method);
-}
-
 static MonoJitInfo*
 lookup_method (MonoDomain *domain, MonoMethod *method)
 {
-       MonoJitInfo *info;
+       MonoJitInfo *ji;
+       MonoMethod *shared;
 
-       mono_loader_lock (); /*FIXME lookup_method_inner acquired it*/
-       mono_domain_jit_code_hash_lock (domain);
-       info = lookup_method_inner (domain, method);
-       mono_domain_jit_code_hash_unlock (domain);
-       mono_loader_unlock ();
+       ji = lookup_method_inner (domain, method, NULL);
 
-       return info;
+       if (!ji) {
+               if (!mono_method_is_generic_sharable (method, FALSE))
+                       return NULL;
+               shared = mini_get_shared_method (method);
+               ji = lookup_method_inner (domain, method, shared);
+       }
+
+       return ji;
 }
 
 #if ENABLE_JIT_MAP
@@ -5819,7 +5877,7 @@ mono_jit_compile_method_inner (MonoMethod *method, MonoDomain *target_domain, in
        MonoException *ex = NULL;
        guint32 prof_options;
        GTimer *jit_timer;
-       MonoMethod *prof_method;
+       MonoMethod *prof_method, *shared;
 
 #ifdef MONO_USE_AOT_COMPILER
        if (opt & MONO_OPT_AOT) {
@@ -5854,7 +5912,7 @@ mono_jit_compile_method_inner (MonoMethod *method, MonoDomain *target_domain, in
                        else
                                mono_lookup_pinvoke_call (method, NULL, NULL);
                }
-               nm = mono_marshal_get_native_wrapper (method, check_for_pending_exc, FALSE);
+               nm = mono_marshal_get_native_wrapper (method, check_for_pending_exc, mono_aot_only);
                code = mono_get_addr_from_ftnptr (mono_compile_method (nm));
                jinfo = mono_jit_info_table_find (target_domain, code);
                if (!jinfo)
@@ -6043,7 +6101,16 @@ mono_jit_compile_method_inner (MonoMethod *method, MonoDomain *target_domain, in
                return NULL;
        }
 
-       mono_loader_lock (); /*FIXME lookup_method_inner requires the loader lock*/
+       if (mono_method_is_generic_sharable (method, FALSE))
+               shared = mini_get_shared_method (method);
+       else
+               shared = NULL;
+
+       /*
+        * FIXME: lookup_method_inner requires the loader lock.
+        * FIXME: This is no longer true, can this be dropped ?
+        */
+       mono_loader_lock ();
        mono_domain_lock (target_domain);
 
        /* Check if some other thread already did the job. In this case, we can
@@ -6051,7 +6118,7 @@ mono_jit_compile_method_inner (MonoMethod *method, MonoDomain *target_domain, in
 
        mono_domain_jit_code_hash_lock (target_domain);
 
-       info = lookup_method_inner (target_domain, method);
+       info = lookup_method_inner (target_domain, method, shared);
        if (info) {
                /* We can't use a domain specific method in another domain */
                if ((target_domain == mono_domain_get ()) || info->domain_neutral) {
@@ -6694,10 +6761,12 @@ SIG_HANDLER_FUNC (, mono_sigfpe_signal_handler)
 #endif
 
        if (!ji) {
-               if (mono_chain_signal (SIG_HANDLER_PARAMS))
+               if (!mono_do_crash_chaining && mono_chain_signal (SIG_HANDLER_PARAMS))
                        return;
 
                mono_handle_native_sigsegv (SIGSEGV, ctx);
+               if (mono_do_crash_chaining)
+                       mono_chain_signal (SIG_HANDLER_PARAMS);
        }
        
        mono_arch_handle_exception (ctx, exc);
@@ -6745,9 +6814,11 @@ SIG_HANDLER_FUNC (, mono_sigsegv_signal_handler)
 
        /* The thread might no be registered with the runtime */
        if (!mono_domain_get () || !jit_tls) {
-               if (mono_chain_signal (SIG_HANDLER_PARAMS))
+               if (!mono_do_crash_chaining && mono_chain_signal (SIG_HANDLER_PARAMS))
                        return;
                mono_handle_native_sigsegv (SIGSEGV, ctx);
+               if (mono_do_crash_chaining)
+                       mono_chain_signal (SIG_HANDLER_PARAMS);
        }
 
        ji = mono_jit_info_table_find (mono_domain_get (), mono_arch_ip_from_context (ctx));
@@ -6786,10 +6857,13 @@ SIG_HANDLER_FUNC (, mono_sigsegv_signal_handler)
 #else
 
        if (!ji) {
-               if (mono_chain_signal (SIG_HANDLER_PARAMS))
+               if (!mono_do_crash_chaining && mono_chain_signal (SIG_HANDLER_PARAMS))
                        return;
 
                mono_handle_native_sigsegv (SIGSEGV, ctx);
+
+               if (mono_do_crash_chaining)
+                       mono_chain_signal (SIG_HANDLER_PARAMS);
        }
                        
        mono_arch_handle_exception (ctx, NULL);
@@ -6907,6 +6981,8 @@ mini_parse_debug_options (void)
                        debug_options.no_gdb_backtrace = TRUE;
                else if (!strcmp (arg, "suspend-on-sigsegv"))
                        debug_options.suspend_on_sigsegv = TRUE;
+               else if (!strcmp (arg, "suspend-on-exception"))
+                       debug_options.suspend_on_exception = TRUE;
                else if (!strcmp (arg, "suspend-on-unhandled"))
                        debug_options.suspend_on_unhandled = TRUE;
                else if (!strcmp (arg, "dont-free-domains"))
@@ -6925,9 +7001,13 @@ mini_parse_debug_options (void)
                        debug_options.better_cast_details = TRUE;
                else if (!strcmp (arg, "soft-breakpoints"))
                        debug_options.soft_breakpoints = TRUE;
+               else if (!strcmp (arg, "check-pinvoke-callconv"))
+                       debug_options.check_pinvoke_callconv = TRUE;
+               else if (!strcmp (arg, "debug-domain-unload"))
+                       mono_enable_debug_domain_unload (TRUE);
                else {
                        fprintf (stderr, "Invalid option for the MONO_DEBUG env variable: %s\n", arg);
-                       fprintf (stderr, "Available options: 'handle-sigint', 'keep-delegates', 'reverse-pinvoke-exceptions', 'collect-pagefault-stats', 'break-on-unverified', 'no-gdb-backtrace', 'dont-free-domains', 'suspend-on-sigsegv', 'suspend-on-unhandled', 'dyn-runtime-invoke', 'gdb', 'explicit-null-checks', 'init-stacks'\n");
+                       fprintf (stderr, "Available options: 'handle-sigint', 'keep-delegates', 'reverse-pinvoke-exceptions', 'collect-pagefault-stats', 'break-on-unverified', 'no-gdb-backtrace', 'dont-free-domains', 'suspend-on-sigsegv', 'suspend-on-exception', 'suspend-on-unhandled', 'dyn-runtime-invoke', 'gdb', 'explicit-null-checks', 'init-stacks', 'check-pinvoke-callconv', 'debug-domain-unload'\n");
                        exit (1);
                }
        }
@@ -7008,7 +7088,24 @@ register_jit_stats (void)
 
 static void runtime_invoke_info_free (gpointer value);
 static void seq_point_info_free (gpointer value);
+
+static gint
+class_method_pair_equal (gconstpointer ka, gconstpointer kb)
+{
+       const MonoClassMethodPair *apair = ka;
+       const MonoClassMethodPair *bpair = kb;
+
+       return apair->klass == bpair->klass && apair->method == bpair->method ? 1 : 0;
+}
+
+static guint
+class_method_pair_hash (gconstpointer data)
+{
+       const MonoClassMethodPair *pair = data;
+
+       return (gsize)pair->klass ^ (gsize)pair->method;
+}
+
 static void
 mini_create_jit_domain_info (MonoDomain *domain)
 {
@@ -7017,7 +7114,7 @@ mini_create_jit_domain_info (MonoDomain *domain)
        info->class_init_trampoline_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
        info->jump_trampoline_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
        info->jit_trampoline_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
-       info->delegate_trampoline_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
+       info->delegate_trampoline_hash = g_hash_table_new (class_method_pair_hash, class_method_pair_equal);
        info->llvm_vcall_trampoline_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
        info->runtime_invoke_hash = g_hash_table_new_full (mono_aligned_addr_hash, NULL, NULL, runtime_invoke_info_free);
        info->seq_points = g_hash_table_new_full (mono_aligned_addr_hash, NULL, NULL, seq_point_info_free);
@@ -7034,6 +7131,13 @@ delete_jump_list (gpointer key, gpointer value, gpointer user_data)
        g_slist_free (jlist->list);
 }
 
+static void
+delete_got_slot_list (gpointer key, gpointer value, gpointer user_data)
+{
+       GSList *list = value;
+       g_slist_free (list);
+}
+
 static void
 dynamic_method_info_free (gpointer key, gpointer value, gpointer user_data)
 {
@@ -7075,7 +7179,7 @@ mini_free_jit_domain_info (MonoDomain *domain)
        g_hash_table_foreach (info->jump_target_hash, delete_jump_list, NULL);
        g_hash_table_destroy (info->jump_target_hash);
        if (info->jump_target_got_slot_hash) {
-               g_hash_table_foreach (info->jump_target_got_slot_hash, delete_jump_list, NULL);
+               g_hash_table_foreach (info->jump_target_got_slot_hash, delete_got_slot_list, NULL);
                g_hash_table_destroy (info->jump_target_got_slot_hash);
        }
        if (info->dynamic_code_hash) {
@@ -7098,6 +7202,9 @@ mini_free_jit_domain_info (MonoDomain *domain)
                mono_debugger_agent_free_domain_info (domain);
        if (info->gsharedvt_arg_tramp_hash)
                g_hash_table_destroy (info->gsharedvt_arg_tramp_hash);
+#ifdef ENABLE_LLVM
+       mono_llvm_free_domain_info (domain);
+#endif
 
        g_free (domain->runtime_info);
        domain->runtime_info = NULL;
@@ -7517,7 +7624,7 @@ mini_init (const char *filename, const char *runtime_version)
 #endif
 
 #ifdef TARGET_IOS
-       register_icall (pthread_getspecific, "pthread_getspecific", NULL, TRUE);
+       register_icall (pthread_getspecific, "pthread_getspecific", "ptr ptr", TRUE);
 #endif
 
        mono_generic_sharing_init ();
@@ -7581,10 +7688,6 @@ print_jit_stats (void)
                g_print ("Shared generic methods: %ld\n", mono_stats.generics_shared_methods);
                g_print ("Shared vtype generic methods: %ld\n", mono_stats.gsharedvt_methods);
 
-               g_print ("Dynamic code allocs:    %ld\n", mono_stats.dynamic_code_alloc_count);
-               g_print ("Dynamic code bytes:     %ld\n", mono_stats.dynamic_code_bytes_count);
-               g_print ("Dynamic code frees:     %ld\n", mono_stats.dynamic_code_frees_count);
-
                g_print ("IMT tables size:        %ld\n", mono_stats.imt_tables_size);
                g_print ("IMT number of tables:   %ld\n", mono_stats.imt_number_of_tables);
                g_print ("IMT number of methods:  %ld\n", mono_stats.imt_number_of_methods);
@@ -7598,7 +7701,6 @@ print_jit_stats (void)
                g_print ("JIT info table removes: %ld\n", mono_stats.jit_info_table_remove_count);
                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_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);
@@ -7669,6 +7771,8 @@ mini_cleanup (MonoDomain *domain)
        g_free (emul_opcode_opcodes);
        g_free (vtable_trampolines);
 
+       mono_tramp_info_cleanup ();
+
        mono_arch_cleanup ();
 
        mono_generic_sharing_cleanup ();
@@ -7856,7 +7960,17 @@ mono_arch_get_gsharedvt_trampoline (MonoTrampInfo **info, gboolean aot)
 
 #endif
 
-#if defined(MONO_ARCH_GSHAREDVT_SUPPORTED) && !defined(MONO_GSHARING)
+#ifndef MONO_ARCH_HAVE_OPCODE_SUPPORTED
+
+gboolean
+mono_arch_opcode_supported (int opcode)
+{
+       return TRUE;
+}
+
+#endif
+
+#if defined(MONO_ARCH_GSHAREDVT_SUPPORTED) && !defined(ENABLE_GSHAREDVT)
 
 gboolean
 mono_arch_gsharedvt_sig_supported (MonoMethodSignature *sig)