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:
authorAlex Rønne Petersen <alpeters@microsoft.com>2017-08-07 23:30:59 +0300
committerAlex Rønne Petersen <alpeters@microsoft.com>2017-08-07 23:47:55 +0300
commita5bc0ce8a0faf81e0a46f9c7d9d7a0913298c057 (patch)
treeacba33efe37d0707964240b65882e62d41c64034
parentb40ae96a9b9c10f650c21aa5ba5769b992e243e2 (diff)
[profiler] Split method_leave callback into a method_tail_call callback.
With this, profilers can distinguish between the two, and also know what the target method of a tail call is. The call instrumentation flags have been renamed accordingly and a new flag has been added for instrumenting tail calls. I've also added a flag for exceptional leave events, and method_exception_leave is only raised if this flag is given for a method. Also refactored the relevant JIT code a bit so it's easier to follow.
-rw-r--r--mono/metadata/profiler-events.h1
-rw-r--r--mono/metadata/profiler.h20
-rw-r--r--mono/mini/interp/interp.c57
-rw-r--r--mono/mini/interp/transform.c3
-rw-r--r--mono/mini/method-to-ir.c18
-rw-r--r--mono/mini/mini-exceptions.c9
-rw-r--r--mono/mini/mini-profiler.c108
-rw-r--r--mono/mini/mini-runtime.c1
-rw-r--r--mono/mini/mini.h11
-rw-r--r--mono/profiler/log.c12
-rw-r--r--samples/profiler/sample.c12
11 files changed, 154 insertions, 98 deletions
diff --git a/mono/metadata/profiler-events.h b/mono/metadata/profiler-events.h
index 1a7e0b25ef9..f0681a6b456 100644
--- a/mono/metadata/profiler-events.h
+++ b/mono/metadata/profiler-events.h
@@ -56,6 +56,7 @@ MONO_PROFILER_EVENT_1(assembly_unloaded, AssemblyLUnloaded, MonoAssembly *, asse
MONO_PROFILER_EVENT_2(method_enter, MethodEnter, MonoMethod *, method, MonoProfilerCallContext *, context)
MONO_PROFILER_EVENT_2(method_leave, MethodLeave, MonoMethod *, method, MonoProfilerCallContext *, context)
+MONO_PROFILER_EVENT_2(method_tail_call, MethodTailCall, MonoMethod *, method, MonoMethod *, target)
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)
diff --git a/mono/metadata/profiler.h b/mono/metadata/profiler.h
index e20dc34c854..b6e836d3638 100644
--- a/mono/metadata/profiler.h
+++ b/mono/metadata/profiler.h
@@ -200,14 +200,18 @@ MONO_API mono_bool mono_profiler_enable_allocations (void);
typedef enum {
/* Do not instrument calls. */
MONO_PROFILER_CALL_INSTRUMENTATION_NONE = 0,
- /* Instrument method prologues. */
- MONO_PROFILER_CALL_INSTRUMENTATION_PROLOGUE = 1 << 1,
- /* Also capture a call context for prologues. */
- MONO_PROFILER_CALL_INSTRUMENTATION_PROLOGUE_CONTEXT = 1 << 2,
- /* Instrument method epilogues. */
- MONO_PROFILER_CALL_INSTRUMENTATION_EPILOGUE = 1 << 3,
- /* Also capture a call context for epilogues. */
- MONO_PROFILER_CALL_INSTRUMENTATION_EPILOGUE_CONTEXT = 1 << 4,
+ /* 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);
diff --git a/mono/mini/interp/interp.c b/mono/mini/interp/interp.c
index fdbbe262ba4..f09df220599 100644
--- a/mono/mini/interp/interp.c
+++ b/mono/mini/interp/interp.c
@@ -2436,6 +2436,10 @@ ves_exec_method_with_context (InterpFrame *frame, ThreadContext *context, unsign
}
MINT_IN_CASE(MINT_JMP) {
InterpMethod *new_method = rtm->data_items [* (guint16 *)(ip + 1)];
+
+ if (frame->imethod->prof_flags & MONO_PROFILER_CALL_INSTRUMENTATION_TAIL_CALL)
+ MONO_PROFILER_RAISE (method_tail_call, (frame->imethod->method, new_method->method));
+
if (!new_method->transformed) {
frame->ip = ip;
frame->ex = mono_interp_transform_method (new_method, context);
@@ -4769,7 +4773,7 @@ array_constructed:
if (MONO_PROFILER_ENABLED (method_enter)) {
MonoProfilerCallContext *prof_ctx = NULL;
- if (frame->imethod->prof_flags & MONO_PROFILER_CALL_INSTRUMENTATION_PROLOGUE_CONTEXT) {
+ if (frame->imethod->prof_flags & MONO_PROFILER_CALL_INSTRUMENTATION_ENTER_CONTEXT) {
prof_ctx = g_new0 (MonoProfilerCallContext, 1);
prof_ctx->interp_frame = frame;
prof_ctx->method = frame->imethod->method;
@@ -5140,35 +5144,34 @@ die_on_ex:
}
exit_frame:
- if (!frame->ex) {
- if (MONO_PROFILER_ENABLED (method_leave) && frame->imethod->prof_flags & MONO_PROFILER_CALL_INSTRUMENTATION_EPILOGUE) {
- MonoProfilerCallContext *prof_ctx = NULL;
-
- if (frame->imethod->prof_flags & MONO_PROFILER_CALL_INSTRUMENTATION_EPILOGUE_CONTEXT) {
- prof_ctx = g_new0 (MonoProfilerCallContext, 1);
- prof_ctx->interp_frame = frame;
- prof_ctx->method = frame->imethod->method;
-
- MonoType *rtype = mono_method_signature (frame->imethod->method)->ret;
-
- switch (rtype->type) {
- case MONO_TYPE_VOID:
- break;
- case MONO_TYPE_VALUETYPE:
- prof_ctx->return_value = frame->retval->data.p;
- break;
- default:
- prof_ctx->return_value = frame->retval;
- break;
- }
- }
+ if (!frame->ex && MONO_PROFILER_ENABLED (method_leave) &&
+ frame->imethod->prof_flags & MONO_PROFILER_CALL_INSTRUMENTATION_LEAVE) {
+ MonoProfilerCallContext *prof_ctx = NULL;
- MONO_PROFILER_RAISE (method_leave, (frame->imethod->method, prof_ctx));
+ if (frame->imethod->prof_flags & MONO_PROFILER_CALL_INSTRUMENTATION_LEAVE_CONTEXT) {
+ prof_ctx = g_new0 (MonoProfilerCallContext, 1);
+ prof_ctx->interp_frame = frame;
+ prof_ctx->method = frame->imethod->method;
- g_free (prof_ctx);
+ MonoType *rtype = mono_method_signature (frame->imethod->method)->ret;
+
+ switch (rtype->type) {
+ case MONO_TYPE_VOID:
+ break;
+ case MONO_TYPE_VALUETYPE:
+ prof_ctx->return_value = frame->retval->data.p;
+ break;
+ default:
+ prof_ctx->return_value = frame->retval;
+ break;
+ }
}
- } else
- MONO_PROFILER_RAISE (method_exception_leave, (frame->imethod->method, (MonoObject *) frame->ex));
+
+ MONO_PROFILER_RAISE (method_leave, (frame->imethod->method, prof_ctx));
+
+ g_free (prof_ctx);
+ } else if (frame->ex && frame->imethod->prof_flags & MONO_PROFILER_CALL_INSTRUMENTATION_EXCEPTION_LEAVE)
+ MONO_PROFILER_RAISE (method_exception_leave, (frame->imethod->method, &frame->ex->object));
DEBUG_LEAVE ();
}
diff --git a/mono/mini/interp/transform.c b/mono/mini/interp/transform.c
index 790f8b191d2..f8144e1952e 100644
--- a/mono/mini/interp/transform.c
+++ b/mono/mini/interp/transform.c
@@ -1514,7 +1514,7 @@ generate (MonoMethod *method, InterpMethod *rtm, unsigned char *is_bb_start, Mon
}
}
- if (rtm->prof_flags & MONO_PROFILER_CALL_INSTRUMENTATION_PROLOGUE)
+ if (rtm->prof_flags & MONO_PROFILER_CALL_INSTRUMENTATION_ENTER)
ADD_CODE (td, MINT_PROF_ENTER);
if (sym_seq_points) {
@@ -3753,6 +3753,7 @@ generate (MonoMethod *method, InterpMethod *rtm, unsigned char *is_bb_start, Mon
case CEE_TAIL_:
++td->ip;
/* FIX: should do something? */;
+ // TODO: This should raise a method_tail_call profiler event.
break;
case CEE_INITOBJ:
CHECK_STACK(td, 1);
diff --git a/mono/mini/method-to-ir.c b/mono/mini/method-to-ir.c
index 84c01946051..a1f6e1fa9ee 100644
--- a/mono/mini/method-to-ir.c
+++ b/mono/mini/method-to-ir.c
@@ -2217,7 +2217,7 @@ check_method_sharing (MonoCompile *cfg, MonoMethod *cmethod, gboolean *out_pass_
inline static MonoCallInst *
mono_emit_call_args (MonoCompile *cfg, MonoMethodSignature *sig,
- MonoInst **args, int calli, int virtual_, int tail, int rgctx, int unbox_trampoline)
+ MonoInst **args, int calli, int virtual_, int tail, int rgctx, int unbox_trampoline, MonoMethod *target)
{
MonoType *sig_ret;
MonoCallInst *call;
@@ -2229,7 +2229,7 @@ mono_emit_call_args (MonoCompile *cfg, MonoMethodSignature *sig,
tail = FALSE;
if (tail) {
- mini_profiler_emit_instrumentation_call (cfg, mono_profiler_raise_method_leave, FALSE, NULL, NULL);
+ mini_profiler_emit_tail_call (cfg, target);
MONO_INST_NEW_CALL (cfg, call, OP_TAILCALL);
} else
@@ -2362,7 +2362,7 @@ mini_emit_calli (MonoCompile *cfg, MonoMethodSignature *sig, MonoInst **args, Mo
MONO_ADD_INS (cfg->cbb, ins);
}
- call = mono_emit_call_args (cfg, sig, args, TRUE, FALSE, FALSE, rgctx_arg ? TRUE : FALSE, FALSE);
+ call = mono_emit_call_args (cfg, sig, args, TRUE, FALSE, FALSE, rgctx_arg ? TRUE : FALSE, FALSE, NULL);
call->inst.sreg1 = addr->dreg;
@@ -2456,7 +2456,7 @@ mono_emit_method_call_full (MonoCompile *cfg, MonoMethod *method, MonoMethodSign
need_unbox_trampoline = method->klass == mono_defaults.object_class || mono_class_is_interface (method->klass);
- call = mono_emit_call_args (cfg, sig, args, FALSE, virtual_, tail, rgctx_arg ? TRUE : FALSE, need_unbox_trampoline);
+ call = mono_emit_call_args (cfg, sig, args, FALSE, virtual_, tail, rgctx_arg ? TRUE : FALSE, need_unbox_trampoline, method);
#ifndef DISABLE_REMOTING
if (might_be_remote)
@@ -2586,7 +2586,7 @@ mono_emit_native_call (MonoCompile *cfg, gconstpointer func, MonoMethodSignature
g_assert (sig);
- call = mono_emit_call_args (cfg, sig, args, FALSE, FALSE, FALSE, FALSE, FALSE);
+ call = mono_emit_call_args (cfg, sig, args, FALSE, FALSE, FALSE, FALSE, FALSE, NULL);
call->fptr = func;
MONO_ADD_INS (cfg->cbb, (MonoInst*)call);
@@ -8030,7 +8030,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);
- mini_profiler_emit_instrumentation_call (cfg, mono_profiler_raise_method_leave, FALSE, NULL, NULL);
+ mini_profiler_emit_tail_call (cfg, cmethod);
fsig = mono_method_signature (cmethod);
n = fsig->param_count + fsig->hasthis;
@@ -8972,7 +8972,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
/* Handle tail calls similarly to normal calls */
tail_call = TRUE;
} else {
- mini_profiler_emit_instrumentation_call (cfg, mono_profiler_raise_method_leave, FALSE, NULL, NULL);
+ mini_profiler_emit_tail_call (cfg, cmethod);
MONO_INST_NEW_CALL (cfg, call, OP_JMP);
call->tail_call = TRUE;
@@ -9083,7 +9083,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
break;
}
case CEE_RET:
- mini_profiler_emit_instrumentation_call (cfg, mono_profiler_raise_method_leave, FALSE, sp - 1, sig->ret);
+ mini_profiler_emit_leave (cfg, sig->ret->type != MONO_TYPE_VOID ? sp [-1] : NULL);
if (cfg->method != method) {
/* return from inlined method */
@@ -12635,7 +12635,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
}
cfg->cbb = init_localsbb;
- mini_profiler_emit_instrumentation_call (cfg, mono_profiler_raise_method_enter, TRUE, NULL, NULL);
+ mini_profiler_emit_enter (cfg);
if (seq_points) {
MonoBasicBlock *bb;
diff --git a/mono/mini/mini-exceptions.c b/mono/mini/mini-exceptions.c
index 348bc3948c5..4f81d7c4c37 100644
--- a/mono/mini/mini-exceptions.c
+++ b/mono/mini/mini-exceptions.c
@@ -2230,9 +2230,12 @@ mono_handle_exception_internal (MonoContext *ctx, MonoObject *obj, gboolean resu
}
}
- jit_tls->orig_ex_ctx_set = TRUE;
- MONO_PROFILER_RAISE (method_exception_leave, (method, ex_obj));
- jit_tls->orig_ex_ctx_set = FALSE;
+ if (MONO_PROFILER_ENABLED (method_exception_leave) &&
+ mono_profiler_get_call_instrumentation_flags (method) & MONO_PROFILER_CALL_INSTRUMENTATION_EXCEPTION_LEAVE) {
+ jit_tls->orig_ex_ctx_set = TRUE;
+ 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-profiler.c b/mono/mini/mini-profiler.c
index 33d39e26df6..c6c61588662 100644
--- a/mono/mini/mini-profiler.c
+++ b/mono/mini/mini-profiler.c
@@ -15,62 +15,94 @@
#ifndef DISABLE_JIT
-void
-mini_profiler_emit_instrumentation_call (MonoCompile *cfg, void *func, gboolean entry, MonoInst **ret, MonoType *rtype)
+static MonoInst *
+emit_fill_call_ctx (MonoCompile *cfg, MonoInst *method, MonoInst *ret)
{
- gboolean instrument, capture;
+ cfg->flags |= MONO_CFG_HAS_ALLOCA;
- /*
- * Do not instrument an inlined method - it becomes
- * part of the current method.
- */
- if (cfg->current_method != cfg->method)
- return;
+ MonoInst *alloc, *size, *fill_ctx;
+
+ EMIT_NEW_ICONST (cfg, size, sizeof (MonoProfilerCallContext));
+ MONO_INST_NEW (cfg, alloc, OP_LOCALLOC);
+ alloc->dreg = alloc_preg (cfg);
+ alloc->sreg1 = size->dreg;
+ alloc->flags |= MONO_INST_INIT;
+ MONO_ADD_INS (cfg->cbb, alloc);
+ MONO_INST_NEW (cfg, fill_ctx, OP_FILL_PROF_CALL_CTX);
+ fill_ctx->sreg1 = alloc->dreg;
+ MONO_ADD_INS (cfg->cbb, fill_ctx);
+ MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, alloc->dreg, MONO_STRUCT_OFFSET (MonoProfilerCallContext, method), method->dreg);
+
+ if (ret) {
+ MonoInst *var = mono_compile_create_var (cfg, mono_method_signature (cfg->method)->ret, OP_LOCAL);
- if (entry) {
- instrument = cfg->prof_flags & MONO_PROFILER_CALL_INSTRUMENTATION_PROLOGUE;
- capture = cfg->prof_flags & MONO_PROFILER_CALL_INSTRUMENTATION_PROLOGUE_CONTEXT;
- } else {
- instrument = cfg->prof_flags & MONO_PROFILER_CALL_INSTRUMENTATION_EPILOGUE;
- capture = cfg->prof_flags & MONO_PROFILER_CALL_INSTRUMENTATION_EPILOGUE_CONTEXT;
+ MonoInst *store, *addr;
+
+ EMIT_NEW_TEMPSTORE (cfg, store, var->inst_c0, ret);
+ EMIT_NEW_VARLOADA (cfg, addr, var, NULL);
+ MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, alloc->dreg, MONO_STRUCT_OFFSET (MonoProfilerCallContext, return_value), addr->dreg);
}
- if (!instrument)
+ return alloc;
+}
+
+void
+mini_profiler_emit_enter (MonoCompile *cfg)
+{
+ if (!MONO_CFG_PROFILE (cfg, ENTER) || cfg->current_method != cfg->method)
+ return;
+
+ MonoInst *iargs [2];
+
+ EMIT_NEW_METHODCONST (cfg, iargs [0], cfg->method);
+
+ if (MONO_CFG_PROFILE (cfg, ENTER_CONTEXT) && !cfg->llvm_only)
+ iargs [1] = emit_fill_call_ctx (cfg, iargs [0], NULL);
+ else
+ EMIT_NEW_PCONST (cfg, iargs [1], NULL);
+
+ /* void mono_profiler_raise_method_enter (MonoMethod *method, MonoProfilerCallContext *ctx) */
+ mono_emit_jit_icall (cfg, mono_profiler_raise_method_enter, iargs);
+}
+
+void
+mini_profiler_emit_leave (MonoCompile *cfg, MonoInst *ret)
+{
+ if (!MONO_CFG_PROFILE (cfg, LEAVE) || cfg->current_method != cfg->method)
return;
MonoInst *iargs [2];
EMIT_NEW_METHODCONST (cfg, iargs [0], cfg->method);
- if (capture && !cfg->llvm_only) {
- cfg->flags |= MONO_CFG_HAS_ALLOCA;
+ if (MONO_CFG_PROFILE (cfg, LEAVE_CONTEXT) && !cfg->llvm_only)
+ iargs [1] = emit_fill_call_ctx (cfg, iargs [0], ret);
+ else
+ EMIT_NEW_PCONST (cfg, iargs [1], NULL);
- MonoInst *size, *fill_ctx;
+ /* void mono_profiler_raise_method_leave (MonoMethod *method, MonoProfilerCallContext *ctx) */
+ mono_emit_jit_icall (cfg, mono_profiler_raise_method_leave, iargs);
+}
- EMIT_NEW_ICONST (cfg, size, sizeof (MonoProfilerCallContext));
- MONO_INST_NEW (cfg, iargs [1], OP_LOCALLOC);
- iargs [1]->dreg = alloc_preg (cfg);
- iargs [1]->sreg1 = size->dreg;
- iargs [1]->flags |= MONO_INST_INIT;
- MONO_ADD_INS (cfg->cbb, iargs [1]);
- MONO_INST_NEW (cfg, fill_ctx, OP_FILL_PROF_CALL_CTX);
- fill_ctx->sreg1 = iargs [1]->dreg;
- MONO_ADD_INS (cfg->cbb, fill_ctx);
- MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, iargs [1]->dreg, MONO_STRUCT_OFFSET (MonoProfilerCallContext, method), iargs [0]->dreg);
+void
+mini_profiler_emit_tail_call (MonoCompile *cfg, MonoMethod *target)
+{
+ if (!MONO_CFG_PROFILE (cfg, TAIL_CALL) || cfg->current_method != cfg->method)
+ return;
- if (rtype && rtype->type != MONO_TYPE_VOID) {
- MonoInst *var = mono_compile_create_var (cfg, rtype, OP_LOCAL);
+ g_assert (cfg->current_method == cfg->method);
- MonoInst *store, *addr;
+ MonoInst *iargs [2];
- EMIT_NEW_TEMPSTORE (cfg, store, var->inst_c0, *ret);
- EMIT_NEW_VARLOADA (cfg, addr, var, NULL);
- MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, iargs [1]->dreg, MONO_STRUCT_OFFSET (MonoProfilerCallContext, return_value), addr->dreg);
- }
- } else
+ EMIT_NEW_METHODCONST (cfg, iargs [0], cfg->method);
+
+ if (target)
+ EMIT_NEW_METHODCONST (cfg, iargs [1], target);
+ else
EMIT_NEW_PCONST (cfg, iargs [1], NULL);
- mono_emit_jit_icall (cfg, func, iargs);
+ /* void mono_profiler_raise_method_tail_call (MonoMethod *method, MonoMethod *target) */
+ mono_emit_jit_icall (cfg, mono_profiler_raise_method_tail_call, iargs);
}
#endif
diff --git a/mono/mini/mini-runtime.c b/mono/mini/mini-runtime.c
index 745ede4dea0..b839e49f096 100644
--- a/mono/mini/mini-runtime.c
+++ b/mono/mini/mini-runtime.c
@@ -4059,6 +4059,7 @@ register_icalls (void)
*/
register_icall (mono_profiler_raise_method_enter, "mono_profiler_raise_method_enter", "void ptr ptr", TRUE);
register_icall (mono_profiler_raise_method_leave, "mono_profiler_raise_method_leave", "void ptr ptr", TRUE);
+ register_icall (mono_profiler_raise_method_tail_call, "mono_profiler_raise_method_tail_call", "void ptr 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);
diff --git a/mono/mini/mini.h b/mono/mini/mini.h
index 7d681122d43..f0d1bb7fc52 100644
--- a/mono/mini/mini.h
+++ b/mono/mini/mini.h
@@ -1920,8 +1920,11 @@ typedef struct {
MonoProfilerCallInstrumentationFlags prof_flags;
} MonoCompile;
+#define MONO_CFG_PROFILE(cfg, flag) \
+ G_UNLIKELY ((cfg)->prof_flags & MONO_PROFILER_CALL_INSTRUMENTATION_ ## flag)
+
#define MONO_CFG_PROFILE_CALL_CONTEXT(cfg) \
- ((cfg)->prof_flags & (MONO_PROFILER_CALL_INSTRUMENTATION_PROLOGUE_CONTEXT | MONO_PROFILER_CALL_INSTRUMENTATION_EPILOGUE_CONTEXT))
+ (MONO_CFG_PROFILE (cfg, ENTER_CONTEXT) || MONO_CFG_PROFILE (cfg, LEAVE_CONTEXT))
typedef enum {
MONO_CFG_HAS_ALLOCA = 1 << 0,
@@ -2357,8 +2360,12 @@ MonoDomain* mini_init (const char *filename, const char *ru
void mini_cleanup (MonoDomain *domain);
MONO_API MonoDebugOptions *mini_get_debug_options (void);
MONO_API gboolean mini_parse_debug_option (const char *option);
+
+/* profiler support */
void mini_add_profiler_argument (const char *desc);
-void mini_profiler_emit_instrumentation_call (MonoCompile *cfg, void *func, gboolean entry, MonoInst **ret, MonoType *rtype);
+void mini_profiler_emit_enter (MonoCompile *cfg);
+void mini_profiler_emit_leave (MonoCompile *cfg, MonoInst *ret);
+void mini_profiler_emit_tail_call (MonoCompile *cfg, MonoMethod *target);
void mini_profiler_context_enable (void);
gpointer mini_profiler_context_get_this (MonoProfilerCallContext *ctx);
gpointer mini_profiler_context_get_argument (MonoProfilerCallContext *ctx, guint32 pos);
diff --git a/mono/profiler/log.c b/mono/profiler/log.c
index 3d4c147cdae..8a3790aac24 100644
--- a/mono/profiler/log.c
+++ b/mono/profiler/log.c
@@ -1792,6 +1792,12 @@ method_leave (MonoProfiler *prof, MonoMethod *method, MonoProfilerCallContext *c
}
static void
+tail_call (MonoProfiler *prof, MonoMethod *method, MonoMethod *target)
+{
+ method_leave (prof, method, NULL);
+}
+
+static void
method_exc_leave (MonoProfiler *prof, MonoMethod *method, MonoObject *exc)
{
if (--get_thread ()->call_depth <= log_config.max_call_depth) {
@@ -1810,7 +1816,10 @@ method_exc_leave (MonoProfiler *prof, MonoMethod *method, MonoObject *exc)
static MonoProfilerCallInstrumentationFlags
method_filter (MonoProfiler *prof, MonoMethod *method)
{
- return MONO_PROFILER_CALL_INSTRUMENTATION_PROLOGUE | MONO_PROFILER_CALL_INSTRUMENTATION_EPILOGUE;
+ return MONO_PROFILER_CALL_INSTRUMENTATION_ENTER |
+ MONO_PROFILER_CALL_INSTRUMENTATION_LEAVE |
+ MONO_PROFILER_CALL_INSTRUMENTATION_TAIL_CALL |
+ MONO_PROFILER_CALL_INSTRUMENTATION_EXCEPTION_LEAVE;
}
static void
@@ -4735,6 +4744,7 @@ mono_profiler_init_log (const char *desc)
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_tail_call_callback (handle, tail_call);
mono_profiler_set_method_exception_leave_callback (handle, method_exc_leave);
}
diff --git a/samples/profiler/sample.c b/samples/profiler/sample.c
index a5ee4435ea6..a210317e913 100644
--- a/samples/profiler/sample.c
+++ b/samples/profiler/sample.c
@@ -2,9 +2,9 @@
/*
* Bare bones profiler. Compile with:
- *
+ *
* linux : gcc -fPIC -shared -o libmono-profiler-sample.so sample.c `pkg-config --cflags --libs mono-2`
- * mac : gcc sample.c -o mono-profiler-sample.dylib -Dmono_free=free -lz `pkg-config --cflags mono-2` -undefined suppress -flat_namespace
+ * mac : gcc -o mono-profiler-sample.dylib sample.c -lz `pkg-config --cflags mono-2` -undefined suppress -flat_namespace
* linux with a custom prefix (e.g. --prefix=/opt/my-mono-build):
* gcc -fPIC -shared -o libmono-profiler-sample.so sample.c `PKG_CONFIG_PATH=/opt/my-mono-build/lib/pkgconfig/ pkg-config --cflags --libs mono-2`
*
@@ -35,15 +35,10 @@ sample_method_enter (MonoProfiler *prof, MonoMethod *method, MonoProfilerCallCon
prof->ncalls++;
}
-static void
-sample_method_leave (MonoProfiler *prof, MonoMethod *method, MonoProfilerCallContext *ctx)
-{
-}
-
static MonoProfilerCallInstrumentationFlags
sample_instrumentation_filter (MonoProfiler *prof, MonoMethod *method)
{
- return MONO_PROFILER_CALL_INSTRUMENTATION_PROLOGUE | MONO_PROFILER_CALL_INSTRUMENTATION_EPILOGUE;
+ return MONO_PROFILER_CALL_INSTRUMENTATION_ENTER;
}
/* the entry point */
@@ -56,7 +51,6 @@ mono_profiler_init_sample (const char *desc)
mono_profiler_set_runtime_shutdown_end_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);
}