#include <mono/metadata/tabledefs.h>
#include <mono/utils/mono-counters.h>
#include <mono/utils/mono-error-internals.h>
+#include <mono/utils/mono-membar.h>
#include "mini.h"
-#include "debug-mini.h"
/*
* Address of the trampoline code. This is used by the debugger to check
#define mono_trampolines_unlock() LeaveCriticalSection (&trampolines_mutex)
static CRITICAL_SECTION trampolines_mutex;
-static gpointer
-get_unbox_trampoline (MonoMethod *m, gpointer addr, gboolean need_rgctx_tramp)
-{
- if (mono_aot_only) {
- if (need_rgctx_tramp)
- /*
- * The unbox trampolines call the method directly, so need to add
- * an rgctx tramp before them.
- */
- return mono_create_static_rgctx_trampoline (m, mono_aot_get_unbox_trampoline (m));
- else
- return mono_aot_get_unbox_trampoline (m);
- } else {
- unbox_trampolines ++;
- return mono_arch_get_unbox_trampoline (m, addr);
- }
-}
-
#ifdef MONO_ARCH_GSHARED_SUPPORTED
typedef struct {
*/
__attribute__ ((noinline))
#endif
-mono_convert_imt_slot_to_vtable_slot (gpointer* slot, mgreg_t *regs, guint8 *code, MonoMethod *method, MonoMethod **impl_method, gboolean *need_rgctx_tramp, gboolean *variance_used, gpointer *aot_addr)
+ mono_convert_imt_slot_to_vtable_slot (gpointer* slot, mgreg_t *regs, guint8 *code, MonoMethod *method, gboolean lookup_aot, MonoMethod **impl_method, gboolean *need_rgctx_tramp, gboolean *variance_used, gpointer *aot_addr)
{
MonoObject *this_argument = mono_arch_get_this_arg_from_call (regs, code);
MonoVTable *vt = this_argument->vtable;
impl = mono_class_inflate_generic_method (impl, &context);
} else {
/* Avoid loading metadata or creating a generic vtable if possible */
- if (!vt->klass->valuetype)
+ if (lookup_aot && !vt->klass->valuetype)
*aot_addr = mono_aot_get_method_from_vt_slot (mono_domain_get (), vt, interface_offset + mono_method_get_vtable_slot (imt_method));
else
*aot_addr = NULL;
return TRUE;
return FALSE;
}
-static gboolean
-ji_is_gsharedvt (MonoJitInfo *ji)
+
+gboolean
+mini_jit_info_is_gsharedvt (MonoJitInfo *ji)
{
if (ji && ji->has_generic_jit_info && (mono_jit_info_get_generic_sharing_context (ji)->var_is_vt ||
mono_jit_info_get_generic_sharing_context (ji)->mvar_is_vt))
/*
* mini_add_method_trampoline:
*
- * Add static rgctx/gsharedvt_in trampoline to M/COMPILED_METHOD if needed. Return the trampoline address, or
+ * Add static rgctx/gsharedvt_in/unbox trampolines to M/COMPILED_METHOD if needed. Return the trampoline address, or
* COMPILED_METHOD if no trampoline is needed.
* ORIG_METHOD is the method the caller originally called i.e. an iface method, or NULL.
*/
gpointer
-mini_add_method_trampoline (MonoMethod *orig_method, MonoMethod *m, gpointer compiled_method, gboolean add_static_rgctx_tramp)
+mini_add_method_trampoline (MonoMethod *orig_method, MonoMethod *m, gpointer compiled_method, gboolean add_static_rgctx_tramp, gboolean add_unbox_tramp)
{
gpointer addr = compiled_method;
gboolean callee_gsharedvt, callee_array_helper;
+ MonoMethod *jmethod = NULL;
MonoJitInfo *ji =
mini_jit_info_table_find (mono_domain_get (), mono_get_addr_from_ftnptr (compiled_method), NULL);
// FIXME: This loads information from AOT
- callee_gsharedvt = ji_is_gsharedvt (ji);
+ callee_gsharedvt = mini_jit_info_is_gsharedvt (ji);
callee_array_helper = FALSE;
if (m->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
addr = compiled_method;
- if (callee_gsharedvt && mini_is_gsharedvt_variable_signature (mono_method_signature (ji->method))) {
+ if (add_unbox_tramp) {
+ /*
+ * The unbox trampolines call the method directly, so need to add
+ * an rgctx tramp before them.
+ */
+ if (mono_aot_only) {
+ addr = mono_aot_get_unbox_trampoline (m);
+ } else {
+ unbox_trampolines ++;
+ addr = mono_arch_get_unbox_trampoline (m, addr);
+ }
+ }
+
+ if (ji)
+ jmethod = jinfo_get_method (ji);
+ if (callee_gsharedvt && mini_is_gsharedvt_variable_signature (mono_method_signature (jmethod))) {
MonoGenericSharingContext *gsctx;
MonoMethodSignature *sig, *gsig;
gsctx = mono_jit_info_get_generic_sharing_context (ji);
sig = mono_method_signature (m);
- gsig = mono_method_signature (ji->method);
+ gsig = mono_method_signature (jmethod);
- addr = mini_get_gsharedvt_wrapper (TRUE, compiled_method, sig, gsig, gsctx, -1, FALSE);
+ addr = mini_get_gsharedvt_wrapper (TRUE, addr, sig, gsig, gsctx, -1, FALSE);
//printf ("IN: %s\n", mono_method_full_name (m, TRUE));
}
{
gpointer addr, compiled_method;
gboolean generic_shared = FALSE;
+ gboolean need_unbox_tramp = FALSE;
MonoMethod *declaring = NULL;
MonoMethod *generic_virtual = NULL, *variant_iface = NULL, *orig_method = NULL;
int context_used;
m = mono_object_get_virtual_method (this_arg, m);
vtable_slot_to_patch = NULL;
} else {
- addr = NULL;
- vtable_slot = mono_convert_imt_slot_to_vtable_slot (vtable_slot, regs, code, m, &impl_method, &need_rgctx_tramp, &variance_used, &addr);
- /* This is the vcall slot which gets called through the IMT thunk */
- vtable_slot_to_patch = vtable_slot;
- /* mono_convert_imt_slot_to_vtable_slot () also gives us the method that is supposed
- * to be called, so we compile it and go ahead as usual.
- */
- /*g_print ("imt found method %p (%s) at %p\n", impl_method, impl_method->name, code);*/
+ gboolean lookup_aot;
+
if (m->is_inflated && ((MonoMethodInflated*)m)->context.method_inst) {
/* Generic virtual method */
generic_virtual = m;
variant_iface = m;
}
- if (addr && !generic_virtual && !variant_iface) {
+ addr = NULL;
+ /* We can only use the AOT compiled code if we don't require further processing */
+ lookup_aot = !generic_virtual & !variant_iface;
+ vtable_slot = mono_convert_imt_slot_to_vtable_slot (vtable_slot, regs, code, m, lookup_aot, &impl_method, &need_rgctx_tramp, &variance_used, &addr);
+ /* This is the vcall slot which gets called through the IMT thunk */
+ vtable_slot_to_patch = vtable_slot;
+ /* mono_convert_imt_slot_to_vtable_slot () also gives us the method that is supposed
+ * to be called, so we compile it and go ahead as usual.
+ */
+ /*g_print ("imt found method %p (%s) at %p\n", impl_method, impl_method->name, code);*/
+
+ if (addr) {
/*
* We found AOT compiled code for the method, skip the rest.
*/
actual_method = vt->klass->vtable [displacement];
}
- if (method_inst) {
+ if (method_inst || m->wrapper_type) {
MonoGenericContext context = { NULL, NULL };
if (m->is_inflated)
addr = compiled_method = mono_compile_method (m);
g_assert (addr);
- mono_debugger_trampoline_compiled (code, m, addr);
+ if (generic_virtual || variant_iface) {
+ if (vt->klass->valuetype) /*FIXME is this required variant iface?*/
+ need_unbox_tramp = TRUE;
+ } else if (orig_vtable_slot) {
+ if (m->klass->valuetype)
+ need_unbox_tramp = TRUE;
+ }
- addr = mini_add_method_trampoline (orig_method, m, compiled_method, need_rgctx_tramp);
+ addr = mini_add_method_trampoline (orig_method, m, compiled_method, need_rgctx_tramp, need_unbox_tramp);
if (generic_virtual || variant_iface) {
MonoMethod *target = generic_virtual ? generic_virtual : variant_iface;
vtable_slot = orig_vtable_slot;
g_assert (vtable_slot);
- if (vt->klass->valuetype) /*FIXME is this required variant iface?*/
- addr = get_unbox_trampoline (m, addr, need_rgctx_tramp);
-
mono_method_add_generic_virtual_invocation (mono_domain_get (),
vt, vtable_slot,
target, addr);
vtable_slot = orig_vtable_slot;
if (vtable_slot) {
- if (m->klass->valuetype)
- addr = get_unbox_trampoline (m, addr, need_rgctx_tramp);
-
if (vtable_slot_to_patch && (mono_aot_is_got_entry (code, (guint8*)vtable_slot_to_patch) || mono_domain_owns_vtable_slot (mono_domain_get (), vtable_slot_to_patch))) {
g_assert (*vtable_slot_to_patch);
*vtable_slot_to_patch = mono_get_addr_from_ftnptr (addr);
if (generic_shared) {
if (m->wrapper_type != MONO_WRAPPER_NONE)
m = mono_marshal_method_from_wrapper (m);
- //g_assert (mono_method_is_generic_sharable_impl (m, FALSE));
+ //g_assert (mono_method_is_generic_sharable (m, FALSE));
}
/* Patch calling code */
addr = mono_compile_method (m);
g_assert (addr);
- mono_debugger_trampoline_compiled (NULL, m, addr);
-
return addr;
}
#endif
#ifndef DISABLE_REMOTING
if (delegate->target && delegate->target->vtable->klass == mono_defaults.transparent_proxy_class) {
#ifndef DISABLE_COM
- if (((MonoTransparentProxy *)delegate->target)->remote_class->proxy_class != mono_defaults.com_object_class &&
+ if (((MonoTransparentProxy *)delegate->target)->remote_class->proxy_class != mono_class_get_com_object_class () &&
!mono_class_is_com_object (((MonoTransparentProxy *)delegate->target)->remote_class->proxy_class))
#endif
method = mono_marshal_get_remoting_invoke (method);
} else {
ji = mono_jit_info_table_find (domain, mono_get_addr_from_ftnptr (delegate->method_ptr));
if (ji)
- method = ji->method;
+ method = jinfo_get_method (ji);
}
if (method) {
delegate->method_ptr = *delegate->method_code;
} else {
compiled_method = addr = mono_compile_method (method);
- if (need_unbox_tramp)
- // FIXME: GSHAREDVT
- addr = get_unbox_trampoline (method, addr, need_rgctx_tramp);
- else
- addr = mini_add_method_trampoline (NULL, method, compiled_method, need_rgctx_tramp);
+ addr = mini_add_method_trampoline (NULL, method, compiled_method, need_rgctx_tramp, need_unbox_tramp);
delegate->method_ptr = addr;
if (enable_caching && delegate->method_code)
*delegate->method_code = delegate->method_ptr;
- mono_debugger_trampoline_compiled (NULL, method, delegate->method_ptr);
}
} else {
if (need_rgctx_tramp)
/* The general, unoptimized case */
m = mono_marshal_get_delegate_invoke (invoke, delegate);
code = mono_compile_method (m);
- code = mini_add_method_trampoline (NULL, m, code, mono_method_needs_static_rgctx_invoke (m, FALSE));
+ code = mini_add_method_trampoline (NULL, m, code, mono_method_needs_static_rgctx_invoke (m, FALSE), FALSE);
delegate->invoke_impl = mono_get_addr_from_ftnptr (code);
- mono_debugger_trampoline_compiled (NULL, m, delegate->invoke_impl);
return code;
}
mono_create_handler_block_trampoline (void)
{
static gpointer code;
+ if (code) {
+ mono_memory_barrier ();
+ return code;
+ }
+
if (mono_aot_only) {
g_assert (0);
mono_trampolines_lock ();
- if (!code)
- code = mono_arch_create_handler_block_trampoline ();
-
+ if (!code) {
+ gpointer tmp = mono_arch_create_handler_block_trampoline ();
+ mono_memory_barrier ();
+ code = tmp;
+ }
mono_trampolines_unlock ();
return code;
guchar *code;
code = mono_arch_create_generic_trampoline (tramp_type, &info, FALSE);
- if (info) {
- mono_save_trampoline_xdebug_info (info);
- if (mono_jit_map_is_enabled ())
- mono_emit_jit_tramp (info->code, info->code_size, info->name);
- mono_tramp_info_free (info);
- }
+ mono_tramp_info_register (info);
return code;
}
code = mono_get_addr_from_ftnptr (mono_aot_get_trampoline ("generic_class_init_trampoline"));
else {
code = mono_arch_create_generic_class_init_trampoline (&info, FALSE);
-
- if (info) {
- mono_save_trampoline_xdebug_info (info);
- if (mono_jit_map_is_enabled ())
- mono_emit_jit_tramp (info->code, info->code_size, info->name);
- mono_tramp_info_free (info);
- }
+ mono_tramp_info_register (info);
}
}
ji = mono_domain_alloc0 (domain, MONO_SIZEOF_JIT_INFO);
ji->code_start = code;
ji->code_size = code_size;
- ji->method = method;
+ ji->d.method = method;
/*
* mono_delegate_ctor needs to find the method metadata from the
gpointer tramp, ptr;
- if (mono_aot_only)
- return mono_aot_get_lazy_fetch_trampoline (offset);
-
mono_trampolines_lock ();
if (rgctx_lazy_fetch_trampoline_hash)
tramp = g_hash_table_lookup (rgctx_lazy_fetch_trampoline_hash, GUINT_TO_POINTER (offset));
if (tramp)
return tramp;
- tramp = mono_arch_create_rgctx_lazy_fetch_trampoline (offset, &info, FALSE);
- if (info) {
- mono_save_trampoline_xdebug_info (info);
- if (mono_jit_map_is_enabled ())
- mono_emit_jit_tramp (info->code, info->code_size, info->name);
- mono_tramp_info_free (info);
+ if (mono_aot_only) {
+ ptr = mono_aot_get_lazy_fetch_trampoline (offset);
+ } else {
+ tramp = mono_arch_create_rgctx_lazy_fetch_trampoline (offset, &info, FALSE);
+ mono_tramp_info_register (info);
+ ptr = mono_create_ftnptr (mono_get_root_domain (), tramp);
}
- ptr = mono_create_ftnptr (mono_get_root_domain (), tramp);
mono_trampolines_lock ();
if (!rgctx_lazy_fetch_trampoline_hash) {
MonoTrampInfo *info;
code = mono_arch_create_monitor_enter_trampoline (&info, FALSE);
- if (info) {
- mono_save_trampoline_xdebug_info (info);
- if (mono_jit_map_is_enabled ())
- mono_emit_jit_tramp (info->code, info->code_size, info->name);
- mono_tramp_info_free (info);
- }
+ mono_tramp_info_register (info);
}
mono_trampolines_unlock ();
MonoTrampInfo *info;
code = mono_arch_create_monitor_exit_trampoline (&info, FALSE);
- if (info) {
- mono_save_trampoline_xdebug_info (info);
- if (mono_jit_map_is_enabled ())
- mono_emit_jit_tramp (info->code, info->code_size, info->name);
- mono_tramp_info_free (info);
- }
+ mono_tramp_info_register (info);
}
mono_trampolines_unlock ();
"aot_plt",
"delegate",
"restore_stack_prot",
-#ifndef DISABLE_REMOTING
"generic_virtual_remoting",
-#endif
"monitor_enter",
"monitor_exit",
"vcall",
-#ifdef MONO_ARCH_HAVE_HANDLER_BLOCK_GUARD
"handler_block_guard"
-#endif
};
/*
return g_strdup_printf ("rgctx_fetch_trampoline_%s_%d", mrgctx ? "mrgctx" : "rgctx", index);
}
+gpointer
+mini_get_nullified_class_init_trampoline (void)
+{
+ static gpointer nullified_class_init_trampoline;
+
+ if (!nullified_class_init_trampoline) {
+ gpointer tramp;
+ MonoTrampInfo *info;
+
+ if (mono_aot_only) {
+ tramp = mono_aot_get_trampoline ("nullified_class_init_trampoline");
+ } else {
+ tramp = mono_arch_get_nullified_class_init_trampoline (&info);
+ mono_tramp_info_register (info);
+ }
+ mono_memory_barrier ();
+ nullified_class_init_trampoline = tramp;
+ }
+
+ return nullified_class_init_trampoline;
+}