Added profiler interface to track GC handles.
authorPaolo Molaro <lupus@oddwiz.org>
Tue, 9 Nov 2010 13:55:31 +0000 (14:55 +0100)
committerPaolo Molaro <lupus@oddwiz.org>
Wed, 10 Nov 2010 09:50:52 +0000 (10:50 +0100)
* 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
mono/metadata/profiler-private.h
mono/metadata/profiler.c
mono/metadata/profiler.h

index 83064485e73f9d4c0f110baeefd8177dac92ee53..10f0976175b29712ae58367b838fcd04aead2b80 100644 (file)
@@ -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);
 }
 
 /**
index ff98938f4f96cd5fc6b2e81104225577e3410f90..b921875ba6be06f8ea102374e83afe12a71ebc43 100644 (file)
@@ -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;
index ab61fbea1e9fdf1d1cad3dead71eb49cb7cefcf8..fc8e1e2bc70e124c87487acfae63a5d2c5cf61ad 100644 (file)
@@ -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)
 {
index 3408b88879a8451244441a8bb60d12dff0b30bea..4775267f266ef2b24107c6d6efcf41ea5c318e89 100644 (file)
@@ -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);