Merge pull request #5714 from alexischr/update_bockbuild
[mono.git] / mono / metadata / profiler.h
index 31fa4a767d48bd7ae6ffbdfb1de6895d6564346c..b6e836d3638b6d0912666f3fec8a33adf2788671 100644 (file)
@@ -27,9 +27,9 @@ MONO_BEGIN_DECLS
  * 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:
+ * A module called foo should declare an entry point like so:
  *
- * void mono_profiler_init (const char *desc)
+ * void mono_profiler_init_foo (const char *desc)
  * {
  * }
  *
@@ -42,7 +42,9 @@ typedef struct _MonoProfilerDesc *MonoProfilerHandle;
 
 /*
  * 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).
+ * other functions in the profiler API (e.g. for setting up callbacks). The
+ * given structure pointer will be passed to all callbacks from the profiler
+ * API. It can be NULL.
  *
  * This function may only be called from your profiler's init function.
  *
@@ -54,12 +56,37 @@ typedef struct _MonoProfilerDesc *MonoProfilerHandle;
  * };
  *
  * MonoProfiler *prof = calloc (1, sizeof (MonoProfiler));
- * MonoProfilerHandle handle = mono_profiler_install (prof);
+ * MonoProfilerHandle handle = mono_profiler_create (prof);
  * mono_profiler_set_shutdown_callback (handle, my_shutdown_cb);
  *
  * This function is not async safe.
  */
-MONO_API MonoProfilerHandle mono_profiler_install (MonoProfiler *prof);
+MONO_API MonoProfilerHandle mono_profiler_create (MonoProfiler *prof);
+
+typedef void (*MonoProfilerCleanupCallback) (MonoProfiler *prof);
+
+/*
+ * Sets a profiler cleanup function. This function will be invoked at shutdown
+ * when the profiler API is cleaning up its internal structures. It's mainly
+ * intended for a profiler to free the structure pointer that was passed to
+ * mono_profiler_create, if necessary.
+ *
+ * This function is async safe.
+ */
+MONO_API void mono_profiler_set_cleanup_callback (MonoProfilerHandle handle, MonoProfilerCleanupCallback cb);
+
+/*
+ * Enables support for code coverage instrumentation. At the moment, this means
+ * enabling the debug info subsystem. If you do not call this function, you
+ * will not be able to use mono_profiler_get_coverage_data. Returns TRUE if
+ * code coverage support 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_coverage (void);
 
 typedef mono_bool (*MonoProfilerCoverageFilterCallback) (MonoProfiler *prof, MonoMethod *method);
 
@@ -67,7 +94,7 @@ typedef mono_bool (*MonoProfilerCoverageFilterCallback) (MonoProfiler *prof, Mon
  * 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
+ * guaranteed to be called at least 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
@@ -91,11 +118,16 @@ typedef void (*MonoProfilerCoverageCallback) (MonoProfiler *prof, const MonoProf
 
 /*
  * Retrieves all coverage data for the specified method and invokes the given
- * callback for each entry.
+ * callback for each entry. Source location information will only be filled out
+ * if the given method has debug info available. Returns TRUE if the given
+ * method was instrumented for code coverage; otherwise, FALSE.
+ *
+ * Please note that the structure passed to the callback is only valid for the
+ * duration of the callback.
  *
  * This function is not async safe.
  */
-MONO_API void mono_profiler_get_coverage_data (MonoProfilerHandle handle, MonoMethod *method, MonoProfilerCoverageCallback cb);
+MONO_API mono_bool mono_profiler_get_coverage_data (MonoProfilerHandle handle, MonoMethod *method, MonoProfilerCoverageCallback cb);
 
 typedef enum {
        /*
@@ -134,14 +166,14 @@ typedef enum {
 MONO_API mono_bool mono_profiler_enable_sampling (MonoProfilerHandle handle);
 
 /*
- * 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.
+ * Sets the sampling mode and frequency (in Hz). The frequency must be a
+ * positive number. 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);
+MONO_API mono_bool mono_profiler_set_sample_mode (MonoProfilerHandle handle, MonoProfilerSampleMode mode, uint32_t freq);
 
 /*
  * Retrieves the current sampling mode and/or frequency (in Hz). Returns TRUE if
@@ -150,7 +182,7 @@ MONO_API mono_bool mono_profiler_set_sample_mode (MonoProfilerHandle handle, Mon
  *
  * This function is async safe.
  */
-MONO_API mono_bool mono_profiler_get_sample_mode (MonoProfilerHandle handle, MonoProfilerSampleMode *mode, uint64_t *freq);
+MONO_API mono_bool mono_profiler_get_sample_mode (MonoProfilerHandle handle, MonoProfilerSampleMode *mode, uint32_t *freq);
 
 /*
  * Enables instrumentation of GC allocations. This is necessary so that managed
@@ -167,11 +199,19 @@ MONO_API mono_bool mono_profiler_enable_allocations (void);
 
 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,
+       MONO_PROFILER_CALL_INSTRUMENTATION_NONE = 0,
+       /* Instrument method entries. */
+       MONO_PROFILER_CALL_INSTRUMENTATION_ENTER = 1 << 1,
+       /* Also capture a call context for method entries. */
+       MONO_PROFILER_CALL_INSTRUMENTATION_ENTER_CONTEXT = 1 << 2,
+       /* Instrument method exits. */
+       MONO_PROFILER_CALL_INSTRUMENTATION_LEAVE = 1 << 3,
+       /* Also capture a call context for method exits. */
+       MONO_PROFILER_CALL_INSTRUMENTATION_LEAVE_CONTEXT = 1 << 4,
+       /* Instrument method exits as a result of a tail call. */
+       MONO_PROFILER_CALL_INSTRUMENTATION_TAIL_CALL = 1 << 5,
+       /* Instrument exceptional method exits. */
+       MONO_PROFILER_CALL_INSTRUMENTATION_EXCEPTION_LEAVE = 1 << 6,
 } MonoProfilerCallInstrumentationFlags;
 
 typedef MonoProfilerCallInstrumentationFlags (*MonoProfilerCallInstrumentationFilterCallback) (MonoProfiler *prof, MonoMethod *method);
@@ -181,21 +221,119 @@ typedef MonoProfilerCallInstrumentationFlags (*MonoProfilerCallInstrumentationFi
  * 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.
+ * exactly once per method, 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.
+ * your profiler's init function. Also, if you want to instrument a method
+ * that's going to be AOT-compiled, you must attach your profiler and install a
+ * call instrumentation filter function at AOT time. This can be done in
+ * exactly the same way as you would normally, i.e. by passing the --profile
+ * option on the command line, by calling mono_profiler_load, or simply by
+ * using the profiler API as an embedder.
  *
- * 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.
+ * Keep in mind that indiscriminate 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);
 
+/*
+ * Enables support for retrieving stack frame data from a call context. At the
+ * moment, this means enabling the debug info subsystem. If you do not call
+ * this function, you will not be able to use the call context introspection
+ * functions (they will simply return NULL). Returns TRUE if call context
+ * introspection was enabled, or FALSE if the function was called too late for
+ * this to be possible.
+ *
+ * Please note: Mono's LLVM backend does not support this feature. This means
+ * that methods with call context instrumentation will be handled by Mono's
+ * JIT even in LLVM mode. There is also a special case when Mono is compiling
+ * in LLVM-only mode: Since LLVM does not provide a way to implement call
+ * contexts, a NULL context will always be passed to enter/leave events even
+ * though this method returns TRUE.
+ *
+ * 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_call_context_introspection (void);
+
+typedef struct _MonoProfilerCallContext MonoProfilerCallContext;
+
+/*
+ * Given a valid call context from an enter/leave event, retrieves a pointer to
+ * the this reference for the method. Returns NULL if none exists (i.e. it's a
+ * static method) or if call context introspection was not enabled.
+ *
+ * The buffer returned by this function must be freed with
+ * mono_profiler_call_context_free_buffer.
+ *
+ * Please note that a call context is only valid for the duration of the
+ * enter/leave callback it was passed to.
+ *
+ * This function is not async safe.
+ */
+MONO_API void *mono_profiler_call_context_get_this (MonoProfilerCallContext *context);
+
+/*
+ * Given a valid call context from an enter/leave event, retrieves a pointer to
+ * the method argument at the given position. Returns NULL if position is out
+ * of bounds or if call context introspection was not enabled.
+ *
+ * The buffer returned by this function must be freed with
+ * mono_profiler_call_context_free_buffer.
+ *
+ * Please note that a call context is only valid for the duration of the
+ * enter/leave callback it was passed to.
+ *
+ * This function is not async safe.
+ */
+MONO_API void *mono_profiler_call_context_get_argument (MonoProfilerCallContext *context, uint32_t position);
+
+/*
+ * Given a valid call context from an enter/leave event, retrieves a pointer to
+ * the local variable at the given position. Returns NULL if position is out of
+ * bounds or if call context introspection was not enabled.
+ *
+ * The buffer returned by this function must be freed with
+ * mono_profiler_call_context_free_buffer.
+ *
+ * Please note that a call context is only valid for the duration of the
+ * enter/leave callback it was passed to.
+ *
+ * This function is not async safe.
+ */
+MONO_API void *mono_profiler_call_context_get_local (MonoProfilerCallContext *context, uint32_t position);
+
+/*
+ * Given a valid call context from an enter/leave event, retrieves a pointer to
+ * return value of a method. Returns NULL if the method has no return value
+ * (i.e. it returns void), if the leave event was the result of a tail call, if
+ * the function is called on a context from an enter event, or if call context
+ * introspection was not enabled.
+ *
+ * The buffer returned by this function must be freed with
+ * mono_profiler_call_context_free_buffer.
+ *
+ * Please note that a call context is only valid for the duration of the
+ * enter/leave callback it was passed to.
+ *
+ * This function is not async safe.
+ */
+MONO_API void *mono_profiler_call_context_get_result (MonoProfilerCallContext *context);
+
+/*
+ * Frees a buffer returned by one of the call context introspection functions.
+ * Passing a NULL buffer is allowed, which makes this function a no-op.
+ *
+ * This function is not async safe.
+ */
+MONO_API void mono_profiler_call_context_free_buffer (void *buffer);
+
 #ifdef MONO_PROFILER_UNSTABLE_GC_ROOTS
 typedef enum {
        /* Upper 2 bytes. */
@@ -229,18 +367,13 @@ typedef enum {
        MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING = 9,
 } MonoProfilerCodeBufferType;
 
-// 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_START = 0,
+       MONO_GC_EVENT_END = 5,
        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,