[runtime] New profiler API.
authorAlex Rønne Petersen <alexrp@xamarin.com>
Thu, 22 Jun 2017 15:15:35 +0000 (17:15 +0200)
committerAlex Rønne Petersen <alexrp@xamarin.com>
Thu, 6 Jul 2017 09:32:29 +0000 (11:32 +0200)
* Profiler callbacks can now be changed and disabled at any point.
* API users no longer have to set event flags. The API instead uses a counter
  internally for each type of callback.
* Filter functions for enter/leave instrumentation can be installed, and they
  can choose whether to instrument the prologue, epilogue, or both.
* Managed allocators can now be instrumented for allocation profiling.
* A profiler must now declare that it wishes to use allocation profiling and/or
  sampling in its init function.
* Sampling parameters can now be changed at any point, and the sampling thread
  can be put into an idle mode when no sampling is needed.
* Only one profiler can have control over the sampling parameters. Whichever
  profiler enables sampling first gets control.
* Adding new events is now very easy: One line in profiler-events.h and one
  line wherever the event should be raised.
* Lifted the restriction that enter/leave instrumentation would cause an abort
  in full AOT mode.
* Support for call chain sampling has been removed.
* Support for the old, platform-specific code coverage mode has been removed.
* The new profiler module entry point is mono_profiler_init. If a module has
  a mono_profiler_startup symbol (the old entry point), a warning will be
  printed and the module won't be loaded.
* Updated the profiler test suite to work with instrumented managed allocators.

70 files changed:
mcs/class/Mono.Profiler.Log/Mono.Profiler.Log/LogEnums.cs
mono/cil/cil-opcodes.xml
mono/cil/opcode.def
mono/metadata/Makefile.am
mono/metadata/appdomain.c
mono/metadata/assembly.c
mono/metadata/boehm-gc.c
mono/metadata/class.c
mono/metadata/domain.c
mono/metadata/dynamic-image.c
mono/metadata/gc-internals.h
mono/metadata/gc.c
mono/metadata/image.c
mono/metadata/loader.c
mono/metadata/monitor.c
mono/metadata/mono-gc.h
mono/metadata/object.c
mono/metadata/profiler-events.h [new file with mode: 0644]
mono/metadata/profiler-private.h
mono/metadata/profiler.c
mono/metadata/profiler.h
mono/metadata/sgen-client-mono.h
mono/metadata/sgen-mono.c
mono/metadata/sgen-stw.c
mono/metadata/sre.c
mono/metadata/threads.c
mono/mini/aot-compiler.c
mono/mini/aot-runtime.c
mono/mini/debugger-agent.c
mono/mini/exceptions-amd64.c
mono/mini/exceptions-arm64.c
mono/mini/exceptions-mips.c
mono/mini/exceptions-ppc.c
mono/mini/exceptions-s390x.c
mono/mini/exceptions-x86.c
mono/mini/interp/interp.c
mono/mini/interp/transform.c
mono/mini/method-to-ir.c
mono/mini/mini-amd64.c
mono/mini/mini-arm.c
mono/mini/mini-exceptions.c
mono/mini/mini-mips.c
mono/mini/mini-posix.c
mono/mini/mini-ppc.c
mono/mini/mini-runtime.c
mono/mini/mini-s390x.c
mono/mini/mini-sparc.c
mono/mini/mini-windows.c
mono/mini/mini-x86.c
mono/mini/mini.c
mono/mini/mini.h
mono/mini/patch-info.h
mono/mini/tramp-amd64-gsharedvt.c
mono/mini/tramp-amd64.c
mono/mini/tramp-arm.c
mono/mini/tramp-arm64.c
mono/mini/tramp-s390x.c
mono/mini/tramp-x86.c
mono/profiler/aot.c
mono/profiler/iomap.c
mono/profiler/log-args.c
mono/profiler/log.c
mono/profiler/log.h
mono/profiler/mprof-report.c
mono/profiler/ptestrunner.pl
mono/profiler/vtune.c
mono/utils/mono-codeman.c
mono/utils/mono-io-portability.c
samples/profiler/sample.c
samples/size/size.c

index 52385963af286574df6f2ed7651242abfb0c03c0..f9a125b5d16a8d011774c600d22bab15ed8ae0fb 100644 (file)
@@ -148,7 +148,7 @@ namespace Mono.Profiler.Log {
                BranchMisses = 6,
        }
 
-       // mono/metadata/profiler.h : MonoProfileGCRootType
+       // mono/metadata/profiler.h : MonoProfilerGCRootType
        [Flags]
        public enum LogHeapRootAttributes {
                Pinning = 1 << 8,
@@ -164,7 +164,7 @@ namespace Mono.Profiler.Log {
                TypeMask = 0xff,
        }
 
-       // mono/metadata/profiler.h : MonoProfilerMonitorEvent
+       // mono/profiler/log.h : MonoProfilerMonitorEvent
        public enum LogMonitorEvent {
                Contention = 1,
                Done = 2,
@@ -179,7 +179,7 @@ namespace Mono.Profiler.Log {
                Fault = 4,
        }
 
-       // mono/metadata/profiler.h : MonoGCEvent
+       // mono/metadata/profiler.h : MonoProfilerGCEvent
        public enum LogGCEvent {
                Begin = 0,
                MarkBegin = 1,
@@ -195,7 +195,7 @@ namespace Mono.Profiler.Log {
                PostStartWorldUnlocked = 11,
        }
 
-       // mono/sgen/gc-internal-agnostic.h : GCHandleType
+       // mono/metadata/mono-gc.h : MonoGCHandleType
        public enum LogGCHandleType {
                Weak = 0,
                WeakTrackResurrection = 1,
index cafb55618910fee90f6ffbdb45ae51ad053cea12..886cf63af6fb3352efe2a2af72bd96c504d60544 100644 (file)
 <opcode name="mono_atomic_store_i4" input="PopI+PopI" output="Push0" args="InlineI" o1="0xF0" o2="0x1A" flow="next" />
 <opcode name="mono_get_last_error" input="Pop0" output="PushI" args="InlineNone" o1="0xF0" o2="0x1B" flow="next" />
 <opcode name="mono_get_rgctx_arg" input="Pop0" output="PushI" args="InlineNone" o1="0xF0" o2="0x1C" flow="next" />
+<opcode name="mono_ldptr_profiler_allocation_count" input="Pop0" output="PushI" args="InlineNone" o1="0xF0" o2="0x1D" flow="next" />
 </opdesc>
index 91e8924febc18e66763e669964aea5d8352ab2c5..7cead418fdfe55b7861f81383de6ae11c56ae617 100644 (file)
@@ -321,6 +321,7 @@ OPDEF(CEE_MONO_LDDOMAIN, "mono_lddomain", Pop0, PushI, InlineNone, X, 2, 0xF0, 0
 OPDEF(CEE_MONO_ATOMIC_STORE_I4, "mono_atomic_store_i4", PopI+PopI, Push0, InlineI, X, 2, 0xF0, 0x1A, NEXT)
 OPDEF(CEE_MONO_GET_LAST_ERROR, "mono_get_last_error", Pop0, PushI, InlineNone, X, 2, 0xF0, 0x1B, NEXT)
 OPDEF(CEE_MONO_GET_RGCTX_ARG, "mono_get_rgctx_arg", Pop0, PushI, InlineNone, X, 2, 0xF0, 0x1C, NEXT)
+OPDEF(CEE_MONO_LDPTR_PROFILER_ALLOCATION_COUNT, "mono_ldptr_profiler_allocation_count", Pop0, PushI, InlineNone, X, 2, 0xF0, 0x1D, NEXT)
 #ifndef OPALIAS
 #define _MONO_CIL_OPALIAS_DEFINED_
 #define OPALIAS(a,s,r)
index 7f4a2bbdc6677dd6f4bb7322e4b2c4d1ea84e13c..3243c12e47ba646cb3d490fea47374b23488c168 100644 (file)
@@ -220,6 +220,7 @@ common_sources = \
        w32process.h            \
        w32process-internals.h          \
        profiler.c              \
+       profiler-events.h       \
        profiler-private.h      \
        rand.h                  \
        rand.c                  \
index 821fd7d8e53501d145f22719113eaaa379b06dcd..19c44470ec7c0a033450ff1dd769b223571cdb84 100644 (file)
@@ -636,7 +636,7 @@ mono_domain_create_appdomain_internal (char *friendly_name, MonoAppDomainSetupHa
        data->domain = MONO_HANDLE_RAW (ad);
        data->friendly_name = g_strdup (friendly_name);
 
-       mono_profiler_appdomain_name (data, data->friendly_name);
+       MONO_PROFILER_RAISE (domain_name, (data, data->friendly_name));
 
        MonoStringHandle app_base = MONO_HANDLE_NEW_GET (MonoString, setup, application_base);
        if (MONO_HANDLE_IS_NULL (app_base)) {
index 3ecd1478ba21be51523deb0542c172ad4798c6d4..e5b1cb0c57ad730db7c323e1ff9741ec7e3e17ac 100644 (file)
@@ -2222,7 +2222,7 @@ mono_assembly_load_from_predicate (MonoImage *image, const char *fname,
        ass->ref_only = refonly;
        ass->image = image;
 
-       mono_profiler_assembly_event (ass, MONO_PROFILE_START_LOAD);
+       MONO_PROFILER_RAISE (assembly_loading, (ass));
 
        mono_assembly_fill_assembly_name (image, &ass->aname);
 
@@ -2314,7 +2314,7 @@ mono_assembly_load_from_predicate (MonoImage *image, const char *fname,
 
        mono_assembly_invoke_load_hook (ass);
 
-       mono_profiler_assembly_loaded (ass, MONO_PROFILE_OK);
+       MONO_PROFILER_RAISE (assembly_loaded, (ass));
        
        return ass;
 }
@@ -3804,7 +3804,7 @@ mono_assembly_close_except_image_pools (MonoAssembly *assembly)
        if (InterlockedDecrement (&assembly->ref_count) > 0)
                return FALSE;
 
-       mono_profiler_assembly_event (assembly, MONO_PROFILE_START_UNLOAD);
+       MONO_PROFILER_RAISE (assembly_unloading, (assembly));
 
        mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_ASSEMBLY, "Unloading assembly %s [%p].", assembly->aname.name, assembly);
 
@@ -3827,7 +3827,7 @@ mono_assembly_close_except_image_pools (MonoAssembly *assembly)
        g_slist_free (assembly->friend_assembly_names);
        g_free (assembly->basedir);
 
-       mono_profiler_assembly_event (assembly, MONO_PROFILE_END_UNLOAD);
+       MONO_PROFILER_RAISE (assembly_unloaded, (assembly));
 
        return TRUE;
 }
index 50ff079d1e2808a8829b893adfca1d992d765ce8..9439ebfab061919bccb7aea1c3454c4b4c39569a 100644 (file)
@@ -428,7 +428,7 @@ static gint64 gc_start_time;
 static void
 on_gc_notification (GC_EventType event)
 {
-       MonoGCEvent e = (MonoGCEvent)event;
+       MonoProfilerGCEvent e = (MonoProfilerGCEvent)event;
 
        switch (e) {
        case MONO_GC_EVENT_PRE_STOP_WORLD:
@@ -483,16 +483,16 @@ on_gc_notification (GC_EventType event)
                break;
        }
 
-       mono_profiler_gc_event (e, 0);
+       MONO_PROFILER_RAISE (gc_event, (e, 0));
 
        switch (e) {
        case MONO_GC_EVENT_PRE_STOP_WORLD:
                mono_thread_info_suspend_lock ();
-               mono_profiler_gc_event (MONO_GC_EVENT_PRE_STOP_WORLD_LOCKED, 0);
+               MONO_PROFILER_RAISE (gc_event, (MONO_GC_EVENT_PRE_STOP_WORLD_LOCKED, 0));
                break;
        case MONO_GC_EVENT_POST_START_WORLD:
                mono_thread_info_suspend_unlock ();
-               mono_profiler_gc_event (MONO_GC_EVENT_POST_START_WORLD_UNLOCKED, 0);
+               MONO_PROFILER_RAISE (gc_event, (MONO_GC_EVENT_POST_START_WORLD_UNLOCKED, 0));
                break;
        default:
                break;
@@ -511,7 +511,8 @@ on_gc_heap_resize (size_t new_size)
                mono_perfcounters->gc_gen0size = heap_size;
        }
 #endif
-       mono_profiler_gc_heap_resize (new_size);
+
+       MONO_PROFILER_RAISE (gc_resize, (new_size));
 }
 
 typedef struct {
@@ -689,8 +690,8 @@ mono_gc_alloc_obj (MonoVTable *vtable, size_t size)
                obj->vtable = vtable;
        }
 
-       if (G_UNLIKELY (mono_profiler_events & MONO_PROFILE_ALLOCATIONS))
-               mono_profiler_allocation (obj);
+       if (G_UNLIKELY (mono_profiler_allocations_enabled ()))
+               MONO_PROFILER_RAISE (gc_allocation, (obj));
 
        return obj;
 }
@@ -723,8 +724,8 @@ mono_gc_alloc_vector (MonoVTable *vtable, size_t size, uintptr_t max_length)
 
        obj->max_length = max_length;
 
-       if (G_UNLIKELY (mono_profiler_events & MONO_PROFILE_ALLOCATIONS))
-               mono_profiler_allocation (&obj->obj);
+       if (G_UNLIKELY (mono_profiler_allocations_enabled ()))
+               MONO_PROFILER_RAISE (gc_allocation, (&obj->obj));
 
        return obj;
 }
@@ -760,8 +761,8 @@ mono_gc_alloc_array (MonoVTable *vtable, size_t size, uintptr_t max_length, uint
        if (bounds_size)
                obj->bounds = (MonoArrayBounds *) ((char *) obj + size - bounds_size);
 
-       if (G_UNLIKELY (mono_profiler_events & MONO_PROFILE_ALLOCATIONS))
-               mono_profiler_allocation (&obj->obj);
+       if (G_UNLIKELY (mono_profiler_allocations_enabled ()))
+               MONO_PROFILER_RAISE (gc_allocation, (&obj->obj));
 
        return obj;
 }
@@ -778,8 +779,8 @@ mono_gc_alloc_string (MonoVTable *vtable, size_t size, gint32 len)
        obj->length = len;
        obj->chars [len] = 0;
 
-       if (G_UNLIKELY (mono_profiler_events & MONO_PROFILE_ALLOCATIONS))
-               mono_profiler_allocation (&obj->object);
+       if (G_UNLIKELY (mono_profiler_allocations_enabled ()))
+               MONO_PROFILER_RAISE (gc_allocation, (&obj->object));
 
        return obj;
 }
@@ -1175,7 +1176,7 @@ mono_gc_get_managed_allocator (MonoClass *klass, gboolean for_box, gboolean know
                return NULL;
        if (mono_class_has_finalizer (klass) || mono_class_is_marshalbyref (klass))
                return NULL;
-       if (mono_profiler_get_events () & (MONO_PROFILE_ALLOCATIONS | MONO_PROFILE_STATISTICAL))
+       if (G_UNLIKELY (mono_profiler_allocations_enabled ()))
                return NULL;
        if (klass->rank)
                return NULL;
@@ -1726,7 +1727,7 @@ alloc_handle (HandleData *handles, MonoObject *obj, gboolean track)
 #endif
        unlock_handles (handles);
        res = MONO_GC_HANDLE (slot, handles->type);
-       mono_profiler_gc_handle (MONO_PROFILER_GC_HANDLE_CREATED, handles->type, res, obj);
+       MONO_PROFILER_RAISE (gc_handle_created, (res, handles->type, obj));
        return res;
 }
 
@@ -1924,7 +1925,7 @@ mono_gchandle_free (guint32 gchandle)
 #endif
        /*g_print ("freed entry %d of type %d\n", slot, handles->type);*/
        unlock_handles (handles);
-       mono_profiler_gc_handle (MONO_PROFILER_GC_HANDLE_DESTROYED, handles->type, gchandle, NULL);
+       MONO_PROFILER_RAISE (gc_handle_deleted, (gchandle, handles->type));
 }
 
 /**
index 4ed4f39da3dc5d648fa30936fb8d50f1d3fd7974..cd3f8bf703b433073663ebb089962c6306f760cf 100644 (file)
@@ -5561,7 +5561,7 @@ mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError
        klass->name = name;
        klass->name_space = nspace;
 
-       mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
+       MONO_PROFILER_RAISE (class_loading, (klass));
 
        klass->image = image;
        klass->type_token = type_token;
@@ -5635,7 +5635,7 @@ mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError
                        /*FIXME implement a mono_class_set_failure_from_mono_error */
                        mono_class_set_type_load_failure (klass, "%s",  mono_error_get_message (error));
                        mono_loader_unlock ();
-                       mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
+                       MONO_PROFILER_RAISE (class_failed, (klass));
                        return NULL;
                }
        }
@@ -5692,7 +5692,7 @@ mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError
 
                        mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
                        mono_loader_unlock ();
-                       mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
+                       MONO_PROFILER_RAISE (class_failed, (klass));
                        return NULL;
                }
 
@@ -5742,7 +5742,7 @@ mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError
                        klass->cast_class = klass->element_class = mono_defaults.int32_class;
                        mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
                        mono_loader_unlock ();
-                       mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
+                       MONO_PROFILER_RAISE (class_failed, (klass));
                        return NULL;
                }
                klass->cast_class = klass->element_class = mono_class_from_mono_type (enum_basetype);
@@ -5756,7 +5756,7 @@ mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError
        if (mono_class_is_gtd (klass) && !mono_metadata_load_generic_param_constraints_checked (image, type_token, mono_class_get_generic_container (klass), error)) {
                mono_class_set_type_load_failure (klass, "Could not load generic parameter constrains due to %s", mono_error_get_message (error));
                mono_loader_unlock ();
-               mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
+               MONO_PROFILER_RAISE (class_failed, (klass));
                return NULL;
        }
 
@@ -5770,7 +5770,7 @@ mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError
 
        mono_loader_unlock ();
 
-       mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
+       MONO_PROFILER_RAISE (class_loaded, (klass));
 
        return klass;
 
@@ -5780,7 +5780,7 @@ parent_failure:
 
        mono_class_setup_mono_type (klass);
        mono_loader_unlock ();
-       mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
+       MONO_PROFILER_RAISE (class_failed, (klass));
        return NULL;
 }
 
@@ -5917,7 +5917,7 @@ mono_generic_class_get_class (MonoGenericClass *gclass)
        if (mono_class_is_nullable (klass))
                klass->cast_class = klass->element_class = mono_class_get_nullable_param (klass);
 
-       mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
+       MONO_PROFILER_RAISE (class_loading, (klass));
 
        mono_generic_class_setup_parent (klass, gklass);
 
@@ -5927,7 +5927,7 @@ mono_generic_class_get_class (MonoGenericClass *gclass)
        mono_memory_barrier ();
        gclass->cached_class = klass;
 
-       mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
+       MONO_PROFILER_RAISE (class_loaded, (klass));
 
        ++class_ginst_count;
        inflated_classes_size += sizeof (MonoClassGenericInst);
@@ -6013,7 +6013,7 @@ make_generic_param_class (MonoGenericParam *param, MonoGenericParamInfo *pinfo)
                CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , oklass ? oklass->name_space : "" );
        }
 
-       mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
+       MONO_PROFILER_RAISE (class_loading, (klass));
 
        // Count non-NULL items in pinfo->constraints
        count = 0;
@@ -6229,9 +6229,9 @@ mono_class_from_generic_parameter_internal (MonoGenericParam *param)
 
        /* FIXME: Should this go inside 'make_generic_param_klass'? */
        if (klass2)
-               mono_profiler_class_loaded (klass2, MONO_PROFILE_FAILED); // Alert profiler about botched class create
+               MONO_PROFILER_RAISE (class_failed, (klass2));
        else
-               mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
+               MONO_PROFILER_RAISE (class_loaded, (klass));
 
        return klass;
 }
@@ -6283,7 +6283,7 @@ mono_ptr_class_get (MonoType *type)
        result->class_kind = MONO_CLASS_POINTER;
        g_free (name);
 
-       mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
+       MONO_PROFILER_RAISE (class_loading, (result));
 
        result->image = el_class->image;
        result->inited = TRUE;
@@ -6303,7 +6303,7 @@ mono_ptr_class_get (MonoType *type)
                MonoClass *result2;
                if ((result2 = (MonoClass *)g_hash_table_lookup (image->ptr_cache, el_class))) {
                        mono_image_unlock (image);
-                       mono_profiler_class_loaded (result, MONO_PROFILE_FAILED);
+                       MONO_PROFILER_RAISE (class_failed, (result));
                        return result2;
                }
        } else {
@@ -6312,7 +6312,7 @@ mono_ptr_class_get (MonoType *type)
        g_hash_table_insert (image->ptr_cache, el_class, result);
        mono_image_unlock (image);
 
-       mono_profiler_class_loaded (result, MONO_PROFILE_OK);
+       MONO_PROFILER_RAISE (class_loaded, (result));
 
        return result;
 }
@@ -6361,7 +6361,7 @@ mono_fnptr_class_get (MonoMethodSignature *sig)
                return cached;
        }
 
-       mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
+       MONO_PROFILER_RAISE (class_loading, (result));
 
        classes_size += sizeof (MonoClassPointer);
        ++class_pointer_count;
@@ -6370,7 +6370,7 @@ mono_fnptr_class_get (MonoMethodSignature *sig)
 
        mono_loader_unlock ();
 
-       mono_profiler_class_loaded (result, MONO_PROFILE_OK);
+       MONO_PROFILER_RAISE (class_loaded, (result));
 
        return result;
 }
@@ -6689,7 +6689,7 @@ mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
                return cached;
        }
 
-       mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
+       MONO_PROFILER_RAISE (class_loading, (klass));
 
        classes_size += sizeof (MonoClassArray);
        ++class_array_count;
@@ -6705,7 +6705,7 @@ mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
 
        mono_loader_unlock ();
 
-       mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
+       MONO_PROFILER_RAISE (class_loaded, (klass));
 
        return klass;
 }
index 16dc31752dde7b1879bc52d9a1042f45f6053aaf..2a97148f212c44612de0764e4a1ed38ea4ea2355 100644 (file)
@@ -398,7 +398,7 @@ mono_domain_create (void)
        domain->friendly_name = NULL;
        domain->search_path = NULL;
 
-       mono_profiler_appdomain_event (domain, MONO_PROFILE_START_LOAD);
+       MONO_PROFILER_RAISE (domain_loading, (domain));
 
        domain->mp = mono_mempool_new ();
        domain->code_mp = mono_code_manager_new ();
@@ -439,7 +439,7 @@ mono_domain_create (void)
        if (create_domain_hook)
                create_domain_hook (domain);
 
-       mono_profiler_appdomain_loaded (domain, MONO_PROFILE_OK);
+       MONO_PROFILER_RAISE (domain_loaded, (domain));
        
        return domain;
 }
@@ -762,7 +762,7 @@ mono_init_internal (const char *filename, const char *exe_filename, const char *
 
        domain->friendly_name = g_path_get_basename (filename);
 
-       mono_profiler_appdomain_name (domain, domain->friendly_name);
+       MONO_PROFILER_RAISE (domain_name, (domain, domain->friendly_name));
 
        return domain;
 }
@@ -1033,7 +1033,7 @@ mono_domain_free (MonoDomain *domain, gboolean force)
        if (mono_dont_free_domains)
                return;
 
-       mono_profiler_appdomain_event (domain, MONO_PROFILE_START_UNLOAD);
+       MONO_PROFILER_RAISE (domain_unloading, (domain));
 
        mono_debug_domain_unload (domain);
 
@@ -1120,7 +1120,7 @@ mono_domain_free (MonoDomain *domain, gboolean force)
         * Send this after the assemblies have been unloaded and the domain is still in a 
         * usable state.
         */
-       mono_profiler_appdomain_event (domain, MONO_PROFILE_END_UNLOAD);
+       MONO_PROFILER_RAISE (domain_unloaded, (domain));
 
        if (free_domain_hook)
                free_domain_hook (domain);
index 9ea2bcf0ee5c5252c362d8b8106a623db82faa87..211ba26266f050be64153fbbe19701171d265f6b 100644 (file)
@@ -316,7 +316,7 @@ mono_dynamic_image_create (MonoDynamicAssembly *assembly, char *assembly_name, c
 
        image = g_new0 (MonoDynamicImage, 1);
 
-       mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
+       MONO_PROFILER_RAISE (image_loading, (&image->image));
        
        /*g_print ("created image %p\n", image);*/
        /* keep in sync with image.c */
@@ -375,7 +375,7 @@ mono_dynamic_image_create (MonoDynamicAssembly *assembly, char *assembly_name, c
        image->pe_kind = 0x1; /* ILOnly */
        image->machine = 0x14c; /* I386 */
        
-       mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
+       MONO_PROFILER_RAISE (image_loaded, (&image->image));
 
        dynamic_images_lock ();
 
index 4473b04d60d9b9d3e02458229c7537fc77be7b03..76e73073dcca807abdc2cfe2d4101b2396f3bd65 100644 (file)
@@ -174,8 +174,10 @@ void mono_gc_wbarrier_set_root (gpointer ptr, MonoObject *value);
 typedef enum {
        // Regular fast path allocator.
        MANAGED_ALLOCATOR_REGULAR,
-       // Managed allocator that just calls into the runtime. Used when allocation profiling w/ AOT.
+       // Managed allocator that just calls into the runtime.
        MANAGED_ALLOCATOR_SLOW_PATH,
+       // Managed allocator that works like the regular one but also calls into the profiler.
+       MANAGED_ALLOCATOR_PROFILER,
 } ManagedAllocatorVariant;
 
 int mono_gc_get_aligned_size_for_allocator (int size);
index f561dc15b4cb01fd6956f23df5c277339b0fdd08..4d8075ffd20e95189d99455dbd83d8035b00e401 100644 (file)
@@ -305,11 +305,11 @@ mono_gc_run_finalize (void *obj, void *data)
        if (log_finalizers)
                g_log ("mono-gc-finalizers", G_LOG_LEVEL_MESSAGE, "<%s at %p> Calling finalizer.", o->vtable->klass->name, o);
 
-       mono_profiler_gc_finalize_object_begin (o);
+       MONO_PROFILER_RAISE (gc_finalizing_object, (o));
 
        runtime_invoke (o, NULL, &exc, NULL);
 
-       mono_profiler_gc_finalize_object_end (o);
+       MONO_PROFILER_RAISE (gc_finalized_object, (o));
 
        if (log_finalizers)
                g_log ("mono-gc-finalizers", G_LOG_LEVEL_MESSAGE, "<%s at %p> Returned from finalizer.", o->vtable->klass->name, o);
@@ -873,14 +873,14 @@ finalizer_thread (gpointer unused)
 
                finalize_domain_objects ();
 
-               mono_profiler_gc_finalize_begin ();
+               MONO_PROFILER_RAISE (gc_finalizing, ());
 
                /* If finished == TRUE, mono_gc_cleanup has been called (from mono_runtime_cleanup),
                 * before the domain is unloaded.
                 */
                mono_gc_invoke_finalizers ();
 
-               mono_profiler_gc_finalize_end ();
+               MONO_PROFILER_RAISE (gc_finalized, ());
 
                mono_threads_join_threads ();
 
index f878339b210764598dcd86d4a823bfe93e5e351e..827ba841c3d5ec61836f1d62c42356499427340b 100644 (file)
@@ -1272,7 +1272,7 @@ do_mono_image_load (MonoImage *image, MonoImageOpenStatus *status,
        GSList *errors = NULL;
        GSList *l;
 
-       mono_profiler_module_event (image, MONO_PROFILE_START_LOAD);
+       MONO_PROFILER_RAISE (image_loading, (image));
 
        mono_image_init (image);
 
@@ -1336,7 +1336,7 @@ do_mono_image_load (MonoImage *image, MonoImageOpenStatus *status,
        load_modules (image);
 
 done:
-       mono_profiler_module_loaded (image, MONO_PROFILE_OK);
+       MONO_PROFILER_RAISE (image_loaded, (image));
        if (status)
                *status = MONO_IMAGE_OK;
 
@@ -1348,7 +1348,7 @@ invalid_image:
                g_warning ("Could not load image %s due to %s", image->name, info->message);
                mono_free_verify_list (errors);
        }
-       mono_profiler_module_loaded (image, MONO_PROFILE_FAILED);
+       MONO_PROFILER_RAISE (image_failed, (image));
        mono_image_close (image);
        return NULL;
 }
@@ -1978,7 +1978,7 @@ mono_image_close_except_pools (MonoImage *image)
        }
 #endif
 
-       mono_profiler_module_event (image, MONO_PROFILE_START_UNLOAD);
+       MONO_PROFILER_RAISE (image_unloading, (image));
 
        mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_ASSEMBLY, "Unloading image %s [%p].", image->name, image);
 
@@ -2139,7 +2139,7 @@ mono_image_close_except_pools (MonoImage *image)
                mono_dynamic_image_free ((MonoDynamicImage*)image);
        }
 
-       mono_profiler_module_event (image, MONO_PROFILE_END_UNLOAD);
+       MONO_PROFILER_RAISE (image_unloaded, (image));
 
        return TRUE;
 }
index d9781cbdfdd8e849e0cc4d742fb4665eb6cbd4c9..56c3572e76e9137f7140bbed28329fd0c871c0dd 100644 (file)
@@ -1901,11 +1901,10 @@ mono_get_method_constrained_checked (MonoImage *image, guint32 token, MonoClass
 void
 mono_free_method  (MonoMethod *method)
 {
-       if (mono_profiler_get_events () & MONO_PROFILE_METHOD_EVENTS)
-               mono_profiler_method_free (method);
+       MONO_PROFILER_RAISE (method_free, (method));
        
        /* FIXME: This hack will go away when the profiler will support freeing methods */
-       if (mono_profiler_get_events () != MONO_PROFILE_NONE)
+       if (G_UNLIKELY (mono_profiler_installed ()))
                return;
        
        if (method->signature) {
index beb96a4dc43924583e799d484d928eb11f24af9b..702a47c654f285402c0cad5bb601f345e3a78ef1 100644 (file)
@@ -801,7 +801,7 @@ retry:
                return 0;
        }
 
-       mono_profiler_monitor_event (obj, MONO_PROFILER_MONITOR_CONTENTION);
+       MONO_PROFILER_RAISE (monitor_contention, (obj));
 
        /* The slow path begins here. */
 retry_contended:
@@ -824,7 +824,7 @@ retry_contended:
                if (G_LIKELY (tmp_status == old_status)) {
                        /* Success */
                        g_assert (mon->nest == 1);
-                       mono_profiler_monitor_event (obj, MONO_PROFILER_MONITOR_DONE);
+                       MONO_PROFILER_RAISE (monitor_acquired, (obj));
                        return 1;
                }
        }
@@ -832,7 +832,7 @@ retry_contended:
        /* If the object is currently locked by this thread... */
        if (mon_status_get_owner (old_status) == id) {
                mon->nest++;
-               mono_profiler_monitor_event (obj, MONO_PROFILER_MONITOR_DONE);
+               MONO_PROFILER_RAISE (monitor_acquired, (obj));
                return 1;
        }
 
@@ -946,7 +946,7 @@ done_waiting:
        /* Timed out or interrupted */
        mon_decrement_entry_count (mon);
 
-       mono_profiler_monitor_event (obj, MONO_PROFILER_MONITOR_FAIL);
+       MONO_PROFILER_RAISE (monitor_failed, (obj));
 
        if (wait_ret == MONO_SEM_TIMEDWAIT_RET_ALERTED) {
                LOCK_DEBUG (g_message ("%s: (%d) interrupted waiting, returning -1", __func__, id));
index d8d5d4435edaad15c29bd53dd90ecdad8dc04645..bd1262a67b8b60fa2dc0e3d329c5ed3170376bb0 100644 (file)
@@ -45,6 +45,15 @@ typedef enum {
        MONO_ROOT_SOURCE_HANDLE = 14,
 } MonoGCRootSource;
 
+typedef enum {
+       MONO_GC_HANDLE_TYPE_MIN = 0,
+       MONO_GC_HANDLE_WEAK = MONO_GC_HANDLE_TYPE_MIN,
+       MONO_GC_HANDLE_WEAK_TRACK_RESURRECTION,
+       MONO_GC_HANDLE_NORMAL,
+       MONO_GC_HANDLE_PINNED,
+       MONO_GC_HANDLE_TYPE_MAX,
+} MonoGCHandleType;
+
 MONO_API void   mono_gc_collect         (int generation);
 MONO_API int    mono_gc_max_generation  (void);
 MONO_API int    mono_gc_get_generation  (MonoObject *object);
index 3ee786a5d6050812a2c9d98993fd4428210876e1..5744f45d3c42c291a155d9e4f88b276b9a44a2cf 100644 (file)
@@ -2822,13 +2822,11 @@ do_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObject **ex
 
        error_init (error);
        
-       if (mono_profiler_get_events () & MONO_PROFILE_METHOD_EVENTS)
-               mono_profiler_method_start_invoke (method);
+       MONO_PROFILER_RAISE (method_begin_invoke, (method));
 
        result = callbacks.runtime_invoke (method, obj, params, exc, error);
 
-       if (mono_profiler_get_events () & MONO_PROFILE_METHOD_EVENTS)
-               mono_profiler_method_end_invoke (method);
+       MONO_PROFILER_RAISE (method_end_invoke, (method));
 
        if (!mono_error_ok (error))
                return NULL;
diff --git a/mono/metadata/profiler-events.h b/mono/metadata/profiler-events.h
new file mode 100644 (file)
index 0000000..4f9ce64
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * Licensed to the .NET Foundation under one or more agreements.
+ * The .NET Foundation licenses this file to you under the MIT license.
+ * See the LICENSE file in the project root for more information.
+ */
+
+/*
+ * To #include this file, #define the following macros first:
+ *
+ * MONO_PROFILER_EVENT_0(name, type)
+ * MONO_PROFILER_EVENT_1(name, type, arg1_type, arg1_name)
+ * MONO_PROFILER_EVENT_2(name, type, arg1_type, arg1_name, arg2_type, arg2_name)
+ * MONO_PROFILER_EVENT_3(name, type, arg1_type, arg1_name, arg2_type, arg2_name, arg3_type, arg3_name)
+ * MONO_PROFILER_EVENT_4(name, type, arg1_type, arg1_name, arg2_type, arg2_name, arg3_type, arg3_name, arg4_type, arg4_name)
+ *
+ * To add new callbacks to the API, simply add a line in this file and use
+ * MONO_PROFILER_RAISE to raise the event wherever. If you need more arguments
+ * then the current macros provide, add another macro and update all areas
+ * where the macros are used.
+ */
+
+MONO_PROFILER_EVENT_0(runtime_initialized, RuntimeInitialized)
+MONO_PROFILER_EVENT_0(runtime_shutdown, RuntimeShutdown)
+
+MONO_PROFILER_EVENT_1(context_loaded, ContextLoaded, MonoAppContext *, context)
+MONO_PROFILER_EVENT_1(context_unloaded, ContextUnloaded, MonoAppContext *, context)
+
+MONO_PROFILER_EVENT_1(domain_loading, DomainLoading, MonoDomain *, domain)
+MONO_PROFILER_EVENT_1(domain_loaded, DomainLoaded, MonoDomain *, domain)
+MONO_PROFILER_EVENT_1(domain_unloading, DomainUnloading, MonoDomain *, domain)
+MONO_PROFILER_EVENT_1(domain_unloaded, DomainUnloaded, MonoDomain *, domain)
+MONO_PROFILER_EVENT_2(domain_name, DomainName, MonoDomain *, domain, const char *, name)
+
+MONO_PROFILER_EVENT_1(jit_begin, JitBegin, MonoMethod *, method)
+MONO_PROFILER_EVENT_1(jit_failed, JitFailed, MonoMethod *, method)
+MONO_PROFILER_EVENT_2(jit_done, JitDone, MonoMethod *, method, MonoJitInfo *, jinfo)
+MONO_PROFILER_EVENT_2(jit_chunk_created, JitChunkCreated, const mono_byte *, chunk, uintptr_t, size)
+MONO_PROFILER_EVENT_1(jit_chunk_destroyed, JitChunkDestroyed, const mono_byte *, chunk)
+MONO_PROFILER_EVENT_4(jit_code_buffer, JitCodeBuffer, const mono_byte *, buffer, uint64_t, size, MonoProfilerCodeBufferType, type, const void *, data)
+
+MONO_PROFILER_EVENT_1(class_loading, ClassLoading, MonoClass *, klass)
+MONO_PROFILER_EVENT_1(class_failed, ClassFailed, MonoClass *, klass)
+MONO_PROFILER_EVENT_1(class_loaded, ClassLoaded, MonoClass *, klass)
+
+MONO_PROFILER_EVENT_1(image_loading, ModuleLoading, MonoImage *, image)
+MONO_PROFILER_EVENT_1(image_failed, ModuleFailed, MonoImage *, image)
+MONO_PROFILER_EVENT_1(image_loaded, ModuleLoaded, MonoImage *, image)
+MONO_PROFILER_EVENT_1(image_unloading, ModuleUnloading, MonoImage *, image)
+MONO_PROFILER_EVENT_1(image_unloaded, ModuleUnloaded, MonoImage *, image)
+
+MONO_PROFILER_EVENT_1(assembly_loading, AssemblyLoading, MonoAssembly *, assembly)
+MONO_PROFILER_EVENT_1(assembly_loaded, AssemblyLLoaded, MonoAssembly *, assembly)
+MONO_PROFILER_EVENT_1(assembly_unloading, AssemblyLUnloading, MonoAssembly *, assembly)
+MONO_PROFILER_EVENT_1(assembly_unloaded, AssemblyLUnloaded, MonoAssembly *, assembly)
+
+MONO_PROFILER_EVENT_1(method_enter, MethodEnter, MonoMethod *, method)
+MONO_PROFILER_EVENT_1(method_leave, MethodLeave, MonoMethod *, method)
+MONO_PROFILER_EVENT_2(method_exception_leave, MethodExceptionLeave, MonoMethod *, method, MonoObject *, exception)
+MONO_PROFILER_EVENT_1(method_free, MethodFree, MonoMethod *, method)
+MONO_PROFILER_EVENT_1(method_begin_invoke, MethodBeginInvoke, MonoMethod *, method)
+MONO_PROFILER_EVENT_1(method_end_invoke, MethodEndInvoke, MonoMethod *, method)
+
+MONO_PROFILER_EVENT_1(exception_throw, ExceptionThrow, MonoObject *, exception)
+MONO_PROFILER_EVENT_4(exception_clause, ExceptionClause, MonoMethod *, method, uint32_t, index, MonoExceptionEnum, type, MonoObject *, exception)
+
+MONO_PROFILER_EVENT_2(gc_event, GCEvent, MonoProfilerGCEvent, event, uint32_t, generation)
+MONO_PROFILER_EVENT_1(gc_allocation, GCAllocation, MonoObject *, object)
+MONO_PROFILER_EVENT_2(gc_moves, GCMoves, MonoObject *const *, objects, uint64_t, count)
+MONO_PROFILER_EVENT_1(gc_resize, GCResize, uintptr_t, size)
+MONO_PROFILER_EVENT_3(gc_handle_created, GCHandleCreated, uint32_t, handle, MonoGCHandleType, type, MonoObject *, object)
+MONO_PROFILER_EVENT_2(gc_handle_deleted, GCHandleDeleted, uint32_t, handle, MonoGCHandleType, type)
+MONO_PROFILER_EVENT_4(gc_roots, GCRoots, MonoObject *const *, roots, const MonoProfilerGCRootType *, types, const uintptr_t *, extra, uint64_t, count)
+MONO_PROFILER_EVENT_0(gc_finalizing, GCFinalizing)
+MONO_PROFILER_EVENT_0(gc_finalized, GCFinalized)
+MONO_PROFILER_EVENT_1(gc_finalizing_object, GCFinalizingObject, MonoObject *, object)
+MONO_PROFILER_EVENT_1(gc_finalized_object, GCFinalizedObject, MonoObject *, object)
+
+MONO_PROFILER_EVENT_1(monitor_contention, MonitorContention, MonoObject *, object)
+MONO_PROFILER_EVENT_1(monitor_failed, MonitorFailed, MonoObject *, object)
+MONO_PROFILER_EVENT_1(monitor_acquired, MonitorAcquired, MonoObject *, object)
+
+MONO_PROFILER_EVENT_1(thread_started, ThreadStarted, uintptr_t, tid)
+MONO_PROFILER_EVENT_1(thread_stopped, ThreadStopped, uintptr_t, tid)
+MONO_PROFILER_EVENT_2(thread_name, ThreadName, uintptr_t, tid, const char *, name)
+
+MONO_PROFILER_EVENT_2(sample_hit, SampleHit, const mono_byte *, ip, const void *, context)
+
+MONO_PROFILER_EVENT_3(iomap_report, IOMap, const char *, report, const char *, old_path, const char *, new_path)
index 07df86b211f6596a06fbf4294242f1d950ec80b8..4d1b93d4a9566b1e452bcf43fce1bf3027bc7b1c 100644 (file)
-/**
- * \file
+/*
+ * Licensed to the .NET Foundation under one or more agreements.
+ * The .NET Foundation licenses this file to you under the MIT license.
+ * See the LICENSE file in the project root for more information.
  */
 
 #ifndef __MONO_PROFILER_PRIVATE_H__
 #define __MONO_PROFILER_PRIVATE_H__
 
 #include <mono/metadata/profiler.h>
-#include "mono/utils/mono-compiler.h"
-#include <glib.h>
-
-extern MonoProfileFlags mono_profiler_events;
-
-enum {
-       MONO_PROFILE_START_LOAD,
-       MONO_PROFILE_END_LOAD,
-       MONO_PROFILE_START_UNLOAD,
-       MONO_PROFILE_END_UNLOAD
+#include <mono/utils/mono-lazy-init.h>
+#include <mono/utils/mono-os-mutex.h>
+#include <mono/utils/mono-os-semaphore.h>
+
+struct _MonoProfilerDesc {
+       MonoProfilerHandle next;
+       MonoProfiler *prof;
+       volatile gpointer coverage_filter;
+       volatile gpointer call_instrumentation_filter;
+
+#define _MONO_PROFILER_EVENT(name) \
+       volatile gpointer name ## _cb;
+#define MONO_PROFILER_EVENT_0(name, type) \
+       _MONO_PROFILER_EVENT(name)
+#define MONO_PROFILER_EVENT_1(name, type, arg1_type, arg1_name) \
+       _MONO_PROFILER_EVENT(name)
+#define MONO_PROFILER_EVENT_2(name, type, arg1_type, arg1_name, arg2_type, arg2_name) \
+       _MONO_PROFILER_EVENT(name)
+#define MONO_PROFILER_EVENT_3(name, type, arg1_type, arg1_name, arg2_type, arg2_name, arg3_type, arg3_name) \
+       _MONO_PROFILER_EVENT(name)
+#define MONO_PROFILER_EVENT_4(name, type, arg1_type, arg1_name, arg2_type, arg2_name, arg3_type, arg3_name, arg4_type, arg4_name) \
+       _MONO_PROFILER_EVENT(name)
+#include <mono/metadata/profiler-events.h>
+#undef MONO_PROFILER_EVENT_0
+#undef MONO_PROFILER_EVENT_1
+#undef MONO_PROFILER_EVENT_2
+#undef MONO_PROFILER_EVENT_3
+#undef MONO_PROFILER_EVENT_4
+#undef _MONO_PROFILER_EVENT
 };
 
 typedef struct {
-       int entries;
-       struct {
-                guchar* cil_code;
-                int count;
-        } data [1];
-} MonoProfileCoverageInfo;
-
-void mono_profiler_shutdown        (void);
-
-void mono_profiler_method_enter    (MonoMethod *method);
-void mono_profiler_method_leave    (MonoMethod *method);
-void mono_profiler_method_jit      (MonoMethod *method);
-void mono_profiler_method_end_jit  (MonoMethod *method, MonoJitInfo* jinfo, int result);
-void mono_profiler_method_free     (MonoMethod *method);
-void mono_profiler_method_start_invoke (MonoMethod *method);
-void mono_profiler_method_end_invoke   (MonoMethod *method);
-
-void mono_profiler_code_transition (MonoMethod *method, int result);
-void mono_profiler_allocation      (MonoObject *obj);
-void mono_profiler_monitor_event   (MonoObject *obj, MonoProfilerMonitorEvent event);
-void mono_profiler_stat_hit        (guchar *ip, void *context);
-void mono_profiler_stat_call_chain (int call_chain_depth, guchar **ips, void *context);
-int  mono_profiler_stat_get_call_chain_depth (void);
-MonoProfilerCallChainStrategy  mono_profiler_stat_get_call_chain_strategy (void);
-void mono_profiler_thread_start    (gsize tid);
-void mono_profiler_thread_end      (gsize tid);
-void mono_profiler_thread_name     (gsize tid, const char *name);
-
-void mono_profiler_exception_thrown         (MonoObject *exception);
-void mono_profiler_exception_method_leave   (MonoMethod *method);
-void mono_profiler_exception_clause_handler (MonoMethod *method, int clause_type, int clause_num, MonoObject *exc);
-
-void mono_profiler_assembly_event  (MonoAssembly *assembly, int code);
-void mono_profiler_assembly_loaded (MonoAssembly *assembly, int result);
-
-void mono_profiler_module_event  (MonoImage *image, int code);
-void mono_profiler_module_loaded (MonoImage *image, int result);
-
-void mono_profiler_class_event  (MonoClass *klass, int code);
-void mono_profiler_class_loaded (MonoClass *klass, int result);
-
-void mono_profiler_appdomain_event  (MonoDomain *domain, int code);
-void mono_profiler_appdomain_loaded (MonoDomain *domain, int result);
-void mono_profiler_appdomain_name   (MonoDomain *domain, const char *name);
-
-void mono_profiler_context_loaded (MonoAppContext *context);
-void mono_profiler_context_unloaded (MonoAppContext *context);
-
-void mono_profiler_iomap (char *report, const char *pathname, const char *new_pathname);
-
-MonoProfileCoverageInfo* mono_profiler_coverage_alloc (MonoMethod *method, int entries);
-void                     mono_profiler_coverage_free  (MonoMethod *method);
-
-void mono_profiler_gc_event       (MonoGCEvent e, int generation);
-void mono_profiler_gc_heap_resize (gint64 new_size);
-void mono_profiler_gc_moves       (void **objects, int num);
-void 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);
-
-void mono_profiler_gc_finalize_begin (void);
-void mono_profiler_gc_finalize_object_begin (MonoObject *obj);
-void mono_profiler_gc_finalize_object_end (MonoObject *obj);
-void mono_profiler_gc_finalize_end (void);
-
-void mono_profiler_code_chunk_new (gpointer chunk, int size);
-void mono_profiler_code_chunk_destroy (gpointer chunk);
-void mono_profiler_code_buffer_new (gpointer buffer, int size, MonoProfilerCodeBufferType type, gconstpointer data);
-
-void mono_profiler_runtime_initialized (void);
-
-int64_t mono_profiler_get_sampling_rate (void);
-MonoProfileSamplingMode mono_profiler_get_sampling_mode (void);
-
-#endif /* __MONO_PROFILER_PRIVATE_H__ */
+       gboolean startup_done;
+       MonoProfilerHandle profilers;
+       mono_lazy_init_t coverage_status;
+       mono_mutex_t coverage_mutex;
+       GHashTable *coverage_hash;
+       MonoProfilerHandle sampling_owner;
+       MonoSemType sampling_semaphore;
+       MonoProfilerSampleMode sample_mode;
+       uint64_t sample_freq;
+       gboolean allocations;
+
+#define _MONO_PROFILER_EVENT(name) \
+       volatile gint32 name ## _count;
+#define MONO_PROFILER_EVENT_0(name, type) \
+       _MONO_PROFILER_EVENT(name)
+#define MONO_PROFILER_EVENT_1(name, type, arg1_type, arg1_name) \
+       _MONO_PROFILER_EVENT(name)
+#define MONO_PROFILER_EVENT_2(name, type, arg1_type, arg1_name, arg2_type, arg2_name) \
+       _MONO_PROFILER_EVENT(name)
+#define MONO_PROFILER_EVENT_3(name, type, arg1_type, arg1_name, arg2_type, arg2_name, arg3_type, arg3_name) \
+       _MONO_PROFILER_EVENT(name)
+#define MONO_PROFILER_EVENT_4(name, type, arg1_type, arg1_name, arg2_type, arg2_name, arg3_type, arg3_name, arg4_type, arg4_name) \
+       _MONO_PROFILER_EVENT(name)
+#include <mono/metadata/profiler-events.h>
+#undef MONO_PROFILER_EVENT_0
+#undef MONO_PROFILER_EVENT_1
+#undef MONO_PROFILER_EVENT_2
+#undef MONO_PROFILER_EVENT_3
+#undef MONO_PROFILER_EVENT_4
+#undef _MONO_PROFILER_EVENT
+} MonoProfilerState;
+
+extern MonoProfilerState mono_profiler_state;
 
+typedef struct {
+       guint32 entries;
+       struct {
+               guchar *cil_code;
+               guint32 count;
+       } data [1];
+} MonoProfilerCoverageInfo;
+
+void mono_profiler_started (void);
+void mono_profiler_cleanup (void);
+
+static inline gboolean
+mono_profiler_installed (void)
+{
+       return !!mono_profiler_state.profilers;
+}
+
+MonoProfilerCoverageInfo *mono_profiler_coverage_alloc (MonoMethod *method, guint32 entries);
+void mono_profiler_coverage_free (MonoMethod *method);
+
+gboolean mono_profiler_should_instrument_method (MonoMethod *method, gboolean entry);
+
+gboolean mono_profiler_sampling_enabled (void);
+void mono_profiler_sampling_thread_sleep (void);
+
+static inline gboolean
+mono_profiler_allocations_enabled (void)
+{
+       return mono_profiler_state.allocations;
+}
+
+#define _MONO_PROFILER_EVENT(name, ...) \
+       void mono_profiler_raise_ ## name (__VA_ARGS__);
+#define MONO_PROFILER_EVENT_0(name, type) \
+       _MONO_PROFILER_EVENT(name, void)
+#define MONO_PROFILER_EVENT_1(name, type, arg1_type, arg1_name) \
+       _MONO_PROFILER_EVENT(name, arg1_type arg1_name)
+#define MONO_PROFILER_EVENT_2(name, type, arg1_type, arg1_name, arg2_type, arg2_name) \
+       _MONO_PROFILER_EVENT(name, arg1_type arg1_name, arg2_type arg2_name)
+#define MONO_PROFILER_EVENT_3(name, type, arg1_type, arg1_name, arg2_type, arg2_name, arg3_type, arg3_name) \
+       _MONO_PROFILER_EVENT(name, arg1_type arg1_name, arg2_type arg2_name, arg3_type arg3_name)
+#define MONO_PROFILER_EVENT_4(name, type, arg1_type, arg1_name, arg2_type, arg2_name, arg3_type, arg3_name, arg4_type, arg4_name) \
+       _MONO_PROFILER_EVENT(name, arg1_type arg1_name, arg2_type arg2_name, arg3_type arg3_name, arg4_type arg4_name)
+#include <mono/metadata/profiler-events.h>
+#undef MONO_PROFILER_EVENT_0
+#undef MONO_PROFILER_EVENT_1
+#undef MONO_PROFILER_EVENT_2
+#undef MONO_PROFILER_EVENT_3
+#undef MONO_PROFILER_EVENT_4
+#undef _MONO_PROFILER_EVENT
+
+// These are the macros the rest of the runtime should use.
+
+#define MONO_PROFILER_ENABLED(name) \
+       G_UNLIKELY (mono_profiler_state.name ## _count)
+
+#define MONO_PROFILER_RAISE(name, args) \
+       do { \
+               if (MONO_PROFILER_ENABLED (name)) \
+                       mono_profiler_raise_ ## name args; \
+       } while (0)
+
+#endif // __MONO_PROFILER_PRIVATE_H__
index c69f55ec6dc258a3c36fee4dfe93045afdd48bec..a1e222fc1e66c2c8c39b26ac6bff50ab6c9aa88b 100644 (file)
-/**
- * \file
- * Profiler interface for Mono
- *
- * Author:
- *   Paolo Molaro (lupus@ximian.com)
- *   Alex Rønne Petersen (alexrp@xamarin.com)
- *
- * 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).
- * Licensed under the MIT license. See LICENSE file in the project root for full license information.
+/*
+ * Licensed to the .NET Foundation under one or more agreements.
+ * The .NET Foundation licenses this file to you under the MIT license.
+ * See the LICENSE file in the project root for more information.
  */
 
-#include "config.h"
-#include "mono/metadata/profiler-private.h"
-#include "mono/metadata/assembly.h"
-#include "mono/metadata/debug-helpers.h"
-#include "mono/metadata/mono-debug.h"
-#include "mono/metadata/debug-internals.h"
-#include "mono/metadata/metadata-internals.h"
-#include "mono/metadata/class-internals.h"
-#include "mono/metadata/domain-internals.h"
-#include "mono/metadata/gc-internals.h"
-#include "mono/metadata/mono-config-dirs.h"
-#include "mono/utils/mono-dl.h"
-#include <mono/utils/mono-logger-internals.h>
-#include <string.h>
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
-#endif
-#ifdef HAVE_BACKTRACE_SYMBOLS
-#include <execinfo.h>
-#endif
-
-typedef struct _ProfilerDesc ProfilerDesc;
-struct _ProfilerDesc {
-       ProfilerDesc *next;
-       MonoProfiler *profiler;
-       MonoProfileFlags events;
-
-       MonoProfileAppDomainFunc   domain_start_load;
-       MonoProfileAppDomainResult domain_end_load;
-       MonoProfileAppDomainFunc   domain_start_unload;
-       MonoProfileAppDomainFunc   domain_end_unload;
-       MonoProfileAppDomainFriendlyNameFunc   domain_name;
-
-       MonoProfileContextFunc context_load;
-       MonoProfileContextFunc context_unload;
-
-       MonoProfileAssemblyFunc   assembly_start_load;
-       MonoProfileAssemblyResult assembly_end_load;
-       MonoProfileAssemblyFunc   assembly_start_unload;
-       MonoProfileAssemblyFunc   assembly_end_unload;
-
-       MonoProfileModuleFunc   module_start_load;
-       MonoProfileModuleResult module_end_load;
-       MonoProfileModuleFunc   module_start_unload;
-       MonoProfileModuleFunc   module_end_unload;
-
-       MonoProfileClassFunc   class_start_load;
-       MonoProfileClassResult class_end_load;
-       MonoProfileClassFunc   class_start_unload;
-       MonoProfileClassFunc   class_end_unload;
-
-       MonoProfileMethodFunc   jit_start;
-       MonoProfileMethodResult jit_end;
-       MonoProfileJitResult    jit_end2;
-       MonoProfileMethodFunc   method_free;
-       MonoProfileMethodFunc   method_start_invoke;
-       MonoProfileMethodFunc   method_end_invoke;
-       MonoProfileMethodResult man_unman_transition;
-       MonoProfileAllocFunc    allocation_cb;
-       MonoProfileMonitorFunc  monitor_event_cb;
-       MonoProfileStatFunc     statistical_cb;
-       MonoProfileStatCallChainFunc statistical_call_chain_cb;
-       int                     statistical_call_chain_depth;
-       MonoProfilerCallChainStrategy  statistical_call_chain_strategy;
-       MonoProfileMethodFunc   method_enter;
-       MonoProfileMethodFunc   method_leave;
-
-       MonoProfileExceptionFunc        exception_throw_cb;
-       MonoProfileMethodFunc exception_method_leave_cb;
-       MonoProfileExceptionClauseFunc exception_clause_cb;
-       MonoProfileExceptionClauseFunc2 exception_clause_cb2;
-
-       MonoProfileIomapFunc iomap_cb;
-
-       MonoProfileThreadFunc   thread_start;
-       MonoProfileThreadFunc   thread_end;
-       MonoProfileThreadNameFunc   thread_name;
-
-       MonoProfileCoverageFilterFunc coverage_filter_cb;
-
-       MonoProfileFunc shutdown_callback;
-
-       MonoProfileGCFunc        gc_event;
-       MonoProfileGCResizeFunc  gc_heap_resize;
-       MonoProfileGCMoveFunc    gc_moves;
-       MonoProfileGCHandleFunc  gc_handle;
-       MonoProfileGCRootFunc    gc_roots;
-
-       MonoProfileGCFinalizeFunc gc_finalize_begin;
-       MonoProfileGCFinalizeObjectFunc gc_finalize_object_begin;
-       MonoProfileGCFinalizeObjectFunc gc_finalize_object_end;
-       MonoProfileGCFinalizeFunc gc_finalize_end;
-
-       MonoProfileFunc          runtime_initialized_event;
-
-       MonoProfilerCodeChunkNew code_chunk_new;
-       MonoProfilerCodeChunkDestroy code_chunk_destroy;
-       MonoProfilerCodeBufferNew code_buffer_new;
-};
-
-static ProfilerDesc *prof_list = NULL;
-
-#define mono_profiler_coverage_lock() mono_os_mutex_lock (&profiler_coverage_mutex)
-#define mono_profiler_coverage_unlock() mono_os_mutex_unlock (&profiler_coverage_mutex)
-static mono_mutex_t profiler_coverage_mutex;
-
-/* this is directly accessible to other mono libs.
- * It is the ORed value of all the profiler's events.
- */
-MonoProfileFlags mono_profiler_events;
-
-/**
- * mono_profiler_install:
- * \param prof a \c MonoProfiler structure pointer, or a pointer to a derived structure.
- * \param callback the function to invoke at shutdown
- * Use \c mono_profiler_install to activate profiling in the Mono runtime.
- * Typically developers of new profilers will create a new structure whose
- * first field is a \c MonoProfiler and put any extra information that they need
- * to access from the various profiling callbacks there.
- */
-void
-mono_profiler_install (MonoProfiler *prof, MonoProfileFunc callback)
-{
-       ProfilerDesc *desc = g_new0 (ProfilerDesc, 1);
-       if (!prof_list)
-               mono_os_mutex_init_recursive (&profiler_coverage_mutex);
-       desc->profiler = prof;
-       desc->shutdown_callback = callback;
-       desc->next = prof_list;
-       prof_list = desc;
-}
+#include <mono/metadata/assembly.h>
+#include <mono/metadata/gc-internals.h>
+#include <mono/metadata/mono-config-dirs.h>
+#include <mono/metadata/mono-debug.h>
+#include <mono/metadata/profiler-private.h>
+#include <mono/utils/mono-dl.h>
+#include <mono/utils/mono-error-internals.h>
 
-/**
- * mono_profiler_set_events:
- * \param events an ORed set of values made up of \c MONO_PROFILER_ flags
- * The events described in the \p events argument is a set of flags
- * that represent which profiling events must be triggered.  For
- * example if you have registered a set of methods for tracking
- * JIT compilation start and end with \c mono_profiler_install_jit_compile,
- * you will want to pass the \c MONO_PROFILE_JIT_COMPILATION flag to
- * this routine.
- *
- * You can call \c mono_profile_set_events more than once and you can
- * do this at runtime to modify which methods are invoked.
- */
-void
-mono_profiler_set_events (MonoProfileFlags events)
-{
-       ProfilerDesc *prof;
-       MonoProfileFlags value = (MonoProfileFlags)0;
-       if (prof_list)
-               prof_list->events = events;
-       for (prof = prof_list; prof; prof = prof->next)
-               value = (MonoProfileFlags)(value | prof->events);
-       mono_profiler_events = value;
-}
+MonoProfilerState mono_profiler_state;
 
-/**
- * mono_profiler_get_events:
- *
- * Returns a list of active events that will be intercepted. 
- */
-MonoProfileFlags
-mono_profiler_get_events (void)
-{
-       return mono_profiler_events;
-}
+typedef void (*MonoProfilerInitializer) (const char *);
 
-/**
- * mono_profiler_install_enter_leave:
- * \param enter the routine to be called on each method entry
- * \param fleave the routine to be called each time a method returns
- *
- * Use this routine to install routines that will be called everytime
- * a method enters and leaves.   The routines will receive as an argument
- * the \c MonoMethod representing the method that is entering or leaving.
- */
-void
-mono_profiler_install_enter_leave (MonoProfileMethodFunc enter, MonoProfileMethodFunc fleave)
-{
-       if (!prof_list)
-               return;
-       prof_list->method_enter = enter;
-       prof_list->method_leave = fleave;
-}
+#define OLD_INITIALIZER_NAME "mono_profiler_startup"
+#define NEW_INITIALIZER_NAME "mono_profiler_init"
 
-/**
- * mono_profiler_install_jit_compile:
- * \param start the routine to be called when the JIT process starts.
- * \param end the routine to be called when the JIT process ends.
- *
- * Use this routine to install routines that will be called when JIT 
- * compilation of a method starts and completes.
- */
-void 
-mono_profiler_install_jit_compile (MonoProfileMethodFunc start, MonoProfileMethodResult end)
+static gboolean
+load_profiler (MonoDl *module, const char *desc, const char *suffix)
 {
-       if (!prof_list)
-               return;
-       prof_list->jit_start = start;
-       prof_list->jit_end = end;
-}
+       if (!module)
+               return FALSE;
 
-void 
-mono_profiler_install_jit_end (MonoProfileJitResult end)
-{
-       if (!prof_list)
-               return;
-       prof_list->jit_end2 = end;
-}
+       char *old_name;
 
-void 
-mono_profiler_install_method_free (MonoProfileMethodFunc callback)
-{
-       if (!prof_list)
-               return;
-       prof_list->method_free = callback;
-}
+       if (suffix)
+               old_name = g_strdup_printf (OLD_INITIALIZER_NAME "_%s", suffix);
+       else
+               old_name = g_strdup_printf (OLD_INITIALIZER_NAME);
 
-void
-mono_profiler_install_method_invoke (MonoProfileMethodFunc start, MonoProfileMethodFunc end)
-{
-       if (!prof_list)
-               return;
-       prof_list->method_start_invoke = start;
-       prof_list->method_end_invoke = end;
-}
+       MonoProfilerInitializer func;
 
-/**
- * mono_profiler_install_thread:
- */
-void 
-mono_profiler_install_thread (MonoProfileThreadFunc start, MonoProfileThreadFunc end)
-{
-       if (!prof_list)
-               return;
-       prof_list->thread_start = start;
-       prof_list->thread_end = end;
-}
+       char *err;
 
-void 
-mono_profiler_install_thread_name (MonoProfileThreadNameFunc thread_name_cb)
-{
-       if (!prof_list)
-               return;
-       prof_list->thread_name = thread_name_cb;
-}
+       if (!(err = mono_dl_symbol (module, old_name, (gpointer) &func))) {
+               g_warning ("Found old-style startup symbol %s; profiler has not been migrated to the new API.", old_name);
+               g_free (old_name);
+               return FALSE;
+       }
 
-/**
- * mono_profiler_install_transition:
- */
-void 
-mono_profiler_install_transition (MonoProfileMethodResult callback)
-{
-       if (!prof_list)
-               return;
-       prof_list->man_unman_transition = callback;
-}
+       g_free (err);
+       g_free (old_name);
 
-/**
- * mono_profiler_install_allocation:
- */
-void 
-mono_profiler_install_allocation (MonoProfileAllocFunc callback)
-{
-       if (!prof_list)
-               return;
-       prof_list->allocation_cb = callback;
-}
+       char *new_name;
 
-void
-mono_profiler_install_monitor  (MonoProfileMonitorFunc callback)
-{
-       if (!prof_list)
-               return;
-       prof_list->monitor_event_cb = callback;
-}
+       if (suffix)
+               new_name = g_strdup_printf (NEW_INITIALIZER_NAME "_%s", suffix);
+       else
+               new_name = g_strdup_printf (NEW_INITIALIZER_NAME);
 
-static MonoProfileSamplingMode sampling_mode = MONO_PROFILER_STAT_MODE_PROCESS;
-static int64_t sampling_frequency = 100; // Hz
-
-/**
- * mono_profiler_set_statistical_mode:
- * \param mode the sampling mode used.
- * \param sample_frequency_is_us the sampling frequency in microseconds.
- *
- * Set the sampling parameters for the profiler. Sampling mode affects the effective sampling rate as in samples/s you'll witness.
- * The default sampling mode is process mode, which only reports samples when there's activity in the process.
- *
- * Sampling frequency should be interpreted as a suggestion that can't always be honored due to how most kernels expose alarms.
- *
- * Said that, when using statistical sampling, always assume variable rate sampling as all sort of external factors can interfere.
- */
-void
-mono_profiler_set_statistical_mode (MonoProfileSamplingMode mode, int64_t sampling_frequency_hz)
-{
-       sampling_mode = mode;
-       sampling_frequency = sampling_frequency_hz;
-}
+       if ((err = mono_dl_symbol (module, new_name, (gpointer *) &func))) {
+               g_free (err);
+               g_free (new_name);
+               return FALSE;
+       }
 
-/**
- * mono_profiler_install_statistical:
- */
-void 
-mono_profiler_install_statistical (MonoProfileStatFunc callback)
-{
-       if (!prof_list)
-               return;
-       prof_list->statistical_cb = callback;
-}
+       g_free (new_name);
 
-int64_t
-mono_profiler_get_sampling_rate (void)
-{
-       return sampling_frequency;
-}
+       func (desc);
 
-MonoProfileSamplingMode
-mono_profiler_get_sampling_mode (void)
-{
-       return sampling_mode;
+       return TRUE;
 }
 
-void 
-mono_profiler_install_statistical_call_chain (MonoProfileStatCallChainFunc callback, int call_chain_depth, MonoProfilerCallChainStrategy call_chain_strategy) {
-       if (!prof_list)
-               return;
-       if (call_chain_depth > MONO_PROFILER_MAX_STAT_CALL_CHAIN_DEPTH) {
-               call_chain_depth = MONO_PROFILER_MAX_STAT_CALL_CHAIN_DEPTH;
-       }
-       if ((call_chain_strategy >= MONO_PROFILER_CALL_CHAIN_INVALID) || (call_chain_strategy < MONO_PROFILER_CALL_CHAIN_NONE)) {
-               call_chain_strategy = MONO_PROFILER_CALL_CHAIN_NONE;
-       }
-       prof_list->statistical_call_chain_cb = callback;
-       prof_list->statistical_call_chain_depth = call_chain_depth;
-       prof_list->statistical_call_chain_strategy = call_chain_strategy;
-}
+static gboolean
+load_profiler_from_executable (const char *desc, const char *name)
+{
+       char *err;
 
-int
-mono_profiler_stat_get_call_chain_depth (void) {
-       if (prof_list && prof_list->statistical_call_chain_cb != NULL) {
-               return prof_list->statistical_call_chain_depth;
-       } else {
-               return 0;
-       }
-}
+       /*
+        * Some profilers (such as ours) may need to call back into the runtime
+        * from their sampling callback (which is called in async-signal context).
+        * They need to be able to know that all references back to the runtime
+        * have been resolved; otherwise, calling runtime functions may result in
+        * invoking the dynamic linker which is not async-signal-safe. Passing
+        * MONO_DL_EAGER will ask the dynamic linker to resolve everything upfront.
+        */
+       MonoDl *module = mono_dl_open (NULL, MONO_DL_EAGER, &err);
 
-MonoProfilerCallChainStrategy
-mono_profiler_stat_get_call_chain_strategy (void) {
-       if (prof_list && prof_list->statistical_call_chain_cb != NULL) {
-               return prof_list->statistical_call_chain_strategy;
-       } else {
-               return MONO_PROFILER_CALL_CHAIN_NONE;
+       if (!module) {
+               g_warning ("Could not open main executable (%s).", err);
+               g_free (err);
+               return FALSE;
        }
-}
-
-void mono_profiler_install_exception (MonoProfileExceptionFunc throw_callback, MonoProfileMethodFunc exc_method_leave, MonoProfileExceptionClauseFunc clause_callback)
-{
-       if (!prof_list)
-               return;
-       prof_list->exception_throw_cb = throw_callback;
-       prof_list->exception_method_leave_cb = exc_method_leave;
-       prof_list->exception_clause_cb = clause_callback;
-}
-
-void mono_profiler_install_exception_clause (MonoProfileExceptionClauseFunc2 clause_callback)
-{
-       if (!prof_list)
-               return;
 
-       prof_list->exception_clause_cb2 = clause_callback;
+       return load_profiler (module, desc, name);
 }
 
-/**
- * mono_profiler_install_coverage_filter:
- */
-void 
-mono_profiler_install_coverage_filter (MonoProfileCoverageFilterFunc callback)
+static gboolean
+load_profiler_from_directory (const char *directory, const char *libname, const char *desc)
 {
-       if (!prof_list)
-               return;
-       prof_list->coverage_filter_cb = callback;
-}
+       char* path;
+       void *iter = NULL;
 
-/**
- * mono_profiler_install_appdomain:
- */
-void 
-mono_profiler_install_appdomain   (MonoProfileAppDomainFunc start_load, MonoProfileAppDomainResult end_load,
-                                   MonoProfileAppDomainFunc start_unload, MonoProfileAppDomainFunc end_unload)
+       while ((path = mono_dl_build_path (directory, libname, &iter))) {
+               // See the comment in load_embedded_profiler ().
+               MonoDl *module = mono_dl_open (path, MONO_DL_EAGER, NULL);
 
-{
-       if (!prof_list)
-               return;
-       prof_list->domain_start_load = start_load;
-       prof_list->domain_end_load = end_load;
-       prof_list->domain_start_unload = start_unload;
-       prof_list->domain_end_unload = end_unload;
-}
+               g_free (path);
 
-void
-mono_profiler_install_appdomain_name (MonoProfileAppDomainFriendlyNameFunc domain_name_cb)
-{
-       if (!prof_list)
-               return;
+               if (module)
+                       return load_profiler (module, desc, NULL);
+       }
 
-       prof_list->domain_name = domain_name_cb;
+       return FALSE;
 }
 
-void
-mono_profiler_install_context (MonoProfileContextFunc load, MonoProfileContextFunc unload)
+static gboolean
+load_profiler_from_installation (const char *libname, const char *desc)
 {
-       if (!prof_list)
-               return;
+       char *err;
+       MonoDl *module = mono_dl_open_runtime_lib (libname, MONO_DL_EAGER, &err);
 
-       prof_list->context_load = load;
-       prof_list->context_unload = unload;
-}
+       g_free (err);
 
-/**
- * mono_profiler_install_assembly:
- */
-void 
-mono_profiler_install_assembly    (MonoProfileAssemblyFunc start_load, MonoProfileAssemblyResult end_load,
-                                   MonoProfileAssemblyFunc start_unload, MonoProfileAssemblyFunc end_unload)
-{
-       if (!prof_list)
-               return;
-       prof_list->assembly_start_load = start_load;
-       prof_list->assembly_end_load = end_load;
-       prof_list->assembly_start_unload = start_unload;
-       prof_list->assembly_end_unload = end_unload;
-}
+       if (module)
+               return load_profiler (module, desc, NULL);
 
-/**
- * mono_profiler_install_module:
- */
-void 
-mono_profiler_install_module      (MonoProfileModuleFunc start_load, MonoProfileModuleResult end_load,
-                                   MonoProfileModuleFunc start_unload, MonoProfileModuleFunc end_unload)
-{
-       if (!prof_list)
-               return;
-       prof_list->module_start_load = start_load;
-       prof_list->module_end_load = end_load;
-       prof_list->module_start_unload = start_unload;
-       prof_list->module_end_unload = end_unload;
+       return FALSE;
 }
 
-/**
- * mono_profiler_install_class:
- */
 void
-mono_profiler_install_class       (MonoProfileClassFunc start_load, MonoProfileClassResult end_load,
-                                   MonoProfileClassFunc start_unload, MonoProfileClassFunc end_unload)
+mono_profiler_load (const char *desc)
 {
-       if (!prof_list)
-               return;
-       prof_list->class_start_load = start_load;
-       prof_list->class_end_load = end_load;
-       prof_list->class_start_unload = start_unload;
-       prof_list->class_end_unload = end_unload;
-}
+       mono_gc_base_init ();
 
-/**
- * mono_profiler_method_enter:
- */
-void
-mono_profiler_method_enter (MonoMethod *method)
-{
-       ProfilerDesc *prof;
-       for (prof = prof_list; prof; prof = prof->next) {
-               if ((prof->events & MONO_PROFILE_ENTER_LEAVE) && prof->method_enter)
-                       prof->method_enter (prof->profiler, method);
-       }
-}
+       if (!desc || !strcmp ("default", desc))
+               desc = "log:report";
 
-/**
- * mono_profiler_method_leave:
- */
-void
-mono_profiler_method_leave (MonoMethod *method)
-{
-       ProfilerDesc *prof;
-       for (prof = prof_list; prof; prof = prof->next) {
-               if ((prof->events & MONO_PROFILE_ENTER_LEAVE) && prof->method_leave)
-                       prof->method_leave (prof->profiler, method);
-       }
-}
+       const char *col = strchr (desc, ':');
+       char *mname;
 
-/**
- * mono_profiler_method_jit:
- */
-void 
-mono_profiler_method_jit (MonoMethod *method)
-{
-       ProfilerDesc *prof;
-       for (prof = prof_list; prof; prof = prof->next) {
-               if ((prof->events & MONO_PROFILE_JIT_COMPILATION) && prof->jit_start)
-                       prof->jit_start (prof->profiler, method);
-       }
-}
+       if (col != NULL) {
+               mname = (char *) g_memdup (desc, col - desc + 1);
+               mname [col - desc] = 0;
+       } else
+               mname = g_strdup (desc);
 
-/**
- * mono_profiler_method_end_jit:
- */
-void 
-mono_profiler_method_end_jit (MonoMethod *method, MonoJitInfo* jinfo, int result)
-{
-       ProfilerDesc *prof;
-       for (prof = prof_list; prof; prof = prof->next) {
-               if ((prof->events & MONO_PROFILE_JIT_COMPILATION)) {
-                       if (prof->jit_end)
-                               prof->jit_end (prof->profiler, method, result);
-                       if (prof->jit_end2)
-                               prof->jit_end2 (prof->profiler, method, jinfo, result);
-               }
-       }
-}
+       if (!load_profiler_from_executable (desc, mname)) {
+               char *libname = g_strdup_printf ("mono-profiler-%s", mname);
+               gboolean res = load_profiler_from_installation (libname, desc);
 
-void 
-mono_profiler_method_free (MonoMethod *method)
-{
-       ProfilerDesc *prof;
-       for (prof = prof_list; prof; prof = prof->next) {
-               if ((prof->events & MONO_PROFILE_METHOD_EVENTS) && prof->method_free)
-                       prof->method_free (prof->profiler, method);
-       }
-}
+               if (!res && mono_config_get_assemblies_dir ())
+                       res = load_profiler_from_directory (mono_assembly_getrootdir (), libname, desc);
 
-void
-mono_profiler_method_start_invoke (MonoMethod *method)
-{
-       ProfilerDesc *prof;
-       for (prof = prof_list; prof; prof = prof->next) {
-               if ((prof->events & MONO_PROFILE_METHOD_EVENTS) && prof->method_start_invoke)
-                       prof->method_start_invoke (prof->profiler, method);
-       }
-}
+               if (!res)
+                       res = load_profiler_from_directory (NULL, libname, desc);
 
-void
-mono_profiler_method_end_invoke (MonoMethod *method)
-{
-       ProfilerDesc *prof;
-       for (prof = prof_list; prof; prof = prof->next) {
-               if ((prof->events & MONO_PROFILE_METHOD_EVENTS) && prof->method_end_invoke)
-                       prof->method_end_invoke (prof->profiler, method);
-       }
-}
+               if (!res)
+                       g_warning ("The '%s' profiler wasn't found in the main executable nor could it be loaded from '%s'.", mname, libname);
 
-/**
- * mono_profiler_code_transition:
- */
-void 
-mono_profiler_code_transition (MonoMethod *method, int result)
-{
-       ProfilerDesc *prof;
-       for (prof = prof_list; prof; prof = prof->next) {
-               if ((prof->events & MONO_PROFILE_TRANSITIONS) && prof->man_unman_transition)
-                       prof->man_unman_transition (prof->profiler, method, result);
+               g_free (libname);
        }
+
+       g_free (mname);
 }
 
-/**
- * mono_profiler_allocation:
- */
-void 
-mono_profiler_allocation (MonoObject *obj)
+MonoProfilerHandle
+mono_profiler_install (MonoProfiler *prof)
 {
-       ProfilerDesc *prof;
-       for (prof = prof_list; prof; prof = prof->next) {
-               if ((prof->events & MONO_PROFILE_ALLOCATIONS) && prof->allocation_cb)
-                       prof->allocation_cb (prof->profiler, obj, obj->vtable->klass);
-       }
-}
+       MonoProfilerHandle handle = g_new0 (struct _MonoProfilerDesc, 1);
 
-void
-mono_profiler_monitor_event      (MonoObject *obj, MonoProfilerMonitorEvent event) {
-       ProfilerDesc *prof;
-       for (prof = prof_list; prof; prof = prof->next) {
-               if ((prof->events & MONO_PROFILE_MONITOR_EVENTS) && prof->monitor_event_cb)
-                       prof->monitor_event_cb (prof->profiler, obj, event);
-       }
-}
+       handle->prof = prof;
+       handle->next = mono_profiler_state.profilers;
 
-/**
- * mono_profiler_stat_hit:
- */
-void
-mono_profiler_stat_hit (guchar *ip, void *context)
-{
-       ProfilerDesc *prof;
-       for (prof = prof_list; prof; prof = prof->next) {
-               if ((prof->events & MONO_PROFILE_STATISTICAL) && prof->statistical_cb)
-                       prof->statistical_cb (prof->profiler, ip, context);
-       }
-}
+       mono_profiler_state.profilers = handle;
 
-void
-mono_profiler_stat_call_chain (int call_chain_depth, guchar **ips, void *context)
-{
-       ProfilerDesc *prof;
-       for (prof = prof_list; prof; prof = prof->next) {
-               if ((prof->events & MONO_PROFILE_STATISTICAL) && prof->statistical_call_chain_cb)
-                       prof->statistical_call_chain_cb (prof->profiler, call_chain_depth, ips, context);
-       }
+       return handle;
 }
 
 void
-mono_profiler_exception_thrown (MonoObject *exception)
+mono_profiler_set_coverage_filter_callback (MonoProfilerHandle handle, MonoProfilerCoverageFilterCallback cb)
 {
-       ProfilerDesc *prof;
-       for (prof = prof_list; prof; prof = prof->next) {
-               if ((prof->events & MONO_PROFILE_EXCEPTIONS) && prof->exception_throw_cb)
-                       prof->exception_throw_cb (prof->profiler, exception);
-       }
+       InterlockedWritePointer (&handle->coverage_filter, (gpointer) cb);
 }
 
-void
-mono_profiler_exception_method_leave (MonoMethod *method)
+static void
+initialize_coverage (void)
 {
-       ProfilerDesc *prof;
-       for (prof = prof_list; prof; prof = prof->next) {
-               if ((prof->events & MONO_PROFILE_EXCEPTIONS) && prof->exception_method_leave_cb)
-                       prof->exception_method_leave_cb (prof->profiler, method);
-       }
+       mono_os_mutex_init (&mono_profiler_state.coverage_mutex);
+       mono_profiler_state.coverage_hash = g_hash_table_new (NULL, NULL);
 }
 
-void
-mono_profiler_exception_clause_handler (MonoMethod *method, int clause_type, int clause_num, MonoObject *exc)
+static void
+lazy_initialize_coverage (void)
 {
-       ProfilerDesc *prof;
-       for (prof = prof_list; prof; prof = prof->next) {
-               if (prof->events & MONO_PROFILE_EXCEPTIONS) {
-                       if (prof->exception_clause_cb)
-                               prof->exception_clause_cb (prof->profiler, method, clause_type, clause_num);
-
-                       if (prof->exception_clause_cb2)
-                               prof->exception_clause_cb2 (prof->profiler, method, clause_type, clause_num, exc);
-               }
-       }
+       mono_lazy_initialize (&mono_profiler_state.coverage_status, initialize_coverage);
 }
 
-/**
- * mono_profiler_thread_start:
- */
-void
-mono_profiler_thread_start (gsize tid)
+static void
+coverage_lock (void)
 {
-       ProfilerDesc *prof;
-       for (prof = prof_list; prof; prof = prof->next) {
-               if ((prof->events & MONO_PROFILE_THREADS) && prof->thread_start)
-                       prof->thread_start (prof->profiler, tid);
-       }
+       mono_os_mutex_lock (&mono_profiler_state.coverage_mutex);
 }
 
-/**
- * mono_profiler_thread_end:
- */
-void 
-mono_profiler_thread_end (gsize tid)
+static void
+coverage_unlock (void)
 {
-       ProfilerDesc *prof;
-       for (prof = prof_list; prof; prof = prof->next) {
-               if ((prof->events & MONO_PROFILE_THREADS) && prof->thread_end)
-                       prof->thread_end (prof->profiler, tid);
-       }
+       mono_os_mutex_unlock (&mono_profiler_state.coverage_mutex);
 }
 
 void
-mono_profiler_thread_name (gsize tid, const char *name)
+mono_profiler_get_coverage_data (MonoProfilerHandle handle, MonoMethod *method, MonoProfilerCoverageCallback cb)
 {
-       ProfilerDesc *prof;
-       for (prof = prof_list; prof; prof = prof->next) {
-               if ((prof->events & MONO_PROFILE_THREADS) && prof->thread_name)
-                       prof->thread_name (prof->profiler, tid, name);
-       }
-}
+       lazy_initialize_coverage ();
 
-/**
- * mono_profiler_assembly_event:
- */
-void 
-mono_profiler_assembly_event  (MonoAssembly *assembly, int code)
-{
-       ProfilerDesc *prof;
-       for (prof = prof_list; prof; prof = prof->next) {
-               if (!(prof->events & MONO_PROFILE_ASSEMBLY_EVENTS))
-                       continue;
-
-               switch (code) {
-               case MONO_PROFILE_START_LOAD:
-                       if (prof->assembly_start_load)
-                               prof->assembly_start_load (prof->profiler, assembly);
-                       break;
-               case MONO_PROFILE_START_UNLOAD:
-                       if (prof->assembly_start_unload)
-                               prof->assembly_start_unload (prof->profiler, assembly);
-                       break;
-               case MONO_PROFILE_END_UNLOAD:
-                       if (prof->assembly_end_unload)
-                               prof->assembly_end_unload (prof->profiler, assembly);
-                       break;
-               default:
-                       g_assert_not_reached ();
-               }
-       }
-}
+       coverage_lock ();
 
-/**
- * mono_profiler_assembly_loaded:
- */
-void 
-mono_profiler_assembly_loaded (MonoAssembly *assembly, int result)
-{
-       ProfilerDesc *prof;
-       for (prof = prof_list; prof; prof = prof->next) {
-               if ((prof->events & MONO_PROFILE_ASSEMBLY_EVENTS) && prof->assembly_end_load)
-                       prof->assembly_end_load (prof->profiler, assembly, result);
-       }
-}
+       MonoProfilerCoverageInfo *info = g_hash_table_lookup (mono_profiler_state.coverage_hash, method);
 
-void mono_profiler_iomap (char *report, const char *pathname, const char *new_pathname)
-{
-       ProfilerDesc *prof;
-       for (prof = prof_list; prof; prof = prof->next) {
-               if ((prof->events & MONO_PROFILE_IOMAP_EVENTS) && prof->iomap_cb)
-                       prof->iomap_cb (prof->profiler, report, pathname, new_pathname);
-       }
-}
+       coverage_unlock ();
 
-/**
- * mono_profiler_module_event:
- */
-void 
-mono_profiler_module_event  (MonoImage *module, int code)
-{
-       ProfilerDesc *prof;
-       for (prof = prof_list; prof; prof = prof->next) {
-               if (!(prof->events & MONO_PROFILE_MODULE_EVENTS))
-                       continue;
-
-               switch (code) {
-               case MONO_PROFILE_START_LOAD:
-                       if (prof->module_start_load)
-                               prof->module_start_load (prof->profiler, module);
-                       break;
-               case MONO_PROFILE_START_UNLOAD:
-                       if (prof->module_start_unload)
-                               prof->module_start_unload (prof->profiler, module);
-                       break;
-               case MONO_PROFILE_END_UNLOAD:
-                       if (prof->module_end_unload)
-                               prof->module_end_unload (prof->profiler, module);
-                       break;
-               default:
-                       g_assert_not_reached ();
-               }
-       }
-}
+       if (!info)
+               return;
 
-/**
- * mono_profiler_module_loaded:
- */
-void 
-mono_profiler_module_loaded (MonoImage *module, int result)
-{
-       ProfilerDesc *prof;
-       for (prof = prof_list; prof; prof = prof->next) {
-               if ((prof->events & MONO_PROFILE_MODULE_EVENTS) && prof->module_end_load)
-                       prof->module_end_load (prof->profiler, module, result);
-       }
-}
+       MonoError error;
+       MonoMethodHeader *header = mono_method_get_header_checked (method, &error);
+       mono_error_assert_ok (&error);
 
-/**
- * mono_profiler_class_event:
- */
-void 
-mono_profiler_class_event  (MonoClass *klass, int code)
-{
-       ProfilerDesc *prof;
-       for (prof = prof_list; prof; prof = prof->next) {
-               if (!(prof->events & MONO_PROFILE_CLASS_EVENTS))
-                       continue;
-
-               switch (code) {
-               case MONO_PROFILE_START_LOAD:
-                       if (prof->class_start_load)
-                               prof->class_start_load (prof->profiler, klass);
-                       break;
-               case MONO_PROFILE_START_UNLOAD:
-                       if (prof->class_start_unload)
-                               prof->class_start_unload (prof->profiler, klass);
-                       break;
-               case MONO_PROFILE_END_UNLOAD:
-                       if (prof->class_end_unload)
-                               prof->class_end_unload (prof->profiler, klass);
-                       break;
-               default:
-                       g_assert_not_reached ();
-               }
-       }
-}
+       guint32 size;
 
-/**
- * mono_profiler_class_loaded:
- */
-void 
-mono_profiler_class_loaded (MonoClass *klass, int result)
-{
-       ProfilerDesc *prof;
-       for (prof = prof_list; prof; prof = prof->next) {
-               if ((prof->events & MONO_PROFILE_CLASS_EVENTS) && prof->class_end_load)
-                       prof->class_end_load (prof->profiler, klass, result);
-       }
-}
+       const unsigned char *start = mono_method_header_get_code (header, &size, NULL);
+       const unsigned char *end = start - size;
+       MonoDebugMethodInfo *minfo = mono_debug_lookup_method (method);
 
-/**
- * mono_profiler_appdomain_event:
- */
-void 
-mono_profiler_appdomain_event  (MonoDomain *domain, int code)
-{
-       ProfilerDesc *prof;
-       for (prof = prof_list; prof; prof = prof->next) {
-               if (!(prof->events & MONO_PROFILE_APPDOMAIN_EVENTS))
-                       continue;
-
-               switch (code) {
-               case MONO_PROFILE_START_LOAD:
-                       if (prof->domain_start_load)
-                               prof->domain_start_load (prof->profiler, domain);
-                       break;
-               case MONO_PROFILE_START_UNLOAD:
-                       if (prof->domain_start_unload)
-                               prof->domain_start_unload (prof->profiler, domain);
-                       break;
-               case MONO_PROFILE_END_UNLOAD:
-                       if (prof->domain_end_unload)
-                               prof->domain_end_unload (prof->profiler, domain);
-                       break;
-               default:
-                       g_assert_not_reached ();
-               }
-       }
-}
+       for (guint32 i = 0; i < info->entries; i++) {
+               guchar *cil_code = info->data [i].cil_code;
 
-/**
- * mono_profiler_appdomain_loaded:
- */
-void 
-mono_profiler_appdomain_loaded (MonoDomain *domain, int result)
-{
-       ProfilerDesc *prof;
-       for (prof = prof_list; prof; prof = prof->next) {
-               if ((prof->events & MONO_PROFILE_APPDOMAIN_EVENTS) && prof->domain_end_load)
-                       prof->domain_end_load (prof->profiler, domain, result);
-       }
-}
+               if (cil_code && cil_code >= start && cil_code < end) {
+                       guint32 offset = cil_code - start;
 
-void
-mono_profiler_appdomain_name (MonoDomain *domain, const char *name)
-{
-       for (ProfilerDesc *prof = prof_list; prof; prof = prof->next)
-               if ((prof->events & MONO_PROFILE_APPDOMAIN_EVENTS) && prof->domain_name)
-                       prof->domain_name (prof->profiler, domain, name);
-}
+                       MonoProfilerCoverageData data = {
+                               .method = method,
+                               .il_offset = offset,
+                               .counter = info->data [i].count,
+                               .line = 1,
+                               .column = 1,
+                       };
 
-void
-mono_profiler_context_loaded (MonoAppContext *context)
-{
-       for (ProfilerDesc *prof = prof_list; prof; prof = prof->next)
-               if ((prof->events & MONO_PROFILE_CONTEXT_EVENTS) && prof->context_load)
-                       prof->context_load (prof->profiler, context);
-}
+                       if (minfo) {
+                               MonoDebugSourceLocation *loc = mono_debug_method_lookup_location (minfo, offset);
 
-void
-mono_profiler_context_unloaded (MonoAppContext *context)
-{
-       for (ProfilerDesc *prof = prof_list; prof; prof = prof->next)
-               if ((prof->events & MONO_PROFILE_CONTEXT_EVENTS) && prof->context_unload)
-                       prof->context_unload (prof->profiler, context);
-}
+                               if (loc) {
+                                       data.file_name = g_strdup (loc->source_file);
+                                       data.line = loc->row;
+                                       data.column = loc->column;
 
-/**
- * mono_profiler_shutdown:
- */
-void 
-mono_profiler_shutdown (void)
-{
-       ProfilerDesc *prof;
-       for (prof = prof_list; prof; prof = prof->next) {
-               if (prof->shutdown_callback)
-                       prof->shutdown_callback (prof->profiler);
-       }
+                                       mono_debug_free_source_location (loc);
+                               }
+                       }
 
-       mono_profiler_set_events ((MonoProfileFlags)0);
-}
+                       cb (handle->prof, &data);
 
-/**
- * mono_profiler_gc_heap_resize:
- */
-void
-mono_profiler_gc_heap_resize (gint64 new_size)
-{
-       ProfilerDesc *prof;
-       for (prof = prof_list; prof; prof = prof->next) {
-               if ((prof->events & MONO_PROFILE_GC) && prof->gc_heap_resize)
-                       prof->gc_heap_resize (prof->profiler, new_size);
+                       g_free ((char *) data.file_name);
+               }
        }
-}
 
-/**
- * mono_profiler_gc_event:
- */
-void
-mono_profiler_gc_event (MonoGCEvent event, int generation)
-{
-       ProfilerDesc *prof;
-       for (prof = prof_list; prof; prof = prof->next) {
-               if ((prof->events & MONO_PROFILE_GC) && prof->gc_event)
-                       prof->gc_event (prof->profiler, event, generation);
-       }
+       mono_metadata_free_mh (header);
 }
 
-void
-mono_profiler_gc_moves (void **objects, int num)
+MonoProfilerCoverageInfo *
+mono_profiler_coverage_alloc (MonoMethod *method, guint32 entries)
 {
-       ProfilerDesc *prof;
-       for (prof = prof_list; prof; prof = prof->next) {
-               if ((prof->events & MONO_PROFILE_GC_MOVES) && prof->gc_moves)
-                       prof->gc_moves (prof->profiler, objects, num);
-       }
-}
+       lazy_initialize_coverage ();
 
-void
-mono_profiler_gc_handle (int op, int type, uintptr_t handle, MonoObject *obj)
-{
-       ProfilerDesc *prof;
-       for (prof = prof_list; prof; prof = prof->next) {
-               if ((prof->events & MONO_PROFILE_GC_ROOTS) && prof->gc_handle)
-                       prof->gc_handle (prof->profiler, op, type, handle, obj);
-       }
-}
+       gboolean cover = FALSE;
 
-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);
+       for (MonoProfilerHandle handle = mono_profiler_state.profilers; handle; handle = handle->next) {
+               MonoProfilerCoverageFilterCallback cb = handle->coverage_filter;
+
+               if (cb)
+                       cover |= cb (handle->prof, method);
        }
-}
 
-/**
- * mono_profiler_install_gc:
- */
-void
-mono_profiler_install_gc (MonoProfileGCFunc callback, MonoProfileGCResizeFunc heap_resize_callback)
-{
-       if (!prof_list)
-               return;
-       prof_list->gc_event = callback;
-       prof_list->gc_heap_resize = heap_resize_callback;
-}
+       if (!cover)
+               return NULL;
 
-/**
- * mono_profiler_install_gc_moves:
- * \param callback callback function
- *
- * Install the \p callback function that the GC will call when moving objects.
- * The callback receives an array of pointers and the number of elements
- * in the array. Every even element in the array is the original object location
- * and the following odd element is the new location of the object in memory.
- * So the number of elements argument will always be a multiple of 2.
- * Since this callback happens during the GC, it is a restricted environment:
- * no locks can be taken and the object pointers can be inspected only once
- * the GC is finished (of course the original location pointers will not
- * point to valid objects anymore).
- */
-void
-mono_profiler_install_gc_moves (MonoProfileGCMoveFunc callback)
-{
-       if (!prof_list)
-               return;
-       prof_list->gc_moves = callback;
-}
+       coverage_lock ();
 
-/**
- * mono_profiler_install_gc_roots:
- * \param handle_callback callback function
- * \param roots_callback callback function
- *
- * Install the \p handle_callback function that the GC will call when GC
- * handles are created or destroyed.
- * The callback receives an operation, which is either \c MONO_PROFILER_GC_HANDLE_CREATED
- * or \c MONO_PROFILER_GC_HANDLE_DESTROYED, the handle type, the handle value and the
- * object pointer, if present.
- * Install the \p 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, MonoProfileGCRootFunc roots_callback)
-{
-       if (!prof_list)
-               return;
-       prof_list->gc_handle = handle_callback;
-       prof_list->gc_roots = roots_callback;
-}
+       MonoProfilerCoverageInfo *info = g_malloc0 (sizeof (MonoProfilerCoverageInfo) + SIZEOF_VOID_P * 2 * entries);
 
-void
-mono_profiler_gc_finalize_begin (void)
-{
-       for (ProfilerDesc *prof = prof_list; prof; prof = prof->next)
-               if ((prof->events & MONO_PROFILE_GC_FINALIZATION) && prof->gc_finalize_begin)
-                       prof->gc_finalize_begin (prof->profiler);
-}
+       info->entries = entries;
 
-void
-mono_profiler_gc_finalize_object_begin (MonoObject *obj)
-{
-       for (ProfilerDesc *prof = prof_list; prof; prof = prof->next)
-               if ((prof->events & MONO_PROFILE_GC_FINALIZATION) && prof->gc_finalize_object_begin)
-                       prof->gc_finalize_object_begin (prof->profiler, obj);
-}
+       g_hash_table_insert (mono_profiler_state.coverage_hash, method, info);
 
-void
-mono_profiler_gc_finalize_object_end (MonoObject *obj)
-{
-       for (ProfilerDesc *prof = prof_list; prof; prof = prof->next)
-               if ((prof->events & MONO_PROFILE_GC_FINALIZATION) && prof->gc_finalize_object_end)
-                       prof->gc_finalize_object_end (prof->profiler, obj);
-}
+       coverage_unlock ();
 
-void
-mono_profiler_gc_finalize_end (void)
-{
-       for (ProfilerDesc *prof = prof_list; prof; prof = prof->next)
-               if ((prof->events & MONO_PROFILE_GC_FINALIZATION) && prof->gc_finalize_end)
-                       prof->gc_finalize_end (prof->profiler);
+       return info;
 }
 
 void
-mono_profiler_install_gc_finalize (MonoProfileGCFinalizeFunc begin, MonoProfileGCFinalizeObjectFunc begin_obj, MonoProfileGCFinalizeObjectFunc end_obj, MonoProfileGCFinalizeFunc end)
+mono_profiler_coverage_free (MonoMethod *method)
 {
-       if (!prof_list)
-               return;
+       lazy_initialize_coverage ();
 
-       prof_list->gc_finalize_begin = begin;
-       prof_list->gc_finalize_object_begin = begin_obj;
-       prof_list->gc_finalize_object_end = end_obj;
-       prof_list->gc_finalize_end = end;
-}
+       coverage_lock ();
 
-void
-mono_profiler_install_runtime_initialized (MonoProfileFunc runtime_initialized_callback)
-{
-       if (!prof_list)
-               return;
-       prof_list->runtime_initialized_event = runtime_initialized_callback;
-}
+       MonoProfilerCoverageInfo *info = g_hash_table_lookup (mono_profiler_state.coverage_hash, method);
 
-void
-mono_profiler_runtime_initialized (void) {
-       ProfilerDesc *prof;
-       for (prof = prof_list; prof; prof = prof->next) {
-               if (prof->runtime_initialized_event)
-                       prof->runtime_initialized_event (prof->profiler);
+       if (info) {
+               g_hash_table_remove (mono_profiler_state.coverage_hash, method);
+               g_free (info);
        }
-}
 
-void
-mono_profiler_install_code_chunk_new (MonoProfilerCodeChunkNew callback) {
-       if (!prof_list)
-               return;
-       prof_list->code_chunk_new = callback;
-}
-void
-mono_profiler_code_chunk_new (gpointer chunk, int size) {
-       ProfilerDesc *prof;
-       for (prof = prof_list; prof; prof = prof->next) {
-               if (prof->code_chunk_new)
-                       prof->code_chunk_new (prof->profiler, chunk, size);
-       }
+       coverage_unlock ();
 }
 
-void
-mono_profiler_install_code_chunk_destroy (MonoProfilerCodeChunkDestroy callback) {
-       if (!prof_list)
-               return;
-       prof_list->code_chunk_destroy = callback;
-}
-void
-mono_profiler_code_chunk_destroy (gpointer chunk) {
-       ProfilerDesc *prof;
-       for (prof = prof_list; prof; prof = prof->next) {
-               if (prof->code_chunk_destroy)
-                       prof->code_chunk_destroy (prof->profiler, chunk);
-       }
-}
+mono_bool
+mono_profiler_enable_sampling (MonoProfilerHandle handle)
+{
+       if (mono_profiler_state.startup_done)
+               return FALSE;
 
-void
-mono_profiler_install_code_buffer_new (MonoProfilerCodeBufferNew callback) {
-       if (!prof_list)
-               return;
-       prof_list->code_buffer_new = callback;
-}
+       if (mono_profiler_state.sampling_owner)
+               return TRUE;
 
-void
-mono_profiler_install_iomap (MonoProfileIomapFunc callback)
-{
-       if (!prof_list)
-               return;
-       prof_list->iomap_cb = callback;
-}
+       mono_profiler_state.sampling_owner = handle;
+       mono_profiler_state.sample_mode = MONO_PROFILER_SAMPLE_MODE_NONE;
+       mono_profiler_state.sample_freq = 100;
+       mono_os_sem_init (&mono_profiler_state.sampling_semaphore, 0);
 
-void
-mono_profiler_code_buffer_new (gpointer buffer, int size, MonoProfilerCodeBufferType type, gconstpointer data) {
-       ProfilerDesc *prof;
-       for (prof = prof_list; prof; prof = prof->next) {
-               if (prof->code_buffer_new)
-                       prof->code_buffer_new (prof->profiler, buffer, size, type, (void*)data);
-       }
+       return TRUE;
 }
 
-static GHashTable *coverage_hash = NULL;
-
-MonoProfileCoverageInfo* 
-mono_profiler_coverage_alloc (MonoMethod *method, int entries)
+mono_bool
+mono_profiler_set_sample_mode (MonoProfilerHandle handle, MonoProfilerSampleMode mode, uint64_t freq)
 {
-       MonoProfileCoverageInfo *res;
-       int instrument = FALSE;
-       ProfilerDesc *prof;
-
-       for (prof = prof_list; prof; prof = prof->next) {
-               /* note that we call the filter on all the profilers even if just
-                * a single one would be enough to instrument a method
-                */
-               if (prof->coverage_filter_cb)
-                       if (prof->coverage_filter_cb (prof->profiler, method))
-                               instrument = TRUE;
-       }
-       if (!instrument)
-               return NULL;
-
-       mono_profiler_coverage_lock ();
-       if (!coverage_hash)
-               coverage_hash = g_hash_table_new (NULL, NULL);
-
-       res = (MonoProfileCoverageInfo *)g_malloc0 (sizeof (MonoProfileCoverageInfo) + sizeof (void*) * 2 * entries);
+       if (handle != mono_profiler_state.sampling_owner)
+               return FALSE;
 
-       res->entries = entries;
+       mono_profiler_state.sample_mode = mode;
+       mono_profiler_state.sample_freq = freq;
 
-       g_hash_table_insert (coverage_hash, method, res);
-       mono_profiler_coverage_unlock ();
+       mono_os_sem_post (&mono_profiler_state.sampling_semaphore);
 
-       return res;
+       return TRUE;
 }
 
-/* safe only when the method antive code has been unloaded */
-void
-mono_profiler_coverage_free (MonoMethod *method)
+mono_bool
+mono_profiler_get_sample_mode (MonoProfilerHandle handle, MonoProfilerSampleMode *mode, uint64_t *freq)
 {
-       MonoProfileCoverageInfo* info;
+       if (mode)
+               *mode = mono_profiler_state.sample_mode;
 
-       mono_profiler_coverage_lock ();
-       if (!coverage_hash) {
-               mono_profiler_coverage_unlock ();
-               return;
-       }
+       if (freq)
+               *freq = mono_profiler_state.sample_freq;
 
-       info = (MonoProfileCoverageInfo *)g_hash_table_lookup (coverage_hash, method);
-       if (info) {
-               g_free (info);
-               g_hash_table_remove (coverage_hash, method);
-       }
-       mono_profiler_coverage_unlock ();
+       return handle == mono_profiler_state.sampling_owner;
 }
 
-/**
- * mono_profiler_coverage_get:
- * \param prof The profiler handle, installed with mono_profiler_install
- * \param method the method to gather information from.
- * \param func A routine that will be called back with the results
- *
- * If the \c MONO_PROFILER_INS_COVERAGE flag was active during JIT compilation
- * it is possible to obtain coverage information about a give method.
- *
- * The function \p func will be invoked repeatedly with instances of the
- * \c MonoProfileCoverageEntry structure.
- */
-void 
-mono_profiler_coverage_get (MonoProfiler *prof, MonoMethod *method, MonoProfileCoverageFunc func)
+gboolean
+mono_profiler_sampling_enabled (void)
 {
-       MonoError error;
-       MonoProfileCoverageInfo* info = NULL;
-       int i, offset;
-       guint32 code_size;
-       const unsigned char *start, *end, *cil_code;
-       MonoMethodHeader *header;
-       MonoProfileCoverageEntry entry;
-       MonoDebugMethodInfo *debug_minfo;
-
-       mono_profiler_coverage_lock ();
-       if (coverage_hash)
-               info = (MonoProfileCoverageInfo *)g_hash_table_lookup (coverage_hash, method);
-       mono_profiler_coverage_unlock ();
-
-       if (!info)
-               return;
-
-       header = mono_method_get_header_checked (method, &error);
-       mono_error_assert_ok (&error);
-       start = mono_method_header_get_code (header, &code_size, NULL);
-       debug_minfo = mono_debug_lookup_method (method);
-
-       end = start + code_size;
-       for (i = 0; i < info->entries; ++i) {
-               cil_code = info->data [i].cil_code;
-               if (cil_code && cil_code >= start && cil_code < end) {
-                       char *fname = NULL;
-                       offset = cil_code - start;
-                       entry.iloffset = offset;
-                       entry.method = method;
-                       entry.counter = info->data [i].count;
-                       entry.line = entry.col = 1;
-                       entry.filename = NULL;
-                       if (debug_minfo) {
-                               MonoDebugSourceLocation *location;
-
-                               location = mono_debug_method_lookup_location (debug_minfo, offset);
-                               if (location) {
-                                       entry.line = location->row;
-                                       entry.col = location->column;
-                                       entry.filename = fname = g_strdup (location->source_file);
-                                       mono_debug_free_source_location (location);
-                               }
-                       }
-
-                       func (prof, &entry);
-                       g_free (fname);
-               }
-       }
-       mono_metadata_free_mh (header);
+       return !!mono_profiler_state.sampling_owner;
 }
 
-typedef void (*ProfilerInitializer) (const char*);
-#define INITIALIZER_NAME "mono_profiler_startup"
-
-
-static gboolean
-load_profiler (MonoDl *pmodule, const char *desc, const char *symbol)
+void
+mono_profiler_sampling_thread_sleep (void)
 {
-       char *err;
-       ProfilerInitializer func;
+       mono_os_sem_wait (&mono_profiler_state.sampling_semaphore, MONO_SEM_FLAGS_NONE);
+}
 
-       if (!pmodule)
+mono_bool
+mono_profiler_enable_allocations (void)
+{
+       if (mono_profiler_state.startup_done)
                return FALSE;
 
-       if ((err = mono_dl_symbol (pmodule, symbol, (gpointer *) &func))) {
-               g_free (err);
-               return FALSE;
-       } else {
-               func (desc);
-       }
+       mono_profiler_state.allocations = TRUE;
+
        return TRUE;
 }
 
-static gboolean
-load_embedded_profiler (const char *desc, const char *name)
+void
+mono_profiler_set_call_instrumentation_filter_callback (MonoProfilerHandle handle, MonoProfilerCallInstrumentationFilterCallback cb)
 {
-       char *err = NULL;
-       char *symbol;
-       MonoDl *pmodule = NULL;
-       gboolean result;
-
-       /*
-        * Some profilers (such as ours) may need to call back into the runtime
-        * from their sampling callback (which is called in async-signal context).
-        * They need to be able to know that all references back to the runtime
-        * have been resolved; otherwise, calling runtime functions may result in
-        * invoking the dynamic linker which is not async-signal-safe. Passing
-        * MONO_DL_EAGER will ask the dynamic linker to resolve everything upfront.
-        */
-       pmodule = mono_dl_open (NULL, MONO_DL_EAGER, &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;
+       InterlockedWritePointer (&handle->call_instrumentation_filter, (gpointer) cb);
 }
 
-// TODO: Much of the library loading code here is custom. It would be better to merge this with mono-dl
-static gboolean
-load_profiler_from_directory (const char *directory, const char *libname, const char *desc)
+gboolean
+mono_profiler_should_instrument_method (MonoMethod *method, gboolean entry)
 {
-       MonoDl *pmodule = NULL;
-       char* path;
-       char *err;
-       void *iter;
+       MonoProfilerCallInstrumentationFlags flags = MONO_PROFILER_CALL_INSTRUMENTATION_NONE;
 
-       mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_DLLIMPORT, "Attempting to load profiler %s from %s (desc %s)", libname, directory, desc);
+       for (MonoProfilerHandle handle = mono_profiler_state.profilers; handle; handle = handle->next) {
+               MonoProfilerCallInstrumentationFilterCallback cb = handle->call_instrumentation_filter;
 
-       iter = NULL;
-       err = NULL;
-       while ((path = mono_dl_build_path (directory, libname, &iter))) {
-               pmodule = mono_dl_open (path, MONO_DL_EAGER, &err);
-               mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_DLLIMPORT, "Attempting to load profiler: %s, %ssuccessful, err: %s", path, pmodule?"":"not ", err);
-               g_free (path);
-               g_free (err);
-               if (pmodule)
-                       return load_profiler (pmodule, desc, INITIALIZER_NAME);
+               if (cb)
+                       flags |= cb (handle->prof, method);
        }
-               
-       return FALSE;
+
+       if (entry)
+               return flags & MONO_PROFILER_CALL_INSTRUMENTATION_PROLOGUE;
+       else
+               return flags & MONO_PROFILER_CALL_INSTRUMENTATION_EPILOGUE;
 }
 
-static gboolean
-load_profiler_from_mono_installation (const char *libname, const char *desc)
+void
+mono_profiler_started (void)
 {
-       char *err = NULL;
-       MonoDl *pmodule = mono_dl_open_runtime_lib (libname, MONO_DL_EAGER, &err);
-       mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_DLLIMPORT, "Attempting to load profiler from runtime libs: %s, %ssuccessful, err: %s", libname, pmodule?"":"not ", err);
-       g_free (err);
-       if (pmodule)
-               return load_profiler (pmodule, desc, INITIALIZER_NAME);
-       return FALSE;
+       mono_profiler_state.startup_done = TRUE;
 }
 
-/**
- * mono_profiler_load:
- * \param desc arguments to configure the profiler
- *
- * Invoke this method to initialize the profiler.   This will drive the
- * loading of the internal ("default") or any external profilers.
- *
- * This routine is invoked by Mono's driver, but must be called manually
- * if you embed Mono into your application.
- */
-void 
-mono_profiler_load (const char *desc)
+void
+mono_profiler_cleanup (void)
 {
-       char *cdesc = NULL;
-       mono_gc_base_init ();
-
-       if (!desc || (strcmp ("default", desc) == 0)) {
-               desc = "log:report";
+       for (MonoProfilerHandle handle = mono_profiler_state.profilers; handle; handle = handle->next) {
+#define _MONO_PROFILER_EVENT(name) \
+       mono_profiler_set_ ## name ## _callback (handle, NULL); \
+       g_assert (!handle->name ## _cb);
+#define MONO_PROFILER_EVENT_0(name, type) \
+       _MONO_PROFILER_EVENT(name)
+#define MONO_PROFILER_EVENT_1(name, type, arg1_type, arg1_name) \
+       _MONO_PROFILER_EVENT(name)
+#define MONO_PROFILER_EVENT_2(name, type, arg1_type, arg1_name, arg2_type, arg2_name) \
+       _MONO_PROFILER_EVENT(name)
+#define MONO_PROFILER_EVENT_3(name, type, arg1_type, arg1_name, arg2_type, arg2_name, arg3_type, arg3_name) \
+       _MONO_PROFILER_EVENT(name)
+#define MONO_PROFILER_EVENT_4(name, type, arg1_type, arg1_name, arg2_type, arg2_name, arg3_type, arg3_name, arg4_type, arg4_name) \
+       _MONO_PROFILER_EVENT(name)
+#include <mono/metadata/profiler-events.h>
+#undef MONO_PROFILER_EVENT_0
+#undef MONO_PROFILER_EVENT_1
+#undef MONO_PROFILER_EVENT_2
+#undef MONO_PROFILER_EVENT_3
+#undef MONO_PROFILER_EVENT_4
+#undef _MONO_PROFILER_EVENT
        }
-       /* 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);
-       }
-       {
-               const char* col = strchr (desc, ':');
-               char* libname;
-               char *mname;
-               gboolean res = FALSE;
-
-               if (col != NULL) {
-                       mname = (char *)g_memdup (desc, col - desc + 1);
-                       mname [col - desc] = 0;
-               } else {
-                       mname = g_strdup (desc);
-               }
-               if (!load_embedded_profiler (desc, mname)) {
-                       libname = g_strdup_printf ("mono-profiler-%s", mname);
-                       res = load_profiler_from_mono_installation (libname, desc);
-                       if (!res && mono_config_get_assemblies_dir ())
-                               res = load_profiler_from_directory (mono_assembly_getrootdir (), libname, desc);
-                       if (!res)
-                               res = load_profiler_from_directory (NULL, 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 (libname);
-               }
-               g_free (mname);
-       }
-       g_free (cdesc);
+
+#define _MONO_PROFILER_EVENT(name, type) \
+       g_assert (!mono_profiler_state.name ## _count);
+#define MONO_PROFILER_EVENT_0(name, type) \
+       _MONO_PROFILER_EVENT(name, type)
+#define MONO_PROFILER_EVENT_1(name, type, arg1_type, arg1_name) \
+       _MONO_PROFILER_EVENT(name, type)
+#define MONO_PROFILER_EVENT_2(name, type, arg1_type, arg1_name, arg2_type, arg2_name) \
+       _MONO_PROFILER_EVENT(name, type)
+#define MONO_PROFILER_EVENT_3(name, type, arg1_type, arg1_name, arg2_type, arg2_name, arg3_type, arg3_name) \
+       _MONO_PROFILER_EVENT(name, type)
+#define MONO_PROFILER_EVENT_4(name, type, arg1_type, arg1_name, arg2_type, arg2_name, arg3_type, arg3_name, arg4_type, arg4_name) \
+       _MONO_PROFILER_EVENT(name, type)
+#include <mono/metadata/profiler-events.h>
+#undef MONO_PROFILER_EVENT_0
+#undef MONO_PROFILER_EVENT_1
+#undef MONO_PROFILER_EVENT_2
+#undef MONO_PROFILER_EVENT_3
+#undef MONO_PROFILER_EVENT_4
+#undef _MONO_PROFILER_EVENT
 }
 
+static void
+update_callback (volatile gpointer *location, gpointer new_, volatile gint32 *counter)
+{
+       gpointer old;
+
+       do {
+               old = InterlockedReadPointer (location);
+       } while (InterlockedCompareExchangePointer (location, new_, old) != old);
+
+       /*
+        * At this point, we could have installed a NULL callback while the counter
+        * is still non-zero, i.e. setting the callback and modifying the counter
+        * is not a single atomic operation. This is fine as we make sure callbacks
+        * are non-NULL before invoking them (see the code below that generates the
+        * raise functions), and besides, updating callbacks at runtime is an
+        * inherently racy operation.
+        */
+
+       if (old)
+               InterlockedDecrement (counter);
+
+       if (new_)
+               InterlockedIncrement (counter);
+}
+
+#define _MONO_PROFILER_EVENT(name, type) \
+       void \
+       mono_profiler_set_ ## name ## _callback (MonoProfilerHandle handle, MonoProfiler ## type ## Callback cb) \
+       { \
+               update_callback (&handle->name ## _cb, (gpointer) cb, &mono_profiler_state.name ## _count); \
+       }
+#define MONO_PROFILER_EVENT_0(name, type) \
+       _MONO_PROFILER_EVENT(name, type)
+#define MONO_PROFILER_EVENT_1(name, type, arg1_type, arg1_name) \
+       _MONO_PROFILER_EVENT(name, type)
+#define MONO_PROFILER_EVENT_2(name, type, arg1_type, arg1_name, arg2_type, arg2_name) \
+       _MONO_PROFILER_EVENT(name, type)
+#define MONO_PROFILER_EVENT_3(name, type, arg1_type, arg1_name, arg2_type, arg2_name, arg3_type, arg3_name) \
+       _MONO_PROFILER_EVENT(name, type)
+#define MONO_PROFILER_EVENT_4(name, type, arg1_type, arg1_name, arg2_type, arg2_name, arg3_type, arg3_name, arg4_type, arg4_name) \
+       _MONO_PROFILER_EVENT(name, type)
+#include <mono/metadata/profiler-events.h>
+#undef MONO_PROFILER_EVENT_0
+#undef MONO_PROFILER_EVENT_1
+#undef MONO_PROFILER_EVENT_2
+#undef MONO_PROFILER_EVENT_3
+#undef MONO_PROFILER_EVENT_4
+#undef _MONO_PROFILER_EVENT
+
+#define _MONO_PROFILER_EVENT(name, type, params, args) \
+       void \
+       mono_profiler_raise_ ## name params \
+       { \
+               for (MonoProfilerHandle h = mono_profiler_state.profilers; h; h = h->next) { \
+                       MonoProfiler ## type ## Callback cb = h->name ## _cb; \
+                       if (cb) \
+                               cb args; \
+               } \
+       }
+#define MONO_PROFILER_EVENT_0(name, type) \
+       _MONO_PROFILER_EVENT(name, type, (void), (h->prof))
+#define MONO_PROFILER_EVENT_1(name, type, arg1_type, arg1_name) \
+       _MONO_PROFILER_EVENT(name, type, (arg1_type arg1_name), (h->prof, arg1_name))
+#define MONO_PROFILER_EVENT_2(name, type, arg1_type, arg1_name, arg2_type, arg2_name) \
+       _MONO_PROFILER_EVENT(name, type, (arg1_type arg1_name, arg2_type arg2_name), (h->prof, arg1_name, arg2_name))
+#define MONO_PROFILER_EVENT_3(name, type, arg1_type, arg1_name, arg2_type, arg2_name, arg3_type, arg3_name) \
+       _MONO_PROFILER_EVENT(name, type, (arg1_type arg1_name, arg2_type arg2_name, arg3_type arg3_name), (h->prof, arg1_name, arg2_name, arg3_name))
+#define MONO_PROFILER_EVENT_4(name, type, arg1_type, arg1_name, arg2_type, arg2_name, arg3_type, arg3_name, arg4_type, arg4_name) \
+       _MONO_PROFILER_EVENT(name, type, (arg1_type arg1_name, arg2_type arg2_name, arg3_type arg3_name, arg4_type arg4_name), (h->prof, arg1_name, arg2_name, arg3_name, arg4_name))
+#include <mono/metadata/profiler-events.h>
+#undef MONO_PROFILER_EVENT_0
+#undef MONO_PROFILER_EVENT_1
+#undef MONO_PROFILER_EVENT_2
+#undef MONO_PROFILER_EVENT_3
+#undef MONO_PROFILER_EVENT_4
+#undef _MONO_PROFILER_EVENT
index 81a98ca124c8a575ea27e10603b34ab3a38a983d..74a9e651ba4064d0a96ae22dc370f4d2b2268170 100644 (file)
-/**
- * \file
+/*
+ * Licensed to the .NET Foundation under one or more agreements.
+ * The .NET Foundation licenses this file to you under the MIT license.
+ * See the LICENSE file in the project root for more information.
  */
 
 #ifndef __MONO_PROFILER_H__
 #define __MONO_PROFILER_H__
 
-#include <mono/metadata/object.h>
 #include <mono/metadata/appdomain.h>
+#include <mono/metadata/mono-gc.h>
+#include <mono/metadata/object.h>
 
 MONO_BEGIN_DECLS
 
-#define MONO_PROFILER_MAX_STAT_CALL_CHAIN_DEPTH 128
+/*
+ * Loads a profiler module based on the specified description. The description
+ * can be of the form "name:args" or just "name". For example, "log:sample" and
+ * "log" will both load "libmono-profiler-log.so". The description is passed to
+ * the module after it has been loaded. If the specified module has already
+ * been loaded, this function has no effect.
+ *
+ * A module should declare an entry point like so:
+ *
+ * void mono_profiler_init (const char *desc)
+ * {
+ * }
+ *
+ * This function is not async safe.
+ */
+MONO_API void mono_profiler_load (const char *desc);
 
-typedef enum {
-       MONO_PROFILE_NONE = 0,
-       MONO_PROFILE_APPDOMAIN_EVENTS = 1 << 0,
-       MONO_PROFILE_ASSEMBLY_EVENTS  = 1 << 1,
-       MONO_PROFILE_MODULE_EVENTS    = 1 << 2,
-       MONO_PROFILE_CLASS_EVENTS     = 1 << 3,
-       MONO_PROFILE_JIT_COMPILATION  = 1 << 4,
-       MONO_PROFILE_INLINING         = 1 << 5,
-       MONO_PROFILE_EXCEPTIONS       = 1 << 6,
-       MONO_PROFILE_ALLOCATIONS      = 1 << 7,
-       MONO_PROFILE_GC               = 1 << 8,
-       MONO_PROFILE_THREADS          = 1 << 9,
-       MONO_PROFILE_REMOTING         = 1 << 10,
-       MONO_PROFILE_TRANSITIONS      = 1 << 11,
-       MONO_PROFILE_ENTER_LEAVE      = 1 << 12,
-       MONO_PROFILE_COVERAGE         = 1 << 13,
-       MONO_PROFILE_INS_COVERAGE     = 1 << 14,
-       MONO_PROFILE_STATISTICAL      = 1 << 15,
-       MONO_PROFILE_METHOD_EVENTS    = 1 << 16,
-       MONO_PROFILE_MONITOR_EVENTS   = 1 << 17,
-       MONO_PROFILE_IOMAP_EVENTS     = 1 << 18, /* this should likely be removed, too */
-       MONO_PROFILE_GC_MOVES         = 1 << 19,
-       MONO_PROFILE_GC_ROOTS         = 1 << 20,
-       MONO_PROFILE_CONTEXT_EVENTS   = 1 << 21,
-       MONO_PROFILE_GC_FINALIZATION  = 1 << 22
-} MonoProfileFlags;
+typedef struct _MonoProfiler MonoProfiler;
+typedef struct _MonoProfilerDesc *MonoProfilerHandle;
 
-typedef enum {
-       MONO_PROFILE_OK,
-       MONO_PROFILE_FAILED
-} MonoProfileResult;
+/*
+ * Installs a profiler and returns a handle for it. The handle is used with the
+ * other functions in the profiler API (e.g. for setting up callbacks).
+ *
+ * This function may only be called from your profiler's init function.
+ *
+ * Example usage:
+ *
+ * struct _MonoProfiler {
+ *     int my_stuff;
+ *     // ...
+ * };
+ *
+ * MonoProfiler *prof = calloc (1, sizeof (MonoProfiler));
+ * MonoProfilerHandle handle = mono_profiler_install (prof);
+ * mono_profiler_set_shutdown_callback (handle, my_shutdown_cb);
+ *
+ * This function is not async safe.
+ */
+MONO_API MonoProfilerHandle mono_profiler_install (MonoProfiler *prof);
 
-// Keep somewhat in sync with libgc/include/gc.h:enum GC_EventType
-typedef enum {
-       MONO_GC_EVENT_START,
-       MONO_GC_EVENT_MARK_START,
-       MONO_GC_EVENT_MARK_END,
-       MONO_GC_EVENT_RECLAIM_START,
-       MONO_GC_EVENT_RECLAIM_END,
-       MONO_GC_EVENT_END,
-       /*
-        * This is the actual arrival order of the following events:
-        *
-        * MONO_GC_EVENT_PRE_STOP_WORLD
-        * MONO_GC_EVENT_PRE_STOP_WORLD_LOCKED
-        * MONO_GC_EVENT_POST_STOP_WORLD
-        * MONO_GC_EVENT_PRE_START_WORLD
-        * MONO_GC_EVENT_POST_START_WORLD_UNLOCKED
-        * MONO_GC_EVENT_POST_START_WORLD
-        *
-        * The LOCKED and UNLOCKED events guarantee that, by the time they arrive,
-        * the GC and suspend locks will both have been acquired and released,
-        * respectively.
-        */
-       MONO_GC_EVENT_PRE_STOP_WORLD,
-       MONO_GC_EVENT_POST_STOP_WORLD,
-       MONO_GC_EVENT_PRE_START_WORLD,
-       MONO_GC_EVENT_POST_START_WORLD,
-       MONO_GC_EVENT_PRE_STOP_WORLD_LOCKED,
-       MONO_GC_EVENT_POST_START_WORLD_UNLOCKED
-} MonoGCEvent;
-
-/* coverage info */
-typedef struct {
-       MonoMethod *method;
-       int iloffset;
-       int counter;
-       const char *filename;
-       int line;
-       int col;
-} MonoProfileCoverageEntry;
-
-/* executable code buffer info */
-typedef enum {
-       MONO_PROFILER_CODE_BUFFER_UNKNOWN,
-       MONO_PROFILER_CODE_BUFFER_METHOD,
-       MONO_PROFILER_CODE_BUFFER_METHOD_TRAMPOLINE,
-       MONO_PROFILER_CODE_BUFFER_UNBOX_TRAMPOLINE,
-       MONO_PROFILER_CODE_BUFFER_IMT_TRAMPOLINE,
-       MONO_PROFILER_CODE_BUFFER_GENERICS_TRAMPOLINE,
-       MONO_PROFILER_CODE_BUFFER_SPECIFIC_TRAMPOLINE,
-       MONO_PROFILER_CODE_BUFFER_HELPER,
-       MONO_PROFILER_CODE_BUFFER_MONITOR,
-       MONO_PROFILER_CODE_BUFFER_DELEGATE_INVOKE,
-       MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING,
-       MONO_PROFILER_CODE_BUFFER_LAST
-} MonoProfilerCodeBufferType;
+typedef mono_bool (*MonoProfilerCoverageFilterCallback) (MonoProfiler *prof, MonoMethod *method);
 
-typedef struct _MonoProfiler MonoProfiler;
+/*
+ * Sets a code coverage filter function. The profiler API will invoke filter
+ * functions from all installed profilers. If any of them return TRUE, then the
+ * given method will be instrumented for coverage analysis. All filters are
+ * guaranteed to be called exactly once per method, even if an earlier filter
+ * has already returned TRUE.
+ *
+ * Note that filter functions must be installed before a method is compiled in
+ * order to have any effect, i.e. you should register your filter function in
+ * your profiler's init function.
+ *
+ * This function is async safe.
+ */
+MONO_API void mono_profiler_set_coverage_filter_callback (MonoProfilerHandle handle, MonoProfilerCoverageFilterCallback cb);
 
-typedef enum {
-       MONO_PROFILER_MONITOR_CONTENTION = 1,
-       MONO_PROFILER_MONITOR_DONE = 2,
-       MONO_PROFILER_MONITOR_FAIL = 3
-} MonoProfilerMonitorEvent;
+typedef struct {
+       MonoMethod *method;
+       uint32_t il_offset;
+       uint32_t counter;
+       const char *file_name;
+       uint32_t line;
+       uint32_t column;
+} MonoProfilerCoverageData;
 
-typedef enum {
-       MONO_PROFILER_CALL_CHAIN_NONE = 0,
-       MONO_PROFILER_CALL_CHAIN_NATIVE = 1,
-       MONO_PROFILER_CALL_CHAIN_GLIBC = 2,
-       MONO_PROFILER_CALL_CHAIN_MANAGED = 3,
-       MONO_PROFILER_CALL_CHAIN_INVALID = 4
-} MonoProfilerCallChainStrategy;
+typedef void (*MonoProfilerCoverageCallback) (MonoProfiler *prof, const MonoProfilerCoverageData *data);
 
-typedef enum {
-       MONO_PROFILER_GC_HANDLE_CREATED,
-       MONO_PROFILER_GC_HANDLE_DESTROYED
-} MonoProfileGCHandleEvent;
+/*
+ * Retrieves all coverage data for the specified method and invokes the given
+ * callback for each entry.
+ *
+ * This function is not async safe.
+ */
+MONO_API void mono_profiler_get_coverage_data (MonoProfilerHandle handle, MonoMethod *method, MonoProfilerCoverageCallback cb);
 
 typedef enum {
-       MONO_PROFILE_GC_ROOT_PINNING  = 1 << 8,
-       MONO_PROFILE_GC_ROOT_WEAKREF  = 2 << 8,
-       MONO_PROFILE_GC_ROOT_INTERIOR = 4 << 8,
-       /* the above are flags, the type is in the low 2 bytes */
-       MONO_PROFILE_GC_ROOT_STACK = 0,
-       MONO_PROFILE_GC_ROOT_FINALIZER = 1,
-       MONO_PROFILE_GC_ROOT_HANDLE = 2,
-       MONO_PROFILE_GC_ROOT_OTHER = 3,
-       MONO_PROFILE_GC_ROOT_MISC = 4, /* could be stack, handle, etc. */
-       MONO_PROFILE_GC_ROOT_TYPEMASK = 0xff
-} MonoProfileGCRootType;
+       /*
+        * Do not perform sampling. Will make the sampling thread sleep until the
+        * sampling mode is changed to one of the below modes.
+        */
+       MONO_PROFILER_SAMPLE_MODE_NONE = 0,
+       /*
+        * Try to base sampling frequency on process activity. Falls back to
+        * MONO_PROFILER_SAMPLE_MODE_REAL if such a clock is not available.
+        */
+       MONO_PROFILER_SAMPLE_MODE_PROCESS = 1,
+       /*
+        * Base sampling frequency on wall clock time. Uses a monotonic clock when
+        * available (all major platforms).
+        */
+       MONO_PROFILER_SAMPLE_MODE_REAL = 2,
+} MonoProfilerSampleMode;
 
 /*
- * Functions that the runtime will call on the profiler.
+ * Enables the sampling thread. You must call this function if you intend to use
+ * statistical sampling; mono_profiler_set_sample_mode will have no effect if
+ * this function has not been called. The first profiler to call this function
+ * will get ownership over sampling settings (mode and frequency) so that no
+ * other profiler can change those settings. Returns TRUE if the sampling
+ * thread was enabled, or FALSE if the function was called too late for this
+ * to be possible.
+ *
+ * Note that you still need to call mono_profiler_set_sample_mode with a mode
+ * other than MONO_PROFILER_SAMPLE_MODE_NONE to actually start sampling.
+ *
+ * This function may only be called from your profiler's init function.
+ *
+ * This function is not async safe.
  */
+MONO_API mono_bool mono_profiler_enable_sampling (MonoProfilerHandle handle);
 
-typedef void (*MonoProfileFunc) (MonoProfiler *prof);
+/*
+ * Sets the sampling mode and frequency (in Hz). If the calling profiler has
+ * ownership over sampling settings, the settings will be changed and this
+ * function will return TRUE; otherwise, it returns FALSE without changing any
+ * settings.
+ *
+ * This function is async safe.
+ */
+MONO_API mono_bool mono_profiler_set_sample_mode (MonoProfilerHandle handle, MonoProfilerSampleMode mode, uint64_t freq);
 
-typedef void (*MonoProfileAppDomainFunc) (MonoProfiler *prof, MonoDomain   *domain);
-typedef void (*MonoProfileContextFunc)   (MonoProfiler *prof, MonoAppContext *context);
-typedef void (*MonoProfileMethodFunc)   (MonoProfiler *prof, MonoMethod   *method);
-typedef void (*MonoProfileClassFunc)    (MonoProfiler *prof, MonoClass    *klass);
-typedef void (*MonoProfileModuleFunc)   (MonoProfiler *prof, MonoImage    *module);
-typedef void (*MonoProfileAssemblyFunc) (MonoProfiler *prof, MonoAssembly *assembly);
-typedef void (*MonoProfileMonitorFunc)  (MonoProfiler *prof, MonoObject *obj, MonoProfilerMonitorEvent event);
+/*
+ * Retrieves the current sampling mode and/or frequency (in Hz). Returns TRUE if
+ * the calling profiler is allowed to change the sampling settings; otherwise,
+ * FALSE.
+ *
+ * This function is async safe.
+ */
+MONO_API mono_bool mono_profiler_get_sample_mode (MonoProfilerHandle handle, MonoProfilerSampleMode *mode, uint64_t *freq);
 
-typedef void (*MonoProfileExceptionFunc) (MonoProfiler *prof, MonoObject *object);
-typedef void (*MonoProfileExceptionClauseFunc) (MonoProfiler *prof, MonoMethod *method, int clause_type, int clause_num);
-typedef void (*MonoProfileExceptionClauseFunc2) (MonoProfiler *prof, MonoMethod *method, int clause_type, int clause_num, MonoObject *exc);
+/*
+ * Enables instrumentation of GC allocations. This is necessary so that managed
+ * allocators can be instrumented with a call into the profiler API. Allocations
+ * will not be reported unless this function is called. Returns TRUE if
+ * allocation instrumentation was enabled, or FALSE if the function was called
+ * too late for this to be possible.
+ *
+ * This function may only be called from your profiler's init function.
+ *
+ * This function is not async safe.
+ */
+MONO_API mono_bool mono_profiler_enable_allocations (void);
 
-typedef void (*MonoProfileAppDomainResult)(MonoProfiler *prof, MonoDomain   *domain,   int result);
-typedef void (*MonoProfileAppDomainFriendlyNameFunc) (MonoProfiler *prof, MonoDomain *domain, const char *name);
-typedef void (*MonoProfileMethodResult)   (MonoProfiler *prof, MonoMethod   *method,   int result);
-typedef void (*MonoProfileJitResult)      (MonoProfiler *prof, MonoMethod   *method,   MonoJitInfo* jinfo,   int result);
-typedef void (*MonoProfileClassResult)    (MonoProfiler *prof, MonoClass    *klass,    int result);
-typedef void (*MonoProfileModuleResult)   (MonoProfiler *prof, MonoImage    *module,   int result);
-typedef void (*MonoProfileAssemblyResult) (MonoProfiler *prof, MonoAssembly *assembly, int result);
+typedef enum {
+       /* Do not instrument calls. */
+       MONO_PROFILER_CALL_INSTRUMENTATION_NONE = 1 << 0,
+       /* Instrument method prologues. */
+       MONO_PROFILER_CALL_INSTRUMENTATION_PROLOGUE = 1 << 1,
+       /* Instrument method epilogues. */
+       MONO_PROFILER_CALL_INSTRUMENTATION_EPILOGUE = 1 << 2,
+} MonoProfilerCallInstrumentationFlags;
 
-typedef void (*MonoProfileMethodInline)   (MonoProfiler *prof, MonoMethod   *parent, MonoMethod *child, int *ok);
+typedef MonoProfilerCallInstrumentationFlags (*MonoProfilerCallInstrumentationFilterCallback) (MonoProfiler *prof, MonoMethod *method);
 
-typedef void (*MonoProfileThreadFunc)     (MonoProfiler *prof, uintptr_t tid);
-typedef void (*MonoProfileThreadNameFunc) (MonoProfiler *prof, uintptr_t tid, const char *name);
-typedef void (*MonoProfileAllocFunc)      (MonoProfiler *prof, MonoObject *obj, MonoClass *klass);
-typedef void (*MonoProfileStatFunc)       (MonoProfiler *prof, mono_byte *ip, void *context);
-typedef void (*MonoProfileStatCallChainFunc) (MonoProfiler *prof, int call_chain_depth, mono_byte **ip, void *context);
-typedef void (*MonoProfileGCFunc)         (MonoProfiler *prof, MonoGCEvent event, int generation);
-typedef void (*MonoProfileGCMoveFunc)     (MonoProfiler *prof, void **objects, int num);
-typedef void (*MonoProfileGCResizeFunc)   (MonoProfiler *prof, int64_t new_size);
-typedef void (*MonoProfileGCHandleFunc)   (MonoProfiler *prof, int op, int type, uintptr_t handle, MonoObject *obj);
-typedef void (*MonoProfileGCRootFunc)     (MonoProfiler *prof, int num_roots, void **objects, int *root_types, uintptr_t *extra_info);
+/*
+ * Sets a call instrumentation filter function. The profiler API will invoke
+ * filter functions from all installed profilers. If any of them return flags
+ * other than MONO_PROFILER_CALL_INSTRUMENTATION_NONE, then the given method
+ * will be instrumented as requested. All filters are guaranteed to be called
+ * at least once (possibly more) per method entry and exit, even if earlier
+ * filters have already specified all flags.
+ *
+ * Note that filter functions must be installed before a method is compiled in
+ * order to have any effect, i.e. you should register your filter function in
+ * your profiler's init function.
+ *
+ * Keep in mind that method instrumentation is extremely heavy and will slow
+ * down most applications to a crawl. Consider using sampling instead if it
+ * would work for your use case.
+ *
+ * This function is async safe.
+ */
+MONO_API void mono_profiler_set_call_instrumentation_filter_callback (MonoProfilerHandle handle, MonoProfilerCallInstrumentationFilterCallback cb);
 
-typedef void (*MonoProfileGCFinalizeFunc)  (MonoProfiler *prof);
-typedef void (*MonoProfileGCFinalizeObjectFunc) (MonoProfiler *prof, MonoObject *obj);
+typedef enum {
+       /* Upper 2 bytes. */
+       MONO_PROFILER_GC_ROOT_PINNING = 1 << 8,
+       MONO_PROFILER_GC_ROOT_WEAKREF = 2 << 8,
+       MONO_PROFILER_GC_ROOT_INTERIOR = 4 << 8,
 
-typedef void (*MonoProfileIomapFunc) (MonoProfiler *prof, const char *report, const char *pathname, const char *new_pathname);
+       /* Lower 2 bytes (flags). */
+       MONO_PROFILER_GC_ROOT_STACK = 1 << 0,
+       MONO_PROFILER_GC_ROOT_FINALIZER = 1 << 1,
+       MONO_PROFILER_GC_ROOT_HANDLE = 1 << 2,
+       MONO_PROFILER_GC_ROOT_OTHER = 1 << 3,
+       MONO_PROFILER_GC_ROOT_MISC = 1 << 4,
 
-typedef mono_bool (*MonoProfileCoverageFilterFunc)   (MonoProfiler *prof, MonoMethod *method);
+       MONO_PROFILER_GC_ROOT_TYPEMASK = 0xff,
+} MonoProfilerGCRootType;
 
-typedef void (*MonoProfileCoverageFunc)   (MonoProfiler *prof, const MonoProfileCoverageEntry *entry);
+typedef enum {
+       /* data = MonoMethod *method */
+       MONO_PROFILER_CODE_BUFFER_METHOD = 0,
+       MONO_PROFILER_CODE_BUFFER_METHOD_TRAMPOLINE = 1,
+       MONO_PROFILER_CODE_BUFFER_UNBOX_TRAMPOLINE = 2,
+       MONO_PROFILER_CODE_BUFFER_IMT_TRAMPOLINE = 3,
+       MONO_PROFILER_CODE_BUFFER_GENERICS_TRAMPOLINE = 4,
+       /* data = const char *name */
+       MONO_PROFILER_CODE_BUFFER_SPECIFIC_TRAMPOLINE = 5,
+       MONO_PROFILER_CODE_BUFFER_HELPER = 6,
+       MONO_PROFILER_CODE_BUFFER_MONITOR = 7,
+       MONO_PROFILER_CODE_BUFFER_DELEGATE_INVOKE = 8,
+       MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING = 9,
+} MonoProfilerCodeBufferType;
 
-typedef void (*MonoProfilerCodeChunkNew) (MonoProfiler *prof, void* chunk, int size);
-typedef void (*MonoProfilerCodeChunkDestroy) (MonoProfiler *prof, void* chunk);
-typedef void (*MonoProfilerCodeBufferNew) (MonoProfiler *prof, void* buffer, int size, MonoProfilerCodeBufferType type, void *data);
+// Keep somewhat in sync with libgc/include/gc.h : GC_EventType.
+typedef enum {
+       MONO_GC_EVENT_START = 0,
+       MONO_GC_EVENT_MARK_START = 1,
+       MONO_GC_EVENT_MARK_END = 2,
+       MONO_GC_EVENT_RECLAIM_START = 3,
+       MONO_GC_EVENT_RECLAIM_END = 4,
+       MONO_GC_EVENT_END = 5,
+       MONO_GC_EVENT_PRE_STOP_WORLD = 6,
+       /* When this event arrives, the GC and suspend locks are acquired. */
+       MONO_GC_EVENT_PRE_STOP_WORLD_LOCKED = 10,
+       MONO_GC_EVENT_POST_STOP_WORLD = 7,
+       MONO_GC_EVENT_PRE_START_WORLD = 8,
+       /* When this event arrives, the GC and suspend locks are released. */
+       MONO_GC_EVENT_POST_START_WORLD_UNLOCKED = 11,
+       MONO_GC_EVENT_POST_START_WORLD = 9,
+} MonoProfilerGCEvent;
 
 /*
- * Function the profiler may call.
+ * The macros below will generate the majority of the callback API. Refer to
+ * mono/metadata/profiler-events.h for a list of callbacks. They are expanded
+ * like so:
+ *
+ * typedef void (*MonoProfilerRuntimeInitializedCallback (MonoProfiler *prof);
+ * MONO_API void mono_profiler_set_runtime_initialized_callback (MonoProfiler *prof, MonoProfilerRuntimeInitializedCallback cb);
+ *
+ * typedef void (*MonoProfilerRuntimeShutdownCallback (MonoProfiler *prof);
+ * MONO_API void mono_profiler_set_runtime_shutdown_callback (MonoProfiler *prof, MonoProfilerRuntimeShutdownCallback cb);
+ *
+ * typedef void (*MonoProfilerContextLoadedCallback (MonoProfiler *prof);
+ * MONO_API void mono_profiler_set_context_loaded_callback (MonoProfiler *prof, MonoProfilerContextLoadedCallback cb);
+ *
+ * typedef void (*MonoProfilerContextUnloadedCallback (MonoProfiler *prof);
+ * MONO_API void mono_profiler_set_context_unloaded_callback (MonoProfiler *prof, MonoProfilerContextUnloadedCallback cb);
+ *
+ * Etc.
+ *
+ * To remove a callback, pass NULL instead of a valid function pointer.
+ * Callbacks can be changed at any point, but note that doing so is inherently
+ * racy with respect to threads that aren't suspended, i.e. you may still see a
+ * call from another thread right after you change a callback.
+ *
+ * These functions are async safe.
  */
-MONO_API void mono_profiler_install       (MonoProfiler *prof, MonoProfileFunc shutdown_callback);
-MONO_API void mono_profiler_set_events    (MonoProfileFlags events);
-
-MONO_API MonoProfileFlags mono_profiler_get_events (void);
-
-MONO_API void mono_profiler_install_appdomain   (MonoProfileAppDomainFunc start_load, MonoProfileAppDomainResult end_load,
-                                        MonoProfileAppDomainFunc start_unload, MonoProfileAppDomainFunc end_unload);
-MONO_API void mono_profiler_install_appdomain_name (MonoProfileAppDomainFriendlyNameFunc domain_name_cb);
-MONO_API void mono_profiler_install_context     (MonoProfileContextFunc load, MonoProfileContextFunc unload);
-MONO_API void mono_profiler_install_assembly    (MonoProfileAssemblyFunc start_load, MonoProfileAssemblyResult end_load,
-                                        MonoProfileAssemblyFunc start_unload, MonoProfileAssemblyFunc end_unload);
-MONO_API void mono_profiler_install_module      (MonoProfileModuleFunc start_load, MonoProfileModuleResult end_load,
-                                        MonoProfileModuleFunc start_unload, MonoProfileModuleFunc end_unload);
-MONO_API void mono_profiler_install_class       (MonoProfileClassFunc start_load, MonoProfileClassResult end_load,
-                                        MonoProfileClassFunc start_unload, MonoProfileClassFunc end_unload);
-
-MONO_API void mono_profiler_install_jit_compile (MonoProfileMethodFunc start, MonoProfileMethodResult end);
-MONO_API void mono_profiler_install_jit_end (MonoProfileJitResult end);
-MONO_API void mono_profiler_install_method_free (MonoProfileMethodFunc callback);
-MONO_API void mono_profiler_install_method_invoke (MonoProfileMethodFunc start, MonoProfileMethodFunc end);
-MONO_API void mono_profiler_install_enter_leave (MonoProfileMethodFunc enter, MonoProfileMethodFunc fleave);
-MONO_API void mono_profiler_install_thread      (MonoProfileThreadFunc start, MonoProfileThreadFunc end);
-MONO_API void mono_profiler_install_thread_name (MonoProfileThreadNameFunc thread_name_cb);
-MONO_API void mono_profiler_install_transition  (MonoProfileMethodResult callback);
-MONO_API void mono_profiler_install_allocation  (MonoProfileAllocFunc callback);
-MONO_API void mono_profiler_install_monitor     (MonoProfileMonitorFunc callback);
-MONO_API void mono_profiler_install_statistical (MonoProfileStatFunc callback);
-MONO_API void mono_profiler_install_statistical_call_chain (MonoProfileStatCallChainFunc callback, int call_chain_depth, MonoProfilerCallChainStrategy call_chain_strategy);
-MONO_API void mono_profiler_install_exception   (MonoProfileExceptionFunc throw_callback, MonoProfileMethodFunc exc_method_leave, MonoProfileExceptionClauseFunc clause_callback);
-MONO_API void mono_profiler_install_exception_clause (MonoProfileExceptionClauseFunc2 clause_callback);
-MONO_API void mono_profiler_install_coverage_filter (MonoProfileCoverageFilterFunc callback);
-MONO_API void mono_profiler_coverage_get  (MonoProfiler *prof, MonoMethod *method, MonoProfileCoverageFunc func);
-MONO_API void mono_profiler_install_gc    (MonoProfileGCFunc callback, MonoProfileGCResizeFunc heap_resize_callback);
-MONO_API void mono_profiler_install_gc_moves    (MonoProfileGCMoveFunc callback);
-MONO_API void mono_profiler_install_gc_roots    (MonoProfileGCHandleFunc handle_callback, MonoProfileGCRootFunc roots_callback);
-MONO_API void mono_profiler_install_gc_finalize (MonoProfileGCFinalizeFunc begin, MonoProfileGCFinalizeObjectFunc begin_obj, MonoProfileGCFinalizeObjectFunc end_obj, MonoProfileGCFinalizeFunc end);
-MONO_API void mono_profiler_install_runtime_initialized (MonoProfileFunc runtime_initialized_callback);
-
-MONO_API void mono_profiler_install_code_chunk_new (MonoProfilerCodeChunkNew callback);
-MONO_API void mono_profiler_install_code_chunk_destroy (MonoProfilerCodeChunkDestroy callback);
-MONO_API void mono_profiler_install_code_buffer_new (MonoProfilerCodeBufferNew callback);
-
-MONO_API void mono_profiler_install_iomap (MonoProfileIomapFunc callback);
-
-MONO_API void mono_profiler_load             (const char *desc);
 
-typedef enum {
-       /* Elapsed time is tracked by user+kernel time of the process - this is the default*/
-       MONO_PROFILER_STAT_MODE_PROCESS = 0,
-       /* Elapsed time is tracked by wallclock time */
-       MONO_PROFILER_STAT_MODE_REAL = 1,
-} MonoProfileSamplingMode;
-
-MONO_API void mono_profiler_set_statistical_mode (MonoProfileSamplingMode mode, int64_t sampling_frequency_hz);
+#define _MONO_PROFILER_EVENT(type, ...) \
+       typedef void (*MonoProfiler ## type ## Callback) (__VA_ARGS__);
+#define MONO_PROFILER_EVENT_0(name, type) \
+               _MONO_PROFILER_EVENT(type, MonoProfiler *prof)
+#define MONO_PROFILER_EVENT_1(name, type, arg1_type, arg1_name) \
+               _MONO_PROFILER_EVENT(type, MonoProfiler *prof, arg1_type arg1_name)
+#define MONO_PROFILER_EVENT_2(name, type, arg1_type, arg1_name, arg2_type, arg2_name) \
+               _MONO_PROFILER_EVENT(type, MonoProfiler *prof, arg1_type arg1_name, arg2_type arg2_name)
+#define MONO_PROFILER_EVENT_3(name, type, arg1_type, arg1_name, arg2_type, arg2_name, arg3_type, arg3_name) \
+               _MONO_PROFILER_EVENT(type, MonoProfiler *prof, arg1_type arg1_name, arg2_type arg2_name, arg3_type arg3_name)
+#define MONO_PROFILER_EVENT_4(name, type, arg1_type, arg1_name, arg2_type, arg2_name, arg3_type, arg3_name, arg4_type, arg4_name) \
+               _MONO_PROFILER_EVENT(type, MonoProfiler *prof, arg1_type arg1_name, arg2_type arg2_name, arg3_type arg3_name, arg4_type arg4_name)
+#include <mono/metadata/profiler-events.h>
+#undef MONO_PROFILER_EVENT_0
+#undef MONO_PROFILER_EVENT_1
+#undef MONO_PROFILER_EVENT_2
+#undef MONO_PROFILER_EVENT_3
+#undef MONO_PROFILER_EVENT_4
+#undef _MONO_PROFILER_EVENT
+
+#define _MONO_PROFILER_EVENT(name, type) \
+       MONO_API void mono_profiler_set_ ## name ## _callback (MonoProfilerHandle handle, MonoProfiler ## type ## Callback cb);
+#define MONO_PROFILER_EVENT_0(name, type) \
+       _MONO_PROFILER_EVENT(name, type)
+#define MONO_PROFILER_EVENT_1(name, type, arg1_type, arg1_name) \
+       _MONO_PROFILER_EVENT(name, type)
+#define MONO_PROFILER_EVENT_2(name, type, arg1_type, arg1_name, arg2_type, arg2_name) \
+       _MONO_PROFILER_EVENT(name, type)
+#define MONO_PROFILER_EVENT_3(name, type, arg1_type, arg1_name, arg2_type, arg2_name, arg3_type, arg3_name) \
+       _MONO_PROFILER_EVENT(name, type)
+#define MONO_PROFILER_EVENT_4(name, type, arg1_type, arg1_name, arg2_type, arg2_name, arg3_type, arg3_name, arg4_type, arg4_name) \
+       _MONO_PROFILER_EVENT(name, type)
+#include <mono/metadata/profiler-events.h>
+#undef MONO_PROFILER_EVENT_0
+#undef MONO_PROFILER_EVENT_1
+#undef MONO_PROFILER_EVENT_2
+#undef MONO_PROFILER_EVENT_3
+#undef MONO_PROFILER_EVENT_4
+#undef _MONO_PROFILER_EVENT
 
 MONO_END_DECLS
 
-#endif /* __MONO_PROFILER_H__ */
-
+#endif // __MONO_PROFILER_H__
index 78c0126396cb308433c982290abedba0ba81b93a..d9a483898e7886b2739973aa57a8745b725d921b 100644 (file)
@@ -198,7 +198,7 @@ sgen_client_update_copied_object (char *destination, GCVTable gc_vtable, void *o
                SGEN_LOG (9, "Array instance %p: size: %lu, rank: %d, length: %lu", array, (unsigned long)objsize, vt->rank, (unsigned long)mono_array_length (array));
        }
 
-       if (G_UNLIKELY (mono_profiler_events & MONO_PROFILE_GC_MOVES))
+       if (MONO_PROFILER_ENABLED (gc_moves))
                mono_sgen_register_moved_object (obj, destination);
 }
 
@@ -293,7 +293,7 @@ sgen_client_binary_protocol_collection_begin (int minor_gc_count, int generation
 {
        MONO_GC_BEGIN (generation);
 
-       mono_profiler_gc_event (MONO_GC_EVENT_START, generation);
+       MONO_PROFILER_RAISE (gc_event, (MONO_GC_EVENT_START, generation));
 
 #ifndef DISABLE_PERFCOUNTERS
        if (generation == GENERATION_NURSERY)
@@ -308,7 +308,7 @@ sgen_client_binary_protocol_collection_end (int minor_gc_count, int generation,
 {
        MONO_GC_END (generation);
 
-       mono_profiler_gc_event (MONO_GC_EVENT_END, generation);
+       MONO_PROFILER_RAISE (gc_event, (MONO_GC_EVENT_END, generation));
 }
 
 static void G_GNUC_UNUSED
@@ -383,25 +383,25 @@ sgen_client_binary_protocol_block_set_state (gpointer addr, size_t size, int old
 static void G_GNUC_UNUSED
 sgen_client_binary_protocol_mark_start (int generation)
 {
-       mono_profiler_gc_event (MONO_GC_EVENT_MARK_START, generation);
+       MONO_PROFILER_RAISE (gc_event, (MONO_GC_EVENT_MARK_START, generation));
 }
 
 static void G_GNUC_UNUSED
 sgen_client_binary_protocol_mark_end (int generation)
 {
-       mono_profiler_gc_event (MONO_GC_EVENT_MARK_END, generation);
+       MONO_PROFILER_RAISE (gc_event, (MONO_GC_EVENT_MARK_END, generation));
 }
 
 static void G_GNUC_UNUSED
 sgen_client_binary_protocol_reclaim_start (int generation)
 {
-       mono_profiler_gc_event (MONO_GC_EVENT_RECLAIM_START, generation);
+       MONO_PROFILER_RAISE (gc_event, (MONO_GC_EVENT_RECLAIM_START, generation));
 }
 
 static void G_GNUC_UNUSED
 sgen_client_binary_protocol_reclaim_end (int generation)
 {
-       mono_profiler_gc_event (MONO_GC_EVENT_RECLAIM_END, generation);
+       MONO_PROFILER_RAISE (gc_event, (MONO_GC_EVENT_RECLAIM_END, generation));
 }
 
 static void
index 99f6100e36bb462136cdd79999dc38f22651e3f8..93bdb1fb5c7e8de8bc64d1af3de5846da6786b27 100644 (file)
@@ -946,10 +946,8 @@ mono_gc_alloc_obj (MonoVTable *vtable, size_t size)
 {
        MonoObject *obj = sgen_alloc_obj (vtable, size);
 
-       if (G_UNLIKELY (mono_profiler_events & MONO_PROFILE_ALLOCATIONS)) {
-               if (obj)
-                       mono_profiler_allocation (obj);
-       }
+       if (G_UNLIKELY (mono_profiler_allocations_enabled ()) && obj)
+               MONO_PROFILER_RAISE (gc_allocation, (obj));
 
        return obj;
 }
@@ -959,10 +957,8 @@ mono_gc_alloc_pinned_obj (MonoVTable *vtable, size_t size)
 {
        MonoObject *obj = sgen_alloc_obj_pinned (vtable, size);
 
-       if (G_UNLIKELY (mono_profiler_events & MONO_PROFILE_ALLOCATIONS)) {
-               if (obj)
-                       mono_profiler_allocation (obj);
-       }
+       if (G_UNLIKELY (mono_profiler_allocations_enabled ()) && obj)
+               MONO_PROFILER_RAISE (gc_allocation, (obj));
 
        return obj;
 }
@@ -972,10 +968,8 @@ mono_gc_alloc_mature (MonoVTable *vtable, size_t size)
 {
        MonoObject *obj = sgen_alloc_obj_mature (vtable, size);
 
-       if (G_UNLIKELY (mono_profiler_events & MONO_PROFILE_ALLOCATIONS)) {
-               if (obj)
-                       mono_profiler_allocation (obj);
-       }
+       if (G_UNLIKELY (mono_profiler_allocations_enabled ()) && obj)
+               MONO_PROFILER_RAISE (gc_allocation, (obj));
 
        return obj;
 }
@@ -1013,6 +1007,7 @@ mono_gc_free_fixed (void* addr)
 
 static MonoMethod* alloc_method_cache [ATYPE_NUM];
 static MonoMethod* slowpath_alloc_method_cache [ATYPE_NUM];
+static MonoMethod* profiler_alloc_method_cache [ATYPE_NUM];
 static gboolean use_managed_allocator = TRUE;
 
 #ifdef MANAGED_ALLOCATION
@@ -1059,6 +1054,7 @@ create_allocator (int atype, ManagedAllocatorVariant variant)
 {
        int p_var, size_var, real_size_var, thread_var G_GNUC_UNUSED;
        gboolean slowpath = variant == MANAGED_ALLOCATOR_SLOW_PATH;
+       gboolean profiler = variant == MANAGED_ALLOCATOR_PROFILER;
        guint32 fastpath_branch, max_size_branch, no_oom_branch;
        MonoMethodBuilder *mb;
        MonoMethod *res;
@@ -1073,17 +1069,18 @@ create_allocator (int atype, ManagedAllocatorVariant variant)
                mono_register_jit_icall (mono_gc_alloc_obj, "mono_gc_alloc_obj", mono_create_icall_signature ("object ptr int"), FALSE);
                mono_register_jit_icall (mono_gc_alloc_vector, "mono_gc_alloc_vector", mono_create_icall_signature ("object ptr int int"), FALSE);
                mono_register_jit_icall (mono_gc_alloc_string, "mono_gc_alloc_string", mono_create_icall_signature ("object ptr int int32"), FALSE);
+               mono_register_jit_icall (mono_profiler_raise_gc_allocation, "mono_profiler_raise_gc_allocation", mono_create_icall_signature ("void object"), FALSE);
                registered = TRUE;
        }
 
        if (atype == ATYPE_SMALL) {
-               name = slowpath ? "SlowAllocSmall" : "AllocSmall";
+               name = slowpath ? "SlowAllocSmall" : (profiler ? "ProfilerAllocSmall" : "AllocSmall");
        } else if (atype == ATYPE_NORMAL) {
-               name = slowpath ? "SlowAlloc" : "Alloc";
+               name = slowpath ? "SlowAlloc" : (profiler ? "ProfilerAlloc" : "Alloc");
        } else if (atype == ATYPE_VECTOR) {
-               name = slowpath ? "SlowAllocVector" : "AllocVector";
+               name = slowpath ? "SlowAllocVector" : (profiler ? "ProfilerAllocVector" : "AllocVector");
        } else if (atype == ATYPE_STRING) {
-               name = slowpath ? "SlowAllocString" : "AllocString";
+               name = slowpath ? "SlowAllocString" : (profiler ? "ProfilerAllocString" : "AllocString");
        } else {
                g_assert_not_reached ();
        }
@@ -1434,6 +1431,32 @@ create_allocator (int atype, ManagedAllocatorVariant variant)
        mono_mb_emit_ldloc (mb, p_var);
 
  done:
+
+       /*
+        * It's important that we do this outside of the critical region as we
+        * will be invoking arbitrary code.
+        */
+       if (profiler) {
+               /*
+                * if (G_UNLIKELY (*&mono_profiler_state.gc_allocation_count)) {
+                *      mono_profiler_raise_gc_allocation (p);
+                * }
+                */
+
+               mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
+               mono_mb_emit_byte (mb, CEE_MONO_LDPTR_PROFILER_ALLOCATION_COUNT);
+               mono_mb_emit_byte (mb, CEE_LDIND_U4);
+
+               int prof_br = mono_mb_emit_short_branch (mb, CEE_BRFALSE_S);
+
+               mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
+               mono_mb_emit_byte (mb, CEE_MONO_NOT_TAKEN);
+               mono_mb_emit_byte (mb, CEE_DUP);
+               mono_mb_emit_icall (mb, mono_profiler_raise_gc_allocation);
+
+               mono_mb_patch_short_branch (mb, prof_br);
+       }
+
        mono_mb_emit_byte (mb, CEE_RET);
 #endif
 
@@ -1468,6 +1491,9 @@ MonoMethod*
 mono_gc_get_managed_allocator (MonoClass *klass, gboolean for_box, gboolean known_instance_size)
 {
 #ifdef MANAGED_ALLOCATION
+       ManagedAllocatorVariant variant = mono_profiler_allocations_enabled () ?
+               MANAGED_ALLOCATOR_PROFILER : MANAGED_ALLOCATOR_REGULAR;
+
        if (collect_before_allocs)
                return NULL;
        if (klass->instance_size > tlab_size)
@@ -1478,15 +1504,13 @@ mono_gc_get_managed_allocator (MonoClass *klass, gboolean for_box, gboolean know
                return NULL;
        if (klass->rank)
                return NULL;
-       if (mono_profiler_get_events () & MONO_PROFILE_ALLOCATIONS)
-               return NULL;
        if (klass->byval_arg.type == MONO_TYPE_STRING)
-               return mono_gc_get_managed_allocator_by_type (ATYPE_STRING, MANAGED_ALLOCATOR_REGULAR);
+               return mono_gc_get_managed_allocator_by_type (ATYPE_STRING, variant);
        /* Generic classes have dynamic field and can go above MAX_SMALL_OBJ_SIZE. */
        if (known_instance_size)
-               return mono_gc_get_managed_allocator_by_type (ATYPE_SMALL, MANAGED_ALLOCATOR_REGULAR);
+               return mono_gc_get_managed_allocator_by_type (ATYPE_SMALL, variant);
        else
-               return mono_gc_get_managed_allocator_by_type (ATYPE_NORMAL, MANAGED_ALLOCATOR_REGULAR);
+               return mono_gc_get_managed_allocator_by_type (ATYPE_NORMAL, variant);
 #else
        return NULL;
 #endif
@@ -1498,13 +1522,12 @@ mono_gc_get_managed_array_allocator (MonoClass *klass)
 #ifdef MANAGED_ALLOCATION
        if (klass->rank != 1)
                return NULL;
-       if (mono_profiler_get_events () & MONO_PROFILE_ALLOCATIONS)
-               return NULL;
        if (has_per_allocation_action)
                return NULL;
        g_assert (!mono_class_has_finalizer (klass) && !mono_class_is_marshalbyref (klass));
 
-       return mono_gc_get_managed_allocator_by_type (ATYPE_VECTOR, MANAGED_ALLOCATOR_REGULAR);
+       return mono_gc_get_managed_allocator_by_type (ATYPE_VECTOR, mono_profiler_allocations_enabled () ?
+               MANAGED_ALLOCATOR_PROFILER : MANAGED_ALLOCATOR_REGULAR);
 #else
        return NULL;
 #endif
@@ -1523,12 +1546,13 @@ mono_gc_get_managed_allocator_by_type (int atype, ManagedAllocatorVariant varian
        MonoMethod *res;
        MonoMethod **cache;
 
-       if (variant == MANAGED_ALLOCATOR_REGULAR && !use_managed_allocator)
+       if (variant != MANAGED_ALLOCATOR_SLOW_PATH && !use_managed_allocator)
                return NULL;
 
        switch (variant) {
        case MANAGED_ALLOCATOR_REGULAR: cache = alloc_method_cache; break;
        case MANAGED_ALLOCATOR_SLOW_PATH: cache = slowpath_alloc_method_cache; break;
+       case MANAGED_ALLOCATOR_PROFILER: cache = profiler_alloc_method_cache; break;
        default: g_assert_not_reached (); break;
        }
 
@@ -1565,7 +1589,7 @@ sgen_is_managed_allocator (MonoMethod *method)
        int i;
 
        for (i = 0; i < ATYPE_NUM; ++i)
-               if (method == alloc_method_cache [i] || method == slowpath_alloc_method_cache [i])
+               if (method == alloc_method_cache [i] || method == slowpath_alloc_method_cache [i] || method == profiler_alloc_method_cache [i])
                        return TRUE;
        return FALSE;
 }
@@ -1576,7 +1600,7 @@ sgen_has_managed_allocator (void)
        int i;
 
        for (i = 0; i < ATYPE_NUM; ++i)
-               if (alloc_method_cache [i] || slowpath_alloc_method_cache [i])
+               if (alloc_method_cache [i] || slowpath_alloc_method_cache [i] || profiler_alloc_method_cache [i])
                        return TRUE;
        return FALSE;
 }
@@ -1727,8 +1751,8 @@ mono_gc_alloc_vector (MonoVTable *vtable, size_t size, uintptr_t max_length)
        UNLOCK_GC;
 
  done:
-       if (G_UNLIKELY (mono_profiler_events & MONO_PROFILE_ALLOCATIONS))
-               mono_profiler_allocation (&arr->obj);
+       if (G_UNLIKELY (mono_profiler_allocations_enabled ()))
+               MONO_PROFILER_RAISE (gc_allocation, (&arr->obj));
 
        SGEN_ASSERT (6, SGEN_ALIGN_UP (size) == SGEN_ALIGN_UP (sgen_client_par_object_get_size (vtable, (GCObject*)arr)), "Vector has incorrect size.");
        return arr;
@@ -1775,8 +1799,8 @@ mono_gc_alloc_array (MonoVTable *vtable, size_t size, uintptr_t max_length, uint
        UNLOCK_GC;
 
  done:
-       if (G_UNLIKELY (mono_profiler_events & MONO_PROFILE_ALLOCATIONS))
-               mono_profiler_allocation (&arr->obj);
+       if (G_UNLIKELY (mono_profiler_allocations_enabled ()))
+               MONO_PROFILER_RAISE (gc_allocation, (&arr->obj));
 
        SGEN_ASSERT (6, SGEN_ALIGN_UP (size) == SGEN_ALIGN_UP (sgen_client_par_object_get_size (vtable, (GCObject*)arr)), "Array has incorrect size.");
        return arr;
@@ -1816,8 +1840,8 @@ mono_gc_alloc_string (MonoVTable *vtable, size_t size, gint32 len)
        UNLOCK_GC;
 
  done:
-       if (G_UNLIKELY (mono_profiler_events & MONO_PROFILE_ALLOCATIONS))
-               mono_profiler_allocation (&str->object);
+       if (G_UNLIKELY (mono_profiler_allocations_enabled ()))
+               MONO_PROFILER_RAISE (gc_allocation, (&str->object));
 
        return str;
 }
@@ -1862,7 +1886,7 @@ notify_gc_roots (GCRootReport *report)
 {
        if (!report->count)
                return;
-       mono_profiler_gc_roots (report->count, report->objects, report->root_types, report->extra_info);
+       MONO_PROFILER_RAISE (gc_roots, ((MonoObject **) report->objects, (MonoProfilerGCRootType *) report->root_types, report->extra_info, report->count));
        report->count = 0;
 }
 
@@ -1879,12 +1903,12 @@ add_profile_gc_root (GCRootReport *report, void *object, int rtype, uintptr_t ex
 void
 sgen_client_nursery_objects_pinned (void **definitely_pinned, int count)
 {
-       if (mono_profiler_get_events () & MONO_PROFILE_GC_ROOTS) {
+       if (MONO_PROFILER_ENABLED (gc_roots)) {
                GCRootReport report;
                int idx;
                report.count = 0;
                for (idx = 0; idx < count; ++idx)
-                       add_profile_gc_root (&report, definitely_pinned [idx], MONO_PROFILE_GC_ROOT_PINNING | MONO_PROFILE_GC_ROOT_MISC, 0);
+                       add_profile_gc_root (&report, definitely_pinned [idx], MONO_PROFILER_GC_ROOT_PINNING | MONO_PROFILER_GC_ROOT_MISC, 0);
                notify_gc_roots (&report);
        }
 }
@@ -1900,7 +1924,7 @@ report_finalizer_roots_from_queue (SgenPointerQueue *queue)
                void *obj = queue->data [i];
                if (!obj)
                        continue;
-               add_profile_gc_root (&report, obj, MONO_PROFILE_GC_ROOT_FINALIZER, 0);
+               add_profile_gc_root (&report, obj, MONO_PROFILER_GC_ROOT_FINALIZER, 0);
        }
        notify_gc_roots (&report);
 }
@@ -1918,7 +1942,7 @@ static void
 single_arg_report_root (MonoObject **obj, void *gc_data)
 {
        if (*obj)
-               add_profile_gc_root (root_report, *obj, MONO_PROFILE_GC_ROOT_OTHER, 0);
+               add_profile_gc_root (root_report, *obj, MONO_PROFILER_GC_ROOT_OTHER, 0);
 }
 
 static void
@@ -1929,7 +1953,7 @@ precisely_report_roots_from (GCRootReport *report, void** start_root, void** end
                desc >>= ROOT_DESC_TYPE_SHIFT;
                while (desc) {
                        if ((desc & 1) && *start_root) {
-                               add_profile_gc_root (report, *start_root, MONO_PROFILE_GC_ROOT_OTHER, 0);
+                               add_profile_gc_root (report, *start_root, MONO_PROFILER_GC_ROOT_OTHER, 0);
                        }
                        desc >>= 1;
                        start_root++;
@@ -1945,7 +1969,7 @@ precisely_report_roots_from (GCRootReport *report, void** start_root, void** end
                        void **objptr = start_run;
                        while (bmap) {
                                if ((bmap & 1) && *objptr) {
-                                       add_profile_gc_root (report, *objptr, MONO_PROFILE_GC_ROOT_OTHER, 0);
+                                       add_profile_gc_root (report, *objptr, MONO_PROFILER_GC_ROOT_OTHER, 0);
                                }
                                bmap >>= 1;
                                ++objptr;
@@ -1959,7 +1983,7 @@ precisely_report_roots_from (GCRootReport *report, void** start_root, void** end
 
                for (p = start_root; p < end_root; p++) {
                        if (*p)
-                               add_profile_gc_root (report, *p, MONO_PROFILE_GC_ROOT_OTHER, 0);
+                               add_profile_gc_root (report, *p, MONO_PROFILER_GC_ROOT_OTHER, 0);
                }
                break;
        }
@@ -2000,9 +2024,10 @@ report_registered_roots (void)
 void
 sgen_client_collecting_minor (SgenPointerQueue *fin_ready_queue, SgenPointerQueue *critical_fin_queue)
 {
-       if (mono_profiler_get_events () & MONO_PROFILE_GC_ROOTS)
+       if (MONO_PROFILER_ENABLED (gc_roots))
                report_registered_roots ();
-       if (mono_profiler_get_events () & MONO_PROFILE_GC_ROOTS)
+
+       if (MONO_PROFILER_ENABLED (gc_roots))
                report_finalizer_roots (fin_ready_queue, critical_fin_queue);
 }
 
@@ -2012,7 +2037,7 @@ static gboolean profile_roots;
 void
 sgen_client_collecting_major_1 (void)
 {
-       profile_roots = mono_profiler_get_events () & MONO_PROFILE_GC_ROOTS;
+       profile_roots = MONO_PROFILER_ENABLED (gc_roots);
        memset (&major_root_report, 0, sizeof (GCRootReport));
 }
 
@@ -2020,7 +2045,7 @@ void
 sgen_client_pinned_los_object (GCObject *obj)
 {
        if (profile_roots)
-               add_profile_gc_root (&major_root_report, (char*)obj, MONO_PROFILE_GC_ROOT_PINNING | MONO_PROFILE_GC_ROOT_MISC, 0);
+               add_profile_gc_root (&major_root_report, (char*)obj, MONO_PROFILER_GC_ROOT_PINNING | MONO_PROFILER_GC_ROOT_MISC, 0);
 }
 
 void
@@ -2029,14 +2054,14 @@ sgen_client_collecting_major_2 (void)
        if (profile_roots)
                notify_gc_roots (&major_root_report);
 
-       if (mono_profiler_get_events () & MONO_PROFILE_GC_ROOTS)
+       if (MONO_PROFILER_ENABLED (gc_roots))
                report_registered_roots ();
 }
 
 void
 sgen_client_collecting_major_3 (SgenPointerQueue *fin_ready_queue, SgenPointerQueue *critical_fin_queue)
 {
-       if (mono_profiler_get_events () & MONO_PROFILE_GC_ROOTS)
+       if (MONO_PROFILER_ENABLED (gc_roots))
                report_finalizer_roots (fin_ready_queue, critical_fin_queue);
 }
 
@@ -2064,7 +2089,7 @@ mono_sgen_register_moved_object (void *obj, void *destination)
                sgen_pointer_queue_add (&moved_objects_queue, destination);
        } else {
                if (moved_objects_idx == MOVED_OBJECTS_NUM) {
-                       mono_profiler_gc_moves (moved_objects, moved_objects_idx);
+                       MONO_PROFILER_RAISE (gc_moves, ((MonoObject **) moved_objects, moved_objects_idx));
                        moved_objects_idx = 0;
                }
 
@@ -2084,7 +2109,7 @@ mono_sgen_gc_event_moves (void)
        }
 
        if (moved_objects_idx) {
-               mono_profiler_gc_moves (moved_objects, moved_objects_idx);
+               MONO_PROFILER_RAISE (gc_moves, ((MonoObject **) moved_objects, moved_objects_idx));
                moved_objects_idx = 0;
        }
 }
@@ -2702,7 +2727,8 @@ sgen_client_gchandle_created (int handle_type, GCObject *obj, guint32 handle)
 #ifndef DISABLE_PERFCOUNTERS
        mono_perfcounters->gc_num_handles++;
 #endif
-       mono_profiler_gc_handle (MONO_PROFILER_GC_HANDLE_CREATED, handle_type, handle, obj);
+
+       MONO_PROFILER_RAISE (gc_handle_created, (handle, handle_type, obj));
 }
 
 void
@@ -2711,7 +2737,8 @@ sgen_client_gchandle_destroyed (int handle_type, guint32 handle)
 #ifndef DISABLE_PERFCOUNTERS
        mono_perfcounters->gc_num_handles--;
 #endif
-       mono_profiler_gc_handle (MONO_PROFILER_GC_HANDLE_DESTROYED, handle_type, handle, NULL);
+
+       MONO_PROFILER_RAISE (gc_handle_deleted, (handle, handle_type));
 }
 
 void
index b90f8c2789e91f0952f4e34a1237f19bff14e7ec..48ce7f963ed23cfab6cc0eb68b6b42aa4f37eebf 100644 (file)
@@ -104,11 +104,11 @@ sgen_client_stop_world (int generation)
 {
        TV_DECLARE (end_handshake);
 
-       mono_profiler_gc_event (MONO_GC_EVENT_PRE_STOP_WORLD, generation);
+       MONO_PROFILER_RAISE (gc_event, (MONO_GC_EVENT_PRE_STOP_WORLD, generation));
 
        acquire_gc_locks ();
 
-       mono_profiler_gc_event (MONO_GC_EVENT_PRE_STOP_WORLD_LOCKED, generation);
+       MONO_PROFILER_RAISE (gc_event, (MONO_GC_EVENT_PRE_STOP_WORLD_LOCKED, generation));
 
        /* We start to scan after locks are taking, this ensures we won't be interrupted. */
        sgen_process_togglerefs ();
@@ -123,7 +123,7 @@ sgen_client_stop_world (int generation)
 
        SGEN_LOG (3, "world stopped");
 
-       mono_profiler_gc_event (MONO_GC_EVENT_POST_STOP_WORLD, generation);
+       MONO_PROFILER_RAISE (gc_event, (MONO_GC_EVENT_POST_STOP_WORLD, generation));
 
        TV_GETTIME (end_handshake);
        time_stop_world += TV_ELAPSED (stop_world_time, end_handshake);
@@ -143,10 +143,10 @@ sgen_client_restart_world (int generation, gint64 *stw_time)
 
        /* notify the profiler of the leftovers */
        /* FIXME this is the wrong spot at we can STW for non collection reasons. */
-       if (G_UNLIKELY (mono_profiler_events & MONO_PROFILE_GC_MOVES))
+       if (MONO_PROFILER_ENABLED (gc_moves))
                mono_sgen_gc_event_moves ();
 
-       mono_profiler_gc_event (MONO_GC_EVENT_PRE_START_WORLD, generation);
+       MONO_PROFILER_RAISE (gc_event, (MONO_GC_EVENT_PRE_START_WORLD, generation));
 
        FOREACH_THREAD (info) {
                info->client_info.stack_start = NULL;
@@ -165,7 +165,7 @@ sgen_client_restart_world (int generation, gint64 *stw_time)
 
        SGEN_LOG (2, "restarted (pause time: %d usec, max: %d)", (int)usec, (int)max_pause_usec);
 
-       mono_profiler_gc_event (MONO_GC_EVENT_POST_START_WORLD, generation);
+       MONO_PROFILER_RAISE (gc_event, (MONO_GC_EVENT_POST_START_WORLD, generation));
 
        /*
         * We must release the thread info suspend lock after doing
@@ -179,7 +179,7 @@ sgen_client_restart_world (int generation, gint64 *stw_time)
         */
        release_gc_locks ();
 
-       mono_profiler_gc_event (MONO_GC_EVENT_POST_START_WORLD_UNLOCKED, generation);
+       MONO_PROFILER_RAISE (gc_event, (MONO_GC_EVENT_POST_START_WORLD_UNLOCKED, generation));
 
        *stw_time = usec;
 }
index bb164f44be53bc29646cab697b78de8a13226466..3beb23242fba8111191c0656cdb74a6d96d10508 100644 (file)
@@ -1243,7 +1243,7 @@ mono_reflection_dynimage_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
 
        assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
 
-       mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
+       MONO_PROFILER_RAISE (assembly_loading, (&assembly->assembly));
        
        assembly->assembly.ref_count = 1;
        assembly->assembly.dynamic = TRUE;
@@ -1305,7 +1305,7 @@ mono_reflection_dynimage_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
 
        register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
        
-       mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
+       MONO_PROFILER_RAISE (assembly_loaded, (&assembly->assembly));
        
        mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
 }
@@ -2453,7 +2453,7 @@ reflection_setup_internal_class_internal (MonoReflectionTypeBuilderHandle ref_tb
        klass->type_token = MONO_TOKEN_TYPE_DEF | table_idx;
        mono_class_set_flags (klass, MONO_HANDLE_GETVAL (ref_tb, attrs));
        
-       mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
+       MONO_PROFILER_RAISE (class_loading, (klass));
 
        klass->element_class = klass;
 
@@ -2545,7 +2545,7 @@ reflection_setup_internal_class_internal (MonoReflectionTypeBuilderHandle ref_tb
 
        /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
 
-       mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
+       MONO_PROFILER_RAISE (class_loaded, (klass));
        
 leave:
        mono_loader_unlock ();
index e19f7e0735193cadde3d8bff77de62b48516ad75..e0a7aee8edc4b6711420fb1961fd2373138bab09 100644 (file)
@@ -824,12 +824,12 @@ static guint32 WINAPI start_wrapper_internal(StartInfo *start_info, gsize *stack
         * to lock the thread, and the lock is held by thread_start () which waits for
         * start_notify.
         */
-       mono_profiler_thread_start (tid);
+       MONO_PROFILER_RAISE (thread_started, (tid));
 
        /* if the name was set before starting, we didn't invoke the profiler callback */
        if (internal->name) {
                char *tname = g_utf16_to_utf8 (internal->name, internal->name_len, NULL, NULL, NULL);
-               mono_profiler_thread_name (internal->tid, tname);
+               MONO_PROFILER_RAISE (thread_name, (internal->tid, tname));
                mono_native_thread_set_name (MONO_UINT_TO_NATIVE_THREAD_ID (internal->tid), tname);
                g_free (tname);
        }
@@ -1124,8 +1124,7 @@ mono_thread_attach_full (MonoDomain *domain, gboolean force_attach)
 
        /* Can happen when we attach the profiler helper thread in order to heapshot. */
        if (!mono_thread_info_current ()->tools_thread)
-               // FIXME: Need a separate callback
-               mono_profiler_thread_start (MONO_NATIVE_THREAD_ID_TO_UINT (tid));
+               MONO_PROFILER_RAISE (thread_started, (MONO_NATIVE_THREAD_ID_TO_UINT (tid)));
 
        return thread;
 }
@@ -1236,7 +1235,7 @@ mono_thread_detach_internal (MonoInternalThread *thread)
 
        /* Can happen when we attach the profiler helper thread in order to heapshot. */
        if (!mono_thread_info_lookup (MONO_UINT_TO_NATIVE_THREAD_ID (thread->tid))->tools_thread)
-               mono_profiler_thread_end (thread->tid);
+               MONO_PROFILER_RAISE (thread_stopped, (thread->tid));
 
        mono_hazard_pointer_clear (mono_hazard_pointer_get (), 1);
 
@@ -1625,7 +1624,7 @@ mono_thread_set_name_internal (MonoInternalThread *this_obj, MonoString *name, g
        if (this_obj->name && this_obj->tid) {
                char *tname = mono_string_to_utf8_checked (name, error);
                return_if_nok (error);
-               mono_profiler_thread_name (this_obj->tid, tname);
+               MONO_PROFILER_RAISE (thread_name, (this_obj->tid, tname));
                mono_native_thread_set_name (thread_get_tid (this_obj), tname);
                mono_free (tname);
        }
@@ -2905,7 +2904,7 @@ mono_threads_register_app_context (MonoAppContext *ctx, MonoError *error)
 
        mono_threads_unlock ();
 
-       mono_profiler_context_loaded (ctx);
+       MONO_PROFILER_RAISE (context_loaded, (ctx));
 }
 
 void
@@ -2926,7 +2925,7 @@ mono_threads_release_app_context (MonoAppContext* ctx, MonoError *error)
 
        //g_print ("Releasing context %d in domain %d\n", ctx->context_id, ctx->domain_id);
 
-       mono_profiler_context_unloaded (ctx);
+       MONO_PROFILER_RAISE (context_unloaded, (ctx));
 }
 
 void
index e4b2378a3e822f033baf8474b29064bef69e441f..a9a477767b6c6f34dee6e1a1689090df86220bb6 100644 (file)
@@ -3978,6 +3978,8 @@ add_wrappers (MonoAotCompile *acfg)
                                add_method (acfg, m);
                        if ((m = mono_gc_get_managed_allocator_by_type (i, MANAGED_ALLOCATOR_SLOW_PATH)))
                                add_method (acfg, m);
+                       if ((m = mono_gc_get_managed_allocator_by_type (i, MANAGED_ALLOCATOR_PROFILER)))
+                               add_method (acfg, m);
                }
 
                /* write barriers */
@@ -5818,6 +5820,8 @@ encode_patch (MonoAotCompile *acfg, MonoJumpInfo *patch_info, guint8 *buf, guint
                break;
        case MONO_PATCH_INFO_INTERRUPTION_REQUEST_FLAG:
                break;
+       case MONO_PATCH_INFO_PROFILER_ALLOCATION_COUNT:
+               break;
        case MONO_PATCH_INFO_RGCTX_FETCH:
        case MONO_PATCH_INFO_RGCTX_SLOT_INDEX: {
                MonoJumpInfoRgctxEntry *entry = patch_info->data.rgctx_entry;
index f161e27169a7aac854fbe58bbe3068b98c05eaa8..7b28d8db4a28bc9c6df49dd5a331c5c54216c924 100644 (file)
@@ -925,12 +925,12 @@ decode_method_ref_with_target (MonoAotModule *module, MethodRef *ref, MonoMethod
                case MONO_WRAPPER_ALLOC: {
                        int atype = decode_value (p, &p);
                        ManagedAllocatorVariant variant =
-                               mono_profiler_get_events () & MONO_PROFILE_ALLOCATIONS ?
-                               MANAGED_ALLOCATOR_SLOW_PATH : MANAGED_ALLOCATOR_REGULAR;
+                               mono_profiler_allocations_enabled () ?
+                               MANAGED_ALLOCATOR_PROFILER : MANAGED_ALLOCATOR_REGULAR;
 
                        ref->method = mono_gc_get_managed_allocator_by_type (atype, variant);
                        /* Try to fallback to the slow path version */
-                       if (!ref->method && variant == MANAGED_ALLOCATOR_REGULAR)
+                       if (!ref->method)
                                ref->method = mono_gc_get_managed_allocator_by_type (atype, MANAGED_ALLOCATOR_SLOW_PATH);
                        if (!ref->method) {
                                mono_error_set_bad_image_name (error, module->aot_name, "Error: No managed allocator, but we need one for AOT.\nAre you using non-standard GC options?\n");
@@ -3662,6 +3662,7 @@ decode_patch (MonoAotModule *aot_module, MonoMemPool *mp, MonoJumpInfo *ji, guin
        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_PROFILER_ALLOCATION_COUNT:
                break;
        case MONO_PATCH_INFO_CASTCLASS_CACHE:
                ji->data.index = decode_value (p, &p);
@@ -3900,13 +3901,6 @@ load_method (MonoDomain *domain, MonoAotModule *amodule, MonoImage *image, MonoM
 
        init_amodule_got (amodule);
 
-       if (mono_profiler_get_events () & MONO_PROFILE_ENTER_LEAVE) {
-               if (mono_aot_only)
-                       /* The caller cannot handle this */
-                       g_assert_not_reached ();
-               return NULL;
-       }
-
        if (domain != mono_get_root_domain ())
                /* Non shared AOT code can't be used in other appdomains */
                return NULL;
@@ -4021,7 +4015,7 @@ load_method (MonoDomain *domain, MonoAotModule *amodule, MonoImage *image, MonoM
 
        amodule_unlock (amodule);
 
-       if (mono_profiler_get_events () & MONO_PROFILE_JIT_COMPILATION) {
+       if (MONO_PROFILER_ENABLED (jit_begin) || MONO_PROFILER_ENABLED (jit_done)) {
                MonoJitInfo *jinfo;
 
                if (!method) {
@@ -4029,10 +4023,10 @@ load_method (MonoDomain *domain, MonoAotModule *amodule, MonoImage *image, MonoM
                        if (!method)
                                return NULL;
                }
-               mono_profiler_method_jit (method);
+               MONO_PROFILER_RAISE (jit_begin, (method));
                jinfo = mono_jit_info_table_find (domain, (char*)code);
                g_assert (jinfo);
-               mono_profiler_method_end_jit (method, jinfo, MONO_PROFILE_OK);
+               MONO_PROFILER_RAISE (jit_done, (method, jinfo));
        }
 
        return code;
index 0c1a63db2e7a23b506f0d83c35e1384b50f8e2fd..96ef5e20ab2de107c067837e096b57178d2d9d83 100644 (file)
@@ -745,11 +745,11 @@ static void runtime_initialized (MonoProfiler *prof);
 
 static void runtime_shutdown (MonoProfiler *prof);
 
-static void thread_startup (MonoProfiler *prof, uintptr_t tid);
+static void thread_startup (MonoProfiler *prof, uint64_t tid);
 
-static void thread_end (MonoProfiler *prof, uintptr_t tid);
+static void thread_end (MonoProfiler *prof, uint64_t tid);
 
-static void appdomain_load (MonoProfiler *prof, MonoDomain *domain, int result);
+static void appdomain_load (MonoProfiler *prof, MonoDomain *domain);
 
 static void appdomain_start_unload (MonoProfiler *prof, MonoDomain *domain);
 
@@ -761,7 +761,7 @@ static void emit_thread_start (gpointer key, gpointer value, gpointer user_data)
 
 static void invalidate_each_thread (gpointer key, gpointer value, gpointer user_data);
 
-static void assembly_load (MonoProfiler *prof, MonoAssembly *assembly, int result);
+static void assembly_load (MonoProfiler *prof, MonoAssembly *assembly);
 
 static void assembly_unload (MonoProfiler *prof, MonoAssembly *assembly);
 
@@ -769,7 +769,11 @@ static void emit_assembly_load (gpointer assembly, gpointer user_data);
 
 static void emit_type_load (gpointer key, gpointer type, gpointer user_data);
 
-static void jit_end (MonoProfiler *prof, MonoMethod *method, MonoJitInfo *jinfo, int result);
+static void jit_done (MonoProfiler *prof, MonoMethod *method, MonoJitInfo *jinfo);
+
+static void jit_failed (MonoProfiler *prof, MonoMethod *method);
+
+static void jit_end (MonoProfiler *prof, MonoMethod *method, MonoJitInfo *jinfo);
 
 static void add_pending_breakpoints (MonoMethod *method, MonoJitInfo *jinfo);
 
@@ -995,13 +999,18 @@ mono_debugger_agent_init (void)
        mono_coop_mutex_init (&debugger_thread_exited_mutex);
        mono_coop_cond_init (&debugger_thread_exited_cond);
 
-       mono_profiler_install ((MonoProfiler*)&debugger_profiler, runtime_shutdown);
-       mono_profiler_set_events ((MonoProfileFlags)(MONO_PROFILE_APPDOMAIN_EVENTS | MONO_PROFILE_THREADS | MONO_PROFILE_ASSEMBLY_EVENTS | MONO_PROFILE_JIT_COMPILATION | MONO_PROFILE_METHOD_EVENTS));
-       mono_profiler_install_runtime_initialized (runtime_initialized);
-       mono_profiler_install_appdomain (NULL, appdomain_load, appdomain_start_unload, appdomain_unload);
-       mono_profiler_install_thread (thread_startup, thread_end);
-       mono_profiler_install_assembly (NULL, assembly_load, assembly_unload, NULL);
-       mono_profiler_install_jit_end (jit_end);
+       MonoProfilerHandle prof = mono_profiler_install ((MonoProfiler*)&debugger_profiler);
+       mono_profiler_set_runtime_shutdown_callback (prof, runtime_shutdown);
+       mono_profiler_set_runtime_initialized_callback (prof, runtime_initialized);
+       mono_profiler_set_domain_loaded_callback (prof, appdomain_load);
+       mono_profiler_set_domain_unloading_callback (prof, appdomain_start_unload);
+       mono_profiler_set_domain_unloaded_callback (prof, appdomain_unload);
+       mono_profiler_set_thread_started_callback (prof, thread_startup);
+       mono_profiler_set_thread_stopped_callback (prof, thread_end);
+       mono_profiler_set_assembly_loaded_callback (prof, assembly_load);
+       mono_profiler_set_assembly_unloading_callback (prof, assembly_unload);
+       mono_profiler_set_jit_done_callback (prof, jit_done);
+       mono_profiler_set_jit_failed_callback (prof, jit_failed);
 
        mono_native_tls_alloc (&debugger_tls_id, NULL);
 
@@ -3861,7 +3870,7 @@ runtime_shutdown (MonoProfiler *prof)
 }
 
 static void
-thread_startup (MonoProfiler *prof, uintptr_t tid)
+thread_startup (MonoProfiler *prof, uint64_t tid)
 {
        MonoInternalThread *thread = mono_thread_internal_current ();
        MonoInternalThread *old_thread;
@@ -3922,7 +3931,7 @@ thread_startup (MonoProfiler *prof, uintptr_t tid)
 }
 
 static void
-thread_end (MonoProfiler *prof, uintptr_t tid)
+thread_end (MonoProfiler *prof, uint64_t tid)
 {
        MonoInternalThread *thread;
        DebuggerTlsData *tls = NULL;
@@ -3960,7 +3969,7 @@ thread_end (MonoProfiler *prof, uintptr_t tid)
 }
 
 static void
-appdomain_load (MonoProfiler *prof, MonoDomain *domain, int result)
+appdomain_load (MonoProfiler *prof, MonoDomain *domain)
 {
        mono_loader_lock ();
        g_hash_table_insert (domains, domain, domain);
@@ -4022,7 +4031,7 @@ invalidate_each_thread (gpointer key, gpointer value, gpointer user_data)
 }
 
 static void
-assembly_load (MonoProfiler *prof, MonoAssembly *assembly, int result)
+assembly_load (MonoProfiler *prof, MonoAssembly *assembly)
 {
        /* Sent later in jit_end () */
        dbg_lock ();
@@ -4110,7 +4119,19 @@ send_assemblies_for_domain (MonoDomain *domain, void *user_data)
 }
 
 static void
-jit_end (MonoProfiler *prof, MonoMethod *method, MonoJitInfo *jinfo, int result)
+jit_done (MonoProfiler *prof, MonoMethod *method, MonoJitInfo *jinfo)
+{
+       jit_end (prof, method, jinfo);
+}
+
+static void
+jit_failed (MonoProfiler *prof, MonoMethod *method)
+{
+       jit_end (prof, method, NULL);
+}
+
+static void
+jit_end (MonoProfiler *prof, MonoMethod *method, MonoJitInfo *jinfo)
 {
        /*
         * We emit type load events when the first method of the type is JITted,
@@ -4138,7 +4159,7 @@ jit_end (MonoProfiler *prof, MonoMethod *method, MonoJitInfo *jinfo, int result)
 
        send_type_load (method->klass);
 
-       if (!result && jinfo)
+       if (jinfo)
                add_pending_breakpoints (method, jinfo);
 }
 
index aeee1d4cbecf520fdfce4fa2bf967bc3e77d3e31..2c5f03e1832adfc2bfdcd51003190a0475564f06 100644 (file)
@@ -203,7 +203,7 @@ mono_arch_get_restore_context (MonoTrampInfo **info, gboolean aot)
        amd64_jump_reg (code, AMD64_R11);
 
        mono_arch_flush_icache (start, code - start);
-       mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL);
+       MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL));
 
        if (info)
                *info = mono_tramp_info_create ("restore_context", start, code - start, ji, unwind_ops);
@@ -291,7 +291,7 @@ mono_arch_get_call_filter (MonoTrampInfo **info, gboolean aot)
        g_assert ((code - start) < kMaxCodeSize);
 
        mono_arch_flush_icache (start, code - start);
-       mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL);
+       MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL));
 
        if (info)
                *info = mono_tramp_info_create ("call_filter", start, code - start, ji, unwind_ops);
@@ -474,7 +474,7 @@ get_throw_trampoline (MonoTrampInfo **info, gboolean rethrow, gboolean corlib, g
        g_assert ((code - start) < kMaxCodeSize);
        g_assert_checked (mono_arch_unwindinfo_validate_size (unwind_ops, MONO_MAX_TRAMPOLINE_UNWINDINFO_SIZE));
 
-       mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL);
+       MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL));
 
        if (info)
                *info = mono_tramp_info_create (tramp_name, start, code - start, ji, unwind_ops);
@@ -1825,7 +1825,7 @@ mono_tasklets_arch_restore (void)
        g_assert ((code - start) <= kMaxCodeSize);
 
        mono_arch_flush_icache (start, code - start);
-       mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL);
+       MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL));
 
        saved = start;
        return (MonoContinuationRestore)saved;
index 29dc7709aa029ff9263677be3fe9e015d2d8231d..fb8d1736c10ac7b69b803ea9d0174677b902b9e7 100644 (file)
@@ -63,7 +63,7 @@ mono_arch_get_restore_context (MonoTrampInfo **info, gboolean aot)
 
        g_assert ((code - start) < size);
        mono_arch_flush_icache (start, code - start);
-       mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL);
+       MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL));
 
        if (info)
                *info = mono_tramp_info_create ("restore_context", start, code - start, ji, unwind_ops);
@@ -152,7 +152,7 @@ mono_arch_get_call_filter (MonoTrampInfo **info, gboolean aot)
 
        g_assert ((code - start) < size);
        mono_arch_flush_icache (start, code - start);
-       mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL);
+       MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL));
 
        if (info)
                *info = mono_tramp_info_create ("call_filter", start, code - start, ji, unwind_ops);
@@ -249,7 +249,7 @@ get_throw_trampoline (int size, gboolean corlib, gboolean rethrow, gboolean llvm
 
        g_assert ((code - start) < size);
        mono_arch_flush_icache (start, code - start);
-       mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL);
+       MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL));
 
        if (info)
                *info = mono_tramp_info_create (tramp_name, start, code - start, ji, unwind_ops);
index 4876fc164cfadd920fc948c7b08e0300d3c528eb..69d37cba757101366624d29b50aec5982c0b3905 100644 (file)
@@ -78,7 +78,7 @@ mono_arch_get_restore_context (MonoTrampInfo **info, gboolean aot)
 
        g_assert ((code - start) < sizeof(start));
        mono_arch_flush_icache (start, code - start);
-       mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL);
+       MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL));
        return start;
 }
 
@@ -170,7 +170,7 @@ mono_arch_get_call_filter (MonoTrampInfo **info, gboolean aot)
 
        g_assert ((code - start) < sizeof(start));
        mono_arch_flush_icache (start, code - start);
-       mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL);
+       MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL));
        return start;
 }
 
@@ -288,7 +288,7 @@ mono_arch_get_throw_exception_generic (guint8 *start, int size, int corlib, gboo
 
        g_assert ((code - start) < size);
        mono_arch_flush_icache (start, code - start);
-       mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL);
+       MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL));
        return start;
 }
 
@@ -354,7 +354,7 @@ mono_arch_get_throw_exception_by_name (void)
        start = code = mono_global_codeman_reserve (size);
        mips_break (code, 0xfd);
        mono_arch_flush_icache (start, code - start);
-       mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL);
+       MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL));
        return start;
 }
 
index 8a758c43c89d7910f1164c5d8ac711ace0619cf8..5e22cb967c8881dc04a983b3e54b34f6f57bdde7 100644 (file)
@@ -220,7 +220,7 @@ mono_arch_get_restore_context (MonoTrampInfo **info, gboolean aot)
 
        g_assert ((code - start) <= size);
        mono_arch_flush_icache (start, code - start);
-       mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL);
+       MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL));
 
        if (info)
                *info = mono_tramp_info_create ("restore_context", start, code - start, ji, unwind_ops);
@@ -311,7 +311,7 @@ mono_arch_get_call_filter (MonoTrampInfo **info, gboolean aot)
 
        g_assert ((code - start) < size);
        mono_arch_flush_icache (start, code - start);
-       mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL);
+       MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL));
 
        if (info)
                *info = mono_tramp_info_create ("call_filter", start, code - start, ji, unwind_ops);
@@ -444,7 +444,7 @@ mono_arch_get_throw_exception_generic (int size, MonoTrampInfo **info, int corli
        ppc_break (code);
        g_assert ((code - start) <= size);
        mono_arch_flush_icache (start, code - start);
-       mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL);
+       MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL));
 
        if (info)
                *info = mono_tramp_info_create (corlib ? "throw_corlib_exception" : (rethrow ? "rethrow_exception" : "throw_exception"), start, code - start, ji, unwind_ops);
index 77241a6c68a3da3a769600184618cf178034a0fb..19204c6ccd6b16a30fbb057867269193e9bb3ce6 100644 (file)
@@ -215,7 +215,7 @@ mono_arch_get_call_filter (MonoTrampInfo **info, gboolean aot)
        g_assert ((code - start) < SZ_THROW); 
 
        mono_arch_flush_icache(start, code - start);
-       mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL);
+       MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL));
 
        if (info)
                *info = mono_tramp_info_create ("call_filter",
@@ -362,7 +362,7 @@ mono_arch_get_throw_exception_generic (int size, MonoTrampInfo **info,
        g_assert ((code - start) < size);
 
        mono_arch_flush_icache (start, code - start);
-       mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL);
+       MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL));
 
        if (info)
                *info = mono_tramp_info_create (corlib ? "throw_corlib_exception" 
index 30cb4b92d27c86ff3c549d23d4a812b8902fc118..5042fa5efd1629755101e2f9c443cfc48877ef26 100644 (file)
@@ -114,7 +114,7 @@ mono_win32_get_handle_stackoverflow (void)
        x86_ret (code);
 
        mono_arch_flush_icache (start, code - start);
-       mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL);
+       MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL));
 
        return start;
 }
@@ -360,7 +360,7 @@ mono_arch_get_restore_context (MonoTrampInfo **info, gboolean aot)
        }
 
        mono_arch_flush_icache (start, code - start);
-       mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL);
+       MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL));
 
        return start;
 }
@@ -438,7 +438,7 @@ mono_arch_get_call_filter (MonoTrampInfo **info, gboolean aot)
        }
 
        mono_arch_flush_icache (start, code - start);
-       mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL);
+       MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL));
 
        g_assert ((code - start) < kMaxCodeSize);
        return start;
@@ -676,7 +676,7 @@ get_throw_trampoline (const char *name, gboolean rethrow, gboolean llvm, gboolea
        }
 
        mono_arch_flush_icache (start, code - start);
-       mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL);
+       MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL));
 
        return start;
 }
@@ -978,7 +978,7 @@ mono_x86_get_signal_exception_trampoline (MonoTrampInfo **info, gboolean aot)
        }
 
        mono_arch_flush_icache (start, code - start);
-       mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL);
+       MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL));
 
        return start;
 }
index 3a14d6923357789c25eb54c3c7e0d5eb08e93f3c..bf3a62195ec70951795373bcee354f143f208b45 100644 (file)
@@ -173,8 +173,8 @@ debug_enter (MonoInvocation *frame, int *tracing)
                g_print  ("%s)\n", args);
                g_free (args);
        }
-       if (mono_profiler_events & MONO_PROFILE_ENTER_LEAVE)
-               mono_profiler_method_enter (frame->runtime_method->method);
+       if (mono_profiler_should_instrument_method (frame->runtime_method->method, TRUE))
+               MONO_PROFILER_RAISE (method_enter, (frame->runtime_method->method));
 }
 
 
@@ -191,8 +191,8 @@ debug_enter (MonoInvocation *frame, int *tracing)
                debug_indent_level--;   \
                if (tracing == 3) global_tracing = 0; \
        }       \
-       if (mono_profiler_events & MONO_PROFILE_ENTER_LEAVE)    \
-               mono_profiler_method_leave (frame->runtime_method->method);
+       if (mono_profiler_should_instrument_method (frame->runtime_method->method, FALSE)) \
+               MONO_PROFILER_RAISE (method_enter, (frame->runtime_method->method));
 
 #else
 
index 35592cb05e2bafe26b4b476b9c0925cd962710d5..02a92f271c83a99ee29e82aac9cd2be02629a25f 100644 (file)
@@ -4012,7 +4012,7 @@ mono_interp_transform_method (RuntimeMethod *runtime_method, ThreadContext *cont
                context->current_env = old_env;
        }
 
-       mono_profiler_method_jit (method); /* sort of... */
+       MONO_PROFILER_RAISE (jit_begin, (method));
 
        if (mono_method_signature (method)->is_inflated)
                generic_context = mono_method_get_context (method);
@@ -4027,7 +4027,7 @@ mono_interp_transform_method (RuntimeMethod *runtime_method, ThreadContext *cont
                mono_os_mutex_lock(&calc_section);
                if (runtime_method->transformed) {
                        mono_os_mutex_unlock(&calc_section);
-                       mono_profiler_method_end_jit (method, runtime_method->jinfo, MONO_PROFILE_OK);
+                       MONO_PROFILER_RAISE (jit_done, (method, runtime_method->jinfo));
                        return NULL;
                }
 
@@ -4061,7 +4061,7 @@ mono_interp_transform_method (RuntimeMethod *runtime_method, ThreadContext *cont
                        runtime_method->alloca_size = runtime_method->stack_size;
                        runtime_method->transformed = TRUE;
                        mono_os_mutex_unlock(&calc_section);
-                       mono_profiler_method_end_jit (method, NULL, MONO_PROFILE_OK);
+                       MONO_PROFILER_RAISE (jit_done, (method, NULL));
                        return NULL;
                }
                method = nm;
@@ -4078,7 +4078,7 @@ mono_interp_transform_method (RuntimeMethod *runtime_method, ThreadContext *cont
                                runtime_method->transformed = TRUE;
                        }
                        mono_os_mutex_unlock(&calc_section);
-                       mono_profiler_method_end_jit (method, NULL, MONO_PROFILE_OK);
+                       MONO_PROFILER_RAISE (jit_done, (method, NULL));
                        return NULL;
                } else if (!strcmp (method->name, "UnsafeStore")) {
                        g_error ("TODO");
@@ -4202,7 +4202,7 @@ mono_interp_transform_method (RuntimeMethod *runtime_method, ThreadContext *cont
        if (runtime_method->transformed) {
                mono_os_mutex_unlock(&calc_section);
                g_free (is_bb_start);
-               mono_profiler_method_end_jit (method, runtime_method->jinfo, MONO_PROFILE_OK);
+               MONO_PROFILER_RAISE (jit_done, (method, runtime_method->jinfo));
                return NULL;
        }
 
@@ -4262,7 +4262,7 @@ mono_interp_transform_method (RuntimeMethod *runtime_method, ThreadContext *cont
        g_free (is_bb_start);
 
        // FIXME: Add a different callback ?
-       mono_profiler_method_end_jit (method, runtime_method->jinfo, MONO_PROFILE_OK);
+       MONO_PROFILER_RAISE (jit_done, (method, runtime_method->jinfo));
        runtime_method->transformed = TRUE;
        mono_os_mutex_unlock(&calc_section);
 
index 2a5f8917d5e86dba99e1612918565f8dfd325040..c20c6b2bbbf6102bd76c963a00cba4af9ba82c56 100644 (file)
@@ -1765,7 +1765,7 @@ emit_pop_lmf (MonoCompile *cfg)
 }
 
 static void
-emit_instrumentation_call (MonoCompile *cfg, void *func)
+emit_instrumentation_call (MonoCompile *cfg, void *func, gboolean entry)
 {
        MonoInst *iargs [1];
 
@@ -1776,7 +1776,7 @@ emit_instrumentation_call (MonoCompile *cfg, void *func)
        if (cfg->method != cfg->current_method)
                return;
 
-       if (cfg->prof_options & MONO_PROFILE_ENTER_LEAVE) {
+       if (mono_profiler_should_instrument_method (cfg->method, entry)) {
                EMIT_NEW_METHODCONST (cfg, iargs [0], cfg->method);
                mono_emit_jit_icall (cfg, func, iargs);
        }
@@ -2247,7 +2247,7 @@ mono_emit_call_args (MonoCompile *cfg, MonoMethodSignature *sig,
                tail = FALSE;
 
        if (tail) {
-               emit_instrumentation_call (cfg, mono_profiler_method_leave);
+               emit_instrumentation_call (cfg, mono_profiler_raise_method_leave, FALSE);
 
                MONO_INST_NEW_CALL (cfg, call, OP_TAILCALL);
        } else
@@ -5867,7 +5867,7 @@ mini_redirect_call (MonoCompile *cfg, MonoMethod *method,
 {
        if (method->klass == mono_defaults.string_class) {
                /* managed string allocation support */
-               if (strcmp (method->name, "InternalAllocateStr") == 0 && !(mono_profiler_events & MONO_PROFILE_ALLOCATIONS) && !(cfg->opt & MONO_OPT_SHARED)) {
+               if (strcmp (method->name, "InternalAllocateStr") == 0 && !(cfg->opt & MONO_OPT_SHARED)) {
                        MonoInst *iargs [2];
                        MonoVTable *vtable = mono_class_vtable (cfg->domain, method->klass);
                        MonoMethod *managed_alloc = NULL;
@@ -7310,8 +7310,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
        cfg->dont_inline = g_list_prepend (cfg->dont_inline, method);
        if (cfg->method == method) {
 
-               if (cfg->prof_options & MONO_PROFILE_INS_COVERAGE)
-                       cfg->coverage_info = mono_profiler_coverage_alloc (cfg->method, header->code_size);
+               cfg->coverage_info = mono_profiler_coverage_alloc (cfg->method, header->code_size);
 
                /* ENTRY BLOCK */
                NEW_BBLOCK (cfg, start_bblock);
@@ -8044,7 +8043,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        if (cfg->gshared && mono_method_check_context_used (cmethod))
                                GENERIC_SHARING_FAILURE (CEE_JMP);
 
-                       emit_instrumentation_call (cfg, mono_profiler_method_leave);
+                       emit_instrumentation_call (cfg, mono_profiler_raise_method_leave, FALSE);
 
                        fsig = mono_method_signature (cmethod);
                        n = fsig->param_count + fsig->hasthis;
@@ -8986,7 +8985,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                        /* Handle tail calls similarly to normal calls */
                                        tail_call = TRUE;
                                } else {
-                                       emit_instrumentation_call (cfg, mono_profiler_method_leave);
+                                       emit_instrumentation_call (cfg, mono_profiler_raise_method_leave, FALSE);
 
                                        MONO_INST_NEW_CALL (cfg, call, OP_JMP);
                                        call->tail_call = TRUE;
@@ -9120,7 +9119,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                        cfg->ret_var_set = TRUE;
                                } 
                        } else {
-                               emit_instrumentation_call (cfg, mono_profiler_method_leave);
+                               emit_instrumentation_call (cfg, mono_profiler_raise_method_leave, FALSE);
 
                                if (cfg->lmf_var && cfg->cbb->in_count && !cfg->llvm_only)
                                        emit_pop_lmf (cfg);
@@ -11500,7 +11499,8 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        case CEE_MONO_LDPTR_CARD_TABLE:
                        case CEE_MONO_LDPTR_NURSERY_START:
                        case CEE_MONO_LDPTR_NURSERY_BITS:
-                       case CEE_MONO_LDPTR_INT_REQ_FLAG: {
+                       case CEE_MONO_LDPTR_INT_REQ_FLAG:
+                       case CEE_MONO_LDPTR_PROFILER_ALLOCATION_COUNT: {
                                CHECK_STACK_OVF (1);
 
                                switch (ip [1]) {
@@ -11516,6 +11516,9 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                case CEE_MONO_LDPTR_INT_REQ_FLAG:
                                        ins = mini_emit_runtime_constant (cfg, MONO_PATCH_INFO_INTERRUPTION_REQUEST_FLAG, NULL);
                                        break;
+                               case CEE_MONO_LDPTR_PROFILER_ALLOCATION_COUNT:
+                                       ins = mini_emit_runtime_constant (cfg, MONO_PATCH_INFO_PROFILER_ALLOCATION_COUNT, NULL);
+                                       break;
                                default:
                                        g_assert_not_reached ();
                                        break;
@@ -12628,7 +12631,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
        }
 
        cfg->cbb = init_localsbb;
-       emit_instrumentation_call (cfg, mono_profiler_method_enter);
+       emit_instrumentation_call (cfg, mono_profiler_raise_method_enter, TRUE);
 
        if (seq_points) {
                MonoBasicBlock *bb;
index 515be71f91f46a1a2f67e26806df644ed46714da..84acd5ce7545f38d737ca4709c2be33e1015ee95 100644 (file)
@@ -3631,16 +3631,6 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
        if (cfg->verbose_level > 2)
                g_print ("Basic block %d starting at offset 0x%x\n", bb->block_num, bb->native_offset);
 
-       if ((cfg->prof_options & MONO_PROFILE_COVERAGE) && cfg->coverage_info) {
-               MonoProfileCoverageInfo *cov = cfg->coverage_info;
-               g_assert (!cfg->compile_aot);
-
-               cov->data [bb->dfn].cil_code = bb->cil_code;
-               amd64_mov_reg_imm (code, AMD64_R11, (guint64)&cov->data [bb->dfn].count);
-               /* this is not thread save, but good enough */
-               amd64_inc_membase (code, AMD64_R11, 0);
-       }
-
        offset = code - cfg->native_code;
 
        mono_debug_open_block (cfg, bb, offset);
@@ -6813,8 +6803,6 @@ mono_arch_emit_prolog (MonoCompile *cfg)
                        MonoInst *ins;
                        int max_length = 0;
 
-                       if (cfg->prof_options & MONO_PROFILE_COVERAGE)
-                               max_length += 6;
                        /* max alignment for loops */
                        if ((cfg->opt & MONO_OPT_LOOP) && bb_is_loop_start (bb))
                                max_length += LOOP_ALIGNMENT;
@@ -7684,7 +7672,7 @@ get_delegate_invoke_impl (MonoTrampInfo **info, gboolean has_target, guint32 par
                if (!has_target)
                        g_free (buff);
        }
-       mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_DELEGATE_INVOKE, NULL);
+       MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_DELEGATE_INVOKE, NULL));
 
        return start;
 }
@@ -7718,7 +7706,7 @@ get_delegate_virtual_invoke_impl (MonoTrampInfo **info, gboolean load_imt_reg, i
        /* Load the vtable */
        amd64_mov_reg_membase (code, AMD64_RAX, AMD64_ARG_REG1, MONO_STRUCT_OFFSET (MonoObject, vtable), 8);
        amd64_jump_membase (code, AMD64_RAX, offset);
-       mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_DELEGATE_INVOKE, NULL);
+       MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_DELEGATE_INVOKE, NULL));
 
        tramp_name = mono_get_delegate_virtual_invoke_impl_name (load_imt_reg, offset);
        *info = mono_tramp_info_create (tramp_name, start, code - start, NULL, unwind_ops);
@@ -8018,7 +8006,7 @@ mono_arch_build_imt_trampoline (MonoVTable *vtable, MonoDomain *domain, MonoIMTC
        g_assert (code - start <= size);
        g_assert_checked (mono_arch_unwindinfo_validate_size (unwind_ops, MONO_TRAMPOLINE_UNWINDINFO_SIZE(0)));
 
-       mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_IMT_TRAMPOLINE, NULL);
+       MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_IMT_TRAMPOLINE, NULL));
 
        mono_tramp_info_register (mono_tramp_info_create (NULL, start, code - start, NULL, unwind_ops), domain);
 
index 1328e762a65dc7059bf0315ff6ab3e85b0531a83..9703c1e09de12282e8cef5f83cb8d4a0a6fa78bf 100644 (file)
@@ -650,7 +650,7 @@ get_delegate_invoke_impl (MonoTrampInfo **info, gboolean has_target, gboolean pa
                 g_free (name);
        }
 
-       mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_DELEGATE_INVOKE, NULL);
+       MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_DELEGATE_INVOKE, NULL));
 
        return start;
 }
@@ -4192,17 +4192,6 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
 
        cpos = bb->max_offset;
 
-       if (cfg->prof_options & MONO_PROFILE_COVERAGE) {
-               //MonoCoverageInfo *cov = mono_get_coverage_info (cfg->method);
-               //g_assert (!mono_compile_aot);
-               //cpos += 6;
-               //if (bb->cil_code)
-               //      cov->data [bb->dfn].iloffset = bb->cil_code - cfg->cil_code;
-               /* this is not thread save, but good enough */
-               /* fixme: howto handle overflows? */
-               //x86_inc_mem (code, &cov->data [bb->dfn].count); 
-       }
-
     if (mono_break_at_bb_method && mono_method_desc_full_match (mono_break_at_bb_method, cfg->method) && bb->block_num == mono_break_at_bb_bb_num) {
                mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD, 
                                                         (gpointer)"mono_break");
@@ -6151,9 +6140,6 @@ mono_arch_emit_prolog (MonoCompile *cfg)
                MonoInst *ins = bb->code;
                bb->max_offset = max_offset;
 
-               if (cfg->prof_options & MONO_PROFILE_COVERAGE)
-                       max_offset += 6; 
-
                MONO_BB_FOR_EACH_INS (bb, ins)
                        max_offset += ((guint8 *)ins_get_spec (ins->opcode))[MONO_INST_LEN];
        }
@@ -7062,7 +7048,7 @@ mono_arch_build_imt_trampoline (MonoVTable *vtable, MonoDomain *domain, MonoIMTC
        g_free (constant_pool_starts);
 
        mono_arch_flush_icache ((guint8*)start, size);
-       mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_IMT_TRAMPOLINE, NULL);
+       MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_IMT_TRAMPOLINE, NULL));
        mono_stats.imt_trampolines_size += code - start;
 
        g_assert (DISTANCE (start, code) <= size);
index 2b8374596e0f30adefe21b196d3c2f1857bd90b9..bd4283bf3f87fab69d58e96c199e53f3acded15c 100644 (file)
@@ -1937,7 +1937,7 @@ mono_handle_exception_internal (MonoContext *ctx, MonoObject *obj, gboolean resu
                                mono_print_thread_dump_from_ctx (ctx);
                }
                jit_tls->orig_ex_ctx_set = TRUE;
-               mono_profiler_exception_thrown (obj);
+               MONO_PROFILER_RAISE (exception_throw, (obj));
                jit_tls->orig_ex_ctx_set = FALSE;
 
                res = mono_handle_exception_internal_first_pass (&ctx_cp, obj, &first_filter_idx, &ji, &prev_ji, non_exception);
@@ -2139,7 +2139,7 @@ mono_handle_exception_internal (MonoContext *ctx, MonoObject *obj, gboolean resu
                                        if (mono_trace_is_enabled () && mono_trace_eval (method))
                                                g_print ("EXCEPTION: catch found at clause %d of %s\n", i, mono_method_full_name (method, TRUE));
                                        jit_tls->orig_ex_ctx_set = TRUE;
-                                       mono_profiler_exception_clause_handler (method, ei->flags, i, ex_obj);
+                                       MONO_PROFILER_RAISE (exception_clause, (method, i, ei->flags, ex_obj));
                                        jit_tls->orig_ex_ctx_set = FALSE;
                                        mini_set_abort_threshold (ctx);
 
@@ -2183,7 +2183,7 @@ mono_handle_exception_internal (MonoContext *ctx, MonoObject *obj, gboolean resu
                                        if (mono_trace_is_enabled () && mono_trace_eval (method))
                                                g_print ("EXCEPTION: fault clause %d of %s\n", i, mono_method_full_name (method, TRUE));
                                        jit_tls->orig_ex_ctx_set = TRUE;
-                                       mono_profiler_exception_clause_handler (method, ei->flags, i, ex_obj);
+                                       MONO_PROFILER_RAISE (exception_clause, (method, i, ei->flags, ex_obj));
                                        jit_tls->orig_ex_ctx_set = FALSE;
                                        mini_set_abort_threshold (ctx);
                                        call_filter (ctx, ei->handler_start);
@@ -2192,7 +2192,7 @@ mono_handle_exception_internal (MonoContext *ctx, MonoObject *obj, gboolean resu
                                        if (mono_trace_is_enabled () && mono_trace_eval (method))
                                                g_print ("EXCEPTION: finally clause %d of %s\n", i, mono_method_full_name (method, TRUE));
                                        jit_tls->orig_ex_ctx_set = TRUE;
-                                       mono_profiler_exception_clause_handler (method, ei->flags, i, ex_obj);
+                                       MONO_PROFILER_RAISE (exception_clause, (method, i, ei->flags, ex_obj));
                                        jit_tls->orig_ex_ctx_set = FALSE;
 #ifndef DISABLE_PERFCOUNTERS
                                        mono_perfcounters->exceptions_finallys++;
@@ -2230,7 +2230,7 @@ mono_handle_exception_internal (MonoContext *ctx, MonoObject *obj, gboolean resu
                }
 
                jit_tls->orig_ex_ctx_set = TRUE;
-               mono_profiler_exception_method_leave (method);
+               MONO_PROFILER_RAISE (method_exception_leave, (method, ex_obj));
                jit_tls->orig_ex_ctx_set = FALSE;
 
                *ctx = new_ctx;
index e18c2bdef1de8b074d31965a7dbe6dc1eca352ed..bf06aee47bb5523f8c68a8d4a8139d73e65292ff 100644 (file)
@@ -3216,21 +3216,6 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
 
        cpos = bb->max_offset;
 
-#if 0
-       if (cfg->prof_options & MONO_PROFILE_COVERAGE) {
-               MonoCoverageInfo *cov = mono_get_coverage_info (cfg->method);
-               g_assert (!mono_compile_aot);
-               cpos += 20;
-               if (bb->cil_code)
-                       cov->data [bb->dfn].iloffset = bb->cil_code - cfg->cil_code;
-               /* this is not thread save, but good enough */
-               /* fixme: howto handle overflows? */
-               mips_load_const (code, mips_at, &cov->data [bb->dfn].count);
-               mips_lw (code, mips_temp, mips_at, 0);
-               mips_addiu (code, mips_temp, mips_temp, 1);
-               mips_sw (code, mips_temp, mips_at, 0);
-       }
-#endif
        MONO_BB_FOR_EACH_INS (bb, ins) {
                offset = code - cfg->native_code;
 
@@ -4831,9 +4816,6 @@ mono_arch_emit_prolog (MonoCompile *cfg)
                MonoInst *ins = bb->code;
                bb->max_offset = max_offset;
 
-               if (cfg->prof_options & MONO_PROFILE_COVERAGE)
-                       max_offset += 6; 
-
                MONO_BB_FOR_EACH_INS (bb, ins)
                        max_offset += ((guint8 *)ins_get_spec (ins->opcode))[MONO_INST_LEN];
        }
index ba60bd9934a62f109dc6698bf24ad129796ebf51..a3fd4f0e2983c745e09adc7c2ec685733a8337af 100644 (file)
@@ -210,101 +210,12 @@ MONO_SIG_HANDLER_FUNC (static, sigabrt_signal_handler)
        }
 }
 
-#if defined(__i386__) || defined(__x86_64__)
-#define FULL_STAT_PROFILER_BACKTRACE 1
-#define CURRENT_FRAME_GET_BASE_POINTER(f) (* (gpointer*)(f))
-#define CURRENT_FRAME_GET_RETURN_ADDRESS(f) (* (((gpointer*)(f)) + 1))
-#if MONO_ARCH_STACK_GROWS_UP
-#define IS_BEFORE_ON_STACK <
-#define IS_AFTER_ON_STACK >
-#else
-#define IS_BEFORE_ON_STACK >
-#define IS_AFTER_ON_STACK <
-#endif
-#else
-#define FULL_STAT_PROFILER_BACKTRACE 0
-#endif
-
 #if (defined (USE_POSIX_BACKEND) && defined (SIGRTMIN)) || defined (SIGPROF)
 #define HAVE_PROFILER_SIGNAL
 #endif
 
 #ifdef HAVE_PROFILER_SIGNAL
 
-static void
-per_thread_profiler_hit (void *ctx)
-{
-       int call_chain_depth = mono_profiler_stat_get_call_chain_depth ();
-       MonoProfilerCallChainStrategy call_chain_strategy = mono_profiler_stat_get_call_chain_strategy ();
-
-       if (call_chain_depth == 0) {
-               mono_profiler_stat_hit ((guchar *)mono_arch_ip_from_context (ctx), ctx);
-       } else {
-               MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_tls_get_jit_tls ();
-               int current_frame_index = 1;
-               MonoContext mono_context;
-               guchar *ips [call_chain_depth + 1];
-
-               mono_sigctx_to_monoctx (ctx, &mono_context);
-               ips [0] = (guchar *)MONO_CONTEXT_GET_IP (&mono_context);
-               
-               if (jit_tls != NULL) {
-                       if (call_chain_strategy == MONO_PROFILER_CALL_CHAIN_NATIVE) {
-#if FULL_STAT_PROFILER_BACKTRACE
-                       guchar *current_frame;
-                       guchar *stack_bottom;
-                       guchar *stack_top;
-                       
-                       stack_bottom = (guchar *)jit_tls->end_of_stack;
-                       stack_top = (guchar *)MONO_CONTEXT_GET_SP (&mono_context);
-                       current_frame = (guchar *)MONO_CONTEXT_GET_BP (&mono_context);
-                       
-                       while ((current_frame_index <= call_chain_depth) &&
-                                       (stack_bottom IS_BEFORE_ON_STACK (guchar*) current_frame) &&
-                                       ((guchar*) current_frame IS_BEFORE_ON_STACK stack_top)) {
-                               ips [current_frame_index] = (guchar *)CURRENT_FRAME_GET_RETURN_ADDRESS (current_frame);
-                               current_frame_index ++;
-                               stack_top = current_frame;
-                               current_frame = (guchar *)CURRENT_FRAME_GET_BASE_POINTER (current_frame);
-                       }
-#else
-                               call_chain_strategy = MONO_PROFILER_CALL_CHAIN_GLIBC;
-#endif
-                       }
-                       
-                       if (call_chain_strategy == MONO_PROFILER_CALL_CHAIN_GLIBC) {
-#if GLIBC_PROFILER_BACKTRACE
-                               current_frame_index = backtrace ((void**) & ips [1], call_chain_depth);
-#else
-                               call_chain_strategy = MONO_PROFILER_CALL_CHAIN_MANAGED;
-#endif
-                       }
-
-                       if (call_chain_strategy == MONO_PROFILER_CALL_CHAIN_MANAGED) {
-                               MonoDomain *domain = mono_domain_get ();
-                               if (domain != NULL) {
-                                       MonoLMF *lmf = NULL;
-                                       MonoJitInfo *ji;
-                                       MonoJitInfo res;
-                                       MonoContext new_mono_context;
-                                       int native_offset;
-                                       ji = mono_find_jit_info (domain, jit_tls, &res, NULL, &mono_context,
-                                                       &new_mono_context, NULL, &lmf, &native_offset, NULL);
-                                       while ((ji != NULL) && (current_frame_index <= call_chain_depth)) {
-                                               ips [current_frame_index] = (guchar *)MONO_CONTEXT_GET_IP (&new_mono_context);
-                                               current_frame_index ++;
-                                               mono_context = new_mono_context;
-                                               ji = mono_find_jit_info (domain, jit_tls, &res, NULL, &mono_context,
-                                                               &new_mono_context, NULL, &lmf, &native_offset, NULL);
-                                       }
-                               }
-                       }
-               }
-               
-               mono_profiler_stat_call_chain (current_frame_index, & ips [0], ctx);
-       }
-}
-
 static MonoNativeThreadId sampling_thread;
 
 static gint32 profiler_signals_sent;
@@ -342,7 +253,9 @@ MONO_SIG_HANDLER_FUNC (static, profiler_signal_handler)
        int hp_save_index = mono_hazard_pointer_save_for_signal_handler ();
 
        mono_thread_info_set_is_async_context (TRUE);
-       per_thread_profiler_hit (ctx);
+
+       MONO_PROFILER_RAISE (sample_hit, (mono_arch_ip_from_context (ctx), ctx));
+
        mono_thread_info_set_is_async_context (FALSE);
 
        mono_hazard_pointer_restore_for_signal_handler (hp_save_index);
@@ -521,7 +434,7 @@ static volatile gint32 sampling_thread_running;
 static clock_serv_t sampling_clock_service;
 
 static void
-clock_init (void)
+clock_init (MonoProfilerSampleMode mode)
 {
        kern_return_t ret;
 
@@ -584,10 +497,10 @@ clock_sleep_ns_abs (guint64 ns_abs)
 clockid_t sampling_posix_clock;
 
 static void
-clock_init (void)
+clock_init (MonoProfilerSampleMode mode)
 {
-       switch (mono_profiler_get_sampling_mode ()) {
-       case MONO_PROFILER_STAT_MODE_PROCESS: {
+       switch (mode) {
+       case MONO_PROFILER_SAMPLE_MODE_PROCESS: {
        /*
         * If we don't have clock_nanosleep (), measuring the process time
         * makes very little sense as we can only use nanosleep () to sleep on
@@ -609,7 +522,7 @@ clock_init (void)
 
                // fallthrough
        }
-       case MONO_PROFILER_STAT_MODE_REAL: sampling_posix_clock = CLOCK_MONOTONIC; break;
+       case MONO_PROFILER_SAMPLE_MODE_REAL: sampling_posix_clock = CLOCK_MONOTONIC; break;
        default: g_assert_not_reached (); break;
        }
 }
@@ -701,8 +614,6 @@ sampling_thread_func (void *data)
        mono_threads_attach_tools_thread ();
        mono_native_thread_set_name (mono_native_thread_id_get (), "Profiler sampler");
 
-       gint64 rate = 1000000000 / mono_profiler_get_sampling_rate ();
-
        int old_policy;
        struct sched_param old_sched;
        pthread_getschedparam (pthread_self (), &old_policy, &old_sched);
@@ -724,12 +635,30 @@ sampling_thread_func (void *data)
        struct sched_param sched = { .sched_priority = sched_get_priority_max (SCHED_FIFO) };
        pthread_setschedparam (pthread_self (), SCHED_FIFO, &sched);
 
-       clock_init ();
+       MonoProfilerSampleMode mode;
+
+init:
+       mono_profiler_get_sample_mode (NULL, &mode, NULL);
 
-       guint64 sleep = clock_get_time_ns ();
+       if (mode == MONO_PROFILER_SAMPLE_MODE_NONE) {
+               mono_profiler_sampling_thread_sleep ();
+               goto init;
+       }
+
+       clock_init (mode);
 
-       while (InterlockedRead (&sampling_thread_running)) {
-               sleep += rate;
+       for (guint64 sleep = clock_get_time_ns (); InterlockedRead (&sampling_thread_running); clock_sleep_ns_abs (sleep)) {
+               uint64_t freq;
+               MonoProfilerSampleMode new_mode;
+
+               mono_profiler_get_sample_mode (NULL, &new_mode, &freq);
+
+               if (new_mode != mode) {
+                       clock_cleanup ();
+                       goto init;
+               }
+
+               sleep += 1000000000 / freq;
 
                FOREACH_THREAD_SAFE (info) {
                        /* info should never be this thread as we're a tools thread. */
@@ -746,8 +675,6 @@ sampling_thread_func (void *data)
                        mono_threads_pthread_kill (info, profiler_signal);
                        InterlockedIncrement (&profiler_signals_sent);
                } FOREACH_THREAD_SAFE_END
-
-               clock_sleep_ns_abs (sleep);
        }
 
        InterlockedWrite (&sampling_thread_exiting, 1);
index d78ef80dfbb9e7d5fb18722c5e1306ddb6a6920e..f36a3fd528ae4e964fdac0435b760bc47c9c3d8d 100644 (file)
@@ -3183,17 +3183,6 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
 
        cpos = bb->max_offset;
 
-       if (cfg->prof_options & MONO_PROFILE_COVERAGE) {
-               //MonoCoverageInfo *cov = mono_get_coverage_info (cfg->method);
-               //g_assert (!mono_compile_aot);
-               //cpos += 6;
-               //if (bb->cil_code)
-               //      cov->data [bb->dfn].iloffset = bb->cil_code - cfg->cil_code;
-               /* this is not thread save, but good enough */
-               /* fixme: howto handle overflows? */
-               //x86_inc_mem (code, &cov->data [bb->dfn].count); 
-       }
-
        MONO_BB_FOR_EACH_INS (bb, ins) {
                offset = code - cfg->native_code;
 
@@ -4918,9 +4907,6 @@ mono_arch_emit_prolog (MonoCompile *cfg)
                MonoInst *ins;
                bb->max_offset = max_offset;
 
-               if (cfg->prof_options & MONO_PROFILE_COVERAGE)
-                       max_offset += 6; 
-
                MONO_BB_FOR_EACH_INS (bb, ins)
                        max_offset += ins_native_length (cfg, ins);
        }
index 77c69bb937514fec3a43b0fdfa691a26ca555a97..0f3c217c65420bcbeb763ddaee76d6d812814784 100644 (file)
@@ -1218,6 +1218,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);
@@ -1648,6 +1649,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 ();
        }
@@ -3938,9 +3943,11 @@ mini_init (const char *filename, const char *runtime_version)
 
        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_RAISE (thread_name, (MONO_NATIVE_THREAD_ID_TO_UINT (mono_native_thread_id_get ()), "Main"));
        }
 
+       mono_profiler_started ();
+
        if (debug_options.collect_pagefault_stats)
                mono_aot_set_make_unreadable (TRUE);
 
@@ -4018,10 +4025,10 @@ mini_init (const char *filename, const char *runtime_version)
        mono_thread_attach (domain);
 #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 ();
 
@@ -4052,8 +4059,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", TRUE);
+       register_icall (mono_profiler_raise_method_leave, "mono_profiler_raise_method_leave", "void 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);
@@ -4349,7 +4356,7 @@ 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 ();
 
 #ifndef DISABLE_COM
@@ -4373,7 +4380,9 @@ mini_cleanup (MonoDomain *domain)
 
        mono_threadpool_cleanup ();
 
-       mono_profiler_shutdown ();
+       MONO_PROFILER_RAISE (runtime_shutdown, ());
+
+       mono_profiler_cleanup ();
 
        free_jit_tls_data ((MonoJitTlsData *)mono_tls_get_jit_tls ());
 
index 2f3cd3ebca373f285a384dd5161b46c1baee8f94..bab41317cc6012bd583e8b0f9063ed8ad80bbb21 100644 (file)
@@ -2985,15 +2985,6 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
        if (cfg->verbose_level > 2)
                g_print ("Basic block %d starting at offset 0x%x\n", bb->block_num, bb->native_offset);
 
-       if ((cfg->prof_options & MONO_PROFILE_COVERAGE) && cfg->coverage_info) {
-               MonoProfileCoverageInfo *cov = cfg->coverage_info;
-               g_assert (!mono_compile_aot);
-               cov->data [bb->dfn].cil_code = bb->cil_code;
-               /* This is not thread save, but good enough */
-               S390_SET (code, s390_r1, &cov->data [bb->dfn].count);
-               s390_alsi (code, 0, s390_r1, 1);
-       }
-
        MONO_BB_FOR_EACH_INS (bb, ins) {
                offset = code - cfg->native_code;
 
@@ -5672,9 +5663,6 @@ mono_arch_emit_prolog (MonoCompile *cfg)
                MonoInst *ins;
                bb->max_offset = max_offset;
 
-               if (cfg->prof_options & MONO_PROFILE_COVERAGE)
-                       max_offset += 6; 
-
                MONO_BB_FOR_EACH_INS (bb, ins)
                        max_offset += ((guint8 *)ins_get_spec (ins->opcode))[MONO_INST_LEN];
        }
@@ -6501,7 +6489,7 @@ get_delegate_invoke_impl (MonoTrampInfo **info, gboolean has_target, guint32 par
                mono_arch_flush_icache (start, size);
        }
 
-       mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_DELEGATE_INVOKE, NULL);
+       MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_DELEGATE_INVOKE, NULL));
 
        if (has_target) {
                *info = mono_tramp_info_create ("delegate_invoke_impl_has_target", start, code - start, NULL, NULL);
@@ -6787,7 +6775,7 @@ mono_arch_build_imt_trampoline (MonoVTable *vtable, MonoDomain *domain,
        }
 
        mono_arch_flush_icache ((guint8*)start, (code - start));
-       mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_IMT_TRAMPOLINE, NULL);
+       MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_IMT_TRAMPOLINE, NULL));
 
        if (!fail_tramp) 
                mono_stats.imt_trampolines_size += (code - start);
index 29c6f96b5c00f0a3fc4b87e03b411e598a4f11f4..1edddbd139c18646423c10962784bb75d46732c2 100644 (file)
@@ -2407,10 +2407,6 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
 
        cpos = bb->max_offset;
 
-       if (cfg->prof_options & MONO_PROFILE_COVERAGE) {
-               NOT_IMPLEMENTED;
-       }
-
        MONO_BB_FOR_EACH_INS (bb, ins) {
                guint8* code_start;
 
index 2d3c64f22e62ba0014bf63ff7dcb4f40619c4f84..3852baf81f1268a1862a32274c4d3a67c4ea3ff6 100644 (file)
@@ -271,11 +271,15 @@ thread_timer_expired (HANDLE thread)
 
        context.ContextFlags = CONTEXT_CONTROL;
        if (GetThreadContext (thread, &context)) {
+               guchar *ip;
+
 #ifdef _WIN64
-               mono_profiler_stat_hit ((guchar *) context.Rip, &context);
+               ip = (guchar *) context.Rip;
 #else
-               mono_profiler_stat_hit ((guchar *) context.Eip, &context);
+               ip = (guchar *) context.Eip;
 #endif
+
+               MONO_PROFILER_RAISE (sample_hit, (ip, &context));
        }
 }
 
index 7f7758c517e2df5b4d18f24a97612aa6cba88a41..ad1637319c864f3875104b3fc4f05c364319f8af 100644 (file)
@@ -2427,16 +2427,6 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
 
        cpos = bb->max_offset;
 
-       if ((cfg->prof_options & MONO_PROFILE_COVERAGE) && cfg->coverage_info) {
-               MonoProfileCoverageInfo *cov = cfg->coverage_info;
-               g_assert (!cfg->compile_aot);
-               cpos += 6;
-
-               cov->data [bb->dfn].cil_code = bb->cil_code;
-               /* this is not thread save, but good enough */
-               x86_inc_mem (code, &cov->data [bb->dfn].count); 
-       }
-
        offset = code - cfg->native_code;
 
        mono_debug_open_block (cfg, bb, offset);
@@ -5165,8 +5155,6 @@ mono_arch_emit_prolog (MonoCompile *cfg)
                        MonoInst *ins;
                        bb->max_offset = max_offset;
 
-                       if (cfg->prof_options & MONO_PROFILE_COVERAGE)
-                               max_offset += 6;
                        /* max alignment for loops */
                        if ((cfg->opt & MONO_OPT_LOOP) && bb_is_loop_start (bb))
                                max_offset += LOOP_ALIGNMENT;
@@ -5666,7 +5654,7 @@ mono_arch_build_imt_trampoline (MonoVTable *vtable, MonoDomain *domain, MonoIMTC
                g_free (buff);
        }
 
-       mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_IMT_TRAMPOLINE, NULL);
+       MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_IMT_TRAMPOLINE, NULL));
 
        mono_tramp_info_register (mono_tramp_info_create (NULL, start, code - start, NULL, unwind_ops), domain);
 
@@ -5937,7 +5925,7 @@ get_delegate_invoke_impl (MonoTrampInfo **info, gboolean has_target, guint32 par
                if (!has_target)
                        g_free (buff);
        }
-       mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_DELEGATE_INVOKE, NULL);
+       MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_DELEGATE_INVOKE, NULL));
 
        return start;
 }
@@ -5977,7 +5965,7 @@ get_delegate_virtual_invoke_impl (MonoTrampInfo **info, gboolean load_imt_reg, i
        /* Load the vtable */
        x86_mov_reg_membase (code, X86_EAX, X86_ECX, MONO_STRUCT_OFFSET (MonoObject, vtable), 4);
        x86_jump_membase (code, X86_EAX, offset);
-       mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_DELEGATE_INVOKE, NULL);
+       MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_DELEGATE_INVOKE, NULL));
 
        tramp_name = mono_get_delegate_virtual_invoke_impl_name (load_imt_reg, offset);
        *info = mono_tramp_info_create (tramp_name, start, code - start, NULL, unwind_ops);
index 10d6eac8b16d0b4a0306565c4a7642c07e5f1edd..d058547fc414d8338372721c6ae99c21b30e05de 100644 (file)
@@ -2230,9 +2230,6 @@ mono_codegen (MonoCompile *cfg)
                        mono_bb_deduplicate_op_il_seq_points (cfg, bb);
        }
 
-       if (cfg->prof_options & MONO_PROFILE_COVERAGE)
-               cfg->coverage_info = mono_profiler_coverage_alloc (cfg->method, cfg->num_bblocks);
-
        code = mono_arch_emit_prolog (cfg);
 
        cfg->code_len = code - cfg->native_code;
@@ -2378,7 +2375,7 @@ mono_codegen (MonoCompile *cfg)
        } else {
                mono_domain_code_commit (code_domain, cfg->native_code, cfg->code_size, cfg->code_len);
        }
-       mono_profiler_code_buffer_new (cfg->native_code, cfg->code_len, MONO_PROFILER_CODE_BUFFER_METHOD, cfg->method);
+       MONO_PROFILER_RAISE (jit_code_buffer, (cfg->native_code, cfg->code_len, MONO_PROFILER_CODE_BUFFER_METHOD, cfg->method));
        
        mono_arch_flush_icache (cfg->native_code, cfg->code_len);
 
@@ -3097,8 +3094,7 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, JitFl
        static char *verbose_method_name;
 
        InterlockedIncrement (&mono_jit_stats.methods_compiled);
-       if (mono_profiler_get_events () & MONO_PROFILE_JIT_COMPILATION)
-               mono_profiler_method_jit (method);
+       MONO_PROFILER_RAISE (jit_begin, (method));
        if (MONO_METHOD_COMPILE_BEGIN_ENABLED ())
                MONO_PROBE_METHOD_COMPILE_BEGIN (method);
 
@@ -3161,7 +3157,6 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, JitFl
        cfg->method = method_to_compile;
        cfg->mempool = mono_mempool_new ();
        cfg->opt = opts;
-       cfg->prof_options = mono_profiler_get_events ();
        cfg->run_cctors = run_cctors;
        cfg->domain = domain;
        cfg->verbose_level = mini_verbose;
@@ -4039,7 +4034,6 @@ mono_jit_compile_method_inner (MonoMethod *method, MonoDomain *target_domain, in
        MonoJitInfo *jinfo, *info;
        MonoVTable *vtable;
        MonoException *ex = NULL;
-       guint32 prof_options;
        GTimer *jit_timer;
        MonoMethod *prof_method, *shared;
 
@@ -4070,7 +4064,7 @@ mono_jit_compile_method_inner (MonoMethod *method, MonoDomain *target_domain, in
                if (!jinfo)
                        jinfo = mono_jit_info_table_find (mono_domain_get (), (char *)code);
                if (jinfo)
-                       mono_profiler_method_end_jit (method, jinfo, MONO_PROFILE_OK);
+                       MONO_PROFILER_RAISE (jit_done, (method, jinfo));
                return code;
        } else if ((method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
                const char *name = method->name;
@@ -4211,8 +4205,7 @@ mono_jit_compile_method_inner (MonoMethod *method, MonoDomain *target_domain, in
        }
 
        if (ex) {
-               if (cfg->prof_options & MONO_PROFILE_JIT_COMPILATION)
-                       mono_profiler_method_end_jit (method, NULL, MONO_PROFILE_FAILED);
+               MONO_PROFILER_RAISE (jit_failed, (method));
 
                mono_destroy_compile (cfg);
                mono_error_set_exception_instance (error, ex);
@@ -4255,8 +4248,6 @@ mono_jit_compile_method_inner (MonoMethod *method, MonoDomain *target_domain, in
 
        jinfo = cfg->jit_info;
 
-       prof_options = cfg->prof_options;
-
        /*
         * Update global stats while holding a lock, instead of doing many
         * InterlockedIncrement operations during JITting.
@@ -4321,19 +4312,16 @@ mono_jit_compile_method_inner (MonoMethod *method, MonoDomain *target_domain, in
                return NULL;
        }
 
-       if (prof_options & MONO_PROFILE_JIT_COMPILATION) {
-               if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE) {
-                       if (mono_marshal_method_from_wrapper (method)) {
-                               /* Native func wrappers have no method */
-                               /* The profiler doesn't know about wrappers, so pass the original icall method */
-                               mono_profiler_method_end_jit (mono_marshal_method_from_wrapper (method), jinfo, MONO_PROFILE_OK);
-                       }
-               }
-               mono_profiler_method_end_jit (method, jinfo, MONO_PROFILE_OK);
-               if (prof_method != method) {
-                       mono_profiler_method_end_jit (prof_method, jinfo, MONO_PROFILE_OK);
+       if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE) {
+               if (mono_marshal_method_from_wrapper (method)) {
+                       /* Native func wrappers have no method */
+                       /* The profiler doesn't know about wrappers, so pass the original icall method */
+                       MONO_PROFILER_RAISE (jit_done, (mono_marshal_method_from_wrapper (method), jinfo));
                }
        }
+       MONO_PROFILER_RAISE (jit_done, (method, jinfo));
+       if (prof_method != method)
+               MONO_PROFILER_RAISE (jit_done, (prof_method, jinfo));
 
        if (!(method->wrapper_type == MONO_WRAPPER_REMOTING_INVOKE ||
                  method->wrapper_type == MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK ||
index 1fcb2f1d892789f35101633f0ec5c7a9f9498535..fea3746e5dac50a59ba8071bdec9f635a84f2dd5 100644 (file)
@@ -1682,7 +1682,6 @@ typedef struct {
        guint            epilog_end;
        regmask_t        used_int_regs;
        guint32          opt;
-       guint32          prof_options;
        guint32          flags;
        guint32          comp_done;
        guint32          verbose_level;
@@ -1761,7 +1760,7 @@ typedef struct {
        gpointer         debug_info;
        guint32          lmf_offset;
     guint16          *intvars;
-       MonoProfileCoverageInfo *coverage_info;
+       MonoProfilerCoverageInfo *coverage_info;
        GHashTable       *token_info_hash;
        MonoCompileArch  arch;
        guint32          inline_depth;
index 8a4ba056ee089d3d40d0b694957111d81e171142..926020246e28eb203b1acf3fb77fdc0e7428e440 100644 (file)
@@ -63,3 +63,4 @@ PATCH_INFO(SET_TLS_TRAMP, "set_tls_tramp")
  * Same as JIT_ICALL_ADDR, but not treated as a call.
  */
 PATCH_INFO(JIT_ICALL_ADDR_NOCALL, "jit_icall_addr_nocall")
+PATCH_INFO(PROFILER_ALLOCATION_COUNT, "profiler_allocation_count")
index 9cf67dd282514ca661d988d4e63b63fad0d99d93..17a6849ed2564315e2f81d0b93601fcac42e779f 100644 (file)
@@ -162,7 +162,7 @@ mono_arch_get_gsharedvt_arg_trampoline (MonoDomain *domain, gpointer arg, gpoint
        g_assert ((code - start) < buf_len);
 
        mono_arch_flush_icache (start, code - start);
-       mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_GENERICS_TRAMPOLINE, NULL);
+       MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_GENERICS_TRAMPOLINE, NULL));
 
        mono_tramp_info_register (mono_tramp_info_create (NULL, start, code - start, NULL, NULL), domain);
 
index 634203bc2e0c92404a2551b3241ccf6c47afae64..cf519e1c9298d378f62a1209838e4452966aef96 100644 (file)
@@ -71,7 +71,7 @@ mono_arch_get_unbox_trampoline (MonoMethod *m, gpointer addr)
        g_assert_checked (mono_arch_unwindinfo_validate_size (unwind_ops, MONO_TRAMPOLINE_UNWINDINFO_SIZE(0)));
 
        mono_arch_flush_icache (start, code - start);
-       mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_UNBOX_TRAMPOLINE, m);
+       MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_UNBOX_TRAMPOLINE, m));
 
        mono_tramp_info_register (mono_tramp_info_create (NULL, start, code - start, NULL, unwind_ops), domain);
 
@@ -112,7 +112,7 @@ mono_arch_get_static_rgctx_trampoline (gpointer arg, gpointer addr)
        g_assert_checked (mono_arch_unwindinfo_validate_size (unwind_ops, MONO_TRAMPOLINE_UNWINDINFO_SIZE(0)));
 
        mono_arch_flush_icache (start, code - start);
-       mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_GENERICS_TRAMPOLINE, NULL);
+       MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_GENERICS_TRAMPOLINE, NULL));
 
        mono_tramp_info_register (mono_tramp_info_create (NULL, start, code - start, NULL, unwind_ops), domain);
 
@@ -162,7 +162,7 @@ mono_arch_patch_callsite (guint8 *method_start, guint8 *orig_code, guint8 *addr)
                                addr = thunk_start;
                                g_assert ((((guint64)(addr)) >> 32) == 0);
                                mono_arch_flush_icache (thunk_start, thunk_code - thunk_start);
-                               mono_profiler_code_buffer_new (thunk_start, thunk_code - thunk_start, MONO_PROFILER_CODE_BUFFER_HELPER, NULL);
+                               MONO_PROFILER_RAISE (jit_code_buffer, (thunk_start, thunk_code - thunk_start, MONO_PROFILER_CODE_BUFFER_HELPER, NULL));
                        }
                        if (can_write) {
                                InterlockedExchange ((gint32*)(orig_code - 4), ((gint64)addr - (gint64)orig_code));
@@ -197,7 +197,7 @@ mono_arch_create_llvm_native_thunk (MonoDomain *domain, guint8 *addr)
        *(guint64*)thunk_code = (guint64)addr;
        addr = thunk_start;
        mono_arch_flush_icache (thunk_start, thunk_code - thunk_start);
-       mono_profiler_code_buffer_new (thunk_start, thunk_code - thunk_start, MONO_PROFILER_CODE_BUFFER_HELPER, NULL);
+       MONO_PROFILER_RAISE (jit_code_buffer, (thunk_start, thunk_code - thunk_start, MONO_PROFILER_CODE_BUFFER_HELPER, NULL));
        return addr;
 }
 #endif /* !DISABLE_JIT */
@@ -574,7 +574,7 @@ mono_arch_create_generic_trampoline (MonoTrampolineType tramp_type, MonoTrampInf
        g_assert_checked (mono_arch_unwindinfo_validate_size (unwind_ops, MONO_MAX_TRAMPOLINE_UNWINDINFO_SIZE));
 
        mono_arch_flush_icache (buf, code - buf);
-       mono_profiler_code_buffer_new (buf, code - buf, MONO_PROFILER_CODE_BUFFER_HELPER, NULL);
+       MONO_PROFILER_RAISE (jit_code_buffer, (buf, code - buf, MONO_PROFILER_CODE_BUFFER_HELPER, NULL));
 
        tramp_name = mono_get_generic_trampoline_name (tramp_type);
        *info = mono_tramp_info_create (tramp_name, buf, code - buf, ji, unwind_ops);
@@ -631,7 +631,7 @@ mono_arch_create_specific_trampoline (gpointer arg1, MonoTrampolineType tramp_ty
                *code_len = size;
 
        mono_arch_flush_icache (buf, size);
-       mono_profiler_code_buffer_new (buf, code - buf, MONO_PROFILER_CODE_BUFFER_SPECIFIC_TRAMPOLINE, mono_get_generic_trampoline_simple_name (tramp_type));
+       MONO_PROFILER_RAISE (jit_code_buffer, (buf, code - buf, MONO_PROFILER_CODE_BUFFER_SPECIFIC_TRAMPOLINE, mono_get_generic_trampoline_simple_name (tramp_type)));
 
        return buf;
 }      
@@ -724,7 +724,7 @@ mono_arch_create_rgctx_lazy_fetch_trampoline (guint32 slot, MonoTrampInfo **info
        }
 
        mono_arch_flush_icache (buf, code - buf);
-       mono_profiler_code_buffer_new (buf, code - buf, MONO_PROFILER_CODE_BUFFER_GENERICS_TRAMPOLINE, NULL);
+       MONO_PROFILER_RAISE (jit_code_buffer, (buf, code - buf, MONO_PROFILER_CODE_BUFFER_GENERICS_TRAMPOLINE, NULL));
 
        g_assert (code - buf <= tramp_size);
        g_assert_checked (mono_arch_unwindinfo_validate_size (unwind_ops, MONO_TRAMPOLINE_UNWINDINFO_SIZE(0)));
@@ -761,7 +761,7 @@ mono_arch_create_general_rgctx_lazy_fetch_trampoline (MonoTrampInfo **info, gboo
        amd64_jump_reg (code, AMD64_R11);
 
        mono_arch_flush_icache (buf, code - buf);
-       mono_profiler_code_buffer_new (buf, code - buf, MONO_PROFILER_CODE_BUFFER_GENERICS_TRAMPOLINE, NULL);
+       MONO_PROFILER_RAISE (jit_code_buffer, (buf, code - buf, MONO_PROFILER_CODE_BUFFER_GENERICS_TRAMPOLINE, NULL));
 
        g_assert (code - buf <= tramp_size);
        g_assert_checked (mono_arch_unwindinfo_validate_size (unwind_ops, MONO_TRAMPOLINE_UNWINDINFO_SIZE(0)));
@@ -855,7 +855,7 @@ mono_arch_create_handler_block_trampoline (MonoTrampInfo **info, gboolean aot)
        amd64_jump_reg (code, AMD64_RAX);
 
        mono_arch_flush_icache (buf, code - buf);
-       mono_profiler_code_buffer_new (buf, code - buf, MONO_PROFILER_CODE_BUFFER_HELPER, NULL);
+       MONO_PROFILER_RAISE (jit_code_buffer, (buf, code - buf, MONO_PROFILER_CODE_BUFFER_HELPER, NULL));
        g_assert (code - buf <= tramp_size);
        g_assert_checked (mono_arch_unwindinfo_validate_size (unwind_ops, MONO_TRAMPOLINE_UNWINDINFO_SIZE(0)));
 
@@ -992,7 +992,7 @@ mono_arch_create_sdb_trampoline (gboolean single_step, MonoTrampInfo **info, gbo
        amd64_ret (code);
 
        mono_arch_flush_icache (code, code - buf);
-       mono_profiler_code_buffer_new (buf, code - buf, MONO_PROFILER_CODE_BUFFER_HELPER, NULL);
+       MONO_PROFILER_RAISE (jit_code_buffer, (buf, code - buf, MONO_PROFILER_CODE_BUFFER_HELPER, NULL));
        g_assert (code - buf <= tramp_size);
        g_assert_checked (mono_arch_unwindinfo_validate_size (unwind_ops, MONO_MAX_TRAMPOLINE_UNWINDINFO_SIZE));
 
@@ -1151,7 +1151,7 @@ mono_arch_get_enter_icall_trampoline (MonoTrampInfo **info)
        g_assert (code - start < buf_len);
 
        mono_arch_flush_icache (start, code - start);
-       mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL);
+       MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL));
 
        if (info)
                *info = mono_tramp_info_create ("enter_icall_trampoline", start, code - start, ji, unwind_ops);
index 13c09ac33a72ca821bbd6085e2568cf7596171d3..82d3e95868cbc7cfeb73749282c80fbe1a644594 100644 (file)
@@ -395,7 +395,7 @@ mono_arch_create_generic_trampoline (MonoTrampolineType tramp_type, MonoTrampInf
 
        /* Flush instruction cache, since we've generated code */
        mono_arch_flush_icache (buf, code - buf);
-       mono_profiler_code_buffer_new (buf, code - buf, MONO_PROFILER_CODE_BUFFER_HELPER, NULL);
+       MONO_PROFILER_RAISE (jit_code_buffer, (buf, code - buf, MONO_PROFILER_CODE_BUFFER_HELPER, NULL));
 
        /* Sanity check */
        g_assert ((code - buf) <= buf_len);
@@ -465,7 +465,7 @@ mono_arch_create_specific_trampoline (gpointer arg1, MonoTrampolineType tramp_ty
 
        /* Flush instruction cache, since we've generated code */
        mono_arch_flush_icache (buf, code - buf);
-       mono_profiler_code_buffer_new (buf, code - buf, MONO_PROFILER_CODE_BUFFER_SPECIFIC_TRAMPOLINE, mono_get_generic_trampoline_simple_name (tramp_type));
+       MONO_PROFILER_RAISE (jit_code_buffer, (buf, code - buf, MONO_PROFILER_CODE_BUFFER_SPECIFIC_TRAMPOLINE, mono_get_generic_trampoline_simple_name (tramp_type)));
 
        g_assert ((code - buf) <= size);
 
@@ -502,7 +502,7 @@ mono_arch_get_unbox_trampoline (MonoMethod *m, gpointer addr)
        *(guint32*)code = (guint32)addr;
        code += 4;
        mono_arch_flush_icache (start, code - start);
-       mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_UNBOX_TRAMPOLINE, m);
+       MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_UNBOX_TRAMPOLINE, m));
        g_assert ((code - start) <= size);
        /*g_print ("unbox trampoline at %d for %s:%s\n", this_pos, m->klass->name, m->name);
        g_print ("unbox code is at %p for method at %p\n", start, addr);*/
@@ -534,7 +534,7 @@ mono_arch_get_static_rgctx_trampoline (gpointer arg, gpointer addr)
        g_assert ((code - start) <= buf_len);
 
        mono_arch_flush_icache (start, code - start);
-       mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_GENERICS_TRAMPOLINE, NULL);
+       MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_GENERICS_TRAMPOLINE, NULL));
 
        mono_tramp_info_register (mono_tramp_info_create (NULL, start, code - start, NULL, unwind_ops), domain);
 
@@ -648,7 +648,7 @@ mono_arch_create_rgctx_lazy_fetch_trampoline (guint32 slot, MonoTrampInfo **info
        }
 
        mono_arch_flush_icache (buf, code - buf);
-       mono_profiler_code_buffer_new (buf, code - buf, MONO_PROFILER_CODE_BUFFER_GENERICS_TRAMPOLINE, NULL);
+       MONO_PROFILER_RAISE (jit_code_buffer, (buf, code - buf, MONO_PROFILER_CODE_BUFFER_GENERICS_TRAMPOLINE, NULL));
 
        g_assert (code - buf <= tramp_size);
 
@@ -683,7 +683,7 @@ mono_arch_create_general_rgctx_lazy_fetch_trampoline (MonoTrampInfo **info, gboo
        code = emit_bx (code, ARMREG_R1);
 
        mono_arch_flush_icache (buf, code - buf);
-       mono_profiler_code_buffer_new (buf, code - buf, MONO_PROFILER_CODE_BUFFER_GENERICS_TRAMPOLINE, NULL);
+       MONO_PROFILER_RAISE (jit_code_buffer, (buf, code - buf, MONO_PROFILER_CODE_BUFFER_GENERICS_TRAMPOLINE, NULL));
 
        g_assert (code - buf <= tramp_size);
 
@@ -741,7 +741,7 @@ mono_arch_create_handler_block_trampoline (MonoTrampInfo **info, gboolean aot)
        }
 
        mono_arch_flush_icache (buf, code - buf);
-       mono_profiler_code_buffer_new (buf, code - buf, MONO_PROFILER_CODE_BUFFER_HELPER, NULL);
+       MONO_PROFILER_RAISE (jit_code_buffer, (buf, code - buf, MONO_PROFILER_CODE_BUFFER_HELPER, NULL));
        g_assert (code - buf <= tramp_size);
 
        *info = mono_tramp_info_create ("handler_block_trampoline", buf, code - buf, ji, unwind_ops);
@@ -824,7 +824,7 @@ mono_arch_create_sdb_trampoline (gboolean single_step, MonoTrampInfo **info, gbo
        ARM_LDM (code, ARMREG_IP, 0xffff);
 
        mono_arch_flush_icache (buf, code - buf);
-       mono_profiler_code_buffer_new (buf, code - buf, MONO_PROFILER_CODE_BUFFER_HELPER, NULL);
+       MONO_PROFILER_RAISE (jit_code_buffer, (buf, code - buf, MONO_PROFILER_CODE_BUFFER_HELPER, NULL));
 
        const char *tramp_name = single_step ? "sdb_single_step_trampoline" : "sdb_breakpoint_trampoline";
        *info = mono_tramp_info_create (tramp_name, buf, code - buf, ji, unwind_ops);
@@ -980,7 +980,7 @@ mono_arch_get_enter_icall_trampoline (MonoTrampInfo **info)
        g_assert (code - start < buf_len);
 
        mono_arch_flush_icache (start, code - start);
-       mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL);
+       MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL));
 
        if (info)
                *info = mono_tramp_info_create ("enter_icall_trampoline", start, code - start, ji, unwind_ops);
@@ -1156,7 +1156,7 @@ mono_arch_get_gsharedvt_arg_trampoline (MonoDomain *domain, gpointer arg, gpoint
        g_assert ((code - buf) <= buf_len);
 
        mono_arch_flush_icache (buf, code - buf);
-       mono_profiler_code_buffer_new (buf, code - buf, MONO_PROFILER_CODE_BUFFER_GENERICS_TRAMPOLINE, NULL);
+       MONO_PROFILER_RAISE (jit_code_buffer, (buf, code - buf, MONO_PROFILER_CODE_BUFFER_GENERICS_TRAMPOLINE, NULL));
 
        mono_tramp_info_register (mono_tramp_info_create (NULL, buf, code - buf, NULL, NULL), domain);
 
index cf4057a9434aba6890c5863629d39bb761c0cb3e..45e18d880aad9724d70a4bffa49cb106393ceebb 100644 (file)
@@ -557,7 +557,7 @@ mono_arch_create_handler_block_trampoline (MonoTrampInfo **info, gboolean aot)
        arm_brx (code, ARMREG_IP0);
 
        mono_arch_flush_icache (buf, code - buf);
-       mono_profiler_code_buffer_new (buf, code - buf, MONO_PROFILER_CODE_BUFFER_HELPER, NULL);
+       MONO_PROFILER_RAISE (jit_code_buffer, (buf, code - buf, MONO_PROFILER_CODE_BUFFER_HELPER, NULL));
        g_assert (code - buf <= tramp_size);
 
        *info = mono_tramp_info_create ("handler_block_trampoline", buf, code - buf, ji, unwind_ops);
@@ -806,7 +806,7 @@ mono_arch_get_enter_icall_trampoline (MonoTrampInfo **info)
        g_assert (code - start < buf_len);
 
        mono_arch_flush_icache (start, code - start);
-       mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL);
+       MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL));
 
        if (info)
                *info = mono_tramp_info_create ("enter_icall_trampoline", start, code - start, ji, unwind_ops);
index 56f1839ae4218621055cf9dd7884439d6a9c1d0d..b0333d3cf18a92c3cfbca8fdec243131d1216168 100644 (file)
@@ -108,7 +108,7 @@ mono_arch_get_unbox_trampoline (MonoMethod *method, gpointer addr)
        g_assert ((code - start) <= 28);
 
        mono_arch_flush_icache (start, code - start);
-       mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_UNBOX_TRAMPOLINE, method);
+       MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_UNBOX_TRAMPOLINE, method));
 
        snprintf(trampName, sizeof(trampName), "%s_unbox_trampoline", method->name);
 
@@ -354,7 +354,7 @@ mono_arch_create_generic_trampoline (MonoTrampolineType tramp_type, MonoTrampInf
 
        /* Flush instruction cache, since we've generated code */
        mono_arch_flush_icache (code, buf - code);
-       mono_profiler_code_buffer_new (buf, code - buf, MONO_PROFILER_CODE_BUFFER_GENERICS_TRAMPOLINE, NULL);
+       MONO_PROFILER_RAISE (jit_code_buffer, (buf, code - buf, MONO_PROFILER_CODE_BUFFER_GENERICS_TRAMPOLINE, NULL));
        
        g_assert (info);
        tramp_name = mono_get_generic_trampoline_name (tramp_type);
@@ -420,8 +420,9 @@ mono_arch_create_specific_trampoline (gpointer arg1, MonoTrampolineType tramp_ty
 
        /* Flush instruction cache, since we've generated code */
        mono_arch_flush_icache (code, buf - code);
-       mono_profiler_code_buffer_new (buf, code - buf, MONO_PROFILER_CODE_BUFFER_SPECIFIC_TRAMPOLINE, 
-                                      (void *) mono_get_generic_trampoline_simple_name (tramp_type));
+       MONO_PROFILER_RAISE (jit_code_buffer, (buf, code - buf,
+                            MONO_PROFILER_CODE_BUFFER_SPECIFIC_TRAMPOLINE,
+                            (void *) mono_get_generic_trampoline_simple_name (tramp_type)));
 
        /* Sanity check */
        g_assert ((buf - code) <= SPECIFIC_TRAMPOLINE_SIZE);
@@ -536,7 +537,7 @@ mono_arch_create_rgctx_lazy_fetch_trampoline (guint32 slot, MonoTrampInfo **info
        s390_jg (code, displace);
 
        mono_arch_flush_icache (buf, code - buf);
-       mono_profiler_code_buffer_new (buf, code - buf, MONO_PROFILER_CODE_BUFFER_GENERICS_TRAMPOLINE, NULL);
+       MONO_PROFILER_RAISE (jit_code_buffer, (buf, code - buf, MONO_PROFILER_CODE_BUFFER_GENERICS_TRAMPOLINE, NULL));
 
        g_assert (code - buf <= tramp_size);
 
@@ -578,7 +579,7 @@ mono_arch_get_static_rgctx_trampoline (gpointer arg,
        g_assert ((code - start) < buf_len);
 
        mono_arch_flush_icache (start, code - start);
-       mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_HELPER, NULL);
+       MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_HELPER, NULL));
 
        mono_tramp_info_register (mono_tramp_info_create (NULL, start, code - start, NULL, NULL), domain);
 
@@ -638,7 +639,7 @@ mono_arch_create_handler_block_trampoline (MonoTrampInfo **info, gboolean aot)
        s390_br   (code, s390_r1);
 
        mono_arch_flush_icache (buf, code - buf);
-       mono_profiler_code_buffer_new (buf, code - buf, MONO_PROFILER_CODE_BUFFER_HELPER, NULL);
+       MONO_PROFILER_RAISE (jit_code_buffer, (buf, code - buf, MONO_PROFILER_CODE_BUFFER_HELPER, NULL));
        g_assert (code - buf <= tramp_size);
 
        *info = mono_tramp_info_create ("handler_block_trampoline", buf, code - buf, ji, unwind_ops);
index 55a6d77191e6a34d30958724a11cb3950be2f46a..6d2ba621ea9af056ea479fa475b5ca87ebb805e3 100644 (file)
@@ -54,7 +54,7 @@ mono_arch_get_unbox_trampoline (MonoMethod *m, gpointer addr)
        x86_jump_code (code, addr);
        g_assert ((code - start) < size);
 
-       mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_UNBOX_TRAMPOLINE, m);
+       MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_UNBOX_TRAMPOLINE, m));
 
        mono_tramp_info_register (mono_tramp_info_create (NULL, start, code - start, NULL, unwind_ops), domain);
 
@@ -81,7 +81,7 @@ mono_arch_get_static_rgctx_trampoline (gpointer arg, gpointer addr)
        g_assert ((code - start) <= buf_len);
 
        mono_arch_flush_icache (start, code - start);
-       mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_GENERICS_TRAMPOLINE, NULL);
+       MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_GENERICS_TRAMPOLINE, NULL));
 
        mono_tramp_info_register (mono_tramp_info_create (NULL, start, code - start, NULL, unwind_ops), domain);
 
@@ -427,7 +427,7 @@ mono_arch_create_generic_trampoline (MonoTrampolineType tramp_type, MonoTrampInf
        }
 
        g_assert ((code - buf) <= 256);
-       mono_profiler_code_buffer_new (buf, code - buf, MONO_PROFILER_CODE_BUFFER_HELPER, NULL);
+       MONO_PROFILER_RAISE (jit_code_buffer, (buf, code - buf, MONO_PROFILER_CODE_BUFFER_HELPER, NULL));
 
        tramp_name = mono_get_generic_trampoline_name (tramp_type);
        *info = mono_tramp_info_create (tramp_name, buf, code - buf, ji, unwind_ops);
@@ -452,7 +452,7 @@ mono_arch_create_specific_trampoline (gpointer arg1, MonoTrampolineType tramp_ty
        g_assert ((buf - code) <= TRAMPOLINE_SIZE);
 
        mono_arch_flush_icache (code, buf - code);
-       mono_profiler_code_buffer_new (code, buf - code, MONO_PROFILER_CODE_BUFFER_SPECIFIC_TRAMPOLINE, mono_get_generic_trampoline_simple_name (tramp_type));
+       MONO_PROFILER_RAISE (jit_code_buffer, (code, buf - code, MONO_PROFILER_CODE_BUFFER_SPECIFIC_TRAMPOLINE, mono_get_generic_trampoline_simple_name (tramp_type)));
 
        if (code_len)
                *code_len = buf - code;
@@ -546,7 +546,7 @@ mono_arch_create_rgctx_lazy_fetch_trampoline (guint32 slot, MonoTrampInfo **info
        }
 
        mono_arch_flush_icache (buf, code - buf);
-       mono_profiler_code_buffer_new (buf, code - buf, MONO_PROFILER_CODE_BUFFER_GENERICS_TRAMPOLINE, NULL);
+       MONO_PROFILER_RAISE (jit_code_buffer, (buf, code - buf, MONO_PROFILER_CODE_BUFFER_GENERICS_TRAMPOLINE, NULL));
 
        g_assert (code - buf <= tramp_size);
 
@@ -589,7 +589,7 @@ mono_arch_create_general_rgctx_lazy_fetch_trampoline (MonoTrampInfo **info, gboo
        x86_jump_reg (code, X86_EAX);
 
        mono_arch_flush_icache (buf, code - buf);
-       mono_profiler_code_buffer_new (buf, code - buf, MONO_PROFILER_CODE_BUFFER_GENERICS_TRAMPOLINE, NULL);
+       MONO_PROFILER_RAISE (jit_code_buffer, (buf, code - buf, MONO_PROFILER_CODE_BUFFER_GENERICS_TRAMPOLINE, NULL));
 
        g_assert (code - buf <= tramp_size);
 
@@ -659,7 +659,7 @@ mono_arch_create_handler_block_trampoline (MonoTrampInfo **info, gboolean aot)
        x86_jump_code (code, tramp);
 
        mono_arch_flush_icache (buf, code - buf);
-       mono_profiler_code_buffer_new (buf, code - buf, MONO_PROFILER_CODE_BUFFER_HELPER, NULL);
+       MONO_PROFILER_RAISE (jit_code_buffer, (buf, code - buf, MONO_PROFILER_CODE_BUFFER_HELPER, NULL));
        g_assert (code - buf <= tramp_size);
 
        *info = mono_tramp_info_create ("handler_block_trampoline", buf, code - buf, ji, unwind_ops);
@@ -710,7 +710,7 @@ mono_arch_get_gsharedvt_arg_trampoline (MonoDomain *domain, gpointer arg, gpoint
        g_assert ((code - start) <= buf_len);
 
        mono_arch_flush_icache (start, code - start);
-       mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_GENERICS_TRAMPOLINE, NULL);
+       MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_GENERICS_TRAMPOLINE, NULL));
 
        mono_tramp_info_register (mono_tramp_info_create (NULL, start, code - start, NULL, unwind_ops), domain);
 
index b5c2d47fb5149cc5b842b4c443fd85f47e74d115..758f86eef1409bf7773d33f1bd1054b34645c815 100644 (file)
@@ -46,12 +46,7 @@ static mono_mutex_t mutex;
 static gboolean verbose;
 
 static void
-prof_jit_enter (MonoProfiler *prof, MonoMethod *method)
-{
-}
-
-static void
-prof_jit_leave (MonoProfiler *prof, MonoMethod *method, int result)
+prof_jit_leave (MonoProfiler *prof, MonoMethod *method, MonoJitInfo *jinfo)
 {
        MonoImage *image = mono_class_get_image (mono_method_get_class (method));
 
@@ -117,14 +112,14 @@ match_option (const char* p, const char *opt, char **rval)
 }
 
 void
-mono_profiler_startup (const char *desc);
+mono_profiler_init (const char *desc);
 
 /**
- * mono_profiler_startup:
+ * mono_profiler_init:
  * the entry point
  */
 void
-mono_profiler_startup (const char *desc)
+mono_profiler_init (const char *desc)
 {
        MonoProfiler *prof;
        const char *p;
@@ -172,11 +167,9 @@ mono_profiler_startup (const char *desc)
 
        mono_os_mutex_init (&mutex);
 
-       mono_profiler_install (prof, prof_shutdown);
-
-       mono_profiler_install_jit_compile (prof_jit_enter, prof_jit_leave);
-
-       mono_profiler_set_events (MONO_PROFILE_JIT_COMPILATION);
+       MonoProfilerHandle handle = mono_profiler_install (prof);
+       mono_profiler_set_runtime_shutdown_callback (handle, prof_shutdown);
+       mono_profiler_set_jit_done_callback (handle, prof_jit_leave);
 }
 
 static void
index 15baec017ac03cd4dc6a5451303577f73ab1433e..5297df369e38ea23a45c5379a8196023f819b8c2 100644 (file)
@@ -92,7 +92,7 @@ static inline gchar *build_hint (SavedString *head);
 static inline gchar *build_hint_from_stack (MonoDomain *domain, void **stack, gint stack_entries);
 static inline void store_string_location (MonoProfiler *prof, const gchar *string, guint32 hash, size_t len);
 static void mono_portability_remember_string (MonoProfiler *prof, MonoDomain *domain, MonoString *str);
-void mono_profiler_startup (const char *desc);
+void mono_profiler_init (const char *desc);
 
 static void mismatched_stats_foreach_func (gpointer key, gpointer value, gpointer user_data)
 {
@@ -477,9 +477,9 @@ static void mono_portability_remember_string (MonoProfiler *prof, MonoDomain *do
 
 static MonoClass *string_class = NULL;
 
-static void mono_portability_remember_alloc (MonoProfiler *prof, MonoObject *obj, MonoClass *klass)
+static void mono_portability_remember_alloc (MonoProfiler *prof, MonoObject *obj)
 {
-       if (klass != string_class)
+       if (mono_object_get_class (obj) != string_class)
                return;
        mono_portability_remember_string (prof, mono_object_get_domain (obj), (MonoString*)obj);
 }
@@ -531,7 +531,7 @@ static void profiler_shutdown (MonoProfiler *prof)
        mono_os_mutex_destroy (&mismatched_files_section);
 }
 
-void mono_profiler_startup (const char *desc)
+void mono_profiler_init (const char *desc)
 {
        MonoProfiler *prof = g_new0 (MonoProfiler, 1);
 
@@ -540,10 +540,10 @@ void mono_profiler_startup (const char *desc)
        prof->saved_strings_hash = g_hash_table_new (NULL, NULL);
        prof->string_locations_hash = g_hash_table_new (mismatched_files_guint32_hash, mismatched_files_guint32_equal);
 
-       mono_profiler_install (prof, profiler_shutdown);
-       mono_profiler_install_runtime_initialized (runtime_initialized_cb);
-       mono_profiler_install_iomap (mono_portability_iomap_event);
-       mono_profiler_install_allocation (mono_portability_remember_alloc);
-
-       mono_profiler_set_events ((MonoProfileFlags)(MONO_PROFILE_ALLOCATIONS | MONO_PROFILE_IOMAP_EVENTS));
+       MonoProfilerHandle handle = mono_profiler_install (prof);
+       mono_profiler_set_runtime_shutdown_callback (handle, profiler_shutdown);
+       mono_profiler_set_runtime_initialized_callback (handle, runtime_initialized_cb);
+       mono_profiler_set_iomap_report_callback (handle, mono_portability_iomap_event);
+       mono_profiler_enable_allocations ();
+       mono_profiler_set_gc_allocation_callback (handle, mono_portability_remember_alloc);
 }
index 53cf67ba6e72228c9a01ccf69e1b62609053732c..9aaf05b580fbc94d8694ec708fbf369a1a23dd97 100644 (file)
@@ -97,9 +97,9 @@ parse_arg (const char *arg, ProfilerConfig *config)
        } else if (match_option (arg, "debug-coverage", NULL)) {
                config->debug_coverage = TRUE;
        } else if (match_option (arg, "sampling-real", NULL)) {
-               config->sampling_mode = MONO_PROFILER_STAT_MODE_REAL;
+               config->sampling_mode = MONO_PROFILER_SAMPLE_MODE_REAL;
        } else if (match_option (arg, "sampling-process", NULL)) {
-               config->sampling_mode = MONO_PROFILER_STAT_MODE_PROCESS;
+               config->sampling_mode = MONO_PROFILER_SAMPLE_MODE_PROCESS;
        } else if (match_option (arg, "heapshot", &val)) {
                config->enable_mask |= PROFLOG_HEAPSHOT_ALIAS;
                set_hsmode (config, val);
@@ -158,6 +158,7 @@ load_args_from_env_or_default (ProfilerConfig *config)
        //XXX change this to header constants
 
        config->max_allocated_sample_hits = mono_cpu_count () * 1000;
+       config->sampling_mode = MONO_PROFILER_SAMPLE_MODE_PROCESS;
        config->sample_freq = 100;
        config->max_call_depth = 100;
        config->num_frames = MAX_FRAMES;
index d84ee526ca223d52314688d838b9f6cc6b1e1ed7..2b586159b6f35194eabd908839add1c180251a1e 100644 (file)
@@ -243,13 +243,13 @@ static MonoLinkedListSet profiler_thread_list;
  *     num is always an even number: the even items are the old
  *     addresses, the odd numbers are the respective new object addresses
  * if exinfo == TYPE_GC_HANDLE_CREATED[_BT]
- *     [handle_type: uleb128] GC handle type (System.Runtime.InteropServices.GCHandleType)
+ *     [handle_type: uleb128] MonoGCHandleType enum value
  *     upper bits reserved as flags
  *     [handle: uleb128] GC handle value
  *     [objaddr: sleb128] object pointer differences from obj_base
  *     If exinfo == TYPE_GC_HANDLE_CREATED_BT, a backtrace follows.
  * if exinfo == TYPE_GC_HANDLE_DESTROYED[_BT]
- *     [handle_type: uleb128] GC handle type (System.Runtime.InteropServices.GCHandleType)
+ *     [handle_type: uleb128] MonoGCHandleType enum value
  *     upper bits reserved as flags
  *     [handle: uleb128] GC handle value
  *     If exinfo == TYPE_GC_HANDLE_DESTROYED_BT, a backtrace follows.
@@ -314,7 +314,7 @@ static MonoLinkedListSet profiler_thread_list;
  * type monitor format:
  * type: TYPE_MONITOR
  * exinfo: zero or TYPE_MONITOR_BT
- * [type: byte] MONO_PROFILER_MONITOR_{CONTENTION,FAIL,DONE}
+ * [type: byte] MonoProfilerMonitorEvent enum value
  * [object: sleb128] the lock object as a difference from obj_base
  * If exinfo == TYPE_MONITOR_BT, a backtrace follows.
  *
@@ -640,6 +640,7 @@ struct _BinaryObject {
 static MonoProfiler *log_profiler;
 
 struct _MonoProfiler {
+       MonoProfilerHandle handle;
        FILE* file;
 #if defined (HAVE_SYS_ZLIB)
        gzFile gzfile;
@@ -1057,7 +1058,7 @@ emit_uvalue (LogBuffer *logbuffer, uint64_t value)
 }
 
 static void
-emit_ptr (LogBuffer *logbuffer, void *ptr)
+emit_ptr (LogBuffer *logbuffer, const void *ptr)
 {
        if (!logbuffer->ptr_base)
                logbuffer->ptr_base = (uintptr_t) ptr;
@@ -1449,7 +1450,7 @@ static gboolean do_heap_walk = FALSE;
 static gboolean ignore_heap_events;
 
 static void
-gc_roots (MonoProfiler *prof, int num, void **objects, int *root_types, uintptr_t *extra_info)
+gc_roots (MonoProfiler *prof, MonoObject *const *objects, const MonoProfilerGCRootType *root_types, const uintptr_t *extra_info, uint64_t num)
 {
        if (ignore_heap_events)
                return;
@@ -1489,7 +1490,7 @@ trigger_on_demand_heapshot (void)
 #define ALL_GC_EVENTS_MASK (PROFLOG_GC_MOVES_EVENTS | PROFLOG_GC_ROOT_EVENTS | PROFLOG_GC_EVENTS | PROFLOG_HEAPSHOT_FEATURE)
 
 static void
-gc_event (MonoProfiler *profiler, MonoGCEvent ev, int generation)
+gc_event (MonoProfiler *profiler, MonoProfilerGCEvent ev, uint32_t generation)
 {
        if (ev == MONO_GC_EVENT_START) {
                uint64_t now = current_time ();
@@ -1607,7 +1608,7 @@ gc_event (MonoProfiler *profiler, MonoGCEvent ev, int generation)
 }
 
 static void
-gc_resize (MonoProfiler *profiler, int64_t new_size)
+gc_resize (MonoProfiler *profiler, uintptr_t new_size)
 {
        ENTER_LOG (&gc_resizes_ctr, logbuffer,
                EVENT_SIZE /* event */ +
@@ -1667,7 +1668,7 @@ emit_bt (MonoProfiler *prof, LogBuffer *logbuffer, FrameData *data)
 }
 
 static void
-gc_alloc (MonoProfiler *prof, MonoObject *obj, MonoClass *klass)
+gc_alloc (MonoProfiler *prof, MonoObject *obj)
 {
        int do_bt = (nocalls && InterlockedRead (&runtime_inited) && !notraces) ? TYPE_ALLOC_BT : 0;
        FrameData data;
@@ -1693,7 +1694,7 @@ gc_alloc (MonoProfiler *prof, MonoObject *obj, MonoClass *klass)
        );
 
        emit_event (logbuffer, do_bt | TYPE_ALLOC);
-       emit_ptr (logbuffer, klass);
+       emit_ptr (logbuffer, mono_object_get_class (obj));
        emit_obj (logbuffer, obj);
        emit_value (logbuffer, len);
 
@@ -1704,7 +1705,7 @@ gc_alloc (MonoProfiler *prof, MonoObject *obj, MonoClass *klass)
 }
 
 static void
-gc_moves (MonoProfiler *prof, void **objects, int num)
+gc_moves (MonoProfiler *prof, MonoObject *const *objects, uint64_t num)
 {
        ENTER_LOG (&gc_moves_ctr, logbuffer,
                EVENT_SIZE /* event */ +
@@ -1724,7 +1725,7 @@ gc_moves (MonoProfiler *prof, void **objects, int num)
 }
 
 static void
-gc_handle (MonoProfiler *prof, int op, int type, uintptr_t handle, MonoObject *obj)
+gc_handle (MonoProfiler *prof, int op, MonoGCHandleType type, uint32_t handle, MonoObject *obj)
 {
        int do_bt = nocalls && InterlockedRead (&runtime_inited) && !notraces;
        FrameData data;
@@ -1768,6 +1769,18 @@ gc_handle (MonoProfiler *prof, int op, int type, uintptr_t handle, MonoObject *o
        EXIT_LOG;
 }
 
+static void
+gc_handle_created (MonoProfiler *prof, uint32_t handle, MonoGCHandleType type, MonoObject *obj)
+{
+       gc_handle (prof, MONO_PROFILER_GC_HANDLE_CREATED, type, handle, obj);
+}
+
+static void
+gc_handle_deleted (MonoProfiler *prof, uint32_t handle, MonoGCHandleType type)
+{
+       gc_handle (prof, MONO_PROFILER_GC_HANDLE_DESTROYED, type, handle, NULL);
+}
+
 static void
 finalize_begin (MonoProfiler *prof)
 {
@@ -1860,11 +1873,8 @@ type_name (MonoClass *klass)
 }
 
 static void
-image_loaded (MonoProfiler *prof, MonoImage *image, int result)
+image_loaded (MonoProfiler *prof, MonoImage *image)
 {
-       if (result != MONO_PROFILE_OK)
-               return;
-
        const char *name = mono_image_get_filename (image);
        int nlen = strlen (name) + 1;
 
@@ -1907,11 +1917,8 @@ image_unloaded (MonoProfiler *prof, MonoImage *image)
 }
 
 static void
-assembly_loaded (MonoProfiler *prof, MonoAssembly *assembly, int result)
+assembly_loaded (MonoProfiler *prof, MonoAssembly *assembly)
 {
-       if (result != MONO_PROFILE_OK)
-               return;
-
        char *name = mono_stringify_assembly_name (mono_assembly_get_name (assembly));
        int nlen = strlen (name) + 1;
        MonoImage *image = mono_assembly_get_image (assembly);
@@ -1964,11 +1971,8 @@ assembly_unloaded (MonoProfiler *prof, MonoAssembly *assembly)
 }
 
 static void
-class_loaded (MonoProfiler *prof, MonoClass *klass, int result)
+class_loaded (MonoProfiler *prof, MonoClass *klass)
 {
-       if (result != MONO_PROFILE_OK)
-               return;
-
        char *name;
 
        if (InterlockedRead (&runtime_inited))
@@ -2039,7 +2043,7 @@ method_leave (MonoProfiler *prof, MonoMethod *method)
 }
 
 static void
-method_exc_leave (MonoProfiler *prof, MonoMethod *method)
+method_exc_leave (MonoProfiler *prof, MonoMethod *method, MonoObject *exc)
 {
        if (!only_coverage && !nocalls && --get_thread ()->call_depth <= max_call_depth) {
                ENTER_LOG (&method_exception_exits_ctr, logbuffer,
@@ -2054,12 +2058,15 @@ method_exc_leave (MonoProfiler *prof, MonoMethod *method)
        }
 }
 
-static void
-method_jitted (MonoProfiler *prof, MonoMethod *method, MonoJitInfo *ji, int result)
+static MonoProfilerCallInstrumentationFlags
+method_filter (MonoProfiler *prof, MonoMethod *method)
 {
-       if (result != MONO_PROFILE_OK)
-               return;
+       return MONO_PROFILER_CALL_INSTRUMENTATION_PROLOGUE | MONO_PROFILER_CALL_INSTRUMENTATION_EPILOGUE;
+}
 
+static void
+method_jitted (MonoProfiler *prof, MonoMethod *method, MonoJitInfo *ji)
+{
        buffer_lock ();
 
        register_method_local (method, ji);
@@ -2068,13 +2075,13 @@ method_jitted (MonoProfiler *prof, MonoMethod *method, MonoJitInfo *ji, int resu
 }
 
 static void
-code_buffer_new (MonoProfiler *prof, void *buffer, int size, MonoProfilerCodeBufferType type, void *data)
+code_buffer_new (MonoProfiler *prof, const mono_byte *buffer, uint64_t size, MonoProfilerCodeBufferType type, const void *data)
 {
-       char *name;
+       const char *name;
        int nlen;
 
        if (type == MONO_PROFILER_CODE_BUFFER_SPECIFIC_TRAMPOLINE) {
-               name = (char *) data;
+               name = (const char *) data;
                nlen = strlen (name) + 1;
        } else {
                name = NULL;
@@ -2134,7 +2141,7 @@ throw_exc (MonoProfiler *prof, MonoObject *object)
 }
 
 static void
-clause_exc (MonoProfiler *prof, MonoMethod *method, int clause_type, int clause_num, MonoObject *exc)
+clause_exc (MonoProfiler *prof, MonoMethod *method, uint32_t clause_num, MonoExceptionEnum clause_type, MonoObject *exc)
 {
        ENTER_LOG (&exception_clauses_ctr, logbuffer,
                EVENT_SIZE /* event */ +
@@ -2183,6 +2190,24 @@ monitor_event (MonoProfiler *profiler, MonoObject *object, MonoProfilerMonitorEv
        EXIT_LOG;
 }
 
+static void
+monitor_contention (MonoProfiler *prof, MonoObject *object)
+{
+       monitor_event (prof, object, MONO_PROFILER_MONITOR_CONTENTION);
+}
+
+static void
+monitor_acquired (MonoProfiler *prof, MonoObject *object)
+{
+       monitor_event (prof, object, MONO_PROFILER_MONITOR_DONE);
+}
+
+static void
+monitor_failed (MonoProfiler *prof, MonoObject *object)
+{
+       monitor_event (prof, object, MONO_PROFILER_MONITOR_FAIL);
+}
+
 static void
 thread_start (MonoProfiler *prof, uintptr_t tid)
 {
@@ -2250,11 +2275,8 @@ thread_name (MonoProfiler *prof, uintptr_t tid, const char *name)
 }
 
 static void
-domain_loaded (MonoProfiler *prof, MonoDomain *domain, int result)
+domain_loaded (MonoProfiler *prof, MonoDomain *domain)
 {
-       if (result != MONO_PROFILE_OK)
-               return;
-
        ENTER_LOG (&domain_loads_ctr, logbuffer,
                EVENT_SIZE /* event */ +
                BYTE_SIZE /* type */ +
@@ -2353,7 +2375,7 @@ typedef struct {
        MonoProfiler *prof;
        uint64_t time;
        uintptr_t tid;
-       void *ip;
+       const void *ip;
        int count;
        AsyncFrameInfo frames [MONO_ZERO_LEN_ARRAY];
 } SampleHit;
@@ -2391,7 +2413,7 @@ enqueue_sample_hit (gpointer p)
 }
 
 static void
-mono_sample_hit (MonoProfiler *profiler, unsigned char *ip, void *context)
+mono_sample_hit (MonoProfiler *profiler, const mono_byte *ip, const void *context)
 {
        /*
         * Please note: We rely on the runtime loading the profiler with
@@ -2422,7 +2444,7 @@ mono_sample_hit (MonoProfiler *profiler, unsigned char *ip, void *context)
        }
 
        sample->count = 0;
-       mono_stack_walk_async_safe (&async_walk_stack, context, sample);
+       mono_stack_walk_async_safe (&async_walk_stack, (void *) context, sample);
 
        sample->time = current_time ();
        sample->tid = thread_id ();
@@ -3231,18 +3253,18 @@ free_coverage_entry (gpointer data, gpointer userdata)
 }
 
 static void
-obtain_coverage_for_method (MonoProfiler *prof, const MonoProfileCoverageEntry *entry)
+obtain_coverage_for_method (MonoProfiler *prof, const MonoProfilerCoverageData *entry)
 {
-       int offset = entry->iloffset - previous_offset;
+       int offset = entry->il_offset - previous_offset;
        CoverageEntry *e = g_new (CoverageEntry, 1);
 
-       previous_offset = entry->iloffset;
+       previous_offset = entry->il_offset;
 
        e->offset = offset;
        e->counter = entry->counter;
-       e->filename = g_strdup(entry->filename ? entry->filename : "");
+       e->filename = g_strdup(entry->file_name ? entry->file_name : "");
        e->line = entry->line;
-       e->column = entry->col;
+       e->column = entry->column;
 
        g_ptr_array_add (coverage_data, e);
 }
@@ -3309,7 +3331,7 @@ build_method_buffer (gpointer key, gpointer value, gpointer userdata)
        previous_offset = 0;
        coverage_data = g_ptr_array_new ();
 
-       mono_profiler_coverage_get (prof, method, obtain_coverage_for_method);
+       mono_profiler_get_coverage_data (prof->handle, method, obtain_coverage_for_method);
 
        klass = mono_method_get_class (method);
        image = mono_class_get_image (klass);
@@ -4631,23 +4653,23 @@ create_profiler (const char *args, const char *filename, GPtrArray *filters)
  * mono will load from the shared library and call.
  */
 extern void
-mono_profiler_startup (const char *desc);
+mono_profiler_init (const char *desc);
 
 extern void
-mono_profiler_startup_log (const char *desc);
+mono_profiler_init_log (const char *desc);
 
 /*
  * this is the entry point that will be used when the profiler
  * is embedded inside the main executable.
  */
 void
-mono_profiler_startup_log (const char *desc)
+mono_profiler_init_log (const char *desc)
 {
-       mono_profiler_startup (desc);
+       mono_profiler_init (desc);
 }
 
 void
-mono_profiler_startup (const char *desc)
+mono_profiler_init (const char *desc)
 {
        GPtrArray *filters = NULL;
 
@@ -4690,112 +4712,107 @@ mono_profiler_startup (const char *desc)
 
        mono_lls_init (&profiler_thread_list, NULL);
 
-       //This two events are required for the profiler to work
-       int events = MONO_PROFILE_THREADS | MONO_PROFILE_GC;
+       MonoProfilerHandle handle = log_profiler->handle = mono_profiler_install (log_profiler);
 
        //Required callbacks
-       mono_profiler_install (log_profiler, log_shutdown);
-       mono_profiler_install_runtime_initialized (runtime_initialized);
+       mono_profiler_set_runtime_shutdown_callback (handle, log_shutdown);
+       mono_profiler_set_runtime_initialized_callback (handle, runtime_initialized);
 
-       mono_profiler_install_gc (gc_event, gc_resize);
-       mono_profiler_install_thread (thread_start, thread_end);
+       mono_profiler_set_gc_event_callback (handle, gc_event);
+       mono_profiler_set_gc_resize_callback (handle, gc_resize);
+       mono_profiler_set_thread_started_callback (handle, thread_start);
+       mono_profiler_set_thread_stopped_callback (handle, thread_end);
 
        //It's questionable whether we actually want this to be mandatory, maybe put it behind the actual event?
-       mono_profiler_install_thread_name (thread_name);
-
+       mono_profiler_set_thread_name_callback (handle, thread_name);
 
        if (config.effective_mask & PROFLOG_DOMAIN_EVENTS) {
-               events |= MONO_PROFILE_APPDOMAIN_EVENTS;
-               mono_profiler_install_appdomain (NULL, domain_loaded, domain_unloaded, NULL);
-               mono_profiler_install_appdomain_name (domain_name);
+               mono_profiler_set_domain_loaded_callback (handle, domain_loaded);
+               mono_profiler_set_domain_unloading_callback (handle, domain_unloaded);
+               mono_profiler_set_domain_name_callback (handle, domain_name);
        }
 
        if (config.effective_mask & PROFLOG_ASSEMBLY_EVENTS) {
-               events |= MONO_PROFILE_ASSEMBLY_EVENTS;
-               mono_profiler_install_assembly (NULL, assembly_loaded, assembly_unloaded, NULL);
+               mono_profiler_set_assembly_loaded_callback (handle, assembly_loaded);
+               mono_profiler_set_assembly_unloading_callback (handle, assembly_unloaded);
        }
 
        if (config.effective_mask & PROFLOG_MODULE_EVENTS) {
-               events |= MONO_PROFILE_MODULE_EVENTS;
-               mono_profiler_install_module (NULL, image_loaded, image_unloaded, NULL);
+               mono_profiler_set_image_loaded_callback (handle, image_loaded);
+               mono_profiler_set_image_unloading_callback (handle, image_unloaded);
        }
 
-       if (config.effective_mask & PROFLOG_CLASS_EVENTS) {
-               events |= MONO_PROFILE_CLASS_EVENTS;
-               mono_profiler_install_class (NULL, class_loaded, NULL, NULL);
-       }
+       if (config.effective_mask & PROFLOG_CLASS_EVENTS)
+               mono_profiler_set_class_loaded_callback (handle, class_loaded);
 
        if (config.effective_mask & PROFLOG_JIT_COMPILATION_EVENTS) {
-               events |= MONO_PROFILE_JIT_COMPILATION;
-               mono_profiler_install_jit_end (method_jitted);
-               mono_profiler_install_code_buffer_new (code_buffer_new);
+               mono_profiler_set_jit_done_callback (handle, method_jitted);
+               mono_profiler_set_jit_code_buffer_callback (handle, code_buffer_new);
        }
 
        if (config.effective_mask & PROFLOG_EXCEPTION_EVENTS) {
-               events |= MONO_PROFILE_EXCEPTIONS;
-               mono_profiler_install_exception (throw_exc, method_exc_leave, NULL);
-               mono_profiler_install_exception_clause (clause_exc);
+               mono_profiler_set_exception_throw_callback (handle, throw_exc);
+               mono_profiler_set_exception_clause_callback (handle, clause_exc);
        }
 
        if (config.effective_mask & PROFLOG_ALLOCATION_EVENTS) {
-               events |= MONO_PROFILE_ALLOCATIONS;
-               mono_profiler_install_allocation (gc_alloc);
+               mono_profiler_enable_allocations ();
+               mono_profiler_set_gc_allocation_callback (handle, gc_alloc);
        }
 
        //PROFLOG_GC_EVENTS is mandatory
        //PROFLOG_THREAD_EVENTS is mandatory
 
        if (config.effective_mask & PROFLOG_CALL_EVENTS) {
-               events |= MONO_PROFILE_ENTER_LEAVE;
-               mono_profiler_install_enter_leave (method_enter, method_leave);
+               mono_profiler_set_call_instrumentation_filter_callback (handle, method_filter);
+               mono_profiler_set_method_enter_callback (handle, method_enter);
+               mono_profiler_set_method_leave_callback (handle, method_leave);
+               mono_profiler_set_method_exception_leave_callback (handle, method_exc_leave);
        }
 
-       if (config.effective_mask & PROFLOG_INS_COVERAGE_EVENTS) {
-               events |= MONO_PROFILE_INS_COVERAGE;
-               mono_profiler_install_coverage_filter (coverage_filter);
-       }
+       if (config.effective_mask & PROFLOG_INS_COVERAGE_EVENTS)
+               mono_profiler_set_coverage_filter_callback (handle, coverage_filter);
 
-       //XXX should we check for PROFLOG_SAMPLING_FEATURE instead??
        if (config.effective_mask & PROFLOG_SAMPLING_EVENTS) {
-               events |= MONO_PROFILE_STATISTICAL;
-               mono_profiler_set_statistical_mode (config.sampling_mode, config.sample_freq);
-               mono_profiler_install_statistical (mono_sample_hit);
+               mono_profiler_enable_sampling (handle);
+
+               if (!mono_profiler_set_sample_mode (handle, config.sampling_mode, config.sample_freq))
+                       g_warning ("Another profiler controls sampling parameters; the log profiler will not be able to modify them");
+
+               mono_profiler_set_sample_hit_callback (handle, mono_sample_hit);
        }
 
        if (config.effective_mask & PROFLOG_MONITOR_EVENTS) {
-               events |= MONO_PROFILE_MONITOR_EVENTS;
-               mono_profiler_install_monitor (monitor_event);
+               mono_profiler_set_monitor_contention_callback (handle, monitor_contention);
+               mono_profiler_set_monitor_acquired_callback (handle, monitor_acquired);
+               mono_profiler_set_monitor_failed_callback (handle, monitor_failed);
        }
 
-       if (config.effective_mask & PROFLOG_GC_MOVES_EVENTS) {
-               events |= MONO_PROFILE_GC_MOVES;
-               mono_profiler_install_gc_moves (gc_moves);
-       }
+       if (config.effective_mask & PROFLOG_GC_MOVES_EVENTS)
+               mono_profiler_set_gc_moves_callback (handle, gc_moves);
 
-       // TODO split those in two profiler events
-       if (config.effective_mask & (PROFLOG_GC_ROOT_EVENTS | PROFLOG_GC_HANDLE_EVENTS)) {
-               events |= MONO_PROFILE_GC_ROOTS;
-               mono_profiler_install_gc_roots (
-                       config.effective_mask & (PROFLOG_GC_HANDLE_EVENTS) ? gc_handle : NULL,
-                       (config.effective_mask & PROFLOG_GC_ROOT_EVENTS) ? gc_roots : NULL);
-       }
+       if (config.effective_mask & PROFLOG_GC_ROOT_EVENTS)
+               mono_profiler_set_gc_roots_callback (handle, gc_roots);
 
        if (config.effective_mask & PROFLOG_CONTEXT_EVENTS) {
-               events |= MONO_PROFILE_CONTEXT_EVENTS;
-               mono_profiler_install_context (context_loaded, context_unloaded);
+               mono_profiler_set_context_loaded_callback (handle, context_loaded);
+               mono_profiler_set_context_unloaded_callback (handle, context_unloaded);
        }
 
        if (config.effective_mask & PROFLOG_FINALIZATION_EVENTS) {
-               events |= MONO_PROFILE_GC_FINALIZATION;
-               mono_profiler_install_gc_finalize (finalize_begin, finalize_object_begin, finalize_object_end, finalize_end);   
+               mono_profiler_set_gc_finalizing_callback (handle, finalize_begin);
+               mono_profiler_set_gc_finalized_callback (handle, finalize_end);
+               mono_profiler_set_gc_finalizing_object_callback (handle, finalize_object_begin);
+               mono_profiler_set_gc_finalized_object_callback (handle, finalize_object_end);
        } else if (ENABLED (PROFLOG_HEAPSHOT_FEATURE) && config.hs_mode_ondemand) {
                //On Demand heapshot uses the finalizer thread to force a collection and thus a heapshot
-               events |= MONO_PROFILE_GC_FINALIZATION;
-               mono_profiler_install_gc_finalize (NULL, NULL, NULL, finalize_end);
+               mono_profiler_set_gc_finalized_callback (handle, finalize_end);
        }
 
        //PROFLOG_COUNTER_EVENTS is a pseudo event controled by the no_counters global var
-       //PROFLOG_GC_HANDLE_EVENTS is handled together with PROFLOG_GC_ROOT_EVENTS
 
-       mono_profiler_set_events ((MonoProfileFlags)events);
+       if (config.effective_mask & PROFLOG_GC_HANDLE_EVENTS) {
+               mono_profiler_set_gc_handle_created_callback (handle, gc_handle_created);
+               mono_profiler_set_gc_handle_deleted_callback (handle, gc_handle_deleted);
+       }
 }
index 5029c26c70c92c287a3226b1de8fb7de6b8b3b06..10171a8d05b9fe07999fe13ed8560e902ed737de 100644 (file)
@@ -150,6 +150,17 @@ typedef enum {
        SYNC_POINT_WORLD_START
 } MonoProfilerSyncPointType;
 
+typedef enum {
+       MONO_PROFILER_MONITOR_CONTENTION = 1,
+       MONO_PROFILER_MONITOR_DONE = 2,
+       MONO_PROFILER_MONITOR_FAIL = 3,
+} MonoProfilerMonitorEvent;
+
+enum {
+       MONO_PROFILER_GC_HANDLE_CREATED,
+       MONO_PROFILER_GC_HANDLE_DESTROYED,
+};
+
 // Sampling sources
 // Unless you have compiled with --enable-perf-events, only SAMPLE_CYCLES is available
 enum {
@@ -265,7 +276,7 @@ typedef struct {
        //Max size of the sample hit buffer, we'll drop frames if it's reached
        int max_allocated_sample_hits;
 
-       MonoProfileSamplingMode sampling_mode;
+       MonoProfilerSampleMode sampling_mode;
 } ProfilerConfig;
 
 void proflog_parse_args (ProfilerConfig *config, const char *desc);
index 00254414925e5b3ea342cd1d06327e3133c51daf..5d93db9746644b73109dca08b0f5b9c8da49cc54 100644 (file)
@@ -1357,7 +1357,7 @@ heap_shot_mark_objects (HeapShot *hs)
                }
                obj = hs->objects_hash [oi];
                cd = obj->hklass;
-               if (hs->roots_types [i] & MONO_PROFILE_GC_ROOT_PINNING)
+               if (hs->roots_types [i] & MONO_PROFILER_GC_ROOT_PINNING)
                        cd->pinned_references++;
                cd->root_references++;
        }
@@ -1959,12 +1959,12 @@ get_handle_name (int htype)
 static const char*
 get_root_name (int rtype)
 {
-       switch (rtype & MONO_PROFILE_GC_ROOT_TYPEMASK) {
-       case MONO_PROFILE_GC_ROOT_STACK: return "stack";
-       case MONO_PROFILE_GC_ROOT_FINALIZER: return "finalizer";
-       case MONO_PROFILE_GC_ROOT_HANDLE: return "handle";
-       case MONO_PROFILE_GC_ROOT_OTHER: return "other";
-       case MONO_PROFILE_GC_ROOT_MISC: return "misc";
+       switch (rtype & MONO_PROFILER_GC_ROOT_TYPEMASK) {
+       case MONO_PROFILER_GC_ROOT_STACK: return "stack";
+       case MONO_PROFILER_GC_ROOT_FINALIZER: return "finalizer";
+       case MONO_PROFILER_GC_ROOT_HANDLE: return "handle";
+       case MONO_PROFILER_GC_ROOT_OTHER: return "other";
+       case MONO_PROFILER_GC_ROOT_MISC: return "misc";
        default: return "unknown";
        }
 }
index 687f644e5e0aa3cc0098872106bfff11b3534326..ab9cb1f663f7ec789d6de4f1b0aa126e27abe418 100755 (executable)
@@ -76,7 +76,7 @@ if ($report ne "missing binary") {
        report_errors ();
 }
 # test traces
-$report = run_test ("test-traces.exe", "legacy,calls,alloc,output=-traces.mlpd", "--traces traces.mlpd");
+$report = run_test ("test-traces.exe", "legacy,calls,alloc,output=-traces.mlpd", "--maxframes=7 --traces traces.mlpd");
 check_report_basics ($report);
 check_call_traces ($report,
        "T:level3 (int)" => [2020, "T:Main (string[])"],
@@ -317,8 +317,10 @@ sub check_alloc_traces
                        while (@desc) {
                                my $dm = pop @desc;
                                my $fm = pop @frames;
-                               $fm = pop @frames if $fm =~ /wrapper/;
-                               push @errors, "Wrong frame $fm for alloc of $type." unless $dm eq $fm;
+                               while ($fm =~ /wrapper/) {
+                                       $fm = pop @frames;
+                               }
+                               push @errors, "Wrong frame $fm for alloc of $type (expected $dm)." unless $dm eq $fm;
                        }
                } else {
                        push @errors, "No alloc frames for $type.";
index 2ed52c541fda284f3e81b05fa0e6f81dde8a3e6c..a1615bfa362fce7b443cbc3127634786ce378a6d 100644 (file)
@@ -76,64 +76,63 @@ codeanalyst_shutdown (MonoProfiler *prof)
 }
 
 static void
-method_jit_result (MonoProfiler *prof, MonoMethod *method, MonoJitInfo* jinfo, int result) {
-       if (result == MONO_PROFILE_OK) {
-               int i;
-               MonoDebugSourceLocation *sourceLoc;
-               MonoDebugMethodJitInfo *dmji;
-               MonoClass *klass = mono_method_get_class (method);
-               char *signature = mono_signature_get_desc (mono_method_signature (method), TRUE);
-               char *name = g_strdup_printf ("%s(%s)", mono_method_get_name (method), signature);
-               char *classname = g_strdup_printf ("%s%s%s", mono_class_get_namespace (klass), mono_class_get_namespace (klass)[0] != 0 ? "::" : "", mono_class_get_name (klass));
-               gpointer code_start = mono_jit_info_get_code_start (jinfo);
-               int code_size = mono_jit_info_get_code_size (jinfo);
-               
-               iJIT_Method_Load vtuneMethod;
-               memset(&vtuneMethod, 0, sizeof(vtuneMethod));
-               vtuneMethod.method_id = iJIT_GetNewMethodID();
-               vtuneMethod.method_name = name;
-               vtuneMethod.method_load_address = code_start;
-               vtuneMethod.method_size = code_size;
-               vtuneMethod.class_file_name = classname;
-
-               dmji = mono_debug_find_method (method, mono_domain_get());
-
-               if (dmji != NULL)
-               {
-                       vtuneMethod.line_number_size = dmji->num_line_numbers;
-                       vtuneMethod.line_number_table = (vtuneMethod.line_number_size != 0) ?
-                               (LineNumberInfo*)malloc(sizeof(LineNumberInfo) * vtuneMethod.line_number_size) : NULL;
+method_jit_done (MonoProfiler *prof, MonoMethod *method, MonoJitInfo* jinfo)
+{
+       int i;
+       MonoDebugSourceLocation *sourceLoc;
+       MonoDebugMethodJitInfo *dmji;
+       MonoClass *klass = mono_method_get_class (method);
+       char *signature = mono_signature_get_desc (mono_method_signature (method), TRUE);
+       char *name = g_strdup_printf ("%s(%s)", mono_method_get_name (method), signature);
+       char *classname = g_strdup_printf ("%s%s%s", mono_class_get_namespace (klass), mono_class_get_namespace (klass)[0] != 0 ? "::" : "", mono_class_get_name (klass));
+       gpointer code_start = mono_jit_info_get_code_start (jinfo);
+       int code_size = mono_jit_info_get_code_size (jinfo);
 
-                       for (i = 0; i < dmji->num_line_numbers; ++i)
+       iJIT_Method_Load vtuneMethod;
+       memset(&vtuneMethod, 0, sizeof(vtuneMethod));
+       vtuneMethod.method_id = iJIT_GetNewMethodID();
+       vtuneMethod.method_name = name;
+       vtuneMethod.method_load_address = code_start;
+       vtuneMethod.method_size = code_size;
+       vtuneMethod.class_file_name = classname;
+
+       dmji = mono_debug_find_method (method, mono_domain_get());
+
+       if (dmji != NULL)
+       {
+               vtuneMethod.line_number_size = dmji->num_line_numbers;
+               vtuneMethod.line_number_table = (vtuneMethod.line_number_size != 0) ?
+                       (LineNumberInfo*)malloc(sizeof(LineNumberInfo) * vtuneMethod.line_number_size) : NULL;
+
+               for (i = 0; i < dmji->num_line_numbers; ++i)
+               {
+                       sourceLoc = mono_debug_lookup_source_location (method, dmji->line_numbers[i].native_offset, mono_domain_get());
+                       if (sourceLoc == NULL)
                        {
-                               sourceLoc = mono_debug_lookup_source_location (method, dmji->line_numbers[i].native_offset, mono_domain_get());
-                               if (sourceLoc == NULL)
-                               {
-                                       g_free (vtuneMethod.line_number_table);
-                                       vtuneMethod.line_number_table = NULL;
-                                       vtuneMethod.line_number_size = 0;
-                                       break;
-                               }
-                               if (i == 0)
-                                       vtuneMethod.source_file_name = strdup(sourceLoc->source_file);
-                               vtuneMethod.line_number_table[i].Offset = dmji->line_numbers[i].native_offset;
-                               vtuneMethod.line_number_table[i].LineNumber = sourceLoc->row;
-                               mono_debug_free_source_location (sourceLoc);
+                               g_free (vtuneMethod.line_number_table);
+                               vtuneMethod.line_number_table = NULL;
+                               vtuneMethod.line_number_size = 0;
+                               break;
                        }
-                       mono_debug_free_method_jit_info (dmji);
+                       if (i == 0)
+                               vtuneMethod.source_file_name = strdup(sourceLoc->source_file);
+                       vtuneMethod.line_number_table[i].Offset = dmji->line_numbers[i].native_offset;
+                       vtuneMethod.line_number_table[i].LineNumber = sourceLoc->row;
+                       mono_debug_free_source_location (sourceLoc);
                }
+               mono_debug_free_method_jit_info (dmji);
+       }
 
-               iJIT_NotifyEvent(iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED, &vtuneMethod);
+       iJIT_NotifyEvent(iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED, &vtuneMethod);
 
-               if (vtuneMethod.source_file_name != NULL)
-                       g_free (vtuneMethod.source_file_name);
-               if (vtuneMethod.line_number_table != NULL)
-                       g_free (vtuneMethod.line_number_table);
-       
-               g_free (signature);
-               g_free (name);
-               g_free (classname);
-       }
+       if (vtuneMethod.source_file_name != NULL)
+               g_free (vtuneMethod.source_file_name);
+       if (vtuneMethod.line_number_table != NULL)
+               g_free (vtuneMethod.line_number_table);
+
+       g_free (signature);
+       g_free (name);
+       g_free (classname);
 }
 
 static void
@@ -162,14 +161,14 @@ code_buffer_new (MonoProfiler *prof, void *buffer, int size, MonoProfilerCodeBuf
 
 /* the entry point */
 void
-mono_profiler_startup (const char *desc)
+mono_profiler_init (const char *desc)
 {
        iJIT_IsProfilingActiveFlags flags = iJIT_IsProfilingActive();
        if (flags == iJIT_SAMPLING_ON)
        {
-               mono_profiler_install (NULL, codeanalyst_shutdown);
-               mono_profiler_install_jit_end (method_jit_result);
-               mono_profiler_install_code_buffer_new (code_buffer_new);
-               mono_profiler_set_events (MONO_PROFILE_JIT_COMPILATION);
+               MonoProfilerHandle handle = mono_profiler_install (NULL);
+               mono_profiler_set_runtime_shutdown_callback (handle, codeanalyst_shutdown);
+               mono_profiler_set_jit_done_callback (handle, method_jit_done);
+               mono_profiler_set_jit_code_buffer_callback (handle, code_buffer_new);
        }
 }
index 2964229a5b1e1c618a5db03a67baac3696cee2c5..4738808880bbdff9dcfe3d8b3e2df5fa5b4d8abb 100644 (file)
@@ -235,7 +235,7 @@ free_chunklist (CodeChunk *chunk)
 
        for (; chunk; ) {
                dead = chunk;
-               mono_profiler_code_chunk_destroy ((gpointer) dead->data);
+               MONO_PROFILER_RAISE (jit_chunk_destroyed, ((mono_byte *) dead->data));
                if (code_manager_callbacks.chunk_destroy)
                        code_manager_callbacks.chunk_destroy ((gpointer)dead->data);
                chunk = chunk->next;
@@ -423,7 +423,7 @@ new_codechunk (CodeChunk *last, int dynamic, int size)
        chunk->bsize = bsize;
        if (code_manager_callbacks.chunk_new)
                code_manager_callbacks.chunk_new ((gpointer)chunk->data, chunk->size);
-       mono_profiler_code_chunk_new((gpointer) chunk->data, chunk->size);
+       MONO_PROFILER_RAISE (jit_chunk_created, ((mono_byte *) chunk->data, chunk->size));
 
        code_memory_used += chunk_size;
        mono_runtime_resource_check_limit (MONO_RESOURCE_JIT_CODE, code_memory_used);
index b164b6b56db21e607b97501f5855bc9b79660bdf..d4763a569b9fd332efcd3318c1e0dc05fd162d12 100644 (file)
@@ -121,7 +121,7 @@ static inline void do_mono_profiler_iomap (GString **report, const char *pathnam
                *report = NULL;
        }
 
-       mono_profiler_iomap (rep, pathname, new_pathname);
+       MONO_PROFILER_RAISE (iomap_report, (rep, pathname, new_pathname));
        g_free (rep);
 }
 
@@ -148,7 +148,7 @@ static inline gchar *mono_portability_find_file_internal (GString **report, cons
        DIR *scanning = NULL;
        size_t len;
        gboolean drive_stripped = FALSE;
-       gboolean do_report = (mono_profiler_get_events () & MONO_PROFILE_IOMAP_EVENTS) != 0;
+       gboolean do_report = MONO_PROFILER_ENABLED (iomap_report);
 
        if (IS_PORTABILITY_NONE) {
                return(NULL);
index 45c46da07d983742adb54409ac23b3aeea64e873..75e2f779590a3d43267625f2650644de75be969c 100644 (file)
@@ -35,19 +35,25 @@ sample_method_leave (MonoProfiler *prof, MonoMethod *method)
 {
 }
 
+static MonoProfilerCallInstrumentationFlags
+sample_instrumentation_filter (MonoProfiler *prof, MonoMethod *method)
+{
+       return MONO_PROFILER_CALL_INSTRUMENTATION_PROLOGUE | MONO_PROFILER_CALL_INSTRUMENTATION_EPILOGUE;
+}
+
 /* the entry point */
 void
-mono_profiler_startup (const char *desc)
+mono_profiler_init (const char *desc)
 {
        MonoProfiler *prof;
 
        prof = g_new0 (MonoProfiler, 1);
 
-       mono_profiler_install (prof, sample_shutdown);
-       
-       mono_profiler_install_enter_leave (sample_method_enter, sample_method_leave);
-
-       mono_profiler_set_events (MONO_PROFILE_ENTER_LEAVE);
+       MonoProfilerHandle handle = mono_profiler_install (prof);
+       mono_profiler_set_runtime_shutdown_callback (handle, sample_shutdown);
+       mono_profiler_set_call_instrumentation_filter_callback (handle, sample_instrumentation_filter);
+       mono_profiler_set_method_enter_callback (handle, sample_method_enter);
+       mono_profiler_set_method_leave_callback (handle, sample_method_leave);
 }
 
 
index c24b417d21f5cfb3527009cc6303b9bdb6e3fff7..86ec27dfd6da4fe6942232aa351e4003c6283b5f 100644 (file)
@@ -121,7 +121,7 @@ GetMemoryUsage (MonoObject *this)
 
 static int installed = 0;
 
-void install_icall (MonoProfiler *prof, MonoMethod *method, MonoJitInfo* jinfo, int result)
+void install_icall (MonoProfiler *prof, MonoMethod *method, MonoJitInfo* jinfo)
 {
        if (installed)
                return;
@@ -131,8 +131,8 @@ void install_icall (MonoProfiler *prof, MonoMethod *method, MonoJitInfo* jinfo,
 }
 
 void
-mono_profiler_startup (const char *desc)
+mono_profiler_init (const char *desc)
 {
-       mono_profiler_install_jit_end (install_icall);
-       mono_profiler_set_events (MONO_PROFILE_JIT_COMPILATION);
+       MonoProfilerHandle handle = mono_profiler_install (NULL);
+       mono_profiler_set_jit_done_callback (handle, install_icall);
 }