From 8fe4e8bdc06e0f6a6c9a169f5272c7499adabc2e Mon Sep 17 00:00:00 2001 From: Paolo Molaro Date: Tue, 9 Nov 2010 14:55:31 +0100 Subject: [PATCH] Added profiler interface to track GC handles. * profiler-private.h, profiler.c, profiler.h: new API to get notiffications when GC handles are created or destroyed. * gc.c: notify the profiler on GC handle creation/destruction. --- mono/metadata/gc.c | 6 +++++- mono/metadata/profiler-private.h | 1 + mono/metadata/profiler.c | 29 +++++++++++++++++++++++++++++ mono/metadata/profiler.h | 10 +++++++++- 4 files changed, 44 insertions(+), 2 deletions(-) diff --git a/mono/metadata/gc.c b/mono/metadata/gc.c index 83064485e73..10f0976175b 100644 --- a/mono/metadata/gc.c +++ b/mono/metadata/gc.c @@ -602,6 +602,7 @@ static guint32 alloc_handle (HandleData *handles, MonoObject *obj, gboolean track) { gint slot, i; + guint32 res; lock_handles (handles); if (!handles->size) { handles->size = 32; @@ -692,7 +693,9 @@ alloc_handle (HandleData *handles, MonoObject *obj, gboolean track) mono_perfcounters->gc_num_handles++; unlock_handles (handles); /*g_print ("allocated entry %d of type %d to object %p (in slot: %p)\n", slot, handles->type, obj, handles->entries [slot]);*/ - return (slot << 3) | (handles->type + 1); + res = (slot << 3) | (handles->type + 1); + mono_profiler_gc_handle (MONO_PROFILER_GC_HANDLE_CREATED, handles->type, res, obj); + return res; } /** @@ -896,6 +899,7 @@ mono_gchandle_free (guint32 gchandle) mono_perfcounters->gc_num_handles--; /*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); } /** diff --git a/mono/metadata/profiler-private.h b/mono/metadata/profiler-private.h index ff98938f4f9..b921875ba6b 100644 --- a/mono/metadata/profiler-private.h +++ b/mono/metadata/profiler-private.h @@ -67,6 +67,7 @@ void mono_profiler_coverage_free (MonoMethod *method) MONO_ void mono_profiler_gc_event (MonoGCEvent e, int generation) MONO_INTERNAL; void mono_profiler_gc_heap_resize (gint64 new_size) MONO_INTERNAL; void mono_profiler_gc_moves (void **objects, int num) MONO_INTERNAL; +void mono_profiler_gc_handle (int op, int type, uintptr_t handle, MonoObject *obj) MONO_INTERNAL; void mono_profiler_code_chunk_new (gpointer chunk, int size) MONO_INTERNAL; void mono_profiler_code_chunk_destroy (gpointer chunk) MONO_INTERNAL; diff --git a/mono/metadata/profiler.c b/mono/metadata/profiler.c index ab61fbea1e9..fc8e1e2bc70 100644 --- a/mono/metadata/profiler.c +++ b/mono/metadata/profiler.c @@ -89,6 +89,7 @@ struct _ProfilerDesc { MonoProfileGCFunc gc_event; MonoProfileGCResizeFunc gc_heap_resize; MonoProfileGCMoveFunc gc_moves; + MonoProfileGCHandleFunc gc_handle; MonoProfileFunc runtime_initialized_event; @@ -740,6 +741,16 @@ mono_profiler_gc_moves (void **objects, int num) } } +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); + } +} + void mono_profiler_install_gc (MonoProfileGCFunc callback, MonoProfileGCResizeFunc heap_resize_callback) { @@ -772,6 +783,24 @@ mono_profiler_install_gc_moves (MonoProfileGCMoveFunc callback) prof_list->gc_moves = callback; } +/** + * mono_profiler_install_gc_roots: + * @handle_callback: callback function + * + * Install the @handle_callback function that the GC will call when GC + * handles are created or destroyed. + * The callback receives an operation, which is either #MONO_PROFILER_GC_HANDLE_CREATED + * or #MONO_PROFILER_GC_HANDLE_DESTROYED, the handle type, the handle value and the + * object pointer, if present. + */ +void +mono_profiler_install_gc_roots (MonoProfileGCHandleFunc handle_callback) +{ + if (!prof_list) + return; + prof_list->gc_handle = handle_callback; +} + void mono_profiler_install_runtime_initialized (MonoProfileFunc runtime_initialized_callback) { diff --git a/mono/metadata/profiler.h b/mono/metadata/profiler.h index 3408b88879a..4775267f266 100644 --- a/mono/metadata/profiler.h +++ b/mono/metadata/profiler.h @@ -29,7 +29,8 @@ typedef enum { 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_MOVES = 1 << 19, + MONO_PROFILE_GC_ROOTS = 1 << 20 } MonoProfileFlags; typedef enum { @@ -83,6 +84,11 @@ typedef enum { MONO_PROFILER_CALL_CHAIN_INVALID = 4 } MonoProfilerCallChainStrategy; +typedef enum { + MONO_PROFILER_GC_HANDLE_CREATED, + MONO_PROFILER_GC_HANDLE_DESTROYED +} MonoProfileGCHandleEvent; + /* * Functions that the runtime will call on the profiler. */ @@ -115,6 +121,7 @@ typedef void (*MonoProfileStatCallChainFunc) (MonoProfiler *prof, int call_chain 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 (*MonoProfileIomapFunc) (MonoProfiler *prof, const char *report, const char *pathname, const char *new_pathname); @@ -159,6 +166,7 @@ void mono_profiler_install_coverage_filter (MonoProfileCoverageFilterFunc callba void mono_profiler_coverage_get (MonoProfiler *prof, MonoMethod *method, MonoProfileCoverageFunc func); void mono_profiler_install_gc (MonoProfileGCFunc callback, MonoProfileGCResizeFunc heap_resize_callback); void mono_profiler_install_gc_moves (MonoProfileGCMoveFunc callback); +void mono_profiler_install_gc_roots (MonoProfileGCHandleFunc handle_callback); void mono_profiler_install_runtime_initialized (MonoProfileFunc runtime_initialized_callback); void mono_profiler_install_code_chunk_new (MonoProfilerCodeChunkNew callback); -- 2.25.1