[profiler] Implement call context introspection for enter/leave events.
[mono.git] / mono / mini / mini-runtime.c
index 64528e75c4eede6ff8aec27badb020472dc88502..af88efa4abd17461d5d55f6a8530c57bd737542f 100644 (file)
@@ -39,7 +39,6 @@
 #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>
@@ -131,16 +130,12 @@ int valgrind_register;
 #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)
 {
@@ -574,7 +569,7 @@ G_GNUC_UNUSED gboolean
 mono_debug_count (void)
 {
        static int count = 0, int_val = 0;
-       static gboolean inited;
+       static gboolean inited, has_value = FALSE;
 
        count ++;
 
@@ -583,11 +578,12 @@ mono_debug_count (void)
                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)
@@ -1217,6 +1213,7 @@ mono_patch_info_hash (gconstpointer data)
        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);
@@ -1647,6 +1644,10 @@ mono_resolve_patch_target (MonoMethod *method, MonoDomain *domain, guint8 *code,
                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 ();
        }
@@ -3759,10 +3760,12 @@ mini_llvm_init (void)
 }
 
 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 *
@@ -3935,10 +3938,18 @@ 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");
-       }
+       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);
@@ -4015,12 +4026,13 @@ mini_init (const char *filename, const char *runtime_version)
        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 ();
 
@@ -4051,8 +4063,8 @@ register_icalls (void)
         * 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);
@@ -4079,6 +4091,7 @@ register_icalls (void)
        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);
 
@@ -4348,9 +4361,11 @@ print_jit_stats (void)
 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
@@ -4372,7 +4387,12 @@ mini_cleanup (MonoDomain *domain)
 
        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 ());