#include <mono/metadata/marshal.h>
#include <mono/metadata/tabledefs.h>
#include <mono/utils/mono-counters.h>
+#include <mono/utils/mono-error-internals.h>
#include "mini.h"
#include "debug-mini.h"
static GHashTable *class_init_hash_addr = NULL;
static GHashTable *rgctx_lazy_fetch_trampoline_hash = NULL;
static GHashTable *rgctx_lazy_fetch_trampoline_hash_addr = NULL;
+static guint32 trampoline_calls;
#define mono_trampolines_lock() EnterCriticalSection (&trampolines_mutex)
#define mono_trampolines_unlock() LeaveCriticalSection (&trampolines_mutex)
static gpointer
common_call_trampoline (mgreg_t *regs, guint8 *code, gpointer arg, guint8* tramp, MonoVTable *vt, gpointer *vtable_slot, gboolean need_rgctx_tramp)
{
- gpointer addr;
+ gpointer addr, compiled_method;
gboolean generic_shared = FALSE;
MonoMethod *m;
MonoMethod *declaring = NULL;
* Call this only if the called method is shared, cause it is slow/loads a lot of
* data in AOT.
*/
- ji = mono_jit_info_table_find (mono_domain_get (), (char*)code);
+ ji = mini_jit_info_table_find (mono_domain_get (), (char*)code, NULL);
if (ji && ji->from_llvm) {
/* LLVM can't pass an rgctx arg */
need_rgctx_tramp = TRUE;
MonoJitInfo *ji;
if (code)
- ji = mono_jit_info_table_find (mono_domain_get (), (char*)code);
+ ji = mini_jit_info_table_find (mono_domain_get (), (char*)code, NULL);
else
ji = NULL;
if (!code && mono_method_needs_static_rgctx_invoke (m, FALSE))
need_rgctx_tramp = TRUE;
- addr = mono_compile_method (m);
+ addr = compiled_method = mono_compile_method (m);
g_assert (addr);
mono_debugger_trampoline_compiled (code, m, addr);
guint8 *plt_entry = mono_aot_get_plt_entry (code);
if (plt_entry) {
- mono_arch_patch_plt_entry (plt_entry, NULL, regs, addr);
- } else if (!generic_shared || (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
- mono_domain_lookup_shared_generic (mono_domain_get (), declaring)) {
+ mono_aot_patch_plt_entry (plt_entry, NULL, regs, addr);
+ } else {
if (generic_shared) {
if (m->wrapper_type != MONO_WRAPPER_NONE)
m = mono_marshal_method_from_wrapper (m);
}
/* Patch calling code */
- if (plt_entry) {
-
- } else {
+ {
MonoJitInfo *target_ji =
- mono_jit_info_table_find (mono_domain_get (), mono_get_addr_from_ftnptr (addr));
+ mono_jit_info_table_find (mono_domain_get (), mono_get_addr_from_ftnptr (compiled_method));
if (!ji)
ji = mono_jit_info_table_find (mono_domain_get (), (char*)code);
int displacement;
MonoVTable *vt;
+ trampoline_calls ++;
+
if (code && !mono_use_llvm)
vt = mono_arch_get_vcall_slot (code, regs, &displacement);
else
gpointer *vtable_slot;
int slot;
+ trampoline_calls ++;
+
/*
* We have the method which is called, we need to obtain the vtable slot without
* disassembly which is impossible with LLVM.
MonoMethod *imt_method, *declaring;
gpointer addr;
+ trampoline_calls ++;
+
g_assert (m->is_generic);
if (m->is_inflated)
MonoMethod *method = NULL;
gpointer addr;
gpointer *vtable_slot;
- gboolean is_got_entry;
guint8 *plt_entry;
- gboolean need_rgctx_tramp = FALSE;
+
+ trampoline_calls ++;
image = *(gpointer*)(gpointer)token_info;
token_info += sizeof (gpointer);
plt_entry = mono_aot_get_plt_entry (code);
g_assert (plt_entry);
- mono_arch_patch_plt_entry (plt_entry, NULL, regs, addr);
-
- is_got_entry = FALSE;
-
- /*
- * Since AOT code is only used in the root domain,
- * mono_domain_get () != mono_get_root_domain () means the calling method
- * is AppDomain:InvokeInDomain, so this is the same check as in
- * mono_method_same_domain () but without loading the metadata for the method.
- */
- if ((is_got_entry && (mono_domain_get () == mono_get_root_domain ())) || mono_domain_owns_vtable_slot (mono_domain_get (), vtable_slot)) {
-#ifdef MONO_ARCH_HAVE_IMT
- gboolean variance_used = FALSE;
- if (!method)
- method = mono_get_method (image, token, NULL);
- vtable_slot = mono_convert_imt_slot_to_vtable_slot (vtable_slot, regs, code, method, NULL, &need_rgctx_tramp, &variance_used);
-#endif
- *vtable_slot = addr;
- }
+ mono_aot_patch_plt_entry (plt_entry, NULL, regs, addr);
return addr;
}
guint32 plt_info_offset = mono_aot_get_plt_info_offset (regs, code);
gpointer res;
+ trampoline_calls ++;
+
res = mono_aot_plt_resolve (aot_module, plt_info_offset, code);
if (!res) {
if (mono_loader_get_last_error ())
{
guint8 *plt_entry = mono_aot_get_plt_entry (code);
+ trampoline_calls ++;
+
mono_runtime_class_init (vtable);
if (plt_entry) {
void
mono_generic_class_init_trampoline (mgreg_t *regs, guint8 *code, MonoVTable *vtable, guint8 *tramp)
{
+ trampoline_calls ++;
+
mono_runtime_class_init (vtable);
}
guint32 index = MONO_RGCTX_SLOT_INDEX (slot);
gboolean mrgctx = MONO_RGCTX_SLOT_IS_MRGCTX (slot);
+ trampoline_calls ++;
+
if (!inited) {
mono_counters_register ("RGCTX unmanaged lookups", MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &num_lookups);
inited = TRUE;
MonoJitInfo *ji;
MonoMethod *m;
MonoMethod *method = NULL;
- gboolean multicast, callvirt;
+ gboolean multicast, callvirt = FALSE;
gboolean need_rgctx_tramp = FALSE;
MonoMethod *invoke = tramp_data [0];
guint8 *impl_this = tramp_data [1];
guint8 *impl_nothis = tramp_data [2];
+ MonoError err;
+ MonoMethodSignature *sig;
+
+ trampoline_calls ++;
/* Obtain the delegate object according to the calling convention */
#endif
method = mono_marshal_get_remoting_invoke (method);
}
- else if (mono_method_signature (method)->hasthis && method->klass->valuetype)
- method = mono_marshal_get_unbox_wrapper (method);
+ else {
+ mono_error_init (&err);
+ sig = mono_method_signature_checked (method, &err);
+ if (!sig)
+ mono_error_raise_exception (&err);
+
+ if (sig->hasthis && method->klass->valuetype)
+ method = mono_marshal_get_unbox_wrapper (method);
+ }
} else {
ji = mono_jit_info_table_find (domain, mono_get_addr_from_ftnptr (delegate->method_ptr));
if (ji)
method = ji->method;
}
- callvirt = !delegate->target && method && mono_method_signature (method)->hasthis;
+
+ if (method) {
+ mono_error_init (&err);
+ sig = mono_method_signature_checked (method, &err);
+ if (!sig)
+ mono_error_raise_exception (&err);
+
+ callvirt = !delegate->target && sig->hasthis;
+ }
if (method && method->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED)
method = mono_marshal_get_synchronized_wrapper (method);
#endif
+#ifdef MONO_ARCH_HAVE_HANDLER_BLOCK_GUARD
+static gpointer
+mono_handler_block_guard_trampoline (mgreg_t *regs, guint8 *code, gpointer *tramp_data, guint8* tramp)
+{
+ MonoContext ctx;
+ MonoException *exc;
+ MonoJitTlsData *jit_tls = TlsGetValue (mono_jit_tls_id);
+ gpointer resume_ip = jit_tls->handler_block_return_address;
+
+ memcpy (&ctx, &jit_tls->ex_ctx, sizeof (MonoContext));
+ MONO_CONTEXT_SET_IP (&ctx, jit_tls->handler_block_return_address);
+
+ jit_tls->handler_block_return_address = NULL;
+ jit_tls->handler_block = NULL;
+
+ if (!resume_ip) /*this should not happen, but we should avoid crashing */
+ exc = mono_get_exception_execution_engine ("Invalid internal state, resuming abort after handler block but no resume ip found");
+ else
+ exc = mono_thread_resume_interruption ();
+
+ if (exc) {
+ static void (*restore_context) (MonoContext *);
+
+ if (!restore_context)
+ restore_context = mono_get_restore_context ();
+
+ mono_handle_exception (&ctx, exc, NULL, FALSE);
+ restore_context (&ctx);
+ }
+
+ return resume_ip;
+}
+
+gpointer
+mono_create_handler_block_trampoline (void)
+{
+ static gpointer code;
+
+ if (mono_aot_only) {
+ g_assert (0);
+ return code;
+ }
+
+ mono_trampolines_lock ();
+
+ if (!code)
+ code = mono_arch_create_handler_block_trampoline ();
+
+ mono_trampolines_unlock ();
+
+ return code;
+}
+#endif
+
/*
* mono_get_trampoline_func:
*
#ifdef MONO_ARCH_LLVM_SUPPORTED
case MONO_TRAMPOLINE_LLVM_VCALL:
return mono_llvm_vcall_trampoline;
+#endif
+#ifdef MONO_ARCH_HAVE_HANDLER_BLOCK_GUARD
+ case MONO_TRAMPOLINE_HANDLER_BLOCK_GUARD:
+ return mono_handler_block_guard_trampoline;
#endif
default:
g_assert_not_reached ();
}
}
+static guchar*
+create_trampoline_code (MonoTrampolineType tramp_type)
+{
+ MonoTrampInfo *info;
+ guchar *code;
+
+ code = mono_arch_create_generic_trampoline (tramp_type, &info, FALSE);
+ if (info) {
+ mono_save_trampoline_xdebug_info (info->name, info->code, info->code_size, info->unwind_ops);
+ mono_tramp_info_free (info);
+ }
+
+ return code;
+}
+
void
mono_trampolines_init (void)
{
if (mono_aot_only)
return;
- mono_trampoline_code [MONO_TRAMPOLINE_JIT] = mono_arch_create_trampoline_code (MONO_TRAMPOLINE_JIT);
- mono_trampoline_code [MONO_TRAMPOLINE_JUMP] = mono_arch_create_trampoline_code (MONO_TRAMPOLINE_JUMP);
- mono_trampoline_code [MONO_TRAMPOLINE_CLASS_INIT] = mono_arch_create_trampoline_code (MONO_TRAMPOLINE_CLASS_INIT);
- mono_trampoline_code [MONO_TRAMPOLINE_GENERIC_CLASS_INIT] = mono_arch_create_trampoline_code (MONO_TRAMPOLINE_GENERIC_CLASS_INIT);
- mono_trampoline_code [MONO_TRAMPOLINE_RGCTX_LAZY_FETCH] = mono_arch_create_trampoline_code (MONO_TRAMPOLINE_RGCTX_LAZY_FETCH);
+ mono_trampoline_code [MONO_TRAMPOLINE_JIT] = create_trampoline_code (MONO_TRAMPOLINE_JIT);
+ mono_trampoline_code [MONO_TRAMPOLINE_JUMP] = create_trampoline_code (MONO_TRAMPOLINE_JUMP);
+ mono_trampoline_code [MONO_TRAMPOLINE_CLASS_INIT] = create_trampoline_code (MONO_TRAMPOLINE_CLASS_INIT);
+ mono_trampoline_code [MONO_TRAMPOLINE_GENERIC_CLASS_INIT] = create_trampoline_code (MONO_TRAMPOLINE_GENERIC_CLASS_INIT);
+ mono_trampoline_code [MONO_TRAMPOLINE_RGCTX_LAZY_FETCH] = create_trampoline_code (MONO_TRAMPOLINE_RGCTX_LAZY_FETCH);
#ifdef MONO_ARCH_AOT_SUPPORTED
- mono_trampoline_code [MONO_TRAMPOLINE_AOT] = mono_arch_create_trampoline_code (MONO_TRAMPOLINE_AOT);
- mono_trampoline_code [MONO_TRAMPOLINE_AOT_PLT] = mono_arch_create_trampoline_code (MONO_TRAMPOLINE_AOT_PLT);
+ mono_trampoline_code [MONO_TRAMPOLINE_AOT] = create_trampoline_code (MONO_TRAMPOLINE_AOT);
+ mono_trampoline_code [MONO_TRAMPOLINE_AOT_PLT] = create_trampoline_code (MONO_TRAMPOLINE_AOT_PLT);
#endif
#ifdef MONO_ARCH_HAVE_CREATE_DELEGATE_TRAMPOLINE
- mono_trampoline_code [MONO_TRAMPOLINE_DELEGATE] = mono_arch_create_trampoline_code (MONO_TRAMPOLINE_DELEGATE);
+ mono_trampoline_code [MONO_TRAMPOLINE_DELEGATE] = create_trampoline_code (MONO_TRAMPOLINE_DELEGATE);
#endif
- mono_trampoline_code [MONO_TRAMPOLINE_RESTORE_STACK_PROT] = mono_arch_create_trampoline_code (MONO_TRAMPOLINE_RESTORE_STACK_PROT);
- mono_trampoline_code [MONO_TRAMPOLINE_GENERIC_VIRTUAL_REMOTING] = mono_arch_create_trampoline_code (MONO_TRAMPOLINE_GENERIC_VIRTUAL_REMOTING);
- mono_trampoline_code [MONO_TRAMPOLINE_MONITOR_ENTER] = mono_arch_create_trampoline_code (MONO_TRAMPOLINE_MONITOR_ENTER);
- mono_trampoline_code [MONO_TRAMPOLINE_MONITOR_EXIT] = mono_arch_create_trampoline_code (MONO_TRAMPOLINE_MONITOR_EXIT);
+ mono_trampoline_code [MONO_TRAMPOLINE_RESTORE_STACK_PROT] = create_trampoline_code (MONO_TRAMPOLINE_RESTORE_STACK_PROT);
+ mono_trampoline_code [MONO_TRAMPOLINE_GENERIC_VIRTUAL_REMOTING] = create_trampoline_code (MONO_TRAMPOLINE_GENERIC_VIRTUAL_REMOTING);
+ mono_trampoline_code [MONO_TRAMPOLINE_MONITOR_ENTER] = create_trampoline_code (MONO_TRAMPOLINE_MONITOR_ENTER);
+ mono_trampoline_code [MONO_TRAMPOLINE_MONITOR_EXIT] = create_trampoline_code (MONO_TRAMPOLINE_MONITOR_EXIT);
#ifdef MONO_ARCH_LLVM_SUPPORTED
- mono_trampoline_code [MONO_TRAMPOLINE_LLVM_VCALL] = mono_arch_create_trampoline_code (MONO_TRAMPOLINE_LLVM_VCALL);
+ mono_trampoline_code [MONO_TRAMPOLINE_LLVM_VCALL] = create_trampoline_code (MONO_TRAMPOLINE_LLVM_VCALL);
#endif
+#ifdef MONO_ARCH_HAVE_HANDLER_BLOCK_GUARD
+ mono_trampoline_code [MONO_TRAMPOLINE_HANDLER_BLOCK_GUARD] = create_trampoline_code (MONO_TRAMPOLINE_HANDLER_BLOCK_GUARD);
+ mono_create_handler_block_trampoline ();
+#endif
+
+ mono_counters_register ("Calls to trampolines", MONO_COUNTER_JIT | MONO_COUNTER_INT, &trampoline_calls);
}
void
if (!code) {
if (mono_aot_only)
/* get_named_code () might return an ftnptr, but our caller expects a direct pointer */
- code = mono_get_addr_from_ftnptr (mono_aot_get_named_code ("generic_class_init_trampoline"));
+ code = mono_get_addr_from_ftnptr (mono_aot_get_trampoline ("generic_class_init_trampoline"));
else
- code = mono_arch_create_generic_class_init_trampoline ();
+ code = mono_arch_create_generic_class_init_trampoline (NULL, FALSE);
}
mono_trampolines_unlock ();
if (tramp)
return tramp;
- tramp = mono_arch_create_rgctx_lazy_fetch_trampoline (offset);
+ tramp = mono_arch_create_rgctx_lazy_fetch_trampoline (offset, NULL, FALSE);
ptr = mono_create_ftnptr (mono_get_root_domain (), tramp);
mono_trampolines_lock ();
if (mono_aot_only) {
if (!code)
- code = mono_aot_get_named_code ("monitor_enter_trampoline");
+ code = mono_aot_get_trampoline ("monitor_enter_trampoline");
return code;
}
mono_trampolines_lock ();
if (!code)
- code = mono_arch_create_monitor_enter_trampoline ();
+ code = mono_arch_create_monitor_enter_trampoline (NULL, FALSE);
mono_trampolines_unlock ();
#else
if (mono_aot_only) {
if (!code)
- code = mono_aot_get_named_code ("monitor_exit_trampoline");
+ code = mono_aot_get_trampoline ("monitor_exit_trampoline");
return code;
}
mono_trampolines_lock ();
if (!code)
- code = mono_arch_create_monitor_exit_trampoline ();
+ code = mono_arch_create_monitor_exit_trampoline (NULL, FALSE);
mono_trampolines_unlock ();
#else