Skip to content

Commit

Permalink
[profiler] Fix exception clause reporting. (#7940)
Browse files Browse the repository at this point in the history
* [runtime] Handle interpreter-related frames in async stack walks.

* [profiler] Fix exception clause reporting.

This fixes three separate issues:

* Finally clauses in the non-exceptional case were not reported because we
  implement these by simply calling them from managed code, as opposed to the
  exceptional case where we call them from runtime C code.
* The catch portion of a try-filter-catch clause was being incorrectly reported
  as a filter.
* Actual exception filters were not being reported at all.

Because we have to instrument JIT'd code to report non-exceptional finally
clauses, a new mono_profiler_enable_clauses () function has been introduced
which profiler API users must call in order to get exception clause events, in
a similar fashion to mono_profiler_enable_allocations (). Since this is a
breaking change, the profiler API version has been bumped.

Fixes #7525.

* [profiler] Remove the iomap_report event and associated code.

The IOMap profiler no longer exists, so we no longer need to expose this
somewhat hacky event.

* [profiler] Replace the old gc_event with gc_event2.
  • Loading branch information
alexrp authored and vargaz committed Apr 8, 2018
1 parent f8c8724 commit d16ca8d
Show file tree
Hide file tree
Showing 27 changed files with 196 additions and 104 deletions.
9 changes: 3 additions & 6 deletions mono/metadata/boehm-gc.c
Original file line number Diff line number Diff line change
Expand Up @@ -502,21 +502,18 @@ on_gc_notification (GC_EventType event)
case GC_EVENT_RECLAIM_END:
break;
default:
MONO_PROFILER_RAISE (gc_event, (e, 0));
MONO_PROFILER_RAISE (gc_event2, (e, 0, TRUE));
MONO_PROFILER_RAISE (gc_event, (e, 0, TRUE));
break;
}

switch (event) {
case GC_EVENT_PRE_STOP_WORLD:
mono_thread_info_suspend_lock ();
MONO_PROFILER_RAISE (gc_event, (MONO_GC_EVENT_PRE_STOP_WORLD_LOCKED, 0));
MONO_PROFILER_RAISE (gc_event2, (MONO_GC_EVENT_PRE_STOP_WORLD_LOCKED, 0, TRUE));
MONO_PROFILER_RAISE (gc_event, (MONO_GC_EVENT_PRE_STOP_WORLD_LOCKED, 0, TRUE));
break;
case GC_EVENT_POST_START_WORLD:
mono_thread_info_suspend_unlock ();
MONO_PROFILER_RAISE (gc_event, (MONO_GC_EVENT_POST_START_WORLD_UNLOCKED, 0));
MONO_PROFILER_RAISE (gc_event2, (MONO_GC_EVENT_POST_START_WORLD_UNLOCKED, 0, TRUE));
MONO_PROFILER_RAISE (gc_event, (MONO_GC_EVENT_POST_START_WORLD_UNLOCKED, 0, TRUE));
break;
default:
break;
Expand Down
12 changes: 6 additions & 6 deletions mono/metadata/loader.c
Original file line number Diff line number Diff line change
Expand Up @@ -2292,16 +2292,16 @@ async_stack_walk_adapter (MonoStackFrameInfo *frame, MonoContext *ctx, gpointer
case FRAME_TYPE_DEBUGGER_INVOKE:
case FRAME_TYPE_MANAGED_TO_NATIVE:
case FRAME_TYPE_TRAMPOLINE:
case FRAME_TYPE_INTERP_TO_MANAGED:
return FALSE;
case FRAME_TYPE_MANAGED:
case FRAME_TYPE_INTERP:
if (!frame->ji)
return FALSE;
if (frame->ji->async) {
return d->func (NULL, frame->domain, frame->ji->code_start, frame->native_offset, d->user_data);
} else {
return d->func (frame->actual_method, frame->domain, frame->ji->code_start, frame->native_offset, d->user_data);
}
break;

MonoMethod *method = frame->ji->async ? NULL : frame->actual_method;

return d->func (method, frame->domain, frame->ji->code_start, frame->native_offset, d->user_data);
default:
g_assert_not_reached ();
return FALSE;
Expand Down
5 changes: 1 addition & 4 deletions mono/metadata/profiler-events.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,7 @@ MONO_PROFILER_EVENT_1(method_end_invoke, MethodEndInvoke, MonoMethod *, method)
MONO_PROFILER_EVENT_1(exception_throw, ExceptionThrow, MonoObject *, exception)
MONO_PROFILER_EVENT_4(exception_clause, ExceptionClause, MonoMethod *, method, uint32_t, index, MonoExceptionEnum, type, MonoObject *, exception)

MONO_PROFILER_EVENT_2(gc_event, GCEvent, MonoProfilerGCEvent, event, uint32_t, generation)
MONO_PROFILER_EVENT_3(gc_event2, GCEvent2, MonoProfilerGCEvent, event, uint32_t, generation, mono_bool, is_serial)
MONO_PROFILER_EVENT_3(gc_event, GCEvent2, MonoProfilerGCEvent, event, uint32_t, generation, mono_bool, is_serial)
MONO_PROFILER_EVENT_1(gc_allocation, GCAllocation, MonoObject *, object)
MONO_PROFILER_EVENT_2(gc_moves, GCMoves, MonoObject *const *, objects, uint64_t, count)
MONO_PROFILER_EVENT_1(gc_resize, GCResize, uintptr_t, size)
Expand All @@ -108,5 +107,3 @@ MONO_PROFILER_EVENT_1(thread_exited, ThreadExited, uintptr_t, tid)
MONO_PROFILER_EVENT_2(thread_name, ThreadName, uintptr_t, tid, const char *, name)

MONO_PROFILER_EVENT_2(sample_hit, SampleHit, const mono_byte *, ip, const void *, context)

MONO_PROFILER_EVENT_3(iomap_report, IOMap, const char *, report, const char *, old_path, const char *, new_path)
8 changes: 8 additions & 0 deletions mono/metadata/profiler-private.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ typedef struct {

gboolean allocations;

gboolean clauses;

gboolean call_contexts;
void (*context_enable) (void);
gpointer (*context_get_this) (MonoProfilerCallContext *);
Expand Down Expand Up @@ -144,6 +146,12 @@ mono_profiler_allocations_enabled (void)
return mono_profiler_state.allocations;
}

static inline gboolean
mono_profiler_clauses_enabled (void)
{
return mono_profiler_state.clauses;
}

#define _MONO_PROFILER_EVENT(name, ...) \
ICALL_DECL_EXPORT void mono_profiler_raise_ ## name (__VA_ARGS__);
#define MONO_PROFILER_EVENT_0(name, type) \
Expand Down
23 changes: 23 additions & 0 deletions mono/metadata/profiler.c
Original file line number Diff line number Diff line change
Expand Up @@ -561,6 +561,29 @@ mono_profiler_enable_allocations (void)
return mono_profiler_state.allocations = TRUE;
}

/**
* mono_profiler_enable_clauses:
*
* Enables instrumentation of exception clauses. This is necessary so that CIL
* \c leave instructions can be instrumented with a call into the profiler API.
* Exception clauses will not be reported unless this function is called.
* Returns \c TRUE if exception clause instrumentation was enabled, or \c FALSE
* if the function was called too late for this to be possible.
*
* This function is \b not async safe.
*
* This function may \b only be called from a profiler's init function or prior
* to running managed code.
*/
mono_bool
mono_profiler_enable_clauses (void)
{
if (mono_profiler_state.startup_done)
return FALSE;

return mono_profiler_state.clauses = TRUE;
}

/**
* mono_profiler_set_call_instrumentation_filter_callback:
*
Expand Down
16 changes: 15 additions & 1 deletion mono/metadata/profiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,21 @@ MONO_BEGIN_DECLS
* This value will be incremented whenever breaking changes to the profiler API
* are made. This macro is intended for use in profiler modules that wish to
* support older versions of the profiler API.
*
* Version 2:
* - Major overhaul of the profiler API.
* Version 3:
* - Added mono_profiler_enable_clauses (). This must now be called to enable
* raising exception_clause events.
* - The exception argument to exception_clause events can now be NULL for
* finally clauses invoked in the non-exceptional case.
* - The type argument to exception_clause events will now correctly indicate
* that the catch portion of the clause is being executed in the case of
* try-filter-catch clauses.
* - Removed the iomap_report event.
* - Removed the old gc_event event and renamed gc_event2 to gc_event.
*/
#define MONO_PROFILER_API_VERSION 2
#define MONO_PROFILER_API_VERSION 3

typedef struct _MonoProfiler MonoProfiler;
typedef struct _MonoProfilerDesc *MonoProfilerHandle;
Expand Down Expand Up @@ -68,6 +81,7 @@ MONO_API mono_bool mono_profiler_set_sample_mode (MonoProfilerHandle handle, Mon
MONO_API mono_bool mono_profiler_get_sample_mode (MonoProfilerHandle handle, MonoProfilerSampleMode *mode, uint32_t *freq);

MONO_API mono_bool mono_profiler_enable_allocations (void);
MONO_API mono_bool mono_profiler_enable_clauses (void);

typedef struct _MonoProfilerCallContext MonoProfilerCallContext;

Expand Down
6 changes: 2 additions & 4 deletions mono/metadata/sgen-mono.c
Original file line number Diff line number Diff line change
Expand Up @@ -2939,8 +2939,7 @@ sgen_client_binary_protocol_collection_begin (int minor_gc_count, int generation

MONO_GC_BEGIN (generation);

MONO_PROFILER_RAISE (gc_event, (MONO_GC_EVENT_START, generation));
MONO_PROFILER_RAISE (gc_event2, (MONO_GC_EVENT_START, generation, generation == GENERATION_OLD && sgen_concurrent_collection_in_progress));
MONO_PROFILER_RAISE (gc_event, (MONO_GC_EVENT_START, generation, generation == GENERATION_OLD && sgen_concurrent_collection_in_progress));

if (!pseudo_roots_registered) {
pseudo_roots_registered = TRUE;
Expand All @@ -2962,8 +2961,7 @@ sgen_client_binary_protocol_collection_end (int minor_gc_count, int generation,
{
MONO_GC_END (generation);

MONO_PROFILER_RAISE (gc_event, (MONO_GC_EVENT_END, generation));
MONO_PROFILER_RAISE (gc_event2, (MONO_GC_EVENT_END, generation, generation == GENERATION_OLD && sgen_concurrent_collection_in_progress));
MONO_PROFILER_RAISE (gc_event, (MONO_GC_EVENT_END, generation, generation == GENERATION_OLD && sgen_concurrent_collection_in_progress));
}

#ifdef HOST_WASM
Expand Down
18 changes: 6 additions & 12 deletions mono/metadata/sgen-stw.c
Original file line number Diff line number Diff line change
Expand Up @@ -106,13 +106,11 @@ sgen_client_stop_world (int generation, gboolean serial_collection)
{
TV_DECLARE (end_handshake);

MONO_PROFILER_RAISE (gc_event, (MONO_GC_EVENT_PRE_STOP_WORLD, generation));
MONO_PROFILER_RAISE (gc_event2, (MONO_GC_EVENT_PRE_STOP_WORLD, generation, serial_collection));
MONO_PROFILER_RAISE (gc_event, (MONO_GC_EVENT_PRE_STOP_WORLD, generation, serial_collection));

acquire_gc_locks ();

MONO_PROFILER_RAISE (gc_event, (MONO_GC_EVENT_PRE_STOP_WORLD_LOCKED, generation));
MONO_PROFILER_RAISE (gc_event2, (MONO_GC_EVENT_PRE_STOP_WORLD_LOCKED, generation, serial_collection));
MONO_PROFILER_RAISE (gc_event, (MONO_GC_EVENT_PRE_STOP_WORLD_LOCKED, generation, serial_collection));

/* We start to scan after locks are taking, this ensures we won't be interrupted. */
sgen_process_togglerefs ();
Expand All @@ -127,8 +125,7 @@ sgen_client_stop_world (int generation, gboolean serial_collection)

SGEN_LOG (3, "world stopped");

MONO_PROFILER_RAISE (gc_event, (MONO_GC_EVENT_POST_STOP_WORLD, generation));
MONO_PROFILER_RAISE (gc_event2, (MONO_GC_EVENT_POST_STOP_WORLD, generation, serial_collection));
MONO_PROFILER_RAISE (gc_event, (MONO_GC_EVENT_POST_STOP_WORLD, generation, serial_collection));

TV_GETTIME (end_handshake);
time_stop_world += TV_ELAPSED (stop_world_time, end_handshake);
Expand All @@ -154,8 +151,7 @@ sgen_client_restart_world (int generation, gboolean serial_collection, gint64 *s
if (MONO_PROFILER_ENABLED (gc_resize))
mono_sgen_gc_event_resize ();

MONO_PROFILER_RAISE (gc_event, (MONO_GC_EVENT_PRE_START_WORLD, generation));
MONO_PROFILER_RAISE (gc_event2, (MONO_GC_EVENT_PRE_START_WORLD, generation, serial_collection));
MONO_PROFILER_RAISE (gc_event, (MONO_GC_EVENT_PRE_START_WORLD, generation, serial_collection));

FOREACH_THREAD_ALL (info) {
info->client_info.stack_start = NULL;
Expand All @@ -174,8 +170,7 @@ sgen_client_restart_world (int generation, gboolean serial_collection, gint64 *s

SGEN_LOG (2, "restarted (pause time: %d usec, max: %d)", (int)usec, (int)max_pause_usec);

MONO_PROFILER_RAISE (gc_event, (MONO_GC_EVENT_POST_START_WORLD, generation));
MONO_PROFILER_RAISE (gc_event2, (MONO_GC_EVENT_POST_START_WORLD, generation, serial_collection));
MONO_PROFILER_RAISE (gc_event, (MONO_GC_EVENT_POST_START_WORLD, generation, serial_collection));

/*
* We must release the thread info suspend lock after doing
Expand All @@ -189,8 +184,7 @@ sgen_client_restart_world (int generation, gboolean serial_collection, gint64 *s
*/
release_gc_locks ();

MONO_PROFILER_RAISE (gc_event, (MONO_GC_EVENT_POST_START_WORLD_UNLOCKED, generation));
MONO_PROFILER_RAISE (gc_event2, (MONO_GC_EVENT_POST_START_WORLD_UNLOCKED, generation, serial_collection));
MONO_PROFILER_RAISE (gc_event, (MONO_GC_EVENT_POST_START_WORLD_UNLOCKED, generation, serial_collection));

*stw_time = usec;
}
Expand Down
1 change: 1 addition & 0 deletions mono/mini/aot-compiler.c
Original file line number Diff line number Diff line change
Expand Up @@ -6010,6 +6010,7 @@ encode_patch (MonoAotCompile *acfg, MonoJumpInfo *patch_info, guint8 *buf, guint
case MONO_PATCH_INFO_INTERRUPTION_REQUEST_FLAG:
break;
case MONO_PATCH_INFO_PROFILER_ALLOCATION_COUNT:
case MONO_PATCH_INFO_PROFILER_CLAUSE_COUNT:
break;
case MONO_PATCH_INFO_RGCTX_FETCH:
case MONO_PATCH_INFO_RGCTX_SLOT_INDEX: {
Expand Down
1 change: 1 addition & 0 deletions mono/mini/aot-runtime.c
Original file line number Diff line number Diff line change
Expand Up @@ -3722,6 +3722,7 @@ decode_patch (MonoAotModule *aot_module, MonoMemPool *mp, MonoJumpInfo *ji, guin
case MONO_PATCH_INFO_GC_NURSERY_START:
case MONO_PATCH_INFO_GC_NURSERY_BITS:
case MONO_PATCH_INFO_PROFILER_ALLOCATION_COUNT:
case MONO_PATCH_INFO_PROFILER_CLAUSE_COUNT:
break;
case MONO_PATCH_INFO_CASTCLASS_CACHE:
ji->data.index = decode_value (p, &p);
Expand Down
17 changes: 15 additions & 2 deletions mono/mini/method-to-ir.c
Original file line number Diff line number Diff line change
Expand Up @@ -711,7 +711,11 @@ mono_find_leave_clauses (MonoCompile *cfg, unsigned char *ip, unsigned char *tar
clause = &header->clauses [i];
if (MONO_OFFSET_IN_CLAUSE (clause, (ip - header->code)) &&
(!MONO_OFFSET_IN_CLAUSE (clause, (target - header->code)))) {
res = g_list_append_mempool (cfg->mempool, res, clause);
MonoLeaveClause *leave = mono_mempool_alloc0 (cfg->mempool, sizeof (MonoLeaveClause));
leave->index = i;
leave->clause = clause;

res = g_list_append_mempool (cfg->mempool, res, leave);
}
}
return res;
Expand Down Expand Up @@ -11628,12 +11632,21 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
* we already exited.
*/
for (tmp = handlers; tmp; tmp = tmp->next) {
MonoExceptionClause *clause = (MonoExceptionClause *)tmp->data;
MonoLeaveClause *leave = (MonoLeaveClause *) tmp->data;
MonoExceptionClause *clause = leave->clause;

if (clause->flags != MONO_EXCEPTION_CLAUSE_FINALLY)
continue;

MonoInst *abort_exc = (MonoInst *)mono_find_exvar_for_offset (cfg, clause->handler_offset);
MonoBasicBlock *dont_throw;

/*
* Emit instrumentation code before linking the basic blocks below as this
* will alter cfg->cbb.
*/
mini_profiler_emit_call_finally (cfg, header, ip, leave->index, clause);

tblock = cfg->cil_offset_to_bb [clause->handler_offset];
g_assert (tblock);
link_bblock (cfg, cfg->cbb, tblock);
Expand Down
2 changes: 1 addition & 1 deletion mono/mini/mini-amd64.c
Original file line number Diff line number Diff line change
Expand Up @@ -4995,7 +4995,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
* basic block. Add only the rest of them.
*/
for (GList *tmp = ins->inst_eh_blocks; tmp != bb->clause_holes; tmp = tmp->prev)
mono_cfg_add_try_hole (cfg, (MonoExceptionClause *)tmp->data, code, bb);
mono_cfg_add_try_hole (cfg, ((MonoLeaveClause *) tmp->data)->clause, code, bb);
/* Restore stack alignment */
amd64_alu_reg_imm (code, X86_ADD, AMD64_RSP, 8);
break;
Expand Down
2 changes: 1 addition & 1 deletion mono/mini/mini-arm.c
Original file line number Diff line number Diff line change
Expand Up @@ -5422,7 +5422,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
code = mono_arm_patchable_bl (code, ARMCOND_AL);
cfg->thunk_area += THUNK_SIZE;
for (GList *tmp = ins->inst_eh_blocks; tmp != bb->clause_holes; tmp = tmp->prev)
mono_cfg_add_try_hole (cfg, (MonoExceptionClause *)tmp->data, code, bb);
mono_cfg_add_try_hole (cfg, ((MonoLeaveClause *) tmp->data)->clause, code, bb);
break;
case OP_GET_EX_OBJ:
if (ins->dreg != ARMREG_R0)
Expand Down
2 changes: 1 addition & 1 deletion mono/mini/mini-arm64.c
Original file line number Diff line number Diff line change
Expand Up @@ -4507,7 +4507,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
arm_bl (code, 0);
cfg->thunk_area += THUNK_SIZE;
for (GList *tmp = ins->inst_eh_blocks; tmp != bb->clause_holes; tmp = tmp->prev)
mono_cfg_add_try_hole (cfg, (MonoExceptionClause *)tmp->data, code, bb);
mono_cfg_add_try_hole (cfg, ((MonoLeaveClause *) tmp->data)->clause, code, bb);
break;
case OP_START_HANDLER: {
MonoInst *spvar = mono_find_spvar_for_region (cfg, bb->region);
Expand Down
43 changes: 34 additions & 9 deletions mono/mini/mini-exceptions.c
Original file line number Diff line number Diff line change
Expand Up @@ -1817,6 +1817,13 @@ handle_exception_first_pass (MonoContext *ctx, MonoObject *obj, gint32 *out_filt
}

mono_debugger_agent_begin_exception_filter (mono_ex, ctx, &initial_ctx);

if (G_UNLIKELY (mono_profiler_clauses_enabled ())) {
jit_tls->orig_ex_ctx_set = TRUE;
MONO_PROFILER_RAISE (exception_clause, (method, i, ei->flags, ex_obj));
jit_tls->orig_ex_ctx_set = FALSE;
}

if (ji->is_interp) {
filtered = mini_get_interp_callbacks ()->run_filter (&frame, (MonoException*)ex_obj, i, ei->data.filter);
} else {
Expand Down Expand Up @@ -2227,9 +2234,20 @@ mono_handle_exception_internal (MonoContext *ctx, MonoObject *obj, gboolean resu

if (mono_trace_is_enabled () && mono_trace_eval (method))
g_print ("EXCEPTION: catch found at clause %d of %s\n", i, mono_method_full_name (method, TRUE));
jit_tls->orig_ex_ctx_set = TRUE;
MONO_PROFILER_RAISE (exception_clause, (method, i, ei->flags, ex_obj));
jit_tls->orig_ex_ctx_set = FALSE;

/*
* At this point, ei->flags can be either MONO_EXCEPTION_CLAUSE_NONE for a
* a try-catch clause or MONO_EXCEPTION_CLAUSE_FILTER for a try-filter-catch
* clause. Since we specifically want to indicate that we're executing the
* catch portion of this EH clause, pass MONO_EXCEPTION_CLAUSE_NONE explicitly
* instead of ei->flags.
*/
if (G_UNLIKELY (mono_profiler_clauses_enabled ())) {
jit_tls->orig_ex_ctx_set = TRUE;
MONO_PROFILER_RAISE (exception_clause, (method, i, MONO_EXCEPTION_CLAUSE_NONE, ex_obj));
jit_tls->orig_ex_ctx_set = FALSE;
}

mini_set_abort_threshold (&frame);

if (in_interp) {
Expand Down Expand Up @@ -2263,16 +2281,23 @@ mono_handle_exception_internal (MonoContext *ctx, MonoObject *obj, gboolean resu
if (ei->flags == MONO_EXCEPTION_CLAUSE_FAULT) {
if (mono_trace_is_enabled () && mono_trace_eval (method))
g_print ("EXCEPTION: fault clause %d of %s\n", i, mono_method_full_name (method, TRUE));
jit_tls->orig_ex_ctx_set = TRUE;
MONO_PROFILER_RAISE (exception_clause, (method, i, ei->flags, ex_obj));
jit_tls->orig_ex_ctx_set = FALSE;

if (G_UNLIKELY (mono_profiler_clauses_enabled ())) {
jit_tls->orig_ex_ctx_set = TRUE;
MONO_PROFILER_RAISE (exception_clause, (method, i, ei->flags, ex_obj));
jit_tls->orig_ex_ctx_set = FALSE;
}
}
if (ei->flags == MONO_EXCEPTION_CLAUSE_FINALLY) {
if (mono_trace_is_enabled () && mono_trace_eval (method))
g_print ("EXCEPTION: finally clause %d of %s\n", i, mono_method_full_name (method, TRUE));
jit_tls->orig_ex_ctx_set = TRUE;
MONO_PROFILER_RAISE (exception_clause, (method, i, ei->flags, ex_obj));
jit_tls->orig_ex_ctx_set = FALSE;

if (G_UNLIKELY (mono_profiler_clauses_enabled ())) {
jit_tls->orig_ex_ctx_set = TRUE;
MONO_PROFILER_RAISE (exception_clause, (method, i, ei->flags, ex_obj));
jit_tls->orig_ex_ctx_set = FALSE;
}

#ifndef DISABLE_PERFCOUNTERS
mono_atomic_inc_i32 (&mono_perfcounters->exceptions_finallys);
#endif
Expand Down
2 changes: 1 addition & 1 deletion mono/mini/mini-mips.c
Original file line number Diff line number Diff line change
Expand Up @@ -3979,7 +3979,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
mips_nop (code);
/*FIXME should it be before the NOP or not? Does MIPS has a delay slot like sparc?*/
for (GList *tmp = ins->inst_eh_blocks; tmp != bb->clause_holes; tmp = tmp->prev)
mono_cfg_add_try_hole (cfg, (MonoExceptionClause *)tmp->data, code, bb);
mono_cfg_add_try_hole (cfg, ((MonoLeaveClause *) tmp->data)->clause, code, bb);
break;
case OP_LABEL:
ins->inst_c0 = code - cfg->native_code;
Expand Down
2 changes: 1 addition & 1 deletion mono/mini/mini-ppc.c
Original file line number Diff line number Diff line change
Expand Up @@ -4103,7 +4103,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_BB, ins->inst_target_bb);
ppc_bl (code, 0);
for (GList *tmp = ins->inst_eh_blocks; tmp != bb->clause_holes; tmp = tmp->prev)
mono_cfg_add_try_hole (cfg, (MonoExceptionClause *)tmp->data, code, bb);
mono_cfg_add_try_hole (cfg, ((MonoLeaveClause *) tmp->data)->clause, code, bb);
break;
case OP_LABEL:
ins->inst_c0 = code - cfg->native_code;
Expand Down
Loading

0 comments on commit d16ca8d

Please sign in to comment.