alloc_handle (HandleData *handles, MonoObject *obj, gboolean track)
{
gint slot, i;
+ guint32 res;
lock_handles (handles);
if (!handles->size) {
handles->size = 32;
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;
}
/**
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);
}
/**
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;
MonoProfileGCFunc gc_event;
MonoProfileGCResizeFunc gc_heap_resize;
MonoProfileGCMoveFunc gc_moves;
+ MonoProfileGCHandleFunc gc_handle;
MonoProfileFunc runtime_initialized_event;
}
}
+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)
{
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)
{
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 {
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.
*/
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);
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);