X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmini%2Fmini-runtime.c;h=9336b94f2d2bcc0f5935fa09163f6f5bfb9e0098;hb=396ea09438b541f2bb793d2ee326fe7ac32b0f56;hp=5c88487a9180aa66ef565f1ce98acca91d048a54;hpb=9a54e8d2267da69596c015d332e1caaeb6373640;p=mono.git diff --git a/mono/mini/mini-runtime.c b/mono/mini/mini-runtime.c index 5c88487a918..9336b94f2d2 100644 --- a/mono/mini/mini-runtime.c +++ b/mono/mini/mini-runtime.c @@ -65,8 +65,8 @@ #include #include #include -#include -#include +#include +#include #include "mini.h" #include "seq-points.h" @@ -81,6 +81,7 @@ #include "mini-gc.h" #include "mini-llvm.h" #include "debugger-agent.h" +#include "lldb.h" #ifdef MONO_ARCH_LLVM_SUPPORTED #ifdef ENABLE_LLVM @@ -89,15 +90,13 @@ #endif #endif +#ifdef ENABLE_INTERPRETER +#include "interp/interp.h" +#endif + static guint32 default_opt = 0; static gboolean default_opt_set = FALSE; -MonoNativeTlsKey mono_jit_tls_id; - -#ifdef MONO_HAVE_FAST_TLS -MONO_FAST_TLS_DECLARE(mono_jit_tls); -#endif - gboolean mono_compile_aot = FALSE; /* If this is set, no code is generated dynamically, everything is taken from AOT files */ gboolean mono_aot_only = FALSE; @@ -116,6 +115,8 @@ int mini_verbose = 0; */ gboolean mono_use_llvm = FALSE; +gboolean mono_use_interpreter = FALSE; + #define mono_jit_lock() mono_os_mutex_lock (&jit_mutex) #define mono_jit_unlock() mono_os_mutex_unlock (&jit_mutex) static mono_mutex_t jit_mutex; @@ -127,11 +128,18 @@ MonoDebugOptions debug_options; #ifdef VALGRIND_JIT_REGISTER_MAP int valgrind_register; #endif +GList* mono_aot_paths; + +static gboolean mini_enable_profiler = FALSE; +static char* mini_profiler_options = NULL; static GSList *tramp_infos; static void register_icalls (void); +static gboolean mini_profiler_enabled (void) { return mini_enable_profiler; } +static const char* mini_profiler_get_options (void) { return mini_profiler_options; } + gboolean mono_running_on_valgrind (void) { @@ -239,7 +247,7 @@ mono_pmip (void *ip) */ #ifdef __GNUC__ /* Prevent the linker from optimizing this away in embedding setups to help debugging */ - __attribute__((used)) + __attribute__ ((__used__)) #endif void mono_print_method_from_ip (void *ip) @@ -253,6 +261,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 +351,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 */ @@ -356,6 +366,15 @@ void *mono_global_codeman_reserve (int size) } } +/* The callback shouldn't take any locks */ +void +mono_global_codeman_foreach (MonoCodeManagerFunc func, void *user_data) +{ + mono_jit_lock (); + mono_code_manager_foreach (global_codeman, func, user_data); + mono_jit_unlock (); +} + #if defined(__native_client_codegen__) && defined(__native_client__) void mono_nacl_gc() @@ -484,6 +503,7 @@ mono_tramp_info_register (MonoTrampInfo *info, MonoDomain *domain) mono_jit_unlock (); mono_save_trampoline_xdebug_info (info); + mono_lldb_save_trampoline_info (info); /* Only register trampolines that have unwind infos */ if (mono_get_root_domain () && copy->uw_info) @@ -692,63 +712,15 @@ register_dyn_icall (gpointer func, const char *name, const char *sigstr, gboolea mono_register_jit_icall (func, name, sig, save); } -#ifdef MONO_HAVE_FAST_TLS -MONO_FAST_TLS_DECLARE(mono_lmf_addr); -#ifdef MONO_ARCH_ENABLE_MONO_LMF_VAR -/* - * When this is defined, the current lmf is stored in this tls variable instead of in - * jit_tls->lmf. - */ -MONO_FAST_TLS_DECLARE(mono_lmf); -#endif -#endif - -gint32 -mono_get_jit_tls_offset (void) -{ - int offset; - -#ifdef HOST_WIN32 - if (mono_jit_tls_id) - offset = mono_jit_tls_id; - else - /* FIXME: Happens during startup */ - offset = -1; -#else - MONO_THREAD_VAR_OFFSET (mono_jit_tls, offset); -#endif - return offset; -} - -gint32 -mono_get_lmf_tls_offset (void) -{ -#if defined(MONO_ARCH_ENABLE_MONO_LMF_VAR) - int offset; - MONO_THREAD_VAR_OFFSET(mono_lmf,offset); - return offset; -#else - return -1; -#endif -} - -gint32 -mono_get_lmf_addr_tls_offset (void) -{ - int offset; - MONO_THREAD_VAR_OFFSET(mono_lmf_addr,offset); - return offset; -} - MonoLMF * mono_get_lmf (void) { -#if defined(MONO_HAVE_FAST_TLS) && defined(MONO_ARCH_ENABLE_MONO_LMF_VAR) - return (MonoLMF *)MONO_FAST_TLS_GET (mono_lmf); +#if defined(MONO_ARCH_ENABLE_MONO_LMF_VAR) && defined(HAVE_GET_TLS_ADDR) + return (MonoLMF *)mono_tls_get_lmf (); #else MonoJitTlsData *jit_tls; - if ((jit_tls = mono_native_tls_get_value (mono_jit_tls_id))) + if ((jit_tls = mono_tls_get_jit_tls ())) return jit_tls->lmf; /* * We do not assert here because this function can be called from @@ -762,48 +734,23 @@ mono_get_lmf (void) MonoLMF ** mono_get_lmf_addr (void) { -#ifdef MONO_HAVE_FAST_TLS - return (MonoLMF **)MONO_FAST_TLS_GET (mono_lmf_addr); -#else - MonoJitTlsData *jit_tls; - - jit_tls = mono_native_tls_get_value (mono_jit_tls_id); - if (G_LIKELY (jit_tls)) - return &jit_tls->lmf; - - /* - * When resolving the call to mono_jit_thread_attach full-aot will look - * in the plt, which causes a call into the generic trampoline, which in turn - * tries to resolve the lmf_addr creating a cyclic dependency. We cannot - * call mono_jit_thread_attach from the native-to-managed wrapper, without - * mono_get_lmf_addr, and mono_get_lmf_addr requires the thread to be attached. - */ - - mono_thread_attach (mono_get_root_domain ()); - mono_thread_set_state (mono_thread_internal_current (), ThreadState_Background); - - if ((jit_tls = mono_native_tls_get_value (mono_jit_tls_id))) - return &jit_tls->lmf; - - g_assert_not_reached (); - return NULL; -#endif + return (MonoLMF **)mono_tls_get_lmf_addr (); } void mono_set_lmf (MonoLMF *lmf) { -#if defined(MONO_HAVE_FAST_TLS) && defined(MONO_ARCH_ENABLE_MONO_LMF_VAR) - MONO_FAST_TLS_SET (mono_lmf, lmf); -#endif - +#if defined(MONO_ARCH_ENABLE_MONO_LMF_VAR) && defined(HAVE_GET_TLS_ADDR) + mono_tls_set_lmf (lmf); +#else (*mono_get_lmf_addr ()) = lmf; +#endif } MonoJitTlsData* mono_get_jit_tls (void) { - return (MonoJitTlsData *)mono_native_tls_get_value (mono_jit_tls_id); + return (MonoJitTlsData *)mono_tls_get_jit_tls (); } static void @@ -811,11 +758,7 @@ mono_set_jit_tls (MonoJitTlsData *jit_tls) { MonoThreadInfo *info; - mono_native_tls_set_value (mono_jit_tls_id, jit_tls); - -#ifdef MONO_HAVE_FAST_TLS - MONO_FAST_TLS_SET (mono_jit_tls, jit_tls); -#endif + mono_tls_set_jit_tls (jit_tls); /* Save it into MonoThreadInfo so it can be accessed by mono_thread_state_init_from_handle () */ info = mono_thread_info_current (); @@ -828,9 +771,7 @@ mono_set_lmf_addr (gpointer lmf_addr) { MonoThreadInfo *info; -#ifdef MONO_HAVE_FAST_TLS - MONO_FAST_TLS_SET (mono_lmf_addr, lmf_addr); -#endif + mono_tls_set_lmf_addr (lmf_addr); /* Save it into MonoThreadInfo so it can be accessed by mono_thread_state_init_from_handle () */ info = mono_thread_info_current (); @@ -861,11 +802,7 @@ mono_jit_thread_attach (MonoDomain *domain) g_assert (domain); -#ifdef MONO_HAVE_FAST_TLS - attached = MONO_FAST_TLS_GET (mono_lmf_addr) != NULL; -#else - attached = mono_native_tls_get_value (mono_jit_tls_id) != NULL; -#endif + attached = mono_tls_get_jit_tls () != NULL; if (!attached) { mono_thread_attach (domain); @@ -923,7 +860,7 @@ setup_jit_tls_data (gpointer stack_start, gpointer abort_func) MonoJitTlsData *jit_tls; MonoLMF *lmf; - jit_tls = (MonoJitTlsData *)mono_native_tls_get_value (mono_jit_tls_id); + jit_tls = (MonoJitTlsData *)mono_tls_get_jit_tls (); if (jit_tls) return jit_tls; @@ -939,10 +876,18 @@ setup_jit_tls_data (gpointer stack_start, gpointer abort_func) jit_tls->first_lmf = lmf; -#if defined(MONO_HAVE_FAST_TLS) && defined(MONO_ARCH_ENABLE_MONO_LMF_VAR) + /* + * We can have 2 configurations for accessing lmf. + * We can use only the tls_lmf_addr variable, which will store the address of + * jit_tls->lmf, or, if we have MONO_ARCH_ENABLE_MONO_LMF_VAR enabled, we can + * use both tls_lmf_addr and tls_lmf variables (in this case we need to have + * means of getting the address of a tls variable; this can be done always + * when using __thread or, on osx, even when using pthread) + */ +#if defined(MONO_ARCH_ENABLE_MONO_LMF_VAR) && defined(HAVE_GET_TLS_ADDR) /* jit_tls->lmf is unused */ - MONO_FAST_TLS_SET (mono_lmf, lmf); - mono_set_lmf_addr (MONO_FAST_TLS_ADDR (mono_lmf)); + mono_tls_set_lmf (lmf); + mono_set_lmf_addr (mono_tls_get_tls_addr (TLS_KEY_LMF)); #else mono_set_lmf_addr (&jit_tls->lmf); @@ -1041,59 +986,76 @@ mini_thread_cleanup (MonoNativeThreadId tid) free_jit_tls_data (jit_tls); } -int -mini_get_tls_offset (MonoTlsKey key) +MonoJumpInfo * +mono_patch_info_list_prepend (MonoJumpInfo *list, int ip, MonoJumpInfoType type, gconstpointer target) { - int offset; - g_assert (MONO_ARCH_HAVE_TLS_GET); + MonoJumpInfo *ji = g_new0 (MonoJumpInfo, 1); - switch (key) { - case TLS_KEY_THREAD: - offset = mono_thread_get_tls_offset (); - break; - case TLS_KEY_JIT_TLS: - offset = mono_get_jit_tls_offset (); - break; - case TLS_KEY_DOMAIN: - offset = mono_domain_get_tls_offset (); + ji->ip.i = ip; + ji->type = type; + ji->data.target = target; + ji->next = list; + + 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 TLS_KEY_LMF: - offset = mono_get_lmf_tls_offset (); + } + case MONO_PATCH_INFO_METHODCONST: { + char *s = mono_method_full_name (ji->data.method, TRUE); + printf ("[METHODCONST - %s]", s); + g_free (s); break; - case TLS_KEY_LMF_ADDR: - offset = mono_get_lmf_addr_tls_offset (); + } + case MONO_PATCH_INFO_INTERNAL_METHOD: { + printf ("[INTERNAL_METHOD - %s]", ji->data.name); break; + } default: - offset = mono_tls_key_get_offset (key); - g_assert (offset != -1); + printf ("[%s]", patch_info_str [ji->type]); break; } - - return offset; } -static gboolean -mini_tls_key_supported (MonoTlsKey key) -{ - if (!MONO_ARCH_HAVE_TLS_GET) - return FALSE; +#else - return mini_get_tls_offset (key) != -1; +const char* +mono_ji_type_to_string (MonoJumpInfoType type) +{ + return ""; } -MonoJumpInfo * -mono_patch_info_list_prepend (MonoJumpInfo *list, int ip, MonoJumpInfoType type, gconstpointer target) +void +mono_print_ji (const MonoJumpInfo *ji) { - MonoJumpInfo *ji = g_new0 (MonoJumpInfo, 1); - - ji->ip.i = ip; - ji->type = type; - ji->data.target = target; - ji->next = list; - - return ji; } +#endif + /** * mono_patch_info_dup_mp: * @@ -1201,9 +1163,10 @@ mono_patch_info_hash (gconstpointer data) case MONO_PATCH_INFO_SEQ_POINT_INFO: case MONO_PATCH_INFO_METHOD_RGCTX: case MONO_PATCH_INFO_SIGNATURE: - case MONO_PATCH_INFO_TLS_OFFSET: case MONO_PATCH_INFO_METHOD_CODE_SLOT: case MONO_PATCH_INFO_AOT_JIT_INFO: + case MONO_PATCH_INFO_GET_TLS_TRAMP: + case MONO_PATCH_INFO_SET_TLS_TRAMP: return (ji->type << 8) | (gssize)ji->data.target; case MONO_PATCH_INFO_GSHAREDVT_CALL: return (ji->type << 8) | (gssize)ji->data.gsharedvt->method; @@ -1218,10 +1181,10 @@ mono_patch_info_hash (gconstpointer data) case MONO_PATCH_INFO_GC_CARD_TABLE_ADDR: case MONO_PATCH_INFO_GC_NURSERY_START: case MONO_PATCH_INFO_GC_NURSERY_BITS: - case MONO_PATCH_INFO_JIT_TLS_ID: case MONO_PATCH_INFO_GOT_OFFSET: case MONO_PATCH_INFO_GC_SAFE_POINT_FLAG: case MONO_PATCH_INFO_AOT_MODULE: + case MONO_PATCH_INFO_JIT_THREAD_ATTACH: return (ji->type << 8); case MONO_PATCH_INFO_CASTCLASS_CACHE: return (ji->type << 8) | (ji->data.index); @@ -1326,7 +1289,7 @@ mono_resolve_patch_target (MonoMethod *method, MonoDomain *domain, guint8 *code, unsigned char *ip = patch_info->ip.i + code; gconstpointer target = NULL; - mono_error_init (error); + error_init (error); switch (patch_info->type) { case MONO_PATCH_INFO_BB: @@ -1441,11 +1404,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 +1438,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 { @@ -1629,20 +1592,6 @@ mono_resolve_patch_target (MonoMethod *method, MonoDomain *domain, guint8 *code, target = mono_domain_alloc0 (domain, sizeof (gpointer)); break; } - case MONO_PATCH_INFO_JIT_TLS_ID: { - target = (gpointer) (size_t) mono_jit_tls_id; - break; - } - case MONO_PATCH_INFO_TLS_OFFSET: { - int offset; - - offset = mini_get_tls_offset ((MonoTlsKey)GPOINTER_TO_INT (patch_info->data.target)); -#ifdef MONO_ARCH_HAVE_TRANSLATE_TLS_OFFSET - offset = mono_arch_translate_tls_offset (offset); -#endif - target = GINT_TO_POINTER (offset); - break; - } case MONO_PATCH_INFO_OBJC_SELECTOR_REF: { target = NULL; break; @@ -1661,6 +1610,18 @@ 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: + target = mono_tls_get_tls_getter (patch_info->data.index, FALSE); + break; + case MONO_PATCH_INFO_SET_TLS_TRAMP: + target = mono_tls_get_tls_setter (patch_info->data.index, FALSE); + 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 (); } @@ -1809,7 +1770,12 @@ mono_jit_compile_method_with_opt (MonoMethod *method, guint32 opt, MonoError *er MonoJitICallInfo *callinfo = NULL; WrapperInfo *winfo = NULL; - mono_error_init (error); + error_init (error); + +#ifdef ENABLE_INTERPRETER + if (mono_use_interpreter) + return mono_interp_create_method_pointer (method, error); +#endif if (mono_llvm_only) /* Should be handled by the caller */ @@ -1879,6 +1845,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 @@ -1993,6 +1968,7 @@ mono_jit_free_method (MonoDomain *domain, MonoMethod *method) return; mono_debug_remove_method (method, domain); + mono_lldb_remove_method (domain, method, ji); mono_domain_lock (domain); g_hash_table_remove (domain_jit_info (domain)->dynamic_code_hash, method); @@ -2302,7 +2278,7 @@ mono_llvmonly_runtime_invoke (MonoMethod *method, RuntimeInvokeInfo *info, void gpointer *param_refs; int i, pindex; - mono_error_init (error); + error_init (error); g_assert (info->gsharedvt_invoke); @@ -2356,10 +2332,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); @@ -2388,7 +2362,12 @@ mono_jit_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObjec MonoJitInfo *ji = NULL; gboolean callee_gsharedvt = FALSE; - mono_error_init (error); +#ifdef ENABLE_INTERPRETER + if (mono_use_interpreter) + return mono_interp_runtime_invoke (method, obj, params, exc, error); +#endif + + error_init (error); if (obj == NULL && !(method->flags & METHOD_ATTRIBUTE_STATIC) && !method->string_ctor && (method->wrapper_type == 0)) { g_warning ("Ignoring invocation of an instance method on a NULL instance.\n"); @@ -2407,10 +2386,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 +2523,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 +2542,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 +2577,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 +2589,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 +2608,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 +2620,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 +2640,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 +2648,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 +2703,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; @@ -2748,6 +2731,8 @@ MONO_SIG_HANDLER_FUNC (, mono_sigfpe_signal_handler) ji = mono_jit_info_table_find_internal (mono_domain_get (), (char *)mono_arch_ip_from_context (ctx), TRUE, TRUE); + MONO_ENTER_GC_UNSAFE_UNBALANCED; + #if defined(MONO_ARCH_HAVE_IS_INT_OVERFLOW) if (mono_arch_is_int_overflow (ctx, info)) /* @@ -2763,33 +2748,37 @@ MONO_SIG_HANDLER_FUNC (, mono_sigfpe_signal_handler) if (!ji) { if (!mono_do_crash_chaining && mono_chain_signal (MONO_SIG_HANDLER_PARAMS)) - return; + goto exit; - mono_handle_native_sigsegv (SIGSEGV, ctx, info); + mono_handle_native_crash ("SIGFPE", ctx, info); if (mono_do_crash_chaining) { mono_chain_signal (MONO_SIG_HANDLER_PARAMS); - return; + goto exit; } } mono_arch_handle_exception (ctx, exc); + +exit: + MONO_EXIT_GC_UNSAFE_UNBALANCED; } MONO_SIG_HANDLER_FUNC (, mono_sigill_signal_handler) { - MonoException *exc; + MONO_SIG_HANDLER_INFO_TYPE *info = MONO_SIG_HANDLER_GET_INFO (); 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"); - mono_arch_handle_exception (ctx, exc); + mono_handle_native_crash ("SIGILL", ctx, info); + if (mono_do_crash_chaining) { + mono_chain_signal (MONO_SIG_HANDLER_PARAMS); + return; + } - MONO_EXIT_GC_UNSAFE_UNBALANCED; + g_assert_not_reached (); } #if defined(MONO_ARCH_USE_SIGACTION) || defined(HOST_WIN32) @@ -2799,7 +2788,7 @@ MONO_SIG_HANDLER_FUNC (, mono_sigill_signal_handler) MONO_SIG_HANDLER_FUNC (, mono_sigsegv_signal_handler) { MonoJitInfo *ji; - MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_native_tls_get_value (mono_jit_tls_id); + MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_tls_get_jit_tls (); gpointer fault_addr = NULL; #ifdef HAVE_SIG_INFO MONO_SIG_HANDLER_INFO_TYPE *info = MONO_SIG_HANDLER_GET_INFO (); @@ -2831,7 +2820,7 @@ MONO_SIG_HANDLER_FUNC (, mono_sigsegv_signal_handler) if (!mono_domain_get () || !jit_tls) { if (!mono_do_crash_chaining && mono_chain_signal (MONO_SIG_HANDLER_PARAMS)) return; - mono_handle_native_sigsegv (SIGSEGV, ctx, info); + mono_handle_native_crash ("SIGSEGV", ctx, info); if (mono_do_crash_chaining) { mono_chain_signal (MONO_SIG_HANDLER_PARAMS); return; @@ -2878,7 +2867,7 @@ MONO_SIG_HANDLER_FUNC (, mono_sigsegv_signal_handler) if (!mono_do_crash_chaining && mono_chain_signal (MONO_SIG_HANDLER_PARAMS)) return; - mono_handle_native_sigsegv (SIGSEGV, ctx, info); + mono_handle_native_crash ("SIGSEGV", ctx, info); if (mono_do_crash_chaining) { mono_chain_signal (MONO_SIG_HANDLER_PARAMS); @@ -2895,9 +2884,13 @@ MONO_SIG_HANDLER_FUNC (, mono_sigint_signal_handler) MonoException *exc; MONO_SIG_HANDLER_GET_CONTEXT; + MONO_ENTER_GC_UNSAFE_UNBALANCED; + exc = mono_get_exception_execution_engine ("Interrupted (SIGINT)."); mono_arch_handle_exception (ctx, exc); + + MONO_EXIT_GC_UNSAFE_UNBALANCED; } #ifndef DISABLE_REMOTING @@ -2915,7 +2908,7 @@ mono_jit_create_remoting_trampoline (MonoDomain *domain, MonoMethod *method, Mon MonoMethod *nm; guint8 *addr = NULL; - mono_error_init (error); + error_init (error); if ((method->flags & METHOD_ATTRIBUTE_VIRTUAL) && mono_method_signature (method)->generic_param_count) { return mono_create_specific_trampoline (method, MONO_TRAMPOLINE_GENERIC_VIRTUAL_REMOTING, @@ -2955,13 +2948,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; @@ -3055,6 +3048,10 @@ mini_init_delegate (MonoDelegate *del) { if (mono_llvm_only) del->extra_arg = mini_get_delegate_arg (del->method, del->method_ptr); +#ifdef ENABLE_INTERPRETER + if (mono_use_interpreter) + mono_interp_init_delegate (del); +#endif } char* @@ -3084,7 +3081,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) @@ -3150,8 +3147,8 @@ mini_parse_debug_option (const char *option) debug_options.break_on_unverified = TRUE; else if (!strcmp (option, "no-gdb-backtrace")) debug_options.no_gdb_backtrace = TRUE; - else if (!strcmp (option, "suspend-on-sigsegv")) - debug_options.suspend_on_sigsegv = TRUE; + else if (!strcmp (option, "suspend-on-native-crash") || !strcmp (option, "suspend-on-sigsegv")) + debug_options.suspend_on_native_crash = TRUE; else if (!strcmp (option, "suspend-on-exception")) debug_options.suspend_on_exception = TRUE; else if (!strcmp (option, "suspend-on-unhandled")) @@ -3162,6 +3159,8 @@ mini_parse_debug_option (const char *option) debug_options.dyn_runtime_invoke = TRUE; else if (!strcmp (option, "gdb")) debug_options.gdb = TRUE; + else if (!strcmp (option, "lldb")) + debug_options.lldb = TRUE; else if (!strcmp (option, "explicit-null-checks")) debug_options.explicit_null_checks = TRUE; else if (!strcmp (option, "gen-seq-points")) @@ -3180,8 +3179,8 @@ mini_parse_debug_option (const char *option) debug_options.soft_breakpoints = TRUE; else if (!strcmp (option, "check-pinvoke-callconv")) debug_options.check_pinvoke_callconv = TRUE; - else if (!strcmp (option, "arm-use-fallback-tls")) - debug_options.arm_use_fallback_tls = TRUE; + else if (!strcmp (option, "use-fallback-tls")) + debug_options.use_fallback_tls = TRUE; else if (!strcmp (option, "debug-domain-unload")) mono_enable_debug_domain_unload (TRUE); else if (!strcmp (option, "partial-sharing")) @@ -3214,7 +3213,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', '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"); + fprintf (stderr, "Available options: 'handle-sigint', 'keep-delegates', 'reverse-pinvoke-exceptions', 'collect-pagefault-stats', 'break-on-unverified', 'no-gdb-backtrace', 'suspend-on-native-crash', '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', 'use-fallback-tls', 'debug-domain-unload', 'partial-sharing', 'align-small-structs', 'native-debugger-break'\n"); exit (1); } } @@ -3450,6 +3449,22 @@ mini_free_jit_domain_info (MonoDomain *domain) domain->runtime_info = NULL; } +#ifdef MONO_ARCH_HAVE_CODE_CHUNK_TRACKING + +static void +code_manager_chunk_new (void *chunk, int size) +{ + mono_arch_code_chunk_new (chunk, size); +} + +static void +code_manager_chunk_destroy (void *chunk) +{ + mono_arch_code_chunk_destroy (chunk); +} + +#endif + #ifdef ENABLE_LLVM static gboolean llvm_init_inner (void) @@ -3487,6 +3502,13 @@ mini_llvm_init (void) #endif } +void +mini_profiler_enable_with_options (const char* profile_options) +{ + mini_enable_profiler = TRUE; + mini_profiler_options = g_strdup (profile_options); +} + MonoDomain * mini_init (const char *filename, const char *runtime_version) { @@ -3494,6 +3516,7 @@ mini_init (const char *filename, const char *runtime_version) MonoDomain *domain; MonoRuntimeCallbacks callbacks; MonoThreadInfoRuntimeCallbacks ticallbacks; + MonoCodeManagerCallbacks code_manager_callbacks; MONO_VES_INIT_BEGIN (); @@ -3510,6 +3533,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 */ @@ -3524,15 +3549,7 @@ mini_init (const char *filename, const char *runtime_version) mono_set_generic_sharing_vt_supported (TRUE); #endif -#ifdef MONO_HAVE_FAST_TLS - MONO_FAST_TLS_INIT (mono_jit_tls); - MONO_FAST_TLS_INIT (mono_lmf_addr); -#ifdef MONO_ARCH_ENABLE_MONO_LMF_VAR - MONO_FAST_TLS_INIT (mono_lmf); -#endif -#endif - - mono_runtime_set_has_tls_get (MONO_ARCH_HAVE_TLS_GET); + mono_tls_init_runtime_keys (); if (!global_codeman) global_codeman = mono_code_manager_new (); @@ -3544,7 +3561,6 @@ mini_init (const char *filename, const char *runtime_version) callbacks.set_cast_details = mono_set_cast_details; callbacks.debug_log = mono_debugger_agent_debug_log; callbacks.debug_log_is_enabled = mono_debugger_agent_debug_log_is_enabled; - callbacks.tls_key_supported = mini_tls_key_supported; callbacks.get_vtable_trampoline = mini_get_vtable_trampoline; callbacks.get_imt_trampoline = mini_get_imt_trampoline; callbacks.imt_entry_inited = mini_imt_entry_inited; @@ -3558,6 +3574,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); @@ -3568,8 +3589,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 @@ -3581,6 +3600,13 @@ mini_init (const char *filename, const char *runtime_version) mono_code_manager_init (); + memset (&code_manager_callbacks, 0, sizeof (code_manager_callbacks)); +#ifdef MONO_ARCH_HAVE_CODE_CHUNK_TRACKING + code_manager_callbacks.chunk_new = code_manager_chunk_new; + code_manager_callbacks.chunk_destroy = code_manager_chunk_destroy; +#endif + mono_code_manager_install_callbacks (&code_manager_callbacks); + mono_hwcap_init (); mono_arch_cpu_init (); @@ -3589,6 +3615,11 @@ mini_init (const char *filename, const char *runtime_version) mono_unwind_init (); + if (mini_get_debug_options ()->lldb || g_getenv ("MONO_LLDB")) { + mono_lldb_init (""); + mono_dont_free_domains = TRUE; + } + #ifdef XDEBUG_ENABLED if (g_getenv ("MONO_XDEBUG")) { const char *xdebug_opts = g_getenv ("MONO_XDEBUG"); @@ -3616,8 +3647,6 @@ mini_init (const char *filename, const char *runtime_version) mono_trampolines_init (); - mono_native_tls_alloc (&mono_jit_tls_id, NULL); - if (default_opt & MONO_OPT_AOT) mono_aot_init (); @@ -3627,17 +3656,14 @@ mini_init (const char *filename, const char *runtime_version) mono_set_generic_sharing_supported (TRUE); #endif + mono_threads_signals_init (); + #ifndef MONO_CROSS_COMPILE mono_runtime_install_handlers (); #endif 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 @@ -3645,6 +3671,11 @@ mini_init (const char *filename, const char *runtime_version) mono_install_get_class_from_name (mono_aot_get_class_from_name); mono_install_jit_info_find_in_aot (mono_aot_find_jit_info); + if (mini_profiler_enabled ()) { + mono_profiler_load (mini_profiler_get_options ()); + mono_profiler_thread_name (MONO_NATIVE_THREAD_ID_TO_UINT (mono_native_thread_id_get ()), "Main"); + } + if (debug_options.collect_pagefault_stats) mono_aot_set_make_unreadable (TRUE); @@ -3660,12 +3691,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 +3743,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 +3772,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,15 +4015,29 @@ 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"); + register_icall_with_wrapper (mono_monitor_enter_internal, "mono_monitor_enter_internal", "void obj"); + register_icall_with_wrapper (mono_monitor_enter_v4_internal, "mono_monitor_enter_v4_internal", "void obj ptr"); register_icall_no_wrapper (mono_monitor_enter_fast, "mono_monitor_enter_fast", "int obj"); register_icall_no_wrapper (mono_monitor_enter_v4_fast, "mono_monitor_enter_v4_fast", "int obj ptr"); #ifdef TARGET_IOS register_icall (pthread_getspecific, "pthread_getspecific", "ptr ptr", TRUE); #endif + /* Register tls icalls */ + register_icall_no_wrapper (mono_tls_get_thread, "mono_tls_get_thread", "ptr"); + register_icall_no_wrapper (mono_tls_get_jit_tls, "mono_tls_get_jit_tls", "ptr"); + register_icall_no_wrapper (mono_tls_get_domain, "mono_tls_get_domain", "ptr"); + register_icall_no_wrapper (mono_tls_get_lmf, "mono_tls_get_lmf", "ptr"); + register_icall_no_wrapper (mono_tls_get_sgen_thread_info, "mono_tls_get_sgen_thread_info", "ptr"); + register_icall_no_wrapper (mono_tls_get_lmf_addr, "mono_tls_get_lmf_addr", "ptr"); + register_icall_no_wrapper (mono_tls_set_thread, "mono_tls_set_thread", "void ptr"); + register_icall_no_wrapper (mono_tls_set_jit_tls, "mono_tls_set_jit_tls", "void ptr"); + register_icall_no_wrapper (mono_tls_set_domain, "mono_tls_set_domain", "void ptr"); + register_icall_no_wrapper (mono_tls_set_lmf, "mono_tls_set_lmf", "void ptr"); + register_icall_no_wrapper (mono_tls_set_sgen_thread_info, "mono_tls_set_sgen_thread_info", "void ptr"); + register_icall_no_wrapper (mono_tls_set_lmf_addr, "mono_tls_set_lmf_addr", "void ptr"); } MonoJitStats mono_jit_stats = {0}; @@ -4028,7 +4077,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); @@ -4066,9 +4115,11 @@ mini_cleanup (MonoDomain *domain) mono_runtime_cleanup (domain); #endif + mono_threadpool_cleanup (); + mono_profiler_shutdown (); - free_jit_tls_data ((MonoJitTlsData *)mono_native_tls_get_value (mono_jit_tls_id)); + free_jit_tls_data ((MonoJitTlsData *)mono_tls_get_jit_tls ()); mono_icall_cleanup (); @@ -4109,7 +4160,7 @@ mini_cleanup (MonoDomain *domain) if (mono_inject_async_exc_method) mono_method_desc_free (mono_inject_async_exc_method); - mono_native_tls_free (mono_jit_tls_id); + mono_tls_free_keys (); mono_os_mutex_destroy (&jit_mutex); @@ -4194,7 +4245,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 +4300,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 */