X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmini%2Fmini-runtime.c;h=231b44d65ecda7a9d32996d8283a86df082d2682;hb=a92792300b43b4d77ec5a5bc6542efa06ed4867d;hp=928716d96a01f2a5cff12ed29df867b5932fd031;hpb=60bee252111dab7264aedf8380a26fedd6036a63;p=mono.git diff --git a/mono/mini/mini-runtime.c b/mono/mini/mini-runtime.c index 928716d96a0..231b44d65ec 100644 --- a/mono/mini/mini-runtime.c +++ b/mono/mini/mini-runtime.c @@ -65,6 +65,7 @@ #include #include #include +#include #include #include "mini.h" @@ -1514,7 +1515,7 @@ mono_resolve_patch_target (MonoMethod *method, MonoDomain *domain, guint8 *code, handle = mono_ldtoken_checked (patch_info->data.token->image, patch_info->data.token->token, &handle_class, patch_info->data.token->has_context ? &patch_info->data.token->context : NULL, error); if (!mono_error_ok (error)) - g_error ("Could not patch ldtoken due to %s", mono_error_get_message (error)); + return NULL; mono_class_init (handle_class); mono_class_init (mono_class_from_mono_type ((MonoType *)handle)); @@ -1810,6 +1811,10 @@ mono_jit_compile_method_with_opt (MonoMethod *method, guint32 opt, MonoError *er mono_error_init (error); + if (mono_llvm_only) + /* Should be handled by the caller */ + g_assert (!(method->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED)); + /* * ICALL wrappers are handled specially, since there is only one copy of them * shared by all appdomains. @@ -2351,10 +2356,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); @@ -2402,10 +2405,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; } } @@ -2540,12 +2542,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; @@ -2554,34 +2561,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); @@ -2589,11 +2596,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]); @@ -2601,16 +2608,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) @@ -2620,7 +2627,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) @@ -2632,14 +2639,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; @@ -2652,7 +2659,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; @@ -2660,7 +2667,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. */ @@ -2715,20 +2722,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; @@ -2775,6 +2782,9 @@ MONO_SIG_HANDLER_FUNC (, mono_sigill_signal_handler) MonoException *exc; MONO_SIG_HANDLER_GET_CONTEXT; + if (mono_runtime_get_no_exec ()) + exit (1); + MONO_ENTER_GC_UNSAFE_UNBALANCED; exc = mono_get_exception_execution_engine ("SIGILL"); @@ -2947,13 +2957,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; @@ -3049,6 +3059,17 @@ mini_init_delegate (MonoDelegate *del) del->extra_arg = mini_get_delegate_arg (del->method, del->method_ptr); } +char* +mono_get_delegate_virtual_invoke_impl_name (gboolean load_imt_reg, int offset) +{ + int abs_offset; + + abs_offset = offset; + if (abs_offset < 0) + abs_offset = - abs_offset; + return g_strdup_printf ("delegate_virtual_invoke%s_%s%d", load_imt_reg ? "_imt" : "", offset < 0 ? "m_" : "", abs_offset / SIZEOF_VOID_P); +} + gpointer mono_get_delegate_virtual_invoke_impl (MonoMethodSignature *sig, MonoMethod *method) { @@ -3100,12 +3121,7 @@ mono_get_delegate_virtual_invoke_impl (MonoMethodSignature *sig, MonoMethod *met /* FIXME Support more cases */ if (mono_aot_only) { - char tramp_name [256]; - const char *imt = load_imt_reg ? "_imt" : ""; - int ind = (load_imt_reg ? (-offset) : offset) / SIZEOF_VOID_P; - - sprintf (tramp_name, "delegate_virtual_invoke%s_%d", imt, ind); - cache [idx] = (guint8 *)mono_aot_get_trampoline (tramp_name); + cache [idx] = (guint8 *)mono_aot_get_trampoline (mono_get_delegate_virtual_invoke_impl_name (load_imt_reg, offset)); g_assert (cache [idx]); } else { cache [idx] = (guint8 *)mono_arch_get_delegate_virtual_invoke_impl (sig, method, offset, load_imt_reg); @@ -3153,7 +3169,9 @@ mini_parse_debug_option (const char *option) else if (!strcmp (option, "gen-seq-points")) debug_options.gen_sdb_seq_points = TRUE; else if (!strcmp (option, "gen-compact-seq-points")) - debug_options.gen_seq_points_compact_data = TRUE; + fprintf (stderr, "Mono Warning: option gen-compact-seq-points is deprecated.\n"); + else if (!strcmp (option, "no-compact-seq-points")) + debug_options.no_seq_points_compact_data = TRUE; else if (!strcmp (option, "single-imm-size")) debug_options.single_imm_size = TRUE; else if (!strcmp (option, "init-stacks")) @@ -3198,7 +3216,7 @@ mini_parse_debug_options (void) if (!mini_parse_debug_option (arg)) { fprintf (stderr, "Invalid option for the MONO_DEBUG env variable: %s\n", arg); - fprintf (stderr, "Available options: 'handle-sigint', 'keep-delegates', 'reverse-pinvoke-exceptions', 'collect-pagefault-stats', 'break-on-unverified', 'no-gdb-backtrace', 'suspend-on-sigsegv', 'suspend-on-exception', 'suspend-on-unhandled', 'dont-free-domains', 'dyn-runtime-invoke', 'gdb', 'explicit-null-checks', 'gen-seq-points', 'gen-compact-seq-points', 'single-imm-size', 'init-stacks', 'casts', 'soft-breakpoints', 'check-pinvoke-callconv', 'arm-use-fallback-tls', 'debug-domain-unload', 'partial-sharing', 'align-small-structs', 'native-debugger-break'\n"); + fprintf (stderr, "Available options: 'handle-sigint', 'keep-delegates', 'reverse-pinvoke-exceptions', 'collect-pagefault-stats', 'break-on-unverified', 'no-gdb-backtrace', 'suspend-on-sigsegv', 'suspend-on-exception', 'suspend-on-unhandled', 'dont-free-domains', 'dyn-runtime-invoke', 'gdb', 'explicit-null-checks', 'gen-seq-points', 'no-compact-seq-points', 'single-imm-size', 'init-stacks', 'casts', 'soft-breakpoints', 'check-pinvoke-callconv', 'arm-use-fallback-tls', 'debug-domain-unload', 'partial-sharing', 'align-small-structs', 'native-debugger-break'\n"); exit (1); } } @@ -3313,6 +3331,7 @@ register_jit_stats (void) mono_counters_register ("Aliases eliminated", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.alias_removed); mono_counters_register ("Aliased loads eliminated", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.loads_eliminated); mono_counters_register ("Aliased stores eliminated", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.stores_eliminated); + mono_counters_register ("Optimized immediate divisions", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.optimized_divisions); } static void runtime_invoke_info_free (gpointer value); @@ -3553,6 +3572,10 @@ mini_init (const char *filename, const char *runtime_version) mono_counters_init (); +#ifndef HOST_WIN32 + mono_w32handle_init (); +#endif + mono_threads_runtime_init (&ticallbacks); if (g_getenv ("MONO_DEBUG") != NULL) @@ -3639,12 +3662,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*/ @@ -3680,9 +3703,7 @@ mini_init (const char *filename, const char *runtime_version) mono_simd_intrinsics_init (); #endif -#if MONO_SUPPORT_TASKLETS mono_tasklets_init (); -#endif register_trampolines (domain); @@ -3693,6 +3714,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); @@ -3720,6 +3743,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", @@ -3763,9 +3788,6 @@ register_icalls (void) register_icall (mono_thread_get_undeniable_exception, "mono_thread_get_undeniable_exception", "object", FALSE); register_icall (mono_thread_interruption_checkpoint, "mono_thread_interruption_checkpoint", "object", FALSE); register_icall (mono_thread_force_interruption_checkpoint_noraise, "mono_thread_force_interruption_checkpoint_noraise", "object", FALSE); -#ifndef DISABLE_REMOTING - register_icall (mono_store_remote_field_new_icall, "mono_store_remote_field_new_icall", "void object ptr ptr object", FALSE); -#endif #if defined(__native_client__) || defined(__native_client_codegen__) register_icall (mono_nacl_gc, "mono_nacl_gc", "void", FALSE); @@ -3943,8 +3965,8 @@ register_icalls (void) register_icall (mono_object_castclass_with_cache, "mono_object_castclass_with_cache", "object object ptr ptr", FALSE); register_icall (mono_object_isinst_with_cache, "mono_object_isinst_with_cache", "object object ptr ptr", FALSE); register_icall (mono_generic_class_init, "mono_generic_class_init", "void ptr", FALSE); - register_icall (mono_fill_class_rgctx, "mono_class_fill_rgctx", "ptr ptr int", FALSE); - register_icall (mono_fill_method_rgctx, "mono_method_fill_rgctx", "ptr ptr int", FALSE); + register_icall (mono_fill_class_rgctx, "mono_fill_class_rgctx", "ptr ptr int", FALSE); + register_icall (mono_fill_method_rgctx, "mono_fill_method_rgctx", "ptr ptr int", FALSE); register_icall (mono_debugger_agent_user_break, "mono_debugger_agent_user_break", "void", FALSE); @@ -3964,6 +3986,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"); @@ -4012,7 +4035,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); @@ -4098,6 +4121,10 @@ mini_cleanup (MonoDomain *domain) mono_os_mutex_destroy (&jit_mutex); mono_code_manager_cleanup (); + +#ifndef HOST_WIN32 + mono_w32handle_cleanup (); +#endif } void