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>
9 #include <mono/utils/mono-counters.h>
11 #ifdef HAVE_VALGRIND_MEMCHECK_H
12 #include <valgrind/memcheck.h>
16 #include "debug-mini.h"
19 * Address of the trampoline code. This is used by the debugger to check
20 * whether a method is a trampoline.
22 guint8* mono_trampoline_code [MONO_TRAMPOLINE_NUM];
24 static GHashTable *class_init_hash_addr = NULL;
25 static GHashTable *delegate_trampoline_hash_addr = NULL;
27 #define mono_trampolines_lock() EnterCriticalSection (&trampolines_mutex)
28 #define mono_trampolines_unlock() LeaveCriticalSection (&trampolines_mutex)
29 static CRITICAL_SECTION trampolines_mutex;
31 #ifdef MONO_ARCH_HAVE_IMT
34 mono_convert_imt_slot_to_vtable_slot (gpointer* slot, gpointer *regs, guint8 *code, MonoMethod *method, MonoMethod **impl_method)
36 MonoGenericSharingContext *gsctx = mono_get_generic_context_from_code (code);
37 MonoObject *this_argument = mono_arch_find_this_argument (regs, method, gsctx);
38 MonoVTable *vt = this_argument->vtable;
39 int displacement = slot - ((gpointer*)vt);
41 if (displacement > 0) {
42 /* slot is in the vtable, not in the IMT */
44 printf ("mono_convert_imt_slot_to_vtable_slot: slot %p is in the vtable, not in the IMT\n", slot);
48 MonoMethod *imt_method = mono_arch_find_imt_method (regs, code);
50 int imt_slot = MONO_IMT_SIZE + displacement;
52 mono_class_setup_vtable (vt->klass);
53 interface_offset = mono_class_interface_offset (vt->klass, imt_method->klass);
55 if (interface_offset < 0) {
56 g_print ("%s doesn't implement interface %s\n", mono_type_get_name_full (&vt->klass->byval_arg, 0), mono_type_get_name_full (&imt_method->klass->byval_arg, 0));
57 g_assert_not_reached ();
59 mono_vtable_build_imt_slot (vt, mono_method_get_imt_slot (imt_method));
62 *impl_method = vt->klass->vtable [interface_offset + imt_method->slot];
64 printf ("mono_convert_imt_slot_to_vtable_slot: method = %s.%s.%s, imt_method = %s.%s.%s\n",
65 method->klass->name_space, method->klass->name, method->name,
66 imt_method->klass->name_space, imt_method->klass->name, imt_method->name);
68 g_assert (imt_slot < MONO_IMT_SIZE);
69 if (vt->imt_collisions_bitmap & (1 << imt_slot)) {
70 int vtable_offset = interface_offset + imt_method->slot;
71 gpointer *vtable_slot = & (vt->vtable [vtable_offset]);
73 printf ("mono_convert_imt_slot_to_vtable_slot: slot %p[%d] is in the IMT, and colliding becomes %p[%d] (interface_offset = %d, method->slot = %d)\n", slot, imt_slot, vtable_slot, vtable_offset, interface_offset, imt_method->slot);
78 printf ("mono_convert_imt_slot_to_vtable_slot: slot %p[%d] is in the IMT, but not colliding\n", slot, imt_slot);
87 * mono_magic_trampoline:
89 * This trampoline handles calls from JITted code.
92 mono_magic_trampoline (gssize *regs, guint8 *code, MonoMethod *m, guint8* tramp)
95 gpointer *vtable_slot;
96 gboolean generic_shared = FALSE;
97 MonoMethod *declaring = NULL;
100 #if MONO_ARCH_COMMON_VTABLE_TRAMPOLINE
101 if (m == MONO_FAKE_VTABLE_METHOD) {
103 MonoVTable *vt = mono_arch_get_vcall_slot (code, (gpointer*)regs, &displacement);
105 if (displacement > 0) {
106 displacement -= G_STRUCT_OFFSET (MonoVTable, vtable);
107 g_assert (displacement >= 0);
108 displacement /= sizeof (gpointer);
110 /* Avoid loading metadata or creating a generic vtable if possible */
111 addr = mono_aot_get_method_from_vt_slot (mono_domain_get (), vt, displacement);
112 if (addr && !vt->klass->valuetype) {
113 vtable_slot = mono_arch_get_vcall_slot_addr (code, (gpointer*)regs);
114 if (mono_aot_is_got_entry (code, (guint8*)vtable_slot) || mono_domain_owns_vtable_slot (mono_domain_get (), vtable_slot)) {
115 *vtable_slot = mono_get_addr_from_ftnptr (addr);
121 mono_class_setup_vtable (vt->klass);
122 m = vt->klass->vtable [displacement];
123 if (m->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED)
124 m = mono_marshal_get_synchronized_wrapper (m);
125 /*g_print ("%s with disp %d: %s at %p\n", vt->klass->name, displacement, m->name, code);*/
127 /* We got here from an interface method: redirect to IMT handling */
128 m = MONO_FAKE_IMT_METHOD;
129 /*g_print ("vtable with disp %d at %p\n", displacement, code);*/
133 /* this is the IMT trampoline */
134 #ifdef MONO_ARCH_HAVE_IMT
135 if (m == MONO_FAKE_IMT_METHOD) {
136 MonoMethod *impl_method;
137 /* we get the interface method because mono_convert_imt_slot_to_vtable_slot ()
138 * needs the signature to be able to find the this argument
140 m = mono_arch_find_imt_method ((gpointer*)regs, code);
141 vtable_slot = mono_arch_get_vcall_slot_addr (code, (gpointer*)regs);
142 g_assert (vtable_slot);
143 vtable_slot = mono_convert_imt_slot_to_vtable_slot (vtable_slot, (gpointer*)regs, code, m, &impl_method);
144 /* mono_convert_imt_slot_to_vtable_slot () also gives us the method that is supposed
145 * to be called, so we compile it and go ahead as usual.
147 /*g_print ("imt found method %p (%s) at %p\n", impl_method, impl_method->name, code);*/
152 if ((context_used = mono_method_check_context_used (m))) {
153 MonoClass *klass = NULL;
154 MonoMethod *actual_method = NULL;
155 MonoVTable *vt = NULL;
156 MonoGenericInst *method_inst = NULL;
159 generic_shared = TRUE;
163 if (m->is_inflated && mono_method_get_context (m)->method_inst) {
164 #ifdef MONO_ARCH_RGCTX_REG
165 MonoMethodRuntimeGenericContext *mrgctx = (MonoMethodRuntimeGenericContext*)mono_arch_find_static_call_vtable ((gpointer*)regs, code);
167 klass = mrgctx->class_vtable->klass;
168 method_inst = mrgctx->method_inst;
170 g_assert_not_reached ();
172 } else if (m->flags & METHOD_ATTRIBUTE_STATIC) {
173 #ifdef MONO_ARCH_RGCTX_REG
174 MonoVTable *vtable = mono_arch_find_static_call_vtable ((gpointer*)regs, code);
176 klass = vtable->klass;
178 g_assert_not_reached ();
181 #ifdef MONO_ARCH_HAVE_IMT
182 MonoObject *this_argument = mono_arch_find_this_argument ((gpointer*)regs, m,
183 mono_get_generic_context_from_code (code));
185 vt = this_argument->vtable;
186 vtable_slot = mono_arch_get_vcall_slot_addr (code, (gpointer*)regs);
188 g_assert (this_argument->vtable->klass->inited);
189 //mono_class_init (this_argument->vtable->klass);
192 klass = this_argument->vtable->klass->supertypes [m->klass->idepth - 1];
198 g_assert (vtable_slot || klass);
201 int displacement = vtable_slot - ((gpointer*)vt);
203 g_assert_not_reached ();
205 g_assert (displacement > 0);
207 actual_method = vt->klass->vtable [displacement];
211 MonoGenericContext context = { NULL, NULL };
214 declaring = mono_method_get_declaring_generic_method (m);
218 if (klass->generic_class)
219 context.class_inst = klass->generic_class->context.class_inst;
220 else if (klass->generic_container)
221 context.class_inst = klass->generic_container->context.class_inst;
222 context.method_inst = method_inst;
224 actual_method = mono_class_inflate_generic_method (declaring, &context);
226 actual_method = mono_class_get_method_generic (klass, m);
230 g_assert (actual_method->klass == klass);
232 if (actual_method->is_inflated)
233 declaring = mono_method_get_declaring_generic_method (actual_method);
240 addr = mono_compile_method (m);
243 mono_debugger_trampoline_compiled (m, addr);
245 /* the method was jumped to */
249 vtable_slot = mono_arch_get_vcall_slot_addr (code, (gpointer*)regs);
252 if (m->klass->valuetype)
253 addr = mono_arch_get_unbox_trampoline (mono_get_generic_context_from_code (code), m, addr);
255 g_assert (*vtable_slot);
257 if (mono_aot_is_got_entry (code, (guint8*)vtable_slot) || mono_domain_owns_vtable_slot (mono_domain_get (), vtable_slot)) {
258 #ifdef MONO_ARCH_HAVE_IMT
259 vtable_slot = mono_convert_imt_slot_to_vtable_slot (vtable_slot, (gpointer*)regs, code, m, NULL);
261 *vtable_slot = mono_get_addr_from_ftnptr (addr);
264 else if (!generic_shared || mono_domain_lookup_shared_generic (mono_domain_get (), declaring)) {
265 guint8 *plt_entry = mono_aot_get_plt_entry (code);
268 g_assert (mono_method_is_generic_sharable_impl (m, FALSE));
270 /* Patch calling code */
272 mono_arch_patch_plt_entry (plt_entry, addr);
275 mono_jit_info_table_find (mono_domain_get (), (char*)code);
276 MonoJitInfo *target_ji =
277 mono_jit_info_table_find (mono_domain_get (), mono_get_addr_from_ftnptr (addr));
279 if (mono_method_same_domain (ji, target_ji))
280 mono_arch_patch_callsite (ji->code_start, code, addr);
288 * mono_aot_trampoline:
290 * This trampoline handles calls made from AOT code. We try to bypass the
291 * normal JIT compilation logic to avoid loading the metadata for the method.
293 #ifdef MONO_ARCH_HAVE_CREATE_TRAMPOLINE_FROM_TOKEN
295 mono_aot_trampoline (gssize *regs, guint8 *code, guint8 *token_info,
300 MonoMethod *method = NULL;
302 gpointer *vtable_slot;
303 gboolean is_got_entry;
305 image = *(gpointer*)(gpointer)token_info;
306 token_info += sizeof (gpointer);
307 token = *(guint32*)(gpointer)token_info;
309 addr = mono_aot_get_method_from_token (mono_domain_get (), image, token);
311 method = mono_get_method (image, token, NULL);
314 //printf ("F: %s\n", mono_method_full_name (method, TRUE));
316 if (method->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED)
317 method = mono_marshal_get_synchronized_wrapper (method);
319 addr = mono_compile_method (method);
323 vtable_slot = mono_arch_get_vcall_slot_addr (code, (gpointer*)regs);
326 is_got_entry = mono_aot_is_got_entry (code, (guint8*)vtable_slot);
330 method = mono_get_method (image, token, NULL);
331 if (method->klass->valuetype)
332 addr = mono_arch_get_unbox_trampoline (mono_get_generic_context_from_code (code), method, addr);
335 /* This is a normal call through a PLT entry */
336 guint8 *plt_entry = mono_aot_get_plt_entry (code);
338 g_assert (plt_entry);
340 mono_arch_patch_plt_entry (plt_entry, addr);
342 is_got_entry = FALSE;
346 * Since AOT code is only used in the root domain,
347 * mono_domain_get () != mono_get_root_domain () means the calling method
348 * is AppDomain:InvokeInDomain, so this is the same check as in
349 * mono_method_same_domain () but without loading the metadata for the method.
351 if ((is_got_entry && (mono_domain_get () == mono_get_root_domain ())) || mono_domain_owns_vtable_slot (mono_domain_get (), vtable_slot)) {
352 #ifdef MONO_ARCH_HAVE_IMT
354 method = mono_get_method (image, token, NULL);
355 vtable_slot = mono_convert_imt_slot_to_vtable_slot (vtable_slot, (gpointer*)regs, code, method, NULL);
364 * mono_aot_plt_trampoline:
366 * This trampoline handles calls made from AOT code through the PLT table.
369 mono_aot_plt_trampoline (gssize *regs, guint8 *code, guint8 *aot_module,
372 #ifdef MONO_ARCH_AOT_PLT_OFFSET_REG
373 guint32 plt_info_offset = regs [MONO_ARCH_AOT_PLT_OFFSET_REG];
375 guint32 plt_info_offset = -1;
378 return mono_aot_plt_resolve (aot_module, plt_info_offset, code);
383 * mono_class_init_trampoline:
385 * This method calls mono_runtime_class_init () to run the static constructor
386 * for the type, then patches the caller code so it is not called again.
389 mono_class_init_trampoline (gssize *regs, guint8 *code, MonoVTable *vtable, guint8 *tramp)
391 guint8 *plt_entry = mono_aot_get_plt_entry (code);
393 mono_runtime_class_init (vtable);
395 if (!mono_running_on_valgrind ()) {
397 mono_arch_nullify_plt_entry (plt_entry);
399 mono_arch_nullify_class_init_trampoline (code, regs);
405 * mono_generic_class_init_trampoline:
407 * This method calls mono_runtime_class_init () to run the static constructor
411 mono_generic_class_init_trampoline (gssize *regs, guint8 *code, MonoVTable *vtable, guint8 *tramp)
413 g_assert (!vtable->initialized);
415 mono_runtime_class_init (vtable);
419 mono_rgctx_lazy_fetch_trampoline (gssize *regs, guint8 *code, gpointer data, guint8 *tramp)
421 static gboolean inited = FALSE;
422 static int num_lookups = 0;
424 guint32 slot = mono_arch_get_rgctx_lazy_fetch_offset ((gpointer*)regs);
425 guint32 index = MONO_RGCTX_SLOT_INDEX (slot);
426 gboolean mrgctx = MONO_RGCTX_SLOT_IS_MRGCTX (slot);
429 mono_counters_register ("RGCTX unmanaged lookups", MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &num_lookups);
436 return mono_method_fill_runtime_generic_context (data, index);
438 return mono_class_fill_runtime_generic_context (data, index);
441 #ifdef MONO_ARCH_HAVE_CREATE_DELEGATE_TRAMPOLINE
444 * mono_delegate_trampoline:
446 * This trampoline handles calls made to Delegate:Invoke ().
447 * This is called once the first time a delegate is invoked, so it must be fast.
450 mono_delegate_trampoline (gssize *regs, guint8 *code, gpointer *tramp_data, guint8* tramp)
452 MonoDomain *domain = mono_domain_get ();
453 MonoDelegate *delegate;
456 MonoMethod *method = NULL;
457 gboolean multicast, callvirt;
458 MonoMethod *invoke = tramp_data [0];
459 guint8 *impl_this = tramp_data [1];
460 guint8 *impl_nothis = tramp_data [2];
462 /* Obtain the delegate object according to the calling convention */
465 * Avoid calling mono_get_generic_context_from_code () now since it is expensive,
466 * get_this_arg_from_call will call it if needed.
468 delegate = mono_arch_get_this_arg_from_call (NULL, mono_method_signature (invoke), regs, code);
470 if (!delegate->method_ptr && delegate->method) {
471 /* The delegate was initialized by mini_delegate_ctor */
472 method = delegate->method;
474 if (delegate->target && delegate->target->vtable->klass == mono_defaults.transparent_proxy_class)
475 method = mono_marshal_get_remoting_invoke (method);
476 else if (mono_method_signature (method)->hasthis && method->klass->valuetype)
477 method = mono_marshal_get_unbox_wrapper (method);
478 } else if (delegate->method) {
479 method = delegate->method;
481 ji = mono_jit_info_table_find (domain, mono_get_addr_from_ftnptr (delegate->method_ptr));
485 callvirt = !delegate->target && method && mono_method_signature (method)->hasthis;
488 * If the called address is a trampoline, replace it with the compiled method so
489 * further calls don't have to go through the trampoline.
491 if (method && !callvirt) {
492 delegate->method_ptr = mono_compile_method (method);
493 mono_debugger_trampoline_compiled (method, delegate->method_ptr);
496 multicast = ((MonoMulticastDelegate*)delegate)->prev != NULL;
497 if (!multicast && !callvirt) {
498 code = delegate->target ? impl_this : impl_nothis;
501 delegate->invoke_impl = code;
506 /* The general, unoptimized case */
507 m = mono_marshal_get_delegate_invoke (invoke, delegate);
508 code = mono_compile_method (m);
509 delegate->invoke_impl = mono_get_addr_from_ftnptr (code);
510 mono_debugger_trampoline_compiled (m, delegate->invoke_impl);
518 * mono_get_trampoline_func:
520 * Return the C function which needs to be called by the generic trampoline of type
524 mono_get_trampoline_func (MonoTrampolineType tramp_type)
526 switch (tramp_type) {
527 case MONO_TRAMPOLINE_JIT:
528 case MONO_TRAMPOLINE_JUMP:
529 return mono_magic_trampoline;
530 case MONO_TRAMPOLINE_CLASS_INIT:
531 return mono_class_init_trampoline;
532 case MONO_TRAMPOLINE_GENERIC_CLASS_INIT:
533 return mono_generic_class_init_trampoline;
534 case MONO_TRAMPOLINE_RGCTX_LAZY_FETCH:
535 return mono_rgctx_lazy_fetch_trampoline;
536 #ifdef MONO_ARCH_AOT_SUPPORTED
537 case MONO_TRAMPOLINE_AOT:
538 return mono_aot_trampoline;
539 case MONO_TRAMPOLINE_AOT_PLT:
540 return mono_aot_plt_trampoline;
542 #ifdef MONO_ARCH_HAVE_CREATE_DELEGATE_TRAMPOLINE
543 case MONO_TRAMPOLINE_DELEGATE:
544 return mono_delegate_trampoline;
547 g_assert_not_reached ();
553 mono_trampolines_init (void)
555 InitializeCriticalSection (&trampolines_mutex);
560 mono_trampoline_code [MONO_TRAMPOLINE_JIT] = mono_arch_create_trampoline_code (MONO_TRAMPOLINE_JIT);
561 mono_trampoline_code [MONO_TRAMPOLINE_JUMP] = mono_arch_create_trampoline_code (MONO_TRAMPOLINE_JUMP);
562 mono_trampoline_code [MONO_TRAMPOLINE_CLASS_INIT] = mono_arch_create_trampoline_code (MONO_TRAMPOLINE_CLASS_INIT);
563 mono_trampoline_code [MONO_TRAMPOLINE_GENERIC_CLASS_INIT] = mono_arch_create_trampoline_code (MONO_TRAMPOLINE_GENERIC_CLASS_INIT);
564 mono_trampoline_code [MONO_TRAMPOLINE_RGCTX_LAZY_FETCH] = mono_arch_create_trampoline_code (MONO_TRAMPOLINE_RGCTX_LAZY_FETCH);
565 #ifdef MONO_ARCH_AOT_SUPPORTED
566 mono_trampoline_code [MONO_TRAMPOLINE_AOT] = mono_arch_create_trampoline_code (MONO_TRAMPOLINE_AOT);
567 mono_trampoline_code [MONO_TRAMPOLINE_AOT_PLT] = mono_arch_create_trampoline_code (MONO_TRAMPOLINE_AOT_PLT);
569 #ifdef MONO_ARCH_HAVE_CREATE_DELEGATE_TRAMPOLINE
570 mono_trampoline_code [MONO_TRAMPOLINE_DELEGATE] = mono_arch_create_trampoline_code (MONO_TRAMPOLINE_DELEGATE);
575 mono_trampolines_cleanup (void)
577 if (class_init_hash_addr)
578 g_hash_table_destroy (class_init_hash_addr);
579 if (delegate_trampoline_hash_addr)
580 g_hash_table_destroy (delegate_trampoline_hash_addr);
582 DeleteCriticalSection (&trampolines_mutex);
586 mono_get_trampoline_code (MonoTrampolineType tramp_type)
588 g_assert (mono_trampoline_code [tramp_type]);
590 return mono_trampoline_code [tramp_type];
594 mono_create_specific_trampoline (gpointer arg1, MonoTrampolineType tramp_type, MonoDomain *domain, guint32 *code_len)
597 return mono_aot_create_specific_trampoline (mono_defaults.corlib, arg1, tramp_type, domain, code_len);
599 return mono_arch_create_specific_trampoline (arg1, tramp_type, domain, code_len);
603 mono_create_class_init_trampoline (MonoVTable *vtable)
607 g_assert (!vtable->klass->generic_container);
609 /* previously created trampoline code */
610 mono_domain_lock (vtable->domain);
612 g_hash_table_lookup (vtable->domain->class_init_trampoline_hash,
614 mono_domain_unlock (vtable->domain);
618 code = mono_create_specific_trampoline (vtable, MONO_TRAMPOLINE_CLASS_INIT, vtable->domain, NULL);
620 ptr = mono_create_ftnptr (vtable->domain, code);
622 /* store trampoline address */
623 mono_domain_lock (vtable->domain);
624 g_hash_table_insert (vtable->domain->class_init_trampoline_hash,
626 mono_domain_unlock (vtable->domain);
628 mono_trampolines_lock ();
629 if (!class_init_hash_addr)
630 class_init_hash_addr = g_hash_table_new (NULL, NULL);
631 g_hash_table_insert (class_init_hash_addr, ptr, vtable);
632 mono_trampolines_unlock ();
638 mono_create_jump_trampoline (MonoDomain *domain, MonoMethod *method,
639 gboolean add_sync_wrapper)
643 guint32 code_size = 0;
645 if (add_sync_wrapper && method->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED)
646 return mono_create_jump_trampoline (domain, mono_marshal_get_synchronized_wrapper (method), FALSE);
648 code = mono_jit_find_compiled_method (domain, method);
652 mono_domain_lock (domain);
653 code = g_hash_table_lookup (domain->jump_trampoline_hash, method);
654 mono_domain_unlock (domain);
658 code = mono_create_specific_trampoline (method, MONO_TRAMPOLINE_JUMP, mono_domain_get (), &code_size);
659 g_assert (code_size);
661 mono_domain_lock (domain);
662 ji = mono_mempool_alloc0 (domain->mp, sizeof (MonoJitInfo));
663 mono_domain_unlock (domain);
664 ji->code_start = code;
665 ji->code_size = code_size;
669 * mono_delegate_ctor needs to find the method metadata from the
670 * trampoline address, so we save it here.
673 mono_jit_info_table_add (domain, ji);
675 mono_domain_lock (domain);
676 g_hash_table_insert (domain->jump_trampoline_hash, method, ji->code_start);
677 mono_domain_unlock (domain);
679 return ji->code_start;
683 mono_create_jit_trampoline_in_domain (MonoDomain *domain, MonoMethod *method, gboolean add_sync_wrapper)
688 /* Avoid creating trampolines if possible */
689 gpointer code = mono_jit_find_compiled_method (domain, method);
695 mono_domain_lock (domain);
696 tramp = g_hash_table_lookup (domain->jit_trampoline_hash, method);
697 mono_domain_unlock (domain);
701 if ((method->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED) && add_sync_wrapper)
702 return mono_create_jit_trampoline (mono_marshal_get_synchronized_wrapper (method));
704 tramp = mono_create_specific_trampoline (method, MONO_TRAMPOLINE_JIT, domain, NULL);
706 mono_domain_lock (domain);
707 g_hash_table_insert (domain->jit_trampoline_hash, method, tramp);
708 mono_domain_unlock (domain);
710 mono_jit_stats.method_trampolines++;
716 mono_create_jit_trampoline (MonoMethod *method)
718 return mono_create_jit_trampoline_in_domain (mono_domain_get (), method, TRUE);
721 #ifdef MONO_ARCH_HAVE_CREATE_TRAMPOLINE_FROM_TOKEN
723 mono_create_jit_trampoline_from_token (MonoImage *image, guint32 token)
727 MonoDomain *domain = mono_domain_get ();
730 mono_domain_lock (domain);
731 buf = start = mono_code_manager_reserve (domain->code_mp, 2 * sizeof (gpointer));
732 mono_domain_unlock (domain);
734 *(gpointer*)(gpointer)buf = image;
735 buf += sizeof (gpointer);
736 *(guint32*)(gpointer)buf = token;
738 tramp = mono_create_specific_trampoline (start, MONO_TRAMPOLINE_AOT, domain, NULL);
740 mono_jit_stats.method_trampolines++;
747 mono_create_delegate_trampoline (MonoClass *klass)
749 #ifdef MONO_ARCH_HAVE_CREATE_DELEGATE_TRAMPOLINE
750 MonoDomain *domain = mono_domain_get ();
752 guint32 code_size = 0;
753 gpointer *tramp_data;
756 mono_domain_lock (domain);
757 ptr = g_hash_table_lookup (domain->delegate_trampoline_hash, klass);
758 mono_domain_unlock (domain);
762 // Precompute the delegate invoke impl and pass it to the delegate trampoline
763 invoke = mono_get_delegate_invoke (klass);
766 mono_domain_lock (domain );
767 tramp_data = mono_mempool_alloc (domain->mp, sizeof (gpointer) * 3);
768 mono_domain_unlock (domain);
769 tramp_data [0] = invoke;
771 tramp_data [1] = NULL;
772 tramp_data [2] = NULL;
774 tramp_data [1] = mono_arch_get_delegate_invoke_impl (mono_method_signature (invoke), TRUE);
775 tramp_data [2] = mono_arch_get_delegate_invoke_impl (mono_method_signature (invoke), FALSE);
778 ptr = mono_create_specific_trampoline (tramp_data, MONO_TRAMPOLINE_DELEGATE, mono_domain_get (), &code_size);
779 g_assert (code_size);
781 /* store trampoline address */
782 mono_domain_lock (domain);
783 g_hash_table_insert (domain->delegate_trampoline_hash,
785 mono_domain_unlock (domain);
787 mono_trampolines_lock ();
788 if (!delegate_trampoline_hash_addr)
789 delegate_trampoline_hash_addr = g_hash_table_new (NULL, NULL);
790 g_hash_table_insert (delegate_trampoline_hash_addr, ptr, klass);
791 mono_trampolines_unlock ();
800 mono_find_class_init_trampoline_by_addr (gconstpointer addr)
804 mono_trampolines_lock ();
805 if (class_init_hash_addr)
806 res = g_hash_table_lookup (class_init_hash_addr, addr);
809 mono_trampolines_unlock ();
814 mono_find_delegate_trampoline_by_addr (gconstpointer addr)
818 mono_trampolines_lock ();
819 if (delegate_trampoline_hash_addr)
820 res = g_hash_table_lookup (delegate_trampoline_hash_addr, addr);
823 mono_trampolines_unlock ();