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.h"
43 #include <mono/metadata/profiler-private.h>
44 #include <mono/metadata/mono-config.h>
45 #include <mono/metadata/environment.h>
46 #include <mono/metadata/mono-debug.h>
47 #include <mono/metadata/gc-internals.h>
48 #include <mono/metadata/threads-types.h>
49 #include <mono/metadata/mempool-internals.h>
50 #include <mono/metadata/attach.h>
51 #include <mono/metadata/runtime.h>
52 #include <mono/metadata/reflection-internals.h>
53 #include <mono/metadata/monitor.h>
54 #include <mono/utils/mono-math.h>
55 #include <mono/utils/mono-compiler.h>
56 #include <mono/utils/mono-counters.h>
57 #include <mono/utils/mono-error-internals.h>
58 #include <mono/utils/mono-logger-internals.h>
59 #include <mono/utils/mono-mmap.h>
60 #include <mono/utils/mono-path.h>
61 #include <mono/utils/mono-tls.h>
62 #include <mono/utils/mono-hwcap.h>
63 #include <mono/utils/dtrace.h>
64 #include <mono/utils/mono-signal-handler.h>
65 #include <mono/utils/mono-threads.h>
66 #include <mono/utils/mono-threads-coop.h>
67 #include <mono/utils/checked-build.h>
68 #include <mono/utils/mono-proclib.h>
69 #include <mono/metadata/w32handle.h>
70 #include <mono/metadata/threadpool.h>
73 #include "seq-points.h"
80 #include "jit-icalls.h"
83 #include "mini-llvm.h"
84 #include "debugger-agent.h"
87 #ifdef MONO_ARCH_LLVM_SUPPORTED
89 #include "mini-llvm-cpp.h"
94 #ifdef ENABLE_INTERPRETER
95 #include "interp/interp.h"
98 static guint32 default_opt = 0;
99 static gboolean default_opt_set = FALSE;
101 gboolean mono_compile_aot = FALSE;
102 /* If this is set, no code is generated dynamically, everything is taken from AOT files */
103 gboolean mono_aot_only = FALSE;
104 /* Same as mono_aot_only, but only LLVM compiled code is used, no trampolines */
105 gboolean mono_llvm_only = FALSE;
106 MonoAotMode mono_aot_mode = MONO_AOT_MODE_NONE;
108 const char *mono_build_date;
109 gboolean mono_do_signal_chaining;
110 gboolean mono_do_crash_chaining;
111 int mini_verbose = 0;
114 * This flag controls whenever the runtime uses LLVM for JIT compilation, and whenever
115 * it can load AOT code compiled by LLVM.
117 gboolean mono_use_llvm = FALSE;
119 gboolean mono_use_interpreter = FALSE;
121 #define mono_jit_lock() mono_os_mutex_lock (&jit_mutex)
122 #define mono_jit_unlock() mono_os_mutex_unlock (&jit_mutex)
123 static mono_mutex_t jit_mutex;
125 static MonoCodeManager *global_codeman;
127 MonoDebugOptions debug_options;
129 #ifdef VALGRIND_JIT_REGISTER_MAP
130 int valgrind_register;
132 GList* mono_aot_paths;
134 static gboolean mini_enable_profiler = FALSE;
135 static char* mini_profiler_options = NULL;
137 static GSList *tramp_infos;
139 static void register_icalls (void);
141 static gboolean mini_profiler_enabled (void) { return mini_enable_profiler; }
142 static const char* mini_profiler_get_options (void) { return mini_profiler_options; }
145 mono_running_on_valgrind (void)
148 if (RUNNING_ON_VALGRIND){
149 #ifdef VALGRIND_JIT_REGISTER_MAP
150 valgrind_register = TRUE;
164 find_tramp (gpointer key, gpointer value, gpointer user_data)
166 FindTrampUserData *ud = (FindTrampUserData*)user_data;
169 ud->method = (MonoMethod*)key;
173 G_GNUC_UNUSED static char*
174 get_method_from_ip (void *ip)
180 MonoDomain *domain = mono_domain_get ();
181 MonoDebugSourceLocation *location;
182 FindTrampUserData user_data;
185 domain = mono_get_root_domain ();
187 ji = mono_jit_info_table_find_internal (domain, (char *)ip, TRUE, TRUE);
190 user_data.method = NULL;
191 mono_domain_lock (domain);
192 g_hash_table_foreach (domain_jit_info (domain)->jit_trampoline_hash, find_tramp, &user_data);
193 mono_domain_unlock (domain);
194 if (user_data.method) {
195 char *mname = mono_method_full_name (user_data.method, TRUE);
196 res = g_strdup_printf ("<%p - JIT trampoline for %s>", ip, mname);
202 } else if (ji->is_trampoline) {
203 res = g_strdup_printf ("<%p - %s trampoline>", ip, ((MonoTrampInfo*)ji->d.tramp_info)->name);
207 method = jinfo_get_method (ji);
208 method_name = mono_method_full_name (method, TRUE);
209 /* FIXME: unused ? */
210 location = mono_debug_lookup_source_location (method, (guint32)((guint8*)ip - (guint8*)ji->code_start), domain);
212 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);
214 mono_debug_free_source_location (location);
215 g_free (method_name);
222 * \param ip an instruction pointer address
224 * This method is used from a debugger to get the name of the
225 * method at address \p ip. This routine is typically invoked from
226 * a debugger like this:
228 * (gdb) print mono_pmip ($pc)
230 * \returns the name of the method at address \p ip.
235 return get_method_from_ip (ip);
239 * mono_print_method_from_ip:
240 * \param ip an instruction pointer address
242 * This method is used from a debugger to get the name of the
243 * method at address \p ip.
245 * This prints the name of the method at address \p ip in the standard
246 * output. Unlike \c mono_pmip which returns a string, this routine
247 * prints the value on the standard output.
250 mono_print_method_from_ip (void *ip)
254 MonoDebugSourceLocation *source;
255 MonoDomain *domain = mono_domain_get ();
256 MonoDomain *target_domain = mono_domain_get ();
257 FindTrampUserData user_data;
258 MonoGenericSharingContext*gsctx;
259 const char *shared_type;
262 domain = mono_get_root_domain ();
263 ji = mini_jit_info_table_find_ext (domain, (char *)ip, TRUE, &target_domain);
264 if (ji && ji->is_trampoline) {
265 MonoTrampInfo *tinfo = (MonoTrampInfo *)ji->d.tramp_info;
267 printf ("IP %p is at offset 0x%x of trampoline '%s'.\n", ip, (int)((guint8*)ip - tinfo->code), tinfo->name);
273 user_data.method = NULL;
274 mono_domain_lock (domain);
275 g_hash_table_foreach (domain_jit_info (domain)->jit_trampoline_hash, find_tramp, &user_data);
276 mono_domain_unlock (domain);
278 if (user_data.method) {
279 char *mname = mono_method_full_name (user_data.method, TRUE);
280 printf ("IP %p is a JIT trampoline for %s\n", ip, mname);
285 g_print ("No method at %p\n", ip);
289 method = mono_method_full_name (jinfo_get_method (ji), TRUE);
290 source = mono_debug_lookup_source_location (jinfo_get_method (ji), (guint32)((guint8*)ip - (guint8*)ji->code_start), target_domain);
292 gsctx = mono_jit_info_get_generic_sharing_context (ji);
295 if (gsctx->is_gsharedvt)
296 shared_type = "gsharedvt ";
298 shared_type = "gshared ";
301 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);
304 g_print ("%s:%d\n", source->source_file, source->row);
307 mono_debug_free_source_location (source);
312 * mono_method_same_domain:
314 * Determine whenever two compiled methods are in the same domain, thus
315 * the address of the callee can be embedded in the caller.
317 gboolean mono_method_same_domain (MonoJitInfo *caller, MonoJitInfo *callee)
321 if (!caller || caller->is_trampoline || !callee || callee->is_trampoline)
325 * If the call was made from domain-neutral to domain-specific
326 * code, we can't patch the call site.
328 if (caller->domain_neutral && !callee->domain_neutral)
331 cmethod = jinfo_get_method (caller);
332 if ((cmethod->klass == mono_defaults.appdomain_class) &&
333 (strstr (cmethod->name, "InvokeInDomain"))) {
334 /* The InvokeInDomain methods change the current appdomain */
342 * mono_global_codeman_reserve:
344 * Allocate code memory from the global code manager.
346 void *mono_global_codeman_reserve (int size)
351 g_error ("Attempting to allocate from the global code manager while running in aot-only mode.\n");
353 if (!global_codeman) {
354 /* This can happen during startup */
355 global_codeman = mono_code_manager_new ();
356 return mono_code_manager_reserve (global_codeman, size);
360 ptr = mono_code_manager_reserve (global_codeman, size);
366 /* The callback shouldn't take any locks */
368 mono_global_codeman_foreach (MonoCodeManagerFunc func, void *user_data)
371 mono_code_manager_foreach (global_codeman, func, user_data);
375 #if defined(__native_client_codegen__) && defined(__native_client__)
379 #ifdef __native_client_gc__
380 __nacl_suspend_thread_if_needed();
383 #endif /* __native_client__ */
386 * mono_create_unwind_op:
388 * Create an unwind op with the given parameters.
391 mono_create_unwind_op (int when, int tag, int reg, int val)
393 MonoUnwindOp *op = g_new0 (MonoUnwindOp, 1);
404 mono_jump_info_token_new2 (MonoMemPool *mp, MonoImage *image, guint32 token, MonoGenericContext *context)
406 MonoJumpInfoToken *res = (MonoJumpInfoToken *)mono_mempool_alloc0 (mp, sizeof (MonoJumpInfoToken));
409 res->has_context = context != NULL;
411 memcpy (&res->context, context, sizeof (MonoGenericContext));
417 mono_jump_info_token_new (MonoMemPool *mp, MonoImage *image, guint32 token)
419 return mono_jump_info_token_new2 (mp, image, token, NULL);
423 * mono_tramp_info_create:
425 * Create a MonoTrampInfo structure from the arguments. This function assumes ownership
426 * of JI, and UNWIND_OPS.
429 mono_tramp_info_create (const char *name, guint8 *code, guint32 code_size, MonoJumpInfo *ji, GSList *unwind_ops)
431 MonoTrampInfo *info = g_new0 (MonoTrampInfo, 1);
433 info->name = g_strdup ((char*)name);
435 info->code_size = code_size;
437 info->unwind_ops = unwind_ops;
443 mono_tramp_info_free (MonoTrampInfo *info)
448 mono_free_unwind_info (info->unwind_ops);
449 if (info->owns_uw_info)
450 g_free (info->uw_info);
455 register_trampoline_jit_info (MonoDomain *domain, MonoTrampInfo *info)
459 ji = (MonoJitInfo *)mono_domain_alloc0 (domain, mono_jit_info_size ((MonoJitInfoFlags)0, 0, 0));
460 mono_jit_info_init (ji, NULL, info->code, info->code_size, (MonoJitInfoFlags)0, 0, 0);
461 ji->d.tramp_info = info;
462 ji->is_trampoline = TRUE;
464 ji->unwind_info = mono_cache_unwind_info (info->uw_info, info->uw_info_len);
466 mono_jit_info_table_add (domain, ji);
470 * mono_tramp_info_register:
472 * Remember INFO for use by xdebug, mono_print_method_from_ip (), jit maps, etc.
477 mono_tramp_info_register_internal (MonoTrampInfo *info, MonoDomain *domain, gboolean aot)
485 domain = mono_get_root_domain ();
487 copy = g_new0 (MonoTrampInfo, 1);
488 copy->code = info->code;
489 copy->code_size = info->code_size;
490 copy->name = g_strdup (info->name);
492 if (info->unwind_ops) {
493 copy->uw_info = mono_unwind_ops_encode (info->unwind_ops, ©->uw_info_len);
494 copy->owns_uw_info = TRUE;
496 /* Trampolines from aot have the unwind ops already encoded */
497 copy->uw_info = info->uw_info;
498 copy->uw_info_len = info->uw_info_len;
502 tramp_infos = g_slist_prepend (tramp_infos, copy);
505 mono_save_trampoline_xdebug_info (info);
506 mono_lldb_save_trampoline_info (info);
508 #ifdef MONO_ARCH_HAVE_UNWIND_TABLE
510 mono_arch_unwindinfo_install_tramp_unwind_info (info->unwind_ops, info->code, info->code_size);
513 /* Only register trampolines that have unwind infos */
514 if (mono_get_root_domain () && copy->uw_info)
515 register_trampoline_jit_info (domain, copy);
517 if (mono_jit_map_is_enabled ())
518 mono_emit_jit_tramp (info->code, info->code_size, info->name);
520 mono_tramp_info_free (info);
524 mono_tramp_info_register (MonoTrampInfo *info, MonoDomain *domain)
526 mono_tramp_info_register_internal (info, domain, FALSE);
530 mono_aot_tramp_info_register (MonoTrampInfo *info, MonoDomain *domain)
532 mono_tramp_info_register_internal (info, domain, TRUE);
536 mono_tramp_info_cleanup (void)
540 for (l = tramp_infos; l; l = l->next) {
541 MonoTrampInfo *info = (MonoTrampInfo *)l->data;
543 mono_tramp_info_free (info);
545 g_slist_free (tramp_infos);
548 /* Register trampolines created before the root domain was created in the jit info tables */
550 register_trampolines (MonoDomain *domain)
554 for (l = tramp_infos; l; l = l->next) {
555 MonoTrampInfo *info = (MonoTrampInfo *)l->data;
557 register_trampoline_jit_info (domain, info);
561 G_GNUC_UNUSED static void
567 * Runtime debugging tool, use if (debug_count ()) <x> else <y> to do <x> the first COUNT times, then do <y> afterwards.
568 * Set a breakpoint in break_count () to break the last time <x> is done.
570 G_GNUC_UNUSED gboolean
571 mono_debug_count (void)
573 static int count = 0;
574 static gboolean inited;
580 value = g_getenv ("COUNT");
587 int int_val = atoi (value);
590 if (count == int_val)
600 mono_icall_get_wrapper_full (MonoJitICallInfo* callinfo, gboolean do_compile)
605 gconstpointer trampoline;
606 MonoDomain *domain = mono_get_root_domain ();
607 gboolean check_exc = TRUE;
609 if (callinfo->wrapper)
610 return callinfo->wrapper;
612 if (callinfo->trampoline)
613 return callinfo->trampoline;
615 if (!strcmp (callinfo->name, "mono_thread_interruption_checkpoint"))
616 /* This icall is used to check for exceptions, so don't check in the wrapper */
619 name = g_strdup_printf ("__icall_wrapper_%s", callinfo->name);
620 wrapper = mono_marshal_get_icall_wrapper (callinfo->sig, name, callinfo->func, check_exc);
624 trampoline = mono_compile_method_checked (wrapper, &error);
625 mono_error_assert_ok (&error);
628 trampoline = mono_create_jit_trampoline (domain, wrapper, &error);
629 mono_error_assert_ok (&error);
630 trampoline = mono_create_ftnptr (domain, (gpointer)trampoline);
634 if (!callinfo->trampoline) {
635 mono_register_jit_icall_wrapper (callinfo, trampoline);
636 callinfo->trampoline = trampoline;
638 mono_loader_unlock ();
640 return callinfo->trampoline;
644 mono_icall_get_wrapper (MonoJitICallInfo* callinfo)
646 return mono_icall_get_wrapper_full (callinfo, FALSE);
649 static MonoJitDynamicMethodInfo*
650 mono_dynamic_code_hash_lookup (MonoDomain *domain, MonoMethod *method)
652 MonoJitDynamicMethodInfo *res;
654 if (domain_jit_info (domain)->dynamic_code_hash)
655 res = (MonoJitDynamicMethodInfo *)g_hash_table_lookup (domain_jit_info (domain)->dynamic_code_hash, method);
662 register_opcode_emulation (int opcode, const char *name, const char *sigstr, gpointer func, const char *symbol, gboolean no_throw)
665 mini_register_opcode_emulation (opcode, name, sigstr, func, symbol, no_throw);
667 MonoMethodSignature *sig = mono_create_icall_signature (sigstr);
669 g_assert (!sig->hasthis);
670 g_assert (sig->param_count < 3);
672 /* Opcode emulation functions are assumed to don't call mono_raise_exception () */
673 mono_register_jit_icall_full (func, name, sig, no_throw, TRUE, symbol);
678 * For JIT icalls implemented in C.
679 * NAME should be the same as the name of the C function whose address is FUNC.
680 * If @avoid_wrapper is TRUE, no wrapper is generated. This is for perf critical icalls which
681 * can't throw exceptions.
684 register_icall (gpointer func, const char *name, const char *sigstr, gboolean avoid_wrapper)
686 MonoMethodSignature *sig;
689 sig = mono_create_icall_signature (sigstr);
693 mono_register_jit_icall_full (func, name, sig, avoid_wrapper, FALSE, avoid_wrapper ? name : NULL);
697 register_icall_no_wrapper (gpointer func, const char *name, const char *sigstr)
699 MonoMethodSignature *sig;
702 sig = mono_create_icall_signature (sigstr);
706 mono_register_jit_icall_full (func, name, sig, TRUE, FALSE, name);
710 register_icall_with_wrapper (gpointer func, const char *name, const char *sigstr)
712 MonoMethodSignature *sig;
715 sig = mono_create_icall_signature (sigstr);
719 mono_register_jit_icall_full (func, name, sig, FALSE, FALSE, NULL);
723 register_dyn_icall (gpointer func, const char *name, const char *sigstr, gboolean save)
725 MonoMethodSignature *sig;
728 sig = mono_create_icall_signature (sigstr);
732 mono_register_jit_icall (func, name, sig, save);
738 MonoJitTlsData *jit_tls;
740 if ((jit_tls = mono_tls_get_jit_tls ()))
743 * We do not assert here because this function can be called from
744 * mini-gc.c on a thread that has not executed any managed code, yet
745 * (the thread object allocation can trigger a collection).
751 mono_get_lmf_addr (void)
753 return (MonoLMF **)mono_tls_get_lmf_addr ();
757 mono_set_lmf (MonoLMF *lmf)
759 (*mono_get_lmf_addr ()) = lmf;
763 mono_get_jit_tls (void)
765 return (MonoJitTlsData *)mono_tls_get_jit_tls ();
769 mono_set_jit_tls (MonoJitTlsData *jit_tls)
771 MonoThreadInfo *info;
773 mono_tls_set_jit_tls (jit_tls);
775 /* Save it into MonoThreadInfo so it can be accessed by mono_thread_state_init_from_handle () */
776 info = mono_thread_info_current ();
778 mono_thread_info_tls_set (info, TLS_KEY_JIT_TLS, jit_tls);
782 mono_set_lmf_addr (gpointer lmf_addr)
784 MonoThreadInfo *info;
786 mono_tls_set_lmf_addr (lmf_addr);
788 /* Save it into MonoThreadInfo so it can be accessed by mono_thread_state_init_from_handle () */
789 info = mono_thread_info_current ();
791 mono_thread_info_tls_set (info, TLS_KEY_LMF_ADDR, lmf_addr);
795 * mono_jit_thread_attach:
797 * Called by Xamarin.Mac and other products. Attach thread to runtime if
798 * needed and switch to @domain.
800 * @return the original domain which needs to be restored, or NULL.
803 mono_jit_thread_attach (MonoDomain *domain)
808 g_assert (!mono_threads_is_coop_enabled ());
811 /* Happens when called from AOTed code which is only used in the root domain. */
812 domain = mono_get_root_domain ();
817 attached = mono_tls_get_jit_tls () != NULL;
820 mono_thread_attach (domain);
823 mono_thread_set_state (mono_thread_internal_current (), ThreadState_Background);
826 orig = mono_domain_get ();
828 mono_domain_set (domain, TRUE);
830 return orig != domain ? orig : NULL;
834 * mono_jit_set_domain:
836 * Set domain to @domain if @domain is not null
839 mono_jit_set_domain (MonoDomain *domain)
841 g_assert (!mono_threads_is_coop_enabled ());
844 mono_domain_set (domain, TRUE);
849 * \param obj exception object
850 * Abort the thread, print exception information and stack trace
853 mono_thread_abort (MonoObject *obj)
855 /* MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_tls_get_jit_tls (); */
857 /* handle_remove should be eventually called for this thread, too
860 if ((mono_runtime_unhandled_exception_policy_get () == MONO_UNHANDLED_POLICY_LEGACY) ||
861 (obj->vtable->klass == mono_defaults.threadabortexception_class)) {
864 mono_invoke_unhandled_exception_hook (obj);
869 setup_jit_tls_data (gpointer stack_start, gpointer abort_func)
871 MonoJitTlsData *jit_tls;
874 jit_tls = (MonoJitTlsData *)mono_tls_get_jit_tls ();
878 jit_tls = g_new0 (MonoJitTlsData, 1);
880 jit_tls->abort_func = (void (*)(MonoObject *))abort_func;
881 jit_tls->end_of_stack = stack_start;
883 mono_set_jit_tls (jit_tls);
885 lmf = g_new0 (MonoLMF, 1);
886 MONO_ARCH_INIT_TOP_LMF_ENTRY (lmf);
888 jit_tls->first_lmf = lmf;
890 mono_set_lmf_addr (&jit_tls->lmf);
894 #ifdef MONO_ARCH_HAVE_TLS_INIT
895 mono_arch_tls_init ();
898 mono_setup_altstack (jit_tls);
904 free_jit_tls_data (MonoJitTlsData *jit_tls)
906 mono_arch_free_jit_tls_data (jit_tls);
907 mono_free_altstack (jit_tls);
909 g_free (jit_tls->first_lmf);
914 mono_thread_start_cb (intptr_t tid, gpointer stack_start, gpointer func)
916 MonoThreadInfo *thread;
917 void *jit_tls = setup_jit_tls_data (stack_start, mono_thread_abort);
918 thread = mono_thread_info_current_unchecked ();
920 thread->jit_data = jit_tls;
922 mono_arch_cpu_init ();
925 void (*mono_thread_attach_aborted_cb ) (MonoObject *obj) = NULL;
928 mono_thread_abort_dummy (MonoObject *obj)
930 if (mono_thread_attach_aborted_cb)
931 mono_thread_attach_aborted_cb (obj);
933 mono_thread_abort (obj);
937 mono_thread_attach_cb (intptr_t tid, gpointer stack_start)
939 MonoThreadInfo *thread;
940 void *jit_tls = setup_jit_tls_data (stack_start, mono_thread_abort_dummy);
941 thread = mono_thread_info_current_unchecked ();
943 thread->jit_data = jit_tls;
945 mono_arch_cpu_init ();
949 mini_thread_cleanup (MonoNativeThreadId tid)
951 MonoJitTlsData *jit_tls = NULL;
952 MonoThreadInfo *info;
954 info = mono_thread_info_current_unchecked ();
956 /* We can't clean up tls information if we are on another thread, it will clean up the wrong stuff
957 * It would be nice to issue a warning when this happens outside of the shutdown sequence. but it's
958 * not a trivial thing.
960 * The current offender is mono_thread_manage which cleanup threads from the outside.
962 if (info && mono_thread_info_get_tid (info) == tid) {
963 jit_tls = (MonoJitTlsData *)info->jit_data;
964 info->jit_data = NULL;
966 mono_set_jit_tls (NULL);
968 /* If we attach a thread but never call into managed land, we might never get an lmf.*/
969 if (mono_get_lmf ()) {
971 mono_set_lmf_addr (NULL);
974 info = mono_thread_info_lookup (tid);
976 jit_tls = (MonoJitTlsData *)info->jit_data;
977 info->jit_data = NULL;
979 mono_hazard_pointer_clear (mono_hazard_pointer_get (), 1);
983 free_jit_tls_data (jit_tls);
987 mono_patch_info_list_prepend (MonoJumpInfo *list, int ip, MonoJumpInfoType type, gconstpointer target)
989 MonoJumpInfo *ji = g_new0 (MonoJumpInfo, 1);
993 ji->data.target = target;
999 #if !defined(DISABLE_LOGGING) && !defined(DISABLE_JIT)
1001 static const char* const patch_info_str[] = {
1002 #define PATCH_INFO(a,b) "" #a,
1003 #include "patch-info.h"
1008 mono_ji_type_to_string (MonoJumpInfoType type)
1010 return patch_info_str [type];
1014 mono_print_ji (const MonoJumpInfo *ji)
1017 case MONO_PATCH_INFO_RGCTX_FETCH: {
1018 MonoJumpInfoRgctxEntry *entry = ji->data.rgctx_entry;
1020 printf ("[RGCTX_FETCH ");
1021 mono_print_ji (entry->data);
1022 printf (" - %s]", mono_rgctx_info_type_to_str (entry->info_type));
1025 case MONO_PATCH_INFO_METHODCONST: {
1026 char *s = mono_method_full_name (ji->data.method, TRUE);
1027 printf ("[METHODCONST - %s]", s);
1031 case MONO_PATCH_INFO_INTERNAL_METHOD: {
1032 printf ("[INTERNAL_METHOD - %s]", ji->data.name);
1036 printf ("[%s]", patch_info_str [ji->type]);
1044 mono_ji_type_to_string (MonoJumpInfoType type)
1050 mono_print_ji (const MonoJumpInfo *ji)
1057 * mono_patch_info_dup_mp:
1059 * Make a copy of PATCH_INFO, allocating memory from the mempool MP.
1062 mono_patch_info_dup_mp (MonoMemPool *mp, MonoJumpInfo *patch_info)
1064 MonoJumpInfo *res = (MonoJumpInfo *)mono_mempool_alloc (mp, sizeof (MonoJumpInfo));
1065 memcpy (res, patch_info, sizeof (MonoJumpInfo));
1067 switch (patch_info->type) {
1068 case MONO_PATCH_INFO_RVA:
1069 case MONO_PATCH_INFO_LDSTR:
1070 case MONO_PATCH_INFO_TYPE_FROM_HANDLE:
1071 case MONO_PATCH_INFO_LDTOKEN:
1072 case MONO_PATCH_INFO_DECLSEC:
1073 res->data.token = (MonoJumpInfoToken *)mono_mempool_alloc (mp, sizeof (MonoJumpInfoToken));
1074 memcpy (res->data.token, patch_info->data.token, sizeof (MonoJumpInfoToken));
1076 case MONO_PATCH_INFO_SWITCH:
1077 res->data.table = (MonoJumpInfoBBTable *)mono_mempool_alloc (mp, sizeof (MonoJumpInfoBBTable));
1078 memcpy (res->data.table, patch_info->data.table, sizeof (MonoJumpInfoBBTable));
1079 res->data.table->table = (MonoBasicBlock **)mono_mempool_alloc (mp, sizeof (MonoBasicBlock*) * patch_info->data.table->table_size);
1080 memcpy (res->data.table->table, patch_info->data.table->table, sizeof (MonoBasicBlock*) * patch_info->data.table->table_size);
1082 case MONO_PATCH_INFO_RGCTX_FETCH:
1083 case MONO_PATCH_INFO_RGCTX_SLOT_INDEX:
1084 res->data.rgctx_entry = (MonoJumpInfoRgctxEntry *)mono_mempool_alloc (mp, sizeof (MonoJumpInfoRgctxEntry));
1085 memcpy (res->data.rgctx_entry, patch_info->data.rgctx_entry, sizeof (MonoJumpInfoRgctxEntry));
1086 res->data.rgctx_entry->data = mono_patch_info_dup_mp (mp, res->data.rgctx_entry->data);
1088 case MONO_PATCH_INFO_DELEGATE_TRAMPOLINE:
1089 res->data.del_tramp = (MonoDelegateClassMethodPair *)mono_mempool_alloc0 (mp, sizeof (MonoDelegateClassMethodPair));
1090 memcpy (res->data.del_tramp, patch_info->data.del_tramp, sizeof (MonoDelegateClassMethodPair));
1092 case MONO_PATCH_INFO_GSHAREDVT_CALL:
1093 res->data.gsharedvt = (MonoJumpInfoGSharedVtCall *)mono_mempool_alloc (mp, sizeof (MonoJumpInfoGSharedVtCall));
1094 memcpy (res->data.gsharedvt, patch_info->data.gsharedvt, sizeof (MonoJumpInfoGSharedVtCall));
1096 case MONO_PATCH_INFO_GSHAREDVT_METHOD: {
1097 MonoGSharedVtMethodInfo *info;
1098 MonoGSharedVtMethodInfo *oinfo;
1101 oinfo = patch_info->data.gsharedvt_method;
1102 info = (MonoGSharedVtMethodInfo *)mono_mempool_alloc (mp, sizeof (MonoGSharedVtMethodInfo));
1103 res->data.gsharedvt_method = info;
1104 memcpy (info, oinfo, sizeof (MonoGSharedVtMethodInfo));
1105 info->entries = (MonoRuntimeGenericContextInfoTemplate *)mono_mempool_alloc (mp, sizeof (MonoRuntimeGenericContextInfoTemplate) * info->count_entries);
1106 for (i = 0; i < oinfo->num_entries; ++i) {
1107 MonoRuntimeGenericContextInfoTemplate *otemplate = &oinfo->entries [i];
1108 MonoRuntimeGenericContextInfoTemplate *template_ = &info->entries [i];
1110 memcpy (template_, otemplate, sizeof (MonoRuntimeGenericContextInfoTemplate));
1112 //info->locals_types = mono_mempool_alloc0 (mp, info->nlocals * sizeof (MonoType*));
1113 //memcpy (info->locals_types, oinfo->locals_types, info->nlocals * sizeof (MonoType*));
1116 case MONO_PATCH_INFO_VIRT_METHOD: {
1117 MonoJumpInfoVirtMethod *info;
1118 MonoJumpInfoVirtMethod *oinfo;
1120 oinfo = patch_info->data.virt_method;
1121 info = (MonoJumpInfoVirtMethod *)mono_mempool_alloc0 (mp, sizeof (MonoJumpInfoVirtMethod));
1122 res->data.virt_method = info;
1123 memcpy (info, oinfo, sizeof (MonoJumpInfoVirtMethod));
1134 mono_patch_info_hash (gconstpointer data)
1136 const MonoJumpInfo *ji = (MonoJumpInfo*)data;
1139 case MONO_PATCH_INFO_RVA:
1140 case MONO_PATCH_INFO_LDSTR:
1141 case MONO_PATCH_INFO_LDTOKEN:
1142 case MONO_PATCH_INFO_DECLSEC:
1143 return (ji->type << 8) | ji->data.token->token;
1144 case MONO_PATCH_INFO_TYPE_FROM_HANDLE:
1145 return (ji->type << 8) | ji->data.token->token | (ji->data.token->has_context ? (gsize)ji->data.token->context.class_inst : 0);
1146 case MONO_PATCH_INFO_INTERNAL_METHOD:
1147 return (ji->type << 8) | g_str_hash (ji->data.name);
1148 case MONO_PATCH_INFO_VTABLE:
1149 case MONO_PATCH_INFO_CLASS:
1150 case MONO_PATCH_INFO_IID:
1151 case MONO_PATCH_INFO_ADJUSTED_IID:
1152 case MONO_PATCH_INFO_METHODCONST:
1153 case MONO_PATCH_INFO_METHOD:
1154 case MONO_PATCH_INFO_METHOD_JUMP:
1155 case MONO_PATCH_INFO_IMAGE:
1156 case MONO_PATCH_INFO_ICALL_ADDR:
1157 case MONO_PATCH_INFO_ICALL_ADDR_CALL:
1158 case MONO_PATCH_INFO_FIELD:
1159 case MONO_PATCH_INFO_SFLDA:
1160 case MONO_PATCH_INFO_SEQ_POINT_INFO:
1161 case MONO_PATCH_INFO_METHOD_RGCTX:
1162 case MONO_PATCH_INFO_SIGNATURE:
1163 case MONO_PATCH_INFO_METHOD_CODE_SLOT:
1164 case MONO_PATCH_INFO_AOT_JIT_INFO:
1165 case MONO_PATCH_INFO_GET_TLS_TRAMP:
1166 case MONO_PATCH_INFO_SET_TLS_TRAMP:
1167 return (ji->type << 8) | (gssize)ji->data.target;
1168 case MONO_PATCH_INFO_GSHAREDVT_CALL:
1169 return (ji->type << 8) | (gssize)ji->data.gsharedvt->method;
1170 case MONO_PATCH_INFO_RGCTX_FETCH:
1171 case MONO_PATCH_INFO_RGCTX_SLOT_INDEX: {
1172 MonoJumpInfoRgctxEntry *e = ji->data.rgctx_entry;
1174 return (ji->type << 8) | (gssize)e->method | (e->in_mrgctx) | e->info_type | mono_patch_info_hash (e->data);
1176 case MONO_PATCH_INFO_INTERRUPTION_REQUEST_FLAG:
1177 case MONO_PATCH_INFO_MSCORLIB_GOT_ADDR:
1178 case MONO_PATCH_INFO_GC_CARD_TABLE_ADDR:
1179 case MONO_PATCH_INFO_GC_NURSERY_START:
1180 case MONO_PATCH_INFO_GC_NURSERY_BITS:
1181 case MONO_PATCH_INFO_GOT_OFFSET:
1182 case MONO_PATCH_INFO_GC_SAFE_POINT_FLAG:
1183 case MONO_PATCH_INFO_AOT_MODULE:
1184 case MONO_PATCH_INFO_JIT_THREAD_ATTACH:
1185 return (ji->type << 8);
1186 case MONO_PATCH_INFO_CASTCLASS_CACHE:
1187 return (ji->type << 8) | (ji->data.index);
1188 case MONO_PATCH_INFO_SWITCH:
1189 return (ji->type << 8) | ji->data.table->table_size;
1190 case MONO_PATCH_INFO_GSHAREDVT_METHOD:
1191 return (ji->type << 8) | (gssize)ji->data.gsharedvt_method->method;
1192 case MONO_PATCH_INFO_OBJC_SELECTOR_REF:
1193 /* Hash on the selector name */
1194 return g_str_hash (ji->data.target);
1195 case MONO_PATCH_INFO_DELEGATE_TRAMPOLINE:
1196 return (ji->type << 8) | (gsize)ji->data.del_tramp->klass | (gsize)ji->data.del_tramp->method | (gsize)ji->data.del_tramp->is_virtual;
1197 case MONO_PATCH_INFO_LDSTR_LIT:
1198 return g_str_hash (ji->data.target);
1199 case MONO_PATCH_INFO_VIRT_METHOD: {
1200 MonoJumpInfoVirtMethod *info = ji->data.virt_method;
1202 return (ji->type << 8) | (gssize)info->klass | (gssize)info->method;
1204 case MONO_PATCH_INFO_JIT_ICALL_ADDR:
1205 return (ji->type << 8) | g_str_hash (ji->data.target);
1206 case MONO_PATCH_INFO_GSHAREDVT_IN_WRAPPER:
1207 return (ji->type << 8) | mono_signature_hash (ji->data.sig);
1209 printf ("info type: %d\n", ji->type);
1210 mono_print_ji (ji); printf ("\n");
1211 g_assert_not_reached ();
1217 * mono_patch_info_equal:
1219 * This might fail to recognize equivalent patches, i.e. floats, so its only
1220 * usable in those cases where this is not a problem, i.e. sharing GOT slots
1224 mono_patch_info_equal (gconstpointer ka, gconstpointer kb)
1226 const MonoJumpInfo *ji1 = (MonoJumpInfo*)ka;
1227 const MonoJumpInfo *ji2 = (MonoJumpInfo*)kb;
1229 if (ji1->type != ji2->type)
1232 switch (ji1->type) {
1233 case MONO_PATCH_INFO_RVA:
1234 case MONO_PATCH_INFO_LDSTR:
1235 case MONO_PATCH_INFO_TYPE_FROM_HANDLE:
1236 case MONO_PATCH_INFO_LDTOKEN:
1237 case MONO_PATCH_INFO_DECLSEC:
1238 if ((ji1->data.token->image != ji2->data.token->image) ||
1239 (ji1->data.token->token != ji2->data.token->token) ||
1240 (ji1->data.token->has_context != ji2->data.token->has_context) ||
1241 (ji1->data.token->context.class_inst != ji2->data.token->context.class_inst) ||
1242 (ji1->data.token->context.method_inst != ji2->data.token->context.method_inst))
1245 case MONO_PATCH_INFO_INTERNAL_METHOD:
1246 return g_str_equal (ji1->data.name, ji2->data.name);
1247 case MONO_PATCH_INFO_RGCTX_FETCH:
1248 case MONO_PATCH_INFO_RGCTX_SLOT_INDEX: {
1249 MonoJumpInfoRgctxEntry *e1 = ji1->data.rgctx_entry;
1250 MonoJumpInfoRgctxEntry *e2 = ji2->data.rgctx_entry;
1252 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);
1254 case MONO_PATCH_INFO_GSHAREDVT_CALL: {
1255 MonoJumpInfoGSharedVtCall *c1 = ji1->data.gsharedvt;
1256 MonoJumpInfoGSharedVtCall *c2 = ji2->data.gsharedvt;
1258 return c1->sig == c2->sig && c1->method == c2->method;
1260 case MONO_PATCH_INFO_GSHAREDVT_METHOD:
1261 return ji1->data.gsharedvt_method->method == ji2->data.gsharedvt_method->method;
1262 case MONO_PATCH_INFO_DELEGATE_TRAMPOLINE:
1263 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;
1264 case MONO_PATCH_INFO_CASTCLASS_CACHE:
1265 return ji1->data.index == ji2->data.index;
1266 case MONO_PATCH_INFO_VIRT_METHOD:
1267 return ji1->data.virt_method->klass == ji2->data.virt_method->klass && ji1->data.virt_method->method == ji2->data.virt_method->method;
1268 case MONO_PATCH_INFO_JIT_ICALL_ADDR:
1269 if (ji1->data.target == ji2->data.target)
1271 return strcmp (ji1->data.target, ji2->data.target) == 0 ? 1 : 0;
1272 case MONO_PATCH_INFO_GSHAREDVT_IN_WRAPPER:
1273 return mono_metadata_signature_equal (ji1->data.sig, ji2->data.sig) ? 1 : 0;
1275 if (ji1->data.target != ji2->data.target)
1284 mono_resolve_patch_target (MonoMethod *method, MonoDomain *domain, guint8 *code, MonoJumpInfo *patch_info, gboolean run_cctors, MonoError *error)
1286 unsigned char *ip = patch_info->ip.i + code;
1287 gconstpointer target = NULL;
1291 switch (patch_info->type) {
1292 case MONO_PATCH_INFO_BB:
1294 * FIXME: This could be hit for methods without a prolog. Should use -1
1295 * but too much code depends on a 0 initial value.
1297 //g_assert (patch_info->data.bb->native_offset);
1298 target = patch_info->data.bb->native_offset + code;
1300 case MONO_PATCH_INFO_ABS:
1301 target = patch_info->data.target;
1303 case MONO_PATCH_INFO_LABEL:
1304 target = patch_info->data.inst->inst_c0 + code;
1306 case MONO_PATCH_INFO_IP:
1309 case MONO_PATCH_INFO_METHOD_REL:
1310 target = code + patch_info->data.offset;
1312 case MONO_PATCH_INFO_INTERNAL_METHOD: {
1313 MonoJitICallInfo *mi = mono_find_jit_icall_by_name (patch_info->data.name);
1315 g_warning ("unknown MONO_PATCH_INFO_INTERNAL_METHOD %s", patch_info->data.name);
1316 g_assert_not_reached ();
1318 target = mono_icall_get_wrapper (mi);
1321 case MONO_PATCH_INFO_JIT_ICALL_ADDR: {
1322 MonoJitICallInfo *mi = mono_find_jit_icall_by_name (patch_info->data.name);
1324 g_warning ("unknown MONO_PATCH_INFO_JIT_ICALL_ADDR %s", patch_info->data.name);
1325 g_assert_not_reached ();
1330 case MONO_PATCH_INFO_METHOD_JUMP:
1331 target = mono_create_jump_trampoline (domain, patch_info->data.method, FALSE, error);
1332 if (!mono_error_ok (error))
1335 case MONO_PATCH_INFO_METHOD:
1336 if (patch_info->data.method == method) {
1339 /* get the trampoline to the method from the domain */
1340 target = mono_create_jit_trampoline (domain, patch_info->data.method, error);
1341 if (!mono_error_ok (error))
1345 case MONO_PATCH_INFO_METHOD_CODE_SLOT: {
1348 mono_domain_lock (domain);
1349 if (!domain_jit_info (domain)->method_code_hash)
1350 domain_jit_info (domain)->method_code_hash = g_hash_table_new (NULL, NULL);
1351 code_slot = g_hash_table_lookup (domain_jit_info (domain)->method_code_hash, patch_info->data.method);
1353 code_slot = mono_domain_alloc0 (domain, sizeof (gpointer));
1354 g_hash_table_insert (domain_jit_info (domain)->method_code_hash, patch_info->data.method, code_slot);
1356 mono_domain_unlock (domain);
1360 case MONO_PATCH_INFO_GC_SAFE_POINT_FLAG:
1361 #if defined(__native_client_codegen__)
1362 target = (gpointer)&__nacl_thread_suspension_needed;
1364 g_assert (mono_threads_is_coop_enabled ());
1365 target = (gpointer)&mono_polling_required;
1368 case MONO_PATCH_INFO_SWITCH: {
1369 gpointer *jump_table;
1371 #if defined(__native_client__) && defined(__native_client_codegen__)
1372 /* This memory will leak, but we don't care if we're */
1373 /* not deleting JIT'd methods anyway */
1374 jump_table = g_malloc0 (sizeof(gpointer) * patch_info->data.table->table_size);
1376 if (method && method->dynamic) {
1377 jump_table = (void **)mono_code_manager_reserve (mono_dynamic_code_hash_lookup (domain, method)->code_mp, sizeof (gpointer) * patch_info->data.table->table_size);
1379 if (mono_aot_only) {
1380 jump_table = (void **)mono_domain_alloc (domain, sizeof (gpointer) * patch_info->data.table->table_size);
1382 jump_table = (void **)mono_domain_code_reserve (domain, sizeof (gpointer) * patch_info->data.table->table_size);
1387 for (i = 0; i < patch_info->data.table->table_size; i++) {
1388 jump_table [i] = code + GPOINTER_TO_INT (patch_info->data.table->table [i]);
1391 target = jump_table;
1394 case MONO_PATCH_INFO_METHODCONST:
1395 case MONO_PATCH_INFO_CLASS:
1396 case MONO_PATCH_INFO_IMAGE:
1397 case MONO_PATCH_INFO_FIELD:
1398 case MONO_PATCH_INFO_SIGNATURE:
1399 case MONO_PATCH_INFO_AOT_MODULE:
1400 target = patch_info->data.target;
1402 case MONO_PATCH_INFO_IID:
1403 mono_class_init (patch_info->data.klass);
1404 target = GUINT_TO_POINTER (patch_info->data.klass->interface_id);
1406 case MONO_PATCH_INFO_ADJUSTED_IID:
1407 mono_class_init (patch_info->data.klass);
1408 target = GUINT_TO_POINTER ((guint32)(-((patch_info->data.klass->interface_id + 1) * SIZEOF_VOID_P)));
1410 case MONO_PATCH_INFO_VTABLE:
1411 target = mono_class_vtable (domain, patch_info->data.klass);
1414 case MONO_PATCH_INFO_DELEGATE_TRAMPOLINE: {
1415 MonoDelegateClassMethodPair *del_tramp = patch_info->data.del_tramp;
1417 if (del_tramp->is_virtual)
1418 target = mono_create_delegate_virtual_trampoline (domain, del_tramp->klass, del_tramp->method);
1420 target = mono_create_delegate_trampoline_info (domain, del_tramp->klass, del_tramp->method);
1423 case MONO_PATCH_INFO_SFLDA: {
1424 MonoVTable *vtable = mono_class_vtable (domain, patch_info->data.field->parent);
1426 if (mono_class_field_is_special_static (patch_info->data.field)) {
1427 gpointer addr = NULL;
1429 mono_domain_lock (domain);
1430 if (domain->special_static_fields)
1431 addr = g_hash_table_lookup (domain->special_static_fields, patch_info->data.field);
1432 mono_domain_unlock (domain);
1438 if (!vtable->initialized && !mono_class_is_before_field_init (vtable->klass) && (method && mono_class_needs_cctor_run (vtable->klass, method)))
1439 /* Done by the generated code */
1443 if (!mono_runtime_class_init_full (vtable, error)) {
1448 target = (char*)mono_vtable_get_static_field_data (vtable) + patch_info->data.field->offset;
1451 case MONO_PATCH_INFO_RVA: {
1452 guint32 field_index = mono_metadata_token_index (patch_info->data.token->token);
1455 mono_metadata_field_info (patch_info->data.token->image, field_index - 1, NULL, &rva, NULL);
1456 target = mono_image_rva_map (patch_info->data.token->image, rva);
1459 case MONO_PATCH_INFO_R4:
1460 case MONO_PATCH_INFO_R8:
1461 target = patch_info->data.target;
1463 case MONO_PATCH_INFO_EXC_NAME:
1464 target = patch_info->data.name;
1466 case MONO_PATCH_INFO_LDSTR:
1468 mono_ldstr_checked (domain, patch_info->data.token->image,
1469 mono_metadata_token_index (patch_info->data.token->token), error);
1471 case MONO_PATCH_INFO_TYPE_FROM_HANDLE: {
1473 MonoClass *handle_class;
1475 handle = mono_ldtoken_checked (patch_info->data.token->image,
1476 patch_info->data.token->token, &handle_class, patch_info->data.token->has_context ? &patch_info->data.token->context : NULL, error);
1477 if (!mono_error_ok (error))
1479 mono_class_init (handle_class);
1480 mono_class_init (mono_class_from_mono_type ((MonoType *)handle));
1482 target = mono_type_get_object_checked (domain, (MonoType *)handle, error);
1483 if (!mono_error_ok (error))
1487 case MONO_PATCH_INFO_LDTOKEN: {
1489 MonoClass *handle_class;
1491 handle = mono_ldtoken_checked (patch_info->data.token->image,
1492 patch_info->data.token->token, &handle_class, patch_info->data.token->has_context ? &patch_info->data.token->context : NULL, error);
1493 if (!mono_error_ok (error))
1494 g_error ("Could not patch ldtoken due to %s", mono_error_get_message (error));
1495 mono_class_init (handle_class);
1500 case MONO_PATCH_INFO_DECLSEC:
1501 target = (mono_metadata_blob_heap (patch_info->data.token->image, patch_info->data.token->token) + 2);
1503 case MONO_PATCH_INFO_ICALL_ADDR:
1504 case MONO_PATCH_INFO_ICALL_ADDR_CALL:
1505 /* run_cctors == 0 -> AOT */
1506 if (patch_info->data.method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
1507 const char *exc_class;
1508 const char *exc_arg;
1511 target = mono_lookup_pinvoke_call (patch_info->data.method, &exc_class, &exc_arg);
1513 if (mono_aot_only) {
1514 mono_error_set_exception_instance (error, mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg));
1517 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));
1523 target = mono_lookup_internal_call (patch_info->data.method);
1525 if (!target && run_cctors)
1526 g_error ("Unregistered icall '%s'\n", mono_method_full_name (patch_info->data.method, TRUE));
1529 case MONO_PATCH_INFO_INTERRUPTION_REQUEST_FLAG:
1530 target = mono_thread_interruption_request_flag ();
1532 case MONO_PATCH_INFO_METHOD_RGCTX: {
1533 MonoVTable *vtable = mono_class_vtable (domain, patch_info->data.method->klass);
1536 target = mono_method_lookup_rgctx (vtable, mini_method_get_context (patch_info->data.method)->method_inst);
1539 case MONO_PATCH_INFO_RGCTX_SLOT_INDEX: {
1540 int slot = mini_get_rgctx_entry_slot (patch_info->data.rgctx_entry);
1542 target = GINT_TO_POINTER (MONO_RGCTX_SLOT_INDEX (slot));
1545 case MONO_PATCH_INFO_BB_OVF:
1546 case MONO_PATCH_INFO_EXC_OVF:
1547 case MONO_PATCH_INFO_GOT_OFFSET:
1548 case MONO_PATCH_INFO_NONE:
1550 case MONO_PATCH_INFO_RGCTX_FETCH: {
1551 int slot = mini_get_rgctx_entry_slot (patch_info->data.rgctx_entry);
1553 target = mono_create_rgctx_lazy_fetch_trampoline (slot);
1556 #ifdef MONO_ARCH_SOFT_DEBUG_SUPPORTED
1557 case MONO_PATCH_INFO_SEQ_POINT_INFO:
1559 /* AOT, not needed */
1562 target = mono_arch_get_seq_point_info (domain, code);
1565 case MONO_PATCH_INFO_GC_CARD_TABLE_ADDR: {
1566 int card_table_shift_bits;
1567 gpointer card_table_mask;
1569 target = mono_gc_get_card_table (&card_table_shift_bits, &card_table_mask);
1572 case MONO_PATCH_INFO_GC_NURSERY_START: {
1576 target = mono_gc_get_nursery (&shift_bits, &size);
1579 case MONO_PATCH_INFO_GC_NURSERY_BITS: {
1583 mono_gc_get_nursery (&shift_bits, &size);
1585 target = (gpointer)(mgreg_t)shift_bits;
1588 case MONO_PATCH_INFO_CASTCLASS_CACHE: {
1589 target = mono_domain_alloc0 (domain, sizeof (gpointer));
1592 case MONO_PATCH_INFO_OBJC_SELECTOR_REF: {
1596 case MONO_PATCH_INFO_LDSTR_LIT: {
1600 len = strlen ((const char *)patch_info->data.target);
1601 s = (char *)mono_domain_alloc0 (domain, len + 1);
1602 memcpy (s, patch_info->data.target, len);
1607 case MONO_PATCH_INFO_GSHAREDVT_IN_WRAPPER:
1608 target = mini_get_gsharedvt_wrapper (TRUE, NULL, patch_info->data.sig, NULL, -1, FALSE);
1610 case MONO_PATCH_INFO_GET_TLS_TRAMP:
1611 target = mono_tls_get_tls_getter (patch_info->data.index, FALSE);
1613 case MONO_PATCH_INFO_SET_TLS_TRAMP:
1614 target = mono_tls_get_tls_setter (patch_info->data.index, FALSE);
1616 case MONO_PATCH_INFO_JIT_THREAD_ATTACH: {
1617 MonoJitICallInfo *mi = mono_find_jit_icall_by_name ("mono_jit_thread_attach");
1623 g_assert_not_reached ();
1626 return (gpointer)target;
1630 mini_init_gsctx (MonoDomain *domain, MonoMemPool *mp, MonoGenericContext *context, MonoGenericSharingContext *gsctx)
1632 MonoGenericInst *inst;
1635 memset (gsctx, 0, sizeof (MonoGenericSharingContext));
1637 if (context && context->class_inst) {
1638 inst = context->class_inst;
1639 for (i = 0; i < inst->type_argc; ++i) {
1640 MonoType *type = inst->type_argv [i];
1642 if (mini_is_gsharedvt_gparam (type))
1643 gsctx->is_gsharedvt = TRUE;
1646 if (context && context->method_inst) {
1647 inst = context->method_inst;
1649 for (i = 0; i < inst->type_argc; ++i) {
1650 MonoType *type = inst->type_argv [i];
1652 if (mini_is_gsharedvt_gparam (type))
1653 gsctx->is_gsharedvt = TRUE;
1659 * LOCKING: Acquires the jit code hash lock.
1662 mini_lookup_method (MonoDomain *domain, MonoMethod *method, MonoMethod *shared)
1665 static gboolean inited = FALSE;
1666 static int lookups = 0;
1667 static int failed_lookups = 0;
1669 mono_domain_jit_code_hash_lock (domain);
1670 ji = (MonoJitInfo *)mono_internal_hash_table_lookup (&domain->jit_code_hash, method);
1671 if (!ji && shared) {
1672 /* Try generic sharing */
1673 ji = (MonoJitInfo *)mono_internal_hash_table_lookup (&domain->jit_code_hash, shared);
1674 if (ji && !ji->has_generic_jit_info)
1677 mono_counters_register ("Shared generic lookups", MONO_COUNTER_INT|MONO_COUNTER_GENERICS, &lookups);
1678 mono_counters_register ("Failed shared generic lookups", MONO_COUNTER_INT|MONO_COUNTER_GENERICS, &failed_lookups);
1686 mono_domain_jit_code_hash_unlock (domain);
1692 lookup_method (MonoDomain *domain, MonoMethod *method)
1697 ji = mini_lookup_method (domain, method, NULL);
1700 if (!mono_method_is_generic_sharable (method, FALSE))
1702 shared = mini_get_shared_method (method);
1703 ji = mini_lookup_method (domain, method, shared);
1710 mono_get_jit_info_from_method (MonoDomain *domain, MonoMethod *method)
1712 return lookup_method (domain, method);
1716 static FILE* perf_map_file;
1719 mono_enable_jit_map (void)
1721 if (!perf_map_file) {
1723 g_snprintf (name, sizeof (name), "/tmp/perf-%d.map", getpid ());
1725 perf_map_file = fopen (name, "w");
1730 mono_emit_jit_tramp (void *start, int size, const char *desc)
1733 fprintf (perf_map_file, "%llx %x %s\n", (long long unsigned int)(gsize)start, size, desc);
1737 mono_emit_jit_map (MonoJitInfo *jinfo)
1739 if (perf_map_file) {
1740 char *name = mono_method_full_name (jinfo_get_method (jinfo), TRUE);
1741 mono_emit_jit_tramp (jinfo->code_start, jinfo->code_size, name);
1747 mono_jit_map_is_enabled (void)
1749 return perf_map_file != NULL;
1755 no_gsharedvt_in_wrapper (void)
1757 g_assert_not_reached ();
1763 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.
1764 If the current thread is already JITing another method, don't wait as it might cause a deadlock.
1765 Dependency management in this case is too complex to justify implementing it.
1767 If there are no outstanding requests, the current thread is doing nothing and there are already mono_cpu_count threads JITing, go to sleep.
1770 Get rid of cctor invocations from within the JIT, it increases JIT duration and complicates things A LOT.
1771 Can we get rid of ref_count and use `done && threads_waiting == 0` as the equivalent of `ref_count == 0`?
1772 Reduce amount of dynamically allocated - possible once the JIT is no longer reentrant
1773 Maybe pool JitCompilationEntry, specially those with an inited cond var;
1778 int compilation_count; /* Number of threads compiling this method - This happens due to the JIT being reentrant */
1779 int ref_count; /* Number of threads using this JitCompilationEntry, roughtly 1 + threads_waiting */
1780 int threads_waiting; /* Number of threads waiting on this job */
1781 gboolean has_cond; /* True if @cond was initialized */
1782 gboolean done; /* True if the method finished JIT'ing */
1783 MonoCoopCond cond; /* Cond sleeping threads wait one */
1784 } JitCompilationEntry;
1787 GPtrArray *in_flight_methods; //JitCompilationEntry*
1789 } JitCompilationData;
1791 static JitCompilationData compilation_data;
1792 static int jit_methods_waited, jit_methods_multiple, jit_methods_overload, jit_spurious_wakeups;
1795 mini_jit_init_job_control (void)
1797 mono_coop_mutex_init (&compilation_data.lock);
1798 compilation_data.in_flight_methods = g_ptr_array_new ();
1802 lock_compilation_data (void)
1804 mono_coop_mutex_lock (&compilation_data.lock);
1808 unlock_compilation_data (void)
1810 mono_coop_mutex_unlock (&compilation_data.lock);
1813 static JitCompilationEntry*
1814 find_method (MonoMethod *method, MonoDomain *domain)
1817 for (i = 0; i < compilation_data.in_flight_methods->len; ++i){
1818 JitCompilationEntry *e = compilation_data.in_flight_methods->pdata [i];
1819 if (e->method == method && e->domain == domain)
1827 add_current_thread (MonoJitTlsData *jit_tls)
1829 ++jit_tls->active_jit_methods;
1833 unref_jit_entry (JitCompilationEntry *entry)
1836 if (entry->ref_count)
1838 if (entry->has_cond)
1839 mono_coop_cond_destroy (&entry->cond);
1844 * Returns true if this method waited successfully for another thread to JIT it
1847 wait_or_register_method_to_compile (MonoMethod *method, MonoDomain *domain)
1849 MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_tls_get_jit_tls ();
1850 JitCompilationEntry *entry;
1852 static gboolean inited;
1854 mono_counters_register ("JIT compile waited others", MONO_COUNTER_INT|MONO_COUNTER_JIT, &jit_methods_waited);
1855 mono_counters_register ("JIT compile 1+ jobs", MONO_COUNTER_INT|MONO_COUNTER_JIT, &jit_methods_multiple);
1856 mono_counters_register ("JIT compile overload wait", MONO_COUNTER_INT|MONO_COUNTER_JIT, &jit_methods_overload);
1857 mono_counters_register ("JIT compile spurious wakeups", MONO_COUNTER_INT|MONO_COUNTER_JIT, &jit_spurious_wakeups);
1861 lock_compilation_data ();
1863 if (!(entry = find_method (method, domain))) {
1864 entry = g_new0 (JitCompilationEntry, 1);
1865 entry->method = method;
1866 entry->domain = domain;
1867 entry->compilation_count = entry->ref_count = 1;
1868 g_ptr_array_add (compilation_data.in_flight_methods, entry);
1869 g_assert (find_method (method, domain) == entry);
1870 add_current_thread (jit_tls);
1872 unlock_compilation_data ();
1874 } else if (jit_tls->active_jit_methods > 0) {
1875 //We can't suspend the current thread if it's already JITing a method.
1876 //Dependency management is too compilated and we want to get rid of this anyways.
1877 ++entry->compilation_count;
1878 ++jit_methods_multiple;
1879 ++jit_tls->active_jit_methods;
1881 unlock_compilation_data ();
1884 ++jit_methods_waited;
1887 if (!entry->has_cond) {
1888 mono_coop_cond_init (&entry->cond);
1889 entry->has_cond = TRUE;
1893 ++entry->threads_waiting;
1895 g_assert (entry->has_cond);
1896 mono_coop_cond_wait (&entry->cond, &compilation_data.lock);
1897 --entry->threads_waiting;
1900 unref_jit_entry (entry);
1901 unlock_compilation_data ();
1904 ++jit_spurious_wakeups;
1911 unregister_method_for_compile (MonoMethod *method, MonoDomain *target_domain)
1913 MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_tls_get_jit_tls ();
1915 lock_compilation_data ();
1917 g_assert (jit_tls->active_jit_methods > 0);
1918 --jit_tls->active_jit_methods;
1920 JitCompilationEntry *entry = find_method (method, target_domain);
1921 g_assert (entry); // It would be weird to fail
1924 if (entry->threads_waiting) {
1925 g_assert (entry->has_cond);
1926 mono_coop_cond_broadcast (&entry->cond);
1929 if (--entry->compilation_count == 0) {
1930 g_ptr_array_remove (compilation_data.in_flight_methods, entry);
1931 unref_jit_entry (entry);
1934 unlock_compilation_data ();
1939 mono_jit_compile_method_with_opt (MonoMethod *method, guint32 opt, gboolean jit_only, MonoError *error)
1941 MonoDomain *target_domain, *domain = mono_domain_get ();
1943 gpointer code = NULL, p;
1945 MonoJitICallInfo *callinfo = NULL;
1946 WrapperInfo *winfo = NULL;
1950 #ifdef ENABLE_INTERPRETER
1951 if (mono_use_interpreter && !jit_only) {
1952 code = mono_interp_create_method_pointer (method, error);
1959 /* Should be handled by the caller */
1960 g_assert (!(method->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED));
1963 * ICALL wrappers are handled specially, since there is only one copy of them
1964 * shared by all appdomains.
1966 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE)
1967 winfo = mono_marshal_get_wrapper_info (method);
1968 if (winfo && winfo->subtype == WRAPPER_SUBTYPE_ICALL_WRAPPER) {
1969 callinfo = mono_find_jit_icall_by_addr (winfo->d.icall.func);
1970 g_assert (callinfo);
1972 /* Must be domain neutral since there is only one copy */
1973 opt |= MONO_OPT_SHARED;
1975 /* MONO_OPT_SHARED is no longer supported, we only use it for icall wrappers */
1976 opt &= ~MONO_OPT_SHARED;
1979 if (opt & MONO_OPT_SHARED)
1980 target_domain = mono_get_root_domain ();
1982 target_domain = domain;
1984 if (method->wrapper_type == MONO_WRAPPER_UNKNOWN) {
1985 WrapperInfo *info = mono_marshal_get_wrapper_info (method);
1988 if (info->subtype == WRAPPER_SUBTYPE_SYNCHRONIZED_INNER) {
1989 MonoGenericContext *ctx = NULL;
1990 if (method->is_inflated)
1991 ctx = mono_method_get_context (method);
1992 method = info->d.synchronized_inner.method;
1994 method = mono_class_inflate_generic_method_checked (method, ctx, error);
1995 g_assert (mono_error_ok (error)); /* FIXME don't swallow the error */
2001 info = lookup_method (target_domain, method);
2003 /* We can't use a domain specific method in another domain */
2004 if (! ((domain != target_domain) && !info->domain_neutral)) {
2007 mono_jit_stats.methods_lookups++;
2008 vtable = mono_class_vtable_full (domain, method->klass, error);
2012 if (!mono_runtime_class_init_full (vtable, error))
2014 return mono_create_ftnptr (target_domain, info->code_start);
2018 #ifdef MONO_USE_AOT_COMPILER
2019 if (opt & MONO_OPT_AOT) {
2020 MonoDomain *domain = mono_domain_get ();
2022 mono_class_init (method->klass);
2024 if ((code = mono_aot_get_method_checked (domain, method, error))) {
2027 if (mono_runtime_is_critical_method (method) || mono_gc_is_critical_method (method)) {
2029 * The suspend code needs to be able to lookup these methods by ip in async context,
2030 * so preload their jit info.
2032 MonoJitInfo *ji = mono_jit_info_table_find (domain, code);
2037 * In llvm-only mode, method might be a shared method, so we can't initialize its class.
2038 * This is not a problem, since it will be initialized when the method is first
2039 * called by init_method ().
2041 if (!mono_llvm_only) {
2042 vtable = mono_class_vtable (domain, method->klass);
2044 if (!mono_runtime_class_init_full (vtable, error))
2053 if (!code && mono_llvm_only) {
2054 if (method->wrapper_type == MONO_WRAPPER_UNKNOWN) {
2055 WrapperInfo *info = mono_marshal_get_wrapper_info (method);
2057 if (info->subtype == WRAPPER_SUBTYPE_GSHAREDVT_IN_SIG) {
2059 * These wrappers are only created for signatures which are in the program, but
2060 * sometimes we load methods too eagerly and have to create them even if they
2061 * will never be called.
2063 return no_gsharedvt_in_wrapper;
2069 if (wait_or_register_method_to_compile (method, target_domain))
2071 code = mono_jit_compile_method_inner (method, target_domain, opt, error);
2072 unregister_method_for_compile (method, target_domain);
2074 if (!mono_error_ok (error))
2077 if (!code && mono_llvm_only) {
2078 printf ("AOT method not found in llvmonly mode: %s\n", mono_method_full_name (method, 1));
2079 g_assert_not_reached ();
2085 if (method->wrapper_type == MONO_WRAPPER_WRITE_BARRIER || method->wrapper_type == MONO_WRAPPER_ALLOC) {
2089 * SGEN requires the JIT info for these methods to be registered, see is_ip_in_managed_allocator ().
2091 ji = mini_jit_info_table_find (mono_domain_get (), (char *)code, &d);
2095 p = mono_create_ftnptr (target_domain, code);
2098 /*mono_register_jit_icall_wrapper takes the loader lock, so we take it on the outside. */
2099 mono_loader_lock ();
2101 if (!callinfo->wrapper) {
2102 callinfo->wrapper = p;
2103 mono_register_jit_icall_wrapper (callinfo, p);
2106 mono_loader_unlock ();
2113 mono_jit_compile_method (MonoMethod *method, MonoError *error)
2117 code = mono_jit_compile_method_with_opt (method, mono_get_optimizations_for_method (method, default_opt), FALSE, error);
2122 * mono_jit_compile_method_jit_only:
2124 * Compile METHOD using the JIT/AOT, even in interpreted mode.
2127 mono_jit_compile_method_jit_only (MonoMethod *method, MonoError *error)
2131 code = mono_jit_compile_method_with_opt (method, mono_get_optimizations_for_method (method, default_opt), TRUE, error);
2135 #ifdef MONO_ARCH_HAVE_INVALIDATE_METHOD
2137 invalidated_delegate_trampoline (char *desc)
2139 g_error ("Unmanaged code called delegate of type %s which was already garbage collected.\n"
2140 "See http://www.mono-project.com/Diagnostic:Delegate for an explanation and ways to fix this.",
2146 * mono_jit_free_method:
2148 * Free all memory allocated by the JIT for METHOD.
2151 mono_jit_free_method (MonoDomain *domain, MonoMethod *method)
2153 MonoJitDynamicMethodInfo *ji;
2154 gboolean destroy = TRUE;
2155 GHashTableIter iter;
2156 MonoJumpList *jlist;
2158 g_assert (method->dynamic);
2160 mono_domain_lock (domain);
2161 ji = mono_dynamic_code_hash_lookup (domain, method);
2162 mono_domain_unlock (domain);
2167 mono_debug_remove_method (method, domain);
2168 mono_lldb_remove_method (domain, method, ji);
2170 mono_domain_lock (domain);
2171 g_hash_table_remove (domain_jit_info (domain)->dynamic_code_hash, method);
2172 mono_domain_jit_code_hash_lock (domain);
2173 mono_internal_hash_table_remove (&domain->jit_code_hash, method);
2174 mono_domain_jit_code_hash_unlock (domain);
2175 g_hash_table_remove (domain_jit_info (domain)->jump_trampoline_hash, method);
2177 /* requires the domain lock - took above */
2178 mono_conc_hashtable_remove (domain_jit_info (domain)->runtime_invoke_hash, method);
2180 /* Remove jump targets in this method */
2181 g_hash_table_iter_init (&iter, domain_jit_info (domain)->jump_target_hash);
2182 while (g_hash_table_iter_next (&iter, NULL, (void**)&jlist)) {
2183 GSList *tmp, *remove;
2186 for (tmp = jlist->list; tmp; tmp = tmp->next) {
2187 guint8 *ip = (guint8 *)tmp->data;
2189 if (ip >= (guint8*)ji->ji->code_start && ip < (guint8*)ji->ji->code_start + ji->ji->code_size)
2190 remove = g_slist_prepend (remove, tmp);
2192 for (tmp = remove; tmp; tmp = tmp->next) {
2193 jlist->list = g_slist_delete_link ((GSList *)jlist->list, (GSList *)tmp->data);
2195 g_slist_free (remove);
2197 mono_domain_unlock (domain);
2199 #ifdef MONO_ARCH_HAVE_INVALIDATE_METHOD
2200 if (debug_options.keep_delegates && method->wrapper_type == MONO_WRAPPER_NATIVE_TO_MANAGED) {
2202 * Instead of freeing the code, change it to call an error routine
2203 * so people can fix their code.
2205 char *type = mono_type_full_name (&method->klass->byval_arg);
2206 char *type_and_method = g_strdup_printf ("%s.%s", type, method->name);
2209 mono_arch_invalidate_method (ji->ji, invalidated_delegate_trampoline, type_and_method);
2215 * This needs to be done before freeing code_mp, since the code address is the
2216 * key in the table, so if we free the code_mp first, another thread can grab the
2217 * same code address and replace our entry in the table.
2219 mono_jit_info_table_remove (domain, ji->ji);
2222 mono_code_manager_destroy (ji->code_mp);
2227 mono_jit_find_compiled_method_with_jit_info (MonoDomain *domain, MonoMethod *method, MonoJitInfo **ji)
2229 MonoDomain *target_domain;
2232 if (default_opt & MONO_OPT_SHARED)
2233 target_domain = mono_get_root_domain ();
2235 target_domain = domain;
2237 info = lookup_method (target_domain, method);
2239 /* We can't use a domain specific method in another domain */
2240 if (! ((domain != target_domain) && !info->domain_neutral)) {
2241 mono_jit_stats.methods_lookups++;
2244 return info->code_start;
2253 static guint32 bisect_opt = 0;
2254 static GHashTable *bisect_methods_hash = NULL;
2257 mono_set_bisect_methods (guint32 opt, const char *method_list_filename)
2260 char method_name [2048];
2263 bisect_methods_hash = g_hash_table_new (g_str_hash, g_str_equal);
2264 g_assert (bisect_methods_hash);
2266 file = fopen (method_list_filename, "r");
2269 while (fgets (method_name, sizeof (method_name), file)) {
2270 size_t len = strlen (method_name);
2272 g_assert (method_name [len - 1] == '\n');
2273 method_name [len - 1] = 0;
2274 g_hash_table_insert (bisect_methods_hash, g_strdup (method_name), GINT_TO_POINTER (1));
2276 g_assert (feof (file));
2279 gboolean mono_do_single_method_regression = FALSE;
2280 guint32 mono_single_method_regression_opt = 0;
2281 MonoMethod *mono_current_single_method;
2282 GSList *mono_single_method_list;
2283 GHashTable *mono_single_method_hash;
2286 mono_get_optimizations_for_method (MonoMethod *method, guint32 default_opt)
2290 if (bisect_methods_hash) {
2291 char *name = mono_method_full_name (method, TRUE);
2292 void *res = g_hash_table_lookup (bisect_methods_hash, name);
2295 return default_opt | bisect_opt;
2297 if (!mono_do_single_method_regression)
2299 if (!mono_current_single_method) {
2300 if (!mono_single_method_hash)
2301 mono_single_method_hash = g_hash_table_new (g_direct_hash, g_direct_equal);
2302 if (!g_hash_table_lookup (mono_single_method_hash, method)) {
2303 g_hash_table_insert (mono_single_method_hash, method, method);
2304 mono_single_method_list = g_slist_prepend (mono_single_method_list, method);
2308 if (method == mono_current_single_method)
2309 return mono_single_method_regression_opt;
2314 mono_jit_find_compiled_method (MonoDomain *domain, MonoMethod *method)
2316 return mono_jit_find_compiled_method_with_jit_info (domain, method, NULL);
2321 gpointer compiled_method;
2322 gpointer runtime_invoke;
2324 MonoDynCallInfo *dyn_call_info;
2325 MonoClass *ret_box_class;
2326 MonoMethodSignature *sig;
2327 gboolean gsharedvt_invoke;
2328 gpointer *wrapper_arg;
2329 } RuntimeInvokeInfo;
2331 static RuntimeInvokeInfo*
2332 create_runtime_invoke_info (MonoDomain *domain, MonoMethod *method, gpointer compiled_method, gboolean callee_gsharedvt, MonoError *error)
2335 RuntimeInvokeInfo *info;
2337 info = g_new0 (RuntimeInvokeInfo, 1);
2338 info->compiled_method = compiled_method;
2339 if (mono_llvm_only && method->string_ctor)
2340 info->sig = mono_marshal_get_string_ctor_signature (method);
2342 info->sig = mono_method_signature (method);
2344 invoke = mono_marshal_get_runtime_invoke (method, FALSE);
2345 info->vtable = mono_class_vtable_full (domain, method->klass, error);
2346 if (!mono_error_ok (error))
2348 g_assert (info->vtable);
2350 MonoMethodSignature *sig = info->sig;
2354 * We want to avoid AOTing 1000s of runtime-invoke wrappers when running
2355 * in full-aot mode, so we use a slower, but more generic wrapper if
2356 * possible, built on top of the OP_DYN_CALL opcode provided by the JIT.
2358 #ifdef MONO_ARCH_DYN_CALL_SUPPORTED
2359 if (!mono_llvm_only && (mono_aot_only || debug_options.dyn_runtime_invoke)) {
2360 gboolean supported = TRUE;
2363 if (method->string_ctor)
2364 sig = mono_marshal_get_string_ctor_signature (method);
2366 for (i = 0; i < sig->param_count; ++i) {
2367 MonoType *t = sig->params [i];
2369 if (t->byref && t->type == MONO_TYPE_GENERICINST && mono_class_is_nullable (mono_class_from_mono_type (t)))
2373 if (mono_class_is_contextbound (method->klass) || !info->compiled_method)
2377 info->dyn_call_info = mono_arch_dyn_call_prepare (sig);
2381 ret_type = sig->ret;
2382 switch (ret_type->type) {
2383 case MONO_TYPE_VOID:
2395 case MONO_TYPE_BOOLEAN:
2396 case MONO_TYPE_CHAR:
2399 info->ret_box_class = mono_class_from_mono_type (ret_type);
2402 info->ret_box_class = mono_defaults.int_class;
2404 case MONO_TYPE_STRING:
2405 case MONO_TYPE_CLASS:
2406 case MONO_TYPE_ARRAY:
2407 case MONO_TYPE_SZARRAY:
2408 case MONO_TYPE_OBJECT:
2410 case MONO_TYPE_GENERICINST:
2411 if (!MONO_TYPE_IS_REFERENCE (ret_type))
2412 info->ret_box_class = mono_class_from_mono_type (ret_type);
2414 case MONO_TYPE_VALUETYPE:
2415 info->ret_box_class = mono_class_from_mono_type (ret_type);
2418 g_assert_not_reached ();
2422 if (!info->dyn_call_info) {
2423 if (mono_llvm_only) {
2424 #ifndef MONO_ARCH_GSHAREDVT_SUPPORTED
2425 g_assert_not_reached ();
2427 info->gsharedvt_invoke = TRUE;
2428 if (!callee_gsharedvt) {
2429 /* Invoke a gsharedvt out wrapper instead */
2430 MonoMethod *wrapper = mini_get_gsharedvt_out_sig_wrapper (sig);
2431 MonoMethodSignature *wrapper_sig = mini_get_gsharedvt_out_sig_wrapper_signature (sig->hasthis, sig->ret->type != MONO_TYPE_VOID, sig->param_count);
2433 info->wrapper_arg = g_malloc0 (2 * sizeof (gpointer));
2434 info->wrapper_arg [0] = mini_add_method_wrappers_llvmonly (method, info->compiled_method, FALSE, FALSE, &(info->wrapper_arg [1]));
2436 /* Pass has_rgctx == TRUE since the wrapper has an extra arg */
2437 invoke = mono_marshal_get_runtime_invoke_for_sig (wrapper_sig);
2438 g_free (wrapper_sig);
2440 info->compiled_method = mono_jit_compile_method (wrapper, error);
2441 if (!mono_error_ok (error)) {
2446 /* Gsharedvt methods can be invoked the same way */
2447 /* The out wrapper has the same signature as the compiled gsharedvt method */
2448 MonoMethodSignature *wrapper_sig = mini_get_gsharedvt_out_sig_wrapper_signature (sig->hasthis, sig->ret->type != MONO_TYPE_VOID, sig->param_count);
2450 info->wrapper_arg = mono_method_needs_static_rgctx_invoke (method, TRUE) ? mini_method_get_rgctx (method) : NULL;
2452 invoke = mono_marshal_get_runtime_invoke_for_sig (wrapper_sig);
2453 g_free (wrapper_sig);
2456 info->runtime_invoke = mono_jit_compile_method (invoke, error);
2457 if (!mono_error_ok (error)) {
2467 mono_llvmonly_runtime_invoke (MonoMethod *method, RuntimeInvokeInfo *info, void *obj, void **params, MonoObject **exc, MonoError *error)
2469 MonoMethodSignature *sig = info->sig;
2470 MonoDomain *domain = mono_domain_get ();
2471 MonoObject *(*runtime_invoke) (MonoObject *this_obj, void **params, MonoObject **exc, void* compiled_method);
2473 gpointer retval_ptr;
2474 guint8 retval [256];
2475 gpointer *param_refs;
2480 g_assert (info->gsharedvt_invoke);
2483 * Instead of invoking the method directly, we invoke a gsharedvt out wrapper.
2484 * The advantage of this is the gsharedvt out wrappers have a reduced set of
2485 * signatures, so we only have to generate runtime invoke wrappers for these
2487 * This code also handles invocation of gsharedvt methods directly, no
2488 * out wrappers are used in that case.
2490 args = (void **)g_alloca ((sig->param_count + sig->hasthis + 2) * sizeof (gpointer));
2491 param_refs = (gpointer*)g_alloca ((sig->param_count + sig->hasthis + 2) * sizeof (gpointer));
2494 * The runtime invoke wrappers expects pointers to primitive types, so have to
2498 args [pindex ++] = &obj;
2499 if (sig->ret->type != MONO_TYPE_VOID) {
2500 retval_ptr = (gpointer)&retval;
2501 args [pindex ++] = &retval_ptr;
2503 for (i = 0; i < sig->param_count; ++i) {
2504 MonoType *t = sig->params [i];
2506 if (t->type == MONO_TYPE_GENERICINST && mono_class_is_nullable (mono_class_from_mono_type (t))) {
2507 MonoClass *klass = mono_class_from_mono_type (t);
2508 guint8 *nullable_buf;
2511 size = mono_class_value_size (klass, NULL);
2512 nullable_buf = g_alloca (size);
2513 g_assert (nullable_buf);
2515 /* The argument pointed to by params [i] is either a boxed vtype or null */
2516 mono_nullable_init (nullable_buf, (MonoObject*)params [i], klass);
2517 params [i] = nullable_buf;
2520 if (!t->byref && (MONO_TYPE_IS_REFERENCE (t) || t->type == MONO_TYPE_PTR)) {
2521 param_refs [i] = params [i];
2522 params [i] = &(param_refs [i]);
2524 args [pindex ++] = ¶ms [i];
2526 /* The gsharedvt out wrapper has an extra argument which contains the method to call */
2527 args [pindex ++] = &info->wrapper_arg;
2529 runtime_invoke = (MonoObject *(*)(MonoObject *, void **, MonoObject **, void *))info->runtime_invoke;
2531 runtime_invoke (NULL, args, exc, info->compiled_method);
2535 if (sig->ret->type != MONO_TYPE_VOID && info->ret_box_class)
2536 return mono_value_box_checked (domain, info->ret_box_class, retval, error);
2538 return *(MonoObject**)retval;
2542 * mono_jit_runtime_invoke:
2543 * \param method: the method to invoke
2544 * \param obj: this pointer
2545 * \param params: array of parameter values.
2546 * \param exc: Set to the exception raised in the managed method.
2547 * \param error: error or caught exception object
2548 * If \p exc is NULL, \p error is thrown instead.
2549 * If coop is enabled, \p exc argument is ignored -
2550 * all exceptions are caught and propagated through \p error
2553 mono_jit_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObject **exc, MonoError *error)
2555 MonoMethod *invoke, *callee;
2556 MonoObject *(*runtime_invoke) (MonoObject *this_obj, void **params, MonoObject **exc, void* compiled_method);
2557 MonoDomain *domain = mono_domain_get ();
2558 MonoJitDomainInfo *domain_info;
2559 RuntimeInvokeInfo *info, *info2;
2560 MonoJitInfo *ji = NULL;
2561 gboolean callee_gsharedvt = FALSE;
2563 #ifdef ENABLE_INTERPRETER
2564 if (mono_use_interpreter)
2565 return mono_interp_runtime_invoke (method, obj, params, exc, error);
2570 if (obj == NULL && !(method->flags & METHOD_ATTRIBUTE_STATIC) && !method->string_ctor && (method->wrapper_type == 0)) {
2571 g_warning ("Ignoring invocation of an instance method on a NULL instance.\n");
2575 domain_info = domain_jit_info (domain);
2577 info = (RuntimeInvokeInfo *)mono_conc_hashtable_lookup (domain_info->runtime_invoke_hash, method);
2580 if (mono_security_core_clr_enabled ()) {
2582 * This might be redundant since mono_class_vtable () already does this,
2583 * but keep it just in case for moonlight.
2585 mono_class_setup_vtable (method->klass);
2586 if (mono_class_has_failure (method->klass)) {
2587 mono_error_set_for_class_failure (error, method->klass);
2589 *exc = (MonoObject*)mono_class_get_exception_for_failure (method->klass);
2594 gpointer compiled_method;
2597 if (method->klass->rank && (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) &&
2598 (method->iflags & METHOD_IMPL_ATTRIBUTE_NATIVE)) {
2600 * Array Get/Set/Address methods. The JIT implements them using inline code
2601 * inside the runtime invoke wrappers, so no need to compile them.
2603 if (mono_aot_only) {
2605 * Call a wrapper, since the runtime invoke wrapper was not generated.
2607 MonoMethod *wrapper;
2609 wrapper = mono_marshal_get_array_accessor_wrapper (method);
2610 invoke = mono_marshal_get_runtime_invoke (wrapper, FALSE);
2618 compiled_method = mono_jit_compile_method (callee, error);
2619 if (!compiled_method) {
2620 g_assert (!mono_error_ok (error));
2624 if (mono_llvm_only) {
2625 ji = mini_jit_info_table_find (mono_domain_get (), (char *)mono_get_addr_from_ftnptr (compiled_method), NULL);
2626 callee_gsharedvt = mini_jit_info_is_gsharedvt (ji);
2627 if (callee_gsharedvt)
2628 callee_gsharedvt = mini_is_gsharedvt_variable_signature (mono_method_signature (jinfo_get_method (ji)));
2631 if (!callee_gsharedvt)
2632 compiled_method = mini_add_method_trampoline (callee, compiled_method, mono_method_needs_static_rgctx_invoke (callee, TRUE), FALSE);
2634 compiled_method = NULL;
2637 info = create_runtime_invoke_info (domain, method, compiled_method, callee_gsharedvt, error);
2638 if (!mono_error_ok (error))
2641 mono_domain_lock (domain);
2642 info2 = (RuntimeInvokeInfo *)mono_conc_hashtable_insert (domain_info->runtime_invoke_hash, method, info);
2643 mono_domain_unlock (domain);
2651 * We need this here because mono_marshal_get_runtime_invoke can place
2652 * the helper method in System.Object and not the target class.
2654 if (!mono_runtime_class_init_full (info->vtable, error)) {
2656 *exc = (MonoObject*) mono_error_convert_to_exception (error);
2660 /* If coop is enabled, and the caller didn't ask for the exception to be caught separately,
2661 we always catch the exception and propagate it through the MonoError */
2662 gboolean catchExcInMonoError =
2663 (exc == NULL) && mono_threads_is_coop_enabled ();
2664 MonoObject *invoke_exc = NULL;
2665 if (catchExcInMonoError)
2668 /* The wrappers expect this to be initialized to NULL */
2672 #ifdef MONO_ARCH_DYN_CALL_SUPPORTED
2673 if (info->dyn_call_info) {
2674 MonoMethodSignature *sig = mono_method_signature (method);
2676 static RuntimeInvokeDynamicFunction dyn_runtime_invoke;
2679 guint8 retval [256];
2681 if (!dyn_runtime_invoke) {
2682 invoke = mono_marshal_get_runtime_invoke_dynamic ();
2683 dyn_runtime_invoke = (RuntimeInvokeDynamicFunction)mono_jit_compile_method (invoke, error);
2684 if (!mono_error_ok (error))
2688 /* Convert the arguments to the format expected by start_dyn_call () */
2689 args = (void **)g_alloca ((sig->param_count + sig->hasthis) * sizeof (gpointer));
2692 args [pindex ++] = &obj;
2693 for (i = 0; i < sig->param_count; ++i) {
2694 MonoType *t = sig->params [i];
2697 args [pindex ++] = ¶ms [i];
2698 } else if (MONO_TYPE_IS_REFERENCE (t) || t->type == MONO_TYPE_PTR) {
2699 args [pindex ++] = ¶ms [i];
2701 args [pindex ++] = params [i];
2705 //printf ("M: %s\n", mono_method_full_name (method, TRUE));
2707 mono_arch_start_dyn_call (info->dyn_call_info, (gpointer**)args, retval, buf, sizeof (buf));
2709 dyn_runtime_invoke (buf, exc, info->compiled_method);
2710 mono_arch_finish_dyn_call (info->dyn_call_info, buf);
2712 if (catchExcInMonoError && *exc != NULL) {
2713 mono_error_set_exception_instance (error, (MonoException*) *exc);
2717 if (info->ret_box_class)
2718 return mono_value_box_checked (domain, info->ret_box_class, retval, error);
2720 return *(MonoObject**)retval;
2726 if (mono_llvm_only) {
2727 result = mono_llvmonly_runtime_invoke (method, info, obj, params, exc, error);
2731 runtime_invoke = (MonoObject *(*)(MonoObject *, void **, MonoObject **, void *))info->runtime_invoke;
2733 result = runtime_invoke ((MonoObject *)obj, params, exc, info->compiled_method);
2735 if (catchExcInMonoError && *exc != NULL)
2736 mono_error_set_exception_instance (error, (MonoException*) *exc);
2745 typedef gpointer (*IMTTrampFunc) (gpointer *arg, MonoMethod *imt_method);
2748 * mini_llvmonly_initial_imt_tramp:
2750 * This function is called the first time a call is made through an IMT trampoline.
2751 * It should have the same signature as the mono_llvmonly_imt_tramp_... functions.
2754 mini_llvmonly_initial_imt_tramp (gpointer *arg, MonoMethod *imt_method)
2756 IMTTrampInfo *info = (IMTTrampInfo*)arg;
2761 mono_vtable_build_imt_slot (info->vtable, info->slot);
2763 imt = (gpointer*)info->vtable;
2764 imt -= MONO_IMT_SIZE;
2766 /* Return what the real IMT trampoline returns */
2767 ftndesc = imt [info->slot];
2770 if (func == (IMTTrampFunc)mini_llvmonly_initial_imt_tramp)
2771 /* Happens when the imt slot contains only a generic virtual method */
2773 return func ((gpointer *)ftndesc [1], imt_method);
2776 /* This is called indirectly through an imt slot. */
2778 mono_llvmonly_imt_tramp (gpointer *arg, MonoMethod *imt_method)
2782 /* arg points to an array created in mono_llvmonly_get_imt_trampoline () */
2783 while (arg [i] && arg [i] != imt_method)
2790 /* Optimized versions of mono_llvmonly_imt_trampoline () for different table sizes */
2792 mono_llvmonly_imt_tramp_1 (gpointer *arg, MonoMethod *imt_method)
2794 //g_assert (arg [0] == imt_method);
2799 mono_llvmonly_imt_tramp_2 (gpointer *arg, MonoMethod *imt_method)
2801 //g_assert (arg [0] == imt_method || arg [2] == imt_method);
2802 if (arg [0] == imt_method)
2809 mono_llvmonly_imt_tramp_3 (gpointer *arg, MonoMethod *imt_method)
2811 //g_assert (arg [0] == imt_method || arg [2] == imt_method || arg [4] == imt_method);
2812 if (arg [0] == imt_method)
2814 else if (arg [2] == imt_method)
2821 * A version of the imt trampoline used for generic virtual/variant iface methods.
2822 * Unlikely a normal imt trampoline, its possible that IMT_METHOD is not found
2823 * in the search table. The original JIT code had a 'fallback' trampoline it could
2824 * call, but we can't do that, so we just return NULL, and the compiled code
2828 mono_llvmonly_fallback_imt_tramp (gpointer *arg, MonoMethod *imt_method)
2832 while (arg [i] && arg [i] != imt_method)
2841 mono_llvmonly_get_imt_trampoline (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckItem **imt_entries, int count, gpointer fail_tramp)
2845 int i, index, real_count;
2846 gboolean virtual_generic = FALSE;
2849 * Create an array which is passed to the imt trampoline functions.
2850 * The array contains MonoMethod-function descriptor pairs, terminated by a NULL entry.
2854 for (i = 0; i < count; ++i) {
2855 MonoIMTCheckItem *item = imt_entries [i];
2857 if (item->is_equals)
2859 if (item->has_target_code)
2860 virtual_generic = TRUE;
2864 * Initialize all vtable entries reachable from this imt slot, so the compiled
2865 * code doesn't have to check it.
2867 for (i = 0; i < count; ++i) {
2868 MonoIMTCheckItem *item = imt_entries [i];
2871 if (!item->is_equals || item->has_target_code)
2873 vt_slot = item->value.vtable_slot;
2874 mono_init_vtable_slot (vtable, vt_slot);
2877 /* Save the entries into an array */
2878 buf = (void **)mono_domain_alloc (domain, (real_count + 1) * 2 * sizeof (gpointer));
2880 for (i = 0; i < count; ++i) {
2881 MonoIMTCheckItem *item = imt_entries [i];
2883 if (!item->is_equals)
2886 g_assert (item->key);
2887 buf [(index * 2)] = item->key;
2888 if (item->has_target_code)
2889 buf [(index * 2) + 1] = item->value.target_code;
2891 buf [(index * 2) + 1] = vtable->vtable [item->value.vtable_slot];
2894 buf [(index * 2)] = NULL;
2895 buf [(index * 2) + 1] = fail_tramp;
2898 * Return a function descriptor for a C function with 'buf' as its argument.
2899 * It will by called by JITted code.
2901 res = (void **)mono_domain_alloc (domain, 2 * sizeof (gpointer));
2902 switch (real_count) {
2904 res [0] = mono_llvmonly_imt_tramp_1;
2907 res [0] = mono_llvmonly_imt_tramp_2;
2910 res [0] = mono_llvmonly_imt_tramp_3;
2913 res [0] = mono_llvmonly_imt_tramp;
2916 if (virtual_generic || fail_tramp)
2917 res [0] = mono_llvmonly_fallback_imt_tramp;
2923 MONO_SIG_HANDLER_FUNC (, mono_sigfpe_signal_handler)
2925 MonoException *exc = NULL;
2927 MONO_SIG_HANDLER_INFO_TYPE *info = MONO_SIG_HANDLER_GET_INFO ();
2928 MONO_SIG_HANDLER_GET_CONTEXT;
2930 ji = mono_jit_info_table_find_internal (mono_domain_get (), (char *)mono_arch_ip_from_context (ctx), TRUE, TRUE);
2932 MONO_ENTER_GC_UNSAFE_UNBALANCED;
2934 #if defined(MONO_ARCH_HAVE_IS_INT_OVERFLOW)
2935 if (mono_arch_is_int_overflow (ctx, info))
2937 * The spec says this throws ArithmeticException, but MS throws the derived
2938 * OverflowException.
2940 exc = mono_get_exception_overflow ();
2942 exc = mono_get_exception_divide_by_zero ();
2944 exc = mono_get_exception_divide_by_zero ();
2948 if (!mono_do_crash_chaining && mono_chain_signal (MONO_SIG_HANDLER_PARAMS))
2951 mono_handle_native_crash ("SIGFPE", ctx, info);
2952 if (mono_do_crash_chaining) {
2953 mono_chain_signal (MONO_SIG_HANDLER_PARAMS);
2958 mono_arch_handle_exception (ctx, exc);
2961 MONO_EXIT_GC_UNSAFE_UNBALANCED;
2964 MONO_SIG_HANDLER_FUNC (, mono_sigill_signal_handler)
2966 MONO_SIG_HANDLER_INFO_TYPE *info = MONO_SIG_HANDLER_GET_INFO ();
2967 MONO_SIG_HANDLER_GET_CONTEXT;
2969 if (mono_runtime_get_no_exec ())
2973 mono_handle_native_crash ("SIGILL", ctx, info);
2974 if (mono_do_crash_chaining) {
2975 mono_chain_signal (MONO_SIG_HANDLER_PARAMS);
2979 g_assert_not_reached ();
2982 #if defined(MONO_ARCH_USE_SIGACTION) || defined(HOST_WIN32)
2983 #define HAVE_SIG_INFO
2986 MONO_SIG_HANDLER_FUNC (, mono_sigsegv_signal_handler)
2989 MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_tls_get_jit_tls ();
2990 gpointer fault_addr = NULL;
2991 #ifdef HAVE_SIG_INFO
2992 MONO_SIG_HANDLER_INFO_TYPE *info = MONO_SIG_HANDLER_GET_INFO ();
2996 MONO_SIG_HANDLER_GET_CONTEXT;
2998 #if defined(MONO_ARCH_SOFT_DEBUG_SUPPORTED) && defined(HAVE_SIG_INFO)
2999 if (mono_arch_is_single_step_event (info, ctx)) {
3000 mono_debugger_agent_single_step_event (ctx);
3002 } else if (mono_arch_is_breakpoint_event (info, ctx)) {
3003 mono_debugger_agent_breakpoint_hit (ctx);
3008 #if defined(HAVE_SIG_INFO)
3009 #if !defined(HOST_WIN32)
3010 fault_addr = info->si_addr;
3011 if (mono_aot_is_pagefault (info->si_addr)) {
3012 mono_aot_handle_pagefault (info->si_addr);
3017 /* The thread might no be registered with the runtime */
3018 if (!mono_domain_get () || !jit_tls) {
3019 if (!mono_do_crash_chaining && mono_chain_signal (MONO_SIG_HANDLER_PARAMS))
3021 mono_handle_native_crash ("SIGSEGV", ctx, info);
3022 if (mono_do_crash_chaining) {
3023 mono_chain_signal (MONO_SIG_HANDLER_PARAMS);
3029 ji = mono_jit_info_table_find_internal (mono_domain_get (), (char *)mono_arch_ip_from_context (ctx), TRUE, TRUE);
3031 #ifdef MONO_ARCH_SIGSEGV_ON_ALTSTACK
3032 if (mono_handle_soft_stack_ovf (jit_tls, ji, ctx, info, (guint8*)info->si_addr))
3035 #ifdef MONO_ARCH_HAVE_SIGCTX_TO_MONOCTX
3036 /* info->si_addr seems to be NULL on some kernels when handling stack overflows */
3037 fault_addr = info->si_addr;
3038 if (fault_addr == NULL) {
3041 mono_sigctx_to_monoctx (ctx, &mctx);
3043 fault_addr = MONO_CONTEXT_GET_SP (&mctx);
3047 if (jit_tls->stack_size &&
3048 ABS ((guint8*)fault_addr - ((guint8*)jit_tls->end_of_stack - jit_tls->stack_size)) < 8192 * sizeof (gpointer)) {
3050 * The hard-guard page has been hit: there is not much we can do anymore
3051 * Print a hopefully clear message and abort.
3053 mono_handle_hard_stack_ovf (jit_tls, ji, ctx, (guint8*)info->si_addr);
3054 g_assert_not_reached ();
3056 /* The original handler might not like that it is executed on an altstack... */
3057 if (!ji && mono_chain_signal (MONO_SIG_HANDLER_PARAMS))
3060 mono_arch_handle_altstack_exception (ctx, info, info->si_addr, FALSE);
3065 if (!mono_do_crash_chaining && mono_chain_signal (MONO_SIG_HANDLER_PARAMS))
3068 mono_handle_native_crash ("SIGSEGV", ctx, info);
3070 if (mono_do_crash_chaining) {
3071 mono_chain_signal (MONO_SIG_HANDLER_PARAMS);
3076 mono_arch_handle_exception (ctx, NULL);
3080 MONO_SIG_HANDLER_FUNC (, mono_sigint_signal_handler)
3083 MONO_SIG_HANDLER_GET_CONTEXT;
3085 MONO_ENTER_GC_UNSAFE_UNBALANCED;
3087 exc = mono_get_exception_execution_engine ("Interrupted (SIGINT).");
3089 mono_arch_handle_exception (ctx, exc);
3091 MONO_EXIT_GC_UNSAFE_UNBALANCED;
3094 #ifndef DISABLE_REMOTING
3095 /* mono_jit_create_remoting_trampoline:
3096 * @method: pointer to the method info
3098 * Creates a trampoline which calls the remoting functions. This
3099 * is used in the vtable of transparent proxies.
3101 * Returns: a pointer to the newly created code
3104 mono_jit_create_remoting_trampoline (MonoDomain *domain, MonoMethod *method, MonoRemotingTarget target, MonoError *error)
3107 guint8 *addr = NULL;
3111 if ((method->flags & METHOD_ATTRIBUTE_VIRTUAL) && mono_method_signature (method)->generic_param_count) {
3112 return mono_create_specific_trampoline (method, MONO_TRAMPOLINE_GENERIC_VIRTUAL_REMOTING,
3116 if ((method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
3117 (mono_method_signature (method)->hasthis && (mono_class_is_marshalbyref (method->klass) || method->klass == mono_defaults.object_class)))
3118 nm = mono_marshal_get_remoting_invoke_for_target (method, target);
3121 addr = (guint8 *)mono_compile_method_checked (nm, error);
3122 return_val_if_nok (error, NULL);
3123 return mono_get_addr_from_ftnptr (addr);
3127 static G_GNUC_UNUSED void
3128 no_imt_trampoline (void)
3130 g_assert_not_reached ();
3133 static G_GNUC_UNUSED void
3134 no_vcall_trampoline (void)
3136 g_assert_not_reached ();
3139 static gpointer *vtable_trampolines;
3140 static int vtable_trampolines_size;
3143 mini_get_vtable_trampoline (MonoVTable *vt, int slot_index)
3145 int index = slot_index + MONO_IMT_SIZE;
3147 if (mono_llvm_only) {
3148 if (slot_index < 0) {
3149 /* Initialize the IMT trampoline to a 'trampoline' so the generated code doesn't have to initialize it */
3150 // FIXME: Memory management
3151 gpointer *ftndesc = g_malloc (2 * sizeof (gpointer));
3152 IMTTrampInfo *info = g_new0 (IMTTrampInfo, 1);
3155 ftndesc [0] = mini_llvmonly_initial_imt_tramp;
3157 mono_memory_barrier ();
3164 g_assert (slot_index >= - MONO_IMT_SIZE);
3165 if (!vtable_trampolines || slot_index + MONO_IMT_SIZE >= vtable_trampolines_size) {
3167 if (!vtable_trampolines || index >= vtable_trampolines_size) {
3171 new_size = vtable_trampolines_size ? vtable_trampolines_size * 2 : 128;
3172 while (new_size <= index)
3174 new_table = g_new0 (gpointer, new_size);
3176 if (vtable_trampolines)
3177 memcpy (new_table, vtable_trampolines, vtable_trampolines_size * sizeof (gpointer));
3178 g_free (vtable_trampolines);
3179 mono_memory_barrier ();
3180 vtable_trampolines = (void **)new_table;
3181 vtable_trampolines_size = new_size;
3186 if (!vtable_trampolines [index])
3187 vtable_trampolines [index] = mono_create_specific_trampoline (GUINT_TO_POINTER (slot_index), MONO_TRAMPOLINE_VCALL, mono_get_root_domain (), NULL);
3188 return vtable_trampolines [index];
3192 mini_get_imt_trampoline (MonoVTable *vt, int slot_index)
3194 return mini_get_vtable_trampoline (vt, slot_index - MONO_IMT_SIZE);
3198 mini_imt_entry_inited (MonoVTable *vt, int imt_slot_index)
3203 gpointer *imt = (gpointer*)vt;
3204 imt -= MONO_IMT_SIZE;
3206 return (imt [imt_slot_index] != mini_get_imt_trampoline (vt, imt_slot_index));
3210 is_callee_gsharedvt_variable (gpointer addr)
3213 gboolean callee_gsharedvt;
3215 ji = mini_jit_info_table_find (mono_domain_get (), (char *)mono_get_addr_from_ftnptr (addr), NULL);
3217 callee_gsharedvt = mini_jit_info_is_gsharedvt (ji);
3218 if (callee_gsharedvt)
3219 callee_gsharedvt = mini_is_gsharedvt_variable_signature (mono_method_signature (jinfo_get_method (ji)));
3220 return callee_gsharedvt;
3224 mini_get_delegate_arg (MonoMethod *method, gpointer method_ptr)
3226 gpointer arg = NULL;
3228 if (mono_method_needs_static_rgctx_invoke (method, FALSE))
3229 arg = mini_method_get_rgctx (method);
3232 * Avoid adding gsharedvt in wrappers since they might not exist if
3233 * this delegate is called through a gsharedvt delegate invoke wrapper.
3234 * Instead, encode that the method is gsharedvt in del->extra_arg,
3235 * the CEE_MONO_CALLI_EXTRA_ARG implementation in the JIT depends on this.
3237 if (method->is_inflated && is_callee_gsharedvt_variable (method_ptr)) {
3238 g_assert ((((mgreg_t)arg) & 1) == 0);
3239 arg = (gpointer)(((mgreg_t)arg) | 1);
3245 mini_init_delegate (MonoDelegate *del)
3248 del->extra_arg = mini_get_delegate_arg (del->method, del->method_ptr);
3249 #ifdef ENABLE_INTERPRETER
3250 if (mono_use_interpreter)
3251 mono_interp_init_delegate (del);
3256 mono_get_delegate_virtual_invoke_impl_name (gboolean load_imt_reg, int offset)
3260 abs_offset = offset;
3262 abs_offset = - abs_offset;
3263 return g_strdup_printf ("delegate_virtual_invoke%s_%s%d", load_imt_reg ? "_imt" : "", offset < 0 ? "m_" : "", abs_offset / SIZEOF_VOID_P);
3267 mono_get_delegate_virtual_invoke_impl (MonoMethodSignature *sig, MonoMethod *method)
3269 gboolean is_virtual_generic, is_interface, load_imt_reg;
3272 static guint8 **cache = NULL;
3273 static int cache_size = 0;
3278 if (MONO_TYPE_ISSTRUCT (sig->ret))
3281 is_virtual_generic = method->is_inflated && mono_method_get_declaring_generic_method (method)->is_generic;
3282 is_interface = mono_class_is_interface (method->klass);
3283 load_imt_reg = is_virtual_generic || is_interface;
3286 offset = ((gint32)mono_method_get_imt_slot (method) - MONO_IMT_SIZE) * SIZEOF_VOID_P;
3288 offset = G_STRUCT_OFFSET (MonoVTable, vtable) + ((mono_method_get_vtable_index (method)) * (SIZEOF_VOID_P));
3290 idx = (offset / SIZEOF_VOID_P + MONO_IMT_SIZE) * 2 + (load_imt_reg ? 1 : 0);
3291 g_assert (idx >= 0);
3293 /* Resize the cache to idx + 1 */
3294 if (cache_size < idx + 1) {
3296 if (cache_size < idx + 1) {
3298 int new_cache_size = idx + 1;
3300 new_cache = g_new0 (guint8*, new_cache_size);
3302 memcpy (new_cache, cache, cache_size * sizeof (guint8*));
3305 mono_memory_barrier ();
3307 cache_size = new_cache_size;
3315 /* FIXME Support more cases */
3316 if (mono_aot_only) {
3317 cache [idx] = (guint8 *)mono_aot_get_trampoline (mono_get_delegate_virtual_invoke_impl_name (load_imt_reg, offset));
3318 g_assert (cache [idx]);
3320 cache [idx] = (guint8 *)mono_arch_get_delegate_virtual_invoke_impl (sig, method, offset, load_imt_reg);
3326 * mini_parse_debug_option:
3327 * @option: The option to parse.
3329 * Parses debug options for the mono runtime. The options are the same as for
3330 * the MONO_DEBUG environment variable.
3334 mini_parse_debug_option (const char *option)
3336 if (!strcmp (option, "handle-sigint"))
3337 debug_options.handle_sigint = TRUE;
3338 else if (!strcmp (option, "keep-delegates"))
3339 debug_options.keep_delegates = TRUE;
3340 else if (!strcmp (option, "reverse-pinvoke-exceptions"))
3341 debug_options.reverse_pinvoke_exceptions = TRUE;
3342 else if (!strcmp (option, "collect-pagefault-stats"))
3343 debug_options.collect_pagefault_stats = TRUE;
3344 else if (!strcmp (option, "break-on-unverified"))
3345 debug_options.break_on_unverified = TRUE;
3346 else if (!strcmp (option, "no-gdb-backtrace"))
3347 debug_options.no_gdb_backtrace = TRUE;
3348 else if (!strcmp (option, "suspend-on-native-crash") || !strcmp (option, "suspend-on-sigsegv"))
3349 debug_options.suspend_on_native_crash = TRUE;
3350 else if (!strcmp (option, "suspend-on-exception"))
3351 debug_options.suspend_on_exception = TRUE;
3352 else if (!strcmp (option, "suspend-on-unhandled"))
3353 debug_options.suspend_on_unhandled = TRUE;
3354 else if (!strcmp (option, "dont-free-domains"))
3355 mono_dont_free_domains = TRUE;
3356 else if (!strcmp (option, "dyn-runtime-invoke"))
3357 debug_options.dyn_runtime_invoke = TRUE;
3358 else if (!strcmp (option, "gdb"))
3359 debug_options.gdb = TRUE;
3360 else if (!strcmp (option, "lldb"))
3361 debug_options.lldb = TRUE;
3362 else if (!strcmp (option, "explicit-null-checks"))
3363 debug_options.explicit_null_checks = TRUE;
3364 else if (!strcmp (option, "gen-seq-points"))
3365 debug_options.gen_sdb_seq_points = TRUE;
3366 else if (!strcmp (option, "gen-compact-seq-points"))
3367 fprintf (stderr, "Mono Warning: option gen-compact-seq-points is deprecated.\n");
3368 else if (!strcmp (option, "no-compact-seq-points"))
3369 debug_options.no_seq_points_compact_data = TRUE;
3370 else if (!strcmp (option, "single-imm-size"))
3371 debug_options.single_imm_size = TRUE;
3372 else if (!strcmp (option, "init-stacks"))
3373 debug_options.init_stacks = TRUE;
3374 else if (!strcmp (option, "casts"))
3375 debug_options.better_cast_details = TRUE;
3376 else if (!strcmp (option, "soft-breakpoints"))
3377 debug_options.soft_breakpoints = TRUE;
3378 else if (!strcmp (option, "check-pinvoke-callconv"))
3379 debug_options.check_pinvoke_callconv = TRUE;
3380 else if (!strcmp (option, "use-fallback-tls"))
3381 debug_options.use_fallback_tls = TRUE;
3382 else if (!strcmp (option, "debug-domain-unload"))
3383 mono_enable_debug_domain_unload (TRUE);
3384 else if (!strcmp (option, "partial-sharing"))
3385 mono_set_partial_sharing_supported (TRUE);
3386 else if (!strcmp (option, "align-small-structs"))
3387 mono_align_small_structs = TRUE;
3388 else if (!strcmp (option, "native-debugger-break"))
3389 debug_options.native_debugger_break = TRUE;
3390 else if (!strcmp (option, "disable_omit_fp"))
3391 debug_options.disable_omit_fp = TRUE;
3399 mini_parse_debug_options (void)
3401 char *options = g_getenv ("MONO_DEBUG");
3402 gchar **args, **ptr;
3407 args = g_strsplit (options, ",", -1);
3410 for (ptr = args; ptr && *ptr; ptr++) {
3411 const char *arg = *ptr;
3413 if (!mini_parse_debug_option (arg)) {
3414 fprintf (stderr, "Invalid option for the MONO_DEBUG env variable: %s\n", arg);
3415 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");
3424 mini_get_debug_options (void)
3426 return &debug_options;
3430 mini_create_ftnptr (MonoDomain *domain, gpointer addr)
3432 #if !defined(__ia64__) && (!defined(__ppc64__) && !defined(__powerpc64__) || _CALL_ELF == 2)
3435 gpointer* desc = NULL;
3437 if ((desc = g_hash_table_lookup (domain->ftnptrs_hash, addr)))
3440 desc = mono_domain_code_reserve (domain, 2 * sizeof (gpointer));
3444 # elif defined(__ppc64__) || defined(__powerpc64__)
3446 desc = mono_domain_alloc0 (domain, 3 * sizeof (gpointer));
3452 g_hash_table_insert (domain->ftnptrs_hash, addr, desc);
3458 mini_get_addr_from_ftnptr (gpointer descr)
3460 #if defined(__ia64__) || ((defined(__ppc64__) || defined(__powerpc64__)) && _CALL_ELF != 2)
3461 return *(gpointer*)descr;
3468 register_jit_stats (void)
3470 mono_counters_register ("Compiled methods", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.methods_compiled);
3471 mono_counters_register ("Methods from AOT", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.methods_aot);
3472 mono_counters_register ("Methods JITted using mono JIT", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.methods_without_llvm);
3473 mono_counters_register ("Methods JITted using LLVM", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.methods_with_llvm);
3474 mono_counters_register ("JIT/method_to_ir (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_method_to_ir);
3475 mono_counters_register ("JIT/liveness_handle_exception_clauses (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_liveness_handle_exception_clauses);
3476 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);
3477 mono_counters_register ("JIT/decompose_long_opts (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_decompose_long_opts);
3478 mono_counters_register ("JIT/decompose_typechecks (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_decompose_typechecks);
3479 mono_counters_register ("JIT/local_cprop (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_local_cprop);
3480 mono_counters_register ("JIT/local_emulate_ops (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_local_emulate_ops);
3481 mono_counters_register ("JIT/optimize_branches (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_optimize_branches);
3482 mono_counters_register ("JIT/handle_global_vregs (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_handle_global_vregs);
3483 mono_counters_register ("JIT/local_deadce (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_local_deadce);
3484 mono_counters_register ("JIT/local_alias_analysis (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_local_alias_analysis);
3485 mono_counters_register ("JIT/if_conversion (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_if_conversion);
3486 mono_counters_register ("JIT/bb_ordering (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_bb_ordering);
3487 mono_counters_register ("JIT/compile_dominator_info (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_compile_dominator_info);
3488 mono_counters_register ("JIT/compute_natural_loops (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_compute_natural_loops);
3489 mono_counters_register ("JIT/insert_safepoints (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_insert_safepoints);
3490 mono_counters_register ("JIT/ssa_compute (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_ssa_compute);
3491 mono_counters_register ("JIT/ssa_cprop (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_ssa_cprop);
3492 mono_counters_register ("JIT/ssa_deadce(sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_ssa_deadce);
3493 mono_counters_register ("JIT/perform_abc_removal (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_perform_abc_removal);
3494 mono_counters_register ("JIT/ssa_remove (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_ssa_remove);
3495 mono_counters_register ("JIT/local_cprop2 (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_local_cprop2);
3496 mono_counters_register ("JIT/handle_global_vregs2 (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_handle_global_vregs2);
3497 mono_counters_register ("JIT/local_deadce2 (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_local_deadce2);
3498 mono_counters_register ("JIT/optimize_branches2 (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_optimize_branches2);
3499 mono_counters_register ("JIT/decompose_vtype_opts (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_decompose_vtype_opts);
3500 mono_counters_register ("JIT/decompose_array_access_opts (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_decompose_array_access_opts);
3501 mono_counters_register ("JIT/liveness_handle_exception_clauses2 (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_liveness_handle_exception_clauses2);
3502 mono_counters_register ("JIT/analyze_liveness (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_analyze_liveness);
3503 mono_counters_register ("JIT/linear_scan (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_linear_scan);
3504 mono_counters_register ("JIT/arch_allocate_vars (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_arch_allocate_vars);
3505 mono_counters_register ("JIT/spill_global_vars (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_spill_global_vars);
3506 mono_counters_register ("JIT/local_cprop3 (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_local_cprop3);
3507 mono_counters_register ("JIT/local_deadce3 (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_local_deadce3);
3508 mono_counters_register ("JIT/codegen (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_codegen);
3509 mono_counters_register ("JIT/create_jit_info (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_create_jit_info);
3510 mono_counters_register ("JIT/gc_create_gc_map (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_gc_create_gc_map);
3511 mono_counters_register ("JIT/save_seq_point_info (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_save_seq_point_info);
3512 mono_counters_register ("Total time spent JITting (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_time);
3513 mono_counters_register ("Basic blocks", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.basic_blocks);
3514 mono_counters_register ("Max basic blocks", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.max_basic_blocks);
3515 mono_counters_register ("Allocated vars", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.allocate_var);
3516 mono_counters_register ("Code reallocs", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.code_reallocs);
3517 mono_counters_register ("Allocated code size", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.allocated_code_size);
3518 mono_counters_register ("Allocated seq points size", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.allocated_seq_points_size);
3519 mono_counters_register ("Inlineable methods", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.inlineable_methods);
3520 mono_counters_register ("Inlined methods", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.inlined_methods);
3521 mono_counters_register ("Regvars", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.regvars);
3522 mono_counters_register ("Locals stack size", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.locals_stack_size);
3523 mono_counters_register ("Method cache lookups", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.methods_lookups);
3524 mono_counters_register ("Compiled CIL code size", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.cil_code_size);
3525 mono_counters_register ("Native code size", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.native_code_size);
3526 mono_counters_register ("Aliases found", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.alias_found);
3527 mono_counters_register ("Aliases eliminated", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.alias_removed);
3528 mono_counters_register ("Aliased loads eliminated", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.loads_eliminated);
3529 mono_counters_register ("Aliased stores eliminated", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.stores_eliminated);
3530 mono_counters_register ("Optimized immediate divisions", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.optimized_divisions);
3533 static void runtime_invoke_info_free (gpointer value);
3536 class_method_pair_equal (gconstpointer ka, gconstpointer kb)
3538 const MonoClassMethodPair *apair = (const MonoClassMethodPair *)ka;
3539 const MonoClassMethodPair *bpair = (const MonoClassMethodPair *)kb;
3541 return apair->klass == bpair->klass && apair->method == bpair->method ? 1 : 0;
3545 class_method_pair_hash (gconstpointer data)
3547 const MonoClassMethodPair *pair = (const MonoClassMethodPair *)data;
3549 return (gsize)pair->klass ^ (gsize)pair->method;
3553 mini_create_jit_domain_info (MonoDomain *domain)
3555 MonoJitDomainInfo *info = g_new0 (MonoJitDomainInfo, 1);
3557 info->jump_trampoline_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
3558 info->jit_trampoline_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
3559 info->delegate_trampoline_hash = g_hash_table_new (class_method_pair_hash, class_method_pair_equal);
3560 info->llvm_vcall_trampoline_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
3561 info->runtime_invoke_hash = mono_conc_hashtable_new_full (mono_aligned_addr_hash, NULL, NULL, runtime_invoke_info_free);
3562 info->seq_points = g_hash_table_new_full (mono_aligned_addr_hash, NULL, NULL, mono_seq_point_info_free);
3563 info->arch_seq_points = g_hash_table_new (mono_aligned_addr_hash, NULL);
3564 info->jump_target_hash = g_hash_table_new (NULL, NULL);
3565 mono_jit_code_hash_init (&info->interp_code_hash);
3567 domain->runtime_info = info;
3571 delete_jump_list (gpointer key, gpointer value, gpointer user_data)
3573 MonoJumpList *jlist = (MonoJumpList *)value;
3574 g_slist_free (jlist->list);
3578 delete_got_slot_list (gpointer key, gpointer value, gpointer user_data)
3580 GSList *list = (GSList *)value;
3581 g_slist_free (list);
3585 dynamic_method_info_free (gpointer key, gpointer value, gpointer user_data)
3587 MonoJitDynamicMethodInfo *di = (MonoJitDynamicMethodInfo *)value;
3588 mono_code_manager_destroy (di->code_mp);
3593 runtime_invoke_info_free (gpointer value)
3595 RuntimeInvokeInfo *info = (RuntimeInvokeInfo*)value;
3597 #ifdef MONO_ARCH_DYN_CALL_SUPPORTED
3598 if (info->dyn_call_info)
3599 mono_arch_dyn_call_free (info->dyn_call_info);
3605 free_jit_callee_list (gpointer key, gpointer value, gpointer user_data)
3607 g_slist_free (value);
3611 mini_free_jit_domain_info (MonoDomain *domain)
3613 MonoJitDomainInfo *info = domain_jit_info (domain);
3615 g_hash_table_foreach (info->jump_target_hash, delete_jump_list, NULL);
3616 g_hash_table_destroy (info->jump_target_hash);
3617 if (info->jump_target_got_slot_hash) {
3618 g_hash_table_foreach (info->jump_target_got_slot_hash, delete_got_slot_list, NULL);
3619 g_hash_table_destroy (info->jump_target_got_slot_hash);
3621 if (info->dynamic_code_hash) {
3622 g_hash_table_foreach (info->dynamic_code_hash, dynamic_method_info_free, NULL);
3623 g_hash_table_destroy (info->dynamic_code_hash);
3625 if (info->method_code_hash)
3626 g_hash_table_destroy (info->method_code_hash);
3627 g_hash_table_destroy (info->jump_trampoline_hash);
3628 g_hash_table_destroy (info->jit_trampoline_hash);
3629 g_hash_table_destroy (info->delegate_trampoline_hash);
3630 if (info->static_rgctx_trampoline_hash)
3631 g_hash_table_destroy (info->static_rgctx_trampoline_hash);
3632 g_hash_table_destroy (info->llvm_vcall_trampoline_hash);
3633 mono_conc_hashtable_destroy (info->runtime_invoke_hash);
3634 g_hash_table_destroy (info->seq_points);
3635 g_hash_table_destroy (info->arch_seq_points);
3636 if (info->agent_info)
3637 mono_debugger_agent_free_domain_info (domain);
3638 if (info->gsharedvt_arg_tramp_hash)
3639 g_hash_table_destroy (info->gsharedvt_arg_tramp_hash);
3640 if (info->llvm_jit_callees) {
3641 g_hash_table_foreach (info->llvm_jit_callees, free_jit_callee_list, NULL);
3642 g_hash_table_destroy (info->llvm_jit_callees);
3644 mono_internal_hash_table_destroy (&info->interp_code_hash);
3646 mono_llvm_free_domain_info (domain);
3649 g_free (domain->runtime_info);
3650 domain->runtime_info = NULL;
3653 #ifdef MONO_ARCH_HAVE_CODE_CHUNK_TRACKING
3656 code_manager_chunk_new (void *chunk, int size)
3658 mono_arch_code_chunk_new (chunk, size);
3662 code_manager_chunk_destroy (void *chunk)
3664 mono_arch_code_chunk_destroy (chunk);
3671 llvm_init_inner (void)
3673 if (!mono_llvm_load (NULL))
3684 * Load and initialize LLVM support.
3685 * Return TRUE on success.
3688 mini_llvm_init (void)
3691 static gboolean llvm_inited;
3692 static gboolean init_result;
3694 mono_loader_lock_if_inited ();
3696 init_result = llvm_init_inner ();
3699 mono_loader_unlock_if_inited ();
3707 mini_profiler_enable_with_options (const char* profile_options)
3709 mini_enable_profiler = TRUE;
3710 mini_profiler_options = g_strdup (profile_options);
3714 mini_init (const char *filename, const char *runtime_version)
3718 MonoRuntimeCallbacks callbacks;
3719 MonoThreadInfoRuntimeCallbacks ticallbacks;
3720 MonoCodeManagerCallbacks code_manager_callbacks;
3722 MONO_VES_INIT_BEGIN ();
3724 CHECKED_MONO_INIT ();
3726 #if defined(__linux__) && !defined(__native_client__)
3727 if (access ("/proc/self/maps", F_OK) != 0) {
3728 g_print ("Mono requires /proc to be mounted.\n");
3733 mono_os_mutex_init_recursive (&jit_mutex);
3735 mono_cross_helpers_run ();
3737 mono_counters_init ();
3741 mini_jit_init_job_control ();
3743 /* Happens when using the embedding interface */
3744 if (!default_opt_set)
3745 default_opt = mono_parse_default_optimizations (NULL);
3747 #ifdef MONO_ARCH_GSHAREDVT_SUPPORTED
3749 mono_set_generic_sharing_vt_supported (TRUE);
3752 mono_set_generic_sharing_vt_supported (TRUE);
3755 mono_tls_init_runtime_keys ();
3757 if (!global_codeman)
3758 global_codeman = mono_code_manager_new ();
3760 memset (&callbacks, 0, sizeof (callbacks));
3761 callbacks.create_ftnptr = mini_create_ftnptr;
3762 callbacks.get_addr_from_ftnptr = mini_get_addr_from_ftnptr;
3763 callbacks.get_runtime_build_info = mono_get_runtime_build_info;
3764 callbacks.set_cast_details = mono_set_cast_details;
3765 callbacks.debug_log = mono_debugger_agent_debug_log;
3766 callbacks.debug_log_is_enabled = mono_debugger_agent_debug_log_is_enabled;
3767 callbacks.get_vtable_trampoline = mini_get_vtable_trampoline;
3768 callbacks.get_imt_trampoline = mini_get_imt_trampoline;
3769 callbacks.imt_entry_inited = mini_imt_entry_inited;
3770 callbacks.init_delegate = mini_init_delegate;
3771 #define JIT_INVOKE_WORKS
3772 #ifdef JIT_INVOKE_WORKS
3773 callbacks.runtime_invoke = mono_jit_runtime_invoke;
3775 #define JIT_TRAMPOLINES_WORK
3776 #ifdef JIT_TRAMPOLINES_WORK
3777 callbacks.compile_method = mono_jit_compile_method;
3778 callbacks.create_jump_trampoline = mono_create_jump_trampoline;
3779 callbacks.create_jit_trampoline = mono_create_jit_trampoline;
3780 callbacks.create_delegate_trampoline = mono_create_delegate_trampoline;
3781 callbacks.free_method = mono_jit_free_method;
3782 #ifndef DISABLE_REMOTING
3783 callbacks.create_remoting_trampoline = mono_jit_create_remoting_trampoline;
3787 mono_install_callbacks (&callbacks);
3789 memset (&ticallbacks, 0, sizeof (ticallbacks));
3790 ticallbacks.setup_async_callback = mono_setup_async_callback;
3791 ticallbacks.thread_state_init_from_sigctx = mono_thread_state_init_from_sigctx;
3792 ticallbacks.thread_state_init_from_handle = mono_thread_state_init_from_handle;
3793 ticallbacks.thread_state_init = mono_thread_state_init;
3796 mono_w32handle_init ();
3799 mono_threads_runtime_init (&ticallbacks);
3801 if (g_hasenv ("MONO_DEBUG")) {
3802 mini_parse_debug_options ();
3805 mono_code_manager_init ();
3807 memset (&code_manager_callbacks, 0, sizeof (code_manager_callbacks));
3808 #ifdef MONO_ARCH_HAVE_CODE_CHUNK_TRACKING
3809 code_manager_callbacks.chunk_new = code_manager_chunk_new;
3810 code_manager_callbacks.chunk_destroy = code_manager_chunk_destroy;
3812 mono_code_manager_install_callbacks (&code_manager_callbacks);
3816 mono_arch_cpu_init ();
3820 mono_unwind_init ();
3822 if (mini_get_debug_options ()->lldb || g_hasenv ("MONO_LLDB")) {
3823 mono_lldb_init ("");
3824 mono_dont_free_domains = TRUE;
3827 #ifdef XDEBUG_ENABLED
3828 char *mono_xdebug = g_getenv ("MONO_XDEBUG");
3830 mono_xdebug_init (mono_xdebug);
3831 g_free (mono_xdebug);
3832 /* So methods for multiple domains don't have the same address */
3833 mono_dont_free_domains = TRUE;
3834 mono_using_xdebug = TRUE;
3835 } else if (mini_get_debug_options ()->gdb) {
3836 mono_xdebug_init ((char*)"gdb");
3837 mono_dont_free_domains = TRUE;
3838 mono_using_xdebug = TRUE;
3843 if (mono_use_llvm) {
3844 if (!mono_llvm_load (NULL)) {
3845 mono_use_llvm = FALSE;
3846 fprintf (stderr, "Mono Warning: llvm support could not be loaded.\n");
3853 mono_trampolines_init ();
3855 if (default_opt & MONO_OPT_AOT)
3858 mono_debugger_agent_init ();
3860 #ifdef MONO_ARCH_GSHARED_SUPPORTED
3861 mono_set_generic_sharing_supported (TRUE);
3864 mono_threads_signals_init ();
3866 #ifndef MONO_CROSS_COMPILE
3867 mono_runtime_install_handlers ();
3869 mono_threads_install_cleanup (mini_thread_cleanup);
3871 #ifdef JIT_TRAMPOLINES_WORK
3872 mono_install_create_domain_hook (mini_create_jit_domain_info);
3873 mono_install_free_domain_hook (mini_free_jit_domain_info);
3875 mono_install_get_cached_class_info (mono_aot_get_cached_class_info);
3876 mono_install_get_class_from_name (mono_aot_get_class_from_name);
3877 mono_install_jit_info_find_in_aot (mono_aot_find_jit_info);
3879 if (mini_profiler_enabled ()) {
3880 mono_profiler_load (mini_profiler_get_options ());
3881 mono_profiler_thread_name (MONO_NATIVE_THREAD_ID_TO_UINT (mono_native_thread_id_get ()), "Main");
3884 if (debug_options.collect_pagefault_stats)
3885 mono_aot_set_make_unreadable (TRUE);
3887 if (runtime_version)
3888 domain = mono_init_version (filename, runtime_version);
3890 domain = mono_init_from_assembly (filename, filename);
3892 if (mono_aot_only) {
3893 /* This helps catch code allocation requests */
3894 mono_code_manager_set_read_only (domain->code_mp);
3895 mono_marshal_use_aot_wrappers (TRUE);
3898 if (mono_llvm_only) {
3899 mono_install_imt_trampoline_builder (mono_llvmonly_get_imt_trampoline);
3900 mono_set_always_build_imt_trampolines (TRUE);
3901 } else if (mono_aot_only) {
3902 mono_install_imt_trampoline_builder (mono_aot_get_imt_trampoline);
3904 mono_install_imt_trampoline_builder (mono_arch_build_imt_trampoline);
3907 /*Init arch tls information only after the metadata side is inited to make sure we see dynamic appdomain tls keys*/
3908 mono_arch_finish_init ();
3912 /* This must come after mono_init () in the aot-only case */
3913 mono_exceptions_init ();
3915 /* This should come after mono_init () too */
3919 mono_create_helper_signatures ();
3922 register_jit_stats ();
3924 #define JIT_CALLS_WORK
3925 #ifdef JIT_CALLS_WORK
3926 /* Needs to be called here since register_jit_icall depends on it */
3927 mono_marshal_init ();
3929 mono_arch_register_lowlevel_calls ();
3933 mono_generic_sharing_init ();
3936 #ifdef MONO_ARCH_SIMD_INTRINSICS
3937 mono_simd_intrinsics_init ();
3940 mono_tasklets_init ();
3942 register_trampolines (domain);
3944 if (mono_compile_aot)
3946 * Avoid running managed code when AOT compiling, since the platform
3947 * might only support aot-only execution.
3949 mono_runtime_set_no_exec (TRUE);
3951 mono_mem_account_register_counters ();
3953 #define JIT_RUNTIME_WORKS
3954 #ifdef JIT_RUNTIME_WORKS
3955 mono_install_runtime_cleanup ((MonoDomainFunc)mini_cleanup);
3956 mono_runtime_init_checked (domain, mono_thread_start_cb, mono_thread_attach_cb, &error);
3957 mono_error_assert_ok (&error);
3958 mono_thread_attach (domain);
3961 if (mono_profiler_get_events () & MONO_PROFILE_STATISTICAL)
3962 mono_runtime_setup_stat_profiler ();
3964 mono_profiler_runtime_initialized ();
3966 MONO_VES_INIT_END ();
3972 register_icalls (void)
3974 mono_add_internal_call ("System.Diagnostics.StackFrame::get_frame_info",
3975 ves_icall_get_frame_info);
3976 mono_add_internal_call ("System.Diagnostics.StackTrace::get_trace",
3977 ves_icall_get_trace);
3978 mono_add_internal_call ("Mono.Runtime::mono_runtime_install_handlers",
3979 mono_runtime_install_handlers);
3980 mono_add_internal_call ("Mono.Runtime::mono_runtime_cleanup_handlers",
3981 mono_runtime_cleanup_handlers);
3983 #if defined(PLATFORM_ANDROID) || defined(TARGET_ANDROID)
3984 mono_add_internal_call ("System.Diagnostics.Debugger::Mono_UnhandledException_internal",
3985 mono_debugger_agent_unhandled_exception);
3989 * It's important that we pass `TRUE` as the last argument here, as
3990 * it causes the JIT to omit a wrapper for these icalls. If the JIT
3991 * *did* emit a wrapper, we'd be looking at infinite recursion since
3992 * the wrapper would call the icall which would call the wrapper and
3995 register_icall (mono_profiler_method_enter, "mono_profiler_method_enter", "void ptr", TRUE);
3996 register_icall (mono_profiler_method_leave, "mono_profiler_method_leave", "void ptr", TRUE);
3998 register_icall (mono_trace_enter_method, "mono_trace_enter_method", NULL, TRUE);
3999 register_icall (mono_trace_leave_method, "mono_trace_leave_method", NULL, TRUE);
4000 register_icall (mono_get_lmf_addr, "mono_get_lmf_addr", "ptr", TRUE);
4001 register_icall (mono_jit_thread_attach, "mono_jit_thread_attach", "ptr ptr", TRUE);
4002 register_icall (mono_jit_set_domain, "mono_jit_set_domain", "void ptr", TRUE);
4003 register_icall (mono_domain_get, "mono_domain_get", "ptr", TRUE);
4005 register_icall (mono_llvm_throw_exception, "mono_llvm_throw_exception", "void object", TRUE);
4006 register_icall (mono_llvm_rethrow_exception, "mono_llvm_rethrow_exception", "void object", TRUE);
4007 register_icall (mono_llvm_resume_exception, "mono_llvm_resume_exception", "void", TRUE);
4008 register_icall (mono_llvm_match_exception, "mono_llvm_match_exception", "int ptr int int", TRUE);
4009 register_icall (mono_llvm_clear_exception, "mono_llvm_clear_exception", NULL, TRUE);
4010 register_icall (mono_llvm_load_exception, "mono_llvm_load_exception", "object", TRUE);
4011 register_icall (mono_llvm_throw_corlib_exception, "mono_llvm_throw_corlib_exception", "void int", TRUE);
4012 #if defined(ENABLE_LLVM) && !defined(MONO_LLVM_LOADED)
4013 register_icall (mono_llvm_set_unhandled_exception_handler, "mono_llvm_set_unhandled_exception_handler", NULL, TRUE);
4015 // FIXME: This is broken
4016 register_icall (mono_debug_personality, "mono_debug_personality", "int int int ptr ptr ptr", TRUE);
4019 register_dyn_icall (mono_get_throw_exception (), "mono_arch_throw_exception", "void object", TRUE);
4020 register_dyn_icall (mono_get_rethrow_exception (), "mono_arch_rethrow_exception", "void object", TRUE);
4021 register_dyn_icall (mono_get_throw_corlib_exception (), "mono_arch_throw_corlib_exception", "void ptr", TRUE);
4022 register_icall (mono_thread_get_undeniable_exception, "mono_thread_get_undeniable_exception", "object", FALSE);
4023 register_icall (mono_thread_interruption_checkpoint, "mono_thread_interruption_checkpoint", "object", FALSE);
4024 register_icall (mono_thread_force_interruption_checkpoint_noraise, "mono_thread_force_interruption_checkpoint_noraise", "object", FALSE);
4026 #if defined(__native_client__) || defined(__native_client_codegen__)
4027 register_icall (mono_nacl_gc, "mono_nacl_gc", "void", FALSE);
4030 if (mono_threads_is_coop_enabled ())
4031 register_icall (mono_threads_state_poll, "mono_threads_state_poll", "void", FALSE);
4033 #ifndef MONO_ARCH_NO_EMULATE_LONG_MUL_OPTS
4034 register_opcode_emulation (OP_LMUL, "__emul_lmul", "long long long", mono_llmult, "mono_llmult", FALSE);
4035 register_opcode_emulation (OP_LDIV, "__emul_ldiv", "long long long", mono_lldiv, "mono_lldiv", FALSE);
4036 register_opcode_emulation (OP_LDIV_UN, "__emul_ldiv_un", "long long long", mono_lldiv_un, "mono_lldiv_un", FALSE);
4037 register_opcode_emulation (OP_LREM, "__emul_lrem", "long long long", mono_llrem, "mono_llrem", FALSE);
4038 register_opcode_emulation (OP_LREM_UN, "__emul_lrem_un", "long long long", mono_llrem_un, "mono_llrem_un", FALSE);
4040 #if !defined(MONO_ARCH_NO_EMULATE_LONG_MUL_OPTS) || defined(MONO_ARCH_EMULATE_LONG_MUL_OVF_OPTS)
4041 register_opcode_emulation (OP_LMUL_OVF_UN, "__emul_lmul_ovf_un", "long long long", mono_llmult_ovf_un, "mono_llmult_ovf_un", FALSE);
4042 register_opcode_emulation (OP_LMUL_OVF, "__emul_lmul_ovf", "long long long", mono_llmult_ovf, "mono_llmult_ovf", FALSE);
4045 #ifndef MONO_ARCH_NO_EMULATE_LONG_SHIFT_OPS
4046 register_opcode_emulation (OP_LSHL, "__emul_lshl", "long long int32", mono_lshl, "mono_lshl", TRUE);
4047 register_opcode_emulation (OP_LSHR, "__emul_lshr", "long long int32", mono_lshr, "mono_lshr", TRUE);
4048 register_opcode_emulation (OP_LSHR_UN, "__emul_lshr_un", "long long int32", mono_lshr_un, "mono_lshr_un", TRUE);
4051 #if defined(MONO_ARCH_EMULATE_MUL_DIV) || defined(MONO_ARCH_EMULATE_DIV)
4052 register_opcode_emulation (OP_IDIV, "__emul_op_idiv", "int32 int32 int32", mono_idiv, "mono_idiv", FALSE);
4053 register_opcode_emulation (OP_IDIV_UN, "__emul_op_idiv_un", "int32 int32 int32", mono_idiv_un, "mono_idiv_un", FALSE);
4054 register_opcode_emulation (OP_IREM, "__emul_op_irem", "int32 int32 int32", mono_irem, "mono_irem", FALSE);
4055 register_opcode_emulation (OP_IREM_UN, "__emul_op_irem_un", "int32 int32 int32", mono_irem_un, "mono_irem_un", FALSE);
4058 #ifdef MONO_ARCH_EMULATE_MUL_DIV
4059 register_opcode_emulation (OP_IMUL, "__emul_op_imul", "int32 int32 int32", mono_imul, "mono_imul", TRUE);
4062 #if defined(MONO_ARCH_EMULATE_MUL_DIV) || defined(MONO_ARCH_EMULATE_MUL_OVF)
4063 register_opcode_emulation (OP_IMUL_OVF, "__emul_op_imul_ovf", "int32 int32 int32", mono_imul_ovf, "mono_imul_ovf", FALSE);
4064 register_opcode_emulation (OP_IMUL_OVF_UN, "__emul_op_imul_ovf_un", "int32 int32 int32", mono_imul_ovf_un, "mono_imul_ovf_un", FALSE);
4067 #if defined(MONO_ARCH_EMULATE_MUL_DIV) || defined(MONO_ARCH_SOFT_FLOAT_FALLBACK)
4068 register_opcode_emulation (OP_FDIV, "__emul_fdiv", "double double double", mono_fdiv, "mono_fdiv", FALSE);
4071 register_opcode_emulation (OP_FCONV_TO_U8, "__emul_fconv_to_u8", "ulong double", mono_fconv_u8, "mono_fconv_u8", FALSE);
4072 register_opcode_emulation (OP_RCONV_TO_U8, "__emul_rconv_to_u8", "ulong float", mono_rconv_u8, "mono_rconv_u8", FALSE);
4073 register_opcode_emulation (OP_FCONV_TO_U4, "__emul_fconv_to_u4", "uint32 double", mono_fconv_u4, "mono_fconv_u4", FALSE);
4074 register_opcode_emulation (OP_FCONV_TO_OVF_I8, "__emul_fconv_to_ovf_i8", "long double", mono_fconv_ovf_i8, "mono_fconv_ovf_i8", FALSE);
4075 register_opcode_emulation (OP_FCONV_TO_OVF_U8, "__emul_fconv_to_ovf_u8", "ulong double", mono_fconv_ovf_u8, "mono_fconv_ovf_u8", FALSE);
4076 register_opcode_emulation (OP_RCONV_TO_OVF_I8, "__emul_rconv_to_ovf_i8", "long float", mono_rconv_ovf_i8, "mono_rconv_ovf_i8", FALSE);
4077 register_opcode_emulation (OP_RCONV_TO_OVF_U8, "__emul_rconv_to_ovf_u8", "ulong float", mono_rconv_ovf_u8, "mono_rconv_ovf_u8", FALSE);
4080 #ifdef MONO_ARCH_EMULATE_FCONV_TO_I8
4081 register_opcode_emulation (OP_FCONV_TO_I8, "__emul_fconv_to_i8", "long double", mono_fconv_i8, "mono_fconv_i8", FALSE);
4082 register_opcode_emulation (OP_RCONV_TO_I8, "__emul_rconv_to_i8", "long float", mono_rconv_i8, "mono_rconv_i8", FALSE);
4085 #ifdef MONO_ARCH_EMULATE_CONV_R8_UN
4086 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);
4088 #ifdef MONO_ARCH_EMULATE_LCONV_TO_R8
4089 register_opcode_emulation (OP_LCONV_TO_R8, "__emul_lconv_to_r8", "double long", mono_lconv_to_r8, "mono_lconv_to_r8", FALSE);
4091 #ifdef MONO_ARCH_EMULATE_LCONV_TO_R4
4092 register_opcode_emulation (OP_LCONV_TO_R4, "__emul_lconv_to_r4", "float long", mono_lconv_to_r4, "mono_lconv_to_r4", FALSE);
4094 #ifdef MONO_ARCH_EMULATE_LCONV_TO_R8_UN
4095 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);
4097 #ifdef MONO_ARCH_EMULATE_FREM
4098 #if !defined(__native_client__)
4099 register_opcode_emulation (OP_FREM, "__emul_frem", "double double double", fmod, "fmod", FALSE);
4100 register_opcode_emulation (OP_RREM, "__emul_rrem", "float float float", fmodf, "fmodf", FALSE);
4102 register_opcode_emulation (OP_FREM, "__emul_frem", "double double double", mono_fmod, "mono_fmod", FALSE);
4106 #ifdef MONO_ARCH_SOFT_FLOAT_FALLBACK
4107 if (mono_arch_is_soft_float ()) {
4108 register_opcode_emulation (OP_FSUB, "__emul_fsub", "double double double", mono_fsub, "mono_fsub", FALSE);
4109 register_opcode_emulation (OP_FADD, "__emul_fadd", "double double double", mono_fadd, "mono_fadd", FALSE);
4110 register_opcode_emulation (OP_FMUL, "__emul_fmul", "double double double", mono_fmul, "mono_fmul", FALSE);
4111 register_opcode_emulation (OP_FNEG, "__emul_fneg", "double double", mono_fneg, "mono_fneg", FALSE);
4112 register_opcode_emulation (OP_ICONV_TO_R8, "__emul_iconv_to_r8", "double int32", mono_conv_to_r8, "mono_conv_to_r8", FALSE);
4113 register_opcode_emulation (OP_ICONV_TO_R4, "__emul_iconv_to_r4", "double int32", mono_conv_to_r4, "mono_conv_to_r4", FALSE);
4114 register_opcode_emulation (OP_FCONV_TO_R4, "__emul_fconv_to_r4", "double double", mono_fconv_r4, "mono_fconv_r4", FALSE);
4115 register_opcode_emulation (OP_FCONV_TO_I1, "__emul_fconv_to_i1", "int8 double", mono_fconv_i1, "mono_fconv_i1", FALSE);
4116 register_opcode_emulation (OP_FCONV_TO_I2, "__emul_fconv_to_i2", "int16 double", mono_fconv_i2, "mono_fconv_i2", FALSE);
4117 register_opcode_emulation (OP_FCONV_TO_I4, "__emul_fconv_to_i4", "int32 double", mono_fconv_i4, "mono_fconv_i4", FALSE);
4118 register_opcode_emulation (OP_FCONV_TO_U1, "__emul_fconv_to_u1", "uint8 double", mono_fconv_u1, "mono_fconv_u1", FALSE);
4119 register_opcode_emulation (OP_FCONV_TO_U2, "__emul_fconv_to_u2", "uint16 double", mono_fconv_u2, "mono_fconv_u2", FALSE);
4121 #if SIZEOF_VOID_P == 4
4122 register_opcode_emulation (OP_FCONV_TO_I, "__emul_fconv_to_i", "int32 double", mono_fconv_i4, "mono_fconv_i4", FALSE);
4125 register_opcode_emulation (OP_FBEQ, "__emul_fcmp_eq", "uint32 double double", mono_fcmp_eq, "mono_fcmp_eq", FALSE);
4126 register_opcode_emulation (OP_FBLT, "__emul_fcmp_lt", "uint32 double double", mono_fcmp_lt, "mono_fcmp_lt", FALSE);
4127 register_opcode_emulation (OP_FBGT, "__emul_fcmp_gt", "uint32 double double", mono_fcmp_gt, "mono_fcmp_gt", FALSE);
4128 register_opcode_emulation (OP_FBLE, "__emul_fcmp_le", "uint32 double double", mono_fcmp_le, "mono_fcmp_le", FALSE);
4129 register_opcode_emulation (OP_FBGE, "__emul_fcmp_ge", "uint32 double double", mono_fcmp_ge, "mono_fcmp_ge", FALSE);
4130 register_opcode_emulation (OP_FBNE_UN, "__emul_fcmp_ne_un", "uint32 double double", mono_fcmp_ne_un, "mono_fcmp_ne_un", FALSE);
4131 register_opcode_emulation (OP_FBLT_UN, "__emul_fcmp_lt_un", "uint32 double double", mono_fcmp_lt_un, "mono_fcmp_lt_un", FALSE);
4132 register_opcode_emulation (OP_FBGT_UN, "__emul_fcmp_gt_un", "uint32 double double", mono_fcmp_gt_un, "mono_fcmp_gt_un", FALSE);
4133 register_opcode_emulation (OP_FBLE_UN, "__emul_fcmp_le_un", "uint32 double double", mono_fcmp_le_un, "mono_fcmp_le_un", FALSE);
4134 register_opcode_emulation (OP_FBGE_UN, "__emul_fcmp_ge_un", "uint32 double double", mono_fcmp_ge_un, "mono_fcmp_ge_un", FALSE);
4136 register_opcode_emulation (OP_FCEQ, "__emul_fcmp_ceq", "uint32 double double", mono_fceq, "mono_fceq", FALSE);
4137 register_opcode_emulation (OP_FCGT, "__emul_fcmp_cgt", "uint32 double double", mono_fcgt, "mono_fcgt", FALSE);
4138 register_opcode_emulation (OP_FCGT_UN, "__emul_fcmp_cgt_un", "uint32 double double", mono_fcgt_un, "mono_fcgt_un", FALSE);
4139 register_opcode_emulation (OP_FCLT, "__emul_fcmp_clt", "uint32 double double", mono_fclt, "mono_fclt", FALSE);
4140 register_opcode_emulation (OP_FCLT_UN, "__emul_fcmp_clt_un", "uint32 double double", mono_fclt_un, "mono_fclt_un", FALSE);
4142 register_icall (mono_fload_r4, "mono_fload_r4", "double ptr", FALSE);
4143 register_icall (mono_fstore_r4, "mono_fstore_r4", "void double ptr", FALSE);
4144 register_icall (mono_fload_r4_arg, "mono_fload_r4_arg", "uint32 double", FALSE);
4145 register_icall (mono_isfinite, "mono_isfinite", "uint32 double", FALSE);
4148 register_icall (mono_ckfinite, "mono_ckfinite", "double double", FALSE);
4150 #ifdef COMPRESSED_INTERFACE_BITMAP
4151 register_icall (mono_class_interface_match, "mono_class_interface_match", "uint32 ptr int32", TRUE);
4154 #if SIZEOF_REGISTER == 4
4155 register_opcode_emulation (OP_FCONV_TO_U, "__emul_fconv_to_u", "uint32 double", mono_fconv_u4, "mono_fconv_u4", TRUE);
4157 register_opcode_emulation (OP_FCONV_TO_U, "__emul_fconv_to_u", "ulong double", mono_fconv_u8, "mono_fconv_u8", TRUE);
4160 /* other jit icalls */
4161 register_icall (ves_icall_mono_delegate_ctor, "ves_icall_mono_delegate_ctor", "void object object ptr", FALSE);
4162 register_icall (mono_class_static_field_address , "mono_class_static_field_address",
4163 "ptr ptr ptr", FALSE);
4164 register_icall (mono_ldtoken_wrapper, "mono_ldtoken_wrapper", "ptr ptr ptr ptr", FALSE);
4165 register_icall (mono_ldtoken_wrapper_generic_shared, "mono_ldtoken_wrapper_generic_shared",
4166 "ptr ptr ptr ptr", FALSE);
4167 register_icall (mono_get_special_static_data, "mono_get_special_static_data", "ptr int", FALSE);
4168 register_icall (ves_icall_mono_ldstr, "ves_icall_mono_ldstr", "object ptr ptr int32", FALSE);
4169 register_icall (mono_helper_stelem_ref_check, "mono_helper_stelem_ref_check", "void object object", FALSE);
4170 register_icall (ves_icall_object_new, "ves_icall_object_new", "object ptr ptr", FALSE);
4171 register_icall (ves_icall_object_new_specific, "ves_icall_object_new_specific", "object ptr", FALSE);
4172 register_icall (ves_icall_array_new, "ves_icall_array_new", "object ptr ptr int32", FALSE);
4173 register_icall (ves_icall_array_new_specific, "ves_icall_array_new_specific", "object ptr int32", FALSE);
4174 register_icall (ves_icall_runtime_class_init, "ves_icall_runtime_class_init", "void ptr", FALSE);
4175 register_icall (mono_ldftn, "mono_ldftn", "ptr ptr", FALSE);
4176 register_icall (mono_ldvirtfn, "mono_ldvirtfn", "ptr object ptr", FALSE);
4177 register_icall (mono_ldvirtfn_gshared, "mono_ldvirtfn_gshared", "ptr object ptr", FALSE);
4178 register_icall (mono_helper_compile_generic_method, "mono_helper_compile_generic_method", "ptr object ptr ptr", FALSE);
4179 register_icall (mono_helper_ldstr, "mono_helper_ldstr", "object ptr int", FALSE);
4180 register_icall (mono_helper_ldstr_mscorlib, "mono_helper_ldstr_mscorlib", "object int", FALSE);
4181 register_icall (mono_helper_newobj_mscorlib, "mono_helper_newobj_mscorlib", "object int", FALSE);
4182 register_icall (mono_value_copy, "mono_value_copy", "void ptr ptr ptr", FALSE);
4183 register_icall (mono_object_castclass_unbox, "mono_object_castclass_unbox", "object object ptr", FALSE);
4184 register_icall (mono_break, "mono_break", NULL, TRUE);
4185 register_icall (mono_create_corlib_exception_0, "mono_create_corlib_exception_0", "object int", TRUE);
4186 register_icall (mono_create_corlib_exception_1, "mono_create_corlib_exception_1", "object int object", TRUE);
4187 register_icall (mono_create_corlib_exception_2, "mono_create_corlib_exception_2", "object int object object", TRUE);
4188 register_icall (mono_array_new_1, "mono_array_new_1", "object ptr int", FALSE);
4189 register_icall (mono_array_new_2, "mono_array_new_2", "object ptr int int", FALSE);
4190 register_icall (mono_array_new_3, "mono_array_new_3", "object ptr int int int", FALSE);
4191 register_icall (mono_array_new_4, "mono_array_new_4", "object ptr int int int int", FALSE);
4192 register_icall (mono_get_native_calli_wrapper, "mono_get_native_calli_wrapper", "ptr ptr ptr ptr", FALSE);
4193 register_icall (mono_resume_unwind, "mono_resume_unwind", "void", TRUE);
4194 register_icall (mono_gsharedvt_constrained_call, "mono_gsharedvt_constrained_call", "object ptr ptr ptr ptr ptr", FALSE);
4195 register_icall (mono_gsharedvt_value_copy, "mono_gsharedvt_value_copy", "void ptr ptr ptr", TRUE);
4197 register_icall_no_wrapper (mono_gc_get_range_copy_func (), "mono_gc_range_copy", "void ptr ptr int");
4199 register_icall (mono_object_castclass_with_cache, "mono_object_castclass_with_cache", "object object ptr ptr", FALSE);
4200 register_icall (mono_object_isinst_with_cache, "mono_object_isinst_with_cache", "object object ptr ptr", FALSE);
4201 register_icall (mono_generic_class_init, "mono_generic_class_init", "void ptr", FALSE);
4202 register_icall (mono_fill_class_rgctx, "mono_fill_class_rgctx", "ptr ptr int", FALSE);
4203 register_icall (mono_fill_method_rgctx, "mono_fill_method_rgctx", "ptr ptr int", FALSE);
4205 register_icall (mono_debugger_agent_user_break, "mono_debugger_agent_user_break", "void", FALSE);
4207 register_icall (mono_aot_init_llvm_method, "mono_aot_init_llvm_method", "void ptr int", TRUE);
4208 register_icall (mono_aot_init_gshared_method_this, "mono_aot_init_gshared_method_this", "void ptr int object", TRUE);
4209 register_icall (mono_aot_init_gshared_method_mrgctx, "mono_aot_init_gshared_method_mrgctx", "void ptr int ptr", TRUE);
4210 register_icall (mono_aot_init_gshared_method_vtable, "mono_aot_init_gshared_method_vtable", "void ptr int ptr", TRUE);
4212 register_icall_no_wrapper (mono_resolve_iface_call_gsharedvt, "mono_resolve_iface_call_gsharedvt", "ptr object int ptr ptr");
4213 register_icall_no_wrapper (mono_resolve_vcall_gsharedvt, "mono_resolve_vcall_gsharedvt", "ptr object int ptr ptr");
4214 register_icall_no_wrapper (mono_resolve_generic_virtual_call, "mono_resolve_generic_virtual_call", "ptr ptr int ptr");
4215 register_icall_no_wrapper (mono_resolve_generic_virtual_iface_call, "mono_resolve_generic_virtual_iface_call", "ptr ptr int ptr");
4216 /* This needs a wrapper so it can have a preserveall cconv */
4217 register_icall (mono_init_vtable_slot, "mono_init_vtable_slot", "ptr ptr int", FALSE);
4218 register_icall (mono_llvmonly_init_delegate, "mono_llvmonly_init_delegate", "void object", TRUE);
4219 register_icall (mono_llvmonly_init_delegate_virtual, "mono_llvmonly_init_delegate_virtual", "void object object ptr", TRUE);
4220 register_icall (mono_get_assembly_object, "mono_get_assembly_object", "object ptr", TRUE);
4221 register_icall (mono_get_method_object, "mono_get_method_object", "object ptr", TRUE);
4222 register_icall (mono_throw_method_access, "mono_throw_method_access", "void ptr ptr", FALSE);
4223 register_icall_no_wrapper (mono_dummy_jit_icall, "mono_dummy_jit_icall", "void");
4225 register_icall_with_wrapper (mono_monitor_enter_internal, "mono_monitor_enter_internal", "void obj");
4226 register_icall_with_wrapper (mono_monitor_enter_v4_internal, "mono_monitor_enter_v4_internal", "void obj ptr");
4227 register_icall_no_wrapper (mono_monitor_enter_fast, "mono_monitor_enter_fast", "int obj");
4228 register_icall_no_wrapper (mono_monitor_enter_v4_fast, "mono_monitor_enter_v4_fast", "int obj ptr");
4231 register_icall (pthread_getspecific, "pthread_getspecific", "ptr ptr", TRUE);
4233 /* Register tls icalls */
4234 register_icall_no_wrapper (mono_tls_get_thread, "mono_tls_get_thread", "ptr");
4235 register_icall_no_wrapper (mono_tls_get_jit_tls, "mono_tls_get_jit_tls", "ptr");
4236 register_icall_no_wrapper (mono_tls_get_domain, "mono_tls_get_domain", "ptr");
4237 register_icall_no_wrapper (mono_tls_get_sgen_thread_info, "mono_tls_get_sgen_thread_info", "ptr");
4238 register_icall_no_wrapper (mono_tls_get_lmf_addr, "mono_tls_get_lmf_addr", "ptr");
4239 register_icall_no_wrapper (mono_tls_set_thread, "mono_tls_set_thread", "void ptr");
4240 register_icall_no_wrapper (mono_tls_set_jit_tls, "mono_tls_set_jit_tls", "void ptr");
4241 register_icall_no_wrapper (mono_tls_set_domain, "mono_tls_set_domain", "void ptr");
4242 register_icall_no_wrapper (mono_tls_set_sgen_thread_info, "mono_tls_set_sgen_thread_info", "void ptr");
4243 register_icall_no_wrapper (mono_tls_set_lmf_addr, "mono_tls_set_lmf_addr", "void ptr");
4246 MonoJitStats mono_jit_stats = {0};
4249 print_jit_stats (void)
4251 if (mono_jit_stats.enabled) {
4252 g_print ("Mono Jit statistics\n");
4253 g_print ("Max code size ratio: %.2f (%s)\n", mono_jit_stats.max_code_size_ratio/100.0,
4254 mono_jit_stats.max_ratio_method);
4255 g_print ("Biggest method: %ld (%s)\n", mono_jit_stats.biggest_method_size,
4256 mono_jit_stats.biggest_method);
4258 g_print ("Delegates created: %ld\n", mono_stats.delegate_creations);
4259 g_print ("Initialized classes: %ld\n", mono_stats.initialized_class_count);
4260 g_print ("Used classes: %ld\n", mono_stats.used_class_count);
4261 g_print ("Generic vtables: %ld\n", mono_stats.generic_vtable_count);
4262 g_print ("Methods: %ld\n", mono_stats.method_count);
4263 g_print ("Static data size: %ld\n", mono_stats.class_static_data_size);
4264 g_print ("VTable data size: %ld\n", mono_stats.class_vtable_size);
4265 g_print ("Mscorlib mempool size: %d\n", mono_mempool_get_allocated (mono_defaults.corlib->mempool));
4267 g_print ("\nInitialized classes: %ld\n", mono_stats.generic_class_count);
4268 g_print ("Inflated types: %ld\n", mono_stats.inflated_type_count);
4269 g_print ("Generics virtual invokes: %ld\n", mono_jit_stats.generic_virtual_invocations);
4271 g_print ("Sharable generic methods: %ld\n", mono_stats.generics_sharable_methods);
4272 g_print ("Unsharable generic methods: %ld\n", mono_stats.generics_unsharable_methods);
4273 g_print ("Shared generic methods: %ld\n", mono_stats.generics_shared_methods);
4274 g_print ("Shared vtype generic methods: %ld\n", mono_stats.gsharedvt_methods);
4276 g_print ("IMT tables size: %ld\n", mono_stats.imt_tables_size);
4277 g_print ("IMT number of tables: %ld\n", mono_stats.imt_number_of_tables);
4278 g_print ("IMT number of methods: %ld\n", mono_stats.imt_number_of_methods);
4279 g_print ("IMT used slots: %ld\n", mono_stats.imt_used_slots);
4280 g_print ("IMT colliding slots: %ld\n", mono_stats.imt_slots_with_collisions);
4281 g_print ("IMT max collisions: %ld\n", mono_stats.imt_max_collisions_in_slot);
4282 g_print ("IMT methods at max col: %ld\n", mono_stats.imt_method_count_when_max_collisions);
4283 g_print ("IMT trampolines size: %ld\n", mono_stats.imt_trampolines_size);
4285 g_print ("JIT info table inserts: %ld\n", mono_stats.jit_info_table_insert_count);
4286 g_print ("JIT info table removes: %ld\n", mono_stats.jit_info_table_remove_count);
4287 g_print ("JIT info table lookups: %ld\n", mono_stats.jit_info_table_lookup_count);
4289 g_free (mono_jit_stats.max_ratio_method);
4290 mono_jit_stats.max_ratio_method = NULL;
4291 g_free (mono_jit_stats.biggest_method);
4292 mono_jit_stats.biggest_method = NULL;
4297 mini_cleanup (MonoDomain *domain)
4299 if (mono_profiler_get_events () & MONO_PROFILE_STATISTICAL)
4300 mono_runtime_shutdown_stat_profiler ();
4303 cominterop_release_all_rcws ();
4306 #ifndef MONO_CROSS_COMPILE
4308 * mono_domain_finalize () needs to be called early since it needs the
4309 * execution engine still fully working (it may invoke managed finalizers).
4311 mono_domain_finalize (domain, 2000);
4314 /* This accesses metadata so needs to be called before runtime shutdown */
4317 #ifndef MONO_CROSS_COMPILE
4318 mono_runtime_cleanup (domain);
4321 mono_threadpool_cleanup ();
4323 mono_profiler_shutdown ();
4325 free_jit_tls_data ((MonoJitTlsData *)mono_tls_get_jit_tls ());
4327 mono_icall_cleanup ();
4329 mono_runtime_cleanup_handlers ();
4331 #ifndef MONO_CROSS_COMPILE
4332 mono_domain_free (domain, TRUE);
4337 mono_llvm_cleanup ();
4340 mono_aot_cleanup ();
4342 mono_trampolines_cleanup ();
4344 mono_unwind_cleanup ();
4346 mono_code_manager_destroy (global_codeman);
4347 g_free (vtable_trampolines);
4349 mini_jit_cleanup ();
4351 mono_tramp_info_cleanup ();
4353 mono_arch_cleanup ();
4355 mono_generic_sharing_cleanup ();
4359 mono_trace_cleanup ();
4361 mono_counters_dump (MONO_COUNTER_SECTION_MASK | MONO_COUNTER_MONOTONIC, stdout);
4363 if (mono_inject_async_exc_method)
4364 mono_method_desc_free (mono_inject_async_exc_method);
4366 mono_tls_free_keys ();
4368 mono_os_mutex_destroy (&jit_mutex);
4370 mono_code_manager_cleanup ();
4373 mono_w32handle_cleanup ();
4378 mono_set_defaults (int verbose_level, guint32 opts)
4380 mini_verbose = verbose_level;
4381 mono_set_optimizations (opts);
4385 mono_disable_optimizations (guint32 opts)
4387 default_opt &= ~opts;
4391 mono_set_optimizations (guint32 opts)
4394 default_opt_set = TRUE;
4395 #ifdef MONO_ARCH_GSHAREDVT_SUPPORTED
4396 mono_set_generic_sharing_vt_supported (mono_aot_only || ((default_opt & MONO_OPT_GSHAREDVT) != 0));
4399 mono_set_generic_sharing_vt_supported (TRUE);
4404 mono_set_verbose_level (guint32 level)
4406 mini_verbose = level;
4410 * mono_get_runtime_build_info:
4411 * The returned string is owned by the caller. The returned string
4412 * format is <code>VERSION (FULL_VERSION BUILD_DATE)</code> and build date is optional.
4413 * \returns the runtime version + build date in string format.
4416 mono_get_runtime_build_info (void)
4418 if (mono_build_date)
4419 return g_strdup_printf ("%s (%s %s)", VERSION, FULL_VERSION, mono_build_date);
4421 return g_strdup_printf ("%s (%s)", VERSION, FULL_VERSION);
4425 mono_precompile_assembly (MonoAssembly *ass, void *user_data)
4427 GHashTable *assemblies = (GHashTable*)user_data;
4428 MonoImage *image = mono_assembly_get_image (ass);
4429 MonoMethod *method, *invoke;
4432 if (g_hash_table_lookup (assemblies, ass))
4435 g_hash_table_insert (assemblies, ass, ass);
4437 if (mini_verbose > 0)
4438 printf ("PRECOMPILE: %s.\n", mono_image_get_filename (image));
4440 for (i = 0; i < mono_image_get_table_rows (image, MONO_TABLE_METHOD); ++i) {
4443 method = mono_get_method_checked (image, MONO_TOKEN_METHOD_DEF | (i + 1), NULL, NULL, &error);
4445 mono_error_cleanup (&error); /* FIXME don't swallow the error */
4448 if (method->flags & METHOD_ATTRIBUTE_ABSTRACT)
4450 if (method->is_generic || mono_class_is_gtd (method->klass))
4454 if (mini_verbose > 1) {
4455 char * desc = mono_method_full_name (method, TRUE);
4456 g_print ("Compiling %d %s\n", count, desc);
4459 mono_compile_method_checked (method, &error);
4460 if (!is_ok (&error)) {
4461 mono_error_cleanup (&error); /* FIXME don't swallow the error */
4464 if (strcmp (method->name, "Finalize") == 0) {
4465 invoke = mono_marshal_get_runtime_invoke (method, FALSE);
4466 mono_compile_method_checked (invoke, &error);
4467 mono_error_assert_ok (&error);
4469 #ifndef DISABLE_REMOTING
4470 if (mono_class_is_marshalbyref (method->klass) && mono_method_signature (method)->hasthis) {
4471 invoke = mono_marshal_get_remoting_invoke_with_check (method);
4472 mono_compile_method_checked (invoke, &error);
4473 mono_error_assert_ok (&error);
4478 /* Load and precompile referenced assemblies as well */
4479 for (i = 0; i < mono_image_get_table_rows (image, MONO_TABLE_ASSEMBLYREF); ++i) {
4480 mono_assembly_load_reference (image, i);
4481 if (image->references [i])
4482 mono_precompile_assembly (image->references [i], assemblies);
4486 void mono_precompile_assemblies ()
4488 GHashTable *assemblies = g_hash_table_new (NULL, NULL);
4490 mono_assembly_foreach ((GFunc)mono_precompile_assembly, assemblies);
4492 g_hash_table_destroy (assemblies);
4497 * Have to export this for AOT.
4500 mono_personality (void)
4503 g_assert_not_reached ();
4506 // Custom handlers currently only implemented by Windows.
4509 mono_runtime_install_custom_handlers (const char *handlers)
4515 mono_runtime_install_custom_handlers_usage (void)
4518 "Custom Handlers:\n"
4519 " --handlers=HANDLERS Enable handler support, HANDLERS is a comma\n"
4520 " separated list of available handlers to install.\n"
4522 "No handlers supported on current platform.\n");
4524 #endif /* HOST_WIN32 */