From a5bc0ce8a0faf81e0a46f9c7d9d7a0913298c057 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Mon, 7 Aug 2017 22:30:59 +0200 Subject: [PATCH] [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. --- mono/metadata/profiler-events.h | 1 + mono/metadata/profiler.h | 20 +++--- mono/mini/interp/interp.c | 57 +++++++++-------- mono/mini/interp/transform.c | 3 +- mono/mini/method-to-ir.c | 18 +++--- mono/mini/mini-exceptions.c | 9 ++- mono/mini/mini-profiler.c | 108 +++++++++++++++++++++----------- mono/mini/mini-runtime.c | 1 + mono/mini/mini.h | 11 +++- mono/profiler/log.c | 12 +++- samples/profiler/sample.c | 12 +--- 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 @@ -1791,6 +1791,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) { @@ -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); } -- 2.25.1