*/
guint8* mono_trampoline_code [MONO_TRAMPOLINE_NUM];
-static GHashTable *class_init_hash_addr;
static GHashTable *rgctx_lazy_fetch_trampoline_hash;
static GHashTable *rgctx_lazy_fetch_trampoline_hash_addr;
static guint32 trampoline_calls, jit_trampolines, unbox_trampolines, static_rgctx_trampolines;
}
#endif
+#if 0
+#define DEBUG_IMT(stmt) do { stmt; } while (0)
+#else
+#define DEBUG_IMT(stmt) do { } while (0)
+#endif
+
/*
- * Either IMPL_METHOD or AOT_ADDR will be set on return.
+ * mini_resolve_imt_method:
+ *
+ * Resolve the actual method called when making an IMT call through VTABLE_SLOT with IMT_METHOD as the interface method.
*
- * MONO_NEVER_INLINE :
- * This works against problems when compiling with gcc 4.6 on arm. The 'then' part of
- * this line gets executed, even when the condition is false:
- * if (impl && mono_method_needs_static_rgctx_invoke (impl, FALSE))
- * *need_rgctx_tramp = TRUE;
+ * Either IMPL_METHOD or OUT_AOT_ADDR will be set on return.
*/
-static MONO_NEVER_INLINE gpointer*
-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)
+gpointer*
+mini_resolve_imt_method (MonoVTable *vt, gpointer *vtable_slot, MonoMethod *imt_method, MonoMethod **impl_method, gpointer *out_aot_addr, gboolean *out_need_rgctx_tramp, MonoMethod **variant_iface)
{
- MonoObject *this_argument = mono_arch_get_this_arg_from_call (regs, code);
- MonoVTable *vt = this_argument->vtable;
- int displacement = slot - ((gpointer*)vt);
-
- if (displacement > 0) {
- /* slot is in the vtable, not in the IMT */
-#if DEBUG_IMT
- printf ("mono_convert_imt_slot_to_vtable_slot: slot %p is in the vtable, not in the IMT\n", slot);
-#endif
- return slot;
- } else {
- MonoMethod *imt_method = mono_arch_find_imt_method (regs, code);
- MonoMethod *impl;
- int interface_offset;
- int imt_slot = MONO_IMT_SIZE + displacement;
-
- /*This has to be variance aware since imt_method can be from an interface that vt->klass doesn't directly implement*/
- interface_offset = mono_class_interface_offset_with_variance (vt->klass, imt_method->klass, variance_used);
-
- if (interface_offset < 0) {
- g_error ("%s doesn't implement interface %s\n", mono_type_get_name_full (&vt->klass->byval_arg, 0), mono_type_get_name_full (&imt_method->klass->byval_arg, 0));
- }
- mono_vtable_build_imt_slot (vt, mono_method_get_imt_slot (imt_method));
+ MonoMethod *impl = NULL, *generic_virtual = NULL;
+ gboolean lookup_aot, variance_used = FALSE, need_rgctx_tramp = FALSE;
+ gpointer addr;
+ guint8 *aot_addr = NULL;
+ int displacement = vtable_slot - ((gpointer*)vt);
+ int interface_offset;
+ int imt_slot = MONO_IMT_SIZE + displacement;
+
+ g_assert (imt_slot < MONO_IMT_SIZE);
+
+ /* This has to be variance aware since imt_method can be from an interface that vt->klass doesn't directly implement */
+ interface_offset = mono_class_interface_offset_with_variance (vt->klass, imt_method->klass, &variance_used);
+ if (interface_offset < 0)
+ g_error ("%s doesn't implement interface %s\n", mono_type_get_name_full (&vt->klass->byval_arg, 0), mono_type_get_name_full (&imt_method->klass->byval_arg, 0));
+
+ *variant_iface = NULL;
+ if (imt_method->is_inflated && ((MonoMethodInflated*)imt_method)->context.method_inst) {
+ /* Generic virtual method */
+ generic_virtual = imt_method;
+ need_rgctx_tramp = TRUE;
+ } else if (variance_used && mono_class_has_variant_generic_params (imt_method->klass)) {
+ *variant_iface = imt_method;
+ }
- if (imt_method->is_inflated && ((MonoMethodInflated*)imt_method)->context.method_inst) {
- MonoError error;
- MonoGenericContext context = { NULL, NULL };
+ addr = NULL;
+ /* We can only use the AOT compiled code if we don't require further processing */
+ lookup_aot = !generic_virtual & !variant_iface;
- /*
- * Generic virtual method, imt_method contains the inflated interface
- * method, need to get the inflated impl method.
- */
- /* imt_method->slot might not be set */
- impl = mono_class_get_vtable_entry (vt->klass, interface_offset + mono_method_get_declaring_generic_method (imt_method)->slot);
+ mono_vtable_build_imt_slot (vt, mono_method_get_imt_slot (imt_method));
- if (impl->klass->generic_class)
- context.class_inst = impl->klass->generic_class->context.class_inst;
- context.method_inst = ((MonoMethodInflated*)imt_method)->context.method_inst;
- impl = mono_class_inflate_generic_method_checked (impl, &context, &error);
- g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
- } else {
- /* Avoid loading metadata or creating a generic vtable if possible */
- 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;
- if (*aot_addr)
- impl = NULL;
- else
- impl = mono_class_get_vtable_entry (vt->klass, interface_offset + mono_method_get_vtable_slot (imt_method));
- }
+ if (imt_method->is_inflated && ((MonoMethodInflated*)imt_method)->context.method_inst) {
+ MonoError error;
+ MonoGenericContext context = { NULL, NULL };
- if (impl && mono_method_needs_static_rgctx_invoke (impl, FALSE))
- *need_rgctx_tramp = TRUE;
- if (impl && impl->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
- WrapperInfo *info = mono_marshal_get_wrapper_info (impl);
+ /*
+ * Generic virtual method, imt_method contains the inflated interface
+ * method, need to get the inflated impl method.
+ */
+ /* imt_method->slot might not be set */
+ impl = mono_class_get_vtable_entry (vt->klass, interface_offset + mono_method_get_declaring_generic_method (imt_method)->slot);
- if (info && info->subtype == WRAPPER_SUBTYPE_GENERIC_ARRAY_HELPER) {
- *need_rgctx_tramp = TRUE;
- }
- }
+ if (impl->klass->generic_class)
+ context.class_inst = impl->klass->generic_class->context.class_inst;
+ context.method_inst = ((MonoMethodInflated*)imt_method)->context.method_inst;
+ impl = mono_class_inflate_generic_method_checked (impl, &context, &error);
+ g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
+ } else {
+ /* Avoid loading metadata or creating a generic vtable if possible */
+ 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;
+ if (aot_addr)
+ impl = NULL;
+ else
+ impl = mono_class_get_vtable_entry (vt->klass, interface_offset + mono_method_get_vtable_slot (imt_method));
+ }
- *impl_method = impl;
-#if DEBUG_IMT
- printf ("mono_convert_imt_slot_to_vtable_slot: method = %s.%s.%s, imt_method = %s.%s.%s\n",
- method->klass->name_space, method->klass->name, method->name,
- imt_method->klass->name_space, imt_method->klass->name, imt_method->name);
-#endif
+ if (impl && mono_method_needs_static_rgctx_invoke (impl, FALSE))
+ need_rgctx_tramp = TRUE;
+ if (impl && impl->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
+ WrapperInfo *info = mono_marshal_get_wrapper_info (impl);
- g_assert (imt_slot < MONO_IMT_SIZE);
- if (vt->imt_collisions_bitmap & (1 << imt_slot)) {
- int slot = mono_method_get_vtable_index (imt_method);
- int vtable_offset;
- gpointer *vtable_slot;
-
- g_assert (slot != -1);
- vtable_offset = interface_offset + slot;
- vtable_slot = & (vt->vtable [vtable_offset]);
-#if DEBUG_IMT
- printf ("mono_convert_imt_slot_to_vtable_slot: slot %p[%d] is in the IMT, and colliding becomes %p[%d] (interface_offset = %d, method->slot = %d)\n", slot, imt_slot, vtable_slot, vtable_offset, interface_offset, imt_method->slot);
-#endif
- return vtable_slot;
- } else {
-#if DEBUG_IMT
- printf ("mono_convert_imt_slot_to_vtable_slot: slot %p[%d] is in the IMT, but not colliding\n", slot, imt_slot);
-#endif
- return slot;
- }
+ if (info && info->subtype == WRAPPER_SUBTYPE_GENERIC_ARRAY_HELPER)
+ need_rgctx_tramp = TRUE;
+ }
+ *impl_method = impl;
+ *out_need_rgctx_tramp = need_rgctx_tramp;
+ *out_aot_addr = aot_addr;
+
+ DEBUG_IMT (printf ("mono_convert_imt_slot_to_vtable_slot: method = %s.%s.%s, imt_method = %s.%s.%s\n",
+ method->klass->name_space, method->klass->name, method->name,
+ imt_method->klass->name_space, imt_method->klass->name, imt_method->name));
+
+ if (vt->imt_collisions_bitmap & (1 << imt_slot)) {
+ int slot = mono_method_get_vtable_index (imt_method);
+ int vtable_offset;
+
+ g_assert (slot != -1);
+ vtable_offset = interface_offset + slot;
+ vtable_slot = & (vt->vtable [vtable_offset]);
+ DEBUG_IMT (printf ("mono_convert_imt_slot_to_vtable_slot: slot %p[%d] is in the IMT, and colliding becomes %p[%d] (interface_offset = %d, method->slot = %d)\n", slot, imt_slot, vtable_slot, vtable_offset, interface_offset, imt_method->slot));
+ return vtable_slot;
+ } else {
+ DEBUG_IMT (printf ("mono_convert_imt_slot_to_vtable_slot: slot %p[%d] is in the IMT, but not colliding\n", slot, imt_slot));
+ return vtable_slot;
}
}
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))
+ if (ji && ji->has_generic_jit_info && (mono_jit_info_get_generic_sharing_context (ji)->is_gsharedvt))
return TRUE;
else
return FALSE;
/**
* mini_add_method_trampoline:
- * @orig_method: the method the caller originally called i.e. an iface method, or NULL.
* @m:
* @compiled_method:
* @add_static_rgctx_tramp: adds a static rgctx trampoline
* is needed.
*/
gpointer
-mini_add_method_trampoline (MonoMethod *orig_method, MonoMethod *m, gpointer compiled_method, gboolean add_static_rgctx_tramp, gboolean add_unbox_tramp)
+mini_add_method_trampoline (MonoMethod *m, gpointer compiled_method, gboolean add_static_rgctx_tramp, gboolean add_unbox_tramp)
{
gpointer addr = compiled_method;
gboolean callee_gsharedvt, callee_array_helper;
}
}
- if (!orig_method)
- orig_method = m;
-
if (callee_gsharedvt)
g_assert (m->is_inflated);
}
}
- if (ji)
+ if (ji && !ji->is_trampoline)
jmethod = jinfo_get_method (ji);
if (callee_gsharedvt && mini_is_gsharedvt_variable_signature (mono_method_signature (jmethod))) {
- MonoGenericSharingContext *gsctx;
MonoMethodSignature *sig, *gsig;
/* Here m is a generic instance, while ji->method is the gsharedvt method implementing it */
/* Call from normal/gshared code to gsharedvt code with variable signature */
- gsctx = mono_jit_info_get_generic_sharing_context (ji);
-
sig = mono_method_signature (m);
gsig = mono_method_signature (jmethod);
- addr = mini_get_gsharedvt_wrapper (TRUE, addr, sig, gsig, gsctx, -1, FALSE);
+ addr = mini_get_gsharedvt_wrapper (TRUE, addr, sig, gsig, -1, FALSE);
//printf ("IN: %s\n", mono_method_full_name (m, TRUE));
}
* from JITted and LLVM compiled code.
*/
static gpointer
-common_call_trampoline_inner (mgreg_t *regs, guint8 *code, MonoMethod *m, guint8* tramp, MonoVTable *vt, gpointer *vtable_slot, gboolean need_rgctx_tramp)
+common_call_trampoline_inner (mgreg_t *regs, guint8 *code, MonoMethod *m, MonoVTable *vt, gpointer *vtable_slot)
{
gpointer addr, compiled_method;
gboolean generic_shared = FALSE;
gboolean need_unbox_tramp = FALSE;
+ gboolean need_rgctx_tramp = FALSE;
MonoMethod *declaring = NULL;
- MonoMethod *generic_virtual = NULL, *variant_iface = NULL, *orig_method = NULL;
+ MonoMethod *generic_virtual = NULL, *variant_iface = NULL;
int context_used;
- gboolean virtual, variance_used = FALSE;
+ gboolean imt_call, virtual;
gpointer *orig_vtable_slot, *vtable_slot_to_patch = NULL;
MonoJitInfo *ji = NULL;
- virtual = (gpointer)vtable_slot > (gpointer)vt;
+ virtual = vt && (gpointer)vtable_slot > (gpointer)vt;
+ imt_call = vt && (gpointer)vtable_slot < (gpointer)vt;
+
+ /*
+ * rgctx trampolines are needed when the call is indirect so the caller can't pass
+ * the rgctx argument needed by the callee.
+ */
+ if (virtual && m)
+ need_rgctx_tramp = mono_method_needs_static_rgctx_invoke (m, FALSE);
orig_vtable_slot = vtable_slot;
vtable_slot_to_patch = vtable_slot;
/* IMT call */
- if (vt && (gpointer)vtable_slot < (gpointer)vt) {
- MonoMethod *impl_method = NULL;
+ if (imt_call) {
+ MonoMethod *imt_method = NULL, *impl_method = NULL;
MonoObject *this_arg;
- /* we get the interface method because mono_convert_imt_slot_to_vtable_slot ()
- * needs the signature to be able to find the this argument
- */
- m = mono_arch_find_imt_method (regs, code);
- vtable_slot = orig_vtable_slot;
g_assert (vtable_slot);
- orig_method = m;
-
+ imt_method = mono_arch_find_imt_method (regs, code);
this_arg = mono_arch_get_this_arg_from_call (regs, code);
if (mono_object_is_transparent_proxy (this_arg)) {
/* Use the slow path for now */
- m = mono_object_get_virtual_method (this_arg, m);
+ m = mono_object_get_virtual_method (this_arg, imt_method);
vtable_slot_to_patch = NULL;
} else {
- gboolean lookup_aot;
-
- mono_class_interface_offset_with_variance (vt->klass, m->klass, &variance_used);
-
- if (m->is_inflated && ((MonoMethodInflated*)m)->context.method_inst) {
+ if (imt_method->is_inflated && ((MonoMethodInflated*)imt_method)->context.method_inst) {
/* Generic virtual method */
- generic_virtual = m;
+ generic_virtual = imt_method;
need_rgctx_tramp = TRUE;
- } else if (variance_used && mono_class_has_variant_generic_params (m->klass)) {
- variant_iface = m;
}
- 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);
+ vtable_slot = mini_resolve_imt_method (vt, vtable_slot, imt_method, &impl_method, &addr, &need_rgctx_tramp, &variant_iface);
/* 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) {
/*
g_assert (!m->klass->generic_container);
generic_virtual = mono_arch_find_imt_method (regs, code);
- if (generic_virtual) {
- g_assert (generic_virtual->is_inflated);
- context.method_inst = ((MonoMethodInflated*)generic_virtual)->context.method_inst;
- }
+ g_assert (generic_virtual);
+ g_assert (generic_virtual->is_inflated);
+ context.method_inst = ((MonoMethodInflated*)generic_virtual)->context.method_inst;
m = mono_class_inflate_generic_method_checked (declaring, &context, &error);
g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
g_assert (code);
+ /*
+ * The caller is gshared code, compute the actual method to call from M and this/rgctx.
+ */
if (m->is_inflated && mono_method_get_context (m)->method_inst) {
-#ifdef MONO_ARCH_RGCTX_REG
MonoMethodRuntimeGenericContext *mrgctx = (MonoMethodRuntimeGenericContext*)mono_arch_find_static_call_vtable (regs, code);
klass = mrgctx->class_vtable->klass;
method_inst = mrgctx->method_inst;
-#else
- g_assert_not_reached ();
-#endif
} else if ((m->flags & METHOD_ATTRIBUTE_STATIC) || m->klass->valuetype) {
-#ifdef MONO_ARCH_RGCTX_REG
MonoVTable *vtable = mono_arch_find_static_call_vtable (regs, code);
klass = vtable->klass;
-#else
- g_assert_not_reached ();
-#endif
} else {
MonoObject *this_argument = mono_arch_get_this_arg_from_call (regs, code);
vtable_slot = orig_vtable_slot;
g_assert (this_argument->vtable->klass->inited);
- //mono_class_init (this_argument->vtable->klass);
if (!vtable_slot) {
mono_class_setup_supertypes (this_argument->vtable->klass);
need_unbox_tramp = TRUE;
}
- addr = mini_add_method_trampoline (orig_method, m, compiled_method, need_rgctx_tramp, need_unbox_tramp);
+ addr = mini_add_method_trampoline (m, compiled_method, need_rgctx_tramp, need_unbox_tramp);
if (generic_virtual || variant_iface) {
MonoMethod *target = generic_virtual ? generic_virtual : variant_iface;
g_assert (*vtable_slot_to_patch);
*vtable_slot_to_patch = mono_get_addr_from_ftnptr (addr);
}
- }
- else {
+ } else {
guint8 *plt_entry = mono_aot_get_plt_entry (code);
gboolean no_patch = FALSE;
MonoJitInfo *target_ji;
}
static gpointer
-common_call_trampoline (mgreg_t *regs, guint8 *code, MonoMethod *m, guint8* tramp, MonoVTable *vt, gpointer *vtable_slot, gboolean need_rgctx_tramp)
+common_call_trampoline (mgreg_t *regs, guint8 *code, MonoMethod *m, MonoVTable *vt, gpointer *vtable_slot)
{
gpointer res;
- MONO_PREPARE_RESET_BLOCKING
- res = common_call_trampoline_inner (regs, code, m, tramp, vt, vtable_slot, need_rgctx_tramp);
- MONO_FINISH_RESET_BLOCKING
+ MONO_PREPARE_RESET_BLOCKING;
+ res = common_call_trampoline_inner (regs, code, m, vt, vtable_slot);
+ MONO_FINISH_RESET_BLOCKING;
return res;
}
{
trampoline_calls ++;
- return common_call_trampoline (regs, code, arg, tramp, NULL, NULL, FALSE);
+ return common_call_trampoline (regs, code, arg, NULL, NULL);
}
/**
static gpointer
mono_vcall_trampoline (mgreg_t *regs, guint8 *code, int slot, guint8 *tramp)
{
- MonoObject *this;
+ MonoObject *this_arg;
MonoVTable *vt;
gpointer *vtable_slot;
MonoMethod *m;
- gboolean need_rgctx_tramp = FALSE;
gpointer addr;
trampoline_calls ++;
/*
* Obtain the vtable from the 'this' arg.
*/
- this = mono_arch_get_this_arg_from_call (regs, code);
- g_assert (this);
+ this_arg = mono_arch_get_this_arg_from_call (regs, code);
+ g_assert (this_arg);
- vt = this->vtable;
+ vt = this_arg->vtable;
if (slot >= 0) {
/* Normal virtual call */
* trustworthy.
*/
m = mono_class_get_vtable_entry (vt->klass, slot);
-
- need_rgctx_tramp = mono_method_needs_static_rgctx_invoke (m, 0);
} else {
/* IMT call */
vtable_slot = &(((gpointer*)vt) [slot]);
m = NULL;
- need_rgctx_tramp = FALSE;
}
- return common_call_trampoline (regs, code, m, tramp, vt, vtable_slot, need_rgctx_tramp);
+ return common_call_trampoline (regs, code, m, vt, vtable_slot);
}
#ifndef DISABLE_REMOTING
}
#endif
-/**
- * mono_class_init_trampoline:
- *
- * This method calls mono_runtime_class_init () to run the static constructor
- * for the type, then patches the caller code so it is not called again.
- */
-void
-mono_class_init_trampoline (mgreg_t *regs, guint8 *code, MonoVTable *vtable, guint8 *tramp)
-{
- guint8 *plt_entry = mono_aot_get_plt_entry (code);
-
- trampoline_calls ++;
-
- mono_runtime_class_init (vtable);
-
- if (vtable->initialized) {
- if (plt_entry)
- mono_aot_patch_plt_entry (code, plt_entry, NULL, regs, mini_get_nullified_class_init_trampoline ());
- else
- mono_arch_nullify_class_init_trampoline (code, regs);
- }
-}
-
-/**
- * mono_generic_class_init_trampoline:
- *
- * This method calls mono_runtime_class_init () to run the static constructor
- * for the type.
- */
-void
-mono_generic_class_init_trampoline (mgreg_t *regs, guint8 *code, MonoVTable *vtable, guint8 *tramp)
-{
- trampoline_calls ++;
-
- mono_runtime_class_init (vtable);
-}
-
static gpointer
mono_rgctx_lazy_fetch_trampoline (mgreg_t *regs, guint8 *code, gpointer data, guint8 *tramp)
{
num_lookups++;
if (mrgctx)
- return mono_method_fill_runtime_generic_context (arg, code, index);
+ return mono_method_fill_runtime_generic_context (arg, index);
else
- return mono_class_fill_runtime_generic_context (arg, code, index);
-}
-
-void
-mono_monitor_enter_trampoline (mgreg_t *regs, guint8 *code, MonoObject *obj, guint8 *tramp)
-{
- mono_monitor_enter (obj);
-}
-
-void
-mono_monitor_enter_v4_trampoline (mgreg_t *regs, guint8 *code, MonoObject *obj, guint8 *tramp)
-{
-#ifdef MONO_ARCH_MONITOR_LOCK_TAKEN_REG
- char *lock_taken = (char*)regs [MONO_ARCH_MONITOR_LOCK_TAKEN_REG];
- mono_monitor_enter_v4 (obj, lock_taken);
-#else
- g_assert_not_reached ();
-#endif
+ return mono_class_fill_runtime_generic_context (arg, index);
}
-void
-mono_monitor_exit_trampoline (mgreg_t *regs, guint8 *code, MonoObject *obj, guint8 *tramp)
-{
- mono_monitor_exit (obj);
-}
-
-#ifdef MONO_ARCH_HAVE_CREATE_DELEGATE_TRAMPOLINE
-
/*
* Precompute data to speed up mono_delegate_trampoline ().
* METHOD might be NULL.
/* Obtain the delegate object according to the calling convention */
delegate = mono_arch_get_this_arg_from_call (regs, code);
+ g_assert (mono_class_has_parent (mono_object_class (delegate), mono_defaults.multicastdelegate_class));
if (delegate->method) {
method = delegate->method;
}
}
}
- } else {
+ // If "delegate->method_ptr" is null mono_get_addr_from_ftnptr will fail if
+ // ftnptrs are being used. "method" would end up null on archtitectures without
+ // ftnptrs so we can just skip this.
+ } else if (delegate->method_ptr) {
ji = mono_jit_info_table_find (domain, mono_get_addr_from_ftnptr (delegate->method_ptr));
if (ji)
method = jinfo_get_method (ji);
delegate->method_ptr = *delegate->method_code;
} else {
compiled_method = addr = mono_compile_method (method);
- addr = mini_add_method_trampoline (NULL, method, compiled_method, need_rgctx_tramp, need_unbox_tramp);
+ addr = mini_add_method_trampoline (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;
/* Necessary for !code condition to fallback to slow path */
code = NULL;
- multicast = ((MonoMulticastDelegate*)delegate)->prev != NULL;
+ multicast = ((MonoMulticastDelegate*)delegate)->delegates != NULL;
if (!multicast && !callvirt) {
if (method && (method->flags & METHOD_ATTRIBUTE_STATIC) && mono_method_signature (method)->param_count == mono_method_signature (invoke)->param_count + 1)
/* Closed static delegate */
/* 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), FALSE);
+ code = mini_add_method_trampoline (m, code, mono_method_needs_static_rgctx_invoke (m, FALSE), FALSE);
}
delegate->invoke_impl = mono_get_addr_from_ftnptr (code);
return code;
}
-#endif
-
#ifdef MONO_ARCH_HAVE_HANDLER_BLOCK_GUARD
static gpointer
mono_handler_block_guard_trampoline (mgreg_t *regs, guint8 *code, gpointer *tramp_info, guint8* tramp)
gpointer tmp;
tmp = mono_arch_create_handler_block_trampoline (&info, FALSE);
- mono_tramp_info_register (info);
+ mono_tramp_info_register (info, NULL);
mono_memory_barrier ();
code = tmp;
}
case MONO_TRAMPOLINE_JIT:
case MONO_TRAMPOLINE_JUMP:
return mono_magic_trampoline;
- case MONO_TRAMPOLINE_CLASS_INIT:
- return mono_class_init_trampoline;
- case MONO_TRAMPOLINE_GENERIC_CLASS_INIT:
- return mono_generic_class_init_trampoline;
case MONO_TRAMPOLINE_RGCTX_LAZY_FETCH:
return mono_rgctx_lazy_fetch_trampoline;
#ifdef MONO_ARCH_AOT_SUPPORTED
case MONO_TRAMPOLINE_AOT_PLT:
return mono_aot_plt_trampoline;
#endif
-#ifdef MONO_ARCH_HAVE_CREATE_DELEGATE_TRAMPOLINE
case MONO_TRAMPOLINE_DELEGATE:
return mono_delegate_trampoline;
-#endif
case MONO_TRAMPOLINE_RESTORE_STACK_PROT:
return mono_altstack_restore_prot;
#ifndef DISABLE_REMOTING
case MONO_TRAMPOLINE_GENERIC_VIRTUAL_REMOTING:
return mono_generic_virtual_remoting_trampoline;
#endif
- case MONO_TRAMPOLINE_MONITOR_ENTER:
- return mono_monitor_enter_trampoline;
- case MONO_TRAMPOLINE_MONITOR_ENTER_V4:
- return mono_monitor_enter_v4_trampoline;
- case MONO_TRAMPOLINE_MONITOR_EXIT:
- return mono_monitor_exit_trampoline;
case MONO_TRAMPOLINE_VCALL:
return mono_vcall_trampoline;
#ifdef MONO_ARCH_HAVE_HANDLER_BLOCK_GUARD
guchar *code;
code = mono_arch_create_generic_trampoline (tramp_type, &info, FALSE);
- mono_tramp_info_register (info);
+ mono_tramp_info_register (info, NULL);
return code;
}
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] = 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] = create_trampoline_code (MONO_TRAMPOLINE_DELEGATE);
-#endif
mono_trampoline_code [MONO_TRAMPOLINE_RESTORE_STACK_PROT] = create_trampoline_code (MONO_TRAMPOLINE_RESTORE_STACK_PROT);
#ifndef DISABLE_REMOTING
mono_trampoline_code [MONO_TRAMPOLINE_GENERIC_VIRTUAL_REMOTING] = create_trampoline_code (MONO_TRAMPOLINE_GENERIC_VIRTUAL_REMOTING);
#endif
- mono_trampoline_code [MONO_TRAMPOLINE_MONITOR_ENTER] = create_trampoline_code (MONO_TRAMPOLINE_MONITOR_ENTER);
- mono_trampoline_code [MONO_TRAMPOLINE_MONITOR_ENTER_V4] = create_trampoline_code (MONO_TRAMPOLINE_MONITOR_ENTER_V4);
- mono_trampoline_code [MONO_TRAMPOLINE_MONITOR_EXIT] = create_trampoline_code (MONO_TRAMPOLINE_MONITOR_EXIT);
mono_trampoline_code [MONO_TRAMPOLINE_VCALL] = create_trampoline_code (MONO_TRAMPOLINE_VCALL);
#ifdef MONO_ARCH_HAVE_HANDLER_BLOCK_GUARD
mono_trampoline_code [MONO_TRAMPOLINE_HANDLER_BLOCK_GUARD] = create_trampoline_code (MONO_TRAMPOLINE_HANDLER_BLOCK_GUARD);
void
mono_trampolines_cleanup (void)
{
- if (class_init_hash_addr)
- g_hash_table_destroy (class_init_hash_addr);
if (rgctx_lazy_fetch_trampoline_hash)
g_hash_table_destroy (rgctx_lazy_fetch_trampoline_hash);
if (rgctx_lazy_fetch_trampoline_hash_addr)
return mono_arch_create_specific_trampoline (arg1, tramp_type, domain, code_len);
}
-gpointer
-mono_create_class_init_trampoline (MonoVTable *vtable)
-{
- gpointer code, ptr;
- MonoDomain *domain = vtable->domain;
-
- g_assert (!vtable->klass->generic_container);
-
- /* previously created trampoline code */
- mono_domain_lock (domain);
- ptr =
- g_hash_table_lookup (domain_jit_info (domain)->class_init_trampoline_hash,
- vtable);
- mono_domain_unlock (domain);
- if (ptr)
- return ptr;
-
- code = mono_create_specific_trampoline (vtable, MONO_TRAMPOLINE_CLASS_INIT, domain, NULL);
-
- ptr = mono_create_ftnptr (domain, code);
-
- /* store trampoline address */
- mono_domain_lock (domain);
- g_hash_table_insert (domain_jit_info (domain)->class_init_trampoline_hash,
- vtable, ptr);
- mono_domain_unlock (domain);
-
- mono_trampolines_lock ();
- if (!class_init_hash_addr)
- class_init_hash_addr = g_hash_table_new (NULL, NULL);
- g_hash_table_insert (class_init_hash_addr, ptr, vtable);
- mono_trampolines_unlock ();
-
- return ptr;
-}
-
-gpointer
-mono_create_generic_class_init_trampoline (void)
-{
- static gpointer code;
- MonoTrampInfo *info;
-
- mono_trampolines_lock ();
-
- 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_trampoline ("generic_class_init_trampoline"));
- else {
- code = mono_arch_create_generic_class_init_trampoline (&info, FALSE);
- mono_tramp_info_register (info);
- }
- }
-
- mono_trampolines_unlock ();
-
- return code;
-}
-
gpointer
mono_create_jump_trampoline (MonoDomain *domain, MonoMethod *method, gboolean add_sync_wrapper)
{
MonoDelegateTrampInfo*
mono_create_delegate_trampoline_info (MonoDomain *domain, MonoClass *klass, MonoMethod *method)
{
-#ifdef MONO_ARCH_HAVE_CREATE_DELEGATE_TRAMPOLINE
MonoDelegateTrampInfo *tramp_info;
MonoClassMethodPair pair, *dpair;
guint32 code_size = 0;
mono_domain_unlock (domain);
return tramp_info;
-#else
- return NULL;
-#endif
}
gpointer
mono_create_delegate_trampoline (MonoDomain *domain, MonoClass *klass)
{
-#ifdef MONO_ARCH_HAVE_CREATE_DELEGATE_TRAMPOLINE
return mono_create_delegate_trampoline_info (domain, klass, NULL)->invoke_impl;
-#else
- return NULL;
-#endif
}
gpointer
mono_create_delegate_virtual_trampoline (MonoDomain *domain, MonoClass *klass, MonoMethod *method)
{
-#ifdef MONO_ARCH_HAVE_CREATE_DELEGATE_TRAMPOLINE
MonoMethod *invoke = mono_get_delegate_invoke (klass);
g_assert (invoke);
return mono_get_delegate_virtual_invoke_impl (mono_method_signature (invoke), method);
-#else
- return NULL;
-#endif
}
gpointer
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);
+ mono_tramp_info_register (info, NULL);
ptr = mono_create_ftnptr (mono_get_root_domain (), tramp);
}
return ptr;
}
-
-gpointer
-mono_create_monitor_enter_trampoline (void)
-{
- static gpointer code;
-
- if (mono_aot_only) {
- if (!code)
- code = mono_aot_get_trampoline ("monitor_enter_trampoline");
- return code;
- }
-
-#ifdef MONO_ARCH_MONITOR_OBJECT_REG
- mono_trampolines_lock ();
-
- if (!code) {
- MonoTrampInfo *info;
-
- code = mono_arch_create_monitor_enter_trampoline (&info, FALSE, FALSE);
- mono_tramp_info_register (info);
- }
-
- mono_trampolines_unlock ();
-#else
- code = NULL;
- g_assert_not_reached ();
-#endif
-
- return code;
-}
-
-gpointer
-mono_create_monitor_enter_v4_trampoline (void)
-{
- static gpointer code;
-
- if (mono_aot_only) {
- if (!code)
- code = mono_aot_get_trampoline ("monitor_enter_v4_trampoline");
- return code;
- }
-
-#if defined(MONO_ARCH_MONITOR_OBJECT_REG) && defined(MONO_ARCH_MONITOR_LOCK_TAKEN_REG)
- mono_trampolines_lock ();
-
- if (!code) {
- MonoTrampInfo *info;
-
- code = mono_arch_create_monitor_enter_trampoline (&info, TRUE, FALSE);
- mono_tramp_info_register (info);
- }
-
- mono_trampolines_unlock ();
-#else
- code = NULL;
- g_assert_not_reached ();
-#endif
-
- return code;
-}
-
-gpointer
-mono_create_monitor_exit_trampoline (void)
-{
- static gpointer code;
-
- if (mono_aot_only) {
- if (!code)
- code = mono_aot_get_trampoline ("monitor_exit_trampoline");
- return code;
- }
-
-#ifdef MONO_ARCH_MONITOR_OBJECT_REG
- mono_trampolines_lock ();
-
- if (!code) {
- MonoTrampInfo *info;
-
- code = mono_arch_create_monitor_exit_trampoline (&info, FALSE);
- mono_tramp_info_register (info);
- }
-
- mono_trampolines_unlock ();
-#else
- code = NULL;
- g_assert_not_reached ();
-#endif
- return code;
-}
#ifdef MONO_ARCH_LLVM_SUPPORTED
/*
}
#endif
-MonoVTable*
-mono_find_class_init_trampoline_by_addr (gconstpointer addr)
-{
- MonoVTable *res;
-
- mono_trampolines_lock ();
- if (class_init_hash_addr)
- res = g_hash_table_lookup (class_init_hash_addr, addr);
- else
- res = NULL;
- mono_trampolines_unlock ();
- return res;
-}
-
guint32
mono_find_rgctx_lazy_fetch_trampoline_by_addr (gconstpointer addr)
{
static const char*tramp_names [MONO_TRAMPOLINE_NUM] = {
"jit",
"jump",
- "class_init",
- "generic_class_init",
"rgctx_lazy_fetch",
"aot",
"aot_plt",
"delegate",
"restore_stack_prot",
"generic_virtual_remoting",
- "monitor_enter",
- "monitor_enter_v4",
- "monitor_exit",
"vcall",
"handler_block_guard"
};
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;
-}
-
/*
* mini_get_single_step_trampoline:
*
#ifdef MONO_ARCH_HAVE_SDB_TRAMPOLINES
MonoTrampInfo *info;
tramp = mono_arch_create_sdb_trampoline (TRUE, &info, FALSE);
- mono_tramp_info_register (info);
+ mono_tramp_info_register (info, NULL);
#else
tramp = NULL;
g_assert_not_reached ();
#ifdef MONO_ARCH_HAVE_SDB_TRAMPOLINES
MonoTrampInfo *info;
tramp = mono_arch_create_sdb_trampoline (FALSE, &info, FALSE);
- mono_tramp_info_register (info);
+ mono_tramp_info_register (info, NULL);
#else
tramp = NULL;
g_assert_not_reached ();