X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmini%2Fmini-runtime.c;h=6a9f054864b68efb5c4915a9b234c442443ec58e;hb=3d44b341e1b0f59ce7cacfa0e6e8943a445cfb7f;hp=e0ccf6fac248fc03b4272b40a2338e3864d79204;hpb=50fe4789db79ab2254bff768406b4a8dee4cfe54;p=mono.git diff --git a/mono/mini/mini-runtime.c b/mono/mini/mini-runtime.c index e0ccf6fac24..6a9f054864b 100644 --- a/mono/mini/mini-runtime.c +++ b/mono/mini/mini-runtime.c @@ -48,6 +48,7 @@ #include #include #include +#include #include #include #include @@ -80,6 +81,7 @@ #ifdef MONO_ARCH_LLVM_SUPPORTED #ifdef ENABLE_LLVM #include "mini-llvm-cpp.h" +#include "llvm-jit.h" #endif #endif @@ -630,10 +632,15 @@ mono_icall_get_wrapper_full (MonoJitICallInfo* callinfo, gboolean do_compile) wrapper = mono_marshal_get_icall_wrapper (callinfo->sig, name, callinfo->func, check_exc); g_free (name); - if (do_compile) + if (do_compile) { trampoline = mono_compile_method (wrapper); - else - trampoline = mono_create_ftnptr (domain, mono_create_jit_trampoline_in_domain (domain, wrapper)); + } else { + MonoError error; + + trampoline = mono_create_jit_trampoline (domain, wrapper, &error); + mono_error_assert_ok (&error); + trampoline = mono_create_ftnptr (domain, (gpointer)trampoline); + } mono_loader_lock (); if (!callinfo->trampoline) { @@ -711,6 +718,19 @@ register_icall_no_wrapper (gpointer func, const char *name, const char *sigstr) mono_register_jit_icall_full (func, name, sig, TRUE, FALSE, name); } +static void +register_icall_with_wrapper (gpointer func, const char *name, const char *sigstr) +{ + MonoMethodSignature *sig; + + if (sigstr) + sig = mono_create_icall_signature (sigstr); + else + sig = NULL; + + mono_register_jit_icall_full (func, name, sig, FALSE, FALSE, NULL); +} + static void register_dyn_icall (gpointer func, const char *name, const char *sigstr, gboolean save) { @@ -811,7 +831,8 @@ mono_get_lmf_addr (void) * mono_get_lmf_addr, and mono_get_lmf_addr requires the thread to be attached. */ - mono_jit_thread_attach (NULL); + 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; @@ -870,48 +891,119 @@ mono_set_lmf_addr (gpointer lmf_addr) } /* - * mono_jit_thread_attach: + * mono_jit_thread_attach: called by native->managed wrappers + * + * In non-coop mode: + * - @dummy: is NULL + * - @return: the original domain which needs to be restored, or NULL. * - * Called by native->managed wrappers. Returns the original domain which needs to be - * restored, or NULL. + * In coop mode: + * - @dummy: contains the original domain + * - @return: a cookie containing current MonoThreadInfo* if it was in BLOCKING mode, NULL otherwise */ -MonoDomain* -mono_jit_thread_attach (MonoDomain *domain) +gpointer +mono_jit_thread_attach (MonoDomain *domain, gpointer *dummy) { MonoDomain *orig; - if (!domain) - /* - * Happens when called from AOTed code which is only used in the root - * domain. - */ + if (!domain) { + /* Happens when called from AOTed code which is only used in the root domain. */ domain = mono_get_root_domain (); + } + + g_assert (domain); + + if (!mono_threads_is_coop_enabled ()) { + gboolean attached; #ifdef MONO_HAVE_FAST_TLS - if (!MONO_FAST_TLS_GET (mono_lmf_addr)) { - mono_thread_attach (domain); - // #678164 - mono_thread_set_state (mono_thread_internal_current (), ThreadState_Background); - } + attached = MONO_FAST_TLS_GET (mono_lmf_addr) != NULL; #else - if (!mono_native_tls_get_value (mono_jit_tls_id)) { - mono_thread_attach (domain); - mono_thread_set_state (mono_thread_internal_current (), ThreadState_Background); - } + attached = mono_native_tls_get_value (mono_jit_tls_id) != NULL; #endif - orig = mono_domain_get (); - if (orig != domain) - mono_domain_set (domain, TRUE); - return orig != domain ? orig : NULL; + if (!attached) { + mono_thread_attach (domain); + + // #678164 + mono_thread_set_state (mono_thread_internal_current (), ThreadState_Background); + } + + orig = mono_domain_get (); + if (orig != domain) + mono_domain_set (domain, TRUE); + + return orig != domain ? orig : NULL; + } else { + MonoThreadInfo *info; + + info = mono_thread_info_current_unchecked (); + if (!info || !mono_thread_info_is_live (info)) { + /* thread state STARTING -> RUNNING */ + mono_thread_attach (domain); + + // #678164 + mono_thread_set_state (mono_thread_internal_current (), ThreadState_Background); + + *dummy = NULL; + + /* mono_threads_reset_blocking_start returns the current MonoThreadInfo + * if we were in BLOCKING mode */ + return mono_thread_info_current (); + } else { + orig = mono_domain_get (); + + /* orig might be null if we did an attach -> detach -> attach sequence */ + + if (orig != domain) + mono_domain_set (domain, TRUE); + + *dummy = orig; + + /* thread state (BLOCKING|RUNNING) -> RUNNING */ + return mono_threads_reset_blocking_start (dummy); + } + } } -/* Called by native->managed wrappers */ +/* + * mono_jit_thread_detach: called by native->managed wrappers + * + * In non-coop mode: + * - @cookie: the original domain which needs to be restored, or NULL. + * - @dummy: is NULL + * + * In coop mode: + * - @cookie: contains current MonoThreadInfo* if it was in BLOCKING mode, NULL otherwise + * - @dummy: contains the original domain + */ void -mono_jit_set_domain (MonoDomain *domain) +mono_jit_thread_detach (gpointer cookie, gpointer *dummy) { - if (domain) - mono_domain_set (domain, TRUE); + MonoDomain *domain, *orig; + + if (!mono_threads_is_coop_enabled ()) { + orig = (MonoDomain*) cookie; + + if (orig) + mono_domain_set (orig, TRUE); + } else { + orig = (MonoDomain*) *dummy; + + domain = mono_domain_get (); + g_assert (domain); + + /* it won't do anything if cookie is NULL + * thread state RUNNING -> (RUNNING|BLOCKING) */ + mono_threads_reset_blocking_end (cookie, dummy); + + if (orig != domain) { + if (!orig) + mono_domain_unset (); + else + mono_domain_set (orig, TRUE); + } + } } /** @@ -1216,6 +1308,7 @@ mono_patch_info_hash (gconstpointer data) case MONO_PATCH_INFO_METHOD_JUMP: case MONO_PATCH_INFO_IMAGE: case MONO_PATCH_INFO_ICALL_ADDR: + case MONO_PATCH_INFO_ICALL_ADDR_CALL: case MONO_PATCH_INFO_FIELD: case MONO_PATCH_INFO_SFLDA: case MONO_PATCH_INFO_SEQ_POINT_INFO: @@ -1341,11 +1434,13 @@ mono_patch_info_equal (gconstpointer ka, gconstpointer kb) } gpointer -mono_resolve_patch_target (MonoMethod *method, MonoDomain *domain, guint8 *code, MonoJumpInfo *patch_info, gboolean run_cctors) +mono_resolve_patch_target (MonoMethod *method, MonoDomain *domain, guint8 *code, MonoJumpInfo *patch_info, gboolean run_cctors, MonoError *error) { unsigned char *ip = patch_info->ip.i + code; gconstpointer target = NULL; + mono_error_init (error); + switch (patch_info->type) { case MONO_PATCH_INFO_BB: /* @@ -1392,7 +1487,9 @@ mono_resolve_patch_target (MonoMethod *method, MonoDomain *domain, guint8 *code, break; } case MONO_PATCH_INFO_METHOD_JUMP: - target = mono_create_jump_trampoline (domain, patch_info->data.method, FALSE); + target = mono_create_jump_trampoline (domain, patch_info->data.method, FALSE, error); + if (!mono_error_ok (error)) + return NULL; #if defined(__native_client__) && defined(__native_client_codegen__) # if defined(TARGET_AMD64) /* This target is an absolute address, not relative to the */ @@ -1408,13 +1505,17 @@ mono_resolve_patch_target (MonoMethod *method, MonoDomain *domain, guint8 *code, * avoid trampoline, as we not yet know where we will * be installed. */ - target = mono_create_jit_trampoline_in_domain (domain, patch_info->data.method); + target = mono_create_jit_trampoline (domain, patch_info->data.method, error); + if (!mono_error_ok (error)) + return NULL; #else if (patch_info->data.method == method) { target = code; } else { /* get the trampoline to the method from the domain */ - target = mono_create_jit_trampoline_in_domain (domain, patch_info->data.method); + target = mono_create_jit_trampoline (domain, patch_info->data.method, error); + if (!mono_error_ok (error)) + return NULL; } #endif break; @@ -1529,8 +1630,11 @@ mono_resolve_patch_target (MonoMethod *method, MonoDomain *domain, guint8 *code, /* Done by the generated code */ ; else { - if (run_cctors) - mono_runtime_class_init (vtable); + if (run_cctors) { + if (!mono_runtime_class_init_full (vtable, error)) { + return NULL; + } + } } target = (char*)mono_vtable_get_static_field_data (vtable) + patch_info->data.field->offset; break; @@ -1558,29 +1662,27 @@ mono_resolve_patch_target (MonoMethod *method, MonoDomain *domain, guint8 *code, case MONO_PATCH_INFO_TYPE_FROM_HANDLE: { gpointer handle; MonoClass *handle_class; - MonoError error; 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)); + 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)); mono_class_init (handle_class); mono_class_init (mono_class_from_mono_type ((MonoType *)handle)); - target = mono_type_get_object_checked (domain, (MonoType *)handle, &error); - mono_error_raise_exception (&error); - + target = mono_type_get_object_checked (domain, (MonoType *)handle, error); + if (!mono_error_ok (error)) + return NULL; break; } case MONO_PATCH_INFO_LDTOKEN: { gpointer handle; MonoClass *handle_class; - MonoError error; 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)); + 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)); mono_class_init (handle_class); target = handle; @@ -1590,6 +1692,7 @@ mono_resolve_patch_target (MonoMethod *method, MonoDomain *domain, guint8 *code, target = (mono_metadata_blob_heap (patch_info->data.token->image, patch_info->data.token->token) + 2); break; case MONO_PATCH_INFO_ICALL_ADDR: + case MONO_PATCH_INFO_ICALL_ADDR_CALL: /* run_cctors == 0 -> AOT */ if (patch_info->data.method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) { const char *exc_class; @@ -1598,8 +1701,10 @@ mono_resolve_patch_target (MonoMethod *method, MonoDomain *domain, guint8 *code, if (run_cctors) { target = mono_lookup_pinvoke_call (patch_info->data.method, &exc_class, &exc_arg); if (!target) { - if (mono_aot_only) - mono_raise_exception (mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg)); + if (mono_aot_only) { + mono_error_set_exception_instance (error, mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg)); + return NULL; + } g_error ("Unable to resolve pinvoke method '%s' Re-run with MONO_LOG_LEVEL=debug for more information.\n", mono_method_full_name (patch_info->data.method, TRUE)); } } else { @@ -1900,16 +2005,12 @@ mono_jit_compile_method_with_opt (MonoMethod *method, guint32 opt, MonoError *er /* We can't use a domain specific method in another domain */ if (! ((domain != target_domain) && !info->domain_neutral)) { MonoVTable *vtable; - MonoException *tmpEx; mono_jit_stats.methods_lookups++; vtable = mono_class_vtable (domain, method->klass); g_assert (vtable); - tmpEx = mono_runtime_class_init_full (vtable, FALSE); - if (tmpEx) { - mono_error_set_exception_instance (error, tmpEx); + if (!mono_runtime_class_init_full (vtable, error)) return NULL; - } return mono_create_ftnptr (target_domain, info->code_start); } } @@ -1931,7 +2032,8 @@ mono_jit_compile_method_with_opt (MonoMethod *method, guint32 opt, MonoError *er if (!mono_llvm_only) { vtable = mono_class_vtable (domain, method->klass); g_assert (vtable); - mono_runtime_class_init (vtable); + if (!mono_runtime_class_init_full (vtable, error)) + return NULL; } } } @@ -2062,7 +2164,6 @@ mono_jit_free_method (MonoDomain *domain, MonoMethod *method) } g_slist_free (remove); } - mono_domain_unlock (domain); #ifdef MONO_ARCH_HAVE_INVALIDATE_METHOD @@ -2208,7 +2309,9 @@ create_runtime_invoke_info (MonoDomain *domain, MonoMethod *method, gpointer com info->sig = mono_method_signature (method); invoke = mono_marshal_get_runtime_invoke (method, FALSE); - info->vtable = mono_class_vtable_full (domain, method->klass, TRUE); + info->vtable = mono_class_vtable_full (domain, method->klass, error); + if (!mono_error_ok (error)) + return NULL; g_assert (info->vtable); MonoMethodSignature *sig = mono_method_signature (method); @@ -2328,7 +2431,7 @@ create_runtime_invoke_info (MonoDomain *domain, MonoMethod *method, gpointer com } static MonoObject* -mono_llvmonly_runtime_invoke (MonoMethod *method, RuntimeInvokeInfo *info, void *obj, void **params, MonoObject **exc) +mono_llvmonly_runtime_invoke (MonoMethod *method, RuntimeInvokeInfo *info, void *obj, void **params, MonoObject **exc, MonoError *error) { MonoMethodSignature *sig = info->sig; MonoDomain *domain = mono_domain_get (); @@ -2339,6 +2442,8 @@ mono_llvmonly_runtime_invoke (MonoMethod *method, RuntimeInvokeInfo *info, void gpointer *param_refs; int i, pindex; + mono_error_init (error); + g_assert (info->gsharedvt_invoke); /* @@ -2391,6 +2496,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 (sig->ret->type != MONO_TYPE_VOID && info->ret_box_class) return mono_value_box (domain, info->ret_box_class, retval); @@ -2403,11 +2510,13 @@ mono_llvmonly_runtime_invoke (MonoMethod *method, RuntimeInvokeInfo *info, void * @method: the method to invoke * @obj: this pointer * @params: array of parameter values. - * @error: error - * @exc: used to catch exceptions objects + * @exc: Set to the exception raised in the managed method. If NULL, error is thrown instead. + * If coop is enabled, this argument is ignored - all exceptoins are caught and propagated + * through @error + * @error: error or caught exception object */ static MonoObject* -mono_jit_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoError *error, MonoObject **exc) +mono_jit_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObject **exc, MonoError *error) { MonoMethod *invoke, *callee; MonoObject *(*runtime_invoke) (MonoObject *this_obj, void **params, MonoObject **exc, void* compiled_method); @@ -2435,11 +2544,11 @@ mono_jit_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoError * but keep it just in case for moonlight. */ mono_class_setup_vtable (method->klass); - if (method->klass->exception_type != MONO_EXCEPTION_NONE) { + if (mono_class_has_failure (method->klass)) { + MonoException *fail_exc = mono_class_get_exception_for_failure (method->klass); if (exc) - *exc = (MonoObject*)mono_class_get_exception_for_failure (method->klass); - else - mono_raise_exception (mono_class_get_exception_for_failure (method->klass)); + *exc = (MonoObject*)fail_exc; + mono_error_set_exception_instance (error, fail_exc); return NULL; } } @@ -2504,14 +2613,20 @@ mono_jit_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoError * We need this here because mono_marshal_get_runtime_invoke can place * the helper method in System.Object and not the target class. */ - if (exc) { - *exc = (MonoObject*)mono_runtime_class_init_full (info->vtable, FALSE); - if (*exc) - return NULL; - } else { - mono_runtime_class_init (info->vtable); + if (!mono_runtime_class_init_full (info->vtable, error)) { + if (exc) + *exc = (MonoObject*) mono_error_convert_to_exception (error); + return NULL; } + /* If coop is enabled, and the caller didn't ask for the exception to be caught separately, + we always catch the exception and propagate it through the MonoError */ + gboolean catchExcInMonoError = + (exc == NULL) && mono_threads_is_coop_enabled (); + MonoObject *invoke_exc = NULL; + if (catchExcInMonoError) + exc = &invoke_exc; + /* The wrappers expect this to be initialized to NULL */ if (exc) *exc = NULL; @@ -2554,6 +2669,8 @@ mono_jit_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoError mono_arch_start_dyn_call (info->dyn_call_info, (gpointer**)args, retval, buf, sizeof (buf)); dyn_runtime_invoke (buf, exc, info->compiled_method); + if (catchExcInMonoError && *exc != NULL) + mono_error_set_exception_instance (error, (MonoException*) *exc); mono_arch_finish_dyn_call (info->dyn_call_info, buf); @@ -2565,11 +2682,14 @@ mono_jit_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoError #endif if (mono_llvm_only) - return mono_llvmonly_runtime_invoke (method, info, obj, params, exc); + return mono_llvmonly_runtime_invoke (method, info, obj, params, exc, error); runtime_invoke = (MonoObject *(*)(MonoObject *, void **, MonoObject **, void *))info->runtime_invoke; - return runtime_invoke ((MonoObject *)obj, params, exc, info->compiled_method); + MonoObject *result = runtime_invoke ((MonoObject *)obj, params, exc, info->compiled_method); + if (catchExcInMonoError && *exc != NULL) + mono_error_set_exception_instance (error, (MonoException*) *exc); + return result; } typedef struct { @@ -3190,6 +3310,8 @@ mini_parse_debug_option (const char *option) mono_align_small_structs = TRUE; else if (!strcmp (option, "native-debugger-break")) debug_options.native_debugger_break = TRUE; + else if (!strcmp (option, "disable_omit_fp")) + debug_options.disable_omit_fp = TRUE; else return FALSE; @@ -3271,6 +3393,43 @@ register_jit_stats (void) mono_counters_register ("Methods from AOT", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.methods_aot); mono_counters_register ("Methods JITted using mono JIT", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.methods_without_llvm); mono_counters_register ("Methods JITted using LLVM", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.methods_with_llvm); + mono_counters_register ("JIT/method-to-IR (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_method_to_ir); + mono_counters_register ("JIT/liveness_handle_exception_clauses (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_liveness_handle_exception_clauses); + mono_counters_register ("JIT/handle_out_of_line_bblock (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_handle_out_of_line_bblock); + mono_counters_register ("JIT/decompose_long_opts (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_decompose_long_opts); + mono_counters_register ("JIT/local_cprop (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_local_cprop); + mono_counters_register ("JIT/local_emulate_ops (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_local_emulate_ops); + mono_counters_register ("JIT/optimize_branches (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_optimize_branches); + mono_counters_register ("JIT/handle_global_vregs (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_handle_global_vregs); + mono_counters_register ("JIT/local_deadce (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_local_deadce); + mono_counters_register ("JIT/local_alias_analysis (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_local_alias_analysis); + mono_counters_register ("JIT/if_conversion (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_if_conversion); + mono_counters_register ("JIT/bb_ordering (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_bb_ordering); + mono_counters_register ("JIT/compile_dominator_info (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_compile_dominator_info); + mono_counters_register ("JIT/compute_natural_loops (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_compute_natural_loops); + mono_counters_register ("JIT/insert_safepoints (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_insert_safepoints); + mono_counters_register ("JIT/ssa_compute (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_ssa_compute); + mono_counters_register ("JIT/ssa_cprop (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_ssa_cprop); + mono_counters_register ("JIT/ssa_deadce(sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_ssa_deadce); + mono_counters_register ("JIT/perform_abc_removal (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_perform_abc_removal); + mono_counters_register ("JIT/ssa_remove (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_ssa_remove); + mono_counters_register ("JIT/local_cprop2 (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_local_cprop2); + mono_counters_register ("JIT/handle_global_vregs2 (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_handle_global_vregs2); + mono_counters_register ("JIT/local_deadce2 (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_local_deadce2); + mono_counters_register ("JIT/optimize_branches2 (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_optimize_branches2); + mono_counters_register ("JIT/decompose_vtype_opts (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_decompose_vtype_opts); + mono_counters_register ("JIT/decompose_array_access_opts (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_decompose_array_access_opts); + mono_counters_register ("JIT/liveness_handle_exception_clauses2 (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_liveness_handle_exception_clauses2); + mono_counters_register ("JIT/analyze_liveness (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_analyze_liveness); + mono_counters_register ("JIT/linear_scan (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_linear_scan); + mono_counters_register ("JIT/arch_allocate_vars (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_arch_allocate_vars); + mono_counters_register ("JIT/spill_global_vars (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_spill_global_vars); + mono_counters_register ("JIT/local_cprop3 (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_local_cprop3); + mono_counters_register ("JIT/local_deadce3 (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_local_deadce3); + mono_counters_register ("JIT/codegen (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_codegen); + mono_counters_register ("JIT/create_jit_info (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_create_jit_info); + mono_counters_register ("JIT/gc_create_gc_map (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_gc_create_gc_map); + mono_counters_register ("JIT/save_seq_point_info (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_save_seq_point_info); mono_counters_register ("Total time spent JITting (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_time); mono_counters_register ("Basic blocks", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.basic_blocks); mono_counters_register ("Max basic blocks", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.max_basic_blocks); @@ -3361,6 +3520,12 @@ runtime_invoke_info_free (gpointer value) g_free (info); } +static void +free_jit_callee_list (gpointer key, gpointer value, gpointer user_data) +{ + g_slist_free (value); +} + static void mini_free_jit_domain_info (MonoDomain *domain) { @@ -3391,6 +3556,10 @@ mini_free_jit_domain_info (MonoDomain *domain) mono_debugger_agent_free_domain_info (domain); if (info->gsharedvt_arg_tramp_hash) g_hash_table_destroy (info->gsharedvt_arg_tramp_hash); + if (info->llvm_jit_callees) { + g_hash_table_foreach (info->llvm_jit_callees, free_jit_callee_list, NULL); + g_hash_table_destroy (info->llvm_jit_callees); + } #ifdef ENABLE_LLVM mono_llvm_free_domain_info (domain); #endif @@ -3439,6 +3608,7 @@ mini_llvm_init (void) MonoDomain * mini_init (const char *filename, const char *runtime_version) { + MonoError error; MonoDomain *domain; MonoRuntimeCallbacks callbacks; MonoThreadInfoRuntimeCallbacks ticallbacks; @@ -3504,6 +3674,8 @@ mini_init (const char *filename, const char *runtime_version) #define JIT_TRAMPOLINES_WORK #ifdef JIT_TRAMPOLINES_WORK callbacks.compile_method = mono_jit_compile_method; + callbacks.create_jump_trampoline = mono_create_jump_trampoline; + callbacks.create_jit_trampoline = mono_create_jit_trampoline; #endif mono_install_callbacks (&callbacks); @@ -3576,8 +3748,6 @@ mini_init (const char *filename, const char *runtime_version) #ifdef JIT_TRAMPOLINES_WORK mono_install_free_method (mono_jit_free_method); - mono_install_trampoline (mono_create_jit_trampoline); - mono_install_jump_trampoline (mono_create_jump_trampoline); #ifndef DISABLE_REMOTING mono_install_remoting_trampoline (mono_jit_create_remoting_trampoline); #endif @@ -3661,7 +3831,8 @@ mini_init (const char *filename, const char *runtime_version) #define JIT_RUNTIME_WORKS #ifdef JIT_RUNTIME_WORKS mono_install_runtime_cleanup ((MonoDomainFunc)mini_cleanup); - mono_runtime_init (domain, mono_thread_start_cb, mono_thread_attach_cb); + mono_runtime_init_checked (domain, mono_thread_start_cb, mono_thread_attach_cb, &error); + mono_error_assert_ok (&error); mono_thread_attach (domain); #endif @@ -3700,8 +3871,8 @@ register_icalls (void) register_icall (mono_trace_enter_method, "mono_trace_enter_method", NULL, TRUE); register_icall (mono_trace_leave_method, "mono_trace_leave_method", NULL, TRUE); register_icall (mono_get_lmf_addr, "mono_get_lmf_addr", "ptr", TRUE); - register_icall (mono_jit_thread_attach, "mono_jit_thread_attach", "ptr ptr", TRUE); - register_icall (mono_jit_set_domain, "mono_jit_set_domain", "void ptr", TRUE); + register_icall (mono_jit_thread_attach, "mono_jit_thread_attach", "ptr ptr ptr", TRUE); + register_icall (mono_jit_thread_detach, "mono_jit_thread_detach", "void ptr ptr", TRUE); register_icall (mono_domain_get, "mono_domain_get", "ptr", TRUE); register_icall (mono_llvm_throw_exception, "mono_llvm_throw_exception", "void object", TRUE); @@ -3710,7 +3881,7 @@ register_icalls (void) register_icall (mono_llvm_match_exception, "mono_llvm_match_exception", "int ptr int int", TRUE); register_icall (mono_llvm_clear_exception, "mono_llvm_clear_exception", NULL, TRUE); register_icall (mono_llvm_load_exception, "mono_llvm_load_exception", "object", TRUE); - register_icall (mono_llvm_throw_corlib_exception, "mono_llvm_throw_corlib_exception", "void int", FALSE); + register_icall (mono_llvm_throw_corlib_exception, "mono_llvm_throw_corlib_exception", "void int", TRUE); #if defined(ENABLE_LLVM) && !defined(MONO_LLVM_LOADED) register_icall (mono_llvm_set_unhandled_exception_handler, "mono_llvm_set_unhandled_exception_handler", NULL, TRUE); @@ -3877,7 +4048,7 @@ register_icalls (void) register_icall (ves_icall_object_new_specific, "ves_icall_object_new_specific", "object ptr", FALSE); register_icall (mono_array_new, "mono_array_new", "object ptr ptr int32", FALSE); register_icall (ves_icall_array_new_specific, "ves_icall_array_new_specific", "object ptr int32", FALSE); - register_icall (mono_runtime_class_init, "mono_runtime_class_init", "void ptr", FALSE); + register_icall (ves_icall_runtime_class_init, "ves_icall_runtime_class_init", "void ptr", FALSE); register_icall (mono_ldftn, "mono_ldftn", "ptr ptr", FALSE); register_icall (mono_ldvirtfn, "mono_ldvirtfn", "ptr object ptr", FALSE); register_icall (mono_ldvirtfn_gshared, "mono_ldvirtfn_gshared", "ptr object ptr", FALSE); @@ -3919,8 +4090,6 @@ register_icalls (void) register_icall_no_wrapper (mono_resolve_vcall_gsharedvt, "mono_resolve_vcall_gsharedvt", "ptr object int ptr ptr"); register_icall_no_wrapper (mono_resolve_generic_virtual_call, "mono_resolve_generic_virtual_call", "ptr ptr int ptr"); register_icall_no_wrapper (mono_resolve_generic_virtual_iface_call, "mono_resolve_generic_virtual_iface_call", "ptr ptr int ptr"); - register_icall_no_wrapper (mono_llvmonly_set_calling_assembly, "mono_llvmonly_set_calling_assembly", "void ptr"); - register_icall_no_wrapper (mono_llvmonly_get_calling_assembly, "mono_llvmonly_get_calling_assembly", "object"); /* This needs a wrapper so it can have a preserveall cconv */ register_icall (mono_init_vtable_slot, "mono_init_vtable_slot", "ptr ptr int", FALSE); register_icall (mono_llvmonly_init_delegate, "mono_llvmonly_init_delegate", "void object", TRUE); @@ -3928,6 +4097,11 @@ 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_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_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