Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/mono.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mcs/class/Mono.Profiler.Log/Mono.Profiler.Log/LogEnums.cs8
-rw-r--r--mono/cil/cil-opcodes.xml1
-rw-r--r--mono/cil/opcode.def1
-rw-r--r--mono/metadata/Makefile.am1
-rw-r--r--mono/metadata/appdomain.c2
-rw-r--r--mono/metadata/assembly.c8
-rw-r--r--mono/metadata/boehm-gc.c33
-rw-r--r--mono/metadata/class.c38
-rw-r--r--mono/metadata/domain.c10
-rw-r--r--mono/metadata/dynamic-image.c4
-rw-r--r--mono/metadata/gc-internals.h4
-rw-r--r--mono/metadata/gc.c8
-rw-r--r--mono/metadata/image.c10
-rw-r--r--mono/metadata/loader.c5
-rw-r--r--mono/metadata/monitor.c8
-rw-r--r--mono/metadata/mono-gc.h9
-rw-r--r--mono/metadata/object.c6
-rw-r--r--mono/metadata/profiler-events.h88
-rw-r--r--mono/metadata/profiler-private.h215
-rw-r--r--mono/metadata/profiler.c1637
-rw-r--r--mono/metadata/profiler.h482
-rw-r--r--mono/metadata/sgen-client-mono.h14
-rw-r--r--mono/metadata/sgen-mono.c129
-rw-r--r--mono/metadata/sgen-stw.c14
-rw-r--r--mono/metadata/sre.c8
-rw-r--r--mono/metadata/threads.c15
-rw-r--r--mono/mini/aot-compiler.c4
-rw-r--r--mono/mini/aot-runtime.c20
-rw-r--r--mono/mini/debugger-agent.c57
-rw-r--r--mono/mini/exceptions-amd64.c8
-rw-r--r--mono/mini/exceptions-arm64.c6
-rw-r--r--mono/mini/exceptions-mips.c8
-rw-r--r--mono/mini/exceptions-ppc.c6
-rw-r--r--mono/mini/exceptions-s390x.c4
-rw-r--r--mono/mini/exceptions-x86.c10
-rw-r--r--mono/mini/interp/interp.c8
-rw-r--r--mono/mini/interp/transform.c12
-rw-r--r--mono/mini/method-to-ir.c25
-rw-r--r--mono/mini/mini-amd64.c18
-rw-r--r--mono/mini/mini-arm.c18
-rw-r--r--mono/mini/mini-exceptions.c10
-rw-r--r--mono/mini/mini-mips.c18
-rw-r--r--mono/mini/mini-posix.c133
-rw-r--r--mono/mini/mini-ppc.c14
-rw-r--r--mono/mini/mini-runtime.c23
-rw-r--r--mono/mini/mini-s390x.c16
-rw-r--r--mono/mini/mini-sparc.c4
-rw-r--r--mono/mini/mini-windows.c8
-rw-r--r--mono/mini/mini-x86.c18
-rw-r--r--mono/mini/mini.c36
-rw-r--r--mono/mini/mini.h3
-rw-r--r--mono/mini/patch-info.h1
-rw-r--r--mono/mini/tramp-amd64-gsharedvt.c2
-rw-r--r--mono/mini/tramp-amd64.c22
-rw-r--r--mono/mini/tramp-arm.c20
-rw-r--r--mono/mini/tramp-arm64.c4
-rw-r--r--mono/mini/tramp-s390x.c15
-rw-r--r--mono/mini/tramp-x86.c16
-rw-r--r--mono/profiler/aot.c21
-rw-r--r--mono/profiler/iomap.c20
-rw-r--r--mono/profiler/log-args.c5
-rw-r--r--mono/profiler/log.c233
-rw-r--r--mono/profiler/log.h13
-rw-r--r--mono/profiler/mprof-report.c14
-rwxr-xr-xmono/profiler/ptestrunner.pl8
-rw-r--r--mono/profiler/vtune.c113
-rw-r--r--mono/utils/mono-codeman.c4
-rw-r--r--mono/utils/mono-io-portability.c4
-rw-r--r--samples/profiler/sample.c18
-rw-r--r--samples/size/size.c8
70 files changed, 1505 insertions, 2281 deletions
diff --git a/mcs/class/Mono.Profiler.Log/Mono.Profiler.Log/LogEnums.cs b/mcs/class/Mono.Profiler.Log/Mono.Profiler.Log/LogEnums.cs
index 52385963af2..f9a125b5d16 100644
--- a/mcs/class/Mono.Profiler.Log/Mono.Profiler.Log/LogEnums.cs
+++ b/mcs/class/Mono.Profiler.Log/Mono.Profiler.Log/LogEnums.cs
@@ -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,
diff --git a/mono/cil/cil-opcodes.xml b/mono/cil/cil-opcodes.xml
index cafb5561891..886cf63af6f 100644
--- a/mono/cil/cil-opcodes.xml
+++ b/mono/cil/cil-opcodes.xml
@@ -321,4 +321,5 @@
<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>
diff --git a/mono/cil/opcode.def b/mono/cil/opcode.def
index 91e8924febc..7cead418fdf 100644
--- a/mono/cil/opcode.def
+++ b/mono/cil/opcode.def
@@ -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)
diff --git a/mono/metadata/Makefile.am b/mono/metadata/Makefile.am
index 7f4a2bbdc66..3243c12e47b 100644
--- a/mono/metadata/Makefile.am
+++ b/mono/metadata/Makefile.am
@@ -220,6 +220,7 @@ common_sources = \
w32process.h \
w32process-internals.h \
profiler.c \
+ profiler-events.h \
profiler-private.h \
rand.h \
rand.c \
diff --git a/mono/metadata/appdomain.c b/mono/metadata/appdomain.c
index 821fd7d8e53..19c44470ec7 100644
--- a/mono/metadata/appdomain.c
+++ b/mono/metadata/appdomain.c
@@ -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)) {
diff --git a/mono/metadata/assembly.c b/mono/metadata/assembly.c
index 3ecd1478ba2..e5b1cb0c57a 100644
--- a/mono/metadata/assembly.c
+++ b/mono/metadata/assembly.c
@@ -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;
}
diff --git a/mono/metadata/boehm-gc.c b/mono/metadata/boehm-gc.c
index 50ff079d1e2..9439ebfab06 100644
--- a/mono/metadata/boehm-gc.c
+++ b/mono/metadata/boehm-gc.c
@@ -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));
}
/**
diff --git a/mono/metadata/class.c b/mono/metadata/class.c
index 4ed4f39da3d..cd3f8bf703b 100644
--- a/mono/metadata/class.c
+++ b/mono/metadata/class.c
@@ -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;
}
diff --git a/mono/metadata/domain.c b/mono/metadata/domain.c
index 16dc31752dd..2a97148f212 100644
--- a/mono/metadata/domain.c
+++ b/mono/metadata/domain.c
@@ -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);
diff --git a/mono/metadata/dynamic-image.c b/mono/metadata/dynamic-image.c
index 9ea2bcf0ee5..211ba26266f 100644
--- a/mono/metadata/dynamic-image.c
+++ b/mono/metadata/dynamic-image.c
@@ -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 ();
diff --git a/mono/metadata/gc-internals.h b/mono/metadata/gc-internals.h
index 4473b04d60d..76e73073dcc 100644
--- a/mono/metadata/gc-internals.h
+++ b/mono/metadata/gc-internals.h
@@ -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);
diff --git a/mono/metadata/gc.c b/mono/metadata/gc.c
index f561dc15b4c..4d8075ffd20 100644
--- a/mono/metadata/gc.c
+++ b/mono/metadata/gc.c
@@ -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 ();
diff --git a/mono/metadata/image.c b/mono/metadata/image.c
index f878339b210..827ba841c3d 100644
--- a/mono/metadata/image.c
+++ b/mono/metadata/image.c
@@ -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;
}
diff --git a/mono/metadata/loader.c b/mono/metadata/loader.c
index d9781cbdfdd..56c3572e76e 100644
--- a/mono/metadata/loader.c
+++ b/mono/metadata/loader.c
@@ -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) {
diff --git a/mono/metadata/monitor.c b/mono/metadata/monitor.c
index beb96a4dc43..702a47c654f 100644
--- a/mono/metadata/monitor.c
+++ b/mono/metadata/monitor.c
@@ -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));
diff --git a/mono/metadata/mono-gc.h b/mono/metadata/mono-gc.h
index d8d5d4435ed..bd1262a67b8 100644
--- a/mono/metadata/mono-gc.h
+++ b/mono/metadata/mono-gc.h
@@ -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);
diff --git a/mono/metadata/object.c b/mono/metadata/object.c
index 3ee786a5d60..5744f45d3c4 100644
--- a/mono/metadata/object.c
+++ b/mono/metadata/object.c
@@ -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
index 00000000000..4f9ce6462c5
--- /dev/null
+++ b/mono/metadata/profiler-events.h
@@ -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)
diff --git a/mono/metadata/profiler-private.h b/mono/metadata/profiler-private.h
index 07df86b211f..4d1b93d4a95 100644
--- a/mono/metadata/profiler-private.h
+++ b/mono/metadata/profiler-private.h
@@ -1,96 +1,139 @@
-/**
- * \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__
diff --git a/mono/metadata/profiler.c b/mono/metadata/profiler.c
index c69f55ec6dc..a1e222fc1e6 100644
--- a/mono/metadata/profiler.c
+++ b/mono/metadata/profiler.c
@@ -1,1428 +1,529 @@
-/**
- * \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
diff --git a/mono/metadata/profiler.h b/mono/metadata/profiler.h
index 81a98ca124c..74a9e651ba4 100644
--- a/mono/metadata/profiler.h
+++ b/mono/metadata/profiler.h
@@ -1,250 +1,310 @@
-/**
- * \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__
diff --git a/mono/metadata/sgen-client-mono.h b/mono/metadata/sgen-client-mono.h
index 78c0126396c..d9a483898e7 100644
--- a/mono/metadata/sgen-client-mono.h
+++ b/mono/metadata/sgen-client-mono.h
@@ -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
diff --git a/mono/metadata/sgen-mono.c b/mono/metadata/sgen-mono.c
index 99f6100e36b..93bdb1fb5c7 100644
--- a/mono/metadata/sgen-mono.c
+++ b/mono/metadata/sgen-mono.c
@@ -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
diff --git a/mono/metadata/sgen-stw.c b/mono/metadata/sgen-stw.c
index b90f8c2789e..48ce7f963ed 100644
--- a/mono/metadata/sgen-stw.c
+++ b/mono/metadata/sgen-stw.c
@@ -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;
}
diff --git a/mono/metadata/sre.c b/mono/metadata/sre.c
index bb164f44be5..3beb23242fb 100644
--- a/mono/metadata/sre.c
+++ b/mono/metadata/sre.c
@@ -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 ();
diff --git a/mono/metadata/threads.c b/mono/metadata/threads.c
index e19f7e07351..e0a7aee8edc 100644
--- a/mono/metadata/threads.c
+++ b/mono/metadata/threads.c
@@ -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
diff --git a/mono/mini/aot-compiler.c b/mono/mini/aot-compiler.c
index e4b2378a3e8..a9a477767b6 100644
--- a/mono/mini/aot-compiler.c
+++ b/mono/mini/aot-compiler.c
@@ -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;
diff --git a/mono/mini/aot-runtime.c b/mono/mini/aot-runtime.c
index f161e27169a..7b28d8db4a2 100644
--- a/mono/mini/aot-runtime.c
+++ b/mono/mini/aot-runtime.c
@@ -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;
diff --git a/mono/mini/debugger-agent.c b/mono/mini/debugger-agent.c
index 0c1a63db2e7..96ef5e20ab2 100644
--- a/mono/mini/debugger-agent.c
+++ b/mono/mini/debugger-agent.c
@@ -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);
}
diff --git a/mono/mini/exceptions-amd64.c b/mono/mini/exceptions-amd64.c
index aeee1d4cbec..2c5f03e1832 100644
--- a/mono/mini/exceptions-amd64.c
+++ b/mono/mini/exceptions-amd64.c
@@ -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;
diff --git a/mono/mini/exceptions-arm64.c b/mono/mini/exceptions-arm64.c
index 29dc7709aa0..fb8d1736c10 100644
--- a/mono/mini/exceptions-arm64.c
+++ b/mono/mini/exceptions-arm64.c
@@ -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);
diff --git a/mono/mini/exceptions-mips.c b/mono/mini/exceptions-mips.c
index 4876fc164cf..69d37cba757 100644
--- a/mono/mini/exceptions-mips.c
+++ b/mono/mini/exceptions-mips.c
@@ -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;
}
diff --git a/mono/mini/exceptions-ppc.c b/mono/mini/exceptions-ppc.c
index 8a758c43c89..5e22cb967c8 100644
--- a/mono/mini/exceptions-ppc.c
+++ b/mono/mini/exceptions-ppc.c
@@ -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);
diff --git a/mono/mini/exceptions-s390x.c b/mono/mini/exceptions-s390x.c
index 77241a6c68a..19204c6ccd6 100644
--- a/mono/mini/exceptions-s390x.c
+++ b/mono/mini/exceptions-s390x.c
@@ -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"
diff --git a/mono/mini/exceptions-x86.c b/mono/mini/exceptions-x86.c
index 30cb4b92d27..5042fa5efd1 100644
--- a/mono/mini/exceptions-x86.c
+++ b/mono/mini/exceptions-x86.c
@@ -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;
}
diff --git a/mono/mini/interp/interp.c b/mono/mini/interp/interp.c
index 3a14d692335..bf3a62195ec 100644
--- a/mono/mini/interp/interp.c
+++ b/mono/mini/interp/interp.c
@@ -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
diff --git a/mono/mini/interp/transform.c b/mono/mini/interp/transform.c
index 35592cb05e2..02a92f271c8 100644
--- a/mono/mini/interp/transform.c
+++ b/mono/mini/interp/transform.c
@@ -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);
diff --git a/mono/mini/method-to-ir.c b/mono/mini/method-to-ir.c
index 2a5f8917d5e..c20c6b2bbbf 100644
--- a/mono/mini/method-to-ir.c
+++ b/mono/mini/method-to-ir.c
@@ -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;
diff --git a/mono/mini/mini-amd64.c b/mono/mini/mini-amd64.c
index 515be71f91f..84acd5ce754 100644
--- a/mono/mini/mini-amd64.c
+++ b/mono/mini/mini-amd64.c
@@ -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);
diff --git a/mono/mini/mini-arm.c b/mono/mini/mini-arm.c
index 1328e762a65..9703c1e09de 100644
--- a/mono/mini/mini-arm.c
+++ b/mono/mini/mini-arm.c
@@ -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);
diff --git a/mono/mini/mini-exceptions.c b/mono/mini/mini-exceptions.c
index 2b8374596e0..bd4283bf3f8 100644
--- a/mono/mini/mini-exceptions.c
+++ b/mono/mini/mini-exceptions.c
@@ -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;
diff --git a/mono/mini/mini-mips.c b/mono/mini/mini-mips.c
index e18c2bdef1d..bf06aee47bb 100644
--- a/mono/mini/mini-mips.c
+++ b/mono/mini/mini-mips.c
@@ -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];
}
diff --git a/mono/mini/mini-posix.c b/mono/mini/mini-posix.c
index ba60bd9934a..a3fd4f0e298 100644
--- a/mono/mini/mini-posix.c
+++ b/mono/mini/mini-posix.c
@@ -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);
diff --git a/mono/mini/mini-ppc.c b/mono/mini/mini-ppc.c
index d78ef80dfbb..f36a3fd528a 100644
--- a/mono/mini/mini-ppc.c
+++ b/mono/mini/mini-ppc.c
@@ -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);
}
diff --git a/mono/mini/mini-runtime.c b/mono/mini/mini-runtime.c
index 77c69bb9375..0f3c217c654 100644
--- a/mono/mini/mini-runtime.c
+++ b/mono/mini/mini-runtime.c
@@ -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 ());
diff --git a/mono/mini/mini-s390x.c b/mono/mini/mini-s390x.c
index 2f3cd3ebca3..bab41317cc6 100644
--- a/mono/mini/mini-s390x.c
+++ b/mono/mini/mini-s390x.c
@@ -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);
diff --git a/mono/mini/mini-sparc.c b/mono/mini/mini-sparc.c
index 29c6f96b5c0..1edddbd139c 100644
--- a/mono/mini/mini-sparc.c
+++ b/mono/mini/mini-sparc.c
@@ -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;
diff --git a/mono/mini/mini-windows.c b/mono/mini/mini-windows.c
index 2d3c64f22e6..3852baf81f1 100644
--- a/mono/mini/mini-windows.c
+++ b/mono/mini/mini-windows.c
@@ -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));
}
}
diff --git a/mono/mini/mini-x86.c b/mono/mini/mini-x86.c
index 7f7758c517e..ad1637319c8 100644
--- a/mono/mini/mini-x86.c
+++ b/mono/mini/mini-x86.c
@@ -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);
diff --git a/mono/mini/mini.c b/mono/mini/mini.c
index 10d6eac8b16..d058547fc41 100644
--- a/mono/mini/mini.c
+++ b/mono/mini/mini.c
@@ -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 ||
diff --git a/mono/mini/mini.h b/mono/mini/mini.h
index 1fcb2f1d892..fea3746e5da 100644
--- a/mono/mini/mini.h
+++ b/mono/mini/mini.h
@@ -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;
diff --git a/mono/mini/patch-info.h b/mono/mini/patch-info.h
index 8a4ba056ee0..926020246e2 100644
--- a/mono/mini/patch-info.h
+++ b/mono/mini/patch-info.h
@@ -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")
diff --git a/mono/mini/tramp-amd64-gsharedvt.c b/mono/mini/tramp-amd64-gsharedvt.c
index 9cf67dd2825..17a6849ed25 100644
--- a/mono/mini/tramp-amd64-gsharedvt.c
+++ b/mono/mini/tramp-amd64-gsharedvt.c
@@ -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);
diff --git a/mono/mini/tramp-amd64.c b/mono/mini/tramp-amd64.c
index 634203bc2e0..cf519e1c929 100644
--- a/mono/mini/tramp-amd64.c
+++ b/mono/mini/tramp-amd64.c
@@ -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);
diff --git a/mono/mini/tramp-arm.c b/mono/mini/tramp-arm.c
index 13c09ac33a7..82d3e95868c 100644
--- a/mono/mini/tramp-arm.c
+++ b/mono/mini/tramp-arm.c
@@ -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);
diff --git a/mono/mini/tramp-arm64.c b/mono/mini/tramp-arm64.c
index cf4057a9434..45e18d880aa 100644
--- a/mono/mini/tramp-arm64.c
+++ b/mono/mini/tramp-arm64.c
@@ -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);
diff --git a/mono/mini/tramp-s390x.c b/mono/mini/tramp-s390x.c
index 56f1839ae42..b0333d3cf18 100644
--- a/mono/mini/tramp-s390x.c
+++ b/mono/mini/tramp-s390x.c
@@ -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);
diff --git a/mono/mini/tramp-x86.c b/mono/mini/tramp-x86.c
index 55a6d77191e..6d2ba621ea9 100644
--- a/mono/mini/tramp-x86.c
+++ b/mono/mini/tramp-x86.c
@@ -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);
diff --git a/mono/profiler/aot.c b/mono/profiler/aot.c
index b5c2d47fb51..758f86eef14 100644
--- a/mono/profiler/aot.c
+++ b/mono/profiler/aot.c
@@ -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
diff --git a/mono/profiler/iomap.c b/mono/profiler/iomap.c
index 15baec017ac..5297df369e3 100644
--- a/mono/profiler/iomap.c
+++ b/mono/profiler/iomap.c
@@ -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);
}
diff --git a/mono/profiler/log-args.c b/mono/profiler/log-args.c
index 53cf67ba6e7..9aaf05b580f 100644
--- a/mono/profiler/log-args.c
+++ b/mono/profiler/log-args.c
@@ -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;
diff --git a/mono/profiler/log.c b/mono/profiler/log.c
index d84ee526ca2..2b586159b6f 100644
--- a/mono/profiler/log.c
+++ b/mono/profiler/log.c
@@ -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;
@@ -1769,6 +1770,18 @@ gc_handle (MonoProfiler *prof, int op, int type, uintptr_t handle, MonoObject *o
}
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)
{
ENTER_LOG (&finalize_begins_ctr, buf,
@@ -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 */ +
@@ -2184,6 +2191,24 @@ monitor_event (MonoProfiler *profiler, MonoObject *object, MonoProfilerMonitorEv
}
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)
{
if (ENABLED (PROFLOG_THREAD_EVENTS)) {
@@ -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);
+ }
}
diff --git a/mono/profiler/log.h b/mono/profiler/log.h
index 5029c26c70c..10171a8d05b 100644
--- a/mono/profiler/log.h
+++ b/mono/profiler/log.h
@@ -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);
diff --git a/mono/profiler/mprof-report.c b/mono/profiler/mprof-report.c
index 00254414925..5d93db97466 100644
--- a/mono/profiler/mprof-report.c
+++ b/mono/profiler/mprof-report.c
@@ -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";
}
}
diff --git a/mono/profiler/ptestrunner.pl b/mono/profiler/ptestrunner.pl
index 687f644e5e0..ab9cb1f663f 100755
--- a/mono/profiler/ptestrunner.pl
+++ b/mono/profiler/ptestrunner.pl
@@ -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.";
diff --git a/mono/profiler/vtune.c b/mono/profiler/vtune.c
index 2ed52c541fd..a1615bfa362 100644
--- a/mono/profiler/vtune.c
+++ b/mono/profiler/vtune.c
@@ -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);
}
}
diff --git a/mono/utils/mono-codeman.c b/mono/utils/mono-codeman.c
index 2964229a5b1..4738808880b 100644
--- a/mono/utils/mono-codeman.c
+++ b/mono/utils/mono-codeman.c
@@ -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);
diff --git a/mono/utils/mono-io-portability.c b/mono/utils/mono-io-portability.c
index b164b6b56db..d4763a569b9 100644
--- a/mono/utils/mono-io-portability.c
+++ b/mono/utils/mono-io-portability.c
@@ -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);
diff --git a/samples/profiler/sample.c b/samples/profiler/sample.c
index 45c46da07d9..75e2f779590 100644
--- a/samples/profiler/sample.c
+++ b/samples/profiler/sample.c
@@ -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);
}
diff --git a/samples/size/size.c b/samples/size/size.c
index c24b417d21f..86ec27dfd6d 100644
--- a/samples/size/size.c
+++ b/samples/size/size.c
@@ -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);
}