#include <mono/metadata/threads.h>
#include <mono/metadata/appdomain.h>
#include <mono/metadata/debug-helpers.h>
-#include "mono/metadata/profiler.h"
#include <mono/metadata/profiler-private.h>
#include <mono/metadata/mono-config.h>
#include <mono/metadata/environment.h>
#endif
GList* mono_aot_paths;
-static gboolean mini_enable_profiler = FALSE;
-static char* mini_profiler_options = NULL;
+static GPtrArray *profile_options;
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)
{
mono_debug_count (void)
{
static int count = 0, int_val = 0;
- static gboolean inited;
+ static gboolean inited, has_value = FALSE;
count ++;
if (value) {
int_val = atoi (value);
g_free (value);
+ has_value = TRUE;
}
inited = TRUE;
}
- if (!int_val)
+ if (!has_value)
return TRUE;
if (count == int_val)
MonoDomain *orig;
gboolean attached;
- g_assert (!mono_threads_is_coop_enabled ());
+ g_assert (!mono_threads_is_blocking_transition_enabled ());
if (!domain) {
/* Happens when called from AOTed code which is only used in the root domain. */
void
mono_jit_set_domain (MonoDomain *domain)
{
- g_assert (!mono_threads_is_coop_enabled ());
+ g_assert (!mono_threads_is_blocking_transition_enabled ());
if (domain)
mono_domain_set (domain, TRUE);
case MONO_PATCH_INFO_GC_SAFE_POINT_FLAG:
case MONO_PATCH_INFO_AOT_MODULE:
case MONO_PATCH_INFO_JIT_THREAD_ATTACH:
+ case MONO_PATCH_INFO_PROFILER_ALLOCATION_COUNT:
return (ji->type << 8);
case MONO_PATCH_INFO_CASTCLASS_CACHE:
return (ji->type << 8) | (ji->data.index);
return (ji->type << 8) | (gssize)info->klass | (gssize)info->method;
}
case MONO_PATCH_INFO_JIT_ICALL_ADDR:
+ case MONO_PATCH_INFO_JIT_ICALL_ADDR_NOCALL:
return (ji->type << 8) | g_str_hash (ji->data.target);
case MONO_PATCH_INFO_GSHAREDVT_IN_WRAPPER:
return (ji->type << 8) | mono_signature_hash (ji->data.sig);
case MONO_PATCH_INFO_VIRT_METHOD:
return ji1->data.virt_method->klass == ji2->data.virt_method->klass && ji1->data.virt_method->method == ji2->data.virt_method->method;
case MONO_PATCH_INFO_JIT_ICALL_ADDR:
+ case MONO_PATCH_INFO_JIT_ICALL_ADDR_NOCALL:
if (ji1->data.target == ji2->data.target)
return 1;
return strcmp (ji1->data.target, ji2->data.target) == 0 ? 1 : 0;
target = mono_icall_get_wrapper (mi);
break;
}
- case MONO_PATCH_INFO_JIT_ICALL_ADDR: {
+ case MONO_PATCH_INFO_JIT_ICALL_ADDR:
+ case MONO_PATCH_INFO_JIT_ICALL_ADDR_NOCALL: {
MonoJitICallInfo *mi = mono_find_jit_icall_by_name (patch_info->data.name);
if (!mi) {
g_warning ("unknown MONO_PATCH_INFO_JIT_ICALL_ADDR %s", patch_info->data.name);
target = mi->func;
break;
}
+ case MONO_PATCH_INFO_PROFILER_ALLOCATION_COUNT: {
+ target = (gpointer) &mono_profiler_state.gc_allocation_count;
+ break;
+ }
default:
g_assert_not_reached ();
}
return lookup_method (domain, method);
}
+MonoClass*
+mini_get_class (MonoMethod *method, guint32 token, MonoGenericContext *context)
+{
+ MonoError error;
+ MonoClass *klass;
+
+ if (method->wrapper_type != MONO_WRAPPER_NONE) {
+ klass = (MonoClass *)mono_method_get_wrapper_data (method, token);
+ if (context) {
+ klass = mono_class_inflate_generic_class_checked (klass, context, &error);
+ mono_error_cleanup (&error); /* FIXME don't swallow the error */
+ }
+ } else {
+ klass = mono_class_get_and_inflate_typespec_checked (method->klass->image, token, context, &error);
+ mono_error_cleanup (&error); /* FIXME don't swallow the error */
+ }
+ if (klass)
+ mono_class_init (klass);
+ return klass;
+}
+
#if ENABLE_JIT_MAP
static FILE* perf_map_file;
#ifdef MONO_USE_AOT_COMPILER
if (opt & MONO_OPT_AOT) {
- MonoDomain *domain = mono_domain_get ();
+ MonoDomain *domain = NULL;
+
+ if (mono_aot_mode == MONO_AOT_MODE_INTERP && method->wrapper_type == MONO_WRAPPER_UNKNOWN) {
+ WrapperInfo *info = mono_marshal_get_wrapper_info (method);
+ g_assert (info);
+ if (info->subtype == WRAPPER_SUBTYPE_INTERP_IN)
+ /* AOT'd wrappers for interp must be owned by root domain */
+ domain = mono_get_root_domain ();
+ }
+
+ if (!domain)
+ domain = mono_domain_get ();
mono_class_init (method->klass);
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)) {
+ if (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.
}
void
-mini_profiler_enable_with_options (const char* profile_options)
+mini_add_profiler_argument (const char *desc)
{
- mini_enable_profiler = TRUE;
- mini_profiler_options = g_strdup (profile_options);
+ if (!profile_options)
+ profile_options = g_ptr_array_new ();
+
+ g_ptr_array_add (profile_options, (gpointer) desc);
}
MonoDomain *
mono_w32handle_init ();
#endif
- mono_threads_runtime_init (&ticallbacks);
+ mono_thread_info_runtime_init (&ticallbacks);
if (g_hasenv ("MONO_DEBUG")) {
mini_parse_debug_options ();
mono_set_generic_sharing_supported (TRUE);
#endif
- mono_threads_signals_init ();
+ mono_thread_info_signals_init ();
#ifndef MONO_CROSS_COMPILE
mono_runtime_install_handlers ();
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");
- }
+ mono_profiler_state.context_enable = mini_profiler_context_enable;
+ mono_profiler_state.context_get_this = mini_profiler_context_get_this;
+ mono_profiler_state.context_get_argument = mini_profiler_context_get_argument;
+ mono_profiler_state.context_get_local = mini_profiler_context_get_local;
+ mono_profiler_state.context_get_result = mini_profiler_context_get_result;
+ mono_profiler_state.context_free_buffer = mini_profiler_context_free_buffer;
+
+ if (profile_options)
+ for (guint i = 0; i < profile_options->len; i++)
+ mono_profiler_load ((const char *) g_ptr_array_index (profile_options, i));
+
+ mono_profiler_started ();
if (debug_options.collect_pagefault_stats)
mono_aot_set_make_unreadable (TRUE);
mono_runtime_init_checked (domain, mono_thread_start_cb, mono_thread_attach_cb, &error);
mono_error_assert_ok (&error);
mono_thread_attach (domain);
+ MONO_PROFILER_RAISE (thread_name, (MONO_NATIVE_THREAD_ID_TO_UINT (mono_native_thread_id_get ()), "Main"));
#endif
- if (mono_profiler_get_events () & MONO_PROFILE_STATISTICAL)
+ if (mono_profiler_sampling_enabled ())
mono_runtime_setup_stat_profiler ();
- mono_profiler_runtime_initialized ();
+ MONO_PROFILER_RAISE (runtime_initialized, ());
MONO_VES_INIT_END ();
* the wrapper would call the icall which would call the wrapper and
* so on.
*/
- register_icall (mono_profiler_method_enter, "mono_profiler_method_enter", "void ptr", TRUE);
- register_icall (mono_profiler_method_leave, "mono_profiler_method_leave", "void ptr", TRUE);
+ register_icall (mono_profiler_raise_method_enter, "mono_profiler_raise_method_enter", "void ptr ptr", TRUE);
+ register_icall (mono_profiler_raise_method_leave, "mono_profiler_raise_method_leave", "void ptr ptr", TRUE);
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_dyn_icall (mono_get_rethrow_exception (), "mono_arch_rethrow_exception", "void object", TRUE);
register_dyn_icall (mono_get_throw_corlib_exception (), "mono_arch_throw_corlib_exception", "void ptr", TRUE);
register_icall (mono_thread_get_undeniable_exception, "mono_thread_get_undeniable_exception", "object", FALSE);
+ register_icall (mono_thread_self_abort, "mono_thread_self_abort", "void", 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);
register_icall (mono_gsharedvt_constrained_call, "mono_gsharedvt_constrained_call", "object ptr ptr ptr ptr ptr", FALSE);
register_icall (mono_gsharedvt_value_copy, "mono_gsharedvt_value_copy", "void ptr ptr ptr", TRUE);
- register_icall_no_wrapper (mono_gc_get_range_copy_func (), "mono_gc_range_copy", "void ptr ptr int");
+ //WARNING We do runtime selection here but the string *MUST* be to a fallback function that has same signature and behavior
+ register_icall_no_wrapper (mono_gc_get_range_copy_func (), "mono_gc_wbarrier_range_copy", "void ptr ptr int");
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);
void
mini_cleanup (MonoDomain *domain)
{
- if (mono_profiler_get_events () & MONO_PROFILE_STATISTICAL)
+ if (mono_profiler_sampling_enabled ())
mono_runtime_shutdown_stat_profiler ();
+ MONO_PROFILER_RAISE (runtime_shutdown_begin, ());
+
#ifndef DISABLE_COM
cominterop_release_all_rcws ();
#endif
mono_threadpool_cleanup ();
- mono_profiler_shutdown ();
+ MONO_PROFILER_RAISE (runtime_shutdown_end, ());
+
+ mono_profiler_cleanup ();
+
+ if (profile_options)
+ g_ptr_array_free (profile_options, TRUE);
free_jit_tls_data ((MonoJitTlsData *)mono_tls_get_jit_tls ());