#include <mono/utils/mono-threads.h>
#include <mono/utils/mono-threads-coop.h>
#include <mono/utils/checked-build.h>
+#include <mono/utils/w32handle.h>
#include <mono/io-layer/io-layer.h>
#include "mini.h"
handle = mono_ldtoken_checked (patch_info->data.token->image,
patch_info->data.token->token, &handle_class, patch_info->data.token->has_context ? &patch_info->data.token->context : NULL, error);
if (!mono_error_ok (error))
- g_error ("Could not patch ldtoken due to %s", mono_error_get_message (error));
+ return NULL;
mono_class_init (handle_class);
mono_class_init (mono_class_from_mono_type ((MonoType *)handle));
runtime_invoke = (MonoObject *(*)(MonoObject *, void **, MonoObject **, void *))info->runtime_invoke;
runtime_invoke (NULL, args, exc, info->compiled_method);
- if (exc && *exc) {
- mono_error_set_exception_instance (error, (MonoException*) *exc);
+ if (exc && *exc)
return NULL;
- }
if (sig->ret->type != MONO_TYPE_VOID && info->ret_box_class)
return mono_value_box_checked (domain, info->ret_box_class, retval, error);
}
#endif
- if (mono_llvm_only)
- return mono_llvmonly_runtime_invoke (method, info, obj, params, exc, error);
+ MonoObject *result;
- runtime_invoke = (MonoObject *(*)(MonoObject *, void **, MonoObject **, void *))info->runtime_invoke;
+ if (mono_llvm_only) {
+ result = mono_llvmonly_runtime_invoke (method, info, obj, params, exc, error);
+ if (!is_ok (error))
+ return NULL;
+ } else {
+ runtime_invoke = (MonoObject *(*)(MonoObject *, void **, MonoObject **, void *))info->runtime_invoke;
- MonoObject *result = runtime_invoke ((MonoObject *)obj, params, exc, info->compiled_method);
+ result = runtime_invoke ((MonoObject *)obj, params, exc, info->compiled_method);
+ }
if (catchExcInMonoError && *exc != NULL)
mono_error_set_exception_instance (error, (MonoException*) *exc);
return result;
typedef struct {
MonoVTable *vtable;
int slot;
-} IMTThunkInfo;
+} IMTTrampInfo;
-typedef gpointer (*IMTThunkFunc) (gpointer *arg, MonoMethod *imt_method);
+typedef gpointer (*IMTTrampFunc) (gpointer *arg, MonoMethod *imt_method);
/*
- * mini_llvmonly_initial_imt_thunk:
+ * mini_llvmonly_initial_imt_tramp:
*
- * This function is called the first time a call is made through an IMT thunk.
- * It should have the same signature as the mono_llvmonly_imt_thunk_... functions.
+ * This function is called the first time a call is made through an IMT trampoline.
+ * It should have the same signature as the mono_llvmonly_imt_tramp_... functions.
*/
static gpointer
-mini_llvmonly_initial_imt_thunk (gpointer *arg, MonoMethod *imt_method)
+mini_llvmonly_initial_imt_tramp (gpointer *arg, MonoMethod *imt_method)
{
- IMTThunkInfo *info = (IMTThunkInfo*)arg;
+ IMTTrampInfo *info = (IMTTrampInfo*)arg;
gpointer *imt;
gpointer *ftndesc;
- IMTThunkFunc func;
+ IMTTrampFunc func;
mono_vtable_build_imt_slot (info->vtable, info->slot);
imt = (gpointer*)info->vtable;
imt -= MONO_IMT_SIZE;
- /* Return what the real IMT thunk returns */
+ /* Return what the real IMT trampoline returns */
ftndesc = imt [info->slot];
func = ftndesc [0];
- if (func == (IMTThunkFunc)mini_llvmonly_initial_imt_thunk)
+ if (func == (IMTTrampFunc)mini_llvmonly_initial_imt_tramp)
/* Happens when the imt slot contains only a generic virtual method */
return NULL;
return func ((gpointer *)ftndesc [1], imt_method);
/* This is called indirectly through an imt slot. */
static gpointer
-mono_llvmonly_imt_thunk (gpointer *arg, MonoMethod *imt_method)
+mono_llvmonly_imt_tramp (gpointer *arg, MonoMethod *imt_method)
{
int i = 0;
- /* arg points to an array created in mono_llvmonly_get_imt_thunk () */
+ /* arg points to an array created in mono_llvmonly_get_imt_trampoline () */
while (arg [i] && arg [i] != imt_method)
i += 2;
g_assert (arg [i]);
return arg [i + 1];
}
-/* Optimized versions of mono_llvmonly_imt_thunk () for different table sizes */
+/* Optimized versions of mono_llvmonly_imt_trampoline () for different table sizes */
static gpointer
-mono_llvmonly_imt_thunk_1 (gpointer *arg, MonoMethod *imt_method)
+mono_llvmonly_imt_tramp_1 (gpointer *arg, MonoMethod *imt_method)
{
//g_assert (arg [0] == imt_method);
return arg [1];
}
static gpointer
-mono_llvmonly_imt_thunk_2 (gpointer *arg, MonoMethod *imt_method)
+mono_llvmonly_imt_tramp_2 (gpointer *arg, MonoMethod *imt_method)
{
//g_assert (arg [0] == imt_method || arg [2] == imt_method);
if (arg [0] == imt_method)
}
static gpointer
-mono_llvmonly_imt_thunk_3 (gpointer *arg, MonoMethod *imt_method)
+mono_llvmonly_imt_tramp_3 (gpointer *arg, MonoMethod *imt_method)
{
//g_assert (arg [0] == imt_method || arg [2] == imt_method || arg [4] == imt_method);
if (arg [0] == imt_method)
}
/*
- * A version of the imt thunk used for generic virtual/variant iface methods.
- * Unlikely a normal imt thunk, its possible that IMT_METHOD is not found
+ * A version of the imt trampoline used for generic virtual/variant iface methods.
+ * Unlikely a normal imt trampoline, its possible that IMT_METHOD is not found
* in the search table. The original JIT code had a 'fallback' trampoline it could
* call, but we can't do that, so we just return NULL, and the compiled code
* will handle it.
*/
static gpointer
-mono_llvmonly_fallback_imt_thunk (gpointer *arg, MonoMethod *imt_method)
+mono_llvmonly_fallback_imt_tramp (gpointer *arg, MonoMethod *imt_method)
{
int i = 0;
}
static gpointer
-mono_llvmonly_get_imt_thunk (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckItem **imt_entries, int count, gpointer fail_tramp)
+mono_llvmonly_get_imt_trampoline (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckItem **imt_entries, int count, gpointer fail_tramp)
{
gpointer *buf;
gpointer *res;
gboolean virtual_generic = FALSE;
/*
- * Create an array which is passed to the imt thunk functions.
+ * Create an array which is passed to the imt trampoline functions.
* The array contains MonoMethod-function descriptor pairs, terminated by a NULL entry.
*/
res = (void **)mono_domain_alloc (domain, 2 * sizeof (gpointer));
switch (real_count) {
case 1:
- res [0] = mono_llvmonly_imt_thunk_1;
+ res [0] = mono_llvmonly_imt_tramp_1;
break;
case 2:
- res [0] = mono_llvmonly_imt_thunk_2;
+ res [0] = mono_llvmonly_imt_tramp_2;
break;
case 3:
- res [0] = mono_llvmonly_imt_thunk_3;
+ res [0] = mono_llvmonly_imt_tramp_3;
break;
default:
- res [0] = mono_llvmonly_imt_thunk;
+ res [0] = mono_llvmonly_imt_tramp;
break;
}
if (virtual_generic || fail_tramp)
- res [0] = mono_llvmonly_fallback_imt_thunk;
+ res [0] = mono_llvmonly_fallback_imt_tramp;
res [1] = buf;
return res;
MonoException *exc;
MONO_SIG_HANDLER_GET_CONTEXT;
+ if (mono_runtime_get_no_exec ())
+ exit (1);
+
MONO_ENTER_GC_UNSAFE_UNBALANCED;
exc = mono_get_exception_execution_engine ("SIGILL");
if (mono_llvm_only) {
if (slot_index < 0) {
- /* Initialize the IMT thunks to a 'trampoline' so the generated code doesn't have to initialize it */
+ /* Initialize the IMT trampoline to a 'trampoline' so the generated code doesn't have to initialize it */
// FIXME: Memory management
gpointer *ftndesc = g_malloc (2 * sizeof (gpointer));
- IMTThunkInfo *info = g_new0 (IMTThunkInfo, 1);
+ IMTTrampInfo *info = g_new0 (IMTTrampInfo, 1);
info->vtable = vt;
info->slot = index;
- ftndesc [0] = mini_llvmonly_initial_imt_thunk;
+ ftndesc [0] = mini_llvmonly_initial_imt_tramp;
ftndesc [1] = info;
mono_memory_barrier ();
return ftndesc;
del->extra_arg = mini_get_delegate_arg (del->method, del->method_ptr);
}
+char*
+mono_get_delegate_virtual_invoke_impl_name (gboolean load_imt_reg, int offset)
+{
+ int abs_offset;
+
+ abs_offset = offset;
+ if (abs_offset < 0)
+ abs_offset = - abs_offset;
+ return g_strdup_printf ("delegate_virtual_invoke%s_%s%d", load_imt_reg ? "_imt" : "", offset < 0 ? "m_" : "", abs_offset / SIZEOF_VOID_P);
+}
+
gpointer
mono_get_delegate_virtual_invoke_impl (MonoMethodSignature *sig, MonoMethod *method)
{
/* FIXME Support more cases */
if (mono_aot_only) {
- char tramp_name [256];
- const char *imt = load_imt_reg ? "_imt" : "";
- int ind = (load_imt_reg ? (-offset) : offset) / SIZEOF_VOID_P;
-
- sprintf (tramp_name, "delegate_virtual_invoke%s_%d", imt, ind);
- cache [idx] = (guint8 *)mono_aot_get_trampoline (tramp_name);
+ cache [idx] = (guint8 *)mono_aot_get_trampoline (mono_get_delegate_virtual_invoke_impl_name (load_imt_reg, offset));
g_assert (cache [idx]);
} else {
cache [idx] = (guint8 *)mono_arch_get_delegate_virtual_invoke_impl (sig, method, offset, load_imt_reg);
mono_counters_register ("Aliases eliminated", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.alias_removed);
mono_counters_register ("Aliased loads eliminated", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.loads_eliminated);
mono_counters_register ("Aliased stores eliminated", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.stores_eliminated);
+ mono_counters_register ("Optimized immediate divisions", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.optimized_divisions);
}
static void runtime_invoke_info_free (gpointer value);
mono_counters_init ();
+#ifndef HOST_WIN32
+ mono_w32handle_init ();
+#endif
+
mono_threads_runtime_init (&ticallbacks);
if (g_getenv ("MONO_DEBUG") != NULL)
}
if (mono_llvm_only) {
- mono_install_imt_thunk_builder (mono_llvmonly_get_imt_thunk);
- mono_set_always_build_imt_thunks (TRUE);
+ mono_install_imt_trampoline_builder (mono_llvmonly_get_imt_trampoline);
+ mono_set_always_build_imt_trampolines (TRUE);
} else if (mono_aot_only) {
- mono_install_imt_thunk_builder (mono_aot_get_imt_thunk);
+ mono_install_imt_trampoline_builder (mono_aot_get_imt_trampoline);
} else {
- mono_install_imt_thunk_builder (mono_arch_build_imt_thunk);
+ mono_install_imt_trampoline_builder (mono_arch_build_imt_trampoline);
}
/*Init arch tls information only after the metadata side is inited to make sure we see dynamic appdomain tls keys*/
mono_simd_intrinsics_init ();
#endif
-#if MONO_SUPPORT_TASKLETS
mono_tasklets_init ();
-#endif
register_trampolines (domain);
*/
mono_runtime_set_no_exec (TRUE);
+ mono_mem_account_register_counters ();
+
#define JIT_RUNTIME_WORKS
#ifdef JIT_RUNTIME_WORKS
mono_install_runtime_cleanup ((MonoDomainFunc)mini_cleanup);
ves_icall_get_trace);
mono_add_internal_call ("Mono.Runtime::mono_runtime_install_handlers",
mono_runtime_install_handlers);
+ mono_add_internal_call ("Mono.Runtime::mono_runtime_cleanup_handlers",
+ mono_runtime_cleanup_handlers);
#if defined(PLATFORM_ANDROID) || defined(TARGET_ANDROID)
mono_add_internal_call ("System.Diagnostics.Debugger::Mono_UnhandledException_internal",
register_icall (mono_thread_get_undeniable_exception, "mono_thread_get_undeniable_exception", "object", FALSE);
register_icall (mono_thread_interruption_checkpoint, "mono_thread_interruption_checkpoint", "object", FALSE);
register_icall (mono_thread_force_interruption_checkpoint_noraise, "mono_thread_force_interruption_checkpoint_noraise", "object", FALSE);
-#ifndef DISABLE_REMOTING
- register_icall (mono_store_remote_field_new_icall, "mono_store_remote_field_new_icall", "void object ptr ptr object", FALSE);
-#endif
#if defined(__native_client__) || defined(__native_client_codegen__)
register_icall (mono_nacl_gc, "mono_nacl_gc", "void", FALSE);
register_icall (mono_get_assembly_object, "mono_get_assembly_object", "object ptr", TRUE);
register_icall (mono_get_method_object, "mono_get_method_object", "object ptr", TRUE);
register_icall (mono_throw_method_access, "mono_throw_method_access", "void ptr ptr", FALSE);
+ register_icall_no_wrapper (mono_dummy_jit_icall, "mono_dummy_jit_icall", "void");
register_icall_with_wrapper (mono_monitor_enter, "mono_monitor_enter", "void obj");
register_icall_with_wrapper (mono_monitor_enter_v4, "mono_monitor_enter_v4", "void obj ptr");
g_print ("IMT colliding slots: %ld\n", mono_stats.imt_slots_with_collisions);
g_print ("IMT max collisions: %ld\n", mono_stats.imt_max_collisions_in_slot);
g_print ("IMT methods at max col: %ld\n", mono_stats.imt_method_count_when_max_collisions);
- g_print ("IMT thunks size: %ld\n", mono_stats.imt_thunks_size);
+ g_print ("IMT trampolines size: %ld\n", mono_stats.imt_trampolines_size);
g_print ("JIT info table inserts: %ld\n", mono_stats.jit_info_table_insert_count);
g_print ("JIT info table removes: %ld\n", mono_stats.jit_info_table_remove_count);
mono_os_mutex_destroy (&jit_mutex);
mono_code_manager_cleanup ();
+
+#ifndef HOST_WIN32
+ mono_w32handle_cleanup ();
+#endif
}
void