3 * Runtime code for the JIT
6 * Paolo Molaro (lupus@ximian.com)
7 * Dietmar Maurer (dietmar@ximian.com)
9 * Copyright 2002-2003 Ximian, Inc.
10 * Copyright 2003-2010 Novell, Inc.
11 * Copyright 2011-2015 Xamarin, Inc (http://www.xamarin.com)
12 * Licensed under the MIT license. See LICENSE file in the project root for full license information.
23 #ifdef HAVE_SYS_TIME_H
30 #include <mono/utils/memcheck.h>
32 #include <mono/metadata/assembly.h>
33 #include <mono/metadata/loader.h>
34 #include <mono/metadata/tabledefs.h>
35 #include <mono/metadata/class.h>
36 #include <mono/metadata/object.h>
37 #include <mono/metadata/tokentype.h>
38 #include <mono/metadata/tabledefs.h>
39 #include <mono/metadata/threads.h>
40 #include <mono/metadata/appdomain.h>
41 #include <mono/metadata/debug-helpers.h>
42 #include <mono/metadata/profiler-private.h>
43 #include <mono/metadata/mono-config.h>
44 #include <mono/metadata/environment.h>
45 #include <mono/metadata/mono-debug.h>
46 #include <mono/metadata/gc-internals.h>
47 #include <mono/metadata/threads-types.h>
48 #include <mono/metadata/mempool-internals.h>
49 #include <mono/metadata/attach.h>
50 #include <mono/metadata/runtime.h>
51 #include <mono/metadata/reflection-internals.h>
52 #include <mono/metadata/monitor.h>
53 #include <mono/utils/mono-math.h>
54 #include <mono/utils/mono-compiler.h>
55 #include <mono/utils/mono-counters.h>
56 #include <mono/utils/mono-error-internals.h>
57 #include <mono/utils/mono-logger-internals.h>
58 #include <mono/utils/mono-mmap.h>
59 #include <mono/utils/mono-path.h>
60 #include <mono/utils/mono-tls.h>
61 #include <mono/utils/mono-hwcap.h>
62 #include <mono/utils/dtrace.h>
63 #include <mono/utils/mono-signal-handler.h>
64 #include <mono/utils/mono-threads.h>
65 #include <mono/utils/mono-threads-coop.h>
66 #include <mono/utils/checked-build.h>
67 #include <mono/utils/mono-proclib.h>
68 #include <mono/metadata/w32handle.h>
69 #include <mono/metadata/threadpool.h>
72 #include "seq-points.h"
79 #include "jit-icalls.h"
82 #include "mini-llvm.h"
83 #include "debugger-agent.h"
86 #ifdef MONO_ARCH_LLVM_SUPPORTED
88 #include "mini-llvm-cpp.h"
93 #ifdef ENABLE_INTERPRETER
94 #include "interp/interp.h"
97 static guint32 default_opt = 0;
98 static gboolean default_opt_set = FALSE;
100 gboolean mono_compile_aot = FALSE;
101 /* If this is set, no code is generated dynamically, everything is taken from AOT files */
102 gboolean mono_aot_only = FALSE;
103 /* Same as mono_aot_only, but only LLVM compiled code is used, no trampolines */
104 gboolean mono_llvm_only = FALSE;
105 MonoAotMode mono_aot_mode = MONO_AOT_MODE_NONE;
107 const char *mono_build_date;
108 gboolean mono_do_signal_chaining;
109 gboolean mono_do_crash_chaining;
110 int mini_verbose = 0;
113 * This flag controls whenever the runtime uses LLVM for JIT compilation, and whenever
114 * it can load AOT code compiled by LLVM.
116 gboolean mono_use_llvm = FALSE;
118 gboolean mono_use_interpreter = FALSE;
120 #define mono_jit_lock() mono_os_mutex_lock (&jit_mutex)
121 #define mono_jit_unlock() mono_os_mutex_unlock (&jit_mutex)
122 static mono_mutex_t jit_mutex;
124 static MonoCodeManager *global_codeman;
126 MonoDebugOptions debug_options;
128 #ifdef VALGRIND_JIT_REGISTER_MAP
129 int valgrind_register;
131 GList* mono_aot_paths;
133 static GPtrArray *profile_options;
135 static GSList *tramp_infos;
137 static void register_icalls (void);
140 mono_running_on_valgrind (void)
143 if (RUNNING_ON_VALGRIND){
144 #ifdef VALGRIND_JIT_REGISTER_MAP
145 valgrind_register = TRUE;
159 find_tramp (gpointer key, gpointer value, gpointer user_data)
161 FindTrampUserData *ud = (FindTrampUserData*)user_data;
164 ud->method = (MonoMethod*)key;
168 G_GNUC_UNUSED static char*
169 get_method_from_ip (void *ip)
175 MonoDomain *domain = mono_domain_get ();
176 MonoDebugSourceLocation *location;
177 FindTrampUserData user_data;
180 domain = mono_get_root_domain ();
182 ji = mono_jit_info_table_find_internal (domain, (char *)ip, TRUE, TRUE);
185 user_data.method = NULL;
186 mono_domain_lock (domain);
187 g_hash_table_foreach (domain_jit_info (domain)->jit_trampoline_hash, find_tramp, &user_data);
188 mono_domain_unlock (domain);
189 if (user_data.method) {
190 char *mname = mono_method_full_name (user_data.method, TRUE);
191 res = g_strdup_printf ("<%p - JIT trampoline for %s>", ip, mname);
197 } else if (ji->is_trampoline) {
198 res = g_strdup_printf ("<%p - %s trampoline>", ip, ((MonoTrampInfo*)ji->d.tramp_info)->name);
202 method = jinfo_get_method (ji);
203 method_name = mono_method_full_name (method, TRUE);
204 /* FIXME: unused ? */
205 location = mono_debug_lookup_source_location (method, (guint32)((guint8*)ip - (guint8*)ji->code_start), domain);
207 res = g_strdup_printf (" %s {%p} + 0x%x (%p %p) [%p - %s]", method_name, method, (int)((char*)ip - (char*)ji->code_start), ji->code_start, (char*)ji->code_start + ji->code_size, domain, domain->friendly_name);
209 mono_debug_free_source_location (location);
210 g_free (method_name);
217 * \param ip an instruction pointer address
219 * This method is used from a debugger to get the name of the
220 * method at address \p ip. This routine is typically invoked from
221 * a debugger like this:
223 * (gdb) print mono_pmip ($pc)
225 * \returns the name of the method at address \p ip.
230 return get_method_from_ip (ip);
234 * mono_print_method_from_ip:
235 * \param ip an instruction pointer address
237 * This method is used from a debugger to get the name of the
238 * method at address \p ip.
240 * This prints the name of the method at address \p ip in the standard
241 * output. Unlike \c mono_pmip which returns a string, this routine
242 * prints the value on the standard output.
245 mono_print_method_from_ip (void *ip)
249 MonoDebugSourceLocation *source;
250 MonoDomain *domain = mono_domain_get ();
251 MonoDomain *target_domain = mono_domain_get ();
252 FindTrampUserData user_data;
253 MonoGenericSharingContext*gsctx;
254 const char *shared_type;
257 domain = mono_get_root_domain ();
258 ji = mini_jit_info_table_find_ext (domain, (char *)ip, TRUE, &target_domain);
259 if (ji && ji->is_trampoline) {
260 MonoTrampInfo *tinfo = (MonoTrampInfo *)ji->d.tramp_info;
262 printf ("IP %p is at offset 0x%x of trampoline '%s'.\n", ip, (int)((guint8*)ip - tinfo->code), tinfo->name);
268 user_data.method = NULL;
269 mono_domain_lock (domain);
270 g_hash_table_foreach (domain_jit_info (domain)->jit_trampoline_hash, find_tramp, &user_data);
271 mono_domain_unlock (domain);
273 if (user_data.method) {
274 char *mname = mono_method_full_name (user_data.method, TRUE);
275 printf ("IP %p is a JIT trampoline for %s\n", ip, mname);
280 g_print ("No method at %p\n", ip);
284 method = mono_method_full_name (jinfo_get_method (ji), TRUE);
285 source = mono_debug_lookup_source_location (jinfo_get_method (ji), (guint32)((guint8*)ip - (guint8*)ji->code_start), target_domain);
287 gsctx = mono_jit_info_get_generic_sharing_context (ji);
290 if (gsctx->is_gsharedvt)
291 shared_type = "gsharedvt ";
293 shared_type = "gshared ";
296 g_print ("IP %p at offset 0x%x of %smethod %s (%p %p)[domain %p - %s]\n", ip, (int)((char*)ip - (char*)ji->code_start), shared_type, method, ji->code_start, (char*)ji->code_start + ji->code_size, target_domain, target_domain->friendly_name);
299 g_print ("%s:%d\n", source->source_file, source->row);
302 mono_debug_free_source_location (source);
307 * mono_method_same_domain:
309 * Determine whenever two compiled methods are in the same domain, thus
310 * the address of the callee can be embedded in the caller.
312 gboolean mono_method_same_domain (MonoJitInfo *caller, MonoJitInfo *callee)
316 if (!caller || caller->is_trampoline || !callee || callee->is_trampoline)
320 * If the call was made from domain-neutral to domain-specific
321 * code, we can't patch the call site.
323 if (caller->domain_neutral && !callee->domain_neutral)
326 cmethod = jinfo_get_method (caller);
327 if ((cmethod->klass == mono_defaults.appdomain_class) &&
328 (strstr (cmethod->name, "InvokeInDomain"))) {
329 /* The InvokeInDomain methods change the current appdomain */
337 * mono_global_codeman_reserve:
339 * Allocate code memory from the global code manager.
341 void *mono_global_codeman_reserve (int size)
346 g_error ("Attempting to allocate from the global code manager while running in aot-only mode.\n");
348 if (!global_codeman) {
349 /* This can happen during startup */
350 global_codeman = mono_code_manager_new ();
351 return mono_code_manager_reserve (global_codeman, size);
355 ptr = mono_code_manager_reserve (global_codeman, size);
361 /* The callback shouldn't take any locks */
363 mono_global_codeman_foreach (MonoCodeManagerFunc func, void *user_data)
366 mono_code_manager_foreach (global_codeman, func, user_data);
371 * mono_create_unwind_op:
373 * Create an unwind op with the given parameters.
376 mono_create_unwind_op (int when, int tag, int reg, int val)
378 MonoUnwindOp *op = g_new0 (MonoUnwindOp, 1);
389 mono_jump_info_token_new2 (MonoMemPool *mp, MonoImage *image, guint32 token, MonoGenericContext *context)
391 MonoJumpInfoToken *res = (MonoJumpInfoToken *)mono_mempool_alloc0 (mp, sizeof (MonoJumpInfoToken));
394 res->has_context = context != NULL;
396 memcpy (&res->context, context, sizeof (MonoGenericContext));
402 mono_jump_info_token_new (MonoMemPool *mp, MonoImage *image, guint32 token)
404 return mono_jump_info_token_new2 (mp, image, token, NULL);
408 * mono_tramp_info_create:
410 * Create a MonoTrampInfo structure from the arguments. This function assumes ownership
411 * of JI, and UNWIND_OPS.
414 mono_tramp_info_create (const char *name, guint8 *code, guint32 code_size, MonoJumpInfo *ji, GSList *unwind_ops)
416 MonoTrampInfo *info = g_new0 (MonoTrampInfo, 1);
418 info->name = g_strdup ((char*)name);
420 info->code_size = code_size;
422 info->unwind_ops = unwind_ops;
428 mono_tramp_info_free (MonoTrampInfo *info)
433 mono_free_unwind_info (info->unwind_ops);
434 if (info->owns_uw_info)
435 g_free (info->uw_info);
440 register_trampoline_jit_info (MonoDomain *domain, MonoTrampInfo *info)
444 ji = (MonoJitInfo *)mono_domain_alloc0 (domain, mono_jit_info_size ((MonoJitInfoFlags)0, 0, 0));
445 mono_jit_info_init (ji, NULL, info->code, info->code_size, (MonoJitInfoFlags)0, 0, 0);
446 ji->d.tramp_info = info;
447 ji->is_trampoline = TRUE;
449 ji->unwind_info = mono_cache_unwind_info (info->uw_info, info->uw_info_len);
451 mono_jit_info_table_add (domain, ji);
455 * mono_tramp_info_register:
457 * Remember INFO for use by xdebug, mono_print_method_from_ip (), jit maps, etc.
462 mono_tramp_info_register_internal (MonoTrampInfo *info, MonoDomain *domain, gboolean aot)
470 domain = mono_get_root_domain ();
473 copy = mono_domain_alloc0 (domain, sizeof (MonoTrampInfo));
475 copy = g_new0 (MonoTrampInfo, 1);
477 copy->code = info->code;
478 copy->code_size = info->code_size;
479 copy->name = g_strdup (info->name);
481 if (info->unwind_ops) {
482 copy->uw_info = mono_unwind_ops_encode (info->unwind_ops, ©->uw_info_len);
483 copy->owns_uw_info = TRUE;
485 /* Move unwind info into the domain's memory pool so that it is removed once the domain is released. */
486 guint8 *temp = copy->uw_info;
487 copy->uw_info = mono_domain_alloc (domain, copy->uw_info_len);
488 memcpy (copy->uw_info, temp, copy->uw_info_len);
492 /* Trampolines from aot have the unwind ops already encoded */
493 copy->uw_info = info->uw_info;
494 copy->uw_info_len = info->uw_info_len;
497 mono_save_trampoline_xdebug_info (info);
498 mono_lldb_save_trampoline_info (info);
500 #ifdef MONO_ARCH_HAVE_UNWIND_TABLE
502 mono_arch_unwindinfo_install_tramp_unwind_info (info->unwind_ops, info->code, info->code_size);
506 /* If no root domain has been created yet, postpone the registration. */
508 tramp_infos = g_slist_prepend (tramp_infos, copy);
510 } else if (copy->uw_info) {
511 /* Only register trampolines that have unwind infos */
512 register_trampoline_jit_info (domain, copy);
515 if (mono_jit_map_is_enabled ())
516 mono_emit_jit_tramp (info->code, info->code_size, info->name);
518 mono_tramp_info_free (info);
522 mono_tramp_info_register (MonoTrampInfo *info, MonoDomain *domain)
524 mono_tramp_info_register_internal (info, domain, FALSE);
528 mono_aot_tramp_info_register (MonoTrampInfo *info, MonoDomain *domain)
530 mono_tramp_info_register_internal (info, domain, TRUE);
534 mono_tramp_info_cleanup (void)
538 for (l = tramp_infos; l; l = l->next) {
539 MonoTrampInfo *info = (MonoTrampInfo *)l->data;
541 mono_tramp_info_free (info);
543 g_slist_free (tramp_infos);
546 /* Register trampolines created before the root domain was created in the jit info tables */
548 register_trampolines (MonoDomain *domain)
552 for (l = tramp_infos; l; l = l->next) {
553 MonoTrampInfo *info = (MonoTrampInfo *)l->data;
555 register_trampoline_jit_info (domain, info);
559 G_GNUC_UNUSED static void
565 * Runtime debugging tool, use if (debug_count ()) <x> else <y> to do <x> the first COUNT times, then do <y> afterwards.
566 * Set a breakpoint in break_count () to break the last time <x> is done.
568 G_GNUC_UNUSED gboolean
569 mono_debug_count (void)
571 static int count = 0, int_val = 0;
572 static gboolean inited, has_value = FALSE;
577 char *value = g_getenv ("COUNT");
579 int_val = atoi (value);
589 if (count == int_val)
599 mono_icall_get_wrapper_full (MonoJitICallInfo* callinfo, gboolean do_compile)
604 gconstpointer trampoline;
605 MonoDomain *domain = mono_get_root_domain ();
606 gboolean check_exc = TRUE;
608 if (callinfo->wrapper)
609 return callinfo->wrapper;
611 if (callinfo->trampoline)
612 return callinfo->trampoline;
614 if (!strcmp (callinfo->name, "mono_thread_interruption_checkpoint"))
615 /* This icall is used to check for exceptions, so don't check in the wrapper */
618 name = g_strdup_printf ("__icall_wrapper_%s", callinfo->name);
619 wrapper = mono_marshal_get_icall_wrapper (callinfo->sig, name, callinfo->func, check_exc);
623 trampoline = mono_compile_method_checked (wrapper, &error);
624 mono_error_assert_ok (&error);
627 trampoline = mono_create_jit_trampoline (domain, wrapper, &error);
628 mono_error_assert_ok (&error);
629 trampoline = mono_create_ftnptr (domain, (gpointer)trampoline);
633 if (!callinfo->trampoline) {
634 mono_register_jit_icall_wrapper (callinfo, trampoline);
635 callinfo->trampoline = trampoline;
637 mono_loader_unlock ();
639 return callinfo->trampoline;
643 mono_icall_get_wrapper (MonoJitICallInfo* callinfo)
645 return mono_icall_get_wrapper_full (callinfo, FALSE);
648 static MonoJitDynamicMethodInfo*
649 mono_dynamic_code_hash_lookup (MonoDomain *domain, MonoMethod *method)
651 MonoJitDynamicMethodInfo *res;
653 if (domain_jit_info (domain)->dynamic_code_hash)
654 res = (MonoJitDynamicMethodInfo *)g_hash_table_lookup (domain_jit_info (domain)->dynamic_code_hash, method);
661 register_opcode_emulation (int opcode, const char *name, const char *sigstr, gpointer func, const char *symbol, gboolean no_throw)
664 mini_register_opcode_emulation (opcode, name, sigstr, func, symbol, no_throw);
666 MonoMethodSignature *sig = mono_create_icall_signature (sigstr);
668 g_assert (!sig->hasthis);
669 g_assert (sig->param_count < 3);
671 /* Opcode emulation functions are assumed to don't call mono_raise_exception () */
672 mono_register_jit_icall_full (func, name, sig, no_throw, TRUE, symbol);
677 * For JIT icalls implemented in C.
678 * NAME should be the same as the name of the C function whose address is FUNC.
679 * If @avoid_wrapper is TRUE, no wrapper is generated. This is for perf critical icalls which
680 * can't throw exceptions.
683 register_icall (gpointer func, const char *name, const char *sigstr, gboolean avoid_wrapper)
685 MonoMethodSignature *sig;
688 sig = mono_create_icall_signature (sigstr);
692 mono_register_jit_icall_full (func, name, sig, avoid_wrapper, FALSE, avoid_wrapper ? name : NULL);
696 register_icall_no_wrapper (gpointer func, const char *name, const char *sigstr)
698 MonoMethodSignature *sig;
701 sig = mono_create_icall_signature (sigstr);
705 mono_register_jit_icall_full (func, name, sig, TRUE, FALSE, name);
709 register_icall_with_wrapper (gpointer func, const char *name, const char *sigstr)
711 MonoMethodSignature *sig;
714 sig = mono_create_icall_signature (sigstr);
718 mono_register_jit_icall_full (func, name, sig, FALSE, FALSE, NULL);
722 register_dyn_icall (gpointer func, const char *name, const char *sigstr, gboolean save)
724 MonoMethodSignature *sig;
727 sig = mono_create_icall_signature (sigstr);
731 mono_register_jit_icall (func, name, sig, save);
737 MonoJitTlsData *jit_tls;
739 if ((jit_tls = mono_tls_get_jit_tls ()))
742 * We do not assert here because this function can be called from
743 * mini-gc.c on a thread that has not executed any managed code, yet
744 * (the thread object allocation can trigger a collection).
750 mono_get_lmf_addr (void)
752 return (MonoLMF **)mono_tls_get_lmf_addr ();
756 mono_set_lmf (MonoLMF *lmf)
758 (*mono_get_lmf_addr ()) = lmf;
762 mono_get_jit_tls (void)
764 return (MonoJitTlsData *)mono_tls_get_jit_tls ();
768 mono_set_jit_tls (MonoJitTlsData *jit_tls)
770 MonoThreadInfo *info;
772 mono_tls_set_jit_tls (jit_tls);
774 /* Save it into MonoThreadInfo so it can be accessed by mono_thread_state_init_from_handle () */
775 info = mono_thread_info_current ();
777 mono_thread_info_tls_set (info, TLS_KEY_JIT_TLS, jit_tls);
781 mono_set_lmf_addr (gpointer lmf_addr)
783 MonoThreadInfo *info;
785 mono_tls_set_lmf_addr (lmf_addr);
787 /* Save it into MonoThreadInfo so it can be accessed by mono_thread_state_init_from_handle () */
788 info = mono_thread_info_current ();
790 mono_thread_info_tls_set (info, TLS_KEY_LMF_ADDR, lmf_addr);
796 * Push an MonoLMFExt frame on the LMF stack.
799 mono_push_lmf (MonoLMFExt *ext)
801 #ifdef MONO_ARCH_HAVE_INIT_LMF_EXT
804 lmf_addr = mono_get_lmf_addr ();
806 mono_arch_init_lmf_ext (ext, *lmf_addr);
808 mono_set_lmf ((MonoLMF*)ext);
817 * Pop the last frame from the LMF stack.
820 mono_pop_lmf (MonoLMF *lmf)
822 mono_set_lmf ((MonoLMF *)(((gssize)lmf->previous_lmf) & ~3));
826 * mono_jit_thread_attach:
828 * Called by Xamarin.Mac and other products. Attach thread to runtime if
829 * needed and switch to @domain.
831 * @return the original domain which needs to be restored, or NULL.
834 mono_jit_thread_attach (MonoDomain *domain)
839 g_assert (!mono_threads_is_blocking_transition_enabled ());
842 /* Happens when called from AOTed code which is only used in the root domain. */
843 domain = mono_get_root_domain ();
848 attached = mono_tls_get_jit_tls () != NULL;
851 mono_thread_attach (domain);
854 mono_thread_set_state (mono_thread_internal_current (), ThreadState_Background);
857 orig = mono_domain_get ();
859 mono_domain_set (domain, TRUE);
861 return orig != domain ? orig : NULL;
865 * mono_jit_set_domain:
867 * Set domain to @domain if @domain is not null
870 mono_jit_set_domain (MonoDomain *domain)
872 g_assert (!mono_threads_is_blocking_transition_enabled ());
875 mono_domain_set (domain, TRUE);
880 * \param obj exception object
881 * Abort the thread, print exception information and stack trace
884 mono_thread_abort (MonoObject *obj)
886 /* MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_tls_get_jit_tls (); */
888 /* handle_remove should be eventually called for this thread, too
891 if ((mono_runtime_unhandled_exception_policy_get () == MONO_UNHANDLED_POLICY_LEGACY) ||
892 (obj->vtable->klass == mono_defaults.threadabortexception_class)) {
895 mono_invoke_unhandled_exception_hook (obj);
900 setup_jit_tls_data (gpointer stack_start, gpointer abort_func)
902 MonoJitTlsData *jit_tls;
905 jit_tls = (MonoJitTlsData *)mono_tls_get_jit_tls ();
909 jit_tls = g_new0 (MonoJitTlsData, 1);
911 jit_tls->abort_func = (void (*)(MonoObject *))abort_func;
912 jit_tls->end_of_stack = stack_start;
914 mono_set_jit_tls (jit_tls);
916 lmf = g_new0 (MonoLMF, 1);
917 MONO_ARCH_INIT_TOP_LMF_ENTRY (lmf);
919 jit_tls->first_lmf = lmf;
921 mono_set_lmf_addr (&jit_tls->lmf);
925 #ifdef MONO_ARCH_HAVE_TLS_INIT
926 mono_arch_tls_init ();
929 mono_setup_altstack (jit_tls);
935 free_jit_tls_data (MonoJitTlsData *jit_tls)
937 mono_arch_free_jit_tls_data (jit_tls);
938 mono_free_altstack (jit_tls);
940 g_free (jit_tls->first_lmf);
945 mono_thread_start_cb (intptr_t tid, gpointer stack_start, gpointer func)
947 MonoThreadInfo *thread;
948 void *jit_tls = setup_jit_tls_data (stack_start, mono_thread_abort);
949 thread = mono_thread_info_current_unchecked ();
951 thread->jit_data = jit_tls;
953 mono_arch_cpu_init ();
956 void (*mono_thread_attach_aborted_cb ) (MonoObject *obj) = NULL;
959 mono_thread_abort_dummy (MonoObject *obj)
961 if (mono_thread_attach_aborted_cb)
962 mono_thread_attach_aborted_cb (obj);
964 mono_thread_abort (obj);
968 mono_thread_attach_cb (intptr_t tid, gpointer stack_start)
970 MonoThreadInfo *thread;
971 void *jit_tls = setup_jit_tls_data (stack_start, mono_thread_abort_dummy);
972 thread = mono_thread_info_current_unchecked ();
974 thread->jit_data = jit_tls;
976 mono_arch_cpu_init ();
980 mini_thread_cleanup (MonoNativeThreadId tid)
982 MonoJitTlsData *jit_tls = NULL;
983 MonoThreadInfo *info;
985 info = mono_thread_info_current_unchecked ();
987 /* We can't clean up tls information if we are on another thread, it will clean up the wrong stuff
988 * It would be nice to issue a warning when this happens outside of the shutdown sequence. but it's
989 * not a trivial thing.
991 * The current offender is mono_thread_manage which cleanup threads from the outside.
993 if (info && mono_thread_info_get_tid (info) == tid) {
994 jit_tls = (MonoJitTlsData *)info->jit_data;
995 info->jit_data = NULL;
997 mono_set_jit_tls (NULL);
999 /* If we attach a thread but never call into managed land, we might never get an lmf.*/
1000 if (mono_get_lmf ()) {
1001 mono_set_lmf (NULL);
1002 mono_set_lmf_addr (NULL);
1005 info = mono_thread_info_lookup (tid);
1007 jit_tls = (MonoJitTlsData *)info->jit_data;
1008 info->jit_data = NULL;
1010 mono_hazard_pointer_clear (mono_hazard_pointer_get (), 1);
1014 free_jit_tls_data (jit_tls);
1018 mono_patch_info_list_prepend (MonoJumpInfo *list, int ip, MonoJumpInfoType type, gconstpointer target)
1020 MonoJumpInfo *ji = g_new0 (MonoJumpInfo, 1);
1024 ji->data.target = target;
1030 #if !defined(DISABLE_LOGGING) && !defined(DISABLE_JIT)
1032 static const char* const patch_info_str[] = {
1033 #define PATCH_INFO(a,b) "" #a,
1034 #include "patch-info.h"
1039 mono_ji_type_to_string (MonoJumpInfoType type)
1041 return patch_info_str [type];
1045 mono_print_ji (const MonoJumpInfo *ji)
1048 case MONO_PATCH_INFO_RGCTX_FETCH: {
1049 MonoJumpInfoRgctxEntry *entry = ji->data.rgctx_entry;
1051 printf ("[RGCTX_FETCH ");
1052 mono_print_ji (entry->data);
1053 printf (" - %s]", mono_rgctx_info_type_to_str (entry->info_type));
1056 case MONO_PATCH_INFO_METHODCONST: {
1057 char *s = mono_method_full_name (ji->data.method, TRUE);
1058 printf ("[METHODCONST - %s]", s);
1062 case MONO_PATCH_INFO_INTERNAL_METHOD: {
1063 printf ("[INTERNAL_METHOD - %s]", ji->data.name);
1067 printf ("[%s]", patch_info_str [ji->type]);
1075 mono_ji_type_to_string (MonoJumpInfoType type)
1081 mono_print_ji (const MonoJumpInfo *ji)
1088 * mono_patch_info_dup_mp:
1090 * Make a copy of PATCH_INFO, allocating memory from the mempool MP.
1093 mono_patch_info_dup_mp (MonoMemPool *mp, MonoJumpInfo *patch_info)
1095 MonoJumpInfo *res = (MonoJumpInfo *)mono_mempool_alloc (mp, sizeof (MonoJumpInfo));
1096 memcpy (res, patch_info, sizeof (MonoJumpInfo));
1098 switch (patch_info->type) {
1099 case MONO_PATCH_INFO_RVA:
1100 case MONO_PATCH_INFO_LDSTR:
1101 case MONO_PATCH_INFO_TYPE_FROM_HANDLE:
1102 case MONO_PATCH_INFO_LDTOKEN:
1103 case MONO_PATCH_INFO_DECLSEC:
1104 res->data.token = (MonoJumpInfoToken *)mono_mempool_alloc (mp, sizeof (MonoJumpInfoToken));
1105 memcpy (res->data.token, patch_info->data.token, sizeof (MonoJumpInfoToken));
1107 case MONO_PATCH_INFO_SWITCH:
1108 res->data.table = (MonoJumpInfoBBTable *)mono_mempool_alloc (mp, sizeof (MonoJumpInfoBBTable));
1109 memcpy (res->data.table, patch_info->data.table, sizeof (MonoJumpInfoBBTable));
1110 res->data.table->table = (MonoBasicBlock **)mono_mempool_alloc (mp, sizeof (MonoBasicBlock*) * patch_info->data.table->table_size);
1111 memcpy (res->data.table->table, patch_info->data.table->table, sizeof (MonoBasicBlock*) * patch_info->data.table->table_size);
1113 case MONO_PATCH_INFO_RGCTX_FETCH:
1114 case MONO_PATCH_INFO_RGCTX_SLOT_INDEX:
1115 res->data.rgctx_entry = (MonoJumpInfoRgctxEntry *)mono_mempool_alloc (mp, sizeof (MonoJumpInfoRgctxEntry));
1116 memcpy (res->data.rgctx_entry, patch_info->data.rgctx_entry, sizeof (MonoJumpInfoRgctxEntry));
1117 res->data.rgctx_entry->data = mono_patch_info_dup_mp (mp, res->data.rgctx_entry->data);
1119 case MONO_PATCH_INFO_DELEGATE_TRAMPOLINE:
1120 res->data.del_tramp = (MonoDelegateClassMethodPair *)mono_mempool_alloc0 (mp, sizeof (MonoDelegateClassMethodPair));
1121 memcpy (res->data.del_tramp, patch_info->data.del_tramp, sizeof (MonoDelegateClassMethodPair));
1123 case MONO_PATCH_INFO_GSHAREDVT_CALL:
1124 res->data.gsharedvt = (MonoJumpInfoGSharedVtCall *)mono_mempool_alloc (mp, sizeof (MonoJumpInfoGSharedVtCall));
1125 memcpy (res->data.gsharedvt, patch_info->data.gsharedvt, sizeof (MonoJumpInfoGSharedVtCall));
1127 case MONO_PATCH_INFO_GSHAREDVT_METHOD: {
1128 MonoGSharedVtMethodInfo *info;
1129 MonoGSharedVtMethodInfo *oinfo;
1132 oinfo = patch_info->data.gsharedvt_method;
1133 info = (MonoGSharedVtMethodInfo *)mono_mempool_alloc (mp, sizeof (MonoGSharedVtMethodInfo));
1134 res->data.gsharedvt_method = info;
1135 memcpy (info, oinfo, sizeof (MonoGSharedVtMethodInfo));
1136 info->entries = (MonoRuntimeGenericContextInfoTemplate *)mono_mempool_alloc (mp, sizeof (MonoRuntimeGenericContextInfoTemplate) * info->count_entries);
1137 for (i = 0; i < oinfo->num_entries; ++i) {
1138 MonoRuntimeGenericContextInfoTemplate *otemplate = &oinfo->entries [i];
1139 MonoRuntimeGenericContextInfoTemplate *template_ = &info->entries [i];
1141 memcpy (template_, otemplate, sizeof (MonoRuntimeGenericContextInfoTemplate));
1143 //info->locals_types = mono_mempool_alloc0 (mp, info->nlocals * sizeof (MonoType*));
1144 //memcpy (info->locals_types, oinfo->locals_types, info->nlocals * sizeof (MonoType*));
1147 case MONO_PATCH_INFO_VIRT_METHOD: {
1148 MonoJumpInfoVirtMethod *info;
1149 MonoJumpInfoVirtMethod *oinfo;
1151 oinfo = patch_info->data.virt_method;
1152 info = (MonoJumpInfoVirtMethod *)mono_mempool_alloc0 (mp, sizeof (MonoJumpInfoVirtMethod));
1153 res->data.virt_method = info;
1154 memcpy (info, oinfo, sizeof (MonoJumpInfoVirtMethod));
1165 mono_patch_info_hash (gconstpointer data)
1167 const MonoJumpInfo *ji = (MonoJumpInfo*)data;
1170 case MONO_PATCH_INFO_RVA:
1171 case MONO_PATCH_INFO_LDSTR:
1172 case MONO_PATCH_INFO_LDTOKEN:
1173 case MONO_PATCH_INFO_DECLSEC:
1174 return (ji->type << 8) | ji->data.token->token;
1175 case MONO_PATCH_INFO_TYPE_FROM_HANDLE:
1176 return (ji->type << 8) | ji->data.token->token | (ji->data.token->has_context ? (gsize)ji->data.token->context.class_inst : 0);
1177 case MONO_PATCH_INFO_INTERNAL_METHOD:
1178 return (ji->type << 8) | g_str_hash (ji->data.name);
1179 case MONO_PATCH_INFO_VTABLE:
1180 case MONO_PATCH_INFO_CLASS:
1181 case MONO_PATCH_INFO_IID:
1182 case MONO_PATCH_INFO_ADJUSTED_IID:
1183 case MONO_PATCH_INFO_METHODCONST:
1184 case MONO_PATCH_INFO_METHOD:
1185 case MONO_PATCH_INFO_METHOD_JUMP:
1186 case MONO_PATCH_INFO_IMAGE:
1187 case MONO_PATCH_INFO_ICALL_ADDR:
1188 case MONO_PATCH_INFO_ICALL_ADDR_CALL:
1189 case MONO_PATCH_INFO_FIELD:
1190 case MONO_PATCH_INFO_SFLDA:
1191 case MONO_PATCH_INFO_SEQ_POINT_INFO:
1192 case MONO_PATCH_INFO_METHOD_RGCTX:
1193 case MONO_PATCH_INFO_SIGNATURE:
1194 case MONO_PATCH_INFO_METHOD_CODE_SLOT:
1195 case MONO_PATCH_INFO_AOT_JIT_INFO:
1196 case MONO_PATCH_INFO_GET_TLS_TRAMP:
1197 case MONO_PATCH_INFO_SET_TLS_TRAMP:
1198 return (ji->type << 8) | (gssize)ji->data.target;
1199 case MONO_PATCH_INFO_GSHAREDVT_CALL:
1200 return (ji->type << 8) | (gssize)ji->data.gsharedvt->method;
1201 case MONO_PATCH_INFO_RGCTX_FETCH:
1202 case MONO_PATCH_INFO_RGCTX_SLOT_INDEX: {
1203 MonoJumpInfoRgctxEntry *e = ji->data.rgctx_entry;
1205 return (ji->type << 8) | (gssize)e->method | (e->in_mrgctx) | e->info_type | mono_patch_info_hash (e->data);
1207 case MONO_PATCH_INFO_INTERRUPTION_REQUEST_FLAG:
1208 case MONO_PATCH_INFO_MSCORLIB_GOT_ADDR:
1209 case MONO_PATCH_INFO_GC_CARD_TABLE_ADDR:
1210 case MONO_PATCH_INFO_GC_NURSERY_START:
1211 case MONO_PATCH_INFO_GC_NURSERY_BITS:
1212 case MONO_PATCH_INFO_GOT_OFFSET:
1213 case MONO_PATCH_INFO_GC_SAFE_POINT_FLAG:
1214 case MONO_PATCH_INFO_AOT_MODULE:
1215 case MONO_PATCH_INFO_JIT_THREAD_ATTACH:
1216 case MONO_PATCH_INFO_PROFILER_ALLOCATION_COUNT:
1217 return (ji->type << 8);
1218 case MONO_PATCH_INFO_CASTCLASS_CACHE:
1219 return (ji->type << 8) | (ji->data.index);
1220 case MONO_PATCH_INFO_SWITCH:
1221 return (ji->type << 8) | ji->data.table->table_size;
1222 case MONO_PATCH_INFO_GSHAREDVT_METHOD:
1223 return (ji->type << 8) | (gssize)ji->data.gsharedvt_method->method;
1224 case MONO_PATCH_INFO_OBJC_SELECTOR_REF:
1225 /* Hash on the selector name */
1226 return g_str_hash (ji->data.target);
1227 case MONO_PATCH_INFO_DELEGATE_TRAMPOLINE:
1228 return (ji->type << 8) | (gsize)ji->data.del_tramp->klass | (gsize)ji->data.del_tramp->method | (gsize)ji->data.del_tramp->is_virtual;
1229 case MONO_PATCH_INFO_LDSTR_LIT:
1230 return g_str_hash (ji->data.target);
1231 case MONO_PATCH_INFO_VIRT_METHOD: {
1232 MonoJumpInfoVirtMethod *info = ji->data.virt_method;
1234 return (ji->type << 8) | (gssize)info->klass | (gssize)info->method;
1236 case MONO_PATCH_INFO_JIT_ICALL_ADDR:
1237 case MONO_PATCH_INFO_JIT_ICALL_ADDR_NOCALL:
1238 return (ji->type << 8) | g_str_hash (ji->data.target);
1239 case MONO_PATCH_INFO_GSHAREDVT_IN_WRAPPER:
1240 return (ji->type << 8) | mono_signature_hash (ji->data.sig);
1242 printf ("info type: %d\n", ji->type);
1243 mono_print_ji (ji); printf ("\n");
1244 g_assert_not_reached ();
1250 * mono_patch_info_equal:
1252 * This might fail to recognize equivalent patches, i.e. floats, so its only
1253 * usable in those cases where this is not a problem, i.e. sharing GOT slots
1257 mono_patch_info_equal (gconstpointer ka, gconstpointer kb)
1259 const MonoJumpInfo *ji1 = (MonoJumpInfo*)ka;
1260 const MonoJumpInfo *ji2 = (MonoJumpInfo*)kb;
1262 if (ji1->type != ji2->type)
1265 switch (ji1->type) {
1266 case MONO_PATCH_INFO_RVA:
1267 case MONO_PATCH_INFO_LDSTR:
1268 case MONO_PATCH_INFO_TYPE_FROM_HANDLE:
1269 case MONO_PATCH_INFO_LDTOKEN:
1270 case MONO_PATCH_INFO_DECLSEC:
1271 if ((ji1->data.token->image != ji2->data.token->image) ||
1272 (ji1->data.token->token != ji2->data.token->token) ||
1273 (ji1->data.token->has_context != ji2->data.token->has_context) ||
1274 (ji1->data.token->context.class_inst != ji2->data.token->context.class_inst) ||
1275 (ji1->data.token->context.method_inst != ji2->data.token->context.method_inst))
1278 case MONO_PATCH_INFO_INTERNAL_METHOD:
1279 return g_str_equal (ji1->data.name, ji2->data.name);
1280 case MONO_PATCH_INFO_RGCTX_FETCH:
1281 case MONO_PATCH_INFO_RGCTX_SLOT_INDEX: {
1282 MonoJumpInfoRgctxEntry *e1 = ji1->data.rgctx_entry;
1283 MonoJumpInfoRgctxEntry *e2 = ji2->data.rgctx_entry;
1285 return e1->method == e2->method && e1->in_mrgctx == e2->in_mrgctx && e1->info_type == e2->info_type && mono_patch_info_equal (e1->data, e2->data);
1287 case MONO_PATCH_INFO_GSHAREDVT_CALL: {
1288 MonoJumpInfoGSharedVtCall *c1 = ji1->data.gsharedvt;
1289 MonoJumpInfoGSharedVtCall *c2 = ji2->data.gsharedvt;
1291 return c1->sig == c2->sig && c1->method == c2->method;
1293 case MONO_PATCH_INFO_GSHAREDVT_METHOD:
1294 return ji1->data.gsharedvt_method->method == ji2->data.gsharedvt_method->method;
1295 case MONO_PATCH_INFO_DELEGATE_TRAMPOLINE:
1296 return ji1->data.del_tramp->klass == ji2->data.del_tramp->klass && ji1->data.del_tramp->method == ji2->data.del_tramp->method && ji1->data.del_tramp->is_virtual == ji2->data.del_tramp->is_virtual;
1297 case MONO_PATCH_INFO_CASTCLASS_CACHE:
1298 return ji1->data.index == ji2->data.index;
1299 case MONO_PATCH_INFO_VIRT_METHOD:
1300 return ji1->data.virt_method->klass == ji2->data.virt_method->klass && ji1->data.virt_method->method == ji2->data.virt_method->method;
1301 case MONO_PATCH_INFO_JIT_ICALL_ADDR:
1302 case MONO_PATCH_INFO_JIT_ICALL_ADDR_NOCALL:
1303 if (ji1->data.target == ji2->data.target)
1305 return strcmp (ji1->data.target, ji2->data.target) == 0 ? 1 : 0;
1306 case MONO_PATCH_INFO_GSHAREDVT_IN_WRAPPER:
1307 return mono_metadata_signature_equal (ji1->data.sig, ji2->data.sig) ? 1 : 0;
1309 if (ji1->data.target != ji2->data.target)
1318 mono_resolve_patch_target (MonoMethod *method, MonoDomain *domain, guint8 *code, MonoJumpInfo *patch_info, gboolean run_cctors, MonoError *error)
1320 unsigned char *ip = patch_info->ip.i + code;
1321 gconstpointer target = NULL;
1325 switch (patch_info->type) {
1326 case MONO_PATCH_INFO_BB:
1328 * FIXME: This could be hit for methods without a prolog. Should use -1
1329 * but too much code depends on a 0 initial value.
1331 //g_assert (patch_info->data.bb->native_offset);
1332 target = patch_info->data.bb->native_offset + code;
1334 case MONO_PATCH_INFO_ABS:
1335 target = patch_info->data.target;
1337 case MONO_PATCH_INFO_LABEL:
1338 target = patch_info->data.inst->inst_c0 + code;
1340 case MONO_PATCH_INFO_IP:
1343 case MONO_PATCH_INFO_METHOD_REL:
1344 target = code + patch_info->data.offset;
1346 case MONO_PATCH_INFO_INTERNAL_METHOD: {
1347 MonoJitICallInfo *mi = mono_find_jit_icall_by_name (patch_info->data.name);
1349 g_warning ("unknown MONO_PATCH_INFO_INTERNAL_METHOD %s", patch_info->data.name);
1350 g_assert_not_reached ();
1352 target = mono_icall_get_wrapper (mi);
1355 case MONO_PATCH_INFO_JIT_ICALL_ADDR:
1356 case MONO_PATCH_INFO_JIT_ICALL_ADDR_NOCALL: {
1357 MonoJitICallInfo *mi = mono_find_jit_icall_by_name (patch_info->data.name);
1359 g_warning ("unknown MONO_PATCH_INFO_JIT_ICALL_ADDR %s", patch_info->data.name);
1360 g_assert_not_reached ();
1365 case MONO_PATCH_INFO_METHOD_JUMP:
1366 target = mono_create_jump_trampoline (domain, patch_info->data.method, FALSE, error);
1367 if (!mono_error_ok (error))
1370 case MONO_PATCH_INFO_METHOD:
1371 if (patch_info->data.method == method) {
1374 /* get the trampoline to the method from the domain */
1375 target = mono_create_jit_trampoline (domain, patch_info->data.method, error);
1376 if (!mono_error_ok (error))
1380 case MONO_PATCH_INFO_METHOD_CODE_SLOT: {
1383 mono_domain_lock (domain);
1384 if (!domain_jit_info (domain)->method_code_hash)
1385 domain_jit_info (domain)->method_code_hash = g_hash_table_new (NULL, NULL);
1386 code_slot = g_hash_table_lookup (domain_jit_info (domain)->method_code_hash, patch_info->data.method);
1388 code_slot = mono_domain_alloc0 (domain, sizeof (gpointer));
1389 g_hash_table_insert (domain_jit_info (domain)->method_code_hash, patch_info->data.method, code_slot);
1391 mono_domain_unlock (domain);
1395 case MONO_PATCH_INFO_GC_SAFE_POINT_FLAG:
1396 g_assert (mono_threads_is_coop_enabled ());
1397 target = (gpointer)&mono_polling_required;
1399 case MONO_PATCH_INFO_SWITCH: {
1400 gpointer *jump_table;
1402 if (method && method->dynamic) {
1403 jump_table = (void **)mono_code_manager_reserve (mono_dynamic_code_hash_lookup (domain, method)->code_mp, sizeof (gpointer) * patch_info->data.table->table_size);
1405 if (mono_aot_only) {
1406 jump_table = (void **)mono_domain_alloc (domain, sizeof (gpointer) * patch_info->data.table->table_size);
1408 jump_table = (void **)mono_domain_code_reserve (domain, sizeof (gpointer) * patch_info->data.table->table_size);
1412 for (i = 0; i < patch_info->data.table->table_size; i++) {
1413 jump_table [i] = code + GPOINTER_TO_INT (patch_info->data.table->table [i]);
1416 target = jump_table;
1419 case MONO_PATCH_INFO_METHODCONST:
1420 case MONO_PATCH_INFO_CLASS:
1421 case MONO_PATCH_INFO_IMAGE:
1422 case MONO_PATCH_INFO_FIELD:
1423 case MONO_PATCH_INFO_SIGNATURE:
1424 case MONO_PATCH_INFO_AOT_MODULE:
1425 target = patch_info->data.target;
1427 case MONO_PATCH_INFO_IID:
1428 mono_class_init (patch_info->data.klass);
1429 target = GUINT_TO_POINTER (patch_info->data.klass->interface_id);
1431 case MONO_PATCH_INFO_ADJUSTED_IID:
1432 mono_class_init (patch_info->data.klass);
1433 target = GUINT_TO_POINTER ((guint32)(-((patch_info->data.klass->interface_id + 1) * SIZEOF_VOID_P)));
1435 case MONO_PATCH_INFO_VTABLE:
1436 target = mono_class_vtable (domain, patch_info->data.klass);
1439 case MONO_PATCH_INFO_DELEGATE_TRAMPOLINE: {
1440 MonoDelegateClassMethodPair *del_tramp = patch_info->data.del_tramp;
1442 if (del_tramp->is_virtual)
1443 target = mono_create_delegate_virtual_trampoline (domain, del_tramp->klass, del_tramp->method);
1445 target = mono_create_delegate_trampoline_info (domain, del_tramp->klass, del_tramp->method);
1448 case MONO_PATCH_INFO_SFLDA: {
1449 MonoVTable *vtable = mono_class_vtable (domain, patch_info->data.field->parent);
1451 if (mono_class_field_is_special_static (patch_info->data.field)) {
1452 gpointer addr = NULL;
1454 mono_domain_lock (domain);
1455 if (domain->special_static_fields)
1456 addr = g_hash_table_lookup (domain->special_static_fields, patch_info->data.field);
1457 mono_domain_unlock (domain);
1463 if (!vtable->initialized && !mono_class_is_before_field_init (vtable->klass) && (method && mono_class_needs_cctor_run (vtable->klass, method)))
1464 /* Done by the generated code */
1468 if (!mono_runtime_class_init_full (vtable, error)) {
1473 target = (char*)mono_vtable_get_static_field_data (vtable) + patch_info->data.field->offset;
1476 case MONO_PATCH_INFO_RVA: {
1477 guint32 field_index = mono_metadata_token_index (patch_info->data.token->token);
1480 mono_metadata_field_info (patch_info->data.token->image, field_index - 1, NULL, &rva, NULL);
1481 target = mono_image_rva_map (patch_info->data.token->image, rva);
1484 case MONO_PATCH_INFO_R4:
1485 case MONO_PATCH_INFO_R8:
1486 target = patch_info->data.target;
1488 case MONO_PATCH_INFO_EXC_NAME:
1489 target = patch_info->data.name;
1491 case MONO_PATCH_INFO_LDSTR:
1493 mono_ldstr_checked (domain, patch_info->data.token->image,
1494 mono_metadata_token_index (patch_info->data.token->token), error);
1496 case MONO_PATCH_INFO_TYPE_FROM_HANDLE: {
1498 MonoClass *handle_class;
1500 handle = mono_ldtoken_checked (patch_info->data.token->image,
1501 patch_info->data.token->token, &handle_class, patch_info->data.token->has_context ? &patch_info->data.token->context : NULL, error);
1502 if (!mono_error_ok (error))
1504 mono_class_init (handle_class);
1505 mono_class_init (mono_class_from_mono_type ((MonoType *)handle));
1507 target = mono_type_get_object_checked (domain, (MonoType *)handle, error);
1508 if (!mono_error_ok (error))
1512 case MONO_PATCH_INFO_LDTOKEN: {
1514 MonoClass *handle_class;
1516 handle = mono_ldtoken_checked (patch_info->data.token->image,
1517 patch_info->data.token->token, &handle_class, patch_info->data.token->has_context ? &patch_info->data.token->context : NULL, error);
1518 if (!mono_error_ok (error))
1519 g_error ("Could not patch ldtoken due to %s", mono_error_get_message (error));
1520 mono_class_init (handle_class);
1525 case MONO_PATCH_INFO_DECLSEC:
1526 target = (mono_metadata_blob_heap (patch_info->data.token->image, patch_info->data.token->token) + 2);
1528 case MONO_PATCH_INFO_ICALL_ADDR:
1529 case MONO_PATCH_INFO_ICALL_ADDR_CALL:
1530 /* run_cctors == 0 -> AOT */
1531 if (patch_info->data.method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
1532 const char *exc_class;
1533 const char *exc_arg;
1536 target = mono_lookup_pinvoke_call (patch_info->data.method, &exc_class, &exc_arg);
1538 if (mono_aot_only) {
1539 mono_error_set_exception_instance (error, mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg));
1542 g_error ("Unable to resolve pinvoke method '%s' Re-run with MONO_LOG_LEVEL=debug for more information.\n", mono_method_full_name (patch_info->data.method, TRUE));
1548 target = mono_lookup_internal_call (patch_info->data.method);
1550 if (!target && run_cctors)
1551 g_error ("Unregistered icall '%s'\n", mono_method_full_name (patch_info->data.method, TRUE));
1554 case MONO_PATCH_INFO_INTERRUPTION_REQUEST_FLAG:
1555 target = mono_thread_interruption_request_flag ();
1557 case MONO_PATCH_INFO_METHOD_RGCTX: {
1558 MonoVTable *vtable = mono_class_vtable (domain, patch_info->data.method->klass);
1561 target = mono_method_lookup_rgctx (vtable, mini_method_get_context (patch_info->data.method)->method_inst);
1564 case MONO_PATCH_INFO_RGCTX_SLOT_INDEX: {
1565 int slot = mini_get_rgctx_entry_slot (patch_info->data.rgctx_entry);
1567 target = GINT_TO_POINTER (MONO_RGCTX_SLOT_INDEX (slot));
1570 case MONO_PATCH_INFO_BB_OVF:
1571 case MONO_PATCH_INFO_EXC_OVF:
1572 case MONO_PATCH_INFO_GOT_OFFSET:
1573 case MONO_PATCH_INFO_NONE:
1575 case MONO_PATCH_INFO_RGCTX_FETCH: {
1576 int slot = mini_get_rgctx_entry_slot (patch_info->data.rgctx_entry);
1578 target = mono_create_rgctx_lazy_fetch_trampoline (slot);
1581 #ifdef MONO_ARCH_SOFT_DEBUG_SUPPORTED
1582 case MONO_PATCH_INFO_SEQ_POINT_INFO:
1584 /* AOT, not needed */
1587 target = mono_arch_get_seq_point_info (domain, code);
1590 case MONO_PATCH_INFO_GC_CARD_TABLE_ADDR: {
1591 int card_table_shift_bits;
1592 gpointer card_table_mask;
1594 target = mono_gc_get_card_table (&card_table_shift_bits, &card_table_mask);
1597 case MONO_PATCH_INFO_GC_NURSERY_START: {
1601 target = mono_gc_get_nursery (&shift_bits, &size);
1604 case MONO_PATCH_INFO_GC_NURSERY_BITS: {
1608 mono_gc_get_nursery (&shift_bits, &size);
1610 target = (gpointer)(mgreg_t)shift_bits;
1613 case MONO_PATCH_INFO_CASTCLASS_CACHE: {
1614 target = mono_domain_alloc0 (domain, sizeof (gpointer));
1617 case MONO_PATCH_INFO_OBJC_SELECTOR_REF: {
1621 case MONO_PATCH_INFO_LDSTR_LIT: {
1625 len = strlen ((const char *)patch_info->data.target);
1626 s = (char *)mono_domain_alloc0 (domain, len + 1);
1627 memcpy (s, patch_info->data.target, len);
1632 case MONO_PATCH_INFO_GSHAREDVT_IN_WRAPPER:
1633 target = mini_get_gsharedvt_wrapper (TRUE, NULL, patch_info->data.sig, NULL, -1, FALSE);
1635 case MONO_PATCH_INFO_GET_TLS_TRAMP:
1636 target = mono_tls_get_tls_getter (patch_info->data.index, FALSE);
1638 case MONO_PATCH_INFO_SET_TLS_TRAMP:
1639 target = mono_tls_get_tls_setter (patch_info->data.index, FALSE);
1641 case MONO_PATCH_INFO_JIT_THREAD_ATTACH: {
1642 MonoJitICallInfo *mi = mono_find_jit_icall_by_name ("mono_jit_thread_attach");
1647 case MONO_PATCH_INFO_PROFILER_ALLOCATION_COUNT: {
1648 target = (gpointer) &mono_profiler_state.gc_allocation_count;
1652 g_assert_not_reached ();
1655 return (gpointer)target;
1659 mini_init_gsctx (MonoDomain *domain, MonoMemPool *mp, MonoGenericContext *context, MonoGenericSharingContext *gsctx)
1661 MonoGenericInst *inst;
1664 memset (gsctx, 0, sizeof (MonoGenericSharingContext));
1666 if (context && context->class_inst) {
1667 inst = context->class_inst;
1668 for (i = 0; i < inst->type_argc; ++i) {
1669 MonoType *type = inst->type_argv [i];
1671 if (mini_is_gsharedvt_gparam (type))
1672 gsctx->is_gsharedvt = TRUE;
1675 if (context && context->method_inst) {
1676 inst = context->method_inst;
1678 for (i = 0; i < inst->type_argc; ++i) {
1679 MonoType *type = inst->type_argv [i];
1681 if (mini_is_gsharedvt_gparam (type))
1682 gsctx->is_gsharedvt = TRUE;
1688 * LOCKING: Acquires the jit code hash lock.
1691 mini_lookup_method (MonoDomain *domain, MonoMethod *method, MonoMethod *shared)
1694 static gboolean inited = FALSE;
1695 static int lookups = 0;
1696 static int failed_lookups = 0;
1698 mono_domain_jit_code_hash_lock (domain);
1699 ji = (MonoJitInfo *)mono_internal_hash_table_lookup (&domain->jit_code_hash, method);
1700 if (!ji && shared) {
1701 /* Try generic sharing */
1702 ji = (MonoJitInfo *)mono_internal_hash_table_lookup (&domain->jit_code_hash, shared);
1703 if (ji && !ji->has_generic_jit_info)
1706 mono_counters_register ("Shared generic lookups", MONO_COUNTER_INT|MONO_COUNTER_GENERICS, &lookups);
1707 mono_counters_register ("Failed shared generic lookups", MONO_COUNTER_INT|MONO_COUNTER_GENERICS, &failed_lookups);
1715 mono_domain_jit_code_hash_unlock (domain);
1721 lookup_method (MonoDomain *domain, MonoMethod *method)
1726 ji = mini_lookup_method (domain, method, NULL);
1729 if (!mono_method_is_generic_sharable (method, FALSE))
1731 shared = mini_get_shared_method (method);
1732 ji = mini_lookup_method (domain, method, shared);
1739 mini_get_class (MonoMethod *method, guint32 token, MonoGenericContext *context)
1744 if (method->wrapper_type != MONO_WRAPPER_NONE) {
1745 klass = (MonoClass *)mono_method_get_wrapper_data (method, token);
1747 klass = mono_class_inflate_generic_class_checked (klass, context, &error);
1748 mono_error_cleanup (&error); /* FIXME don't swallow the error */
1751 klass = mono_class_get_and_inflate_typespec_checked (method->klass->image, token, context, &error);
1752 mono_error_cleanup (&error); /* FIXME don't swallow the error */
1755 mono_class_init (klass);
1760 static FILE* perf_map_file;
1763 mono_enable_jit_map (void)
1765 if (!perf_map_file) {
1767 g_snprintf (name, sizeof (name), "/tmp/perf-%d.map", getpid ());
1769 perf_map_file = fopen (name, "w");
1774 mono_emit_jit_tramp (void *start, int size, const char *desc)
1777 fprintf (perf_map_file, "%llx %x %s\n", (long long unsigned int)(gsize)start, size, desc);
1781 mono_emit_jit_map (MonoJitInfo *jinfo)
1783 if (perf_map_file) {
1784 char *name = mono_method_full_name (jinfo_get_method (jinfo), TRUE);
1785 mono_emit_jit_tramp (jinfo->code_start, jinfo->code_size, name);
1791 mono_jit_map_is_enabled (void)
1793 return perf_map_file != NULL;
1799 no_gsharedvt_in_wrapper (void)
1801 g_assert_not_reached ();
1807 When a JIT request is made, we check if there's an outstanding one for that method and, if it exits, put the thread to sleep.
1808 If the current thread is already JITing another method, don't wait as it might cause a deadlock.
1809 Dependency management in this case is too complex to justify implementing it.
1811 If there are no outstanding requests, the current thread is doing nothing and there are already mono_cpu_count threads JITing, go to sleep.
1814 Get rid of cctor invocations from within the JIT, it increases JIT duration and complicates things A LOT.
1815 Can we get rid of ref_count and use `done && threads_waiting == 0` as the equivalent of `ref_count == 0`?
1816 Reduce amount of dynamically allocated - possible once the JIT is no longer reentrant
1817 Maybe pool JitCompilationEntry, specially those with an inited cond var;
1822 int compilation_count; /* Number of threads compiling this method - This happens due to the JIT being reentrant */
1823 int ref_count; /* Number of threads using this JitCompilationEntry, roughtly 1 + threads_waiting */
1824 int threads_waiting; /* Number of threads waiting on this job */
1825 gboolean has_cond; /* True if @cond was initialized */
1826 gboolean done; /* True if the method finished JIT'ing */
1827 MonoCoopCond cond; /* Cond sleeping threads wait one */
1828 } JitCompilationEntry;
1831 GPtrArray *in_flight_methods; //JitCompilationEntry*
1833 } JitCompilationData;
1835 static JitCompilationData compilation_data;
1836 static int jit_methods_waited, jit_methods_multiple, jit_methods_overload, jit_spurious_wakeups;
1839 mini_jit_init_job_control (void)
1841 mono_coop_mutex_init (&compilation_data.lock);
1842 compilation_data.in_flight_methods = g_ptr_array_new ();
1846 lock_compilation_data (void)
1848 mono_coop_mutex_lock (&compilation_data.lock);
1852 unlock_compilation_data (void)
1854 mono_coop_mutex_unlock (&compilation_data.lock);
1857 static JitCompilationEntry*
1858 find_method (MonoMethod *method, MonoDomain *domain)
1861 for (i = 0; i < compilation_data.in_flight_methods->len; ++i){
1862 JitCompilationEntry *e = compilation_data.in_flight_methods->pdata [i];
1863 if (e->method == method && e->domain == domain)
1871 add_current_thread (MonoJitTlsData *jit_tls)
1873 ++jit_tls->active_jit_methods;
1877 unref_jit_entry (JitCompilationEntry *entry)
1880 if (entry->ref_count)
1882 if (entry->has_cond)
1883 mono_coop_cond_destroy (&entry->cond);
1888 * Returns true if this method waited successfully for another thread to JIT it
1891 wait_or_register_method_to_compile (MonoMethod *method, MonoDomain *domain)
1893 MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_tls_get_jit_tls ();
1894 JitCompilationEntry *entry;
1896 static gboolean inited;
1898 mono_counters_register ("JIT compile waited others", MONO_COUNTER_INT|MONO_COUNTER_JIT, &jit_methods_waited);
1899 mono_counters_register ("JIT compile 1+ jobs", MONO_COUNTER_INT|MONO_COUNTER_JIT, &jit_methods_multiple);
1900 mono_counters_register ("JIT compile overload wait", MONO_COUNTER_INT|MONO_COUNTER_JIT, &jit_methods_overload);
1901 mono_counters_register ("JIT compile spurious wakeups", MONO_COUNTER_INT|MONO_COUNTER_JIT, &jit_spurious_wakeups);
1905 lock_compilation_data ();
1907 if (!(entry = find_method (method, domain))) {
1908 entry = g_new0 (JitCompilationEntry, 1);
1909 entry->method = method;
1910 entry->domain = domain;
1911 entry->compilation_count = entry->ref_count = 1;
1912 g_ptr_array_add (compilation_data.in_flight_methods, entry);
1913 g_assert (find_method (method, domain) == entry);
1914 add_current_thread (jit_tls);
1916 unlock_compilation_data ();
1918 } else if (jit_tls->active_jit_methods > 0) {
1919 //We can't suspend the current thread if it's already JITing a method.
1920 //Dependency management is too compilated and we want to get rid of this anyways.
1921 ++entry->compilation_count;
1922 ++jit_methods_multiple;
1923 ++jit_tls->active_jit_methods;
1925 unlock_compilation_data ();
1928 ++jit_methods_waited;
1931 if (!entry->has_cond) {
1932 mono_coop_cond_init (&entry->cond);
1933 entry->has_cond = TRUE;
1937 ++entry->threads_waiting;
1939 g_assert (entry->has_cond);
1940 mono_coop_cond_wait (&entry->cond, &compilation_data.lock);
1941 --entry->threads_waiting;
1944 unref_jit_entry (entry);
1945 unlock_compilation_data ();
1948 ++jit_spurious_wakeups;
1955 unregister_method_for_compile (MonoMethod *method, MonoDomain *target_domain)
1957 MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_tls_get_jit_tls ();
1959 lock_compilation_data ();
1961 g_assert (jit_tls->active_jit_methods > 0);
1962 --jit_tls->active_jit_methods;
1964 JitCompilationEntry *entry = find_method (method, target_domain);
1965 g_assert (entry); // It would be weird to fail
1968 if (entry->threads_waiting) {
1969 g_assert (entry->has_cond);
1970 mono_coop_cond_broadcast (&entry->cond);
1973 if (--entry->compilation_count == 0) {
1974 g_ptr_array_remove (compilation_data.in_flight_methods, entry);
1975 unref_jit_entry (entry);
1978 unlock_compilation_data ();
1983 mono_jit_compile_method_with_opt (MonoMethod *method, guint32 opt, gboolean jit_only, MonoError *error)
1985 MonoDomain *target_domain, *domain = mono_domain_get ();
1987 gpointer code = NULL, p;
1989 MonoJitICallInfo *callinfo = NULL;
1990 WrapperInfo *winfo = NULL;
1994 #ifdef ENABLE_INTERPRETER
1995 if (mono_use_interpreter && !jit_only) {
1996 code = mono_interp_create_method_pointer (method, error);
2003 /* Should be handled by the caller */
2004 g_assert (!(method->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED));
2007 * ICALL wrappers are handled specially, since there is only one copy of them
2008 * shared by all appdomains.
2010 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE)
2011 winfo = mono_marshal_get_wrapper_info (method);
2012 if (winfo && winfo->subtype == WRAPPER_SUBTYPE_ICALL_WRAPPER) {
2013 callinfo = mono_find_jit_icall_by_addr (winfo->d.icall.func);
2014 g_assert (callinfo);
2016 /* Must be domain neutral since there is only one copy */
2017 opt |= MONO_OPT_SHARED;
2019 /* MONO_OPT_SHARED is no longer supported, we only use it for icall wrappers */
2020 opt &= ~MONO_OPT_SHARED;
2023 if (opt & MONO_OPT_SHARED)
2024 target_domain = mono_get_root_domain ();
2026 target_domain = domain;
2028 if (method->wrapper_type == MONO_WRAPPER_UNKNOWN) {
2029 WrapperInfo *info = mono_marshal_get_wrapper_info (method);
2032 if (info->subtype == WRAPPER_SUBTYPE_SYNCHRONIZED_INNER) {
2033 MonoGenericContext *ctx = NULL;
2034 if (method->is_inflated)
2035 ctx = mono_method_get_context (method);
2036 method = info->d.synchronized_inner.method;
2038 method = mono_class_inflate_generic_method_checked (method, ctx, error);
2039 g_assert (mono_error_ok (error)); /* FIXME don't swallow the error */
2045 info = lookup_method (target_domain, method);
2047 /* We can't use a domain specific method in another domain */
2048 if (! ((domain != target_domain) && !info->domain_neutral)) {
2051 mono_jit_stats.methods_lookups++;
2052 vtable = mono_class_vtable_full (domain, method->klass, error);
2056 if (!mono_runtime_class_init_full (vtable, error))
2058 return mono_create_ftnptr (target_domain, info->code_start);
2062 #ifdef MONO_USE_AOT_COMPILER
2063 if (opt & MONO_OPT_AOT) {
2064 MonoDomain *domain = NULL;
2066 if (mono_aot_mode == MONO_AOT_MODE_INTERP && method->wrapper_type == MONO_WRAPPER_UNKNOWN) {
2067 WrapperInfo *info = mono_marshal_get_wrapper_info (method);
2069 if (info->subtype == WRAPPER_SUBTYPE_INTERP_IN)
2070 /* AOT'd wrappers for interp must be owned by root domain */
2071 domain = mono_get_root_domain ();
2075 domain = mono_domain_get ();
2077 mono_class_init (method->klass);
2079 if ((code = mono_aot_get_method_checked (domain, method, error))) {
2082 if (mono_gc_is_critical_method (method)) {
2084 * The suspend code needs to be able to lookup these methods by ip in async context,
2085 * so preload their jit info.
2087 MonoJitInfo *ji = mono_jit_info_table_find (domain, code);
2092 * In llvm-only mode, method might be a shared method, so we can't initialize its class.
2093 * This is not a problem, since it will be initialized when the method is first
2094 * called by init_method ().
2096 if (!mono_llvm_only) {
2097 vtable = mono_class_vtable (domain, method->klass);
2099 if (!mono_runtime_class_init_full (vtable, error))
2108 if (!code && mono_llvm_only) {
2109 if (method->wrapper_type == MONO_WRAPPER_UNKNOWN) {
2110 WrapperInfo *info = mono_marshal_get_wrapper_info (method);
2112 if (info->subtype == WRAPPER_SUBTYPE_GSHAREDVT_IN_SIG) {
2114 * These wrappers are only created for signatures which are in the program, but
2115 * sometimes we load methods too eagerly and have to create them even if they
2116 * will never be called.
2118 return no_gsharedvt_in_wrapper;
2124 if (wait_or_register_method_to_compile (method, target_domain))
2126 code = mono_jit_compile_method_inner (method, target_domain, opt, error);
2127 unregister_method_for_compile (method, target_domain);
2129 if (!mono_error_ok (error))
2132 if (!code && mono_llvm_only) {
2133 printf ("AOT method not found in llvmonly mode: %s\n", mono_method_full_name (method, 1));
2134 g_assert_not_reached ();
2140 if (method->wrapper_type == MONO_WRAPPER_WRITE_BARRIER || method->wrapper_type == MONO_WRAPPER_ALLOC) {
2144 * SGEN requires the JIT info for these methods to be registered, see is_ip_in_managed_allocator ().
2146 ji = mini_jit_info_table_find (mono_domain_get (), (char *)code, &d);
2150 p = mono_create_ftnptr (target_domain, code);
2153 /*mono_register_jit_icall_wrapper takes the loader lock, so we take it on the outside. */
2154 mono_loader_lock ();
2156 if (!callinfo->wrapper) {
2157 callinfo->wrapper = p;
2158 mono_register_jit_icall_wrapper (callinfo, p);
2161 mono_loader_unlock ();
2168 mono_jit_compile_method (MonoMethod *method, MonoError *error)
2172 code = mono_jit_compile_method_with_opt (method, mono_get_optimizations_for_method (method, default_opt), FALSE, error);
2177 * mono_jit_compile_method_jit_only:
2179 * Compile METHOD using the JIT/AOT, even in interpreted mode.
2182 mono_jit_compile_method_jit_only (MonoMethod *method, MonoError *error)
2186 code = mono_jit_compile_method_with_opt (method, mono_get_optimizations_for_method (method, default_opt), TRUE, error);
2190 #ifdef MONO_ARCH_HAVE_INVALIDATE_METHOD
2192 invalidated_delegate_trampoline (char *desc)
2194 g_error ("Unmanaged code called delegate of type %s which was already garbage collected.\n"
2195 "See http://www.mono-project.com/Diagnostic:Delegate for an explanation and ways to fix this.",
2201 * mono_jit_free_method:
2203 * Free all memory allocated by the JIT for METHOD.
2206 mono_jit_free_method (MonoDomain *domain, MonoMethod *method)
2208 MonoJitDynamicMethodInfo *ji;
2209 gboolean destroy = TRUE;
2210 GHashTableIter iter;
2211 MonoJumpList *jlist;
2213 g_assert (method->dynamic);
2215 mono_domain_lock (domain);
2216 ji = mono_dynamic_code_hash_lookup (domain, method);
2217 mono_domain_unlock (domain);
2222 mono_debug_remove_method (method, domain);
2223 mono_lldb_remove_method (domain, method, ji);
2225 mono_domain_lock (domain);
2226 g_hash_table_remove (domain_jit_info (domain)->dynamic_code_hash, method);
2227 mono_domain_jit_code_hash_lock (domain);
2228 mono_internal_hash_table_remove (&domain->jit_code_hash, method);
2229 mono_domain_jit_code_hash_unlock (domain);
2230 g_hash_table_remove (domain_jit_info (domain)->jump_trampoline_hash, method);
2232 /* requires the domain lock - took above */
2233 mono_conc_hashtable_remove (domain_jit_info (domain)->runtime_invoke_hash, method);
2235 /* Remove jump targets in this method */
2236 g_hash_table_iter_init (&iter, domain_jit_info (domain)->jump_target_hash);
2237 while (g_hash_table_iter_next (&iter, NULL, (void**)&jlist)) {
2238 GSList *tmp, *remove;
2241 for (tmp = jlist->list; tmp; tmp = tmp->next) {
2242 guint8 *ip = (guint8 *)tmp->data;
2244 if (ip >= (guint8*)ji->ji->code_start && ip < (guint8*)ji->ji->code_start + ji->ji->code_size)
2245 remove = g_slist_prepend (remove, tmp);
2247 for (tmp = remove; tmp; tmp = tmp->next) {
2248 jlist->list = g_slist_delete_link ((GSList *)jlist->list, (GSList *)tmp->data);
2250 g_slist_free (remove);
2252 mono_domain_unlock (domain);
2254 #ifdef MONO_ARCH_HAVE_INVALIDATE_METHOD
2255 if (debug_options.keep_delegates && method->wrapper_type == MONO_WRAPPER_NATIVE_TO_MANAGED) {
2257 * Instead of freeing the code, change it to call an error routine
2258 * so people can fix their code.
2260 char *type = mono_type_full_name (&method->klass->byval_arg);
2261 char *type_and_method = g_strdup_printf ("%s.%s", type, method->name);
2264 mono_arch_invalidate_method (ji->ji, invalidated_delegate_trampoline, type_and_method);
2270 * This needs to be done before freeing code_mp, since the code address is the
2271 * key in the table, so if we free the code_mp first, another thread can grab the
2272 * same code address and replace our entry in the table.
2274 mono_jit_info_table_remove (domain, ji->ji);
2277 mono_code_manager_destroy (ji->code_mp);
2282 mono_jit_find_compiled_method_with_jit_info (MonoDomain *domain, MonoMethod *method, MonoJitInfo **ji)
2284 MonoDomain *target_domain;
2287 if (default_opt & MONO_OPT_SHARED)
2288 target_domain = mono_get_root_domain ();
2290 target_domain = domain;
2292 info = lookup_method (target_domain, method);
2294 /* We can't use a domain specific method in another domain */
2295 if (! ((domain != target_domain) && !info->domain_neutral)) {
2296 mono_jit_stats.methods_lookups++;
2299 return info->code_start;
2308 static guint32 bisect_opt = 0;
2309 static GHashTable *bisect_methods_hash = NULL;
2312 mono_set_bisect_methods (guint32 opt, const char *method_list_filename)
2315 char method_name [2048];
2318 bisect_methods_hash = g_hash_table_new (g_str_hash, g_str_equal);
2319 g_assert (bisect_methods_hash);
2321 file = fopen (method_list_filename, "r");
2324 while (fgets (method_name, sizeof (method_name), file)) {
2325 size_t len = strlen (method_name);
2327 g_assert (method_name [len - 1] == '\n');
2328 method_name [len - 1] = 0;
2329 g_hash_table_insert (bisect_methods_hash, g_strdup (method_name), GINT_TO_POINTER (1));
2331 g_assert (feof (file));
2334 gboolean mono_do_single_method_regression = FALSE;
2335 guint32 mono_single_method_regression_opt = 0;
2336 MonoMethod *mono_current_single_method;
2337 GSList *mono_single_method_list;
2338 GHashTable *mono_single_method_hash;
2341 mono_get_optimizations_for_method (MonoMethod *method, guint32 default_opt)
2345 if (bisect_methods_hash) {
2346 char *name = mono_method_full_name (method, TRUE);
2347 void *res = g_hash_table_lookup (bisect_methods_hash, name);
2350 return default_opt | bisect_opt;
2352 if (!mono_do_single_method_regression)
2354 if (!mono_current_single_method) {
2355 if (!mono_single_method_hash)
2356 mono_single_method_hash = g_hash_table_new (g_direct_hash, g_direct_equal);
2357 if (!g_hash_table_lookup (mono_single_method_hash, method)) {
2358 g_hash_table_insert (mono_single_method_hash, method, method);
2359 mono_single_method_list = g_slist_prepend (mono_single_method_list, method);
2363 if (method == mono_current_single_method)
2364 return mono_single_method_regression_opt;
2369 mono_jit_find_compiled_method (MonoDomain *domain, MonoMethod *method)
2371 return mono_jit_find_compiled_method_with_jit_info (domain, method, NULL);
2376 gpointer compiled_method;
2377 gpointer runtime_invoke;
2379 MonoDynCallInfo *dyn_call_info;
2380 MonoClass *ret_box_class;
2381 MonoMethodSignature *sig;
2382 gboolean gsharedvt_invoke;
2383 gpointer *wrapper_arg;
2384 } RuntimeInvokeInfo;
2386 static RuntimeInvokeInfo*
2387 create_runtime_invoke_info (MonoDomain *domain, MonoMethod *method, gpointer compiled_method, gboolean callee_gsharedvt, MonoError *error)
2390 RuntimeInvokeInfo *info;
2392 info = g_new0 (RuntimeInvokeInfo, 1);
2393 info->compiled_method = compiled_method;
2394 if (mono_llvm_only && method->string_ctor)
2395 info->sig = mono_marshal_get_string_ctor_signature (method);
2397 info->sig = mono_method_signature (method);
2399 invoke = mono_marshal_get_runtime_invoke (method, FALSE);
2400 info->vtable = mono_class_vtable_full (domain, method->klass, error);
2401 if (!mono_error_ok (error))
2403 g_assert (info->vtable);
2405 MonoMethodSignature *sig = info->sig;
2409 * We want to avoid AOTing 1000s of runtime-invoke wrappers when running
2410 * in full-aot mode, so we use a slower, but more generic wrapper if
2411 * possible, built on top of the OP_DYN_CALL opcode provided by the JIT.
2413 #ifdef MONO_ARCH_DYN_CALL_SUPPORTED
2414 if (!mono_llvm_only && (mono_aot_only || debug_options.dyn_runtime_invoke)) {
2415 gboolean supported = TRUE;
2418 if (method->string_ctor)
2419 sig = mono_marshal_get_string_ctor_signature (method);
2421 for (i = 0; i < sig->param_count; ++i) {
2422 MonoType *t = sig->params [i];
2424 if (t->byref && t->type == MONO_TYPE_GENERICINST && mono_class_is_nullable (mono_class_from_mono_type (t)))
2428 if (mono_class_is_contextbound (method->klass) || !info->compiled_method)
2432 info->dyn_call_info = mono_arch_dyn_call_prepare (sig);
2436 ret_type = sig->ret;
2437 switch (ret_type->type) {
2438 case MONO_TYPE_VOID:
2450 case MONO_TYPE_BOOLEAN:
2451 case MONO_TYPE_CHAR:
2454 info->ret_box_class = mono_class_from_mono_type (ret_type);
2457 info->ret_box_class = mono_defaults.int_class;
2459 case MONO_TYPE_STRING:
2460 case MONO_TYPE_CLASS:
2461 case MONO_TYPE_ARRAY:
2462 case MONO_TYPE_SZARRAY:
2463 case MONO_TYPE_OBJECT:
2465 case MONO_TYPE_GENERICINST:
2466 if (!MONO_TYPE_IS_REFERENCE (ret_type))
2467 info->ret_box_class = mono_class_from_mono_type (ret_type);
2469 case MONO_TYPE_VALUETYPE:
2470 info->ret_box_class = mono_class_from_mono_type (ret_type);
2473 g_assert_not_reached ();
2477 if (!info->dyn_call_info) {
2478 if (mono_llvm_only) {
2479 #ifndef MONO_ARCH_GSHAREDVT_SUPPORTED
2480 g_assert_not_reached ();
2482 info->gsharedvt_invoke = TRUE;
2483 if (!callee_gsharedvt) {
2484 /* Invoke a gsharedvt out wrapper instead */
2485 MonoMethod *wrapper = mini_get_gsharedvt_out_sig_wrapper (sig);
2486 MonoMethodSignature *wrapper_sig = mini_get_gsharedvt_out_sig_wrapper_signature (sig->hasthis, sig->ret->type != MONO_TYPE_VOID, sig->param_count);
2488 info->wrapper_arg = g_malloc0 (2 * sizeof (gpointer));
2489 info->wrapper_arg [0] = mini_add_method_wrappers_llvmonly (method, info->compiled_method, FALSE, FALSE, &(info->wrapper_arg [1]));
2491 /* Pass has_rgctx == TRUE since the wrapper has an extra arg */
2492 invoke = mono_marshal_get_runtime_invoke_for_sig (wrapper_sig);
2493 g_free (wrapper_sig);
2495 info->compiled_method = mono_jit_compile_method (wrapper, error);
2496 if (!mono_error_ok (error)) {
2501 /* Gsharedvt methods can be invoked the same way */
2502 /* The out wrapper has the same signature as the compiled gsharedvt method */
2503 MonoMethodSignature *wrapper_sig = mini_get_gsharedvt_out_sig_wrapper_signature (sig->hasthis, sig->ret->type != MONO_TYPE_VOID, sig->param_count);
2505 info->wrapper_arg = mono_method_needs_static_rgctx_invoke (method, TRUE) ? mini_method_get_rgctx (method) : NULL;
2507 invoke = mono_marshal_get_runtime_invoke_for_sig (wrapper_sig);
2508 g_free (wrapper_sig);
2511 info->runtime_invoke = mono_jit_compile_method (invoke, error);
2512 if (!mono_error_ok (error)) {
2522 mono_llvmonly_runtime_invoke (MonoMethod *method, RuntimeInvokeInfo *info, void *obj, void **params, MonoObject **exc, MonoError *error)
2524 MonoMethodSignature *sig = info->sig;
2525 MonoDomain *domain = mono_domain_get ();
2526 MonoObject *(*runtime_invoke) (MonoObject *this_obj, void **params, MonoObject **exc, void* compiled_method);
2528 gpointer retval_ptr;
2529 guint8 retval [256];
2530 gpointer *param_refs;
2535 g_assert (info->gsharedvt_invoke);
2538 * Instead of invoking the method directly, we invoke a gsharedvt out wrapper.
2539 * The advantage of this is the gsharedvt out wrappers have a reduced set of
2540 * signatures, so we only have to generate runtime invoke wrappers for these
2542 * This code also handles invocation of gsharedvt methods directly, no
2543 * out wrappers are used in that case.
2545 args = (void **)g_alloca ((sig->param_count + sig->hasthis + 2) * sizeof (gpointer));
2546 param_refs = (gpointer*)g_alloca ((sig->param_count + sig->hasthis + 2) * sizeof (gpointer));
2549 * The runtime invoke wrappers expects pointers to primitive types, so have to
2553 args [pindex ++] = &obj;
2554 if (sig->ret->type != MONO_TYPE_VOID) {
2555 retval_ptr = (gpointer)&retval;
2556 args [pindex ++] = &retval_ptr;
2558 for (i = 0; i < sig->param_count; ++i) {
2559 MonoType *t = sig->params [i];
2561 if (t->type == MONO_TYPE_GENERICINST && mono_class_is_nullable (mono_class_from_mono_type (t))) {
2562 MonoClass *klass = mono_class_from_mono_type (t);
2563 guint8 *nullable_buf;
2566 size = mono_class_value_size (klass, NULL);
2567 nullable_buf = g_alloca (size);
2568 g_assert (nullable_buf);
2570 /* The argument pointed to by params [i] is either a boxed vtype or null */
2571 mono_nullable_init (nullable_buf, (MonoObject*)params [i], klass);
2572 params [i] = nullable_buf;
2575 if (!t->byref && (MONO_TYPE_IS_REFERENCE (t) || t->type == MONO_TYPE_PTR)) {
2576 param_refs [i] = params [i];
2577 params [i] = &(param_refs [i]);
2579 args [pindex ++] = ¶ms [i];
2581 /* The gsharedvt out wrapper has an extra argument which contains the method to call */
2582 args [pindex ++] = &info->wrapper_arg;
2584 runtime_invoke = (MonoObject *(*)(MonoObject *, void **, MonoObject **, void *))info->runtime_invoke;
2586 runtime_invoke (NULL, args, exc, info->compiled_method);
2590 if (sig->ret->type != MONO_TYPE_VOID && info->ret_box_class)
2591 return mono_value_box_checked (domain, info->ret_box_class, retval, error);
2593 return *(MonoObject**)retval;
2597 * mono_jit_runtime_invoke:
2598 * \param method: the method to invoke
2599 * \param obj: this pointer
2600 * \param params: array of parameter values.
2601 * \param exc: Set to the exception raised in the managed method.
2602 * \param error: error or caught exception object
2603 * If \p exc is NULL, \p error is thrown instead.
2604 * If coop is enabled, \p exc argument is ignored -
2605 * all exceptions are caught and propagated through \p error
2608 mono_jit_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObject **exc, MonoError *error)
2610 MonoMethod *invoke, *callee;
2611 MonoObject *(*runtime_invoke) (MonoObject *this_obj, void **params, MonoObject **exc, void* compiled_method);
2612 MonoDomain *domain = mono_domain_get ();
2613 MonoJitDomainInfo *domain_info;
2614 RuntimeInvokeInfo *info, *info2;
2615 MonoJitInfo *ji = NULL;
2616 gboolean callee_gsharedvt = FALSE;
2618 #ifdef ENABLE_INTERPRETER
2619 if (mono_use_interpreter)
2620 return mono_interp_runtime_invoke (method, obj, params, exc, error);
2625 if (obj == NULL && !(method->flags & METHOD_ATTRIBUTE_STATIC) && !method->string_ctor && (method->wrapper_type == 0)) {
2626 g_warning ("Ignoring invocation of an instance method on a NULL instance.\n");
2630 domain_info = domain_jit_info (domain);
2632 info = (RuntimeInvokeInfo *)mono_conc_hashtable_lookup (domain_info->runtime_invoke_hash, method);
2635 if (mono_security_core_clr_enabled ()) {
2637 * This might be redundant since mono_class_vtable () already does this,
2638 * but keep it just in case for moonlight.
2640 mono_class_setup_vtable (method->klass);
2641 if (mono_class_has_failure (method->klass)) {
2642 mono_error_set_for_class_failure (error, method->klass);
2644 *exc = (MonoObject*)mono_class_get_exception_for_failure (method->klass);
2649 gpointer compiled_method;
2652 if (method->klass->rank && (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) &&
2653 (method->iflags & METHOD_IMPL_ATTRIBUTE_NATIVE)) {
2655 * Array Get/Set/Address methods. The JIT implements them using inline code
2656 * inside the runtime invoke wrappers, so no need to compile them.
2658 if (mono_aot_only) {
2660 * Call a wrapper, since the runtime invoke wrapper was not generated.
2662 MonoMethod *wrapper;
2664 wrapper = mono_marshal_get_array_accessor_wrapper (method);
2665 invoke = mono_marshal_get_runtime_invoke (wrapper, FALSE);
2673 compiled_method = mono_jit_compile_method (callee, error);
2674 if (!compiled_method) {
2675 g_assert (!mono_error_ok (error));
2679 if (mono_llvm_only) {
2680 ji = mini_jit_info_table_find (mono_domain_get (), (char *)mono_get_addr_from_ftnptr (compiled_method), NULL);
2681 callee_gsharedvt = mini_jit_info_is_gsharedvt (ji);
2682 if (callee_gsharedvt)
2683 callee_gsharedvt = mini_is_gsharedvt_variable_signature (mono_method_signature (jinfo_get_method (ji)));
2686 if (!callee_gsharedvt)
2687 compiled_method = mini_add_method_trampoline (callee, compiled_method, mono_method_needs_static_rgctx_invoke (callee, TRUE), FALSE);
2689 compiled_method = NULL;
2692 info = create_runtime_invoke_info (domain, method, compiled_method, callee_gsharedvt, error);
2693 if (!mono_error_ok (error))
2696 mono_domain_lock (domain);
2697 info2 = (RuntimeInvokeInfo *)mono_conc_hashtable_insert (domain_info->runtime_invoke_hash, method, info);
2698 mono_domain_unlock (domain);
2706 * We need this here because mono_marshal_get_runtime_invoke can place
2707 * the helper method in System.Object and not the target class.
2709 if (!mono_runtime_class_init_full (info->vtable, error)) {
2711 *exc = (MonoObject*) mono_error_convert_to_exception (error);
2715 /* If coop is enabled, and the caller didn't ask for the exception to be caught separately,
2716 we always catch the exception and propagate it through the MonoError */
2717 gboolean catchExcInMonoError =
2718 (exc == NULL) && mono_threads_is_coop_enabled ();
2719 MonoObject *invoke_exc = NULL;
2720 if (catchExcInMonoError)
2723 /* The wrappers expect this to be initialized to NULL */
2727 #ifdef MONO_ARCH_DYN_CALL_SUPPORTED
2728 if (info->dyn_call_info) {
2729 MonoMethodSignature *sig = mono_method_signature (method);
2731 static RuntimeInvokeDynamicFunction dyn_runtime_invoke;
2734 guint8 retval [256];
2736 if (!dyn_runtime_invoke) {
2737 invoke = mono_marshal_get_runtime_invoke_dynamic ();
2738 dyn_runtime_invoke = (RuntimeInvokeDynamicFunction)mono_jit_compile_method (invoke, error);
2739 if (!mono_error_ok (error))
2743 /* Convert the arguments to the format expected by start_dyn_call () */
2744 args = (void **)g_alloca ((sig->param_count + sig->hasthis) * sizeof (gpointer));
2747 args [pindex ++] = &obj;
2748 for (i = 0; i < sig->param_count; ++i) {
2749 MonoType *t = sig->params [i];
2752 args [pindex ++] = ¶ms [i];
2753 } else if (MONO_TYPE_IS_REFERENCE (t) || t->type == MONO_TYPE_PTR) {
2754 args [pindex ++] = ¶ms [i];
2756 args [pindex ++] = params [i];
2760 //printf ("M: %s\n", mono_method_full_name (method, TRUE));
2762 mono_arch_start_dyn_call (info->dyn_call_info, (gpointer**)args, retval, buf, sizeof (buf));
2764 dyn_runtime_invoke (buf, exc, info->compiled_method);
2765 mono_arch_finish_dyn_call (info->dyn_call_info, buf);
2767 if (catchExcInMonoError && *exc != NULL) {
2768 mono_error_set_exception_instance (error, (MonoException*) *exc);
2772 if (info->ret_box_class)
2773 return mono_value_box_checked (domain, info->ret_box_class, retval, error);
2775 return *(MonoObject**)retval;
2781 if (mono_llvm_only) {
2782 result = mono_llvmonly_runtime_invoke (method, info, obj, params, exc, error);
2786 runtime_invoke = (MonoObject *(*)(MonoObject *, void **, MonoObject **, void *))info->runtime_invoke;
2788 result = runtime_invoke ((MonoObject *)obj, params, exc, info->compiled_method);
2790 if (catchExcInMonoError && *exc != NULL)
2791 mono_error_set_exception_instance (error, (MonoException*) *exc);
2800 typedef gpointer (*IMTTrampFunc) (gpointer *arg, MonoMethod *imt_method);
2803 * mini_llvmonly_initial_imt_tramp:
2805 * This function is called the first time a call is made through an IMT trampoline.
2806 * It should have the same signature as the mono_llvmonly_imt_tramp_... functions.
2809 mini_llvmonly_initial_imt_tramp (gpointer *arg, MonoMethod *imt_method)
2811 IMTTrampInfo *info = (IMTTrampInfo*)arg;
2816 mono_vtable_build_imt_slot (info->vtable, info->slot);
2818 imt = (gpointer*)info->vtable;
2819 imt -= MONO_IMT_SIZE;
2821 /* Return what the real IMT trampoline returns */
2822 ftndesc = imt [info->slot];
2825 if (func == (IMTTrampFunc)mini_llvmonly_initial_imt_tramp)
2826 /* Happens when the imt slot contains only a generic virtual method */
2828 return func ((gpointer *)ftndesc [1], imt_method);
2831 /* This is called indirectly through an imt slot. */
2833 mono_llvmonly_imt_tramp (gpointer *arg, MonoMethod *imt_method)
2837 /* arg points to an array created in mono_llvmonly_get_imt_trampoline () */
2838 while (arg [i] && arg [i] != imt_method)
2845 /* Optimized versions of mono_llvmonly_imt_trampoline () for different table sizes */
2847 mono_llvmonly_imt_tramp_1 (gpointer *arg, MonoMethod *imt_method)
2849 //g_assert (arg [0] == imt_method);
2854 mono_llvmonly_imt_tramp_2 (gpointer *arg, MonoMethod *imt_method)
2856 //g_assert (arg [0] == imt_method || arg [2] == imt_method);
2857 if (arg [0] == imt_method)
2864 mono_llvmonly_imt_tramp_3 (gpointer *arg, MonoMethod *imt_method)
2866 //g_assert (arg [0] == imt_method || arg [2] == imt_method || arg [4] == imt_method);
2867 if (arg [0] == imt_method)
2869 else if (arg [2] == imt_method)
2876 * A version of the imt trampoline used for generic virtual/variant iface methods.
2877 * Unlikely a normal imt trampoline, its possible that IMT_METHOD is not found
2878 * in the search table. The original JIT code had a 'fallback' trampoline it could
2879 * call, but we can't do that, so we just return NULL, and the compiled code
2883 mono_llvmonly_fallback_imt_tramp (gpointer *arg, MonoMethod *imt_method)
2887 while (arg [i] && arg [i] != imt_method)
2896 mono_llvmonly_get_imt_trampoline (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckItem **imt_entries, int count, gpointer fail_tramp)
2900 int i, index, real_count;
2901 gboolean virtual_generic = FALSE;
2904 * Create an array which is passed to the imt trampoline functions.
2905 * The array contains MonoMethod-function descriptor pairs, terminated by a NULL entry.
2909 for (i = 0; i < count; ++i) {
2910 MonoIMTCheckItem *item = imt_entries [i];
2912 if (item->is_equals)
2914 if (item->has_target_code)
2915 virtual_generic = TRUE;
2919 * Initialize all vtable entries reachable from this imt slot, so the compiled
2920 * code doesn't have to check it.
2922 for (i = 0; i < count; ++i) {
2923 MonoIMTCheckItem *item = imt_entries [i];
2926 if (!item->is_equals || item->has_target_code)
2928 vt_slot = item->value.vtable_slot;
2929 mono_init_vtable_slot (vtable, vt_slot);
2932 /* Save the entries into an array */
2933 buf = (void **)mono_domain_alloc (domain, (real_count + 1) * 2 * sizeof (gpointer));
2935 for (i = 0; i < count; ++i) {
2936 MonoIMTCheckItem *item = imt_entries [i];
2938 if (!item->is_equals)
2941 g_assert (item->key);
2942 buf [(index * 2)] = item->key;
2943 if (item->has_target_code)
2944 buf [(index * 2) + 1] = item->value.target_code;
2946 buf [(index * 2) + 1] = vtable->vtable [item->value.vtable_slot];
2949 buf [(index * 2)] = NULL;
2950 buf [(index * 2) + 1] = fail_tramp;
2953 * Return a function descriptor for a C function with 'buf' as its argument.
2954 * It will by called by JITted code.
2956 res = (void **)mono_domain_alloc (domain, 2 * sizeof (gpointer));
2957 switch (real_count) {
2959 res [0] = mono_llvmonly_imt_tramp_1;
2962 res [0] = mono_llvmonly_imt_tramp_2;
2965 res [0] = mono_llvmonly_imt_tramp_3;
2968 res [0] = mono_llvmonly_imt_tramp;
2971 if (virtual_generic || fail_tramp)
2972 res [0] = mono_llvmonly_fallback_imt_tramp;
2978 MONO_SIG_HANDLER_FUNC (, mono_sigfpe_signal_handler)
2980 MonoException *exc = NULL;
2982 MONO_SIG_HANDLER_INFO_TYPE *info = MONO_SIG_HANDLER_GET_INFO ();
2983 MONO_SIG_HANDLER_GET_CONTEXT;
2985 ji = mono_jit_info_table_find_internal (mono_domain_get (), (char *)mono_arch_ip_from_context (ctx), TRUE, TRUE);
2987 MONO_ENTER_GC_UNSAFE_UNBALANCED;
2989 #if defined(MONO_ARCH_HAVE_IS_INT_OVERFLOW)
2990 if (mono_arch_is_int_overflow (ctx, info))
2992 * The spec says this throws ArithmeticException, but MS throws the derived
2993 * OverflowException.
2995 exc = mono_get_exception_overflow ();
2997 exc = mono_get_exception_divide_by_zero ();
2999 exc = mono_get_exception_divide_by_zero ();
3003 if (!mono_do_crash_chaining && mono_chain_signal (MONO_SIG_HANDLER_PARAMS))
3006 mono_handle_native_crash ("SIGFPE", ctx, info);
3007 if (mono_do_crash_chaining) {
3008 mono_chain_signal (MONO_SIG_HANDLER_PARAMS);
3013 mono_arch_handle_exception (ctx, exc);
3016 MONO_EXIT_GC_UNSAFE_UNBALANCED;
3019 MONO_SIG_HANDLER_FUNC (, mono_sigill_signal_handler)
3021 MONO_SIG_HANDLER_INFO_TYPE *info = MONO_SIG_HANDLER_GET_INFO ();
3022 MONO_SIG_HANDLER_GET_CONTEXT;
3024 if (mono_runtime_get_no_exec ())
3028 mono_handle_native_crash ("SIGILL", ctx, info);
3029 if (mono_do_crash_chaining) {
3030 mono_chain_signal (MONO_SIG_HANDLER_PARAMS);
3034 g_assert_not_reached ();
3037 #if defined(MONO_ARCH_USE_SIGACTION) || defined(HOST_WIN32)
3038 #define HAVE_SIG_INFO
3041 MONO_SIG_HANDLER_FUNC (, mono_sigsegv_signal_handler)
3044 MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_tls_get_jit_tls ();
3045 gpointer fault_addr = NULL;
3046 #ifdef HAVE_SIG_INFO
3047 MONO_SIG_HANDLER_INFO_TYPE *info = MONO_SIG_HANDLER_GET_INFO ();
3051 MONO_SIG_HANDLER_GET_CONTEXT;
3053 #if defined(MONO_ARCH_SOFT_DEBUG_SUPPORTED) && defined(HAVE_SIG_INFO)
3054 if (mono_arch_is_single_step_event (info, ctx)) {
3055 mono_debugger_agent_single_step_event (ctx);
3057 } else if (mono_arch_is_breakpoint_event (info, ctx)) {
3058 mono_debugger_agent_breakpoint_hit (ctx);
3063 #if defined(HAVE_SIG_INFO)
3064 #if !defined(HOST_WIN32)
3065 fault_addr = info->si_addr;
3066 if (mono_aot_is_pagefault (info->si_addr)) {
3067 mono_aot_handle_pagefault (info->si_addr);
3072 /* The thread might no be registered with the runtime */
3073 if (!mono_domain_get () || !jit_tls) {
3074 if (!mono_do_crash_chaining && mono_chain_signal (MONO_SIG_HANDLER_PARAMS))
3076 mono_handle_native_crash ("SIGSEGV", ctx, info);
3077 if (mono_do_crash_chaining) {
3078 mono_chain_signal (MONO_SIG_HANDLER_PARAMS);
3084 ji = mono_jit_info_table_find_internal (mono_domain_get (), (char *)mono_arch_ip_from_context (ctx), TRUE, TRUE);
3086 #ifdef MONO_ARCH_SIGSEGV_ON_ALTSTACK
3087 if (mono_handle_soft_stack_ovf (jit_tls, ji, ctx, info, (guint8*)info->si_addr))
3090 #ifdef MONO_ARCH_HAVE_SIGCTX_TO_MONOCTX
3091 /* info->si_addr seems to be NULL on some kernels when handling stack overflows */
3092 fault_addr = info->si_addr;
3093 if (fault_addr == NULL) {
3096 mono_sigctx_to_monoctx (ctx, &mctx);
3098 fault_addr = MONO_CONTEXT_GET_SP (&mctx);
3102 if (jit_tls->stack_size &&
3103 ABS ((guint8*)fault_addr - ((guint8*)jit_tls->end_of_stack - jit_tls->stack_size)) < 8192 * sizeof (gpointer)) {
3105 * The hard-guard page has been hit: there is not much we can do anymore
3106 * Print a hopefully clear message and abort.
3108 mono_handle_hard_stack_ovf (jit_tls, ji, ctx, (guint8*)info->si_addr);
3109 g_assert_not_reached ();
3111 /* The original handler might not like that it is executed on an altstack... */
3112 if (!ji && mono_chain_signal (MONO_SIG_HANDLER_PARAMS))
3115 mono_arch_handle_altstack_exception (ctx, info, info->si_addr, FALSE);
3120 if (!mono_do_crash_chaining && mono_chain_signal (MONO_SIG_HANDLER_PARAMS))
3123 mono_handle_native_crash ("SIGSEGV", ctx, info);
3125 if (mono_do_crash_chaining) {
3126 mono_chain_signal (MONO_SIG_HANDLER_PARAMS);
3131 mono_arch_handle_exception (ctx, NULL);
3135 MONO_SIG_HANDLER_FUNC (, mono_sigint_signal_handler)
3138 MONO_SIG_HANDLER_GET_CONTEXT;
3140 MONO_ENTER_GC_UNSAFE_UNBALANCED;
3142 exc = mono_get_exception_execution_engine ("Interrupted (SIGINT).");
3144 mono_arch_handle_exception (ctx, exc);
3146 MONO_EXIT_GC_UNSAFE_UNBALANCED;
3149 #ifndef DISABLE_REMOTING
3150 /* mono_jit_create_remoting_trampoline:
3151 * @method: pointer to the method info
3153 * Creates a trampoline which calls the remoting functions. This
3154 * is used in the vtable of transparent proxies.
3156 * Returns: a pointer to the newly created code
3159 mono_jit_create_remoting_trampoline (MonoDomain *domain, MonoMethod *method, MonoRemotingTarget target, MonoError *error)
3162 guint8 *addr = NULL;
3166 if ((method->flags & METHOD_ATTRIBUTE_VIRTUAL) && mono_method_signature (method)->generic_param_count) {
3167 return mono_create_specific_trampoline (method, MONO_TRAMPOLINE_GENERIC_VIRTUAL_REMOTING,
3171 if ((method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
3172 (mono_method_signature (method)->hasthis && (mono_class_is_marshalbyref (method->klass) || method->klass == mono_defaults.object_class)))
3173 nm = mono_marshal_get_remoting_invoke_for_target (method, target);
3176 addr = (guint8 *)mono_compile_method_checked (nm, error);
3177 return_val_if_nok (error, NULL);
3178 return mono_get_addr_from_ftnptr (addr);
3182 static G_GNUC_UNUSED void
3183 no_imt_trampoline (void)
3185 g_assert_not_reached ();
3188 static G_GNUC_UNUSED void
3189 no_vcall_trampoline (void)
3191 g_assert_not_reached ();
3194 static gpointer *vtable_trampolines;
3195 static int vtable_trampolines_size;
3198 mini_get_vtable_trampoline (MonoVTable *vt, int slot_index)
3200 int index = slot_index + MONO_IMT_SIZE;
3202 if (mono_llvm_only) {
3203 if (slot_index < 0) {
3204 /* Initialize the IMT trampoline to a 'trampoline' so the generated code doesn't have to initialize it */
3205 // FIXME: Memory management
3206 gpointer *ftndesc = g_malloc (2 * sizeof (gpointer));
3207 IMTTrampInfo *info = g_new0 (IMTTrampInfo, 1);
3210 ftndesc [0] = mini_llvmonly_initial_imt_tramp;
3212 mono_memory_barrier ();
3219 g_assert (slot_index >= - MONO_IMT_SIZE);
3220 if (!vtable_trampolines || slot_index + MONO_IMT_SIZE >= vtable_trampolines_size) {
3222 if (!vtable_trampolines || index >= vtable_trampolines_size) {
3226 new_size = vtable_trampolines_size ? vtable_trampolines_size * 2 : 128;
3227 while (new_size <= index)
3229 new_table = g_new0 (gpointer, new_size);
3231 if (vtable_trampolines)
3232 memcpy (new_table, vtable_trampolines, vtable_trampolines_size * sizeof (gpointer));
3233 g_free (vtable_trampolines);
3234 mono_memory_barrier ();
3235 vtable_trampolines = (void **)new_table;
3236 vtable_trampolines_size = new_size;
3241 if (!vtable_trampolines [index])
3242 vtable_trampolines [index] = mono_create_specific_trampoline (GUINT_TO_POINTER (slot_index), MONO_TRAMPOLINE_VCALL, mono_get_root_domain (), NULL);
3243 return vtable_trampolines [index];
3247 mini_get_imt_trampoline (MonoVTable *vt, int slot_index)
3249 return mini_get_vtable_trampoline (vt, slot_index - MONO_IMT_SIZE);
3253 mini_imt_entry_inited (MonoVTable *vt, int imt_slot_index)
3258 gpointer *imt = (gpointer*)vt;
3259 imt -= MONO_IMT_SIZE;
3261 return (imt [imt_slot_index] != mini_get_imt_trampoline (vt, imt_slot_index));
3265 is_callee_gsharedvt_variable (gpointer addr)
3268 gboolean callee_gsharedvt;
3270 ji = mini_jit_info_table_find (mono_domain_get (), (char *)mono_get_addr_from_ftnptr (addr), NULL);
3272 callee_gsharedvt = mini_jit_info_is_gsharedvt (ji);
3273 if (callee_gsharedvt)
3274 callee_gsharedvt = mini_is_gsharedvt_variable_signature (mono_method_signature (jinfo_get_method (ji)));
3275 return callee_gsharedvt;
3279 mini_get_delegate_arg (MonoMethod *method, gpointer method_ptr)
3281 gpointer arg = NULL;
3283 if (mono_method_needs_static_rgctx_invoke (method, FALSE))
3284 arg = mini_method_get_rgctx (method);
3287 * Avoid adding gsharedvt in wrappers since they might not exist if
3288 * this delegate is called through a gsharedvt delegate invoke wrapper.
3289 * Instead, encode that the method is gsharedvt in del->extra_arg,
3290 * the CEE_MONO_CALLI_EXTRA_ARG implementation in the JIT depends on this.
3292 if (method->is_inflated && is_callee_gsharedvt_variable (method_ptr)) {
3293 g_assert ((((mgreg_t)arg) & 1) == 0);
3294 arg = (gpointer)(((mgreg_t)arg) | 1);
3300 mini_init_delegate (MonoDelegate *del)
3303 del->extra_arg = mini_get_delegate_arg (del->method, del->method_ptr);
3304 #ifdef ENABLE_INTERPRETER
3305 if (mono_use_interpreter)
3306 mono_interp_init_delegate (del);
3311 mono_get_delegate_virtual_invoke_impl_name (gboolean load_imt_reg, int offset)
3315 abs_offset = offset;
3317 abs_offset = - abs_offset;
3318 return g_strdup_printf ("delegate_virtual_invoke%s_%s%d", load_imt_reg ? "_imt" : "", offset < 0 ? "m_" : "", abs_offset / SIZEOF_VOID_P);
3322 mono_get_delegate_virtual_invoke_impl (MonoMethodSignature *sig, MonoMethod *method)
3324 gboolean is_virtual_generic, is_interface, load_imt_reg;
3327 static guint8 **cache = NULL;
3328 static int cache_size = 0;
3333 if (MONO_TYPE_ISSTRUCT (sig->ret))
3336 is_virtual_generic = method->is_inflated && mono_method_get_declaring_generic_method (method)->is_generic;
3337 is_interface = mono_class_is_interface (method->klass);
3338 load_imt_reg = is_virtual_generic || is_interface;
3341 offset = ((gint32)mono_method_get_imt_slot (method) - MONO_IMT_SIZE) * SIZEOF_VOID_P;
3343 offset = G_STRUCT_OFFSET (MonoVTable, vtable) + ((mono_method_get_vtable_index (method)) * (SIZEOF_VOID_P));
3345 idx = (offset / SIZEOF_VOID_P + MONO_IMT_SIZE) * 2 + (load_imt_reg ? 1 : 0);
3346 g_assert (idx >= 0);
3348 /* Resize the cache to idx + 1 */
3349 if (cache_size < idx + 1) {
3351 if (cache_size < idx + 1) {
3353 int new_cache_size = idx + 1;
3355 new_cache = g_new0 (guint8*, new_cache_size);
3357 memcpy (new_cache, cache, cache_size * sizeof (guint8*));
3360 mono_memory_barrier ();
3362 cache_size = new_cache_size;
3370 /* FIXME Support more cases */
3371 if (mono_aot_only) {
3372 cache [idx] = (guint8 *)mono_aot_get_trampoline (mono_get_delegate_virtual_invoke_impl_name (load_imt_reg, offset));
3373 g_assert (cache [idx]);
3375 cache [idx] = (guint8 *)mono_arch_get_delegate_virtual_invoke_impl (sig, method, offset, load_imt_reg);
3381 * mini_parse_debug_option:
3382 * @option: The option to parse.
3384 * Parses debug options for the mono runtime. The options are the same as for
3385 * the MONO_DEBUG environment variable.
3389 mini_parse_debug_option (const char *option)
3391 if (!strcmp (option, "handle-sigint"))
3392 debug_options.handle_sigint = TRUE;
3393 else if (!strcmp (option, "keep-delegates"))
3394 debug_options.keep_delegates = TRUE;
3395 else if (!strcmp (option, "reverse-pinvoke-exceptions"))
3396 debug_options.reverse_pinvoke_exceptions = TRUE;
3397 else if (!strcmp (option, "collect-pagefault-stats"))
3398 debug_options.collect_pagefault_stats = TRUE;
3399 else if (!strcmp (option, "break-on-unverified"))
3400 debug_options.break_on_unverified = TRUE;
3401 else if (!strcmp (option, "no-gdb-backtrace"))
3402 debug_options.no_gdb_backtrace = TRUE;
3403 else if (!strcmp (option, "suspend-on-native-crash") || !strcmp (option, "suspend-on-sigsegv"))
3404 debug_options.suspend_on_native_crash = TRUE;
3405 else if (!strcmp (option, "suspend-on-exception"))
3406 debug_options.suspend_on_exception = TRUE;
3407 else if (!strcmp (option, "suspend-on-unhandled"))
3408 debug_options.suspend_on_unhandled = TRUE;
3409 else if (!strcmp (option, "dont-free-domains"))
3410 mono_dont_free_domains = TRUE;
3411 else if (!strcmp (option, "dyn-runtime-invoke"))
3412 debug_options.dyn_runtime_invoke = TRUE;
3413 else if (!strcmp (option, "gdb"))
3414 debug_options.gdb = TRUE;
3415 else if (!strcmp (option, "lldb"))
3416 debug_options.lldb = TRUE;
3417 else if (!strcmp (option, "explicit-null-checks"))
3418 debug_options.explicit_null_checks = TRUE;
3419 else if (!strcmp (option, "gen-seq-points"))
3420 debug_options.gen_sdb_seq_points = TRUE;
3421 else if (!strcmp (option, "gen-compact-seq-points"))
3422 fprintf (stderr, "Mono Warning: option gen-compact-seq-points is deprecated.\n");
3423 else if (!strcmp (option, "no-compact-seq-points"))
3424 debug_options.no_seq_points_compact_data = TRUE;
3425 else if (!strcmp (option, "single-imm-size"))
3426 debug_options.single_imm_size = TRUE;
3427 else if (!strcmp (option, "init-stacks"))
3428 debug_options.init_stacks = TRUE;
3429 else if (!strcmp (option, "casts"))
3430 debug_options.better_cast_details = TRUE;
3431 else if (!strcmp (option, "soft-breakpoints"))
3432 debug_options.soft_breakpoints = TRUE;
3433 else if (!strcmp (option, "check-pinvoke-callconv"))
3434 debug_options.check_pinvoke_callconv = TRUE;
3435 else if (!strcmp (option, "use-fallback-tls"))
3436 debug_options.use_fallback_tls = TRUE;
3437 else if (!strcmp (option, "debug-domain-unload"))
3438 mono_enable_debug_domain_unload (TRUE);
3439 else if (!strcmp (option, "partial-sharing"))
3440 mono_set_partial_sharing_supported (TRUE);
3441 else if (!strcmp (option, "align-small-structs"))
3442 mono_align_small_structs = TRUE;
3443 else if (!strcmp (option, "native-debugger-break"))
3444 debug_options.native_debugger_break = TRUE;
3445 else if (!strcmp (option, "disable_omit_fp"))
3446 debug_options.disable_omit_fp = TRUE;
3454 mini_parse_debug_options (void)
3456 char *options = g_getenv ("MONO_DEBUG");
3457 gchar **args, **ptr;
3462 args = g_strsplit (options, ",", -1);
3465 for (ptr = args; ptr && *ptr; ptr++) {
3466 const char *arg = *ptr;
3468 if (!mini_parse_debug_option (arg)) {
3469 fprintf (stderr, "Invalid option for the MONO_DEBUG env variable: %s\n", arg);
3470 fprintf (stderr, "Available options: 'handle-sigint', 'keep-delegates', 'reverse-pinvoke-exceptions', 'collect-pagefault-stats', 'break-on-unverified', 'no-gdb-backtrace', 'suspend-on-native-crash', 'suspend-on-sigsegv', 'suspend-on-exception', 'suspend-on-unhandled', 'dont-free-domains', 'dyn-runtime-invoke', 'gdb', 'explicit-null-checks', 'gen-seq-points', 'no-compact-seq-points', 'single-imm-size', 'init-stacks', 'casts', 'soft-breakpoints', 'check-pinvoke-callconv', 'use-fallback-tls', 'debug-domain-unload', 'partial-sharing', 'align-small-structs', 'native-debugger-break'\n");
3479 mini_get_debug_options (void)
3481 return &debug_options;
3485 mini_create_ftnptr (MonoDomain *domain, gpointer addr)
3487 #if (!defined(__ppc64__) && !defined(__powerpc64__) || _CALL_ELF == 2)
3490 gpointer* desc = NULL;
3492 if ((desc = g_hash_table_lookup (domain->ftnptrs_hash, addr)))
3494 # if defined(__ppc64__) || defined(__powerpc64__)
3496 desc = mono_domain_alloc0 (domain, 3 * sizeof (gpointer));
3502 g_hash_table_insert (domain->ftnptrs_hash, addr, desc);
3508 mini_get_addr_from_ftnptr (gpointer descr)
3510 #if ((defined(__ppc64__) || defined(__powerpc64__)) && _CALL_ELF != 2)
3511 return *(gpointer*)descr;
3518 register_jit_stats (void)
3520 mono_counters_register ("Compiled methods", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.methods_compiled);
3521 mono_counters_register ("Methods from AOT", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.methods_aot);
3522 mono_counters_register ("Methods JITted using mono JIT", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.methods_without_llvm);
3523 mono_counters_register ("Methods JITted using LLVM", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.methods_with_llvm);
3524 mono_counters_register ("JIT/method_to_ir (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_method_to_ir);
3525 mono_counters_register ("JIT/liveness_handle_exception_clauses (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_liveness_handle_exception_clauses);
3526 mono_counters_register ("JIT/handle_out_of_line_bblock (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_handle_out_of_line_bblock);
3527 mono_counters_register ("JIT/decompose_long_opts (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_decompose_long_opts);
3528 mono_counters_register ("JIT/decompose_typechecks (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_decompose_typechecks);
3529 mono_counters_register ("JIT/local_cprop (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_local_cprop);
3530 mono_counters_register ("JIT/local_emulate_ops (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_local_emulate_ops);
3531 mono_counters_register ("JIT/optimize_branches (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_optimize_branches);
3532 mono_counters_register ("JIT/handle_global_vregs (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_handle_global_vregs);
3533 mono_counters_register ("JIT/local_deadce (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_local_deadce);
3534 mono_counters_register ("JIT/local_alias_analysis (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_local_alias_analysis);
3535 mono_counters_register ("JIT/if_conversion (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_if_conversion);
3536 mono_counters_register ("JIT/bb_ordering (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_bb_ordering);
3537 mono_counters_register ("JIT/compile_dominator_info (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_compile_dominator_info);
3538 mono_counters_register ("JIT/compute_natural_loops (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_compute_natural_loops);
3539 mono_counters_register ("JIT/insert_safepoints (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_insert_safepoints);
3540 mono_counters_register ("JIT/ssa_compute (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_ssa_compute);
3541 mono_counters_register ("JIT/ssa_cprop (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_ssa_cprop);
3542 mono_counters_register ("JIT/ssa_deadce(sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_ssa_deadce);
3543 mono_counters_register ("JIT/perform_abc_removal (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_perform_abc_removal);
3544 mono_counters_register ("JIT/ssa_remove (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_ssa_remove);
3545 mono_counters_register ("JIT/local_cprop2 (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_local_cprop2);
3546 mono_counters_register ("JIT/handle_global_vregs2 (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_handle_global_vregs2);
3547 mono_counters_register ("JIT/local_deadce2 (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_local_deadce2);
3548 mono_counters_register ("JIT/optimize_branches2 (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_optimize_branches2);
3549 mono_counters_register ("JIT/decompose_vtype_opts (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_decompose_vtype_opts);
3550 mono_counters_register ("JIT/decompose_array_access_opts (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_decompose_array_access_opts);
3551 mono_counters_register ("JIT/liveness_handle_exception_clauses2 (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_liveness_handle_exception_clauses2);
3552 mono_counters_register ("JIT/analyze_liveness (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_analyze_liveness);
3553 mono_counters_register ("JIT/linear_scan (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_linear_scan);
3554 mono_counters_register ("JIT/arch_allocate_vars (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_arch_allocate_vars);
3555 mono_counters_register ("JIT/spill_global_vars (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_spill_global_vars);
3556 mono_counters_register ("JIT/local_cprop3 (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_local_cprop3);
3557 mono_counters_register ("JIT/local_deadce3 (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_local_deadce3);
3558 mono_counters_register ("JIT/codegen (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_codegen);
3559 mono_counters_register ("JIT/create_jit_info (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_create_jit_info);
3560 mono_counters_register ("JIT/gc_create_gc_map (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_gc_create_gc_map);
3561 mono_counters_register ("JIT/save_seq_point_info (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_save_seq_point_info);
3562 mono_counters_register ("Total time spent JITting (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_time);
3563 mono_counters_register ("Basic blocks", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.basic_blocks);
3564 mono_counters_register ("Max basic blocks", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.max_basic_blocks);
3565 mono_counters_register ("Allocated vars", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.allocate_var);
3566 mono_counters_register ("Code reallocs", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.code_reallocs);
3567 mono_counters_register ("Allocated code size", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.allocated_code_size);
3568 mono_counters_register ("Allocated seq points size", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.allocated_seq_points_size);
3569 mono_counters_register ("Inlineable methods", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.inlineable_methods);
3570 mono_counters_register ("Inlined methods", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.inlined_methods);
3571 mono_counters_register ("Regvars", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.regvars);
3572 mono_counters_register ("Locals stack size", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.locals_stack_size);
3573 mono_counters_register ("Method cache lookups", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.methods_lookups);
3574 mono_counters_register ("Compiled CIL code size", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.cil_code_size);
3575 mono_counters_register ("Native code size", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.native_code_size);
3576 mono_counters_register ("Aliases found", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.alias_found);
3577 mono_counters_register ("Aliases eliminated", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.alias_removed);
3578 mono_counters_register ("Aliased loads eliminated", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.loads_eliminated);
3579 mono_counters_register ("Aliased stores eliminated", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.stores_eliminated);
3580 mono_counters_register ("Optimized immediate divisions", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.optimized_divisions);
3583 static void runtime_invoke_info_free (gpointer value);
3586 class_method_pair_equal (gconstpointer ka, gconstpointer kb)
3588 const MonoClassMethodPair *apair = (const MonoClassMethodPair *)ka;
3589 const MonoClassMethodPair *bpair = (const MonoClassMethodPair *)kb;
3591 return apair->klass == bpair->klass && apair->method == bpair->method ? 1 : 0;
3595 class_method_pair_hash (gconstpointer data)
3597 const MonoClassMethodPair *pair = (const MonoClassMethodPair *)data;
3599 return (gsize)pair->klass ^ (gsize)pair->method;
3603 mini_create_jit_domain_info (MonoDomain *domain)
3605 MonoJitDomainInfo *info = g_new0 (MonoJitDomainInfo, 1);
3607 info->jump_trampoline_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
3608 info->jit_trampoline_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
3609 info->delegate_trampoline_hash = g_hash_table_new (class_method_pair_hash, class_method_pair_equal);
3610 info->llvm_vcall_trampoline_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
3611 info->runtime_invoke_hash = mono_conc_hashtable_new_full (mono_aligned_addr_hash, NULL, NULL, runtime_invoke_info_free);
3612 info->seq_points = g_hash_table_new_full (mono_aligned_addr_hash, NULL, NULL, mono_seq_point_info_free);
3613 info->arch_seq_points = g_hash_table_new (mono_aligned_addr_hash, NULL);
3614 info->jump_target_hash = g_hash_table_new (NULL, NULL);
3615 mono_jit_code_hash_init (&info->interp_code_hash);
3617 domain->runtime_info = info;
3621 delete_jump_list (gpointer key, gpointer value, gpointer user_data)
3623 MonoJumpList *jlist = (MonoJumpList *)value;
3624 g_slist_free (jlist->list);
3628 delete_got_slot_list (gpointer key, gpointer value, gpointer user_data)
3630 GSList *list = (GSList *)value;
3631 g_slist_free (list);
3635 dynamic_method_info_free (gpointer key, gpointer value, gpointer user_data)
3637 MonoJitDynamicMethodInfo *di = (MonoJitDynamicMethodInfo *)value;
3638 mono_code_manager_destroy (di->code_mp);
3643 runtime_invoke_info_free (gpointer value)
3645 RuntimeInvokeInfo *info = (RuntimeInvokeInfo*)value;
3647 #ifdef MONO_ARCH_DYN_CALL_SUPPORTED
3648 if (info->dyn_call_info)
3649 mono_arch_dyn_call_free (info->dyn_call_info);
3655 free_jit_callee_list (gpointer key, gpointer value, gpointer user_data)
3657 g_slist_free (value);
3661 mini_free_jit_domain_info (MonoDomain *domain)
3663 MonoJitDomainInfo *info = domain_jit_info (domain);
3665 g_hash_table_foreach (info->jump_target_hash, delete_jump_list, NULL);
3666 g_hash_table_destroy (info->jump_target_hash);
3667 if (info->jump_target_got_slot_hash) {
3668 g_hash_table_foreach (info->jump_target_got_slot_hash, delete_got_slot_list, NULL);
3669 g_hash_table_destroy (info->jump_target_got_slot_hash);
3671 if (info->dynamic_code_hash) {
3672 g_hash_table_foreach (info->dynamic_code_hash, dynamic_method_info_free, NULL);
3673 g_hash_table_destroy (info->dynamic_code_hash);
3675 if (info->method_code_hash)
3676 g_hash_table_destroy (info->method_code_hash);
3677 g_hash_table_destroy (info->jump_trampoline_hash);
3678 g_hash_table_destroy (info->jit_trampoline_hash);
3679 g_hash_table_destroy (info->delegate_trampoline_hash);
3680 if (info->static_rgctx_trampoline_hash)
3681 g_hash_table_destroy (info->static_rgctx_trampoline_hash);
3682 g_hash_table_destroy (info->llvm_vcall_trampoline_hash);
3683 mono_conc_hashtable_destroy (info->runtime_invoke_hash);
3684 g_hash_table_destroy (info->seq_points);
3685 g_hash_table_destroy (info->arch_seq_points);
3686 if (info->agent_info)
3687 mono_debugger_agent_free_domain_info (domain);
3688 if (info->gsharedvt_arg_tramp_hash)
3689 g_hash_table_destroy (info->gsharedvt_arg_tramp_hash);
3690 if (info->llvm_jit_callees) {
3691 g_hash_table_foreach (info->llvm_jit_callees, free_jit_callee_list, NULL);
3692 g_hash_table_destroy (info->llvm_jit_callees);
3694 mono_internal_hash_table_destroy (&info->interp_code_hash);
3696 mono_llvm_free_domain_info (domain);
3699 g_free (domain->runtime_info);
3700 domain->runtime_info = NULL;
3703 #ifdef MONO_ARCH_HAVE_CODE_CHUNK_TRACKING
3706 code_manager_chunk_new (void *chunk, int size)
3708 mono_arch_code_chunk_new (chunk, size);
3712 code_manager_chunk_destroy (void *chunk)
3714 mono_arch_code_chunk_destroy (chunk);
3721 llvm_init_inner (void)
3723 if (!mono_llvm_load (NULL))
3734 * Load and initialize LLVM support.
3735 * Return TRUE on success.
3738 mini_llvm_init (void)
3741 static gboolean llvm_inited;
3742 static gboolean init_result;
3744 mono_loader_lock_if_inited ();
3746 init_result = llvm_init_inner ();
3749 mono_loader_unlock_if_inited ();
3757 mini_add_profiler_argument (const char *desc)
3759 if (!profile_options)
3760 profile_options = g_ptr_array_new ();
3762 g_ptr_array_add (profile_options, (gpointer) desc);
3766 mini_init (const char *filename, const char *runtime_version)
3770 MonoRuntimeCallbacks callbacks;
3771 MonoThreadInfoRuntimeCallbacks ticallbacks;
3772 MonoCodeManagerCallbacks code_manager_callbacks;
3774 MONO_VES_INIT_BEGIN ();
3776 CHECKED_MONO_INIT ();
3778 #if defined(__linux__)
3779 if (access ("/proc/self/maps", F_OK) != 0) {
3780 g_print ("Mono requires /proc to be mounted.\n");
3785 #ifdef ENABLE_INTERPRETER
3786 mono_interp_init ();
3789 mono_os_mutex_init_recursive (&jit_mutex);
3791 mono_cross_helpers_run ();
3793 mono_counters_init ();
3797 mini_jit_init_job_control ();
3799 /* Happens when using the embedding interface */
3800 if (!default_opt_set)
3801 default_opt = mono_parse_default_optimizations (NULL);
3803 #ifdef MONO_ARCH_GSHAREDVT_SUPPORTED
3805 mono_set_generic_sharing_vt_supported (TRUE);
3808 mono_set_generic_sharing_vt_supported (TRUE);
3811 mono_tls_init_runtime_keys ();
3813 if (!global_codeman)
3814 global_codeman = mono_code_manager_new ();
3816 memset (&callbacks, 0, sizeof (callbacks));
3817 callbacks.create_ftnptr = mini_create_ftnptr;
3818 callbacks.get_addr_from_ftnptr = mini_get_addr_from_ftnptr;
3819 callbacks.get_runtime_build_info = mono_get_runtime_build_info;
3820 callbacks.set_cast_details = mono_set_cast_details;
3821 callbacks.debug_log = mono_debugger_agent_debug_log;
3822 callbacks.debug_log_is_enabled = mono_debugger_agent_debug_log_is_enabled;
3823 callbacks.get_vtable_trampoline = mini_get_vtable_trampoline;
3824 callbacks.get_imt_trampoline = mini_get_imt_trampoline;
3825 callbacks.imt_entry_inited = mini_imt_entry_inited;
3826 callbacks.init_delegate = mini_init_delegate;
3827 #define JIT_INVOKE_WORKS
3828 #ifdef JIT_INVOKE_WORKS
3829 callbacks.runtime_invoke = mono_jit_runtime_invoke;
3831 #define JIT_TRAMPOLINES_WORK
3832 #ifdef JIT_TRAMPOLINES_WORK
3833 callbacks.compile_method = mono_jit_compile_method;
3834 callbacks.create_jump_trampoline = mono_create_jump_trampoline;
3835 callbacks.create_jit_trampoline = mono_create_jit_trampoline;
3836 callbacks.create_delegate_trampoline = mono_create_delegate_trampoline;
3837 callbacks.free_method = mono_jit_free_method;
3838 #ifndef DISABLE_REMOTING
3839 callbacks.create_remoting_trampoline = mono_jit_create_remoting_trampoline;
3843 mono_install_callbacks (&callbacks);
3845 memset (&ticallbacks, 0, sizeof (ticallbacks));
3846 ticallbacks.setup_async_callback = mono_setup_async_callback;
3847 ticallbacks.thread_state_init_from_sigctx = mono_thread_state_init_from_sigctx;
3848 ticallbacks.thread_state_init_from_handle = mono_thread_state_init_from_handle;
3849 ticallbacks.thread_state_init = mono_thread_state_init;
3852 mono_w32handle_init ();
3855 mono_thread_info_runtime_init (&ticallbacks);
3857 if (g_hasenv ("MONO_DEBUG")) {
3858 mini_parse_debug_options ();
3861 mono_code_manager_init ();
3863 memset (&code_manager_callbacks, 0, sizeof (code_manager_callbacks));
3864 #ifdef MONO_ARCH_HAVE_CODE_CHUNK_TRACKING
3865 code_manager_callbacks.chunk_new = code_manager_chunk_new;
3866 code_manager_callbacks.chunk_destroy = code_manager_chunk_destroy;
3868 mono_code_manager_install_callbacks (&code_manager_callbacks);
3872 mono_arch_cpu_init ();
3876 mono_unwind_init ();
3878 if (mini_get_debug_options ()->lldb || g_hasenv ("MONO_LLDB")) {
3879 mono_lldb_init ("");
3880 mono_dont_free_domains = TRUE;
3883 #ifdef XDEBUG_ENABLED
3884 char *mono_xdebug = g_getenv ("MONO_XDEBUG");
3886 mono_xdebug_init (mono_xdebug);
3887 g_free (mono_xdebug);
3888 /* So methods for multiple domains don't have the same address */
3889 mono_dont_free_domains = TRUE;
3890 mono_using_xdebug = TRUE;
3891 } else if (mini_get_debug_options ()->gdb) {
3892 mono_xdebug_init ((char*)"gdb");
3893 mono_dont_free_domains = TRUE;
3894 mono_using_xdebug = TRUE;
3899 if (mono_use_llvm) {
3900 if (!mono_llvm_load (NULL)) {
3901 mono_use_llvm = FALSE;
3902 fprintf (stderr, "Mono Warning: llvm support could not be loaded.\n");
3909 mono_trampolines_init ();
3911 if (default_opt & MONO_OPT_AOT)
3914 mono_debugger_agent_init ();
3916 #ifdef MONO_ARCH_GSHARED_SUPPORTED
3917 mono_set_generic_sharing_supported (TRUE);
3920 mono_thread_info_signals_init ();
3922 #ifndef MONO_CROSS_COMPILE
3923 mono_runtime_install_handlers ();
3925 mono_threads_install_cleanup (mini_thread_cleanup);
3927 #ifdef JIT_TRAMPOLINES_WORK
3928 mono_install_create_domain_hook (mini_create_jit_domain_info);
3929 mono_install_free_domain_hook (mini_free_jit_domain_info);
3931 mono_install_get_cached_class_info (mono_aot_get_cached_class_info);
3932 mono_install_get_class_from_name (mono_aot_get_class_from_name);
3933 mono_install_jit_info_find_in_aot (mono_aot_find_jit_info);
3935 mono_profiler_state.context_enable = mini_profiler_context_enable;
3936 mono_profiler_state.context_get_this = mini_profiler_context_get_this;
3937 mono_profiler_state.context_get_argument = mini_profiler_context_get_argument;
3938 mono_profiler_state.context_get_local = mini_profiler_context_get_local;
3939 mono_profiler_state.context_get_result = mini_profiler_context_get_result;
3940 mono_profiler_state.context_free_buffer = mini_profiler_context_free_buffer;
3942 if (profile_options)
3943 for (guint i = 0; i < profile_options->len; i++)
3944 mono_profiler_load ((const char *) g_ptr_array_index (profile_options, i));
3946 mono_profiler_started ();
3948 if (debug_options.collect_pagefault_stats)
3949 mono_aot_set_make_unreadable (TRUE);
3951 if (runtime_version)
3952 domain = mono_init_version (filename, runtime_version);
3954 domain = mono_init_from_assembly (filename, filename);
3956 if (mono_aot_only) {
3957 /* This helps catch code allocation requests */
3958 mono_code_manager_set_read_only (domain->code_mp);
3959 mono_marshal_use_aot_wrappers (TRUE);
3962 if (mono_llvm_only) {
3963 mono_install_imt_trampoline_builder (mono_llvmonly_get_imt_trampoline);
3964 mono_set_always_build_imt_trampolines (TRUE);
3965 } else if (mono_aot_only) {
3966 mono_install_imt_trampoline_builder (mono_aot_get_imt_trampoline);
3968 mono_install_imt_trampoline_builder (mono_arch_build_imt_trampoline);
3971 /*Init arch tls information only after the metadata side is inited to make sure we see dynamic appdomain tls keys*/
3972 mono_arch_finish_init ();
3976 /* This must come after mono_init () in the aot-only case */
3977 mono_exceptions_init ();
3979 /* This should come after mono_init () too */
3983 mono_create_helper_signatures ();
3986 register_jit_stats ();
3988 #define JIT_CALLS_WORK
3989 #ifdef JIT_CALLS_WORK
3990 /* Needs to be called here since register_jit_icall depends on it */
3991 mono_marshal_init ();
3993 mono_arch_register_lowlevel_calls ();
3997 mono_generic_sharing_init ();
4000 #ifdef MONO_ARCH_SIMD_INTRINSICS
4001 mono_simd_intrinsics_init ();
4004 mono_tasklets_init ();
4006 register_trampolines (domain);
4008 if (mono_compile_aot)
4010 * Avoid running managed code when AOT compiling, since the platform
4011 * might only support aot-only execution.
4013 mono_runtime_set_no_exec (TRUE);
4015 mono_mem_account_register_counters ();
4017 #define JIT_RUNTIME_WORKS
4018 #ifdef JIT_RUNTIME_WORKS
4019 mono_install_runtime_cleanup ((MonoDomainFunc)mini_cleanup);
4020 mono_runtime_init_checked (domain, mono_thread_start_cb, mono_thread_attach_cb, &error);
4021 mono_error_assert_ok (&error);
4022 mono_thread_attach (domain);
4023 MONO_PROFILER_RAISE (thread_name, (MONO_NATIVE_THREAD_ID_TO_UINT (mono_native_thread_id_get ()), "Main"));
4026 if (mono_profiler_sampling_enabled ())
4027 mono_runtime_setup_stat_profiler ();
4029 MONO_PROFILER_RAISE (runtime_initialized, ());
4031 MONO_VES_INIT_END ();
4037 register_icalls (void)
4039 mono_add_internal_call ("System.Diagnostics.StackFrame::get_frame_info",
4040 ves_icall_get_frame_info);
4041 mono_add_internal_call ("System.Diagnostics.StackTrace::get_trace",
4042 ves_icall_get_trace);
4043 mono_add_internal_call ("Mono.Runtime::mono_runtime_install_handlers",
4044 mono_runtime_install_handlers);
4045 mono_add_internal_call ("Mono.Runtime::mono_runtime_cleanup_handlers",
4046 mono_runtime_cleanup_handlers);
4048 #if defined(PLATFORM_ANDROID) || defined(TARGET_ANDROID)
4049 mono_add_internal_call ("System.Diagnostics.Debugger::Mono_UnhandledException_internal",
4050 mono_debugger_agent_unhandled_exception);
4054 * It's important that we pass `TRUE` as the last argument here, as
4055 * it causes the JIT to omit a wrapper for these icalls. If the JIT
4056 * *did* emit a wrapper, we'd be looking at infinite recursion since
4057 * the wrapper would call the icall which would call the wrapper and
4060 register_icall (mono_profiler_raise_method_enter, "mono_profiler_raise_method_enter", "void ptr ptr", TRUE);
4061 register_icall (mono_profiler_raise_method_leave, "mono_profiler_raise_method_leave", "void ptr ptr", TRUE);
4062 register_icall (mono_profiler_raise_method_tail_call, "mono_profiler_raise_method_tail_call", "void ptr ptr", TRUE);
4064 register_icall (mono_trace_enter_method, "mono_trace_enter_method", NULL, TRUE);
4065 register_icall (mono_trace_leave_method, "mono_trace_leave_method", NULL, TRUE);
4066 register_icall (mono_get_lmf_addr, "mono_get_lmf_addr", "ptr", TRUE);
4067 register_icall (mono_jit_thread_attach, "mono_jit_thread_attach", "ptr ptr", TRUE);
4068 register_icall (mono_jit_set_domain, "mono_jit_set_domain", "void ptr", TRUE);
4069 register_icall (mono_domain_get, "mono_domain_get", "ptr", TRUE);
4071 register_icall (mono_llvm_throw_exception, "mono_llvm_throw_exception", "void object", TRUE);
4072 register_icall (mono_llvm_rethrow_exception, "mono_llvm_rethrow_exception", "void object", TRUE);
4073 register_icall (mono_llvm_resume_exception, "mono_llvm_resume_exception", "void", TRUE);
4074 register_icall (mono_llvm_match_exception, "mono_llvm_match_exception", "int ptr int int", TRUE);
4075 register_icall (mono_llvm_clear_exception, "mono_llvm_clear_exception", NULL, TRUE);
4076 register_icall (mono_llvm_load_exception, "mono_llvm_load_exception", "object", TRUE);
4077 register_icall (mono_llvm_throw_corlib_exception, "mono_llvm_throw_corlib_exception", "void int", TRUE);
4078 #if defined(ENABLE_LLVM) && !defined(MONO_LLVM_LOADED)
4079 register_icall (mono_llvm_set_unhandled_exception_handler, "mono_llvm_set_unhandled_exception_handler", NULL, TRUE);
4081 // FIXME: This is broken
4082 register_icall (mono_debug_personality, "mono_debug_personality", "int int int ptr ptr ptr", TRUE);
4085 register_dyn_icall (mono_get_throw_exception (), "mono_arch_throw_exception", "void object", TRUE);
4086 register_dyn_icall (mono_get_rethrow_exception (), "mono_arch_rethrow_exception", "void object", TRUE);
4087 register_dyn_icall (mono_get_throw_corlib_exception (), "mono_arch_throw_corlib_exception", "void ptr", TRUE);
4088 register_icall (mono_thread_get_undeniable_exception, "mono_thread_get_undeniable_exception", "object", FALSE);
4089 register_icall (mono_thread_self_abort, "mono_thread_self_abort", "void", FALSE);
4090 register_icall (mono_thread_interruption_checkpoint, "mono_thread_interruption_checkpoint", "object", FALSE);
4091 register_icall (mono_thread_force_interruption_checkpoint_noraise, "mono_thread_force_interruption_checkpoint_noraise", "object", FALSE);
4093 if (mono_threads_is_coop_enabled ())
4094 register_icall (mono_threads_state_poll, "mono_threads_state_poll", "void", FALSE);
4096 #ifndef MONO_ARCH_NO_EMULATE_LONG_MUL_OPTS
4097 register_opcode_emulation (OP_LMUL, "__emul_lmul", "long long long", mono_llmult, "mono_llmult", FALSE);
4098 register_opcode_emulation (OP_LDIV, "__emul_ldiv", "long long long", mono_lldiv, "mono_lldiv", FALSE);
4099 register_opcode_emulation (OP_LDIV_UN, "__emul_ldiv_un", "long long long", mono_lldiv_un, "mono_lldiv_un", FALSE);
4100 register_opcode_emulation (OP_LREM, "__emul_lrem", "long long long", mono_llrem, "mono_llrem", FALSE);
4101 register_opcode_emulation (OP_LREM_UN, "__emul_lrem_un", "long long long", mono_llrem_un, "mono_llrem_un", FALSE);
4103 #if !defined(MONO_ARCH_NO_EMULATE_LONG_MUL_OPTS) || defined(MONO_ARCH_EMULATE_LONG_MUL_OVF_OPTS)
4104 register_opcode_emulation (OP_LMUL_OVF_UN, "__emul_lmul_ovf_un", "long long long", mono_llmult_ovf_un, "mono_llmult_ovf_un", FALSE);
4105 register_opcode_emulation (OP_LMUL_OVF, "__emul_lmul_ovf", "long long long", mono_llmult_ovf, "mono_llmult_ovf", FALSE);
4108 #ifndef MONO_ARCH_NO_EMULATE_LONG_SHIFT_OPS
4109 register_opcode_emulation (OP_LSHL, "__emul_lshl", "long long int32", mono_lshl, "mono_lshl", TRUE);
4110 register_opcode_emulation (OP_LSHR, "__emul_lshr", "long long int32", mono_lshr, "mono_lshr", TRUE);
4111 register_opcode_emulation (OP_LSHR_UN, "__emul_lshr_un", "long long int32", mono_lshr_un, "mono_lshr_un", TRUE);
4114 #if defined(MONO_ARCH_EMULATE_MUL_DIV) || defined(MONO_ARCH_EMULATE_DIV)
4115 register_opcode_emulation (OP_IDIV, "__emul_op_idiv", "int32 int32 int32", mono_idiv, "mono_idiv", FALSE);
4116 register_opcode_emulation (OP_IDIV_UN, "__emul_op_idiv_un", "int32 int32 int32", mono_idiv_un, "mono_idiv_un", FALSE);
4117 register_opcode_emulation (OP_IREM, "__emul_op_irem", "int32 int32 int32", mono_irem, "mono_irem", FALSE);
4118 register_opcode_emulation (OP_IREM_UN, "__emul_op_irem_un", "int32 int32 int32", mono_irem_un, "mono_irem_un", FALSE);
4121 #ifdef MONO_ARCH_EMULATE_MUL_DIV
4122 register_opcode_emulation (OP_IMUL, "__emul_op_imul", "int32 int32 int32", mono_imul, "mono_imul", TRUE);
4125 #if defined(MONO_ARCH_EMULATE_MUL_DIV) || defined(MONO_ARCH_EMULATE_MUL_OVF)
4126 register_opcode_emulation (OP_IMUL_OVF, "__emul_op_imul_ovf", "int32 int32 int32", mono_imul_ovf, "mono_imul_ovf", FALSE);
4127 register_opcode_emulation (OP_IMUL_OVF_UN, "__emul_op_imul_ovf_un", "int32 int32 int32", mono_imul_ovf_un, "mono_imul_ovf_un", FALSE);
4130 #if defined(MONO_ARCH_EMULATE_MUL_DIV) || defined(MONO_ARCH_SOFT_FLOAT_FALLBACK)
4131 register_opcode_emulation (OP_FDIV, "__emul_fdiv", "double double double", mono_fdiv, "mono_fdiv", FALSE);
4134 register_opcode_emulation (OP_FCONV_TO_U8, "__emul_fconv_to_u8", "ulong double", mono_fconv_u8, "mono_fconv_u8", FALSE);
4135 register_opcode_emulation (OP_RCONV_TO_U8, "__emul_rconv_to_u8", "ulong float", mono_rconv_u8, "mono_rconv_u8", FALSE);
4136 register_opcode_emulation (OP_FCONV_TO_U4, "__emul_fconv_to_u4", "uint32 double", mono_fconv_u4, "mono_fconv_u4", FALSE);
4137 register_opcode_emulation (OP_FCONV_TO_OVF_I8, "__emul_fconv_to_ovf_i8", "long double", mono_fconv_ovf_i8, "mono_fconv_ovf_i8", FALSE);
4138 register_opcode_emulation (OP_FCONV_TO_OVF_U8, "__emul_fconv_to_ovf_u8", "ulong double", mono_fconv_ovf_u8, "mono_fconv_ovf_u8", FALSE);
4139 register_opcode_emulation (OP_RCONV_TO_OVF_I8, "__emul_rconv_to_ovf_i8", "long float", mono_rconv_ovf_i8, "mono_rconv_ovf_i8", FALSE);
4140 register_opcode_emulation (OP_RCONV_TO_OVF_U8, "__emul_rconv_to_ovf_u8", "ulong float", mono_rconv_ovf_u8, "mono_rconv_ovf_u8", FALSE);
4143 #ifdef MONO_ARCH_EMULATE_FCONV_TO_I8
4144 register_opcode_emulation (OP_FCONV_TO_I8, "__emul_fconv_to_i8", "long double", mono_fconv_i8, "mono_fconv_i8", FALSE);
4145 register_opcode_emulation (OP_RCONV_TO_I8, "__emul_rconv_to_i8", "long float", mono_rconv_i8, "mono_rconv_i8", FALSE);
4148 #ifdef MONO_ARCH_EMULATE_CONV_R8_UN
4149 register_opcode_emulation (OP_ICONV_TO_R_UN, "__emul_iconv_to_r_un", "double int32", mono_conv_to_r8_un, "mono_conv_to_r8_un", FALSE);
4151 #ifdef MONO_ARCH_EMULATE_LCONV_TO_R8
4152 register_opcode_emulation (OP_LCONV_TO_R8, "__emul_lconv_to_r8", "double long", mono_lconv_to_r8, "mono_lconv_to_r8", FALSE);
4154 #ifdef MONO_ARCH_EMULATE_LCONV_TO_R4
4155 register_opcode_emulation (OP_LCONV_TO_R4, "__emul_lconv_to_r4", "float long", mono_lconv_to_r4, "mono_lconv_to_r4", FALSE);
4157 #ifdef MONO_ARCH_EMULATE_LCONV_TO_R8_UN
4158 register_opcode_emulation (OP_LCONV_TO_R_UN, "__emul_lconv_to_r8_un", "double long", mono_lconv_to_r8_un, "mono_lconv_to_r8_un", FALSE);
4160 #ifdef MONO_ARCH_EMULATE_FREM
4161 register_opcode_emulation (OP_FREM, "__emul_frem", "double double double", fmod, "fmod", FALSE);
4162 register_opcode_emulation (OP_RREM, "__emul_rrem", "float float float", fmodf, "fmodf", FALSE);
4165 #ifdef MONO_ARCH_SOFT_FLOAT_FALLBACK
4166 if (mono_arch_is_soft_float ()) {
4167 register_opcode_emulation (OP_FSUB, "__emul_fsub", "double double double", mono_fsub, "mono_fsub", FALSE);
4168 register_opcode_emulation (OP_FADD, "__emul_fadd", "double double double", mono_fadd, "mono_fadd", FALSE);
4169 register_opcode_emulation (OP_FMUL, "__emul_fmul", "double double double", mono_fmul, "mono_fmul", FALSE);
4170 register_opcode_emulation (OP_FNEG, "__emul_fneg", "double double", mono_fneg, "mono_fneg", FALSE);
4171 register_opcode_emulation (OP_ICONV_TO_R8, "__emul_iconv_to_r8", "double int32", mono_conv_to_r8, "mono_conv_to_r8", FALSE);
4172 register_opcode_emulation (OP_ICONV_TO_R4, "__emul_iconv_to_r4", "double int32", mono_conv_to_r4, "mono_conv_to_r4", FALSE);
4173 register_opcode_emulation (OP_FCONV_TO_R4, "__emul_fconv_to_r4", "double double", mono_fconv_r4, "mono_fconv_r4", FALSE);
4174 register_opcode_emulation (OP_FCONV_TO_I1, "__emul_fconv_to_i1", "int8 double", mono_fconv_i1, "mono_fconv_i1", FALSE);
4175 register_opcode_emulation (OP_FCONV_TO_I2, "__emul_fconv_to_i2", "int16 double", mono_fconv_i2, "mono_fconv_i2", FALSE);
4176 register_opcode_emulation (OP_FCONV_TO_I4, "__emul_fconv_to_i4", "int32 double", mono_fconv_i4, "mono_fconv_i4", FALSE);
4177 register_opcode_emulation (OP_FCONV_TO_U1, "__emul_fconv_to_u1", "uint8 double", mono_fconv_u1, "mono_fconv_u1", FALSE);
4178 register_opcode_emulation (OP_FCONV_TO_U2, "__emul_fconv_to_u2", "uint16 double", mono_fconv_u2, "mono_fconv_u2", FALSE);
4180 #if SIZEOF_VOID_P == 4
4181 register_opcode_emulation (OP_FCONV_TO_I, "__emul_fconv_to_i", "int32 double", mono_fconv_i4, "mono_fconv_i4", FALSE);
4184 register_opcode_emulation (OP_FBEQ, "__emul_fcmp_eq", "uint32 double double", mono_fcmp_eq, "mono_fcmp_eq", FALSE);
4185 register_opcode_emulation (OP_FBLT, "__emul_fcmp_lt", "uint32 double double", mono_fcmp_lt, "mono_fcmp_lt", FALSE);
4186 register_opcode_emulation (OP_FBGT, "__emul_fcmp_gt", "uint32 double double", mono_fcmp_gt, "mono_fcmp_gt", FALSE);
4187 register_opcode_emulation (OP_FBLE, "__emul_fcmp_le", "uint32 double double", mono_fcmp_le, "mono_fcmp_le", FALSE);
4188 register_opcode_emulation (OP_FBGE, "__emul_fcmp_ge", "uint32 double double", mono_fcmp_ge, "mono_fcmp_ge", FALSE);
4189 register_opcode_emulation (OP_FBNE_UN, "__emul_fcmp_ne_un", "uint32 double double", mono_fcmp_ne_un, "mono_fcmp_ne_un", FALSE);
4190 register_opcode_emulation (OP_FBLT_UN, "__emul_fcmp_lt_un", "uint32 double double", mono_fcmp_lt_un, "mono_fcmp_lt_un", FALSE);
4191 register_opcode_emulation (OP_FBGT_UN, "__emul_fcmp_gt_un", "uint32 double double", mono_fcmp_gt_un, "mono_fcmp_gt_un", FALSE);
4192 register_opcode_emulation (OP_FBLE_UN, "__emul_fcmp_le_un", "uint32 double double", mono_fcmp_le_un, "mono_fcmp_le_un", FALSE);
4193 register_opcode_emulation (OP_FBGE_UN, "__emul_fcmp_ge_un", "uint32 double double", mono_fcmp_ge_un, "mono_fcmp_ge_un", FALSE);
4195 register_opcode_emulation (OP_FCEQ, "__emul_fcmp_ceq", "uint32 double double", mono_fceq, "mono_fceq", FALSE);
4196 register_opcode_emulation (OP_FCGT, "__emul_fcmp_cgt", "uint32 double double", mono_fcgt, "mono_fcgt", FALSE);
4197 register_opcode_emulation (OP_FCGT_UN, "__emul_fcmp_cgt_un", "uint32 double double", mono_fcgt_un, "mono_fcgt_un", FALSE);
4198 register_opcode_emulation (OP_FCLT, "__emul_fcmp_clt", "uint32 double double", mono_fclt, "mono_fclt", FALSE);
4199 register_opcode_emulation (OP_FCLT_UN, "__emul_fcmp_clt_un", "uint32 double double", mono_fclt_un, "mono_fclt_un", FALSE);
4201 register_icall (mono_fload_r4, "mono_fload_r4", "double ptr", FALSE);
4202 register_icall (mono_fstore_r4, "mono_fstore_r4", "void double ptr", FALSE);
4203 register_icall (mono_fload_r4_arg, "mono_fload_r4_arg", "uint32 double", FALSE);
4204 register_icall (mono_isfinite, "mono_isfinite", "uint32 double", FALSE);
4207 register_icall (mono_ckfinite, "mono_ckfinite", "double double", FALSE);
4209 #ifdef COMPRESSED_INTERFACE_BITMAP
4210 register_icall (mono_class_interface_match, "mono_class_interface_match", "uint32 ptr int32", TRUE);
4213 #if SIZEOF_REGISTER == 4
4214 register_opcode_emulation (OP_FCONV_TO_U, "__emul_fconv_to_u", "uint32 double", mono_fconv_u4, "mono_fconv_u4", TRUE);
4216 register_opcode_emulation (OP_FCONV_TO_U, "__emul_fconv_to_u", "ulong double", mono_fconv_u8, "mono_fconv_u8", TRUE);
4219 /* other jit icalls */
4220 register_icall (ves_icall_mono_delegate_ctor, "ves_icall_mono_delegate_ctor", "void object object ptr", FALSE);
4221 register_icall (mono_class_static_field_address , "mono_class_static_field_address",
4222 "ptr ptr ptr", FALSE);
4223 register_icall (mono_ldtoken_wrapper, "mono_ldtoken_wrapper", "ptr ptr ptr ptr", FALSE);
4224 register_icall (mono_ldtoken_wrapper_generic_shared, "mono_ldtoken_wrapper_generic_shared",
4225 "ptr ptr ptr ptr", FALSE);
4226 register_icall (mono_get_special_static_data, "mono_get_special_static_data", "ptr int", FALSE);
4227 register_icall (ves_icall_mono_ldstr, "ves_icall_mono_ldstr", "object ptr ptr int32", FALSE);
4228 register_icall (mono_helper_stelem_ref_check, "mono_helper_stelem_ref_check", "void object object", FALSE);
4229 register_icall (ves_icall_object_new, "ves_icall_object_new", "object ptr ptr", FALSE);
4230 register_icall (ves_icall_object_new_specific, "ves_icall_object_new_specific", "object ptr", FALSE);
4231 register_icall (ves_icall_array_new, "ves_icall_array_new", "object ptr ptr int32", FALSE);
4232 register_icall (ves_icall_array_new_specific, "ves_icall_array_new_specific", "object ptr int32", FALSE);
4233 register_icall (ves_icall_runtime_class_init, "ves_icall_runtime_class_init", "void ptr", FALSE);
4234 register_icall (mono_ldftn, "mono_ldftn", "ptr ptr", FALSE);
4235 register_icall (mono_ldvirtfn, "mono_ldvirtfn", "ptr object ptr", FALSE);
4236 register_icall (mono_ldvirtfn_gshared, "mono_ldvirtfn_gshared", "ptr object ptr", FALSE);
4237 register_icall (mono_helper_compile_generic_method, "mono_helper_compile_generic_method", "ptr object ptr ptr", FALSE);
4238 register_icall (mono_helper_ldstr, "mono_helper_ldstr", "object ptr int", FALSE);
4239 register_icall (mono_helper_ldstr_mscorlib, "mono_helper_ldstr_mscorlib", "object int", FALSE);
4240 register_icall (mono_helper_newobj_mscorlib, "mono_helper_newobj_mscorlib", "object int", FALSE);
4241 register_icall (mono_value_copy, "mono_value_copy", "void ptr ptr ptr", FALSE);
4242 register_icall (mono_object_castclass_unbox, "mono_object_castclass_unbox", "object object ptr", FALSE);
4243 register_icall (mono_break, "mono_break", NULL, TRUE);
4244 register_icall (mono_create_corlib_exception_0, "mono_create_corlib_exception_0", "object int", TRUE);
4245 register_icall (mono_create_corlib_exception_1, "mono_create_corlib_exception_1", "object int object", TRUE);
4246 register_icall (mono_create_corlib_exception_2, "mono_create_corlib_exception_2", "object int object object", TRUE);
4247 register_icall (mono_array_new_1, "mono_array_new_1", "object ptr int", FALSE);
4248 register_icall (mono_array_new_2, "mono_array_new_2", "object ptr int int", FALSE);
4249 register_icall (mono_array_new_3, "mono_array_new_3", "object ptr int int int", FALSE);
4250 register_icall (mono_array_new_4, "mono_array_new_4", "object ptr int int int int", FALSE);
4251 register_icall (mono_get_native_calli_wrapper, "mono_get_native_calli_wrapper", "ptr ptr ptr ptr", FALSE);
4252 register_icall (mono_resume_unwind, "mono_resume_unwind", "void", TRUE);
4253 register_icall (mono_gsharedvt_constrained_call, "mono_gsharedvt_constrained_call", "object ptr ptr ptr ptr ptr", FALSE);
4254 register_icall (mono_gsharedvt_value_copy, "mono_gsharedvt_value_copy", "void ptr ptr ptr", TRUE);
4256 //WARNING We do runtime selection here but the string *MUST* be to a fallback function that has same signature and behavior
4257 register_icall_no_wrapper (mono_gc_get_range_copy_func (), "mono_gc_wbarrier_range_copy", "void ptr ptr int");
4259 register_icall (mono_object_castclass_with_cache, "mono_object_castclass_with_cache", "object object ptr ptr", FALSE);
4260 register_icall (mono_object_isinst_with_cache, "mono_object_isinst_with_cache", "object object ptr ptr", FALSE);
4261 register_icall (mono_generic_class_init, "mono_generic_class_init", "void ptr", FALSE);
4262 register_icall (mono_fill_class_rgctx, "mono_fill_class_rgctx", "ptr ptr int", FALSE);
4263 register_icall (mono_fill_method_rgctx, "mono_fill_method_rgctx", "ptr ptr int", FALSE);
4265 register_icall (mono_debugger_agent_user_break, "mono_debugger_agent_user_break", "void", FALSE);
4267 register_icall (mono_aot_init_llvm_method, "mono_aot_init_llvm_method", "void ptr int", TRUE);
4268 register_icall (mono_aot_init_gshared_method_this, "mono_aot_init_gshared_method_this", "void ptr int object", TRUE);
4269 register_icall (mono_aot_init_gshared_method_mrgctx, "mono_aot_init_gshared_method_mrgctx", "void ptr int ptr", TRUE);
4270 register_icall (mono_aot_init_gshared_method_vtable, "mono_aot_init_gshared_method_vtable", "void ptr int ptr", TRUE);
4272 register_icall_no_wrapper (mono_resolve_iface_call_gsharedvt, "mono_resolve_iface_call_gsharedvt", "ptr object int ptr ptr");
4273 register_icall_no_wrapper (mono_resolve_vcall_gsharedvt, "mono_resolve_vcall_gsharedvt", "ptr object int ptr ptr");
4274 register_icall_no_wrapper (mono_resolve_generic_virtual_call, "mono_resolve_generic_virtual_call", "ptr ptr int ptr");
4275 register_icall_no_wrapper (mono_resolve_generic_virtual_iface_call, "mono_resolve_generic_virtual_iface_call", "ptr ptr int ptr");
4276 /* This needs a wrapper so it can have a preserveall cconv */
4277 register_icall (mono_init_vtable_slot, "mono_init_vtable_slot", "ptr ptr int", FALSE);
4278 register_icall (mono_llvmonly_init_delegate, "mono_llvmonly_init_delegate", "void object", TRUE);
4279 register_icall (mono_llvmonly_init_delegate_virtual, "mono_llvmonly_init_delegate_virtual", "void object object ptr", TRUE);
4280 register_icall (mono_get_assembly_object, "mono_get_assembly_object", "object ptr", TRUE);
4281 register_icall (mono_get_method_object, "mono_get_method_object", "object ptr", TRUE);
4282 register_icall (mono_throw_method_access, "mono_throw_method_access", "void ptr ptr", FALSE);
4283 register_icall_no_wrapper (mono_dummy_jit_icall, "mono_dummy_jit_icall", "void");
4285 register_icall_with_wrapper (mono_monitor_enter_internal, "mono_monitor_enter_internal", "void obj");
4286 register_icall_with_wrapper (mono_monitor_enter_v4_internal, "mono_monitor_enter_v4_internal", "void obj ptr");
4287 register_icall_no_wrapper (mono_monitor_enter_fast, "mono_monitor_enter_fast", "int obj");
4288 register_icall_no_wrapper (mono_monitor_enter_v4_fast, "mono_monitor_enter_v4_fast", "int obj ptr");
4291 register_icall (pthread_getspecific, "pthread_getspecific", "ptr ptr", TRUE);
4293 /* Register tls icalls */
4294 register_icall_no_wrapper (mono_tls_get_thread, "mono_tls_get_thread", "ptr");
4295 register_icall_no_wrapper (mono_tls_get_jit_tls, "mono_tls_get_jit_tls", "ptr");
4296 register_icall_no_wrapper (mono_tls_get_domain, "mono_tls_get_domain", "ptr");
4297 register_icall_no_wrapper (mono_tls_get_sgen_thread_info, "mono_tls_get_sgen_thread_info", "ptr");
4298 register_icall_no_wrapper (mono_tls_get_lmf_addr, "mono_tls_get_lmf_addr", "ptr");
4299 register_icall_no_wrapper (mono_tls_set_thread, "mono_tls_set_thread", "void ptr");
4300 register_icall_no_wrapper (mono_tls_set_jit_tls, "mono_tls_set_jit_tls", "void ptr");
4301 register_icall_no_wrapper (mono_tls_set_domain, "mono_tls_set_domain", "void ptr");
4302 register_icall_no_wrapper (mono_tls_set_sgen_thread_info, "mono_tls_set_sgen_thread_info", "void ptr");
4303 register_icall_no_wrapper (mono_tls_set_lmf_addr, "mono_tls_set_lmf_addr", "void ptr");
4306 MonoJitStats mono_jit_stats = {0};
4309 print_jit_stats (void)
4311 if (mono_jit_stats.enabled) {
4312 g_print ("Mono Jit statistics\n");
4313 g_print ("Max code size ratio: %.2f (%s)\n", mono_jit_stats.max_code_size_ratio/100.0,
4314 mono_jit_stats.max_ratio_method);
4315 g_print ("Biggest method: %ld (%s)\n", mono_jit_stats.biggest_method_size,
4316 mono_jit_stats.biggest_method);
4318 g_print ("Delegates created: %ld\n", mono_stats.delegate_creations);
4319 g_print ("Initialized classes: %ld\n", mono_stats.initialized_class_count);
4320 g_print ("Used classes: %ld\n", mono_stats.used_class_count);
4321 g_print ("Generic vtables: %ld\n", mono_stats.generic_vtable_count);
4322 g_print ("Methods: %ld\n", mono_stats.method_count);
4323 g_print ("Static data size: %ld\n", mono_stats.class_static_data_size);
4324 g_print ("VTable data size: %ld\n", mono_stats.class_vtable_size);
4325 g_print ("Mscorlib mempool size: %d\n", mono_mempool_get_allocated (mono_defaults.corlib->mempool));
4327 g_print ("\nInitialized classes: %ld\n", mono_stats.generic_class_count);
4328 g_print ("Inflated types: %ld\n", mono_stats.inflated_type_count);
4329 g_print ("Generics virtual invokes: %ld\n", mono_jit_stats.generic_virtual_invocations);
4331 g_print ("Sharable generic methods: %ld\n", mono_stats.generics_sharable_methods);
4332 g_print ("Unsharable generic methods: %ld\n", mono_stats.generics_unsharable_methods);
4333 g_print ("Shared generic methods: %ld\n", mono_stats.generics_shared_methods);
4334 g_print ("Shared vtype generic methods: %ld\n", mono_stats.gsharedvt_methods);
4336 g_print ("IMT tables size: %ld\n", mono_stats.imt_tables_size);
4337 g_print ("IMT number of tables: %ld\n", mono_stats.imt_number_of_tables);
4338 g_print ("IMT number of methods: %ld\n", mono_stats.imt_number_of_methods);
4339 g_print ("IMT used slots: %ld\n", mono_stats.imt_used_slots);
4340 g_print ("IMT colliding slots: %ld\n", mono_stats.imt_slots_with_collisions);
4341 g_print ("IMT max collisions: %ld\n", mono_stats.imt_max_collisions_in_slot);
4342 g_print ("IMT methods at max col: %ld\n", mono_stats.imt_method_count_when_max_collisions);
4343 g_print ("IMT trampolines size: %ld\n", mono_stats.imt_trampolines_size);
4345 g_print ("JIT info table inserts: %ld\n", mono_stats.jit_info_table_insert_count);
4346 g_print ("JIT info table removes: %ld\n", mono_stats.jit_info_table_remove_count);
4347 g_print ("JIT info table lookups: %ld\n", mono_stats.jit_info_table_lookup_count);
4349 g_free (mono_jit_stats.max_ratio_method);
4350 mono_jit_stats.max_ratio_method = NULL;
4351 g_free (mono_jit_stats.biggest_method);
4352 mono_jit_stats.biggest_method = NULL;
4357 mini_cleanup (MonoDomain *domain)
4359 if (mono_profiler_sampling_enabled ())
4360 mono_runtime_shutdown_stat_profiler ();
4362 MONO_PROFILER_RAISE (runtime_shutdown_begin, ());
4365 cominterop_release_all_rcws ();
4368 #ifndef MONO_CROSS_COMPILE
4370 * mono_domain_finalize () needs to be called early since it needs the
4371 * execution engine still fully working (it may invoke managed finalizers).
4373 mono_domain_finalize (domain, 2000);
4376 /* This accesses metadata so needs to be called before runtime shutdown */
4379 #ifndef MONO_CROSS_COMPILE
4380 mono_runtime_cleanup (domain);
4383 mono_threadpool_cleanup ();
4385 MONO_PROFILER_RAISE (runtime_shutdown_end, ());
4387 mono_profiler_cleanup ();
4389 if (profile_options)
4390 g_ptr_array_free (profile_options, TRUE);
4392 free_jit_tls_data ((MonoJitTlsData *)mono_tls_get_jit_tls ());
4394 mono_icall_cleanup ();
4396 mono_runtime_cleanup_handlers ();
4398 #ifndef MONO_CROSS_COMPILE
4399 mono_domain_free (domain, TRUE);
4404 mono_llvm_cleanup ();
4407 mono_aot_cleanup ();
4409 mono_trampolines_cleanup ();
4411 mono_unwind_cleanup ();
4413 mono_code_manager_destroy (global_codeman);
4414 g_free (vtable_trampolines);
4416 mini_jit_cleanup ();
4418 mono_tramp_info_cleanup ();
4420 mono_arch_cleanup ();
4422 mono_generic_sharing_cleanup ();
4426 mono_trace_cleanup ();
4428 mono_counters_dump (MONO_COUNTER_SECTION_MASK | MONO_COUNTER_MONOTONIC, stdout);
4430 if (mono_inject_async_exc_method)
4431 mono_method_desc_free (mono_inject_async_exc_method);
4433 mono_tls_free_keys ();
4435 mono_os_mutex_destroy (&jit_mutex);
4437 mono_code_manager_cleanup ();
4440 mono_w32handle_cleanup ();
4445 mono_set_defaults (int verbose_level, guint32 opts)
4447 mini_verbose = verbose_level;
4448 mono_set_optimizations (opts);
4452 mono_disable_optimizations (guint32 opts)
4454 default_opt &= ~opts;
4458 mono_set_optimizations (guint32 opts)
4461 default_opt_set = TRUE;
4462 #ifdef MONO_ARCH_GSHAREDVT_SUPPORTED
4463 mono_set_generic_sharing_vt_supported (mono_aot_only || ((default_opt & MONO_OPT_GSHAREDVT) != 0));
4466 mono_set_generic_sharing_vt_supported (TRUE);
4471 mono_set_verbose_level (guint32 level)
4473 mini_verbose = level;
4477 * mono_get_runtime_build_info:
4478 * The returned string is owned by the caller. The returned string
4479 * format is <code>VERSION (FULL_VERSION BUILD_DATE)</code> and build date is optional.
4480 * \returns the runtime version + build date in string format.
4483 mono_get_runtime_build_info (void)
4485 if (mono_build_date)
4486 return g_strdup_printf ("%s (%s %s)", VERSION, FULL_VERSION, mono_build_date);
4488 return g_strdup_printf ("%s (%s)", VERSION, FULL_VERSION);
4492 mono_precompile_assembly (MonoAssembly *ass, void *user_data)
4494 GHashTable *assemblies = (GHashTable*)user_data;
4495 MonoImage *image = mono_assembly_get_image (ass);
4496 MonoMethod *method, *invoke;
4499 if (g_hash_table_lookup (assemblies, ass))
4502 g_hash_table_insert (assemblies, ass, ass);
4504 if (mini_verbose > 0)
4505 printf ("PRECOMPILE: %s.\n", mono_image_get_filename (image));
4507 for (i = 0; i < mono_image_get_table_rows (image, MONO_TABLE_METHOD); ++i) {
4510 method = mono_get_method_checked (image, MONO_TOKEN_METHOD_DEF | (i + 1), NULL, NULL, &error);
4512 mono_error_cleanup (&error); /* FIXME don't swallow the error */
4515 if (method->flags & METHOD_ATTRIBUTE_ABSTRACT)
4517 if (method->is_generic || mono_class_is_gtd (method->klass))
4521 if (mini_verbose > 1) {
4522 char * desc = mono_method_full_name (method, TRUE);
4523 g_print ("Compiling %d %s\n", count, desc);
4526 mono_compile_method_checked (method, &error);
4527 if (!is_ok (&error)) {
4528 mono_error_cleanup (&error); /* FIXME don't swallow the error */
4531 if (strcmp (method->name, "Finalize") == 0) {
4532 invoke = mono_marshal_get_runtime_invoke (method, FALSE);
4533 mono_compile_method_checked (invoke, &error);
4534 mono_error_assert_ok (&error);
4536 #ifndef DISABLE_REMOTING
4537 if (mono_class_is_marshalbyref (method->klass) && mono_method_signature (method)->hasthis) {
4538 invoke = mono_marshal_get_remoting_invoke_with_check (method);
4539 mono_compile_method_checked (invoke, &error);
4540 mono_error_assert_ok (&error);
4545 /* Load and precompile referenced assemblies as well */
4546 for (i = 0; i < mono_image_get_table_rows (image, MONO_TABLE_ASSEMBLYREF); ++i) {
4547 mono_assembly_load_reference (image, i);
4548 if (image->references [i])
4549 mono_precompile_assembly (image->references [i], assemblies);
4553 void mono_precompile_assemblies ()
4555 GHashTable *assemblies = g_hash_table_new (NULL, NULL);
4557 mono_assembly_foreach ((GFunc)mono_precompile_assembly, assemblies);
4559 g_hash_table_destroy (assemblies);
4564 * Have to export this for AOT.
4567 mono_personality (void)
4570 g_assert_not_reached ();
4574 static MonoBreakPolicy
4575 always_insert_breakpoint (MonoMethod *method)
4577 return MONO_BREAK_POLICY_ALWAYS;
4580 static MonoBreakPolicyFunc break_policy_func = always_insert_breakpoint;
4583 * mono_set_break_policy:
4584 * \param policy_callback the new callback function
4586 * Allow embedders to decide whether to actually obey breakpoint instructions
4587 * (both break IL instructions and \c Debugger.Break method calls), for example
4588 * to not allow an app to be aborted by a perfectly valid IL opcode when executing
4589 * untrusted or semi-trusted code.
4591 * \p policy_callback will be called every time a break point instruction needs to
4592 * be inserted with the method argument being the method that calls \c Debugger.Break
4593 * or has the IL \c break instruction. The callback should return \c MONO_BREAK_POLICY_NEVER
4594 * if it wants the breakpoint to not be effective in the given method.
4595 * \c MONO_BREAK_POLICY_ALWAYS is the default.
4598 mono_set_break_policy (MonoBreakPolicyFunc policy_callback)
4600 if (policy_callback)
4601 break_policy_func = policy_callback;
4603 break_policy_func = always_insert_breakpoint;
4607 mini_should_insert_breakpoint (MonoMethod *method)
4609 switch (break_policy_func (method)) {
4610 case MONO_BREAK_POLICY_ALWAYS:
4612 case MONO_BREAK_POLICY_NEVER:
4614 case MONO_BREAK_POLICY_ON_DBG:
4615 g_warning ("mdb no longer supported");
4618 g_warning ("Incorrect value returned from break policy callback");
4623 // Custom handlers currently only implemented by Windows.
4626 mono_runtime_install_custom_handlers (const char *handlers)
4632 mono_runtime_install_custom_handlers_usage (void)
4635 "Custom Handlers:\n"
4636 " --handlers=HANDLERS Enable handler support, HANDLERS is a comma\n"
4637 " separated list of available handlers to install.\n"
4639 "No handlers supported on current platform.\n");
4641 #endif /* HOST_WIN32 */