X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmini%2Fmini-trampolines.c;h=e0402664a964f9fcf5b675446e92841c7642b2e4;hb=HEAD;hp=fbc9674fb52702f0c2a3cc0100b36a9d93f35393;hpb=64b7e70f0d5f9ec7ae2b5c2b4ba4b51ed5f71d39;p=mono.git diff --git a/mono/mini/mini-trampolines.c b/mono/mini/mini-trampolines.c index fbc9674fb52..e0402664a96 100644 --- a/mono/mini/mini-trampolines.c +++ b/mono/mini/mini-trampolines.c @@ -1,4 +1,5 @@ -/* +/** + * \file * (C) 2003 Ximian, Inc. * (C) 2003-2011 Novell, Inc. * Copyright 2011 Xamarin, Inc (http://www.xamarin.com) @@ -16,8 +17,14 @@ #include #include #include +#include #include "mini.h" +#include "lldb.h" + +#ifdef ENABLE_INTERPRETER +#include "interp/interp.h" +#endif /* * Address of the trampoline code. This is used by the debugger to check @@ -27,7 +34,13 @@ guint8* mono_trampoline_code [MONO_TRAMPOLINE_NUM]; static GHashTable *rgctx_lazy_fetch_trampoline_hash; static GHashTable *rgctx_lazy_fetch_trampoline_hash_addr; -static guint32 trampoline_calls, jit_trampolines, unbox_trampolines, static_rgctx_trampolines; + +static gint32 trampoline_calls; +static gint32 jit_trampolines; +static gint32 unbox_trampolines; +static gint32 static_rgctx_trampolines; +static gint32 rgctx_unmanaged_lookups; +static gint32 rgctx_num_lazy_fetch_trampolines; #define mono_trampolines_lock() mono_os_mutex_lock (&trampolines_mutex) #define mono_trampolines_unlock() mono_os_mutex_unlock (&trampolines_mutex) @@ -62,8 +75,8 @@ rgctx_tramp_info_hash (gconstpointer data) /** * mono_create_static_rgctx_trampoline: - * @m: the mono method to create a trampoline for - * @addr: the address to jump to (where the compiled code for M lives) + * \param m the mono method to create a trampoline for + * \param addr the address to jump to (where the compiled code for M lives) * * Creates a static rgctx trampoline for M which branches to ADDR which should * point to the compiled code of M. @@ -77,7 +90,7 @@ rgctx_tramp_info_hash (gconstpointer data) * * On PPC addr should be an ftnptr and the return value is an ftnptr too. * - * Returns the generated static rgctx trampoline. + * \returns the generated static rgctx trampoline. */ gpointer mono_create_static_rgctx_trampoline (MonoMethod *m, gpointer addr) @@ -114,7 +127,7 @@ mono_create_static_rgctx_trampoline (MonoMethod *m, gpointer addr) if (mono_aot_only) res = mono_aot_get_static_rgctx_trampoline (ctx, addr); else - res = mono_arch_get_static_rgctx_trampoline (m, (MonoMethodRuntimeGenericContext *)ctx, addr); + res = mono_arch_get_static_rgctx_trampoline (ctx, addr); mono_domain_lock (domain); /* Duplicates inserted while we didn't hold the lock are OK */ @@ -122,9 +135,9 @@ mono_create_static_rgctx_trampoline (MonoMethod *m, gpointer addr) info->m = m; info->addr = addr; g_hash_table_insert (domain_jit_info (domain)->static_rgctx_trampoline_hash, info, res); - mono_domain_unlock (domain); - static_rgctx_trampolines ++; + UnlockedIncrement (&static_rgctx_trampolines); + mono_domain_unlock (domain); return res; } @@ -166,7 +179,7 @@ mini_resolve_imt_method (MonoVTable *vt, gpointer *vtable_slot, MonoMethod *imt_ g_assert (imt_slot < MONO_IMT_SIZE); - mono_error_init (error); + error_init (error); /* This has to be variance aware since imt_method can be from an interface that vt->klass doesn't directly implement */ interface_offset = mono_class_interface_offset_with_variance (vt->klass, imt_method->klass, &variance_used); if (interface_offset < 0) @@ -198,8 +211,8 @@ mini_resolve_imt_method (MonoVTable *vt, gpointer *vtable_slot, MonoMethod *imt_ /* imt_method->slot might not be set */ impl = mono_class_get_vtable_entry (vt->klass, interface_offset + mono_method_get_declaring_generic_method (imt_method)->slot); - if (impl->klass->generic_class) - context.class_inst = impl->klass->generic_class->context.class_inst; + if (mono_class_is_ginst (impl->klass)) + context.class_inst = mono_class_get_generic_class (impl->klass)->context.class_inst; context.method_inst = ((MonoMethodInflated*)imt_method)->context.method_inst; impl = mono_class_inflate_generic_method_checked (impl, &context, error); mono_error_assert_ok (error); @@ -366,12 +379,9 @@ mini_add_method_trampoline (MonoMethod *m, gpointer compiled_method, gboolean ad if (callee_array_helper) { add_static_rgctx_tramp = FALSE; - /* FIXME: ji->from_aot is not set for llvm methods */ - if (ji && (ji->from_aot || mono_aot_only)) { - /* In AOT mode, compiled_method points to one of the InternalArray methods in Array. */ - if (!mono_llvm_only && mono_method_needs_static_rgctx_invoke (jinfo_get_method (ji), TRUE)) - add_static_rgctx_tramp = TRUE; - } + /* In AOT mode, compiled_method points to one of the InternalArray methods in Array. */ + if (ji && !mono_llvm_only && mono_method_needs_static_rgctx_invoke (jinfo_get_method (ji), TRUE)) + add_static_rgctx_tramp = TRUE; } if (mono_llvm_only) @@ -525,7 +535,7 @@ common_call_trampoline (mgreg_t *regs, guint8 *code, MonoMethod *m, MonoVTable * gpointer *orig_vtable_slot, *vtable_slot_to_patch = NULL; MonoJitInfo *ji = NULL; - mono_error_init (error); + error_init (error); virtual_ = vt && (gpointer)vtable_slot > (gpointer)vt; imt_call = vt && (gpointer)vtable_slot < (gpointer)vt; @@ -564,7 +574,11 @@ common_call_trampoline (mgreg_t *regs, guint8 *code, MonoMethod *m, MonoVTable * vtable_slot = mini_resolve_imt_method (vt, vtable_slot, imt_method, &impl_method, &addr, &need_rgctx_tramp, &variant_iface, error); return_val_if_nok (error, NULL); - /* This is the vcall slot which gets called through the IMT thunk */ + /* We must handle magic interfaces on rank 1 arrays of ref types as if they were variant */ + if (!variant_iface && vt->klass->rank == 1 && !vt->klass->element_class->valuetype && imt_method->klass->is_array_special_interface) + variant_iface = imt_method; + + /* This is the vcall slot which gets called through the IMT trampoline */ vtable_slot_to_patch = vtable_slot; if (addr) { @@ -594,10 +608,10 @@ common_call_trampoline (mgreg_t *regs, guint8 *code, MonoMethod *m, MonoVTable * else declaring = m; - if (m->klass->generic_class) - context.class_inst = m->klass->generic_class->context.class_inst; + if (mono_class_is_ginst (m->klass)) + context.class_inst = mono_class_get_generic_class (m->klass)->context.class_inst; else - g_assert (!m->klass->generic_container); + g_assert (!mono_class_is_gtd (m->klass)); generic_virtual = mono_arch_find_imt_method (regs, code); g_assert (generic_virtual); @@ -665,10 +679,10 @@ common_call_trampoline (mgreg_t *regs, guint8 *code, MonoMethod *m, MonoVTable * else declaring = m; - if (klass->generic_class) - context.class_inst = klass->generic_class->context.class_inst; - else if (klass->generic_container) - context.class_inst = klass->generic_container->context.class_inst; + if (mono_class_is_ginst (klass)) + context.class_inst = mono_class_get_generic_class (klass)->context.class_inst; + else if (mono_class_is_gtd (klass)) + context.class_inst = mono_class_get_generic_container (klass)->context.class_inst; context.method_inst = method_inst; actual_method = mono_class_inflate_generic_method_checked (declaring, &context, error); @@ -821,19 +835,19 @@ gpointer mono_magic_trampoline (mgreg_t *regs, guint8 *code, gpointer arg, guint8* tramp) { gpointer res; - - MONO_ENTER_GC_UNSAFE_UNBALANCED; - MonoError error; - trampoline_calls ++; + MONO_REQ_GC_UNSAFE_MODE; - res = common_call_trampoline (regs, code, (MonoMethod *)arg, NULL, NULL, &error); - mono_error_set_pending_exception (&error); + g_assert (mono_thread_is_gc_unsafe_mode ()); - mono_interruption_checkpoint_from_trampoline (); + UnlockedIncrement (&trampoline_calls); - MONO_EXIT_GC_UNSAFE_UNBALANCED; + res = common_call_trampoline (regs, code, (MonoMethod *)arg, NULL, NULL, &error); + if (!is_ok (&error)) { + mono_error_set_pending_exception (&error); + return NULL; + } return res; } @@ -853,9 +867,9 @@ mono_vcall_trampoline (mgreg_t *regs, guint8 *code, int slot, guint8 *tramp) gpointer *vtable_slot; MonoMethod *m; MonoError error; - gpointer addr, res; + gpointer addr, res = NULL; - trampoline_calls ++; + UnlockedIncrement (&trampoline_calls); /* * We need to obtain the following pieces of information: @@ -929,7 +943,7 @@ mono_generic_virtual_remoting_trampoline (mgreg_t *regs, guint8 *code, MonoMetho MonoMethod *imt_method, *declaring; gpointer addr; - trampoline_calls ++; + UnlockedIncrement (&trampoline_calls); g_assert (m->is_generic); @@ -938,10 +952,10 @@ mono_generic_virtual_remoting_trampoline (mgreg_t *regs, guint8 *code, MonoMetho else declaring = m; - if (m->klass->generic_class) - context.class_inst = m->klass->generic_class->context.class_inst; + if (mono_class_is_ginst (m->klass)) + context.class_inst = mono_class_get_generic_class (m->klass)->context.class_inst; else - g_assert (!m->klass->generic_container); + g_assert (!mono_class_is_gtd (m->klass)); imt_method = mono_arch_find_imt_method (regs, code); if (imt_method->is_inflated) @@ -981,7 +995,7 @@ mono_aot_trampoline (mgreg_t *regs, guint8 *code, guint8 *token_info, guint8 *plt_entry; MonoError error; - trampoline_calls ++; + UnlockedIncrement (&trampoline_calls); image = (MonoImage *)*(gpointer*)(gpointer)token_info; token_info += sizeof (gpointer); @@ -1025,7 +1039,7 @@ mono_aot_plt_trampoline (mgreg_t *regs, guint8 *code, guint8 *aot_module, gpointer res; MonoError error; - trampoline_calls ++; + UnlockedIncrement (&trampoline_calls); res = mono_aot_plt_resolve (aot_module, plt_info_offset, code, &error); if (!res) { @@ -1046,8 +1060,6 @@ mono_rgctx_lazy_fetch_trampoline (mgreg_t *regs, guint8 *code, gpointer data, gu { MONO_REQ_GC_UNSAFE_MODE; - static gboolean inited = FALSE; - static int num_lookups = 0; guint32 slot = GPOINTER_TO_UINT (data); mgreg_t *r = (mgreg_t*)regs; gpointer arg = (gpointer)(gssize)r [MONO_ARCH_VTABLE_REG]; @@ -1056,14 +1068,8 @@ mono_rgctx_lazy_fetch_trampoline (mgreg_t *regs, guint8 *code, gpointer data, gu MonoError error; gpointer res; - trampoline_calls ++; - - if (!inited) { - mono_counters_register ("RGCTX unmanaged lookups", MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &num_lookups); - inited = TRUE; - } - - num_lookups++; + UnlockedIncrement (&trampoline_calls); + UnlockedIncrement (&rgctx_unmanaged_lookups); if (mrgctx) res = mono_method_fill_runtime_generic_context ((MonoMethodRuntimeGenericContext *)arg, index, &error); @@ -1106,7 +1112,7 @@ mono_delegate_trampoline (mgreg_t *regs, guint8 *code, gpointer *arg, guint8* tr gpointer addr, compiled_method; gboolean is_remote = FALSE; - trampoline_calls ++; + UnlockedIncrement (&trampoline_calls); /* Obtain the delegate object according to the calling convention */ delegate = (MonoDelegate *)mono_arch_get_this_arg_from_call (regs, code); @@ -1123,7 +1129,7 @@ mono_delegate_trampoline (mgreg_t *regs, guint8 *code, gpointer *arg, guint8* tr * delegate->method). */ #ifndef DISABLE_REMOTING - if (delegate->target && delegate->target->vtable->klass == mono_defaults.transparent_proxy_class) { + if (delegate->target && mono_object_is_transparent_proxy (delegate->target)) { is_remote = TRUE; #ifndef DISABLE_COM if (((MonoTransparentProxy *)delegate->target)->remote_class->proxy_class != mono_class_get_com_object_class () && @@ -1135,7 +1141,7 @@ mono_delegate_trampoline (mgreg_t *regs, guint8 *code, gpointer *arg, guint8* tr if (!is_remote) { sig = tramp_info->sig; if (!(sig && method == tramp_info->method)) { - mono_error_init (&err); + error_init (&err); sig = mono_method_signature_checked (method, &err); if (!sig) { mono_error_set_pending_exception (&err); @@ -1169,7 +1175,7 @@ mono_delegate_trampoline (mgreg_t *regs, guint8 *code, gpointer *arg, guint8* tr if (method) { sig = tramp_info->sig; if (!(sig && method == tramp_info->method)) { - mono_error_init (&err); + error_init (&err); sig = mono_method_signature_checked (method, &err); if (!sig) { mono_error_set_pending_exception (&err); @@ -1191,7 +1197,7 @@ mono_delegate_trampoline (mgreg_t *regs, guint8 *code, gpointer *arg, guint8* tr * If the call doesn't return a valuetype, then the vcall uses the same calling * convention as a normal call. */ - if (((method->klass->flags & TYPE_ATTRIBUTE_SEALED) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) && !MONO_TYPE_ISSTRUCT (sig->ret)) { + if ((mono_class_is_sealed (method->klass) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) && !MONO_TYPE_ISSTRUCT (sig->ret)) { callvirt = FALSE; enable_caching = FALSE; } @@ -1200,7 +1206,7 @@ mono_delegate_trampoline (mgreg_t *regs, guint8 *code, gpointer *arg, guint8* tr if (delegate->target && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->flags & METHOD_ATTRIBUTE_ABSTRACT && - method->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) { + mono_class_is_abstract (method->klass)) { method = mono_object_get_virtual_method (delegate->target, method); enable_caching = FALSE; } @@ -1270,64 +1276,6 @@ mono_delegate_trampoline (mgreg_t *regs, guint8 *code, gpointer *arg, guint8* tr return code; } -#ifdef MONO_ARCH_HAVE_HANDLER_BLOCK_GUARD -static gpointer -mono_handler_block_guard_trampoline (mgreg_t *regs, guint8 *code, gpointer *tramp_info, guint8* tramp) -{ - MONO_REQ_GC_UNSAFE_MODE; - - MonoContext ctx; - MonoException *exc; - MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_native_tls_get_value (mono_jit_tls_id); - gpointer resume_ip = jit_tls->handler_block_return_address; - - memcpy (&ctx, &jit_tls->handler_block_context, sizeof (MonoContext)); - MONO_CONTEXT_SET_IP (&ctx, jit_tls->handler_block_return_address); - - jit_tls->handler_block_return_address = NULL; - jit_tls->handler_block = NULL; - - if (!resume_ip) /*this should not happen, but we should avoid crashing */ - exc = mono_get_exception_execution_engine ("Invalid internal state, resuming abort after handler block but no resume ip found"); - else - exc = mono_thread_resume_interruption (); - - if (exc) { - mono_handle_exception (&ctx, (MonoObject *)exc); - mono_restore_context (&ctx); - } - - return resume_ip; -} - -gpointer -mono_create_handler_block_trampoline (void) -{ - static gpointer code; - if (code) { - mono_memory_barrier (); - return code; - } - - g_assert (!mono_aot_only); - - mono_trampolines_lock (); - - if (!code) { - MonoTrampInfo *info; - gpointer tmp; - - tmp = mono_arch_create_handler_block_trampoline (&info, FALSE); - mono_tramp_info_register (info, NULL); - mono_memory_barrier (); - code = tmp; - } - mono_trampolines_unlock (); - - return code; -} -#endif - /* * mono_get_trampoline_func: * @@ -1359,10 +1307,6 @@ mono_get_trampoline_func (MonoTrampolineType tramp_type) #endif case MONO_TRAMPOLINE_VCALL: return mono_vcall_trampoline; -#ifdef MONO_ARCH_HAVE_HANDLER_BLOCK_GUARD - case MONO_TRAMPOLINE_HANDLER_BLOCK_GUARD: - return mono_handler_block_guard_trampoline; -#endif default: g_assert_not_reached (); return NULL; @@ -1402,15 +1346,13 @@ mono_trampolines_init (void) mono_trampoline_code [MONO_TRAMPOLINE_GENERIC_VIRTUAL_REMOTING] = create_trampoline_code (MONO_TRAMPOLINE_GENERIC_VIRTUAL_REMOTING); #endif mono_trampoline_code [MONO_TRAMPOLINE_VCALL] = create_trampoline_code (MONO_TRAMPOLINE_VCALL); -#ifdef MONO_ARCH_HAVE_HANDLER_BLOCK_GUARD - mono_trampoline_code [MONO_TRAMPOLINE_HANDLER_BLOCK_GUARD] = create_trampoline_code (MONO_TRAMPOLINE_HANDLER_BLOCK_GUARD); - mono_create_handler_block_trampoline (); -#endif mono_counters_register ("Calls to trampolines", MONO_COUNTER_JIT | MONO_COUNTER_INT, &trampoline_calls); mono_counters_register ("JIT trampolines", MONO_COUNTER_JIT | MONO_COUNTER_INT, &jit_trampolines); mono_counters_register ("Unbox trampolines", MONO_COUNTER_JIT | MONO_COUNTER_INT, &unbox_trampolines); mono_counters_register ("Static rgctx trampolines", MONO_COUNTER_JIT | MONO_COUNTER_INT, &static_rgctx_trampolines); + mono_counters_register ("RGCTX unmanaged lookups", MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &rgctx_unmanaged_lookups); + mono_counters_register ("RGCTX num lazy fetch trampolines", MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &rgctx_num_lazy_fetch_trampolines); } void @@ -1435,10 +1377,17 @@ mono_get_trampoline_code (MonoTrampolineType tramp_type) gpointer mono_create_specific_trampoline (gpointer arg1, MonoTrampolineType tramp_type, MonoDomain *domain, guint32 *code_len) { + gpointer code; + guint32 len; + if (mono_aot_only) - return mono_aot_create_specific_trampoline (mono_defaults.corlib, arg1, tramp_type, domain, code_len); + code = mono_aot_create_specific_trampoline (mono_defaults.corlib, arg1, tramp_type, domain, &len); else - return mono_arch_create_specific_trampoline (arg1, tramp_type, domain, code_len); + code = mono_arch_create_specific_trampoline (arg1, tramp_type, domain, &len); + mono_lldb_save_specific_trampoline_info (arg1, tramp_type, domain, code, len); + if (code_len) + *code_len = len; + return code; } gpointer @@ -1448,7 +1397,16 @@ mono_create_jump_trampoline (MonoDomain *domain, MonoMethod *method, gboolean ad gpointer code; guint32 code_size = 0; - mono_error_init (error); + error_init (error); + +#ifdef ENABLE_INTERPRETER + if (mono_use_interpreter) { + gpointer ret = mono_interp_create_trampoline (domain, method, error); + if (!mono_error_ok (error)) + return NULL; + return ret; + } +#endif code = mono_jit_find_compiled_method_with_jit_info (domain, method, &ji); /* @@ -1506,7 +1464,7 @@ mono_create_jit_trampoline (MonoDomain *domain, MonoMethod *method, MonoError *e { gpointer tramp; - mono_error_init (error); + error_init (error); if (mono_aot_only) { if (mono_llvm_only && method->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED) @@ -1518,8 +1476,7 @@ mono_create_jit_trampoline (MonoDomain *domain, MonoMethod *method, MonoError *e if (code) return code; if (mono_llvm_only) { - if (method->wrapper_type == MONO_WRAPPER_PROXY_ISINST || - method->wrapper_type == MONO_WRAPPER_STFLD_REMOTE) + if (method->wrapper_type == MONO_WRAPPER_PROXY_ISINST) /* These wrappers are not generated */ return method_not_found; /* Methods are lazily initialized on first call, so this can't lead recursion */ @@ -1540,10 +1497,9 @@ mono_create_jit_trampoline (MonoDomain *domain, MonoMethod *method, MonoError *e mono_domain_lock (domain); g_hash_table_insert (domain_jit_info (domain)->jit_trampoline_hash, method, tramp); + UnlockedIncrement (&jit_trampolines); mono_domain_unlock (domain); - jit_trampolines++; - return tramp; } @@ -1563,7 +1519,7 @@ mono_create_jit_trampoline_from_token (MonoImage *image, guint32 token) tramp = mono_create_specific_trampoline (start, MONO_TRAMPOLINE_AOT, domain, NULL); - jit_trampolines++; + UnlockedIncrement (&jit_trampolines); return tramp; } @@ -1601,7 +1557,7 @@ mono_create_delegate_trampoline_info (MonoDomain *domain, MonoClass *klass, Mono tramp_info->impl_nothis = mono_arch_get_delegate_invoke_impl (mono_method_signature (invoke), FALSE); tramp_info->method = method; if (method) { - mono_error_init (&error); + error_init (&error); tramp_info->sig = mono_method_signature_checked (method, &error); tramp_info->need_rgctx_tramp = mono_method_needs_static_rgctx_invoke (method, FALSE); } @@ -1628,7 +1584,7 @@ no_delegate_trampoline (void) gpointer mono_create_delegate_trampoline (MonoDomain *domain, MonoClass *klass) { - if (mono_llvm_only) + if (mono_llvm_only || mono_use_interpreter) return no_delegate_trampoline; return mono_create_delegate_trampoline_info (domain, klass, NULL)->invoke_impl; @@ -1646,10 +1602,7 @@ mono_create_delegate_virtual_trampoline (MonoDomain *domain, MonoClass *klass, M gpointer mono_create_rgctx_lazy_fetch_trampoline (guint32 offset) { - static gboolean inited = FALSE; - static int num_trampolines = 0; MonoTrampInfo *info; - gpointer tramp, ptr; mono_trampolines_lock (); @@ -1677,15 +1630,9 @@ mono_create_rgctx_lazy_fetch_trampoline (guint32 offset) g_hash_table_insert (rgctx_lazy_fetch_trampoline_hash, GUINT_TO_POINTER (offset), ptr); g_assert (offset != -1); g_hash_table_insert (rgctx_lazy_fetch_trampoline_hash_addr, ptr, GUINT_TO_POINTER (offset + 1)); + rgctx_num_lazy_fetch_trampolines ++; mono_trampolines_unlock (); - if (!inited) { - mono_counters_register ("RGCTX num lazy fetch trampolines", - MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &num_trampolines); - inited = TRUE; - } - num_trampolines++; - return ptr; } @@ -1718,8 +1665,7 @@ static const char*tramp_names [MONO_TRAMPOLINE_NUM] = { "delegate", "restore_stack_prot", "generic_virtual_remoting", - "vcall", - "handler_block_guard" + "vcall" }; /*