#include <mono/utils/mono-membar.h>
#include <mono/utils/mono-compiler.h>
#include <mono/utils/mono-threads-coop.h>
+#include <mono/utils/unlocked.h>
#include "mini.h"
#include "lldb.h"
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;
+
+static gint32 trampoline_calls;
+static gint32 jit_trampolines;
+static gint32 unbox_trampolines;
+static gint32 static_rgctx_trampolines;
+static gint32 rgctx_unmanaged_lookups;
+static gint32 rgctx_num_lazy_fetch_trampolines;
#define mono_trampolines_lock() mono_os_mutex_lock (&trampolines_mutex)
#define mono_trampolines_unlock() mono_os_mutex_unlock (&trampolines_mutex)
info->m = m;
info->addr = addr;
g_hash_table_insert (domain_jit_info (domain)->static_rgctx_trampoline_hash, info, res);
- mono_domain_unlock (domain);
- static_rgctx_trampolines ++;
+ UnlockedIncrement (&static_rgctx_trampolines);
+ mono_domain_unlock (domain);
return res;
}
vtable_slot = mini_resolve_imt_method (vt, vtable_slot, imt_method, &impl_method, &addr, &need_rgctx_tramp, &variant_iface, error);
return_val_if_nok (error, NULL);
+ /* We must handle magic interfaces on rank 1 arrays of ref types as if they were variant */
+ if (!variant_iface && vt->klass->rank == 1 && !vt->klass->element_class->valuetype && imt_method->klass->is_array_special_interface)
+ variant_iface = imt_method;
+
/* This is the vcall slot which gets called through the IMT trampoline */
vtable_slot_to_patch = vtable_slot;
mono_magic_trampoline (mgreg_t *regs, guint8 *code, gpointer arg, guint8* tramp)
{
gpointer res;
-
- MONO_ENTER_GC_UNSAFE_UNBALANCED;
-
MonoError error;
- trampoline_calls ++;
+ MONO_REQ_GC_UNSAFE_MODE;
- res = common_call_trampoline (regs, code, (MonoMethod *)arg, NULL, NULL, &error);
- mono_error_set_pending_exception (&error);
+ g_assert (mono_thread_is_gc_unsafe_mode ());
- mono_interruption_checkpoint_from_trampoline ();
+ UnlockedIncrement (&trampoline_calls);
- MONO_EXIT_GC_UNSAFE_UNBALANCED;
+ res = common_call_trampoline (regs, code, (MonoMethod *)arg, NULL, NULL, &error);
+ if (!is_ok (&error)) {
+ mono_error_set_pending_exception (&error);
+ return NULL;
+ }
return res;
}
MonoError error;
gpointer addr, res = NULL;
- trampoline_calls ++;
+ UnlockedIncrement (&trampoline_calls);
/*
* We need to obtain the following pieces of information:
MonoMethod *imt_method, *declaring;
gpointer addr;
- trampoline_calls ++;
+ UnlockedIncrement (&trampoline_calls);
g_assert (m->is_generic);
guint8 *plt_entry;
MonoError error;
- trampoline_calls ++;
+ UnlockedIncrement (&trampoline_calls);
image = (MonoImage *)*(gpointer*)(gpointer)token_info;
token_info += sizeof (gpointer);
gpointer res;
MonoError error;
- trampoline_calls ++;
+ UnlockedIncrement (&trampoline_calls);
res = mono_aot_plt_resolve (aot_module, plt_info_offset, code, &error);
if (!res) {
{
MONO_REQ_GC_UNSAFE_MODE;
- static gboolean inited = FALSE;
- static int num_lookups = 0;
guint32 slot = GPOINTER_TO_UINT (data);
mgreg_t *r = (mgreg_t*)regs;
gpointer arg = (gpointer)(gssize)r [MONO_ARCH_VTABLE_REG];
MonoError error;
gpointer res;
- trampoline_calls ++;
-
- if (!inited) {
- mono_counters_register ("RGCTX unmanaged lookups", MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &num_lookups);
- inited = TRUE;
- }
-
- num_lookups++;
+ UnlockedIncrement (&trampoline_calls);
+ UnlockedIncrement (&rgctx_unmanaged_lookups);
if (mrgctx)
res = mono_method_fill_runtime_generic_context ((MonoMethodRuntimeGenericContext *)arg, index, &error);
gpointer addr, compiled_method;
gboolean is_remote = FALSE;
- trampoline_calls ++;
+ UnlockedIncrement (&trampoline_calls);
/* Obtain the delegate object according to the calling convention */
delegate = (MonoDelegate *)mono_arch_get_this_arg_from_call (regs, code);
mono_counters_register ("JIT trampolines", MONO_COUNTER_JIT | MONO_COUNTER_INT, &jit_trampolines);
mono_counters_register ("Unbox trampolines", MONO_COUNTER_JIT | MONO_COUNTER_INT, &unbox_trampolines);
mono_counters_register ("Static rgctx trampolines", MONO_COUNTER_JIT | MONO_COUNTER_INT, &static_rgctx_trampolines);
+ mono_counters_register ("RGCTX unmanaged lookups", MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &rgctx_unmanaged_lookups);
+ mono_counters_register ("RGCTX num lazy fetch trampolines", MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &rgctx_num_lazy_fetch_trampolines);
}
void
mono_domain_lock (domain);
g_hash_table_insert (domain_jit_info (domain)->jit_trampoline_hash, method, tramp);
+ UnlockedIncrement (&jit_trampolines);
mono_domain_unlock (domain);
- jit_trampolines++;
-
return tramp;
}
tramp = mono_create_specific_trampoline (start, MONO_TRAMPOLINE_AOT, domain, NULL);
- jit_trampolines++;
+ UnlockedIncrement (&jit_trampolines);
return tramp;
}
gpointer
mono_create_rgctx_lazy_fetch_trampoline (guint32 offset)
{
- static gboolean inited = FALSE;
- static int num_trampolines = 0;
MonoTrampInfo *info;
-
gpointer tramp, ptr;
mono_trampolines_lock ();
g_hash_table_insert (rgctx_lazy_fetch_trampoline_hash, GUINT_TO_POINTER (offset), ptr);
g_assert (offset != -1);
g_hash_table_insert (rgctx_lazy_fetch_trampoline_hash_addr, ptr, GUINT_TO_POINTER (offset + 1));
+ rgctx_num_lazy_fetch_trampolines ++;
mono_trampolines_unlock ();
- if (!inited) {
- mono_counters_register ("RGCTX num lazy fetch trampolines",
- MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &num_trampolines);
- inited = TRUE;
- }
- num_trampolines++;
-
return ptr;
}