X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmetadata%2Fprofiler.c;h=ea779238aa063df21656b422516b854df810bfaf;hb=623e43dcd6f28da4e486ea50e4120925039bae34;hp=52d68739fb235a041e631f0e26451395fc82c6cd;hpb=62dd77c10cf1aa2f702850254217b76816ccc9b0;p=mono.git diff --git a/mono/metadata/profiler.c b/mono/metadata/profiler.c index 52d68739fb2..ea779238aa0 100644 --- a/mono/metadata/profiler.c +++ b/mono/metadata/profiler.c @@ -6,11 +6,12 @@ * * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com) * Copyright 2004-2009 Novell, Inc (http://www.novell.com) + * Copyright 2011 Xamarin Inc (http://www.xamarin.com). */ #include "config.h" #include "mono/metadata/profiler-private.h" -#include "mono/metadata/profiler-default.h" +#include "mono/metadata/assembly.h" #include "mono/metadata/debug-helpers.h" #include "mono/metadata/mono-debug.h" #include "mono/metadata/debug-mono-symfile.h" @@ -91,6 +92,7 @@ struct _ProfilerDesc { MonoProfileGCResizeFunc gc_heap_resize; MonoProfileGCMoveFunc gc_moves; MonoProfileGCHandleFunc gc_handle; + MonoProfileGCRootFunc gc_roots; MonoProfileFunc runtime_initialized_event; @@ -770,6 +772,16 @@ mono_profiler_gc_handle (int op, int type, uintptr_t handle, MonoObject *obj) } } +void +mono_profiler_gc_roots (int num, void **objects, int *root_types, uintptr_t *extra_info) +{ + ProfilerDesc *prof; + for (prof = prof_list; prof; prof = prof->next) { + if ((prof->events & MONO_PROFILE_GC_ROOTS) && prof->gc_roots) + prof->gc_roots (prof->profiler, num, objects, root_types, extra_info); + } +} + void mono_profiler_install_gc (MonoProfileGCFunc callback, MonoProfileGCResizeFunc heap_resize_callback) { @@ -805,19 +817,26 @@ mono_profiler_install_gc_moves (MonoProfileGCMoveFunc callback) /** * mono_profiler_install_gc_roots: * @handle_callback: callback function + * @roots_callback: callback function * * Install the @handle_callback function that the GC will call when GC * handles are created or destroyed. * The callback receives an operation, which is either #MONO_PROFILER_GC_HANDLE_CREATED * or #MONO_PROFILER_GC_HANDLE_DESTROYED, the handle type, the handle value and the * object pointer, if present. + * Install the @roots_callback function that the GC will call when tracing + * the roots for a collection. + * The callback receives the number of elements and three arrays: an array + * of objects, an array of root types and flags and an array of extra info. + * The size of each array is given by the first argument. */ void -mono_profiler_install_gc_roots (MonoProfileGCHandleFunc handle_callback) +mono_profiler_install_gc_roots (MonoProfileGCHandleFunc handle_callback, MonoProfileGCRootFunc roots_callback) { if (!prof_list) return; prof_list->gc_handle = handle_callback; + prof_list->gc_roots = roots_callback; } void @@ -1012,6 +1031,79 @@ mono_profiler_coverage_get (MonoProfiler *prof, MonoMethod *method, MonoProfileC typedef void (*ProfilerInitializer) (const char*); #define INITIALIZER_NAME "mono_profiler_startup" + +static gboolean +load_profiler (MonoDl *pmodule, const char *desc, const char *symbol) +{ + char *err; + ProfilerInitializer func; + + if (!pmodule) + return FALSE; + + if ((err = mono_dl_symbol (pmodule, symbol, (gpointer *) &func))) { + g_free (err); + return FALSE; + } else { + func (desc); + } + return TRUE; +} + +static gboolean +load_embedded_profiler (const char *desc, const char *name) +{ + char *err = NULL; + char *symbol; + MonoDl *pmodule = NULL; + gboolean result; + + pmodule = mono_dl_open (NULL, MONO_DL_LAZY, &err); + if (!pmodule) { + g_warning ("Could not open main executable (%s)", err); + g_free (err); + return FALSE; + } + + symbol = g_strdup_printf (INITIALIZER_NAME "_%s", name); + result = load_profiler (pmodule, desc, symbol); + g_free (symbol); + + return result; +} + +static gboolean +load_profiler_from_directory (const char *directory, const char *libname, const char *desc) +{ + MonoDl *pmodule = NULL; + char* path; + char *err; + void *iter; + + iter = NULL; + err = NULL; + while ((path = mono_dl_build_path (directory, libname, &iter))) { + pmodule = mono_dl_open (path, MONO_DL_LAZY, &err); + g_free (path); + g_free (err); + if (pmodule) + return load_profiler (pmodule, desc, INITIALIZER_NAME); + } + + return FALSE; +} + +static gboolean +load_profiler_from_mono_instalation (const char *libname, const char *desc) +{ + char *err = NULL; + MonoDl *pmodule = mono_dl_open_runtime_lib (libname, MONO_DL_LAZY, &err); + g_free (err); + if (pmodule) + return load_profiler (pmodule, desc, INITIALIZER_NAME); + return FALSE; +} + /** * mono_profiler_load: * @desc: arguments to configure the profiler @@ -1025,58 +1117,66 @@ typedef void (*ProfilerInitializer) (const char*); void mono_profiler_load (const char *desc) { + char *cdesc = NULL; mono_gc_base_init (); -#ifndef DISABLE_PROFILER - if (!desc || (strcmp ("default", desc) == 0) || (strncmp (desc, "default:", 8) == 0)) { - mono_profiler_install_simple (desc); - return; + if (!desc || (strcmp ("default", desc) == 0)) { + desc = "log:report"; } -#else - if (!desc) { - desc = "default"; + /* we keep command-line compat with the old version here */ + if (strncmp (desc, "default:", 8) == 0) { + gchar **args, **ptr; + GString *str = g_string_new ("log:report"); + args = g_strsplit (desc + 8, ",", -1); + for (ptr = args; ptr && *ptr; ptr++) { + const char *arg = *ptr; + + if (!strcmp (arg, "time")) + g_string_append (str, ",calls"); + else if (!strcmp (arg, "alloc")) + g_string_append (str, ",alloc"); + else if (!strcmp (arg, "stat")) + g_string_append (str, ",sample"); + else if (!strcmp (arg, "jit")) + continue; /* accept and do nothing */ + else if (strncmp (arg, "file=", 5) == 0) { + g_string_append_printf (str, ",output=%s", arg + 5); + } else { + fprintf (stderr, "profiler : Unknown argument '%s'.\n", arg); + return; + } + } + desc = cdesc = g_string_free (str, FALSE); } -#endif { - MonoDl *pmodule = NULL; const char* col = strchr (desc, ':'); char* libname; - char* path; char *mname; - char *err; - void *iter; + gboolean res = FALSE; + if (col != NULL) { mname = g_memdup (desc, col - desc + 1); mname [col - desc] = 0; } else { mname = g_strdup (desc); } - libname = g_strdup_printf ("mono-profiler-%s", mname); - iter = NULL; - err = NULL; - while ((path = mono_dl_build_path (NULL, libname, &iter))) { - g_free (err); - pmodule = mono_dl_open (path, MONO_DL_LAZY, &err); - if (pmodule) { - ProfilerInitializer func; - if ((err = mono_dl_symbol (pmodule, INITIALIZER_NAME, (gpointer *)&func))) { - g_warning ("Cannot find initializer function %s in profiler module: %s (%s)", INITIALIZER_NAME, libname, err); - g_free (err); - err = NULL; - } else { - func (desc); - } - break; + if (!load_embedded_profiler (desc, mname)) { + libname = g_strdup_printf ("mono-profiler-%s", mname); + if (!load_profiler_from_directory (NULL, libname, desc)) { + res = FALSE; +#if defined (MONO_ASSEMBLIES) + res = load_profiler_from_directory (mono_assembly_getrootdir (), libname, desc); +#endif + if (!res) + res = load_profiler_from_mono_instalation (libname, desc); + + if (!res) + g_warning ("The '%s' profiler wasn't found in the main executable nor could it be loaded from '%s'.", mname, libname); } - g_free (path); + g_free (libname); } - if (!pmodule) { - g_warning ("Error loading profiler module '%s': %s", libname, err); - g_free (err); - } - g_free (libname); g_free (mname); - g_free (path); } + g_free (cdesc); }