+
/*
* mini-runtime.c: Runtime code for the JIT
*
* Copyright 2002-2003 Ximian, Inc.
* Copyright 2003-2010 Novell, Inc.
* Copyright 2011-2015 Xamarin, Inc (http://www.xamarin.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
*/
#include <config.h>
#ifdef MONO_ARCH_LLVM_SUPPORTED
#ifdef ENABLE_LLVM
#include "mini-llvm-cpp.h"
+#include "llvm-jit.h"
#endif
#endif
wrapper = mono_marshal_get_icall_wrapper (callinfo->sig, name, callinfo->func, check_exc);
g_free (name);
- if (do_compile)
+ if (do_compile) {
trampoline = mono_compile_method (wrapper);
- else
- trampoline = mono_create_ftnptr (domain, mono_create_jit_trampoline_in_domain (domain, wrapper));
+ } else {
+ MonoError error;
+
+ trampoline = mono_create_jit_trampoline (domain, wrapper, &error);
+ mono_error_assert_ok (&error);
+ trampoline = mono_create_ftnptr (domain, (gpointer)trampoline);
+ }
mono_loader_lock ();
if (!callinfo->trampoline) {
case MONO_PATCH_INFO_METHOD_JUMP:
case MONO_PATCH_INFO_IMAGE:
case MONO_PATCH_INFO_ICALL_ADDR:
+ case MONO_PATCH_INFO_ICALL_ADDR_CALL:
case MONO_PATCH_INFO_FIELD:
case MONO_PATCH_INFO_SFLDA:
case MONO_PATCH_INFO_SEQ_POINT_INFO:
break;
}
case MONO_PATCH_INFO_METHOD_JUMP:
- target = mono_create_jump_trampoline (domain, patch_info->data.method, FALSE);
+ target = mono_create_jump_trampoline (domain, patch_info->data.method, FALSE, error);
+ if (!mono_error_ok (error))
+ return NULL;
#if defined(__native_client__) && defined(__native_client_codegen__)
# if defined(TARGET_AMD64)
/* This target is an absolute address, not relative to the */
* avoid trampoline, as we not yet know where we will
* be installed.
*/
- target = mono_create_jit_trampoline_in_domain (domain, patch_info->data.method);
+ target = mono_create_jit_trampoline (domain, patch_info->data.method, error);
+ if (!mono_error_ok (error))
+ return NULL;
#else
if (patch_info->data.method == method) {
target = code;
} else {
/* get the trampoline to the method from the domain */
- target = mono_create_jit_trampoline_in_domain (domain, patch_info->data.method);
+ target = mono_create_jit_trampoline (domain, patch_info->data.method, error);
+ if (!mono_error_ok (error))
+ return NULL;
}
#endif
break;
/* Done by the generated code */
;
else {
- if (run_cctors)
- mono_runtime_class_init (vtable);
+ if (run_cctors) {
+ if (!mono_runtime_class_init_full (vtable, error)) {
+ return NULL;
+ }
+ }
}
target = (char*)mono_vtable_get_static_field_data (vtable) + patch_info->data.field->offset;
break;
target = (mono_metadata_blob_heap (patch_info->data.token->image, patch_info->data.token->token) + 2);
break;
case MONO_PATCH_INFO_ICALL_ADDR:
+ case MONO_PATCH_INFO_ICALL_ADDR_CALL:
/* run_cctors == 0 -> AOT */
if (patch_info->data.method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
const char *exc_class;
/* We can't use a domain specific method in another domain */
if (! ((domain != target_domain) && !info->domain_neutral)) {
MonoVTable *vtable;
- MonoException *tmpEx;
mono_jit_stats.methods_lookups++;
- vtable = mono_class_vtable (domain, method->klass);
+ vtable = mono_class_vtable_full (domain, method->klass, error);
+ if (!is_ok (error))
+ return NULL;
g_assert (vtable);
- tmpEx = mono_runtime_class_init_full (vtable, FALSE);
- if (tmpEx) {
- mono_error_set_exception_instance (error, tmpEx);
+ if (!mono_runtime_class_init_full (vtable, error))
return NULL;
- }
return mono_create_ftnptr (target_domain, info->code_start);
}
}
if (!mono_llvm_only) {
vtable = mono_class_vtable (domain, method->klass);
g_assert (vtable);
- mono_runtime_class_init (vtable);
+ if (!mono_runtime_class_init_full (vtable, error))
+ return NULL;
}
}
}
}
g_slist_free (remove);
}
-
mono_domain_unlock (domain);
#ifdef MONO_ARCH_HAVE_INVALIDATE_METHOD
info->sig = mono_method_signature (method);
invoke = mono_marshal_get_runtime_invoke (method, FALSE);
- info->vtable = mono_class_vtable_full (domain, method->klass, TRUE);
+ info->vtable = mono_class_vtable_full (domain, method->klass, error);
+ if (!mono_error_ok (error))
+ return NULL;
g_assert (info->vtable);
MonoMethodSignature *sig = mono_method_signature (method);
if (!info->dyn_call_info) {
if (mono_llvm_only) {
-#ifndef ENABLE_GSHAREDVT
+#ifndef MONO_ARCH_GSHAREDVT_SUPPORTED
g_assert_not_reached ();
#endif
info->gsharedvt_invoke = TRUE;
mono_error_set_exception_instance (error, (MonoException*) *exc);
if (sig->ret->type != MONO_TYPE_VOID && info->ret_box_class)
- return mono_value_box (domain, info->ret_box_class, retval);
+ return mono_value_box_checked (domain, info->ret_box_class, retval, error);
else
return *(MonoObject**)retval;
}
* but keep it just in case for moonlight.
*/
mono_class_setup_vtable (method->klass);
- if (method->klass->exception_type != MONO_EXCEPTION_NONE) {
+ if (mono_class_has_failure (method->klass)) {
MonoException *fail_exc = mono_class_get_exception_for_failure (method->klass);
if (exc)
*exc = (MonoObject*)fail_exc;
* We need this here because mono_marshal_get_runtime_invoke can place
* the helper method in System.Object and not the target class.
*/
- if (exc)
- {
- *exc = (MonoObject*)mono_runtime_class_init_full (info->vtable, FALSE);
- if (*exc) {
- mono_error_set_exception_instance (error, (MonoException*) *exc);
- return NULL;
- }
- } else {
- mono_runtime_class_init (info->vtable);
+ if (!mono_runtime_class_init_full (info->vtable, error)) {
+ if (exc)
+ *exc = (MonoObject*) mono_error_convert_to_exception (error);
+ return NULL;
}
/* If coop is enabled, and the caller didn't ask for the exception to be caught separately,
mono_arch_finish_dyn_call (info->dyn_call_info, buf);
if (info->ret_box_class)
- return mono_value_box (domain, info->ret_box_class, retval);
+ return mono_value_box_checked (domain, info->ret_box_class, retval, error);
else
return *(MonoObject**)retval;
}
}
#endif
-static void
+static G_GNUC_UNUSED void
no_imt_trampoline (void)
{
g_assert_not_reached ();
}
-static void
+static G_GNUC_UNUSED void
no_vcall_trampoline (void)
{
g_assert_not_reached ();
mono_align_small_structs = TRUE;
else if (!strcmp (option, "native-debugger-break"))
debug_options.native_debugger_break = TRUE;
+ else if (!strcmp (option, "disable_omit_fp"))
+ debug_options.disable_omit_fp = TRUE;
else
return FALSE;
mono_counters_register ("JIT/linear_scan (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_linear_scan);
mono_counters_register ("JIT/arch_allocate_vars (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_arch_allocate_vars);
mono_counters_register ("JIT/spill_global_vars (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_spill_global_vars);
- mono_counters_register ("JIT/jit_local_cprop3 (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_local_cprop3);
- mono_counters_register ("JIT/jit_local_deadce3 (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_local_deadce3);
+ mono_counters_register ("JIT/local_cprop3 (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_local_cprop3);
+ mono_counters_register ("JIT/local_deadce3 (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_local_deadce3);
mono_counters_register ("JIT/codegen (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_codegen);
mono_counters_register ("JIT/create_jit_info (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_create_jit_info);
mono_counters_register ("JIT/gc_create_gc_map (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_gc_create_gc_map);
g_free (info);
}
+static void
+free_jit_callee_list (gpointer key, gpointer value, gpointer user_data)
+{
+ g_slist_free (value);
+}
+
static void
mini_free_jit_domain_info (MonoDomain *domain)
{
mono_debugger_agent_free_domain_info (domain);
if (info->gsharedvt_arg_tramp_hash)
g_hash_table_destroy (info->gsharedvt_arg_tramp_hash);
+ if (info->llvm_jit_callees) {
+ g_hash_table_foreach (info->llvm_jit_callees, free_jit_callee_list, NULL);
+ g_hash_table_destroy (info->llvm_jit_callees);
+ }
#ifdef ENABLE_LLVM
mono_llvm_free_domain_info (domain);
#endif
#define JIT_TRAMPOLINES_WORK
#ifdef JIT_TRAMPOLINES_WORK
callbacks.compile_method = mono_jit_compile_method;
+ callbacks.create_jump_trampoline = mono_create_jump_trampoline;
+ callbacks.create_jit_trampoline = mono_create_jit_trampoline;
#endif
mono_install_callbacks (&callbacks);
#ifdef JIT_TRAMPOLINES_WORK
mono_install_free_method (mono_jit_free_method);
- mono_install_trampoline (mono_create_jit_trampoline);
- mono_install_jump_trampoline (mono_create_jump_trampoline);
#ifndef DISABLE_REMOTING
mono_install_remoting_trampoline (mono_jit_create_remoting_trampoline);
#endif
register_icall (ves_icall_object_new_specific, "ves_icall_object_new_specific", "object ptr", FALSE);
register_icall (mono_array_new, "mono_array_new", "object ptr ptr int32", FALSE);
register_icall (ves_icall_array_new_specific, "ves_icall_array_new_specific", "object ptr int32", FALSE);
- register_icall (mono_runtime_class_init, "mono_runtime_class_init", "void ptr", FALSE);
+ register_icall (ves_icall_runtime_class_init, "ves_icall_runtime_class_init", "void ptr", FALSE);
register_icall (mono_ldftn, "mono_ldftn", "ptr ptr", FALSE);
register_icall (mono_ldvirtfn, "mono_ldvirtfn", "ptr object ptr", FALSE);
register_icall (mono_ldvirtfn_gshared, "mono_ldvirtfn_gshared", "ptr object ptr", FALSE);
void
mini_cleanup (MonoDomain *domain)
{
- mono_runtime_shutdown_stat_profiler ();
+ if (mono_profiler_get_events () & MONO_PROFILE_STATISTICAL)
+ mono_runtime_shutdown_stat_profiler ();
#ifndef DISABLE_COM
cominterop_release_all_rcws ();
/* This accesses metadata so needs to be called before runtime shutdown */
print_jit_stats ();
- mono_profiler_shutdown ();
-
#ifndef MONO_CROSS_COMPILE
mono_runtime_cleanup (domain);
#endif
+ mono_profiler_shutdown ();
+
free_jit_tls_data ((MonoJitTlsData *)mono_native_tls_get_value (mono_jit_tls_id));
mono_icall_cleanup ();