X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmini%2Fmini-runtime.c;h=572048ff5ff8b401b415ab6ba0fe9de8e88cc02f;hb=4c960e1dd530396fdd9400c87729a6ce3101e5c1;hp=5c88487a9180aa66ef565f1ce98acca91d048a54;hpb=3806fa0d2c3bbb7db072702a5af587f6647c870e;p=mono.git diff --git a/mono/mini/mini-runtime.c b/mono/mini/mini-runtime.c index 5c88487a918..572048ff5ff 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" @@ -341,7 +341,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 +1094,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 +1279,7 @@ 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: return (ji->type << 8); case MONO_PATCH_INFO_CASTCLASS_CACHE: return (ji->type << 8) | (ji->data.index); @@ -1441,11 +1499,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 +1533,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 +1719,13 @@ 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; default: g_assert_not_reached (); } @@ -1879,6 +1944,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 @@ -2356,10 +2430,8 @@ mono_llvmonly_runtime_invoke (MonoMethod *method, RuntimeInvokeInfo *info, void runtime_invoke = (MonoObject *(*)(MonoObject *, void **, MonoObject **, void *))info->runtime_invoke; runtime_invoke (NULL, args, exc, info->compiled_method); - if (exc && *exc) { - mono_error_set_exception_instance (error, (MonoException*) *exc); + if (exc && *exc) return NULL; - } if (sig->ret->type != MONO_TYPE_VOID && info->ret_box_class) return mono_value_box_checked (domain, info->ret_box_class, retval, error); @@ -2407,10 +2479,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; } } @@ -2545,12 +2616,17 @@ mono_jit_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObjec } #endif - if (mono_llvm_only) - return mono_llvmonly_runtime_invoke (method, info, obj, params, exc, error); + MonoObject *result; - runtime_invoke = (MonoObject *(*)(MonoObject *, void **, MonoObject **, void *))info->runtime_invoke; + if (mono_llvm_only) { + result = mono_llvmonly_runtime_invoke (method, info, obj, params, exc, error); + if (!is_ok (error)) + return NULL; + } else { + runtime_invoke = (MonoObject *(*)(MonoObject *, void **, MonoObject **, void *))info->runtime_invoke; - MonoObject *result = runtime_invoke ((MonoObject *)obj, params, exc, info->compiled_method); + result = runtime_invoke ((MonoObject *)obj, params, exc, info->compiled_method); + } if (catchExcInMonoError && *exc != NULL) mono_error_set_exception_instance (error, (MonoException*) *exc); return result; @@ -2559,34 +2635,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); @@ -2594,11 +2670,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]); @@ -2606,16 +2682,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) @@ -2625,7 +2701,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) @@ -2637,14 +2713,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; @@ -2657,7 +2733,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; @@ -2665,7 +2741,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. */ @@ -2720,20 +2796,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; @@ -2955,13 +3031,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; @@ -3084,7 +3160,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) @@ -3660,12 +3736,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*/ @@ -3712,6 +3788,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); @@ -3739,6 +3817,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", @@ -3980,6 +4060,7 @@ register_icalls (void) register_icall (mono_get_assembly_object, "mono_get_assembly_object", "object ptr", TRUE); register_icall (mono_get_method_object, "mono_get_method_object", "object ptr", TRUE); register_icall (mono_throw_method_access, "mono_throw_method_access", "void ptr ptr", FALSE); + register_icall_no_wrapper (mono_dummy_jit_icall, "mono_dummy_jit_icall", "void"); register_icall_with_wrapper (mono_monitor_enter, "mono_monitor_enter", "void obj"); register_icall_with_wrapper (mono_monitor_enter_v4, "mono_monitor_enter_v4", "void obj ptr"); @@ -4028,7 +4109,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); @@ -4194,7 +4275,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++; @@ -4249,3 +4330,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 */