* mini-codegen.c (mono_local_regalloc): Make free mask
[mono.git] / mono / mini / mini.c
index 7b06779dc1c1b127a935e68901ff1db0b25c2b8e..b074740dc7456833ac2c336b2d7cab922a15acdc 100644 (file)
@@ -216,6 +216,8 @@ gboolean check_for_pending_exc = TRUE;
 /* Whenever to disable passing/returning small valuetypes in registers for managed methods */
 gboolean disable_vtypes_in_regs = FALSE;
 
+gboolean mono_dont_free_global_codeman;
+
 #ifdef DISABLE_JIT
 /* Define this here, since many files reference it */
 const guint8 mono_burg_arity [MBMAX_OPCODES] = {
@@ -268,7 +270,7 @@ get_method_from_ip (void *ip)
                user_data.ip = ip;
                user_data.method = NULL;
                mono_domain_lock (domain);
-               g_hash_table_foreach (domain->jit_trampoline_hash, find_tramp, &user_data);
+               g_hash_table_foreach (domain_jit_info (domain)->jit_trampoline_hash, find_tramp, &user_data);
                mono_domain_unlock (domain);
                if (user_data.method) {
                        char *mname = mono_method_full_name (user_data.method, TRUE);
@@ -334,7 +336,7 @@ mono_print_method_from_ip (void *ip)
                user_data.ip = ip;
                user_data.method = NULL;
                mono_domain_lock (domain);
-               g_hash_table_foreach (domain->jit_trampoline_hash, find_tramp, &user_data);
+               g_hash_table_foreach (domain_jit_info (domain)->jit_trampoline_hash, find_tramp, &user_data);
                mono_domain_unlock (domain);
                if (user_data.method) {
                        char *mname = mono_method_full_name (user_data.method, TRUE);
@@ -9318,7 +9320,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                MonoInst *argconst;
                                MonoMethod *cil_method, *ctor_method;
                                int temp;
-                               gboolean is_shared = FALSE;
+                               gboolean needs_static_rgctx_invoke;
 
                                CHECK_STACK_OVF (1);
                                CHECK_OPSIZE (6);
@@ -9331,15 +9333,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                if (cfg->generic_sharing_context)
                                        context_used = mono_method_check_context_used (cmethod);
 
-                               if (mono_class_generic_sharing_enabled (cmethod->klass)) {
-                                       if (((cmethod->flags & METHOD_ATTRIBUTE_STATIC) || cmethod->klass->valuetype) &&
-                                                       (cmethod->klass->generic_class ||
-                                                       cmethod->klass->generic_container)) {
-                                               is_shared = TRUE;
-                                       }
-                                       if (cmethod->is_inflated && mono_method_get_context (cmethod)->method_inst)
-                                               is_shared = TRUE;
-                               }
+                               needs_static_rgctx_invoke = mono_method_needs_static_rgctx_invoke (cmethod, TRUE);
 
                                cil_method = cmethod;
                                if (!dont_verify && !cfg->skip_visibility && !mono_method_can_access_method (method, cmethod))
@@ -9359,7 +9353,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                /* FIXME: SGEN support */
                                /* FIXME: handle shared static generic methods */
                                /* FIXME: handle this in shared code */
-                               if (!is_shared && !context_used && (sp > stack_start) && (ip + 6 + 5 < end) && ip_in_bb (cfg, bblock, ip + 6) && (ip [6] == CEE_NEWOBJ) && (ctor_method = mini_get_method (cfg, method, read32 (ip + 7), NULL, generic_context)) && (ctor_method->klass->parent == mono_defaults.multicastdelegate_class)) {
+                               if (!needs_static_rgctx_invoke && !context_used && (sp > stack_start) && (ip + 6 + 5 < end) && ip_in_bb (cfg, bblock, ip + 6) && (ip [6] == CEE_NEWOBJ) && (ctor_method = mini_get_method (cfg, method, read32 (ip + 7), NULL, generic_context)) && (ctor_method->klass->parent == mono_defaults.multicastdelegate_class)) {
                                        MonoInst *target_ins;
 
                                        ip += 6;
@@ -9379,14 +9373,14 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                if (context_used) {
                                        MonoInst *rgctx;
 
-                                       if (is_shared)
+                                       if (needs_static_rgctx_invoke)
                                                cmethod = mono_marshal_get_static_rgctx_invoke (cmethod);
 
                                        GET_RGCTX (rgctx, context_used);
                                        argconst = get_runtime_generic_context_method (cfg, method, context_used,
                                                        bblock, cmethod,
                                                        generic_context, rgctx, MONO_RGCTX_INFO_METHOD, ip);
-                               } else if (is_shared) {
+                               } else if (needs_static_rgctx_invoke) {
                                        NEW_METHODCONST (cfg, argconst, mono_marshal_get_static_rgctx_invoke (cmethod));
                                } else {
                                        NEW_METHODCONST (cfg, argconst, cmethod);
@@ -10017,8 +10011,8 @@ create_helper_signature (void)
        helper_sig_rgctx_lazy_fetch_trampoline = mono_create_icall_signature ("ptr ptr");
 }
 
-gconstpointer
-mono_icall_get_wrapper (MonoJitICallInfo* callinfo)
+static gconstpointer
+mono_icall_get_wrapper_full (MonoJitICallInfo* callinfo, gboolean do_compile)
 {
        char *name;
        MonoMethod *wrapper;
@@ -10047,7 +10041,10 @@ mono_icall_get_wrapper (MonoJitICallInfo* callinfo)
        wrapper = mono_marshal_get_icall_wrapper (callinfo->sig, name, callinfo->func, check_for_pending_exc);
        g_free (name);
 
-       trampoline = mono_create_ftnptr (domain, mono_create_jit_trampoline_in_domain (domain, wrapper));
+       if (do_compile)
+               trampoline = mono_compile_method (wrapper);
+       else
+               trampoline = mono_create_ftnptr (domain, mono_create_jit_trampoline_in_domain (domain, wrapper));
        mono_register_jit_icall_wrapper (callinfo, trampoline);
 
        callinfo->trampoline = trampoline;
@@ -10057,12 +10054,18 @@ mono_icall_get_wrapper (MonoJitICallInfo* callinfo)
        return callinfo->trampoline;
 }
 
+gconstpointer
+mono_icall_get_wrapper (MonoJitICallInfo* callinfo)
+{
+       return mono_icall_get_wrapper_full (callinfo, FALSE);
+}
+
 static void
 mono_dynamic_code_hash_insert (MonoDomain *domain, MonoMethod *method, MonoJitDynamicMethodInfo *ji)
 {
-       if (!domain->dynamic_code_hash)
-               domain->dynamic_code_hash = g_hash_table_new (NULL, NULL);
-       g_hash_table_insert (domain->dynamic_code_hash, method, ji);
+       if (!domain_jit_info (domain)->dynamic_code_hash)
+               domain_jit_info (domain)->dynamic_code_hash = g_hash_table_new (NULL, NULL);
+       g_hash_table_insert (domain_jit_info (domain)->dynamic_code_hash, method, ji);
 }
 
 static MonoJitDynamicMethodInfo*
@@ -10070,8 +10073,8 @@ mono_dynamic_code_hash_lookup (MonoDomain *domain, MonoMethod *method)
 {
        MonoJitDynamicMethodInfo *res;
 
-       if (domain->dynamic_code_hash)
-               res = g_hash_table_lookup (domain->dynamic_code_hash, method);
+       if (domain_jit_info (domain)->dynamic_code_hash)
+               res = g_hash_table_lookup (domain_jit_info (domain)->dynamic_code_hash, method);
        else
                res = NULL;
        return res;
@@ -12136,11 +12139,11 @@ mono_codegen (MonoCompile *cfg)
                        unsigned char *ip = cfg->native_code + patch_info->ip.i;
 
                        mono_domain_lock (domain);
-                       if (!domain->jump_target_hash)
-                               domain->jump_target_hash = g_hash_table_new (NULL, NULL);
-                       list = g_hash_table_lookup (domain->jump_target_hash, patch_info->data.method);
+                       if (!domain_jit_info (domain)->jump_target_hash)
+                               domain_jit_info (domain)->jump_target_hash = g_hash_table_new (NULL, NULL);
+                       list = g_hash_table_lookup (domain_jit_info (domain)->jump_target_hash, patch_info->data.method);
                        list = g_slist_prepend (list, ip);
-                       g_hash_table_insert (domain->jump_target_hash, patch_info->data.method, list);
+                       g_hash_table_insert (domain_jit_info (domain)->jump_target_hash, patch_info->data.method, list);
                        mono_domain_unlock (domain);
                        break;
                }
@@ -13134,7 +13137,17 @@ mono_jit_compile_method_inner (MonoMethod *method, MonoDomain *target_domain, in
                        if (*name == '.' && (strcmp (name, ".ctor") == 0)) {
                                MonoJitICallInfo *mi = mono_find_jit_icall_by_name ("mono_delegate_ctor");
                                g_assert (mi);
-                               return mono_get_addr_from_ftnptr ((gpointer)mono_icall_get_wrapper (mi));
+                               /*
+                                * We need to make sure this wrapper
+                                * is compiled because it might end up
+                                * in an (M)RGCTX if generic sharing
+                                * is enabled, and would be called
+                                * indirectly.  If it were a
+                                * trampoline we'd try to patch that
+                                * indirect call, which is not
+                                * possible.
+                                */
+                               return mono_get_addr_from_ftnptr ((gpointer)mono_icall_get_wrapper_full (mi, TRUE));
                        } else if (*name == 'I' && (strcmp (name, "Invoke") == 0)) {
 #ifdef MONO_ARCH_HAVE_CREATE_DELEGATE_TRAMPOLINE
                                return mono_create_delegate_trampoline (method->klass);
@@ -13277,16 +13290,16 @@ mono_jit_compile_method_inner (MonoMethod *method, MonoDomain *target_domain, in
 
        mono_destroy_compile (cfg);
 
-       if (target_domain->jump_target_hash) {
+       if (domain_jit_info (target_domain)->jump_target_hash) {
                MonoJumpInfo patch_info;
                GSList *list, *tmp;
-               list = g_hash_table_lookup (target_domain->jump_target_hash, method);
+               list = g_hash_table_lookup (domain_jit_info (target_domain)->jump_target_hash, method);
                if (list) {
                        patch_info.next = NULL;
                        patch_info.ip.i = 0;
                        patch_info.type = MONO_PATCH_INFO_METHOD_JUMP;
                        patch_info.data.method = method;
-                       g_hash_table_remove (target_domain->jump_target_hash, method);
+                       g_hash_table_remove (domain_jit_info (target_domain)->jump_target_hash, method);
                }
                for (tmp = list; tmp; tmp = tmp->next)
                        mono_arch_patch_code (NULL, target_domain, tmp->data, &patch_info, TRUE);
@@ -13399,9 +13412,9 @@ mono_jit_free_method (MonoDomain *domain, MonoMethod *method)
        if (!ji)
                return;
        mono_domain_lock (domain);
-       g_hash_table_remove (domain->dynamic_code_hash, method);
+       g_hash_table_remove (domain_jit_info (domain)->dynamic_code_hash, method);
        mono_internal_hash_table_remove (&domain->jit_code_hash, method);
-       g_hash_table_remove (domain->jump_trampoline_hash, method);
+       g_hash_table_remove (domain_jit_info (domain)->jump_trampoline_hash, method);
        mono_domain_unlock (domain);
 
 #ifdef MONO_ARCH_HAVE_INVALIDATE_METHOD
@@ -13475,15 +13488,10 @@ mono_jit_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObjec
                return NULL;
        }
 
-       if (((method->flags & METHOD_ATTRIBUTE_STATIC) ||
-                               method->klass->valuetype ||
-                               (method->is_inflated && mono_method_get_context (method)->method_inst)) &&
-                       mono_class_generic_sharing_enabled (method->klass) &&
-                       mono_method_is_generic_sharable_impl (method, FALSE)) {
+       if (mono_method_needs_static_rgctx_invoke (method, FALSE))
                to_compile = mono_marshal_get_static_rgctx_invoke (method);
-       } else {
+       else
                to_compile = method;
-       }
 
        invoke = mono_marshal_get_runtime_invoke (method);
        runtime_invoke = mono_jit_compile_method (invoke);
@@ -13602,30 +13610,9 @@ SIG_HANDLER_SIGNATURE (sigsegv_signal_handler)
        ji = mono_jit_info_table_find (mono_domain_get (), mono_arch_ip_from_context (ctx));
 
 #ifdef MONO_ARCH_SIGSEGV_ON_ALTSTACK
-       /* we got a stack overflow in the soft-guard pages
-        * There are two cases:
-        * 1) managed code caused the overflow: we unprotect the soft-guard page
-        * and let the arch-specific code trigger the exception handling mechanism
-        * in the thread stack. The soft-guard pages will be protected again as the stack is unwound.
-        * 2) unmanaged code caused the overflow: we unprotect the soft-guard page
-        * and hope we can continue with those enabled, at least until the hard-guard page
-        * is hit. The alternative to continuing here is to just print a message and abort.
-        * We may add in the future the code to protect the pages again in the codepath
-        * when we return from unmanaged to managed code.
-        */
-       if (jit_tls->stack_ovf_guard_size && (guint8*)info->si_addr >= (guint8*)jit_tls->stack_ovf_guard_base &&
-                       (guint8*)info->si_addr < (guint8*)jit_tls->stack_ovf_guard_base + jit_tls->stack_ovf_guard_size) {
-               mono_mprotect (jit_tls->stack_ovf_guard_base, jit_tls->stack_ovf_guard_size, MONO_MMAP_READ|MONO_MMAP_WRITE|MONO_MMAP_EXEC);
-               if (ji) {
-                       mono_arch_handle_altstack_exception (ctx, info->si_addr, TRUE);
-               } else {
-                       /* We print a message: after this even managed stack overflows
-                        * may crash the runtime
-                        */
-                       fprintf (stderr, "Stack overflow in unmanaged: IP: %p, fault addr: %p\n", mono_arch_ip_from_context (ctx), (gpointer)info->si_addr);
-               }
+       if (mono_handle_soft_stack_ovf (jit_tls, ji, ctx, (guint8*)info->si_addr))
                return;
-       }
+
        /* The hard-guard page has been hit: there is not much we can do anymore
         * Print a hopefully clear message and abort.
         */
@@ -13639,7 +13626,7 @@ SIG_HANDLER_SIGNATURE (sigsegv_signal_handler)
                else
                        method = "Unmanaged";
                fprintf (stderr, "At %s\n", method);
-               abort ();
+               _exit (1);
        } else {
                mono_arch_handle_altstack_exception (ctx, info->si_addr, FALSE);
        }
@@ -14270,6 +14257,11 @@ mini_create_jit_domain_info (MonoDomain *domain)
 {
        MonoJitDomainInfo *info = g_new0 (MonoJitDomainInfo, 1);
 
+       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);
+
        domain->runtime_info = info;
 }
 
@@ -14279,16 +14271,40 @@ delete_jump_list (gpointer key, gpointer value, gpointer user_data)
        g_slist_free (value);
 }
 
+static void
+dynamic_method_info_free (gpointer key, gpointer value, gpointer user_data)
+{
+       MonoJitDynamicMethodInfo *di = value;
+       mono_code_manager_destroy (di->code_mp);
+       g_free (di);
+}
+
 static void
 mini_free_jit_domain_info (MonoDomain *domain)
 {
-       MonoJitDomainInfo *info = jit_domain_info (domain);
+       MonoJitDomainInfo *info = domain_jit_info (domain);
 
+       if (info->jump_target_hash) {
+               g_hash_table_foreach (info->jump_target_hash, delete_jump_list, NULL);
+               g_hash_table_destroy (info->jump_target_hash);
+       }
        if (info->jump_target_got_slot_hash) {
                g_hash_table_foreach (info->jump_target_got_slot_hash, delete_jump_list, NULL);
                g_hash_table_destroy (info->jump_target_got_slot_hash);
        }
+       if (info->dynamic_code_hash) {
+               g_hash_table_foreach (info->dynamic_code_hash, dynamic_method_info_free, NULL);
+               g_hash_table_destroy (info->dynamic_code_hash);
+       }
+       if (info->method_code_hash)
+               g_hash_table_destroy (info->method_code_hash);
+       g_hash_table_destroy (info->class_init_trampoline_hash);
+       g_hash_table_destroy (info->jump_trampoline_hash);
+       g_hash_table_destroy (info->jit_trampoline_hash);
+       g_hash_table_destroy (info->delegate_trampoline_hash);
+
        g_free (domain->runtime_info);
+       domain->runtime_info = NULL;
 }
 
 MonoDomain *
@@ -14740,7 +14756,8 @@ mini_cleanup (MonoDomain *domain)
 
        mono_trampolines_cleanup ();
 
-       mono_code_manager_destroy (global_codeman);
+       if (!mono_dont_free_global_codeman)
+               mono_code_manager_destroy (global_codeman);
        g_hash_table_destroy (jit_icall_name_hash);
        g_free (emul_opcode_map);