/* 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] = {
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);
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);
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);
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))
/* 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;
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);
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;
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;
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*
{
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;
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;
}
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);
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);
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
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);
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.
*/
else
method = "Unmanaged";
fprintf (stderr, "At %s\n", method);
- abort ();
+ _exit (1);
} else {
mono_arch_handle_altstack_exception (ctx, info->si_addr, FALSE);
}
{
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;
}
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 *
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);