5 #include <mono/metadata/appdomain.h>
6 #include <mono/metadata/metadata-internals.h>
7 #include <mono/metadata/marshal.h>
8 #include <mono/metadata/tabledefs.h>
10 #ifdef HAVE_VALGRIND_MEMCHECK_H
11 #include <valgrind/memcheck.h>
17 * mono_magic_trampoline:
19 * This trampoline handles calls from JITted code.
22 mono_magic_trampoline (gssize *regs, guint8 *code, MonoMethod *m, guint8* tramp)
25 gpointer *vtable_slot;
27 addr = mono_compile_method (m);
30 /* the method was jumped to */
34 vtable_slot = mono_arch_get_vcall_slot_addr (code, (gpointer*)regs);
37 if (m->klass->valuetype)
38 addr = mono_arch_get_unbox_trampoline (m, addr);
40 g_assert (*vtable_slot);
42 if (mono_aot_is_got_entry (code, (guint8*)vtable_slot) || mono_domain_owns_vtable_slot (mono_domain_get (), vtable_slot))
43 *vtable_slot = mono_get_addr_from_ftnptr (addr);
46 /* Patch calling code */
49 mono_jit_info_table_find (mono_domain_get (), code);
50 MonoJitInfo *target_ji =
51 mono_jit_info_table_find (mono_domain_get (), mono_get_addr_from_ftnptr (addr));
53 if (mono_method_same_domain (ji, target_ji))
54 mono_arch_patch_callsite (code, addr);
61 * mono_aot_trampoline:
63 * This trampoline handles calls made from AOT code. We try to bypass the
64 * normal JIT compilation logic to avoid loading the metadata for the method.
66 #ifdef MONO_ARCH_HAVE_CREATE_TRAMPOLINE_FROM_TOKEN
68 mono_aot_trampoline (gssize *regs, guint8 *code, guint8 *token_info,
73 MonoMethod *method = NULL;
75 gpointer *vtable_slot;
76 gboolean is_got_entry;
78 image = *(gpointer*)(gpointer)token_info;
79 token_info += sizeof (gpointer);
80 token = *(guint32*)(gpointer)token_info;
82 addr = mono_aot_get_method_from_token (mono_domain_get (), image, token);
84 method = mono_get_method (image, token, NULL);
87 //printf ("F: %s\n", mono_method_full_name (method, TRUE));
89 if (method->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED)
90 method = mono_marshal_get_synchronized_wrapper (method);
92 addr = mono_compile_method (method);
96 vtable_slot = mono_arch_get_vcall_slot_addr (code, (gpointer*)regs);
97 g_assert (vtable_slot);
99 is_got_entry = mono_aot_is_got_entry (code, (guint8*)vtable_slot);
103 method = mono_get_method (image, token, NULL);
104 if (method->klass->valuetype)
105 addr = mono_arch_get_unbox_trampoline (method, addr);
109 * Since AOT code is only used in the root domain,
110 * mono_domain_get () != mono_get_root_domain () means the calling method
111 * is AppDomain:InvokeInDomain, so this is the same check as in
112 * mono_method_same_domain () but without loading the metadata for the method.
114 if ((is_got_entry && (mono_domain_get () == mono_get_root_domain ())) || mono_domain_owns_vtable_slot (mono_domain_get (), vtable_slot))
122 * mono_class_init_trampoline:
124 * This method calls mono_runtime_class_init () to run the static constructor
125 * for the type, then patches the caller code so it is not called again.
128 mono_class_init_trampoline (gssize *regs, guint8 *code, MonoVTable *vtable, guint8 *tramp)
130 mono_runtime_class_init (vtable);
132 if (!mono_running_on_valgrind ())
133 mono_arch_nullify_class_init_trampoline (code, regs);
136 #ifdef MONO_ARCH_HAVE_CREATE_DELEGATE_TRAMPOLINE
139 * mono_delegate_trampoline:
141 * This trampoline handles calls made from the delegate invoke wrapper. It patches
142 * the function address inside the delegate.
145 mono_delegate_trampoline (gssize *regs, guint8 *code, MonoMethod *m, guint8* tramp)
149 addr = mono_compile_method (m);
152 mono_arch_patch_delegate_trampoline (code, tramp, regs, addr);