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)
480 gboolean postpone_domain_reg;
486 domain = mono_get_root_domain ();
489 postpone_domain_reg = FALSE;
490 g_assert (domain->mp);
491 copy = mono_mempool_alloc0 (domain->mp, sizeof (MonoTrampInfo));
493 postpone_domain_reg = TRUE;
494 copy = g_new0 (MonoTrampInfo, 1);
497 copy->code = info->code;
498 copy->code_size = info->code_size;
499 copy->name = g_strdup (info->name);
501 if (info->unwind_ops) {
502 copy->uw_info = mono_unwind_ops_encode (info->unwind_ops, ©->uw_info_len);
503 copy->owns_uw_info = TRUE;
505 /* Trampolines from aot have the unwind ops already encoded */
506 copy->uw_info = info->uw_info;
507 copy->uw_info_len = info->uw_info_len;
510 mono_save_trampoline_xdebug_info (info);
511 mono_lldb_save_trampoline_info (info);
513 #ifdef MONO_ARCH_HAVE_UNWIND_TABLE
515 mono_arch_unwindinfo_install_tramp_unwind_info (info->unwind_ops, info->code, info->code_size);
518 if (postpone_domain_reg) {
520 tramp_infos = g_slist_prepend (tramp_infos, copy);
522 } else if (copy->uw_info) {
523 /* Only register trampolines that have unwind infos */
524 register_trampoline_jit_info (domain, copy);
527 if (mono_jit_map_is_enabled ())
528 mono_emit_jit_tramp (info->code, info->code_size, info->name);
530 mono_tramp_info_free (info);
534 mono_tramp_info_register (MonoTrampInfo *info, MonoDomain *domain)
536 mono_tramp_info_register_internal (info, domain, FALSE);
540 mono_aot_tramp_info_register (MonoTrampInfo *info, MonoDomain *domain)
542 mono_tramp_info_register_internal (info, domain, TRUE);
546 mono_tramp_info_cleanup (void)
550 for (l = tramp_infos; l; l = l->next) {
551 MonoTrampInfo *info = (MonoTrampInfo *)l->data;
553 mono_tramp_info_free (info);
555 g_slist_free (tramp_infos);
558 /* Register trampolines created before the root domain was created in the jit info tables */
560 register_trampolines (MonoDomain *domain)
564 for (l = tramp_infos; l; l = l->next) {
565 MonoTrampInfo *info = (MonoTrampInfo *)l->data;
567 register_trampoline_jit_info (domain, info);
571 G_GNUC_UNUSED static void
577 * Runtime debugging tool, use if (debug_count ()) <x> else <y> to do <x> the first COUNT times, then do <y> afterwards.
578 * Set a breakpoint in break_count () to break the last time <x> is done.
580 G_GNUC_UNUSED gboolean
581 mono_debug_count (void)
583 static int count = 0;
584 static gboolean inited;
590 value = g_getenv ("COUNT");
597 int int_val = atoi (value);
600 if (count == int_val)
610 mono_icall_get_wrapper_full (MonoJitICallInfo* callinfo, gboolean do_compile)
615 gconstpointer trampoline;
616 MonoDomain *domain = mono_get_root_domain ();
617 gboolean check_exc = TRUE;
619 if (callinfo->wrapper)
620 return callinfo->wrapper;
622 if (callinfo->trampoline)
623 return callinfo->trampoline;
625 if (!strcmp (callinfo->name, "mono_thread_interruption_checkpoint"))
626 /* This icall is used to check for exceptions, so don't check in the wrapper */
629 name = g_strdup_printf ("__icall_wrapper_%s", callinfo->name);
630 wrapper = mono_marshal_get_icall_wrapper (callinfo->sig, name, callinfo->func, check_exc);
634 trampoline = mono_compile_method_checked (wrapper, &error);
635 mono_error_assert_ok (&error);
638 trampoline = mono_create_jit_trampoline (domain, wrapper, &error);
639 mono_error_assert_ok (&error);
640 trampoline = mono_create_ftnptr (domain, (gpointer)trampoline);
644 if (!callinfo->trampoline) {
645 mono_register_jit_icall_wrapper (callinfo, trampoline);
646 callinfo->trampoline = trampoline;
648 mono_loader_unlock ();
650 return callinfo->trampoline;
654 mono_icall_get_wrapper (MonoJitICallInfo* callinfo)
656 return mono_icall_get_wrapper_full (callinfo, FALSE);
659 static MonoJitDynamicMethodInfo*
660 mono_dynamic_code_hash_lookup (MonoDomain *domain, MonoMethod *method)
662 MonoJitDynamicMethodInfo *res;
664 if (domain_jit_info (domain)->dynamic_code_hash)
665 res = (MonoJitDynamicMethodInfo *)g_hash_table_lookup (domain_jit_info (domain)->dynamic_code_hash, method);
672 register_opcode_emulation (int opcode, const char *name, const char *sigstr, gpointer func, const char *symbol, gboolean no_throw)
675 mini_register_opcode_emulation (opcode, name, sigstr, func, symbol, no_throw);
677 MonoMethodSignature *sig = mono_create_icall_signature (sigstr);
679 g_assert (!sig->hasthis);
680 g_assert (sig->param_count < 3);
682 /* Opcode emulation functions are assumed to don't call mono_raise_exception () */
683 mono_register_jit_icall_full (func, name, sig, no_throw, TRUE, symbol);
688 * For JIT icalls implemented in C.
689 * NAME should be the same as the name of the C function whose address is FUNC.
690 * If @avoid_wrapper is TRUE, no wrapper is generated. This is for perf critical icalls which
691 * can't throw exceptions.
694 register_icall (gpointer func, const char *name, const char *sigstr, gboolean avoid_wrapper)
696 MonoMethodSignature *sig;
699 sig = mono_create_icall_signature (sigstr);
703 mono_register_jit_icall_full (func, name, sig, avoid_wrapper, FALSE, avoid_wrapper ? name : NULL);
707 register_icall_no_wrapper (gpointer func, const char *name, const char *sigstr)
709 MonoMethodSignature *sig;
712 sig = mono_create_icall_signature (sigstr);
716 mono_register_jit_icall_full (func, name, sig, TRUE, FALSE, name);
720 register_icall_with_wrapper (gpointer func, const char *name, const char *sigstr)
722 MonoMethodSignature *sig;
725 sig = mono_create_icall_signature (sigstr);
729 mono_register_jit_icall_full (func, name, sig, FALSE, FALSE, NULL);
733 register_dyn_icall (gpointer func, const char *name, const char *sigstr, gboolean save)
735 MonoMethodSignature *sig;
738 sig = mono_create_icall_signature (sigstr);
742 mono_register_jit_icall (func, name, sig, save);
748 MonoJitTlsData *jit_tls;
750 if ((jit_tls = mono_tls_get_jit_tls ()))
753 * We do not assert here because this function can be called from
754 * mini-gc.c on a thread that has not executed any managed code, yet
755 * (the thread object allocation can trigger a collection).
761 mono_get_lmf_addr (void)
763 return (MonoLMF **)mono_tls_get_lmf_addr ();
767 mono_set_lmf (MonoLMF *lmf)
769 (*mono_get_lmf_addr ()) = lmf;
773 mono_get_jit_tls (void)
775 return (MonoJitTlsData *)mono_tls_get_jit_tls ();
779 mono_set_jit_tls (MonoJitTlsData *jit_tls)
781 MonoThreadInfo *info;
783 mono_tls_set_jit_tls (jit_tls);
785 /* Save it into MonoThreadInfo so it can be accessed by mono_thread_state_init_from_handle () */
786 info = mono_thread_info_current ();
788 mono_thread_info_tls_set (info, TLS_KEY_JIT_TLS, jit_tls);
792 mono_set_lmf_addr (gpointer lmf_addr)
794 MonoThreadInfo *info;
796 mono_tls_set_lmf_addr (lmf_addr);
798 /* Save it into MonoThreadInfo so it can be accessed by mono_thread_state_init_from_handle () */
799 info = mono_thread_info_current ();
801 mono_thread_info_tls_set (info, TLS_KEY_LMF_ADDR, lmf_addr);
805 * mono_jit_thread_attach:
807 * Called by Xamarin.Mac and other products. Attach thread to runtime if
808 * needed and switch to @domain.
810 * @return the original domain which needs to be restored, or NULL.
813 mono_jit_thread_attach (MonoDomain *domain)
818 g_assert (!mono_threads_is_coop_enabled ());
821 /* Happens when called from AOTed code which is only used in the root domain. */
822 domain = mono_get_root_domain ();
827 attached = mono_tls_get_jit_tls () != NULL;
830 mono_thread_attach (domain);
833 mono_thread_set_state (mono_thread_internal_current (), ThreadState_Background);
836 orig = mono_domain_get ();
838 mono_domain_set (domain, TRUE);
840 return orig != domain ? orig : NULL;
844 * mono_jit_set_domain:
846 * Set domain to @domain if @domain is not null
849 mono_jit_set_domain (MonoDomain *domain)
851 g_assert (!mono_threads_is_coop_enabled ());
854 mono_domain_set (domain, TRUE);
859 * \param obj exception object
860 * Abort the thread, print exception information and stack trace
863 mono_thread_abort (MonoObject *obj)
865 /* MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_tls_get_jit_tls (); */
867 /* handle_remove should be eventually called for this thread, too
870 if ((mono_runtime_unhandled_exception_policy_get () == MONO_UNHANDLED_POLICY_LEGACY) ||
871 (obj->vtable->klass == mono_defaults.threadabortexception_class)) {
874 mono_invoke_unhandled_exception_hook (obj);
879 setup_jit_tls_data (gpointer stack_start, gpointer abort_func)
881 MonoJitTlsData *jit_tls;
884 jit_tls = (MonoJitTlsData *)mono_tls_get_jit_tls ();
888 jit_tls = g_new0 (MonoJitTlsData, 1);
890 jit_tls->abort_func = (void (*)(MonoObject *))abort_func;
891 jit_tls->end_of_stack = stack_start;
893 mono_set_jit_tls (jit_tls);
895 lmf = g_new0 (MonoLMF, 1);
896 MONO_ARCH_INIT_TOP_LMF_ENTRY (lmf);
898 jit_tls->first_lmf = lmf;
900 mono_set_lmf_addr (&jit_tls->lmf);
904 #ifdef MONO_ARCH_HAVE_TLS_INIT
905 mono_arch_tls_init ();
908 mono_setup_altstack (jit_tls);
914 free_jit_tls_data (MonoJitTlsData *jit_tls)
916 mono_arch_free_jit_tls_data (jit_tls);
917 mono_free_altstack (jit_tls);
919 g_free (jit_tls->first_lmf);
924 mono_thread_start_cb (intptr_t tid, gpointer stack_start, gpointer func)
926 MonoThreadInfo *thread;
927 void *jit_tls = setup_jit_tls_data (stack_start, mono_thread_abort);
928 thread = mono_thread_info_current_unchecked ();
930 thread->jit_data = jit_tls;
932 mono_arch_cpu_init ();
935 void (*mono_thread_attach_aborted_cb ) (MonoObject *obj) = NULL;
938 mono_thread_abort_dummy (MonoObject *obj)
940 if (mono_thread_attach_aborted_cb)
941 mono_thread_attach_aborted_cb (obj);
943 mono_thread_abort (obj);
947 mono_thread_attach_cb (intptr_t tid, gpointer stack_start)
949 MonoThreadInfo *thread;
950 void *jit_tls = setup_jit_tls_data (stack_start, mono_thread_abort_dummy);
951 thread = mono_thread_info_current_unchecked ();
953 thread->jit_data = jit_tls;
955 mono_arch_cpu_init ();
959 mini_thread_cleanup (MonoNativeThreadId tid)
961 MonoJitTlsData *jit_tls = NULL;
962 MonoThreadInfo *info;
964 info = mono_thread_info_current_unchecked ();
966 /* We can't clean up tls information if we are on another thread, it will clean up the wrong stuff
967 * It would be nice to issue a warning when this happens outside of the shutdown sequence. but it's
968 * not a trivial thing.
970 * The current offender is mono_thread_manage which cleanup threads from the outside.
972 if (info && mono_thread_info_get_tid (info) == tid) {
973 jit_tls = (MonoJitTlsData *)info->jit_data;
974 info->jit_data = NULL;
976 mono_set_jit_tls (NULL);
978 /* If we attach a thread but never call into managed land, we might never get an lmf.*/
979 if (mono_get_lmf ()) {
981 mono_set_lmf_addr (NULL);
984 info = mono_thread_info_lookup (tid);
986 jit_tls = (MonoJitTlsData *)info->jit_data;
987 info->jit_data = NULL;
989 mono_hazard_pointer_clear (mono_hazard_pointer_get (), 1);
993 free_jit_tls_data (jit_tls);
997 mono_patch_info_list_prepend (MonoJumpInfo *list, int ip, MonoJumpInfoType type, gconstpointer target)
999 MonoJumpInfo *ji = g_new0 (MonoJumpInfo, 1);
1003 ji->data.target = target;
1009 #if !defined(DISABLE_LOGGING) && !defined(DISABLE_JIT)
1011 static const char* const patch_info_str[] = {
1012 #define PATCH_INFO(a,b) "" #a,
1013 #include "patch-info.h"
1018 mono_ji_type_to_string (MonoJumpInfoType type)
1020 return patch_info_str [type];
1024 mono_print_ji (const MonoJumpInfo *ji)
1027 case MONO_PATCH_INFO_RGCTX_FETCH: {
1028 MonoJumpInfoRgctxEntry *entry = ji->data.rgctx_entry;
1030 printf ("[RGCTX_FETCH ");
1031 mono_print_ji (entry->data);
1032 printf (" - %s]", mono_rgctx_info_type_to_str (entry->info_type));
1035 case MONO_PATCH_INFO_METHODCONST: {
1036 char *s = mono_method_full_name (ji->data.method, TRUE);
1037 printf ("[METHODCONST - %s]", s);
1041 case MONO_PATCH_INFO_INTERNAL_METHOD: {
1042 printf ("[INTERNAL_METHOD - %s]", ji->data.name);
1046 printf ("[%s]", patch_info_str [ji->type]);
1054 mono_ji_type_to_string (MonoJumpInfoType type)
1060 mono_print_ji (const MonoJumpInfo *ji)
1067 * mono_patch_info_dup_mp:
1069 * Make a copy of PATCH_INFO, allocating memory from the mempool MP.
1072 mono_patch_info_dup_mp (MonoMemPool *mp, MonoJumpInfo *patch_info)
1074 MonoJumpInfo *res = (MonoJumpInfo *)mono_mempool_alloc (mp, sizeof (MonoJumpInfo));
1075 memcpy (res, patch_info, sizeof (MonoJumpInfo));
1077 switch (patch_info->type) {
1078 case MONO_PATCH_INFO_RVA:
1079 case MONO_PATCH_INFO_LDSTR:
1080 case MONO_PATCH_INFO_TYPE_FROM_HANDLE:
1081 case MONO_PATCH_INFO_LDTOKEN:
1082 case MONO_PATCH_INFO_DECLSEC:
1083 res->data.token = (MonoJumpInfoToken *)mono_mempool_alloc (mp, sizeof (MonoJumpInfoToken));
1084 memcpy (res->data.token, patch_info->data.token, sizeof (MonoJumpInfoToken));
1086 case MONO_PATCH_INFO_SWITCH:
1087 res->data.table = (MonoJumpInfoBBTable *)mono_mempool_alloc (mp, sizeof (MonoJumpInfoBBTable));
1088 memcpy (res->data.table, patch_info->data.table, sizeof (MonoJumpInfoBBTable));
1089 res->data.table->table = (MonoBasicBlock **)mono_mempool_alloc (mp, sizeof (MonoBasicBlock*) * patch_info->data.table->table_size);
1090 memcpy (res->data.table->table, patch_info->data.table->table, sizeof (MonoBasicBlock*) * patch_info->data.table->table_size);
1092 case MONO_PATCH_INFO_RGCTX_FETCH:
1093 case MONO_PATCH_INFO_RGCTX_SLOT_INDEX:
1094 res->data.rgctx_entry = (MonoJumpInfoRgctxEntry *)mono_mempool_alloc (mp, sizeof (MonoJumpInfoRgctxEntry));
1095 memcpy (res->data.rgctx_entry, patch_info->data.rgctx_entry, sizeof (MonoJumpInfoRgctxEntry));
1096 res->data.rgctx_entry->data = mono_patch_info_dup_mp (mp, res->data.rgctx_entry->data);
1098 case MONO_PATCH_INFO_DELEGATE_TRAMPOLINE:
1099 res->data.del_tramp = (MonoDelegateClassMethodPair *)mono_mempool_alloc0 (mp, sizeof (MonoDelegateClassMethodPair));
1100 memcpy (res->data.del_tramp, patch_info->data.del_tramp, sizeof (MonoDelegateClassMethodPair));
1102 case MONO_PATCH_INFO_GSHAREDVT_CALL:
1103 res->data.gsharedvt = (MonoJumpInfoGSharedVtCall *)mono_mempool_alloc (mp, sizeof (MonoJumpInfoGSharedVtCall));
1104 memcpy (res->data.gsharedvt, patch_info->data.gsharedvt, sizeof (MonoJumpInfoGSharedVtCall));
1106 case MONO_PATCH_INFO_GSHAREDVT_METHOD: {
1107 MonoGSharedVtMethodInfo *info;
1108 MonoGSharedVtMethodInfo *oinfo;
1111 oinfo = patch_info->data.gsharedvt_method;
1112 info = (MonoGSharedVtMethodInfo *)mono_mempool_alloc (mp, sizeof (MonoGSharedVtMethodInfo));
1113 res->data.gsharedvt_method = info;
1114 memcpy (info, oinfo, sizeof (MonoGSharedVtMethodInfo));
1115 info->entries = (MonoRuntimeGenericContextInfoTemplate *)mono_mempool_alloc (mp, sizeof (MonoRuntimeGenericContextInfoTemplate) * info->count_entries);
1116 for (i = 0; i < oinfo->num_entries; ++i) {
1117 MonoRuntimeGenericContextInfoTemplate *otemplate = &oinfo->entries [i];
1118 MonoRuntimeGenericContextInfoTemplate *template_ = &info->entries [i];
1120 memcpy (template_, otemplate, sizeof (MonoRuntimeGenericContextInfoTemplate));
1122 //info->locals_types = mono_mempool_alloc0 (mp, info->nlocals * sizeof (MonoType*));
1123 //memcpy (info->locals_types, oinfo->locals_types, info->nlocals * sizeof (MonoType*));
1126 case MONO_PATCH_INFO_VIRT_METHOD: {
1127 MonoJumpInfoVirtMethod *info;
1128 MonoJumpInfoVirtMethod *oinfo;
1130 oinfo = patch_info->data.virt_method;
1131 info = (MonoJumpInfoVirtMethod *)mono_mempool_alloc0 (mp, sizeof (MonoJumpInfoVirtMethod));
1132 res->data.virt_method = info;
1133 memcpy (info, oinfo, sizeof (MonoJumpInfoVirtMethod));
1144 mono_patch_info_hash (gconstpointer data)
1146 const MonoJumpInfo *ji = (MonoJumpInfo*)data;
1149 case MONO_PATCH_INFO_RVA:
1150 case MONO_PATCH_INFO_LDSTR:
1151 case MONO_PATCH_INFO_LDTOKEN:
1152 case MONO_PATCH_INFO_DECLSEC:
1153 return (ji->type << 8) | ji->data.token->token;
1154 case MONO_PATCH_INFO_TYPE_FROM_HANDLE:
1155 return (ji->type << 8) | ji->data.token->token | (ji->data.token->has_context ? (gsize)ji->data.token->context.class_inst : 0);
1156 case MONO_PATCH_INFO_INTERNAL_METHOD:
1157 return (ji->type << 8) | g_str_hash (ji->data.name);
1158 case MONO_PATCH_INFO_VTABLE:
1159 case MONO_PATCH_INFO_CLASS:
1160 case MONO_PATCH_INFO_IID:
1161 case MONO_PATCH_INFO_ADJUSTED_IID:
1162 case MONO_PATCH_INFO_METHODCONST:
1163 case MONO_PATCH_INFO_METHOD:
1164 case MONO_PATCH_INFO_METHOD_JUMP:
1165 case MONO_PATCH_INFO_IMAGE:
1166 case MONO_PATCH_INFO_ICALL_ADDR:
1167 case MONO_PATCH_INFO_ICALL_ADDR_CALL:
1168 case MONO_PATCH_INFO_FIELD:
1169 case MONO_PATCH_INFO_SFLDA:
1170 case MONO_PATCH_INFO_SEQ_POINT_INFO:
1171 case MONO_PATCH_INFO_METHOD_RGCTX:
1172 case MONO_PATCH_INFO_SIGNATURE:
1173 case MONO_PATCH_INFO_METHOD_CODE_SLOT:
1174 case MONO_PATCH_INFO_AOT_JIT_INFO:
1175 case MONO_PATCH_INFO_GET_TLS_TRAMP:
1176 case MONO_PATCH_INFO_SET_TLS_TRAMP:
1177 return (ji->type << 8) | (gssize)ji->data.target;
1178 case MONO_PATCH_INFO_GSHAREDVT_CALL:
1179 return (ji->type << 8) | (gssize)ji->data.gsharedvt->method;
1180 case MONO_PATCH_INFO_RGCTX_FETCH:
1181 case MONO_PATCH_INFO_RGCTX_SLOT_INDEX: {
1182 MonoJumpInfoRgctxEntry *e = ji->data.rgctx_entry;
1184 return (ji->type << 8) | (gssize)e->method | (e->in_mrgctx) | e->info_type | mono_patch_info_hash (e->data);
1186 case MONO_PATCH_INFO_INTERRUPTION_REQUEST_FLAG:
1187 case MONO_PATCH_INFO_MSCORLIB_GOT_ADDR:
1188 case MONO_PATCH_INFO_GC_CARD_TABLE_ADDR:
1189 case MONO_PATCH_INFO_GC_NURSERY_START:
1190 case MONO_PATCH_INFO_GC_NURSERY_BITS:
1191 case MONO_PATCH_INFO_GOT_OFFSET:
1192 case MONO_PATCH_INFO_GC_SAFE_POINT_FLAG:
1193 case MONO_PATCH_INFO_AOT_MODULE:
1194 case MONO_PATCH_INFO_JIT_THREAD_ATTACH:
1195 return (ji->type << 8);
1196 case MONO_PATCH_INFO_CASTCLASS_CACHE:
1197 return (ji->type << 8) | (ji->data.index);
1198 case MONO_PATCH_INFO_SWITCH:
1199 return (ji->type << 8) | ji->data.table->table_size;
1200 case MONO_PATCH_INFO_GSHAREDVT_METHOD:
1201 return (ji->type << 8) | (gssize)ji->data.gsharedvt_method->method;
1202 case MONO_PATCH_INFO_OBJC_SELECTOR_REF:
1203 /* Hash on the selector name */
1204 return g_str_hash (ji->data.target);
1205 case MONO_PATCH_INFO_DELEGATE_TRAMPOLINE:
1206 return (ji->type << 8) | (gsize)ji->data.del_tramp->klass | (gsize)ji->data.del_tramp->method | (gsize)ji->data.del_tramp->is_virtual;
1207 case MONO_PATCH_INFO_LDSTR_LIT:
1208 return g_str_hash (ji->data.target);
1209 case MONO_PATCH_INFO_VIRT_METHOD: {
1210 MonoJumpInfoVirtMethod *info = ji->data.virt_method;
1212 return (ji->type << 8) | (gssize)info->klass | (gssize)info->method;
1214 case MONO_PATCH_INFO_JIT_ICALL_ADDR:
1215 return (ji->type << 8) | g_str_hash (ji->data.target);
1216 case MONO_PATCH_INFO_GSHAREDVT_IN_WRAPPER:
1217 return (ji->type << 8) | mono_signature_hash (ji->data.sig);
1219 printf ("info type: %d\n", ji->type);
1220 mono_print_ji (ji); printf ("\n");
1221 g_assert_not_reached ();
1227 * mono_patch_info_equal:
1229 * This might fail to recognize equivalent patches, i.e. floats, so its only
1230 * usable in those cases where this is not a problem, i.e. sharing GOT slots
1234 mono_patch_info_equal (gconstpointer ka, gconstpointer kb)
1236 const MonoJumpInfo *ji1 = (MonoJumpInfo*)ka;
1237 const MonoJumpInfo *ji2 = (MonoJumpInfo*)kb;
1239 if (ji1->type != ji2->type)
1242 switch (ji1->type) {
1243 case MONO_PATCH_INFO_RVA:
1244 case MONO_PATCH_INFO_LDSTR:
1245 case MONO_PATCH_INFO_TYPE_FROM_HANDLE:
1246 case MONO_PATCH_INFO_LDTOKEN:
1247 case MONO_PATCH_INFO_DECLSEC:
1248 if ((ji1->data.token->image != ji2->data.token->image) ||
1249 (ji1->data.token->token != ji2->data.token->token) ||
1250 (ji1->data.token->has_context != ji2->data.token->has_context) ||
1251 (ji1->data.token->context.class_inst != ji2->data.token->context.class_inst) ||
1252 (ji1->data.token->context.method_inst != ji2->data.token->context.method_inst))
1255 case MONO_PATCH_INFO_INTERNAL_METHOD:
1256 return g_str_equal (ji1->data.name, ji2->data.name);
1257 case MONO_PATCH_INFO_RGCTX_FETCH:
1258 case MONO_PATCH_INFO_RGCTX_SLOT_INDEX: {
1259 MonoJumpInfoRgctxEntry *e1 = ji1->data.rgctx_entry;
1260 MonoJumpInfoRgctxEntry *e2 = ji2->data.rgctx_entry;
1262 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);
1264 case MONO_PATCH_INFO_GSHAREDVT_CALL: {
1265 MonoJumpInfoGSharedVtCall *c1 = ji1->data.gsharedvt;
1266 MonoJumpInfoGSharedVtCall *c2 = ji2->data.gsharedvt;
1268 return c1->sig == c2->sig && c1->method == c2->method;
1270 case MONO_PATCH_INFO_GSHAREDVT_METHOD:
1271 return ji1->data.gsharedvt_method->method == ji2->data.gsharedvt_method->method;
1272 case MONO_PATCH_INFO_DELEGATE_TRAMPOLINE:
1273 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;
1274 case MONO_PATCH_INFO_CASTCLASS_CACHE:
1275 return ji1->data.index == ji2->data.index;
1276 case MONO_PATCH_INFO_VIRT_METHOD:
1277 return ji1->data.virt_method->klass == ji2->data.virt_method->klass && ji1->data.virt_method->method == ji2->data.virt_method->method;
1278 case MONO_PATCH_INFO_JIT_ICALL_ADDR:
1279 if (ji1->data.target == ji2->data.target)
1281 return strcmp (ji1->data.target, ji2->data.target) == 0 ? 1 : 0;
1282 case MONO_PATCH_INFO_GSHAREDVT_IN_WRAPPER:
1283 return mono_metadata_signature_equal (ji1->data.sig, ji2->data.sig) ? 1 : 0;
1285 if (ji1->data.target != ji2->data.target)
1294 mono_resolve_patch_target (MonoMethod *method, MonoDomain *domain, guint8 *code, MonoJumpInfo *patch_info, gboolean run_cctors, MonoError *error)
1296 unsigned char *ip = patch_info->ip.i + code;
1297 gconstpointer target = NULL;
1301 switch (patch_info->type) {
1302 case MONO_PATCH_INFO_BB:
1304 * FIXME: This could be hit for methods without a prolog. Should use -1
1305 * but too much code depends on a 0 initial value.
1307 //g_assert (patch_info->data.bb->native_offset);
1308 target = patch_info->data.bb->native_offset + code;
1310 case MONO_PATCH_INFO_ABS:
1311 target = patch_info->data.target;
1313 case MONO_PATCH_INFO_LABEL:
1314 target = patch_info->data.inst->inst_c0 + code;
1316 case MONO_PATCH_INFO_IP:
1319 case MONO_PATCH_INFO_METHOD_REL:
1320 target = code + patch_info->data.offset;
1322 case MONO_PATCH_INFO_INTERNAL_METHOD: {
1323 MonoJitICallInfo *mi = mono_find_jit_icall_by_name (patch_info->data.name);
1325 g_warning ("unknown MONO_PATCH_INFO_INTERNAL_METHOD %s", patch_info->data.name);
1326 g_assert_not_reached ();
1328 target = mono_icall_get_wrapper (mi);
1331 case MONO_PATCH_INFO_JIT_ICALL_ADDR: {
1332 MonoJitICallInfo *mi = mono_find_jit_icall_by_name (patch_info->data.name);
1334 g_warning ("unknown MONO_PATCH_INFO_JIT_ICALL_ADDR %s", patch_info->data.name);
1335 g_assert_not_reached ();
1340 case MONO_PATCH_INFO_METHOD_JUMP:
1341 target = mono_create_jump_trampoline (domain, patch_info->data.method, FALSE, error);
1342 if (!mono_error_ok (error))
1345 case MONO_PATCH_INFO_METHOD:
1346 if (patch_info->data.method == method) {
1349 /* get the trampoline to the method from the domain */
1350 target = mono_create_jit_trampoline (domain, patch_info->data.method, error);
1351 if (!mono_error_ok (error))
1355 case MONO_PATCH_INFO_METHOD_CODE_SLOT: {
1358 mono_domain_lock (domain);
1359 if (!domain_jit_info (domain)->method_code_hash)
1360 domain_jit_info (domain)->method_code_hash = g_hash_table_new (NULL, NULL);
1361 code_slot = g_hash_table_lookup (domain_jit_info (domain)->method_code_hash, patch_info->data.method);
1363 code_slot = mono_domain_alloc0 (domain, sizeof (gpointer));
1364 g_hash_table_insert (domain_jit_info (domain)->method_code_hash, patch_info->data.method, code_slot);
1366 mono_domain_unlock (domain);
1370 case MONO_PATCH_INFO_GC_SAFE_POINT_FLAG:
1371 #if defined(__native_client_codegen__)
1372 target = (gpointer)&__nacl_thread_suspension_needed;
1374 g_assert (mono_threads_is_coop_enabled ());
1375 target = (gpointer)&mono_polling_required;
1378 case MONO_PATCH_INFO_SWITCH: {
1379 gpointer *jump_table;
1381 #if defined(__native_client__) && defined(__native_client_codegen__)
1382 /* This memory will leak, but we don't care if we're */
1383 /* not deleting JIT'd methods anyway */
1384 jump_table = g_malloc0 (sizeof(gpointer) * patch_info->data.table->table_size);
1386 if (method && method->dynamic) {
1387 jump_table = (void **)mono_code_manager_reserve (mono_dynamic_code_hash_lookup (domain, method)->code_mp, sizeof (gpointer) * patch_info->data.table->table_size);
1389 if (mono_aot_only) {
1390 jump_table = (void **)mono_domain_alloc (domain, sizeof (gpointer) * patch_info->data.table->table_size);
1392 jump_table = (void **)mono_domain_code_reserve (domain, sizeof (gpointer) * patch_info->data.table->table_size);
1397 for (i = 0; i < patch_info->data.table->table_size; i++) {
1398 jump_table [i] = code + GPOINTER_TO_INT (patch_info->data.table->table [i]);
1401 target = jump_table;
1404 case MONO_PATCH_INFO_METHODCONST:
1405 case MONO_PATCH_INFO_CLASS:
1406 case MONO_PATCH_INFO_IMAGE:
1407 case MONO_PATCH_INFO_FIELD:
1408 case MONO_PATCH_INFO_SIGNATURE:
1409 case MONO_PATCH_INFO_AOT_MODULE:
1410 target = patch_info->data.target;
1412 case MONO_PATCH_INFO_IID:
1413 mono_class_init (patch_info->data.klass);
1414 target = GUINT_TO_POINTER (patch_info->data.klass->interface_id);
1416 case MONO_PATCH_INFO_ADJUSTED_IID:
1417 mono_class_init (patch_info->data.klass);
1418 target = GUINT_TO_POINTER ((guint32)(-((patch_info->data.klass->interface_id + 1) * SIZEOF_VOID_P)));
1420 case MONO_PATCH_INFO_VTABLE:
1421 target = mono_class_vtable (domain, patch_info->data.klass);
1424 case MONO_PATCH_INFO_DELEGATE_TRAMPOLINE: {
1425 MonoDelegateClassMethodPair *del_tramp = patch_info->data.del_tramp;
1427 if (del_tramp->is_virtual)
1428 target = mono_create_delegate_virtual_trampoline (domain, del_tramp->klass, del_tramp->method);
1430 target = mono_create_delegate_trampoline_info (domain, del_tramp->klass, del_tramp->method);
1433 case MONO_PATCH_INFO_SFLDA: {
1434 MonoVTable *vtable = mono_class_vtable (domain, patch_info->data.field->parent);
1436 if (mono_class_field_is_special_static (patch_info->data.field)) {
1437 gpointer addr = NULL;
1439 mono_domain_lock (domain);
1440 if (domain->special_static_fields)
1441 addr = g_hash_table_lookup (domain->special_static_fields, patch_info->data.field);
1442 mono_domain_unlock (domain);
1448 if (!vtable->initialized && !mono_class_is_before_field_init (vtable->klass) && (method && mono_class_needs_cctor_run (vtable->klass, method)))
1449 /* Done by the generated code */
1453 if (!mono_runtime_class_init_full (vtable, error)) {
1458 target = (char*)mono_vtable_get_static_field_data (vtable) + patch_info->data.field->offset;
1461 case MONO_PATCH_INFO_RVA: {
1462 guint32 field_index = mono_metadata_token_index (patch_info->data.token->token);
1465 mono_metadata_field_info (patch_info->data.token->image, field_index - 1, NULL, &rva, NULL);
1466 target = mono_image_rva_map (patch_info->data.token->image, rva);
1469 case MONO_PATCH_INFO_R4:
1470 case MONO_PATCH_INFO_R8:
1471 target = patch_info->data.target;
1473 case MONO_PATCH_INFO_EXC_NAME:
1474 target = patch_info->data.name;
1476 case MONO_PATCH_INFO_LDSTR:
1478 mono_ldstr_checked (domain, patch_info->data.token->image,
1479 mono_metadata_token_index (patch_info->data.token->token), error);
1481 case MONO_PATCH_INFO_TYPE_FROM_HANDLE: {
1483 MonoClass *handle_class;
1485 handle = mono_ldtoken_checked (patch_info->data.token->image,
1486 patch_info->data.token->token, &handle_class, patch_info->data.token->has_context ? &patch_info->data.token->context : NULL, error);
1487 if (!mono_error_ok (error))
1489 mono_class_init (handle_class);
1490 mono_class_init (mono_class_from_mono_type ((MonoType *)handle));
1492 target = mono_type_get_object_checked (domain, (MonoType *)handle, error);
1493 if (!mono_error_ok (error))
1497 case MONO_PATCH_INFO_LDTOKEN: {
1499 MonoClass *handle_class;
1501 handle = mono_ldtoken_checked (patch_info->data.token->image,
1502 patch_info->data.token->token, &handle_class, patch_info->data.token->has_context ? &patch_info->data.token->context : NULL, error);
1503 if (!mono_error_ok (error))
1504 g_error ("Could not patch ldtoken due to %s", mono_error_get_message (error));
1505 mono_class_init (handle_class);
1510 case MONO_PATCH_INFO_DECLSEC:
1511 target = (mono_metadata_blob_heap (patch_info->data.token->image, patch_info->data.token->token) + 2);
1513 case MONO_PATCH_INFO_ICALL_ADDR:
1514 case MONO_PATCH_INFO_ICALL_ADDR_CALL:
1515 /* run_cctors == 0 -> AOT */
1516 if (patch_info->data.method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
1517 const char *exc_class;
1518 const char *exc_arg;
1521 target = mono_lookup_pinvoke_call (patch_info->data.method, &exc_class, &exc_arg);
1523 if (mono_aot_only) {
1524 mono_error_set_exception_instance (error, mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg));
1527 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));
1533 target = mono_lookup_internal_call (patch_info->data.method);
1535 if (!target && run_cctors)
1536 g_error ("Unregistered icall '%s'\n", mono_method_full_name (patch_info->data.method, TRUE));
1539 case MONO_PATCH_INFO_INTERRUPTION_REQUEST_FLAG:
1540 target = mono_thread_interruption_request_flag ();
1542 case MONO_PATCH_INFO_METHOD_RGCTX: {
1543 MonoVTable *vtable = mono_class_vtable (domain, patch_info->data.method->klass);
1546 target = mono_method_lookup_rgctx (vtable, mini_method_get_context (patch_info->data.method)->method_inst);
1549 case MONO_PATCH_INFO_RGCTX_SLOT_INDEX: {
1550 int slot = mini_get_rgctx_entry_slot (patch_info->data.rgctx_entry);
1552 target = GINT_TO_POINTER (MONO_RGCTX_SLOT_INDEX (slot));
1555 case MONO_PATCH_INFO_BB_OVF:
1556 case MONO_PATCH_INFO_EXC_OVF:
1557 case MONO_PATCH_INFO_GOT_OFFSET:
1558 case MONO_PATCH_INFO_NONE:
1560 case MONO_PATCH_INFO_RGCTX_FETCH: {
1561 int slot = mini_get_rgctx_entry_slot (patch_info->data.rgctx_entry);
1563 target = mono_create_rgctx_lazy_fetch_trampoline (slot);
1566 #ifdef MONO_ARCH_SOFT_DEBUG_SUPPORTED
1567 case MONO_PATCH_INFO_SEQ_POINT_INFO:
1569 /* AOT, not needed */
1572 target = mono_arch_get_seq_point_info (domain, code);
1575 case MONO_PATCH_INFO_GC_CARD_TABLE_ADDR: {
1576 int card_table_shift_bits;
1577 gpointer card_table_mask;
1579 target = mono_gc_get_card_table (&card_table_shift_bits, &card_table_mask);
1582 case MONO_PATCH_INFO_GC_NURSERY_START: {
1586 target = mono_gc_get_nursery (&shift_bits, &size);
1589 case MONO_PATCH_INFO_GC_NURSERY_BITS: {
1593 mono_gc_get_nursery (&shift_bits, &size);
1595 target = (gpointer)(mgreg_t)shift_bits;
1598 case MONO_PATCH_INFO_CASTCLASS_CACHE: {
1599 target = mono_domain_alloc0 (domain, sizeof (gpointer));
1602 case MONO_PATCH_INFO_OBJC_SELECTOR_REF: {
1606 case MONO_PATCH_INFO_LDSTR_LIT: {
1610 len = strlen ((const char *)patch_info->data.target);
1611 s = (char *)mono_domain_alloc0 (domain, len + 1);
1612 memcpy (s, patch_info->data.target, len);
1617 case MONO_PATCH_INFO_GSHAREDVT_IN_WRAPPER:
1618 target = mini_get_gsharedvt_wrapper (TRUE, NULL, patch_info->data.sig, NULL, -1, FALSE);
1620 case MONO_PATCH_INFO_GET_TLS_TRAMP:
1621 target = mono_tls_get_tls_getter (patch_info->data.index, FALSE);
1623 case MONO_PATCH_INFO_SET_TLS_TRAMP:
1624 target = mono_tls_get_tls_setter (patch_info->data.index, FALSE);
1626 case MONO_PATCH_INFO_JIT_THREAD_ATTACH: {
1627 MonoJitICallInfo *mi = mono_find_jit_icall_by_name ("mono_jit_thread_attach");
1633 g_assert_not_reached ();
1636 return (gpointer)target;
1640 mini_init_gsctx (MonoDomain *domain, MonoMemPool *mp, MonoGenericContext *context, MonoGenericSharingContext *gsctx)
1642 MonoGenericInst *inst;
1645 memset (gsctx, 0, sizeof (MonoGenericSharingContext));
1647 if (context && context->class_inst) {
1648 inst = context->class_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;
1656 if (context && context->method_inst) {
1657 inst = context->method_inst;
1659 for (i = 0; i < inst->type_argc; ++i) {
1660 MonoType *type = inst->type_argv [i];
1662 if (mini_is_gsharedvt_gparam (type))
1663 gsctx->is_gsharedvt = TRUE;
1669 * LOCKING: Acquires the jit code hash lock.
1672 mini_lookup_method (MonoDomain *domain, MonoMethod *method, MonoMethod *shared)
1675 static gboolean inited = FALSE;
1676 static int lookups = 0;
1677 static int failed_lookups = 0;
1679 mono_domain_jit_code_hash_lock (domain);
1680 ji = (MonoJitInfo *)mono_internal_hash_table_lookup (&domain->jit_code_hash, method);
1681 if (!ji && shared) {
1682 /* Try generic sharing */
1683 ji = (MonoJitInfo *)mono_internal_hash_table_lookup (&domain->jit_code_hash, shared);
1684 if (ji && !ji->has_generic_jit_info)
1687 mono_counters_register ("Shared generic lookups", MONO_COUNTER_INT|MONO_COUNTER_GENERICS, &lookups);
1688 mono_counters_register ("Failed shared generic lookups", MONO_COUNTER_INT|MONO_COUNTER_GENERICS, &failed_lookups);
1696 mono_domain_jit_code_hash_unlock (domain);
1702 lookup_method (MonoDomain *domain, MonoMethod *method)
1707 ji = mini_lookup_method (domain, method, NULL);
1710 if (!mono_method_is_generic_sharable (method, FALSE))
1712 shared = mini_get_shared_method (method);
1713 ji = mini_lookup_method (domain, method, shared);
1720 mono_get_jit_info_from_method (MonoDomain *domain, MonoMethod *method)
1722 return lookup_method (domain, method);
1726 static FILE* perf_map_file;
1729 mono_enable_jit_map (void)
1731 if (!perf_map_file) {
1733 g_snprintf (name, sizeof (name), "/tmp/perf-%d.map", getpid ());
1735 perf_map_file = fopen (name, "w");
1740 mono_emit_jit_tramp (void *start, int size, const char *desc)
1743 fprintf (perf_map_file, "%llx %x %s\n", (long long unsigned int)(gsize)start, size, desc);
1747 mono_emit_jit_map (MonoJitInfo *jinfo)
1749 if (perf_map_file) {
1750 char *name = mono_method_full_name (jinfo_get_method (jinfo), TRUE);
1751 mono_emit_jit_tramp (jinfo->code_start, jinfo->code_size, name);
1757 mono_jit_map_is_enabled (void)
1759 return perf_map_file != NULL;
1765 no_gsharedvt_in_wrapper (void)
1767 g_assert_not_reached ();
1773 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.
1774 If the current thread is already JITing another method, don't wait as it might cause a deadlock.
1775 Dependency management in this case is too complex to justify implementing it.
1777 If there are no outstanding requests, the current thread is doing nothing and there are already mono_cpu_count threads JITing, go to sleep.
1780 Get rid of cctor invocations from within the JIT, it increases JIT duration and complicates things A LOT.
1781 Can we get rid of ref_count and use `done && threads_waiting == 0` as the equivalent of `ref_count == 0`?
1782 Reduce amount of dynamically allocated - possible once the JIT is no longer reentrant
1783 Maybe pool JitCompilationEntry, specially those with an inited cond var;
1788 int compilation_count; /* Number of threads compiling this method - This happens due to the JIT being reentrant */
1789 int ref_count; /* Number of threads using this JitCompilationEntry, roughtly 1 + threads_waiting */
1790 int threads_waiting; /* Number of threads waiting on this job */
1791 gboolean has_cond; /* True if @cond was initialized */
1792 gboolean done; /* True if the method finished JIT'ing */
1793 MonoCoopCond cond; /* Cond sleeping threads wait one */
1794 } JitCompilationEntry;
1797 GPtrArray *in_flight_methods; //JitCompilationEntry*
1799 } JitCompilationData;
1801 static JitCompilationData compilation_data;
1802 static int jit_methods_waited, jit_methods_multiple, jit_methods_overload, jit_spurious_wakeups;
1805 mini_jit_init_job_control (void)
1807 mono_coop_mutex_init (&compilation_data.lock);
1808 compilation_data.in_flight_methods = g_ptr_array_new ();
1812 lock_compilation_data (void)
1814 mono_coop_mutex_lock (&compilation_data.lock);
1818 unlock_compilation_data (void)
1820 mono_coop_mutex_unlock (&compilation_data.lock);
1823 static JitCompilationEntry*
1824 find_method (MonoMethod *method, MonoDomain *domain)
1827 for (i = 0; i < compilation_data.in_flight_methods->len; ++i){
1828 JitCompilationEntry *e = compilation_data.in_flight_methods->pdata [i];
1829 if (e->method == method && e->domain == domain)
1837 add_current_thread (MonoJitTlsData *jit_tls)
1839 ++jit_tls->active_jit_methods;
1843 unref_jit_entry (JitCompilationEntry *entry)
1846 if (entry->ref_count)
1848 if (entry->has_cond)
1849 mono_coop_cond_destroy (&entry->cond);
1854 * Returns true if this method waited successfully for another thread to JIT it
1857 wait_or_register_method_to_compile (MonoMethod *method, MonoDomain *domain)
1859 MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_tls_get_jit_tls ();
1860 JitCompilationEntry *entry;
1862 static gboolean inited;
1864 mono_counters_register ("JIT compile waited others", MONO_COUNTER_INT|MONO_COUNTER_JIT, &jit_methods_waited);
1865 mono_counters_register ("JIT compile 1+ jobs", MONO_COUNTER_INT|MONO_COUNTER_JIT, &jit_methods_multiple);
1866 mono_counters_register ("JIT compile overload wait", MONO_COUNTER_INT|MONO_COUNTER_JIT, &jit_methods_overload);
1867 mono_counters_register ("JIT compile spurious wakeups", MONO_COUNTER_INT|MONO_COUNTER_JIT, &jit_spurious_wakeups);
1871 lock_compilation_data ();
1873 if (!(entry = find_method (method, domain))) {
1874 entry = g_new0 (JitCompilationEntry, 1);
1875 entry->method = method;
1876 entry->domain = domain;
1877 entry->compilation_count = entry->ref_count = 1;
1878 g_ptr_array_add (compilation_data.in_flight_methods, entry);
1879 g_assert (find_method (method, domain) == entry);
1880 add_current_thread (jit_tls);
1882 unlock_compilation_data ();
1884 } else if (jit_tls->active_jit_methods > 0) {
1885 //We can't suspend the current thread if it's already JITing a method.
1886 //Dependency management is too compilated and we want to get rid of this anyways.
1887 ++entry->compilation_count;
1888 ++jit_methods_multiple;
1889 ++jit_tls->active_jit_methods;
1891 unlock_compilation_data ();
1894 ++jit_methods_waited;
1897 if (!entry->has_cond) {
1898 mono_coop_cond_init (&entry->cond);
1899 entry->has_cond = TRUE;
1903 ++entry->threads_waiting;
1905 g_assert (entry->has_cond);
1906 mono_coop_cond_wait (&entry->cond, &compilation_data.lock);
1907 --entry->threads_waiting;
1910 unref_jit_entry (entry);
1911 unlock_compilation_data ();
1914 ++jit_spurious_wakeups;
1921 unregister_method_for_compile (MonoMethod *method, MonoDomain *target_domain)
1923 MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_tls_get_jit_tls ();
1925 lock_compilation_data ();
1927 g_assert (jit_tls->active_jit_methods > 0);
1928 --jit_tls->active_jit_methods;
1930 JitCompilationEntry *entry = find_method (method, target_domain);
1931 g_assert (entry); // It would be weird to fail
1934 if (entry->threads_waiting) {
1935 g_assert (entry->has_cond);
1936 mono_coop_cond_broadcast (&entry->cond);
1939 if (--entry->compilation_count == 0) {
1940 g_ptr_array_remove (compilation_data.in_flight_methods, entry);
1941 unref_jit_entry (entry);
1944 unlock_compilation_data ();
1949 mono_jit_compile_method_with_opt (MonoMethod *method, guint32 opt, gboolean jit_only, MonoError *error)
1951 MonoDomain *target_domain, *domain = mono_domain_get ();
1953 gpointer code = NULL, p;
1955 MonoJitICallInfo *callinfo = NULL;
1956 WrapperInfo *winfo = NULL;
1960 #ifdef ENABLE_INTERPRETER
1961 if (mono_use_interpreter && !jit_only) {
1962 code = mono_interp_create_method_pointer (method, error);
1969 /* Should be handled by the caller */
1970 g_assert (!(method->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED));
1973 * ICALL wrappers are handled specially, since there is only one copy of them
1974 * shared by all appdomains.
1976 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE)
1977 winfo = mono_marshal_get_wrapper_info (method);
1978 if (winfo && winfo->subtype == WRAPPER_SUBTYPE_ICALL_WRAPPER) {
1979 callinfo = mono_find_jit_icall_by_addr (winfo->d.icall.func);
1980 g_assert (callinfo);
1982 /* Must be domain neutral since there is only one copy */
1983 opt |= MONO_OPT_SHARED;
1985 /* MONO_OPT_SHARED is no longer supported, we only use it for icall wrappers */
1986 opt &= ~MONO_OPT_SHARED;
1989 if (opt & MONO_OPT_SHARED)
1990 target_domain = mono_get_root_domain ();
1992 target_domain = domain;
1994 if (method->wrapper_type == MONO_WRAPPER_UNKNOWN) {
1995 WrapperInfo *info = mono_marshal_get_wrapper_info (method);
1998 if (info->subtype == WRAPPER_SUBTYPE_SYNCHRONIZED_INNER) {
1999 MonoGenericContext *ctx = NULL;
2000 if (method->is_inflated)
2001 ctx = mono_method_get_context (method);
2002 method = info->d.synchronized_inner.method;
2004 method = mono_class_inflate_generic_method_checked (method, ctx, error);
2005 g_assert (mono_error_ok (error)); /* FIXME don't swallow the error */
2011 info = lookup_method (target_domain, method);
2013 /* We can't use a domain specific method in another domain */
2014 if (! ((domain != target_domain) && !info->domain_neutral)) {
2017 mono_jit_stats.methods_lookups++;
2018 vtable = mono_class_vtable_full (domain, method->klass, error);
2022 if (!mono_runtime_class_init_full (vtable, error))
2024 return mono_create_ftnptr (target_domain, info->code_start);
2028 #ifdef MONO_USE_AOT_COMPILER
2029 if (opt & MONO_OPT_AOT) {
2030 MonoDomain *domain = mono_domain_get ();
2032 mono_class_init (method->klass);
2034 if ((code = mono_aot_get_method_checked (domain, method, error))) {
2037 if (mono_runtime_is_critical_method (method) || mono_gc_is_critical_method (method)) {
2039 * The suspend code needs to be able to lookup these methods by ip in async context,
2040 * so preload their jit info.
2042 MonoJitInfo *ji = mono_jit_info_table_find (domain, code);
2047 * In llvm-only mode, method might be a shared method, so we can't initialize its class.
2048 * This is not a problem, since it will be initialized when the method is first
2049 * called by init_method ().
2051 if (!mono_llvm_only) {
2052 vtable = mono_class_vtable (domain, method->klass);
2054 if (!mono_runtime_class_init_full (vtable, error))
2063 if (!code && mono_llvm_only) {
2064 if (method->wrapper_type == MONO_WRAPPER_UNKNOWN) {
2065 WrapperInfo *info = mono_marshal_get_wrapper_info (method);
2067 if (info->subtype == WRAPPER_SUBTYPE_GSHAREDVT_IN_SIG) {
2069 * These wrappers are only created for signatures which are in the program, but
2070 * sometimes we load methods too eagerly and have to create them even if they
2071 * will never be called.
2073 return no_gsharedvt_in_wrapper;
2079 if (wait_or_register_method_to_compile (method, target_domain))
2081 code = mono_jit_compile_method_inner (method, target_domain, opt, error);
2082 unregister_method_for_compile (method, target_domain);
2084 if (!mono_error_ok (error))
2087 if (!code && mono_llvm_only) {
2088 printf ("AOT method not found in llvmonly mode: %s\n", mono_method_full_name (method, 1));
2089 g_assert_not_reached ();
2095 if (method->wrapper_type == MONO_WRAPPER_WRITE_BARRIER || method->wrapper_type == MONO_WRAPPER_ALLOC) {
2099 * SGEN requires the JIT info for these methods to be registered, see is_ip_in_managed_allocator ().
2101 ji = mini_jit_info_table_find (mono_domain_get (), (char *)code, &d);
2105 p = mono_create_ftnptr (target_domain, code);
2108 /*mono_register_jit_icall_wrapper takes the loader lock, so we take it on the outside. */
2109 mono_loader_lock ();
2111 if (!callinfo->wrapper) {
2112 callinfo->wrapper = p;
2113 mono_register_jit_icall_wrapper (callinfo, p);
2116 mono_loader_unlock ();
2123 mono_jit_compile_method (MonoMethod *method, MonoError *error)
2127 code = mono_jit_compile_method_with_opt (method, mono_get_optimizations_for_method (method, default_opt), FALSE, error);
2132 * mono_jit_compile_method_jit_only:
2134 * Compile METHOD using the JIT/AOT, even in interpreted mode.
2137 mono_jit_compile_method_jit_only (MonoMethod *method, MonoError *error)
2141 code = mono_jit_compile_method_with_opt (method, mono_get_optimizations_for_method (method, default_opt), TRUE, error);
2145 #ifdef MONO_ARCH_HAVE_INVALIDATE_METHOD
2147 invalidated_delegate_trampoline (char *desc)
2149 g_error ("Unmanaged code called delegate of type %s which was already garbage collected.\n"
2150 "See http://www.mono-project.com/Diagnostic:Delegate for an explanation and ways to fix this.",
2156 * mono_jit_free_method:
2158 * Free all memory allocated by the JIT for METHOD.
2161 mono_jit_free_method (MonoDomain *domain, MonoMethod *method)
2163 MonoJitDynamicMethodInfo *ji;
2164 gboolean destroy = TRUE;
2165 GHashTableIter iter;
2166 MonoJumpList *jlist;
2168 g_assert (method->dynamic);
2170 mono_domain_lock (domain);
2171 ji = mono_dynamic_code_hash_lookup (domain, method);
2172 mono_domain_unlock (domain);
2177 mono_debug_remove_method (method, domain);
2178 mono_lldb_remove_method (domain, method, ji);
2180 mono_domain_lock (domain);
2181 g_hash_table_remove (domain_jit_info (domain)->dynamic_code_hash, method);
2182 mono_domain_jit_code_hash_lock (domain);
2183 mono_internal_hash_table_remove (&domain->jit_code_hash, method);
2184 mono_domain_jit_code_hash_unlock (domain);
2185 g_hash_table_remove (domain_jit_info (domain)->jump_trampoline_hash, method);
2187 /* requires the domain lock - took above */
2188 mono_conc_hashtable_remove (domain_jit_info (domain)->runtime_invoke_hash, method);
2190 /* Remove jump targets in this method */
2191 g_hash_table_iter_init (&iter, domain_jit_info (domain)->jump_target_hash);
2192 while (g_hash_table_iter_next (&iter, NULL, (void**)&jlist)) {
2193 GSList *tmp, *remove;
2196 for (tmp = jlist->list; tmp; tmp = tmp->next) {
2197 guint8 *ip = (guint8 *)tmp->data;
2199 if (ip >= (guint8*)ji->ji->code_start && ip < (guint8*)ji->ji->code_start + ji->ji->code_size)
2200 remove = g_slist_prepend (remove, tmp);
2202 for (tmp = remove; tmp; tmp = tmp->next) {
2203 jlist->list = g_slist_delete_link ((GSList *)jlist->list, (GSList *)tmp->data);
2205 g_slist_free (remove);
2207 mono_domain_unlock (domain);
2209 #ifdef MONO_ARCH_HAVE_INVALIDATE_METHOD
2210 if (debug_options.keep_delegates && method->wrapper_type == MONO_WRAPPER_NATIVE_TO_MANAGED) {
2212 * Instead of freeing the code, change it to call an error routine
2213 * so people can fix their code.
2215 char *type = mono_type_full_name (&method->klass->byval_arg);
2216 char *type_and_method = g_strdup_printf ("%s.%s", type, method->name);
2219 mono_arch_invalidate_method (ji->ji, invalidated_delegate_trampoline, type_and_method);
2225 * This needs to be done before freeing code_mp, since the code address is the
2226 * key in the table, so if we free the code_mp first, another thread can grab the
2227 * same code address and replace our entry in the table.
2229 mono_jit_info_table_remove (domain, ji->ji);
2232 mono_code_manager_destroy (ji->code_mp);
2237 mono_jit_find_compiled_method_with_jit_info (MonoDomain *domain, MonoMethod *method, MonoJitInfo **ji)
2239 MonoDomain *target_domain;
2242 if (default_opt & MONO_OPT_SHARED)
2243 target_domain = mono_get_root_domain ();
2245 target_domain = domain;
2247 info = lookup_method (target_domain, method);
2249 /* We can't use a domain specific method in another domain */
2250 if (! ((domain != target_domain) && !info->domain_neutral)) {
2251 mono_jit_stats.methods_lookups++;
2254 return info->code_start;
2263 static guint32 bisect_opt = 0;
2264 static GHashTable *bisect_methods_hash = NULL;
2267 mono_set_bisect_methods (guint32 opt, const char *method_list_filename)
2270 char method_name [2048];
2273 bisect_methods_hash = g_hash_table_new (g_str_hash, g_str_equal);
2274 g_assert (bisect_methods_hash);
2276 file = fopen (method_list_filename, "r");
2279 while (fgets (method_name, sizeof (method_name), file)) {
2280 size_t len = strlen (method_name);
2282 g_assert (method_name [len - 1] == '\n');
2283 method_name [len - 1] = 0;
2284 g_hash_table_insert (bisect_methods_hash, g_strdup (method_name), GINT_TO_POINTER (1));
2286 g_assert (feof (file));
2289 gboolean mono_do_single_method_regression = FALSE;
2290 guint32 mono_single_method_regression_opt = 0;
2291 MonoMethod *mono_current_single_method;
2292 GSList *mono_single_method_list;
2293 GHashTable *mono_single_method_hash;
2296 mono_get_optimizations_for_method (MonoMethod *method, guint32 default_opt)
2300 if (bisect_methods_hash) {
2301 char *name = mono_method_full_name (method, TRUE);
2302 void *res = g_hash_table_lookup (bisect_methods_hash, name);
2305 return default_opt | bisect_opt;
2307 if (!mono_do_single_method_regression)
2309 if (!mono_current_single_method) {
2310 if (!mono_single_method_hash)
2311 mono_single_method_hash = g_hash_table_new (g_direct_hash, g_direct_equal);
2312 if (!g_hash_table_lookup (mono_single_method_hash, method)) {
2313 g_hash_table_insert (mono_single_method_hash, method, method);
2314 mono_single_method_list = g_slist_prepend (mono_single_method_list, method);
2318 if (method == mono_current_single_method)
2319 return mono_single_method_regression_opt;
2324 mono_jit_find_compiled_method (MonoDomain *domain, MonoMethod *method)
2326 return mono_jit_find_compiled_method_with_jit_info (domain, method, NULL);
2331 gpointer compiled_method;
2332 gpointer runtime_invoke;
2334 MonoDynCallInfo *dyn_call_info;
2335 MonoClass *ret_box_class;
2336 MonoMethodSignature *sig;
2337 gboolean gsharedvt_invoke;
2338 gpointer *wrapper_arg;
2339 } RuntimeInvokeInfo;
2341 static RuntimeInvokeInfo*
2342 create_runtime_invoke_info (MonoDomain *domain, MonoMethod *method, gpointer compiled_method, gboolean callee_gsharedvt, MonoError *error)
2345 RuntimeInvokeInfo *info;
2347 info = g_new0 (RuntimeInvokeInfo, 1);
2348 info->compiled_method = compiled_method;
2349 if (mono_llvm_only && method->string_ctor)
2350 info->sig = mono_marshal_get_string_ctor_signature (method);
2352 info->sig = mono_method_signature (method);
2354 invoke = mono_marshal_get_runtime_invoke (method, FALSE);
2355 info->vtable = mono_class_vtable_full (domain, method->klass, error);
2356 if (!mono_error_ok (error))
2358 g_assert (info->vtable);
2360 MonoMethodSignature *sig = info->sig;
2364 * We want to avoid AOTing 1000s of runtime-invoke wrappers when running
2365 * in full-aot mode, so we use a slower, but more generic wrapper if
2366 * possible, built on top of the OP_DYN_CALL opcode provided by the JIT.
2368 #ifdef MONO_ARCH_DYN_CALL_SUPPORTED
2369 if (!mono_llvm_only && (mono_aot_only || debug_options.dyn_runtime_invoke)) {
2370 gboolean supported = TRUE;
2373 if (method->string_ctor)
2374 sig = mono_marshal_get_string_ctor_signature (method);
2376 for (i = 0; i < sig->param_count; ++i) {
2377 MonoType *t = sig->params [i];
2379 if (t->byref && t->type == MONO_TYPE_GENERICINST && mono_class_is_nullable (mono_class_from_mono_type (t)))
2383 if (mono_class_is_contextbound (method->klass) || !info->compiled_method)
2387 info->dyn_call_info = mono_arch_dyn_call_prepare (sig);
2391 ret_type = sig->ret;
2392 switch (ret_type->type) {
2393 case MONO_TYPE_VOID:
2405 case MONO_TYPE_BOOLEAN:
2406 case MONO_TYPE_CHAR:
2409 info->ret_box_class = mono_class_from_mono_type (ret_type);
2412 info->ret_box_class = mono_defaults.int_class;
2414 case MONO_TYPE_STRING:
2415 case MONO_TYPE_CLASS:
2416 case MONO_TYPE_ARRAY:
2417 case MONO_TYPE_SZARRAY:
2418 case MONO_TYPE_OBJECT:
2420 case MONO_TYPE_GENERICINST:
2421 if (!MONO_TYPE_IS_REFERENCE (ret_type))
2422 info->ret_box_class = mono_class_from_mono_type (ret_type);
2424 case MONO_TYPE_VALUETYPE:
2425 info->ret_box_class = mono_class_from_mono_type (ret_type);
2428 g_assert_not_reached ();
2432 if (!info->dyn_call_info) {
2433 if (mono_llvm_only) {
2434 #ifndef MONO_ARCH_GSHAREDVT_SUPPORTED
2435 g_assert_not_reached ();
2437 info->gsharedvt_invoke = TRUE;
2438 if (!callee_gsharedvt) {
2439 /* Invoke a gsharedvt out wrapper instead */
2440 MonoMethod *wrapper = mini_get_gsharedvt_out_sig_wrapper (sig);
2441 MonoMethodSignature *wrapper_sig = mini_get_gsharedvt_out_sig_wrapper_signature (sig->hasthis, sig->ret->type != MONO_TYPE_VOID, sig->param_count);
2443 info->wrapper_arg = g_malloc0 (2 * sizeof (gpointer));
2444 info->wrapper_arg [0] = mini_add_method_wrappers_llvmonly (method, info->compiled_method, FALSE, FALSE, &(info->wrapper_arg [1]));
2446 /* Pass has_rgctx == TRUE since the wrapper has an extra arg */
2447 invoke = mono_marshal_get_runtime_invoke_for_sig (wrapper_sig);
2448 g_free (wrapper_sig);
2450 info->compiled_method = mono_jit_compile_method (wrapper, error);
2451 if (!mono_error_ok (error)) {
2456 /* Gsharedvt methods can be invoked the same way */
2457 /* The out wrapper has the same signature as the compiled gsharedvt method */
2458 MonoMethodSignature *wrapper_sig = mini_get_gsharedvt_out_sig_wrapper_signature (sig->hasthis, sig->ret->type != MONO_TYPE_VOID, sig->param_count);
2460 info->wrapper_arg = mono_method_needs_static_rgctx_invoke (method, TRUE) ? mini_method_get_rgctx (method) : NULL;
2462 invoke = mono_marshal_get_runtime_invoke_for_sig (wrapper_sig);
2463 g_free (wrapper_sig);
2466 info->runtime_invoke = mono_jit_compile_method (invoke, error);
2467 if (!mono_error_ok (error)) {
2477 mono_llvmonly_runtime_invoke (MonoMethod *method, RuntimeInvokeInfo *info, void *obj, void **params, MonoObject **exc, MonoError *error)
2479 MonoMethodSignature *sig = info->sig;
2480 MonoDomain *domain = mono_domain_get ();
2481 MonoObject *(*runtime_invoke) (MonoObject *this_obj, void **params, MonoObject **exc, void* compiled_method);
2483 gpointer retval_ptr;
2484 guint8 retval [256];
2485 gpointer *param_refs;
2490 g_assert (info->gsharedvt_invoke);
2493 * Instead of invoking the method directly, we invoke a gsharedvt out wrapper.
2494 * The advantage of this is the gsharedvt out wrappers have a reduced set of
2495 * signatures, so we only have to generate runtime invoke wrappers for these
2497 * This code also handles invocation of gsharedvt methods directly, no
2498 * out wrappers are used in that case.
2500 args = (void **)g_alloca ((sig->param_count + sig->hasthis + 2) * sizeof (gpointer));
2501 param_refs = (gpointer*)g_alloca ((sig->param_count + sig->hasthis + 2) * sizeof (gpointer));
2504 * The runtime invoke wrappers expects pointers to primitive types, so have to
2508 args [pindex ++] = &obj;
2509 if (sig->ret->type != MONO_TYPE_VOID) {
2510 retval_ptr = (gpointer)&retval;
2511 args [pindex ++] = &retval_ptr;
2513 for (i = 0; i < sig->param_count; ++i) {
2514 MonoType *t = sig->params [i];
2516 if (t->type == MONO_TYPE_GENERICINST && mono_class_is_nullable (mono_class_from_mono_type (t))) {
2517 MonoClass *klass = mono_class_from_mono_type (t);
2518 guint8 *nullable_buf;
2521 size = mono_class_value_size (klass, NULL);
2522 nullable_buf = g_alloca (size);
2523 g_assert (nullable_buf);
2525 /* The argument pointed to by params [i] is either a boxed vtype or null */
2526 mono_nullable_init (nullable_buf, (MonoObject*)params [i], klass);
2527 params [i] = nullable_buf;
2530 if (!t->byref && (MONO_TYPE_IS_REFERENCE (t) || t->type == MONO_TYPE_PTR)) {
2531 param_refs [i] = params [i];
2532 params [i] = &(param_refs [i]);
2534 args [pindex ++] = ¶ms [i];
2536 /* The gsharedvt out wrapper has an extra argument which contains the method to call */
2537 args [pindex ++] = &info->wrapper_arg;
2539 runtime_invoke = (MonoObject *(*)(MonoObject *, void **, MonoObject **, void *))info->runtime_invoke;
2541 runtime_invoke (NULL, args, exc, info->compiled_method);
2545 if (sig->ret->type != MONO_TYPE_VOID && info->ret_box_class)
2546 return mono_value_box_checked (domain, info->ret_box_class, retval, error);
2548 return *(MonoObject**)retval;
2552 * mono_jit_runtime_invoke:
2553 * \param method: the method to invoke
2554 * \param obj: this pointer
2555 * \param params: array of parameter values.
2556 * \param exc: Set to the exception raised in the managed method.
2557 * \param error: error or caught exception object
2558 * If \p exc is NULL, \p error is thrown instead.
2559 * If coop is enabled, \p exc argument is ignored -
2560 * all exceptions are caught and propagated through \p error
2563 mono_jit_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObject **exc, MonoError *error)
2565 MonoMethod *invoke, *callee;
2566 MonoObject *(*runtime_invoke) (MonoObject *this_obj, void **params, MonoObject **exc, void* compiled_method);
2567 MonoDomain *domain = mono_domain_get ();
2568 MonoJitDomainInfo *domain_info;
2569 RuntimeInvokeInfo *info, *info2;
2570 MonoJitInfo *ji = NULL;
2571 gboolean callee_gsharedvt = FALSE;
2573 #ifdef ENABLE_INTERPRETER
2574 if (mono_use_interpreter)
2575 return mono_interp_runtime_invoke (method, obj, params, exc, error);
2580 if (obj == NULL && !(method->flags & METHOD_ATTRIBUTE_STATIC) && !method->string_ctor && (method->wrapper_type == 0)) {
2581 g_warning ("Ignoring invocation of an instance method on a NULL instance.\n");
2585 domain_info = domain_jit_info (domain);
2587 info = (RuntimeInvokeInfo *)mono_conc_hashtable_lookup (domain_info->runtime_invoke_hash, method);
2590 if (mono_security_core_clr_enabled ()) {
2592 * This might be redundant since mono_class_vtable () already does this,
2593 * but keep it just in case for moonlight.
2595 mono_class_setup_vtable (method->klass);
2596 if (mono_class_has_failure (method->klass)) {
2597 mono_error_set_for_class_failure (error, method->klass);
2599 *exc = (MonoObject*)mono_class_get_exception_for_failure (method->klass);
2604 gpointer compiled_method;
2607 if (method->klass->rank && (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) &&
2608 (method->iflags & METHOD_IMPL_ATTRIBUTE_NATIVE)) {
2610 * Array Get/Set/Address methods. The JIT implements them using inline code
2611 * inside the runtime invoke wrappers, so no need to compile them.
2613 if (mono_aot_only) {
2615 * Call a wrapper, since the runtime invoke wrapper was not generated.
2617 MonoMethod *wrapper;
2619 wrapper = mono_marshal_get_array_accessor_wrapper (method);
2620 invoke = mono_marshal_get_runtime_invoke (wrapper, FALSE);
2628 compiled_method = mono_jit_compile_method (callee, error);
2629 if (!compiled_method) {
2630 g_assert (!mono_error_ok (error));
2634 if (mono_llvm_only) {
2635 ji = mini_jit_info_table_find (mono_domain_get (), (char *)mono_get_addr_from_ftnptr (compiled_method), NULL);
2636 callee_gsharedvt = mini_jit_info_is_gsharedvt (ji);
2637 if (callee_gsharedvt)
2638 callee_gsharedvt = mini_is_gsharedvt_variable_signature (mono_method_signature (jinfo_get_method (ji)));
2641 if (!callee_gsharedvt)
2642 compiled_method = mini_add_method_trampoline (callee, compiled_method, mono_method_needs_static_rgctx_invoke (callee, TRUE), FALSE);
2644 compiled_method = NULL;
2647 info = create_runtime_invoke_info (domain, method, compiled_method, callee_gsharedvt, error);
2648 if (!mono_error_ok (error))
2651 mono_domain_lock (domain);
2652 info2 = (RuntimeInvokeInfo *)mono_conc_hashtable_insert (domain_info->runtime_invoke_hash, method, info);
2653 mono_domain_unlock (domain);
2661 * We need this here because mono_marshal_get_runtime_invoke can place
2662 * the helper method in System.Object and not the target class.
2664 if (!mono_runtime_class_init_full (info->vtable, error)) {
2666 *exc = (MonoObject*) mono_error_convert_to_exception (error);
2670 /* If coop is enabled, and the caller didn't ask for the exception to be caught separately,
2671 we always catch the exception and propagate it through the MonoError */
2672 gboolean catchExcInMonoError =
2673 (exc == NULL) && mono_threads_is_coop_enabled ();
2674 MonoObject *invoke_exc = NULL;
2675 if (catchExcInMonoError)
2678 /* The wrappers expect this to be initialized to NULL */
2682 #ifdef MONO_ARCH_DYN_CALL_SUPPORTED
2683 if (info->dyn_call_info) {
2684 MonoMethodSignature *sig = mono_method_signature (method);
2686 static RuntimeInvokeDynamicFunction dyn_runtime_invoke;
2689 guint8 retval [256];
2691 if (!dyn_runtime_invoke) {
2692 invoke = mono_marshal_get_runtime_invoke_dynamic ();
2693 dyn_runtime_invoke = (RuntimeInvokeDynamicFunction)mono_jit_compile_method (invoke, error);
2694 if (!mono_error_ok (error))
2698 /* Convert the arguments to the format expected by start_dyn_call () */
2699 args = (void **)g_alloca ((sig->param_count + sig->hasthis) * sizeof (gpointer));
2702 args [pindex ++] = &obj;
2703 for (i = 0; i < sig->param_count; ++i) {
2704 MonoType *t = sig->params [i];
2707 args [pindex ++] = ¶ms [i];
2708 } else if (MONO_TYPE_IS_REFERENCE (t) || t->type == MONO_TYPE_PTR) {
2709 args [pindex ++] = ¶ms [i];
2711 args [pindex ++] = params [i];
2715 //printf ("M: %s\n", mono_method_full_name (method, TRUE));
2717 mono_arch_start_dyn_call (info->dyn_call_info, (gpointer**)args, retval, buf, sizeof (buf));
2719 dyn_runtime_invoke (buf, exc, info->compiled_method);
2720 mono_arch_finish_dyn_call (info->dyn_call_info, buf);
2722 if (catchExcInMonoError && *exc != NULL) {
2723 mono_error_set_exception_instance (error, (MonoException*) *exc);
2727 if (info->ret_box_class)
2728 return mono_value_box_checked (domain, info->ret_box_class, retval, error);
2730 return *(MonoObject**)retval;
2736 if (mono_llvm_only) {
2737 result = mono_llvmonly_runtime_invoke (method, info, obj, params, exc, error);
2741 runtime_invoke = (MonoObject *(*)(MonoObject *, void **, MonoObject **, void *))info->runtime_invoke;
2743 result = runtime_invoke ((MonoObject *)obj, params, exc, info->compiled_method);
2745 if (catchExcInMonoError && *exc != NULL)
2746 mono_error_set_exception_instance (error, (MonoException*) *exc);
2755 typedef gpointer (*IMTTrampFunc) (gpointer *arg, MonoMethod *imt_method);
2758 * mini_llvmonly_initial_imt_tramp:
2760 * This function is called the first time a call is made through an IMT trampoline.
2761 * It should have the same signature as the mono_llvmonly_imt_tramp_... functions.
2764 mini_llvmonly_initial_imt_tramp (gpointer *arg, MonoMethod *imt_method)
2766 IMTTrampInfo *info = (IMTTrampInfo*)arg;
2771 mono_vtable_build_imt_slot (info->vtable, info->slot);
2773 imt = (gpointer*)info->vtable;
2774 imt -= MONO_IMT_SIZE;
2776 /* Return what the real IMT trampoline returns */
2777 ftndesc = imt [info->slot];
2780 if (func == (IMTTrampFunc)mini_llvmonly_initial_imt_tramp)
2781 /* Happens when the imt slot contains only a generic virtual method */
2783 return func ((gpointer *)ftndesc [1], imt_method);
2786 /* This is called indirectly through an imt slot. */
2788 mono_llvmonly_imt_tramp (gpointer *arg, MonoMethod *imt_method)
2792 /* arg points to an array created in mono_llvmonly_get_imt_trampoline () */
2793 while (arg [i] && arg [i] != imt_method)
2800 /* Optimized versions of mono_llvmonly_imt_trampoline () for different table sizes */
2802 mono_llvmonly_imt_tramp_1 (gpointer *arg, MonoMethod *imt_method)
2804 //g_assert (arg [0] == imt_method);
2809 mono_llvmonly_imt_tramp_2 (gpointer *arg, MonoMethod *imt_method)
2811 //g_assert (arg [0] == imt_method || arg [2] == imt_method);
2812 if (arg [0] == imt_method)
2819 mono_llvmonly_imt_tramp_3 (gpointer *arg, MonoMethod *imt_method)
2821 //g_assert (arg [0] == imt_method || arg [2] == imt_method || arg [4] == imt_method);
2822 if (arg [0] == imt_method)
2824 else if (arg [2] == imt_method)
2831 * A version of the imt trampoline used for generic virtual/variant iface methods.
2832 * Unlikely a normal imt trampoline, its possible that IMT_METHOD is not found
2833 * in the search table. The original JIT code had a 'fallback' trampoline it could
2834 * call, but we can't do that, so we just return NULL, and the compiled code
2838 mono_llvmonly_fallback_imt_tramp (gpointer *arg, MonoMethod *imt_method)
2842 while (arg [i] && arg [i] != imt_method)
2851 mono_llvmonly_get_imt_trampoline (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckItem **imt_entries, int count, gpointer fail_tramp)
2855 int i, index, real_count;
2856 gboolean virtual_generic = FALSE;
2859 * Create an array which is passed to the imt trampoline functions.
2860 * The array contains MonoMethod-function descriptor pairs, terminated by a NULL entry.
2864 for (i = 0; i < count; ++i) {
2865 MonoIMTCheckItem *item = imt_entries [i];
2867 if (item->is_equals)
2869 if (item->has_target_code)
2870 virtual_generic = TRUE;
2874 * Initialize all vtable entries reachable from this imt slot, so the compiled
2875 * code doesn't have to check it.
2877 for (i = 0; i < count; ++i) {
2878 MonoIMTCheckItem *item = imt_entries [i];
2881 if (!item->is_equals || item->has_target_code)
2883 vt_slot = item->value.vtable_slot;
2884 mono_init_vtable_slot (vtable, vt_slot);
2887 /* Save the entries into an array */
2888 buf = (void **)mono_domain_alloc (domain, (real_count + 1) * 2 * sizeof (gpointer));
2890 for (i = 0; i < count; ++i) {
2891 MonoIMTCheckItem *item = imt_entries [i];
2893 if (!item->is_equals)
2896 g_assert (item->key);
2897 buf [(index * 2)] = item->key;
2898 if (item->has_target_code)
2899 buf [(index * 2) + 1] = item->value.target_code;
2901 buf [(index * 2) + 1] = vtable->vtable [item->value.vtable_slot];
2904 buf [(index * 2)] = NULL;
2905 buf [(index * 2) + 1] = fail_tramp;
2908 * Return a function descriptor for a C function with 'buf' as its argument.
2909 * It will by called by JITted code.
2911 res = (void **)mono_domain_alloc (domain, 2 * sizeof (gpointer));
2912 switch (real_count) {
2914 res [0] = mono_llvmonly_imt_tramp_1;
2917 res [0] = mono_llvmonly_imt_tramp_2;
2920 res [0] = mono_llvmonly_imt_tramp_3;
2923 res [0] = mono_llvmonly_imt_tramp;
2926 if (virtual_generic || fail_tramp)
2927 res [0] = mono_llvmonly_fallback_imt_tramp;
2933 MONO_SIG_HANDLER_FUNC (, mono_sigfpe_signal_handler)
2935 MonoException *exc = NULL;
2937 MONO_SIG_HANDLER_INFO_TYPE *info = MONO_SIG_HANDLER_GET_INFO ();
2938 MONO_SIG_HANDLER_GET_CONTEXT;
2940 ji = mono_jit_info_table_find_internal (mono_domain_get (), (char *)mono_arch_ip_from_context (ctx), TRUE, TRUE);
2942 MONO_ENTER_GC_UNSAFE_UNBALANCED;
2944 #if defined(MONO_ARCH_HAVE_IS_INT_OVERFLOW)
2945 if (mono_arch_is_int_overflow (ctx, info))
2947 * The spec says this throws ArithmeticException, but MS throws the derived
2948 * OverflowException.
2950 exc = mono_get_exception_overflow ();
2952 exc = mono_get_exception_divide_by_zero ();
2954 exc = mono_get_exception_divide_by_zero ();
2958 if (!mono_do_crash_chaining && mono_chain_signal (MONO_SIG_HANDLER_PARAMS))
2961 mono_handle_native_crash ("SIGFPE", ctx, info);
2962 if (mono_do_crash_chaining) {
2963 mono_chain_signal (MONO_SIG_HANDLER_PARAMS);
2968 mono_arch_handle_exception (ctx, exc);
2971 MONO_EXIT_GC_UNSAFE_UNBALANCED;
2974 MONO_SIG_HANDLER_FUNC (, mono_sigill_signal_handler)
2976 MONO_SIG_HANDLER_INFO_TYPE *info = MONO_SIG_HANDLER_GET_INFO ();
2977 MONO_SIG_HANDLER_GET_CONTEXT;
2979 if (mono_runtime_get_no_exec ())
2983 mono_handle_native_crash ("SIGILL", ctx, info);
2984 if (mono_do_crash_chaining) {
2985 mono_chain_signal (MONO_SIG_HANDLER_PARAMS);
2989 g_assert_not_reached ();
2992 #if defined(MONO_ARCH_USE_SIGACTION) || defined(HOST_WIN32)
2993 #define HAVE_SIG_INFO
2996 MONO_SIG_HANDLER_FUNC (, mono_sigsegv_signal_handler)
2999 MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_tls_get_jit_tls ();
3000 gpointer fault_addr = NULL;
3001 #ifdef HAVE_SIG_INFO
3002 MONO_SIG_HANDLER_INFO_TYPE *info = MONO_SIG_HANDLER_GET_INFO ();
3006 MONO_SIG_HANDLER_GET_CONTEXT;
3008 #if defined(MONO_ARCH_SOFT_DEBUG_SUPPORTED) && defined(HAVE_SIG_INFO)
3009 if (mono_arch_is_single_step_event (info, ctx)) {
3010 mono_debugger_agent_single_step_event (ctx);
3012 } else if (mono_arch_is_breakpoint_event (info, ctx)) {
3013 mono_debugger_agent_breakpoint_hit (ctx);
3018 #if defined(HAVE_SIG_INFO)
3019 #if !defined(HOST_WIN32)
3020 fault_addr = info->si_addr;
3021 if (mono_aot_is_pagefault (info->si_addr)) {
3022 mono_aot_handle_pagefault (info->si_addr);
3027 /* The thread might no be registered with the runtime */
3028 if (!mono_domain_get () || !jit_tls) {
3029 if (!mono_do_crash_chaining && mono_chain_signal (MONO_SIG_HANDLER_PARAMS))
3031 mono_handle_native_crash ("SIGSEGV", ctx, info);
3032 if (mono_do_crash_chaining) {
3033 mono_chain_signal (MONO_SIG_HANDLER_PARAMS);
3039 ji = mono_jit_info_table_find_internal (mono_domain_get (), (char *)mono_arch_ip_from_context (ctx), TRUE, TRUE);
3041 #ifdef MONO_ARCH_SIGSEGV_ON_ALTSTACK
3042 if (mono_handle_soft_stack_ovf (jit_tls, ji, ctx, info, (guint8*)info->si_addr))
3045 #ifdef MONO_ARCH_HAVE_SIGCTX_TO_MONOCTX
3046 /* info->si_addr seems to be NULL on some kernels when handling stack overflows */
3047 fault_addr = info->si_addr;
3048 if (fault_addr == NULL) {
3051 mono_sigctx_to_monoctx (ctx, &mctx);
3053 fault_addr = MONO_CONTEXT_GET_SP (&mctx);
3057 if (jit_tls->stack_size &&
3058 ABS ((guint8*)fault_addr - ((guint8*)jit_tls->end_of_stack - jit_tls->stack_size)) < 8192 * sizeof (gpointer)) {
3060 * The hard-guard page has been hit: there is not much we can do anymore
3061 * Print a hopefully clear message and abort.
3063 mono_handle_hard_stack_ovf (jit_tls, ji, ctx, (guint8*)info->si_addr);
3064 g_assert_not_reached ();
3066 /* The original handler might not like that it is executed on an altstack... */
3067 if (!ji && mono_chain_signal (MONO_SIG_HANDLER_PARAMS))
3070 mono_arch_handle_altstack_exception (ctx, info, info->si_addr, FALSE);
3075 if (!mono_do_crash_chaining && mono_chain_signal (MONO_SIG_HANDLER_PARAMS))
3078 mono_handle_native_crash ("SIGSEGV", ctx, info);
3080 if (mono_do_crash_chaining) {
3081 mono_chain_signal (MONO_SIG_HANDLER_PARAMS);
3086 mono_arch_handle_exception (ctx, NULL);
3090 MONO_SIG_HANDLER_FUNC (, mono_sigint_signal_handler)
3093 MONO_SIG_HANDLER_GET_CONTEXT;
3095 MONO_ENTER_GC_UNSAFE_UNBALANCED;
3097 exc = mono_get_exception_execution_engine ("Interrupted (SIGINT).");
3099 mono_arch_handle_exception (ctx, exc);
3101 MONO_EXIT_GC_UNSAFE_UNBALANCED;
3104 #ifndef DISABLE_REMOTING
3105 /* mono_jit_create_remoting_trampoline:
3106 * @method: pointer to the method info
3108 * Creates a trampoline which calls the remoting functions. This
3109 * is used in the vtable of transparent proxies.
3111 * Returns: a pointer to the newly created code
3114 mono_jit_create_remoting_trampoline (MonoDomain *domain, MonoMethod *method, MonoRemotingTarget target, MonoError *error)
3117 guint8 *addr = NULL;
3121 if ((method->flags & METHOD_ATTRIBUTE_VIRTUAL) && mono_method_signature (method)->generic_param_count) {
3122 return mono_create_specific_trampoline (method, MONO_TRAMPOLINE_GENERIC_VIRTUAL_REMOTING,
3126 if ((method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
3127 (mono_method_signature (method)->hasthis && (mono_class_is_marshalbyref (method->klass) || method->klass == mono_defaults.object_class)))
3128 nm = mono_marshal_get_remoting_invoke_for_target (method, target);
3131 addr = (guint8 *)mono_compile_method_checked (nm, error);
3132 return_val_if_nok (error, NULL);
3133 return mono_get_addr_from_ftnptr (addr);
3137 static G_GNUC_UNUSED void
3138 no_imt_trampoline (void)
3140 g_assert_not_reached ();
3143 static G_GNUC_UNUSED void
3144 no_vcall_trampoline (void)
3146 g_assert_not_reached ();
3149 static gpointer *vtable_trampolines;
3150 static int vtable_trampolines_size;
3153 mini_get_vtable_trampoline (MonoVTable *vt, int slot_index)
3155 int index = slot_index + MONO_IMT_SIZE;
3157 if (mono_llvm_only) {
3158 if (slot_index < 0) {
3159 /* Initialize the IMT trampoline to a 'trampoline' so the generated code doesn't have to initialize it */
3160 // FIXME: Memory management
3161 gpointer *ftndesc = g_malloc (2 * sizeof (gpointer));
3162 IMTTrampInfo *info = g_new0 (IMTTrampInfo, 1);
3165 ftndesc [0] = mini_llvmonly_initial_imt_tramp;
3167 mono_memory_barrier ();
3174 g_assert (slot_index >= - MONO_IMT_SIZE);
3175 if (!vtable_trampolines || slot_index + MONO_IMT_SIZE >= vtable_trampolines_size) {
3177 if (!vtable_trampolines || index >= vtable_trampolines_size) {
3181 new_size = vtable_trampolines_size ? vtable_trampolines_size * 2 : 128;
3182 while (new_size <= index)
3184 new_table = g_new0 (gpointer, new_size);
3186 if (vtable_trampolines)
3187 memcpy (new_table, vtable_trampolines, vtable_trampolines_size * sizeof (gpointer));
3188 g_free (vtable_trampolines);
3189 mono_memory_barrier ();
3190 vtable_trampolines = (void **)new_table;
3191 vtable_trampolines_size = new_size;
3196 if (!vtable_trampolines [index])
3197 vtable_trampolines [index] = mono_create_specific_trampoline (GUINT_TO_POINTER (slot_index), MONO_TRAMPOLINE_VCALL, mono_get_root_domain (), NULL);
3198 return vtable_trampolines [index];
3202 mini_get_imt_trampoline (MonoVTable *vt, int slot_index)
3204 return mini_get_vtable_trampoline (vt, slot_index - MONO_IMT_SIZE);
3208 mini_imt_entry_inited (MonoVTable *vt, int imt_slot_index)
3213 gpointer *imt = (gpointer*)vt;
3214 imt -= MONO_IMT_SIZE;
3216 return (imt [imt_slot_index] != mini_get_imt_trampoline (vt, imt_slot_index));
3220 is_callee_gsharedvt_variable (gpointer addr)
3223 gboolean callee_gsharedvt;
3225 ji = mini_jit_info_table_find (mono_domain_get (), (char *)mono_get_addr_from_ftnptr (addr), NULL);
3227 callee_gsharedvt = mini_jit_info_is_gsharedvt (ji);
3228 if (callee_gsharedvt)
3229 callee_gsharedvt = mini_is_gsharedvt_variable_signature (mono_method_signature (jinfo_get_method (ji)));
3230 return callee_gsharedvt;
3234 mini_get_delegate_arg (MonoMethod *method, gpointer method_ptr)
3236 gpointer arg = NULL;
3238 if (mono_method_needs_static_rgctx_invoke (method, FALSE))
3239 arg = mini_method_get_rgctx (method);
3242 * Avoid adding gsharedvt in wrappers since they might not exist if
3243 * this delegate is called through a gsharedvt delegate invoke wrapper.
3244 * Instead, encode that the method is gsharedvt in del->extra_arg,
3245 * the CEE_MONO_CALLI_EXTRA_ARG implementation in the JIT depends on this.
3247 if (method->is_inflated && is_callee_gsharedvt_variable (method_ptr)) {
3248 g_assert ((((mgreg_t)arg) & 1) == 0);
3249 arg = (gpointer)(((mgreg_t)arg) | 1);
3255 mini_init_delegate (MonoDelegate *del)
3258 del->extra_arg = mini_get_delegate_arg (del->method, del->method_ptr);
3259 #ifdef ENABLE_INTERPRETER
3260 if (mono_use_interpreter)
3261 mono_interp_init_delegate (del);
3266 mono_get_delegate_virtual_invoke_impl_name (gboolean load_imt_reg, int offset)
3270 abs_offset = offset;
3272 abs_offset = - abs_offset;
3273 return g_strdup_printf ("delegate_virtual_invoke%s_%s%d", load_imt_reg ? "_imt" : "", offset < 0 ? "m_" : "", abs_offset / SIZEOF_VOID_P);
3277 mono_get_delegate_virtual_invoke_impl (MonoMethodSignature *sig, MonoMethod *method)
3279 gboolean is_virtual_generic, is_interface, load_imt_reg;
3282 static guint8 **cache = NULL;
3283 static int cache_size = 0;
3288 if (MONO_TYPE_ISSTRUCT (sig->ret))
3291 is_virtual_generic = method->is_inflated && mono_method_get_declaring_generic_method (method)->is_generic;
3292 is_interface = mono_class_is_interface (method->klass);
3293 load_imt_reg = is_virtual_generic || is_interface;
3296 offset = ((gint32)mono_method_get_imt_slot (method) - MONO_IMT_SIZE) * SIZEOF_VOID_P;
3298 offset = G_STRUCT_OFFSET (MonoVTable, vtable) + ((mono_method_get_vtable_index (method)) * (SIZEOF_VOID_P));
3300 idx = (offset / SIZEOF_VOID_P + MONO_IMT_SIZE) * 2 + (load_imt_reg ? 1 : 0);
3301 g_assert (idx >= 0);
3303 /* Resize the cache to idx + 1 */
3304 if (cache_size < idx + 1) {
3306 if (cache_size < idx + 1) {
3308 int new_cache_size = idx + 1;
3310 new_cache = g_new0 (guint8*, new_cache_size);
3312 memcpy (new_cache, cache, cache_size * sizeof (guint8*));
3315 mono_memory_barrier ();
3317 cache_size = new_cache_size;
3325 /* FIXME Support more cases */
3326 if (mono_aot_only) {
3327 cache [idx] = (guint8 *)mono_aot_get_trampoline (mono_get_delegate_virtual_invoke_impl_name (load_imt_reg, offset));
3328 g_assert (cache [idx]);
3330 cache [idx] = (guint8 *)mono_arch_get_delegate_virtual_invoke_impl (sig, method, offset, load_imt_reg);
3336 * mini_parse_debug_option:
3337 * @option: The option to parse.
3339 * Parses debug options for the mono runtime. The options are the same as for
3340 * the MONO_DEBUG environment variable.
3344 mini_parse_debug_option (const char *option)
3346 if (!strcmp (option, "handle-sigint"))
3347 debug_options.handle_sigint = TRUE;
3348 else if (!strcmp (option, "keep-delegates"))
3349 debug_options.keep_delegates = TRUE;
3350 else if (!strcmp (option, "reverse-pinvoke-exceptions"))
3351 debug_options.reverse_pinvoke_exceptions = TRUE;
3352 else if (!strcmp (option, "collect-pagefault-stats"))
3353 debug_options.collect_pagefault_stats = TRUE;
3354 else if (!strcmp (option, "break-on-unverified"))
3355 debug_options.break_on_unverified = TRUE;
3356 else if (!strcmp (option, "no-gdb-backtrace"))
3357 debug_options.no_gdb_backtrace = TRUE;
3358 else if (!strcmp (option, "suspend-on-native-crash") || !strcmp (option, "suspend-on-sigsegv"))
3359 debug_options.suspend_on_native_crash = TRUE;
3360 else if (!strcmp (option, "suspend-on-exception"))
3361 debug_options.suspend_on_exception = TRUE;
3362 else if (!strcmp (option, "suspend-on-unhandled"))
3363 debug_options.suspend_on_unhandled = TRUE;
3364 else if (!strcmp (option, "dont-free-domains"))
3365 mono_dont_free_domains = TRUE;
3366 else if (!strcmp (option, "dyn-runtime-invoke"))
3367 debug_options.dyn_runtime_invoke = TRUE;
3368 else if (!strcmp (option, "gdb"))
3369 debug_options.gdb = TRUE;
3370 else if (!strcmp (option, "lldb"))
3371 debug_options.lldb = TRUE;
3372 else if (!strcmp (option, "explicit-null-checks"))
3373 debug_options.explicit_null_checks = TRUE;
3374 else if (!strcmp (option, "gen-seq-points"))
3375 debug_options.gen_sdb_seq_points = TRUE;
3376 else if (!strcmp (option, "gen-compact-seq-points"))
3377 fprintf (stderr, "Mono Warning: option gen-compact-seq-points is deprecated.\n");
3378 else if (!strcmp (option, "no-compact-seq-points"))
3379 debug_options.no_seq_points_compact_data = TRUE;
3380 else if (!strcmp (option, "single-imm-size"))
3381 debug_options.single_imm_size = TRUE;
3382 else if (!strcmp (option, "init-stacks"))
3383 debug_options.init_stacks = TRUE;
3384 else if (!strcmp (option, "casts"))
3385 debug_options.better_cast_details = TRUE;
3386 else if (!strcmp (option, "soft-breakpoints"))
3387 debug_options.soft_breakpoints = TRUE;
3388 else if (!strcmp (option, "check-pinvoke-callconv"))
3389 debug_options.check_pinvoke_callconv = TRUE;
3390 else if (!strcmp (option, "use-fallback-tls"))
3391 debug_options.use_fallback_tls = TRUE;
3392 else if (!strcmp (option, "debug-domain-unload"))
3393 mono_enable_debug_domain_unload (TRUE);
3394 else if (!strcmp (option, "partial-sharing"))
3395 mono_set_partial_sharing_supported (TRUE);
3396 else if (!strcmp (option, "align-small-structs"))
3397 mono_align_small_structs = TRUE;
3398 else if (!strcmp (option, "native-debugger-break"))
3399 debug_options.native_debugger_break = TRUE;
3400 else if (!strcmp (option, "disable_omit_fp"))
3401 debug_options.disable_omit_fp = TRUE;
3409 mini_parse_debug_options (void)
3411 char *options = g_getenv ("MONO_DEBUG");
3412 gchar **args, **ptr;
3417 args = g_strsplit (options, ",", -1);
3420 for (ptr = args; ptr && *ptr; ptr++) {
3421 const char *arg = *ptr;
3423 if (!mini_parse_debug_option (arg)) {
3424 fprintf (stderr, "Invalid option for the MONO_DEBUG env variable: %s\n", arg);
3425 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");
3434 mini_get_debug_options (void)
3436 return &debug_options;
3440 mini_create_ftnptr (MonoDomain *domain, gpointer addr)
3442 #if !defined(__ia64__) && (!defined(__ppc64__) && !defined(__powerpc64__) || _CALL_ELF == 2)
3445 gpointer* desc = NULL;
3447 if ((desc = g_hash_table_lookup (domain->ftnptrs_hash, addr)))
3450 desc = mono_domain_code_reserve (domain, 2 * sizeof (gpointer));
3454 # elif defined(__ppc64__) || defined(__powerpc64__)
3456 desc = mono_domain_alloc0 (domain, 3 * sizeof (gpointer));
3462 g_hash_table_insert (domain->ftnptrs_hash, addr, desc);
3468 mini_get_addr_from_ftnptr (gpointer descr)
3470 #if defined(__ia64__) || ((defined(__ppc64__) || defined(__powerpc64__)) && _CALL_ELF != 2)
3471 return *(gpointer*)descr;
3478 register_jit_stats (void)
3480 mono_counters_register ("Compiled methods", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.methods_compiled);
3481 mono_counters_register ("Methods from AOT", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.methods_aot);
3482 mono_counters_register ("Methods JITted using mono JIT", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.methods_without_llvm);
3483 mono_counters_register ("Methods JITted using LLVM", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.methods_with_llvm);
3484 mono_counters_register ("JIT/method_to_ir (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_method_to_ir);
3485 mono_counters_register ("JIT/liveness_handle_exception_clauses (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_liveness_handle_exception_clauses);
3486 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);
3487 mono_counters_register ("JIT/decompose_long_opts (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_decompose_long_opts);
3488 mono_counters_register ("JIT/decompose_typechecks (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_decompose_typechecks);
3489 mono_counters_register ("JIT/local_cprop (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_local_cprop);
3490 mono_counters_register ("JIT/local_emulate_ops (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_local_emulate_ops);
3491 mono_counters_register ("JIT/optimize_branches (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_optimize_branches);
3492 mono_counters_register ("JIT/handle_global_vregs (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_handle_global_vregs);
3493 mono_counters_register ("JIT/local_deadce (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_local_deadce);
3494 mono_counters_register ("JIT/local_alias_analysis (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_local_alias_analysis);
3495 mono_counters_register ("JIT/if_conversion (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_if_conversion);
3496 mono_counters_register ("JIT/bb_ordering (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_bb_ordering);
3497 mono_counters_register ("JIT/compile_dominator_info (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_compile_dominator_info);
3498 mono_counters_register ("JIT/compute_natural_loops (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_compute_natural_loops);
3499 mono_counters_register ("JIT/insert_safepoints (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_insert_safepoints);
3500 mono_counters_register ("JIT/ssa_compute (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_ssa_compute);
3501 mono_counters_register ("JIT/ssa_cprop (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_ssa_cprop);
3502 mono_counters_register ("JIT/ssa_deadce(sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_ssa_deadce);
3503 mono_counters_register ("JIT/perform_abc_removal (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_perform_abc_removal);
3504 mono_counters_register ("JIT/ssa_remove (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_ssa_remove);
3505 mono_counters_register ("JIT/local_cprop2 (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_local_cprop2);
3506 mono_counters_register ("JIT/handle_global_vregs2 (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_handle_global_vregs2);
3507 mono_counters_register ("JIT/local_deadce2 (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_local_deadce2);
3508 mono_counters_register ("JIT/optimize_branches2 (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_optimize_branches2);
3509 mono_counters_register ("JIT/decompose_vtype_opts (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_decompose_vtype_opts);
3510 mono_counters_register ("JIT/decompose_array_access_opts (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_decompose_array_access_opts);
3511 mono_counters_register ("JIT/liveness_handle_exception_clauses2 (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_liveness_handle_exception_clauses2);
3512 mono_counters_register ("JIT/analyze_liveness (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_analyze_liveness);
3513 mono_counters_register ("JIT/linear_scan (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_linear_scan);
3514 mono_counters_register ("JIT/arch_allocate_vars (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_arch_allocate_vars);
3515 mono_counters_register ("JIT/spill_global_vars (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_spill_global_vars);
3516 mono_counters_register ("JIT/local_cprop3 (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_local_cprop3);
3517 mono_counters_register ("JIT/local_deadce3 (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_local_deadce3);
3518 mono_counters_register ("JIT/codegen (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_codegen);
3519 mono_counters_register ("JIT/create_jit_info (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_create_jit_info);
3520 mono_counters_register ("JIT/gc_create_gc_map (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_gc_create_gc_map);
3521 mono_counters_register ("JIT/save_seq_point_info (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_save_seq_point_info);
3522 mono_counters_register ("Total time spent JITting (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_time);
3523 mono_counters_register ("Basic blocks", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.basic_blocks);
3524 mono_counters_register ("Max basic blocks", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.max_basic_blocks);
3525 mono_counters_register ("Allocated vars", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.allocate_var);
3526 mono_counters_register ("Code reallocs", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.code_reallocs);
3527 mono_counters_register ("Allocated code size", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.allocated_code_size);
3528 mono_counters_register ("Allocated seq points size", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.allocated_seq_points_size);
3529 mono_counters_register ("Inlineable methods", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.inlineable_methods);
3530 mono_counters_register ("Inlined methods", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.inlined_methods);
3531 mono_counters_register ("Regvars", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.regvars);
3532 mono_counters_register ("Locals stack size", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.locals_stack_size);
3533 mono_counters_register ("Method cache lookups", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.methods_lookups);
3534 mono_counters_register ("Compiled CIL code size", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.cil_code_size);
3535 mono_counters_register ("Native code size", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.native_code_size);
3536 mono_counters_register ("Aliases found", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.alias_found);
3537 mono_counters_register ("Aliases eliminated", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.alias_removed);
3538 mono_counters_register ("Aliased loads eliminated", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.loads_eliminated);
3539 mono_counters_register ("Aliased stores eliminated", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.stores_eliminated);
3540 mono_counters_register ("Optimized immediate divisions", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.optimized_divisions);
3543 static void runtime_invoke_info_free (gpointer value);
3546 class_method_pair_equal (gconstpointer ka, gconstpointer kb)
3548 const MonoClassMethodPair *apair = (const MonoClassMethodPair *)ka;
3549 const MonoClassMethodPair *bpair = (const MonoClassMethodPair *)kb;
3551 return apair->klass == bpair->klass && apair->method == bpair->method ? 1 : 0;
3555 class_method_pair_hash (gconstpointer data)
3557 const MonoClassMethodPair *pair = (const MonoClassMethodPair *)data;
3559 return (gsize)pair->klass ^ (gsize)pair->method;
3563 mini_create_jit_domain_info (MonoDomain *domain)
3565 MonoJitDomainInfo *info = g_new0 (MonoJitDomainInfo, 1);
3567 info->jump_trampoline_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
3568 info->jit_trampoline_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
3569 info->delegate_trampoline_hash = g_hash_table_new (class_method_pair_hash, class_method_pair_equal);
3570 info->llvm_vcall_trampoline_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
3571 info->runtime_invoke_hash = mono_conc_hashtable_new_full (mono_aligned_addr_hash, NULL, NULL, runtime_invoke_info_free);
3572 info->seq_points = g_hash_table_new_full (mono_aligned_addr_hash, NULL, NULL, mono_seq_point_info_free);
3573 info->arch_seq_points = g_hash_table_new (mono_aligned_addr_hash, NULL);
3574 info->jump_target_hash = g_hash_table_new (NULL, NULL);
3575 mono_jit_code_hash_init (&info->interp_code_hash);
3577 domain->runtime_info = info;
3581 delete_jump_list (gpointer key, gpointer value, gpointer user_data)
3583 MonoJumpList *jlist = (MonoJumpList *)value;
3584 g_slist_free (jlist->list);
3588 delete_got_slot_list (gpointer key, gpointer value, gpointer user_data)
3590 GSList *list = (GSList *)value;
3591 g_slist_free (list);
3595 dynamic_method_info_free (gpointer key, gpointer value, gpointer user_data)
3597 MonoJitDynamicMethodInfo *di = (MonoJitDynamicMethodInfo *)value;
3598 mono_code_manager_destroy (di->code_mp);
3603 runtime_invoke_info_free (gpointer value)
3605 RuntimeInvokeInfo *info = (RuntimeInvokeInfo*)value;
3607 #ifdef MONO_ARCH_DYN_CALL_SUPPORTED
3608 if (info->dyn_call_info)
3609 mono_arch_dyn_call_free (info->dyn_call_info);
3615 free_jit_callee_list (gpointer key, gpointer value, gpointer user_data)
3617 g_slist_free (value);
3621 mini_free_jit_domain_info (MonoDomain *domain)
3623 MonoJitDomainInfo *info = domain_jit_info (domain);
3625 g_hash_table_foreach (info->jump_target_hash, delete_jump_list, NULL);
3626 g_hash_table_destroy (info->jump_target_hash);
3627 if (info->jump_target_got_slot_hash) {
3628 g_hash_table_foreach (info->jump_target_got_slot_hash, delete_got_slot_list, NULL);
3629 g_hash_table_destroy (info->jump_target_got_slot_hash);
3631 if (info->dynamic_code_hash) {
3632 g_hash_table_foreach (info->dynamic_code_hash, dynamic_method_info_free, NULL);
3633 g_hash_table_destroy (info->dynamic_code_hash);
3635 if (info->method_code_hash)
3636 g_hash_table_destroy (info->method_code_hash);
3637 g_hash_table_destroy (info->jump_trampoline_hash);
3638 g_hash_table_destroy (info->jit_trampoline_hash);
3639 g_hash_table_destroy (info->delegate_trampoline_hash);
3640 if (info->static_rgctx_trampoline_hash)
3641 g_hash_table_destroy (info->static_rgctx_trampoline_hash);
3642 g_hash_table_destroy (info->llvm_vcall_trampoline_hash);
3643 mono_conc_hashtable_destroy (info->runtime_invoke_hash);
3644 g_hash_table_destroy (info->seq_points);
3645 g_hash_table_destroy (info->arch_seq_points);
3646 if (info->agent_info)
3647 mono_debugger_agent_free_domain_info (domain);
3648 if (info->gsharedvt_arg_tramp_hash)
3649 g_hash_table_destroy (info->gsharedvt_arg_tramp_hash);
3650 if (info->llvm_jit_callees) {
3651 g_hash_table_foreach (info->llvm_jit_callees, free_jit_callee_list, NULL);
3652 g_hash_table_destroy (info->llvm_jit_callees);
3654 mono_internal_hash_table_destroy (&info->interp_code_hash);
3656 mono_llvm_free_domain_info (domain);
3659 g_free (domain->runtime_info);
3660 domain->runtime_info = NULL;
3663 #ifdef MONO_ARCH_HAVE_CODE_CHUNK_TRACKING
3666 code_manager_chunk_new (void *chunk, int size)
3668 mono_arch_code_chunk_new (chunk, size);
3672 code_manager_chunk_destroy (void *chunk)
3674 mono_arch_code_chunk_destroy (chunk);
3681 llvm_init_inner (void)
3683 if (!mono_llvm_load (NULL))
3694 * Load and initialize LLVM support.
3695 * Return TRUE on success.
3698 mini_llvm_init (void)
3701 static gboolean llvm_inited;
3702 static gboolean init_result;
3704 mono_loader_lock_if_inited ();
3706 init_result = llvm_init_inner ();
3709 mono_loader_unlock_if_inited ();
3717 mini_profiler_enable_with_options (const char* profile_options)
3719 mini_enable_profiler = TRUE;
3720 mini_profiler_options = g_strdup (profile_options);
3724 mini_init (const char *filename, const char *runtime_version)
3728 MonoRuntimeCallbacks callbacks;
3729 MonoThreadInfoRuntimeCallbacks ticallbacks;
3730 MonoCodeManagerCallbacks code_manager_callbacks;
3732 MONO_VES_INIT_BEGIN ();
3734 CHECKED_MONO_INIT ();
3736 #if defined(__linux__) && !defined(__native_client__)
3737 if (access ("/proc/self/maps", F_OK) != 0) {
3738 g_print ("Mono requires /proc to be mounted.\n");
3743 mono_os_mutex_init_recursive (&jit_mutex);
3745 mono_cross_helpers_run ();
3747 mono_counters_init ();
3751 mini_jit_init_job_control ();
3753 /* Happens when using the embedding interface */
3754 if (!default_opt_set)
3755 default_opt = mono_parse_default_optimizations (NULL);
3757 #ifdef MONO_ARCH_GSHAREDVT_SUPPORTED
3759 mono_set_generic_sharing_vt_supported (TRUE);
3762 mono_set_generic_sharing_vt_supported (TRUE);
3765 mono_tls_init_runtime_keys ();
3767 if (!global_codeman)
3768 global_codeman = mono_code_manager_new ();
3770 memset (&callbacks, 0, sizeof (callbacks));
3771 callbacks.create_ftnptr = mini_create_ftnptr;
3772 callbacks.get_addr_from_ftnptr = mini_get_addr_from_ftnptr;
3773 callbacks.get_runtime_build_info = mono_get_runtime_build_info;
3774 callbacks.set_cast_details = mono_set_cast_details;
3775 callbacks.debug_log = mono_debugger_agent_debug_log;
3776 callbacks.debug_log_is_enabled = mono_debugger_agent_debug_log_is_enabled;
3777 callbacks.get_vtable_trampoline = mini_get_vtable_trampoline;
3778 callbacks.get_imt_trampoline = mini_get_imt_trampoline;
3779 callbacks.imt_entry_inited = mini_imt_entry_inited;
3780 callbacks.init_delegate = mini_init_delegate;
3781 #define JIT_INVOKE_WORKS
3782 #ifdef JIT_INVOKE_WORKS
3783 callbacks.runtime_invoke = mono_jit_runtime_invoke;
3785 #define JIT_TRAMPOLINES_WORK
3786 #ifdef JIT_TRAMPOLINES_WORK
3787 callbacks.compile_method = mono_jit_compile_method;
3788 callbacks.create_jump_trampoline = mono_create_jump_trampoline;
3789 callbacks.create_jit_trampoline = mono_create_jit_trampoline;
3790 callbacks.create_delegate_trampoline = mono_create_delegate_trampoline;
3791 callbacks.free_method = mono_jit_free_method;
3792 #ifndef DISABLE_REMOTING
3793 callbacks.create_remoting_trampoline = mono_jit_create_remoting_trampoline;
3797 mono_install_callbacks (&callbacks);
3799 memset (&ticallbacks, 0, sizeof (ticallbacks));
3800 ticallbacks.setup_async_callback = mono_setup_async_callback;
3801 ticallbacks.thread_state_init_from_sigctx = mono_thread_state_init_from_sigctx;
3802 ticallbacks.thread_state_init_from_handle = mono_thread_state_init_from_handle;
3803 ticallbacks.thread_state_init = mono_thread_state_init;
3806 mono_w32handle_init ();
3809 mono_threads_runtime_init (&ticallbacks);
3811 if (g_hasenv ("MONO_DEBUG")) {
3812 mini_parse_debug_options ();
3815 mono_code_manager_init ();
3817 memset (&code_manager_callbacks, 0, sizeof (code_manager_callbacks));
3818 #ifdef MONO_ARCH_HAVE_CODE_CHUNK_TRACKING
3819 code_manager_callbacks.chunk_new = code_manager_chunk_new;
3820 code_manager_callbacks.chunk_destroy = code_manager_chunk_destroy;
3822 mono_code_manager_install_callbacks (&code_manager_callbacks);
3826 mono_arch_cpu_init ();
3830 mono_unwind_init ();
3832 if (mini_get_debug_options ()->lldb || g_hasenv ("MONO_LLDB")) {
3833 mono_lldb_init ("");
3834 mono_dont_free_domains = TRUE;
3837 #ifdef XDEBUG_ENABLED
3838 char *mono_xdebug = g_getenv ("MONO_XDEBUG");
3840 mono_xdebug_init (mono_xdebug);
3841 g_free (mono_xdebug);
3842 /* So methods for multiple domains don't have the same address */
3843 mono_dont_free_domains = TRUE;
3844 mono_using_xdebug = TRUE;
3845 } else if (mini_get_debug_options ()->gdb) {
3846 mono_xdebug_init ((char*)"gdb");
3847 mono_dont_free_domains = TRUE;
3848 mono_using_xdebug = TRUE;
3853 if (mono_use_llvm) {
3854 if (!mono_llvm_load (NULL)) {
3855 mono_use_llvm = FALSE;
3856 fprintf (stderr, "Mono Warning: llvm support could not be loaded.\n");
3863 mono_trampolines_init ();
3865 if (default_opt & MONO_OPT_AOT)
3868 mono_debugger_agent_init ();
3870 #ifdef MONO_ARCH_GSHARED_SUPPORTED
3871 mono_set_generic_sharing_supported (TRUE);
3874 mono_threads_signals_init ();
3876 #ifndef MONO_CROSS_COMPILE
3877 mono_runtime_install_handlers ();
3879 mono_threads_install_cleanup (mini_thread_cleanup);
3881 #ifdef JIT_TRAMPOLINES_WORK
3882 mono_install_create_domain_hook (mini_create_jit_domain_info);
3883 mono_install_free_domain_hook (mini_free_jit_domain_info);
3885 mono_install_get_cached_class_info (mono_aot_get_cached_class_info);
3886 mono_install_get_class_from_name (mono_aot_get_class_from_name);
3887 mono_install_jit_info_find_in_aot (mono_aot_find_jit_info);
3889 if (mini_profiler_enabled ()) {
3890 mono_profiler_load (mini_profiler_get_options ());
3891 mono_profiler_thread_name (MONO_NATIVE_THREAD_ID_TO_UINT (mono_native_thread_id_get ()), "Main");
3894 if (debug_options.collect_pagefault_stats)
3895 mono_aot_set_make_unreadable (TRUE);
3897 if (runtime_version)
3898 domain = mono_init_version (filename, runtime_version);
3900 domain = mono_init_from_assembly (filename, filename);
3902 if (mono_aot_only) {
3903 /* This helps catch code allocation requests */
3904 mono_code_manager_set_read_only (domain->code_mp);
3905 mono_marshal_use_aot_wrappers (TRUE);
3908 if (mono_llvm_only) {
3909 mono_install_imt_trampoline_builder (mono_llvmonly_get_imt_trampoline);
3910 mono_set_always_build_imt_trampolines (TRUE);
3911 } else if (mono_aot_only) {
3912 mono_install_imt_trampoline_builder (mono_aot_get_imt_trampoline);
3914 mono_install_imt_trampoline_builder (mono_arch_build_imt_trampoline);
3917 /*Init arch tls information only after the metadata side is inited to make sure we see dynamic appdomain tls keys*/
3918 mono_arch_finish_init ();
3922 /* This must come after mono_init () in the aot-only case */
3923 mono_exceptions_init ();
3925 /* This should come after mono_init () too */
3929 mono_create_helper_signatures ();
3932 register_jit_stats ();
3934 #define JIT_CALLS_WORK
3935 #ifdef JIT_CALLS_WORK
3936 /* Needs to be called here since register_jit_icall depends on it */
3937 mono_marshal_init ();
3939 mono_arch_register_lowlevel_calls ();
3943 mono_generic_sharing_init ();
3946 #ifdef MONO_ARCH_SIMD_INTRINSICS
3947 mono_simd_intrinsics_init ();
3950 mono_tasklets_init ();
3952 register_trampolines (domain);
3954 if (mono_compile_aot)
3956 * Avoid running managed code when AOT compiling, since the platform
3957 * might only support aot-only execution.
3959 mono_runtime_set_no_exec (TRUE);
3961 mono_mem_account_register_counters ();
3963 #define JIT_RUNTIME_WORKS
3964 #ifdef JIT_RUNTIME_WORKS
3965 mono_install_runtime_cleanup ((MonoDomainFunc)mini_cleanup);
3966 mono_runtime_init_checked (domain, mono_thread_start_cb, mono_thread_attach_cb, &error);
3967 mono_error_assert_ok (&error);
3968 mono_thread_attach (domain);
3971 if (mono_profiler_get_events () & MONO_PROFILE_STATISTICAL)
3972 mono_runtime_setup_stat_profiler ();
3974 mono_profiler_runtime_initialized ();
3976 MONO_VES_INIT_END ();
3982 register_icalls (void)
3984 mono_add_internal_call ("System.Diagnostics.StackFrame::get_frame_info",
3985 ves_icall_get_frame_info);
3986 mono_add_internal_call ("System.Diagnostics.StackTrace::get_trace",
3987 ves_icall_get_trace);
3988 mono_add_internal_call ("Mono.Runtime::mono_runtime_install_handlers",
3989 mono_runtime_install_handlers);
3990 mono_add_internal_call ("Mono.Runtime::mono_runtime_cleanup_handlers",
3991 mono_runtime_cleanup_handlers);
3993 #if defined(PLATFORM_ANDROID) || defined(TARGET_ANDROID)
3994 mono_add_internal_call ("System.Diagnostics.Debugger::Mono_UnhandledException_internal",
3995 mono_debugger_agent_unhandled_exception);
3999 * It's important that we pass `TRUE` as the last argument here, as
4000 * it causes the JIT to omit a wrapper for these icalls. If the JIT
4001 * *did* emit a wrapper, we'd be looking at infinite recursion since
4002 * the wrapper would call the icall which would call the wrapper and
4005 register_icall (mono_profiler_method_enter, "mono_profiler_method_enter", "void ptr", TRUE);
4006 register_icall (mono_profiler_method_leave, "mono_profiler_method_leave", "void ptr", TRUE);
4008 register_icall (mono_trace_enter_method, "mono_trace_enter_method", NULL, TRUE);
4009 register_icall (mono_trace_leave_method, "mono_trace_leave_method", NULL, TRUE);
4010 register_icall (mono_get_lmf_addr, "mono_get_lmf_addr", "ptr", TRUE);
4011 register_icall (mono_jit_thread_attach, "mono_jit_thread_attach", "ptr ptr", TRUE);
4012 register_icall (mono_jit_set_domain, "mono_jit_set_domain", "void ptr", TRUE);
4013 register_icall (mono_domain_get, "mono_domain_get", "ptr", TRUE);
4015 register_icall (mono_llvm_throw_exception, "mono_llvm_throw_exception", "void object", TRUE);
4016 register_icall (mono_llvm_rethrow_exception, "mono_llvm_rethrow_exception", "void object", TRUE);
4017 register_icall (mono_llvm_resume_exception, "mono_llvm_resume_exception", "void", TRUE);
4018 register_icall (mono_llvm_match_exception, "mono_llvm_match_exception", "int ptr int int", TRUE);
4019 register_icall (mono_llvm_clear_exception, "mono_llvm_clear_exception", NULL, TRUE);
4020 register_icall (mono_llvm_load_exception, "mono_llvm_load_exception", "object", TRUE);
4021 register_icall (mono_llvm_throw_corlib_exception, "mono_llvm_throw_corlib_exception", "void int", TRUE);
4022 #if defined(ENABLE_LLVM) && !defined(MONO_LLVM_LOADED)
4023 register_icall (mono_llvm_set_unhandled_exception_handler, "mono_llvm_set_unhandled_exception_handler", NULL, TRUE);
4025 // FIXME: This is broken
4026 register_icall (mono_debug_personality, "mono_debug_personality", "int int int ptr ptr ptr", TRUE);
4029 register_dyn_icall (mono_get_throw_exception (), "mono_arch_throw_exception", "void object", TRUE);
4030 register_dyn_icall (mono_get_rethrow_exception (), "mono_arch_rethrow_exception", "void object", TRUE);
4031 register_dyn_icall (mono_get_throw_corlib_exception (), "mono_arch_throw_corlib_exception", "void ptr", TRUE);
4032 register_icall (mono_thread_get_undeniable_exception, "mono_thread_get_undeniable_exception", "object", FALSE);
4033 register_icall (mono_thread_interruption_checkpoint, "mono_thread_interruption_checkpoint", "object", FALSE);
4034 register_icall (mono_thread_force_interruption_checkpoint_noraise, "mono_thread_force_interruption_checkpoint_noraise", "object", FALSE);
4036 #if defined(__native_client__) || defined(__native_client_codegen__)
4037 register_icall (mono_nacl_gc, "mono_nacl_gc", "void", FALSE);
4040 if (mono_threads_is_coop_enabled ())
4041 register_icall (mono_threads_state_poll, "mono_threads_state_poll", "void", FALSE);
4043 #ifndef MONO_ARCH_NO_EMULATE_LONG_MUL_OPTS
4044 register_opcode_emulation (OP_LMUL, "__emul_lmul", "long long long", mono_llmult, "mono_llmult", FALSE);
4045 register_opcode_emulation (OP_LDIV, "__emul_ldiv", "long long long", mono_lldiv, "mono_lldiv", FALSE);
4046 register_opcode_emulation (OP_LDIV_UN, "__emul_ldiv_un", "long long long", mono_lldiv_un, "mono_lldiv_un", FALSE);
4047 register_opcode_emulation (OP_LREM, "__emul_lrem", "long long long", mono_llrem, "mono_llrem", FALSE);
4048 register_opcode_emulation (OP_LREM_UN, "__emul_lrem_un", "long long long", mono_llrem_un, "mono_llrem_un", FALSE);
4050 #if !defined(MONO_ARCH_NO_EMULATE_LONG_MUL_OPTS) || defined(MONO_ARCH_EMULATE_LONG_MUL_OVF_OPTS)
4051 register_opcode_emulation (OP_LMUL_OVF_UN, "__emul_lmul_ovf_un", "long long long", mono_llmult_ovf_un, "mono_llmult_ovf_un", FALSE);
4052 register_opcode_emulation (OP_LMUL_OVF, "__emul_lmul_ovf", "long long long", mono_llmult_ovf, "mono_llmult_ovf", FALSE);
4055 #ifndef MONO_ARCH_NO_EMULATE_LONG_SHIFT_OPS
4056 register_opcode_emulation (OP_LSHL, "__emul_lshl", "long long int32", mono_lshl, "mono_lshl", TRUE);
4057 register_opcode_emulation (OP_LSHR, "__emul_lshr", "long long int32", mono_lshr, "mono_lshr", TRUE);
4058 register_opcode_emulation (OP_LSHR_UN, "__emul_lshr_un", "long long int32", mono_lshr_un, "mono_lshr_un", TRUE);
4061 #if defined(MONO_ARCH_EMULATE_MUL_DIV) || defined(MONO_ARCH_EMULATE_DIV)
4062 register_opcode_emulation (OP_IDIV, "__emul_op_idiv", "int32 int32 int32", mono_idiv, "mono_idiv", FALSE);
4063 register_opcode_emulation (OP_IDIV_UN, "__emul_op_idiv_un", "int32 int32 int32", mono_idiv_un, "mono_idiv_un", FALSE);
4064 register_opcode_emulation (OP_IREM, "__emul_op_irem", "int32 int32 int32", mono_irem, "mono_irem", FALSE);
4065 register_opcode_emulation (OP_IREM_UN, "__emul_op_irem_un", "int32 int32 int32", mono_irem_un, "mono_irem_un", FALSE);
4068 #ifdef MONO_ARCH_EMULATE_MUL_DIV
4069 register_opcode_emulation (OP_IMUL, "__emul_op_imul", "int32 int32 int32", mono_imul, "mono_imul", TRUE);
4072 #if defined(MONO_ARCH_EMULATE_MUL_DIV) || defined(MONO_ARCH_EMULATE_MUL_OVF)
4073 register_opcode_emulation (OP_IMUL_OVF, "__emul_op_imul_ovf", "int32 int32 int32", mono_imul_ovf, "mono_imul_ovf", FALSE);
4074 register_opcode_emulation (OP_IMUL_OVF_UN, "__emul_op_imul_ovf_un", "int32 int32 int32", mono_imul_ovf_un, "mono_imul_ovf_un", FALSE);
4077 #if defined(MONO_ARCH_EMULATE_MUL_DIV) || defined(MONO_ARCH_SOFT_FLOAT_FALLBACK)
4078 register_opcode_emulation (OP_FDIV, "__emul_fdiv", "double double double", mono_fdiv, "mono_fdiv", FALSE);
4081 register_opcode_emulation (OP_FCONV_TO_U8, "__emul_fconv_to_u8", "ulong double", mono_fconv_u8, "mono_fconv_u8", FALSE);
4082 register_opcode_emulation (OP_RCONV_TO_U8, "__emul_rconv_to_u8", "ulong float", mono_rconv_u8, "mono_rconv_u8", FALSE);
4083 register_opcode_emulation (OP_FCONV_TO_U4, "__emul_fconv_to_u4", "uint32 double", mono_fconv_u4, "mono_fconv_u4", FALSE);
4084 register_opcode_emulation (OP_FCONV_TO_OVF_I8, "__emul_fconv_to_ovf_i8", "long double", mono_fconv_ovf_i8, "mono_fconv_ovf_i8", FALSE);
4085 register_opcode_emulation (OP_FCONV_TO_OVF_U8, "__emul_fconv_to_ovf_u8", "ulong double", mono_fconv_ovf_u8, "mono_fconv_ovf_u8", FALSE);
4086 register_opcode_emulation (OP_RCONV_TO_OVF_I8, "__emul_rconv_to_ovf_i8", "long float", mono_rconv_ovf_i8, "mono_rconv_ovf_i8", FALSE);
4087 register_opcode_emulation (OP_RCONV_TO_OVF_U8, "__emul_rconv_to_ovf_u8", "ulong float", mono_rconv_ovf_u8, "mono_rconv_ovf_u8", FALSE);
4090 #ifdef MONO_ARCH_EMULATE_FCONV_TO_I8
4091 register_opcode_emulation (OP_FCONV_TO_I8, "__emul_fconv_to_i8", "long double", mono_fconv_i8, "mono_fconv_i8", FALSE);
4092 register_opcode_emulation (OP_RCONV_TO_I8, "__emul_rconv_to_i8", "long float", mono_rconv_i8, "mono_rconv_i8", FALSE);
4095 #ifdef MONO_ARCH_EMULATE_CONV_R8_UN
4096 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);
4098 #ifdef MONO_ARCH_EMULATE_LCONV_TO_R8
4099 register_opcode_emulation (OP_LCONV_TO_R8, "__emul_lconv_to_r8", "double long", mono_lconv_to_r8, "mono_lconv_to_r8", FALSE);
4101 #ifdef MONO_ARCH_EMULATE_LCONV_TO_R4
4102 register_opcode_emulation (OP_LCONV_TO_R4, "__emul_lconv_to_r4", "float long", mono_lconv_to_r4, "mono_lconv_to_r4", FALSE);
4104 #ifdef MONO_ARCH_EMULATE_LCONV_TO_R8_UN
4105 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);
4107 #ifdef MONO_ARCH_EMULATE_FREM
4108 #if !defined(__native_client__)
4109 register_opcode_emulation (OP_FREM, "__emul_frem", "double double double", fmod, "fmod", FALSE);
4110 register_opcode_emulation (OP_RREM, "__emul_rrem", "float float float", fmodf, "fmodf", FALSE);
4112 register_opcode_emulation (OP_FREM, "__emul_frem", "double double double", mono_fmod, "mono_fmod", FALSE);
4116 #ifdef MONO_ARCH_SOFT_FLOAT_FALLBACK
4117 if (mono_arch_is_soft_float ()) {
4118 register_opcode_emulation (OP_FSUB, "__emul_fsub", "double double double", mono_fsub, "mono_fsub", FALSE);
4119 register_opcode_emulation (OP_FADD, "__emul_fadd", "double double double", mono_fadd, "mono_fadd", FALSE);
4120 register_opcode_emulation (OP_FMUL, "__emul_fmul", "double double double", mono_fmul, "mono_fmul", FALSE);
4121 register_opcode_emulation (OP_FNEG, "__emul_fneg", "double double", mono_fneg, "mono_fneg", FALSE);
4122 register_opcode_emulation (OP_ICONV_TO_R8, "__emul_iconv_to_r8", "double int32", mono_conv_to_r8, "mono_conv_to_r8", FALSE);
4123 register_opcode_emulation (OP_ICONV_TO_R4, "__emul_iconv_to_r4", "double int32", mono_conv_to_r4, "mono_conv_to_r4", FALSE);
4124 register_opcode_emulation (OP_FCONV_TO_R4, "__emul_fconv_to_r4", "double double", mono_fconv_r4, "mono_fconv_r4", FALSE);
4125 register_opcode_emulation (OP_FCONV_TO_I1, "__emul_fconv_to_i1", "int8 double", mono_fconv_i1, "mono_fconv_i1", FALSE);
4126 register_opcode_emulation (OP_FCONV_TO_I2, "__emul_fconv_to_i2", "int16 double", mono_fconv_i2, "mono_fconv_i2", FALSE);
4127 register_opcode_emulation (OP_FCONV_TO_I4, "__emul_fconv_to_i4", "int32 double", mono_fconv_i4, "mono_fconv_i4", FALSE);
4128 register_opcode_emulation (OP_FCONV_TO_U1, "__emul_fconv_to_u1", "uint8 double", mono_fconv_u1, "mono_fconv_u1", FALSE);
4129 register_opcode_emulation (OP_FCONV_TO_U2, "__emul_fconv_to_u2", "uint16 double", mono_fconv_u2, "mono_fconv_u2", FALSE);
4131 #if SIZEOF_VOID_P == 4
4132 register_opcode_emulation (OP_FCONV_TO_I, "__emul_fconv_to_i", "int32 double", mono_fconv_i4, "mono_fconv_i4", FALSE);
4135 register_opcode_emulation (OP_FBEQ, "__emul_fcmp_eq", "uint32 double double", mono_fcmp_eq, "mono_fcmp_eq", FALSE);
4136 register_opcode_emulation (OP_FBLT, "__emul_fcmp_lt", "uint32 double double", mono_fcmp_lt, "mono_fcmp_lt", FALSE);
4137 register_opcode_emulation (OP_FBGT, "__emul_fcmp_gt", "uint32 double double", mono_fcmp_gt, "mono_fcmp_gt", FALSE);
4138 register_opcode_emulation (OP_FBLE, "__emul_fcmp_le", "uint32 double double", mono_fcmp_le, "mono_fcmp_le", FALSE);
4139 register_opcode_emulation (OP_FBGE, "__emul_fcmp_ge", "uint32 double double", mono_fcmp_ge, "mono_fcmp_ge", FALSE);
4140 register_opcode_emulation (OP_FBNE_UN, "__emul_fcmp_ne_un", "uint32 double double", mono_fcmp_ne_un, "mono_fcmp_ne_un", FALSE);
4141 register_opcode_emulation (OP_FBLT_UN, "__emul_fcmp_lt_un", "uint32 double double", mono_fcmp_lt_un, "mono_fcmp_lt_un", FALSE);
4142 register_opcode_emulation (OP_FBGT_UN, "__emul_fcmp_gt_un", "uint32 double double", mono_fcmp_gt_un, "mono_fcmp_gt_un", FALSE);
4143 register_opcode_emulation (OP_FBLE_UN, "__emul_fcmp_le_un", "uint32 double double", mono_fcmp_le_un, "mono_fcmp_le_un", FALSE);
4144 register_opcode_emulation (OP_FBGE_UN, "__emul_fcmp_ge_un", "uint32 double double", mono_fcmp_ge_un, "mono_fcmp_ge_un", FALSE);
4146 register_opcode_emulation (OP_FCEQ, "__emul_fcmp_ceq", "uint32 double double", mono_fceq, "mono_fceq", FALSE);
4147 register_opcode_emulation (OP_FCGT, "__emul_fcmp_cgt", "uint32 double double", mono_fcgt, "mono_fcgt", FALSE);
4148 register_opcode_emulation (OP_FCGT_UN, "__emul_fcmp_cgt_un", "uint32 double double", mono_fcgt_un, "mono_fcgt_un", FALSE);
4149 register_opcode_emulation (OP_FCLT, "__emul_fcmp_clt", "uint32 double double", mono_fclt, "mono_fclt", FALSE);
4150 register_opcode_emulation (OP_FCLT_UN, "__emul_fcmp_clt_un", "uint32 double double", mono_fclt_un, "mono_fclt_un", FALSE);
4152 register_icall (mono_fload_r4, "mono_fload_r4", "double ptr", FALSE);
4153 register_icall (mono_fstore_r4, "mono_fstore_r4", "void double ptr", FALSE);
4154 register_icall (mono_fload_r4_arg, "mono_fload_r4_arg", "uint32 double", FALSE);
4155 register_icall (mono_isfinite, "mono_isfinite", "uint32 double", FALSE);
4158 register_icall (mono_ckfinite, "mono_ckfinite", "double double", FALSE);
4160 #ifdef COMPRESSED_INTERFACE_BITMAP
4161 register_icall (mono_class_interface_match, "mono_class_interface_match", "uint32 ptr int32", TRUE);
4164 #if SIZEOF_REGISTER == 4
4165 register_opcode_emulation (OP_FCONV_TO_U, "__emul_fconv_to_u", "uint32 double", mono_fconv_u4, "mono_fconv_u4", TRUE);
4167 register_opcode_emulation (OP_FCONV_TO_U, "__emul_fconv_to_u", "ulong double", mono_fconv_u8, "mono_fconv_u8", TRUE);
4170 /* other jit icalls */
4171 register_icall (ves_icall_mono_delegate_ctor, "ves_icall_mono_delegate_ctor", "void object object ptr", FALSE);
4172 register_icall (mono_class_static_field_address , "mono_class_static_field_address",
4173 "ptr ptr ptr", FALSE);
4174 register_icall (mono_ldtoken_wrapper, "mono_ldtoken_wrapper", "ptr ptr ptr ptr", FALSE);
4175 register_icall (mono_ldtoken_wrapper_generic_shared, "mono_ldtoken_wrapper_generic_shared",
4176 "ptr ptr ptr ptr", FALSE);
4177 register_icall (mono_get_special_static_data, "mono_get_special_static_data", "ptr int", FALSE);
4178 register_icall (ves_icall_mono_ldstr, "ves_icall_mono_ldstr", "object ptr ptr int32", FALSE);
4179 register_icall (mono_helper_stelem_ref_check, "mono_helper_stelem_ref_check", "void object object", FALSE);
4180 register_icall (ves_icall_object_new, "ves_icall_object_new", "object ptr ptr", FALSE);
4181 register_icall (ves_icall_object_new_specific, "ves_icall_object_new_specific", "object ptr", FALSE);
4182 register_icall (ves_icall_array_new, "ves_icall_array_new", "object ptr ptr int32", FALSE);
4183 register_icall (ves_icall_array_new_specific, "ves_icall_array_new_specific", "object ptr int32", FALSE);
4184 register_icall (ves_icall_runtime_class_init, "ves_icall_runtime_class_init", "void ptr", FALSE);
4185 register_icall (mono_ldftn, "mono_ldftn", "ptr ptr", FALSE);
4186 register_icall (mono_ldvirtfn, "mono_ldvirtfn", "ptr object ptr", FALSE);
4187 register_icall (mono_ldvirtfn_gshared, "mono_ldvirtfn_gshared", "ptr object ptr", FALSE);
4188 register_icall (mono_helper_compile_generic_method, "mono_helper_compile_generic_method", "ptr object ptr ptr", FALSE);
4189 register_icall (mono_helper_ldstr, "mono_helper_ldstr", "object ptr int", FALSE);
4190 register_icall (mono_helper_ldstr_mscorlib, "mono_helper_ldstr_mscorlib", "object int", FALSE);
4191 register_icall (mono_helper_newobj_mscorlib, "mono_helper_newobj_mscorlib", "object int", FALSE);
4192 register_icall (mono_value_copy, "mono_value_copy", "void ptr ptr ptr", FALSE);
4193 register_icall (mono_object_castclass_unbox, "mono_object_castclass_unbox", "object object ptr", FALSE);
4194 register_icall (mono_break, "mono_break", NULL, TRUE);
4195 register_icall (mono_create_corlib_exception_0, "mono_create_corlib_exception_0", "object int", TRUE);
4196 register_icall (mono_create_corlib_exception_1, "mono_create_corlib_exception_1", "object int object", TRUE);
4197 register_icall (mono_create_corlib_exception_2, "mono_create_corlib_exception_2", "object int object object", TRUE);
4198 register_icall (mono_array_new_1, "mono_array_new_1", "object ptr int", FALSE);
4199 register_icall (mono_array_new_2, "mono_array_new_2", "object ptr int int", FALSE);
4200 register_icall (mono_array_new_3, "mono_array_new_3", "object ptr int int int", FALSE);
4201 register_icall (mono_array_new_4, "mono_array_new_4", "object ptr int int int int", FALSE);
4202 register_icall (mono_get_native_calli_wrapper, "mono_get_native_calli_wrapper", "ptr ptr ptr ptr", FALSE);
4203 register_icall (mono_resume_unwind, "mono_resume_unwind", "void", TRUE);
4204 register_icall (mono_gsharedvt_constrained_call, "mono_gsharedvt_constrained_call", "object ptr ptr ptr ptr ptr", FALSE);
4205 register_icall (mono_gsharedvt_value_copy, "mono_gsharedvt_value_copy", "void ptr ptr ptr", TRUE);
4207 register_icall_no_wrapper (mono_gc_get_range_copy_func (), "mono_gc_range_copy", "void ptr ptr int");
4209 register_icall (mono_object_castclass_with_cache, "mono_object_castclass_with_cache", "object object ptr ptr", FALSE);
4210 register_icall (mono_object_isinst_with_cache, "mono_object_isinst_with_cache", "object object ptr ptr", FALSE);
4211 register_icall (mono_generic_class_init, "mono_generic_class_init", "void ptr", FALSE);
4212 register_icall (mono_fill_class_rgctx, "mono_fill_class_rgctx", "ptr ptr int", FALSE);
4213 register_icall (mono_fill_method_rgctx, "mono_fill_method_rgctx", "ptr ptr int", FALSE);
4215 register_icall (mono_debugger_agent_user_break, "mono_debugger_agent_user_break", "void", FALSE);
4217 register_icall (mono_aot_init_llvm_method, "mono_aot_init_llvm_method", "void ptr int", TRUE);
4218 register_icall (mono_aot_init_gshared_method_this, "mono_aot_init_gshared_method_this", "void ptr int object", TRUE);
4219 register_icall (mono_aot_init_gshared_method_mrgctx, "mono_aot_init_gshared_method_mrgctx", "void ptr int ptr", TRUE);
4220 register_icall (mono_aot_init_gshared_method_vtable, "mono_aot_init_gshared_method_vtable", "void ptr int ptr", TRUE);
4222 register_icall_no_wrapper (mono_resolve_iface_call_gsharedvt, "mono_resolve_iface_call_gsharedvt", "ptr object int ptr ptr");
4223 register_icall_no_wrapper (mono_resolve_vcall_gsharedvt, "mono_resolve_vcall_gsharedvt", "ptr object int ptr ptr");
4224 register_icall_no_wrapper (mono_resolve_generic_virtual_call, "mono_resolve_generic_virtual_call", "ptr ptr int ptr");
4225 register_icall_no_wrapper (mono_resolve_generic_virtual_iface_call, "mono_resolve_generic_virtual_iface_call", "ptr ptr int ptr");
4226 /* This needs a wrapper so it can have a preserveall cconv */
4227 register_icall (mono_init_vtable_slot, "mono_init_vtable_slot", "ptr ptr int", FALSE);
4228 register_icall (mono_llvmonly_init_delegate, "mono_llvmonly_init_delegate", "void object", TRUE);
4229 register_icall (mono_llvmonly_init_delegate_virtual, "mono_llvmonly_init_delegate_virtual", "void object object ptr", TRUE);
4230 register_icall (mono_get_assembly_object, "mono_get_assembly_object", "object ptr", TRUE);
4231 register_icall (mono_get_method_object, "mono_get_method_object", "object ptr", TRUE);
4232 register_icall (mono_throw_method_access, "mono_throw_method_access", "void ptr ptr", FALSE);
4233 register_icall_no_wrapper (mono_dummy_jit_icall, "mono_dummy_jit_icall", "void");
4235 register_icall_with_wrapper (mono_monitor_enter_internal, "mono_monitor_enter_internal", "void obj");
4236 register_icall_with_wrapper (mono_monitor_enter_v4_internal, "mono_monitor_enter_v4_internal", "void obj ptr");
4237 register_icall_no_wrapper (mono_monitor_enter_fast, "mono_monitor_enter_fast", "int obj");
4238 register_icall_no_wrapper (mono_monitor_enter_v4_fast, "mono_monitor_enter_v4_fast", "int obj ptr");
4241 register_icall (pthread_getspecific, "pthread_getspecific", "ptr ptr", TRUE);
4243 /* Register tls icalls */
4244 register_icall_no_wrapper (mono_tls_get_thread, "mono_tls_get_thread", "ptr");
4245 register_icall_no_wrapper (mono_tls_get_jit_tls, "mono_tls_get_jit_tls", "ptr");
4246 register_icall_no_wrapper (mono_tls_get_domain, "mono_tls_get_domain", "ptr");
4247 register_icall_no_wrapper (mono_tls_get_sgen_thread_info, "mono_tls_get_sgen_thread_info", "ptr");
4248 register_icall_no_wrapper (mono_tls_get_lmf_addr, "mono_tls_get_lmf_addr", "ptr");
4249 register_icall_no_wrapper (mono_tls_set_thread, "mono_tls_set_thread", "void ptr");
4250 register_icall_no_wrapper (mono_tls_set_jit_tls, "mono_tls_set_jit_tls", "void ptr");
4251 register_icall_no_wrapper (mono_tls_set_domain, "mono_tls_set_domain", "void ptr");
4252 register_icall_no_wrapper (mono_tls_set_sgen_thread_info, "mono_tls_set_sgen_thread_info", "void ptr");
4253 register_icall_no_wrapper (mono_tls_set_lmf_addr, "mono_tls_set_lmf_addr", "void ptr");
4256 MonoJitStats mono_jit_stats = {0};
4259 print_jit_stats (void)
4261 if (mono_jit_stats.enabled) {
4262 g_print ("Mono Jit statistics\n");
4263 g_print ("Max code size ratio: %.2f (%s)\n", mono_jit_stats.max_code_size_ratio/100.0,
4264 mono_jit_stats.max_ratio_method);
4265 g_print ("Biggest method: %ld (%s)\n", mono_jit_stats.biggest_method_size,
4266 mono_jit_stats.biggest_method);
4268 g_print ("Delegates created: %ld\n", mono_stats.delegate_creations);
4269 g_print ("Initialized classes: %ld\n", mono_stats.initialized_class_count);
4270 g_print ("Used classes: %ld\n", mono_stats.used_class_count);
4271 g_print ("Generic vtables: %ld\n", mono_stats.generic_vtable_count);
4272 g_print ("Methods: %ld\n", mono_stats.method_count);
4273 g_print ("Static data size: %ld\n", mono_stats.class_static_data_size);
4274 g_print ("VTable data size: %ld\n", mono_stats.class_vtable_size);
4275 g_print ("Mscorlib mempool size: %d\n", mono_mempool_get_allocated (mono_defaults.corlib->mempool));
4277 g_print ("\nInitialized classes: %ld\n", mono_stats.generic_class_count);
4278 g_print ("Inflated types: %ld\n", mono_stats.inflated_type_count);
4279 g_print ("Generics virtual invokes: %ld\n", mono_jit_stats.generic_virtual_invocations);
4281 g_print ("Sharable generic methods: %ld\n", mono_stats.generics_sharable_methods);
4282 g_print ("Unsharable generic methods: %ld\n", mono_stats.generics_unsharable_methods);
4283 g_print ("Shared generic methods: %ld\n", mono_stats.generics_shared_methods);
4284 g_print ("Shared vtype generic methods: %ld\n", mono_stats.gsharedvt_methods);
4286 g_print ("IMT tables size: %ld\n", mono_stats.imt_tables_size);
4287 g_print ("IMT number of tables: %ld\n", mono_stats.imt_number_of_tables);
4288 g_print ("IMT number of methods: %ld\n", mono_stats.imt_number_of_methods);
4289 g_print ("IMT used slots: %ld\n", mono_stats.imt_used_slots);
4290 g_print ("IMT colliding slots: %ld\n", mono_stats.imt_slots_with_collisions);
4291 g_print ("IMT max collisions: %ld\n", mono_stats.imt_max_collisions_in_slot);
4292 g_print ("IMT methods at max col: %ld\n", mono_stats.imt_method_count_when_max_collisions);
4293 g_print ("IMT trampolines size: %ld\n", mono_stats.imt_trampolines_size);
4295 g_print ("JIT info table inserts: %ld\n", mono_stats.jit_info_table_insert_count);
4296 g_print ("JIT info table removes: %ld\n", mono_stats.jit_info_table_remove_count);
4297 g_print ("JIT info table lookups: %ld\n", mono_stats.jit_info_table_lookup_count);
4299 g_free (mono_jit_stats.max_ratio_method);
4300 mono_jit_stats.max_ratio_method = NULL;
4301 g_free (mono_jit_stats.biggest_method);
4302 mono_jit_stats.biggest_method = NULL;
4307 mini_cleanup (MonoDomain *domain)
4309 if (mono_profiler_get_events () & MONO_PROFILE_STATISTICAL)
4310 mono_runtime_shutdown_stat_profiler ();
4313 cominterop_release_all_rcws ();
4316 #ifndef MONO_CROSS_COMPILE
4318 * mono_domain_finalize () needs to be called early since it needs the
4319 * execution engine still fully working (it may invoke managed finalizers).
4321 mono_domain_finalize (domain, 2000);
4324 /* This accesses metadata so needs to be called before runtime shutdown */
4327 #ifndef MONO_CROSS_COMPILE
4328 mono_runtime_cleanup (domain);
4331 mono_threadpool_cleanup ();
4333 mono_profiler_shutdown ();
4335 free_jit_tls_data ((MonoJitTlsData *)mono_tls_get_jit_tls ());
4337 mono_icall_cleanup ();
4339 mono_runtime_cleanup_handlers ();
4341 #ifndef MONO_CROSS_COMPILE
4342 mono_domain_free (domain, TRUE);
4347 mono_llvm_cleanup ();
4350 mono_aot_cleanup ();
4352 mono_trampolines_cleanup ();
4354 mono_unwind_cleanup ();
4356 mono_code_manager_destroy (global_codeman);
4357 g_free (vtable_trampolines);
4359 mini_jit_cleanup ();
4361 mono_tramp_info_cleanup ();
4363 mono_arch_cleanup ();
4365 mono_generic_sharing_cleanup ();
4369 mono_trace_cleanup ();
4371 mono_counters_dump (MONO_COUNTER_SECTION_MASK | MONO_COUNTER_MONOTONIC, stdout);
4373 if (mono_inject_async_exc_method)
4374 mono_method_desc_free (mono_inject_async_exc_method);
4376 mono_tls_free_keys ();
4378 mono_os_mutex_destroy (&jit_mutex);
4380 mono_code_manager_cleanup ();
4383 mono_w32handle_cleanup ();
4388 mono_set_defaults (int verbose_level, guint32 opts)
4390 mini_verbose = verbose_level;
4391 mono_set_optimizations (opts);
4395 mono_disable_optimizations (guint32 opts)
4397 default_opt &= ~opts;
4401 mono_set_optimizations (guint32 opts)
4404 default_opt_set = TRUE;
4405 #ifdef MONO_ARCH_GSHAREDVT_SUPPORTED
4406 mono_set_generic_sharing_vt_supported (mono_aot_only || ((default_opt & MONO_OPT_GSHAREDVT) != 0));
4409 mono_set_generic_sharing_vt_supported (TRUE);
4414 mono_set_verbose_level (guint32 level)
4416 mini_verbose = level;
4420 * mono_get_runtime_build_info:
4421 * The returned string is owned by the caller. The returned string
4422 * format is <code>VERSION (FULL_VERSION BUILD_DATE)</code> and build date is optional.
4423 * \returns the runtime version + build date in string format.
4426 mono_get_runtime_build_info (void)
4428 if (mono_build_date)
4429 return g_strdup_printf ("%s (%s %s)", VERSION, FULL_VERSION, mono_build_date);
4431 return g_strdup_printf ("%s (%s)", VERSION, FULL_VERSION);
4435 mono_precompile_assembly (MonoAssembly *ass, void *user_data)
4437 GHashTable *assemblies = (GHashTable*)user_data;
4438 MonoImage *image = mono_assembly_get_image (ass);
4439 MonoMethod *method, *invoke;
4442 if (g_hash_table_lookup (assemblies, ass))
4445 g_hash_table_insert (assemblies, ass, ass);
4447 if (mini_verbose > 0)
4448 printf ("PRECOMPILE: %s.\n", mono_image_get_filename (image));
4450 for (i = 0; i < mono_image_get_table_rows (image, MONO_TABLE_METHOD); ++i) {
4453 method = mono_get_method_checked (image, MONO_TOKEN_METHOD_DEF | (i + 1), NULL, NULL, &error);
4455 mono_error_cleanup (&error); /* FIXME don't swallow the error */
4458 if (method->flags & METHOD_ATTRIBUTE_ABSTRACT)
4460 if (method->is_generic || mono_class_is_gtd (method->klass))
4464 if (mini_verbose > 1) {
4465 char * desc = mono_method_full_name (method, TRUE);
4466 g_print ("Compiling %d %s\n", count, desc);
4469 mono_compile_method_checked (method, &error);
4470 if (!is_ok (&error)) {
4471 mono_error_cleanup (&error); /* FIXME don't swallow the error */
4474 if (strcmp (method->name, "Finalize") == 0) {
4475 invoke = mono_marshal_get_runtime_invoke (method, FALSE);
4476 mono_compile_method_checked (invoke, &error);
4477 mono_error_assert_ok (&error);
4479 #ifndef DISABLE_REMOTING
4480 if (mono_class_is_marshalbyref (method->klass) && mono_method_signature (method)->hasthis) {
4481 invoke = mono_marshal_get_remoting_invoke_with_check (method);
4482 mono_compile_method_checked (invoke, &error);
4483 mono_error_assert_ok (&error);
4488 /* Load and precompile referenced assemblies as well */
4489 for (i = 0; i < mono_image_get_table_rows (image, MONO_TABLE_ASSEMBLYREF); ++i) {
4490 mono_assembly_load_reference (image, i);
4491 if (image->references [i])
4492 mono_precompile_assembly (image->references [i], assemblies);
4496 void mono_precompile_assemblies ()
4498 GHashTable *assemblies = g_hash_table_new (NULL, NULL);
4500 mono_assembly_foreach ((GFunc)mono_precompile_assembly, assemblies);
4502 g_hash_table_destroy (assemblies);
4507 * Have to export this for AOT.
4510 mono_personality (void)
4513 g_assert_not_reached ();
4516 // Custom handlers currently only implemented by Windows.
4519 mono_runtime_install_custom_handlers (const char *handlers)
4525 mono_runtime_install_custom_handlers_usage (void)
4528 "Custom Handlers:\n"
4529 " --handlers=HANDLERS Enable handler support, HANDLERS is a comma\n"
4530 " separated list of available handlers to install.\n"
4532 "No handlers supported on current platform.\n");
4534 #endif /* HOST_WIN32 */