X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmini%2Fmini-runtime.c;h=4c504f1e93a50742d736ff7cfafc2a0aa1523324;hb=256e3ee192da85cf7c09a3890c06f7bc448ac817;hp=f4f30c69e6ba02fb18ddc33d4b0c2e580d4d541b;hpb=ef85a70d453f9215f522ec08979363d917b45dd3;p=mono.git diff --git a/mono/mini/mini-runtime.c b/mono/mini/mini-runtime.c index f4f30c69e6b..4c504f1e93a 100644 --- a/mono/mini/mini-runtime.c +++ b/mono/mini/mini-runtime.c @@ -65,7 +65,7 @@ #include #include #include -#include +#include #include #include "mini.h" @@ -253,6 +253,8 @@ mono_print_method_from_ip (void *ip) MonoGenericSharingContext*gsctx; const char *shared_type; + if (!domain) + domain = mono_get_root_domain (); ji = mini_jit_info_table_find_ext (domain, (char *)ip, TRUE, &target_domain); if (ji && ji->is_trampoline) { MonoTrampInfo *tinfo = (MonoTrampInfo *)ji->d.tramp_info; @@ -341,7 +343,7 @@ void *mono_global_codeman_reserve (int size) void *ptr; if (mono_aot_only) - g_error ("Attempting to allocate from the global code manager while running with --aot-only.\n"); + g_error ("Attempting to allocate from the global code manager while running in aot-only mode.\n"); if (!global_codeman) { /* This can happen during startup */ @@ -1094,6 +1096,63 @@ mono_patch_info_list_prepend (MonoJumpInfo *list, int ip, MonoJumpInfoType type, return ji; } +#if !defined(DISABLE_LOGGING) && !defined(DISABLE_JIT) + +static const char* const patch_info_str[] = { +#define PATCH_INFO(a,b) "" #a, +#include "patch-info.h" +#undef PATCH_INFO +}; + +const char* +mono_ji_type_to_string (MonoJumpInfoType type) +{ + return patch_info_str [type]; +} + +void +mono_print_ji (const MonoJumpInfo *ji) +{ + switch (ji->type) { + case MONO_PATCH_INFO_RGCTX_FETCH: { + MonoJumpInfoRgctxEntry *entry = ji->data.rgctx_entry; + + printf ("[RGCTX_FETCH "); + mono_print_ji (entry->data); + printf (" - %s]", mono_rgctx_info_type_to_str (entry->info_type)); + break; + } + case MONO_PATCH_INFO_METHODCONST: { + char *s = mono_method_full_name (ji->data.method, TRUE); + printf ("[METHODCONST - %s]", s); + g_free (s); + break; + } + case MONO_PATCH_INFO_INTERNAL_METHOD: { + printf ("[INTERNAL_METHOD - %s]", ji->data.name); + break; + } + default: + printf ("[%s]", patch_info_str [ji->type]); + break; + } +} + +#else + +const char* +mono_ji_type_to_string (MonoJumpInfoType type) +{ + return ""; +} + +void +mono_print_ji (const MonoJumpInfo *ji) +{ +} + +#endif + /** * mono_patch_info_dup_mp: * @@ -1222,6 +1281,8 @@ mono_patch_info_hash (gconstpointer data) case MONO_PATCH_INFO_GOT_OFFSET: case MONO_PATCH_INFO_GC_SAFE_POINT_FLAG: case MONO_PATCH_INFO_AOT_MODULE: + case MONO_PATCH_INFO_GET_TLS_TRAMP: + case MONO_PATCH_INFO_JIT_THREAD_ATTACH: return (ji->type << 8); case MONO_PATCH_INFO_CASTCLASS_CACHE: return (ji->type << 8) | (ji->data.index); @@ -1441,11 +1502,11 @@ mono_resolve_patch_target (MonoMethod *method, MonoDomain *domain, guint8 *code, break; case MONO_PATCH_INFO_IID: mono_class_init (patch_info->data.klass); - target = GINT_TO_POINTER ((int)patch_info->data.klass->interface_id); + target = GUINT_TO_POINTER (patch_info->data.klass->interface_id); break; case MONO_PATCH_INFO_ADJUSTED_IID: mono_class_init (patch_info->data.klass); - target = GINT_TO_POINTER ((int)(-((patch_info->data.klass->interface_id + 1) * SIZEOF_VOID_P))); + target = GUINT_TO_POINTER ((guint32)(-((patch_info->data.klass->interface_id + 1) * SIZEOF_VOID_P))); break; case MONO_PATCH_INFO_VTABLE: target = mono_class_vtable (domain, patch_info->data.klass); @@ -1475,7 +1536,7 @@ mono_resolve_patch_target (MonoMethod *method, MonoDomain *domain, guint8 *code, } g_assert (vtable); - if (!vtable->initialized && !(vtable->klass->flags & TYPE_ATTRIBUTE_BEFORE_FIELD_INIT) && (method && mono_class_needs_cctor_run (vtable->klass, method))) + if (!vtable->initialized && !mono_class_is_before_field_init (vtable->klass) && (method && mono_class_needs_cctor_run (vtable->klass, method))) /* Done by the generated code */ ; else { @@ -1661,6 +1722,19 @@ mono_resolve_patch_target (MonoMethod *method, MonoDomain *domain, guint8 *code, case MONO_PATCH_INFO_GSHAREDVT_IN_WRAPPER: target = mini_get_gsharedvt_wrapper (TRUE, NULL, patch_info->data.sig, NULL, -1, FALSE); break; + case MONO_PATCH_INFO_GET_TLS_TRAMP: +#ifdef MONO_ARCH_HAVE_GET_TLS_TRAMP + target = mono_arch_get_get_tls_tramp (); +#else + target = NULL; +#endif + break; + case MONO_PATCH_INFO_JIT_THREAD_ATTACH: { + MonoJitICallInfo *mi = mono_find_jit_icall_by_name ("mono_jit_thread_attach"); + g_assert (mi); + target = mi->func; + break; + } default: g_assert_not_reached (); } @@ -1879,6 +1953,15 @@ mono_jit_compile_method_with_opt (MonoMethod *method, guint32 opt, MonoError *er if ((code = mono_aot_get_method_checked (domain, method, error))) { MonoVTable *vtable; + if (mono_runtime_is_critical_method (method) || mono_gc_is_critical_method (method)) { + /* + * The suspend code needs to be able to lookup these methods by ip in async context, + * so preload their jit info. + */ + MonoJitInfo *ji = mono_jit_info_table_find (domain, code); + g_assert (ji); + } + /* * In llvm-only mode, method might be a shared method, so we can't initialize its class. * This is not a problem, since it will be initialized when the method is first @@ -2405,10 +2488,9 @@ mono_jit_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObjec */ mono_class_setup_vtable (method->klass); if (mono_class_has_failure (method->klass)) { - MonoException *fail_exc = mono_class_get_exception_for_failure (method->klass); + mono_error_set_for_class_failure (error, method->klass); if (exc) - *exc = (MonoObject*)fail_exc; - mono_error_set_exception_instance (error, fail_exc); + *exc = (MonoObject*)mono_class_get_exception_for_failure (method->klass); return NULL; } } @@ -2562,34 +2644,34 @@ mono_jit_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObjec typedef struct { MonoVTable *vtable; int slot; -} IMTThunkInfo; +} IMTTrampInfo; -typedef gpointer (*IMTThunkFunc) (gpointer *arg, MonoMethod *imt_method); +typedef gpointer (*IMTTrampFunc) (gpointer *arg, MonoMethod *imt_method); /* - * mini_llvmonly_initial_imt_thunk: + * mini_llvmonly_initial_imt_tramp: * - * This function is called the first time a call is made through an IMT thunk. - * It should have the same signature as the mono_llvmonly_imt_thunk_... functions. + * This function is called the first time a call is made through an IMT trampoline. + * It should have the same signature as the mono_llvmonly_imt_tramp_... functions. */ static gpointer -mini_llvmonly_initial_imt_thunk (gpointer *arg, MonoMethod *imt_method) +mini_llvmonly_initial_imt_tramp (gpointer *arg, MonoMethod *imt_method) { - IMTThunkInfo *info = (IMTThunkInfo*)arg; + IMTTrampInfo *info = (IMTTrampInfo*)arg; gpointer *imt; gpointer *ftndesc; - IMTThunkFunc func; + IMTTrampFunc func; mono_vtable_build_imt_slot (info->vtable, info->slot); imt = (gpointer*)info->vtable; imt -= MONO_IMT_SIZE; - /* Return what the real IMT thunk returns */ + /* Return what the real IMT trampoline returns */ ftndesc = imt [info->slot]; func = ftndesc [0]; - if (func == (IMTThunkFunc)mini_llvmonly_initial_imt_thunk) + if (func == (IMTTrampFunc)mini_llvmonly_initial_imt_tramp) /* Happens when the imt slot contains only a generic virtual method */ return NULL; return func ((gpointer *)ftndesc [1], imt_method); @@ -2597,11 +2679,11 @@ mini_llvmonly_initial_imt_thunk (gpointer *arg, MonoMethod *imt_method) /* This is called indirectly through an imt slot. */ static gpointer -mono_llvmonly_imt_thunk (gpointer *arg, MonoMethod *imt_method) +mono_llvmonly_imt_tramp (gpointer *arg, MonoMethod *imt_method) { int i = 0; - /* arg points to an array created in mono_llvmonly_get_imt_thunk () */ + /* arg points to an array created in mono_llvmonly_get_imt_trampoline () */ while (arg [i] && arg [i] != imt_method) i += 2; g_assert (arg [i]); @@ -2609,16 +2691,16 @@ mono_llvmonly_imt_thunk (gpointer *arg, MonoMethod *imt_method) return arg [i + 1]; } -/* Optimized versions of mono_llvmonly_imt_thunk () for different table sizes */ +/* Optimized versions of mono_llvmonly_imt_trampoline () for different table sizes */ static gpointer -mono_llvmonly_imt_thunk_1 (gpointer *arg, MonoMethod *imt_method) +mono_llvmonly_imt_tramp_1 (gpointer *arg, MonoMethod *imt_method) { //g_assert (arg [0] == imt_method); return arg [1]; } static gpointer -mono_llvmonly_imt_thunk_2 (gpointer *arg, MonoMethod *imt_method) +mono_llvmonly_imt_tramp_2 (gpointer *arg, MonoMethod *imt_method) { //g_assert (arg [0] == imt_method || arg [2] == imt_method); if (arg [0] == imt_method) @@ -2628,7 +2710,7 @@ mono_llvmonly_imt_thunk_2 (gpointer *arg, MonoMethod *imt_method) } static gpointer -mono_llvmonly_imt_thunk_3 (gpointer *arg, MonoMethod *imt_method) +mono_llvmonly_imt_tramp_3 (gpointer *arg, MonoMethod *imt_method) { //g_assert (arg [0] == imt_method || arg [2] == imt_method || arg [4] == imt_method); if (arg [0] == imt_method) @@ -2640,14 +2722,14 @@ mono_llvmonly_imt_thunk_3 (gpointer *arg, MonoMethod *imt_method) } /* - * A version of the imt thunk used for generic virtual/variant iface methods. - * Unlikely a normal imt thunk, its possible that IMT_METHOD is not found + * A version of the imt trampoline used for generic virtual/variant iface methods. + * Unlikely a normal imt trampoline, its possible that IMT_METHOD is not found * in the search table. The original JIT code had a 'fallback' trampoline it could * call, but we can't do that, so we just return NULL, and the compiled code * will handle it. */ static gpointer -mono_llvmonly_fallback_imt_thunk (gpointer *arg, MonoMethod *imt_method) +mono_llvmonly_fallback_imt_tramp (gpointer *arg, MonoMethod *imt_method) { int i = 0; @@ -2660,7 +2742,7 @@ mono_llvmonly_fallback_imt_thunk (gpointer *arg, MonoMethod *imt_method) } static gpointer -mono_llvmonly_get_imt_thunk (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckItem **imt_entries, int count, gpointer fail_tramp) +mono_llvmonly_get_imt_trampoline (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckItem **imt_entries, int count, gpointer fail_tramp) { gpointer *buf; gpointer *res; @@ -2668,7 +2750,7 @@ mono_llvmonly_get_imt_thunk (MonoVTable *vtable, MonoDomain *domain, MonoIMTChec gboolean virtual_generic = FALSE; /* - * Create an array which is passed to the imt thunk functions. + * Create an array which is passed to the imt trampoline functions. * The array contains MonoMethod-function descriptor pairs, terminated by a NULL entry. */ @@ -2723,20 +2805,20 @@ mono_llvmonly_get_imt_thunk (MonoVTable *vtable, MonoDomain *domain, MonoIMTChec res = (void **)mono_domain_alloc (domain, 2 * sizeof (gpointer)); switch (real_count) { case 1: - res [0] = mono_llvmonly_imt_thunk_1; + res [0] = mono_llvmonly_imt_tramp_1; break; case 2: - res [0] = mono_llvmonly_imt_thunk_2; + res [0] = mono_llvmonly_imt_tramp_2; break; case 3: - res [0] = mono_llvmonly_imt_thunk_3; + res [0] = mono_llvmonly_imt_tramp_3; break; default: - res [0] = mono_llvmonly_imt_thunk; + res [0] = mono_llvmonly_imt_tramp; break; } if (virtual_generic || fail_tramp) - res [0] = mono_llvmonly_fallback_imt_thunk; + res [0] = mono_llvmonly_fallback_imt_tramp; res [1] = buf; return res; @@ -2958,13 +3040,13 @@ mini_get_vtable_trampoline (MonoVTable *vt, int slot_index) if (mono_llvm_only) { if (slot_index < 0) { - /* Initialize the IMT thunks to a 'trampoline' so the generated code doesn't have to initialize it */ + /* Initialize the IMT trampoline to a 'trampoline' so the generated code doesn't have to initialize it */ // FIXME: Memory management gpointer *ftndesc = g_malloc (2 * sizeof (gpointer)); - IMTThunkInfo *info = g_new0 (IMTThunkInfo, 1); + IMTTrampInfo *info = g_new0 (IMTTrampInfo, 1); info->vtable = vt; info->slot = index; - ftndesc [0] = mini_llvmonly_initial_imt_thunk; + ftndesc [0] = mini_llvmonly_initial_imt_tramp; ftndesc [1] = info; mono_memory_barrier (); return ftndesc; @@ -3087,7 +3169,7 @@ mono_get_delegate_virtual_invoke_impl (MonoMethodSignature *sig, MonoMethod *met return NULL; is_virtual_generic = method->is_inflated && mono_method_get_declaring_generic_method (method)->is_generic; - is_interface = method->klass->flags & TYPE_ATTRIBUTE_INTERFACE ? TRUE : FALSE; + is_interface = mono_class_is_interface (method->klass); load_imt_reg = is_virtual_generic || is_interface; if (is_interface) @@ -3513,6 +3595,8 @@ mini_init (const char *filename, const char *runtime_version) mono_cross_helpers_run (); + mono_counters_init (); + mini_jit_init (); /* Happens when using the embedding interface */ @@ -3561,6 +3645,11 @@ mini_init (const char *filename, const char *runtime_version) callbacks.compile_method = mono_jit_compile_method; callbacks.create_jump_trampoline = mono_create_jump_trampoline; callbacks.create_jit_trampoline = mono_create_jit_trampoline; + callbacks.create_delegate_trampoline = mono_create_delegate_trampoline; + callbacks.free_method = mono_jit_free_method; +#ifndef DISABLE_REMOTING + callbacks.create_remoting_trampoline = mono_jit_create_remoting_trampoline; +#endif #endif mono_install_callbacks (&callbacks); @@ -3571,8 +3660,6 @@ mini_init (const char *filename, const char *runtime_version) ticallbacks.thread_state_init_from_handle = mono_thread_state_init_from_handle; ticallbacks.thread_state_init = mono_thread_state_init; - mono_counters_init (); - #ifndef HOST_WIN32 mono_w32handle_init (); #endif @@ -3636,11 +3723,6 @@ mini_init (const char *filename, const char *runtime_version) mono_threads_install_cleanup (mini_thread_cleanup); #ifdef JIT_TRAMPOLINES_WORK - mono_install_free_method (mono_jit_free_method); -#ifndef DISABLE_REMOTING - mono_install_remoting_trampoline (mono_jit_create_remoting_trampoline); -#endif - mono_install_delegate_trampoline (mono_create_delegate_trampoline); mono_install_create_domain_hook (mini_create_jit_domain_info); mono_install_free_domain_hook (mini_free_jit_domain_info); #endif @@ -3663,12 +3745,12 @@ mini_init (const char *filename, const char *runtime_version) } if (mono_llvm_only) { - mono_install_imt_thunk_builder (mono_llvmonly_get_imt_thunk); - mono_set_always_build_imt_thunks (TRUE); + mono_install_imt_trampoline_builder (mono_llvmonly_get_imt_trampoline); + mono_set_always_build_imt_trampolines (TRUE); } else if (mono_aot_only) { - mono_install_imt_thunk_builder (mono_aot_get_imt_thunk); + mono_install_imt_trampoline_builder (mono_aot_get_imt_trampoline); } else { - mono_install_imt_thunk_builder (mono_arch_build_imt_thunk); + mono_install_imt_trampoline_builder (mono_arch_build_imt_trampoline); } /*Init arch tls information only after the metadata side is inited to make sure we see dynamic appdomain tls keys*/ @@ -3715,6 +3797,8 @@ mini_init (const char *filename, const char *runtime_version) */ mono_runtime_set_no_exec (TRUE); + mono_mem_account_register_counters (); + #define JIT_RUNTIME_WORKS #ifdef JIT_RUNTIME_WORKS mono_install_runtime_cleanup ((MonoDomainFunc)mini_cleanup); @@ -3742,6 +3826,8 @@ register_icalls (void) ves_icall_get_trace); mono_add_internal_call ("Mono.Runtime::mono_runtime_install_handlers", mono_runtime_install_handlers); + mono_add_internal_call ("Mono.Runtime::mono_runtime_cleanup_handlers", + mono_runtime_cleanup_handlers); #if defined(PLATFORM_ANDROID) || defined(TARGET_ANDROID) mono_add_internal_call ("System.Diagnostics.Debugger::Mono_UnhandledException_internal", @@ -4032,7 +4118,7 @@ print_jit_stats (void) g_print ("IMT colliding slots: %ld\n", mono_stats.imt_slots_with_collisions); g_print ("IMT max collisions: %ld\n", mono_stats.imt_max_collisions_in_slot); g_print ("IMT methods at max col: %ld\n", mono_stats.imt_method_count_when_max_collisions); - g_print ("IMT thunks size: %ld\n", mono_stats.imt_thunks_size); + g_print ("IMT trampolines size: %ld\n", mono_stats.imt_trampolines_size); g_print ("JIT info table inserts: %ld\n", mono_stats.jit_info_table_insert_count); g_print ("JIT info table removes: %ld\n", mono_stats.jit_info_table_remove_count); @@ -4198,7 +4284,7 @@ mono_precompile_assembly (MonoAssembly *ass, void *user_data) } if (method->flags & METHOD_ATTRIBUTE_ABSTRACT) continue; - if (method->is_generic || method->klass->generic_container) + if (method->is_generic || mono_class_is_gtd (method->klass)) continue; count++; @@ -4253,3 +4339,23 @@ mono_personality (void) /* Not used */ g_assert_not_reached (); } + +// Custom handlers currently only implemented by Windows. +#ifndef HOST_WIN32 +gboolean +mono_runtime_install_custom_handlers (const char *handlers) +{ + return FALSE; +} + +void +mono_runtime_install_custom_handlers_usage (void) +{ + fprintf (stdout, + "Custom Handlers:\n" + " --handlers=HANDLERS Enable handler support, HANDLERS is a comma\n" + " separated list of available handlers to install.\n" + "\n" + "No handlers supported on current platform.\n"); +} +#endif /* HOST_WIN32 */