From d933222dc9c9324694a95049279674b2e502d230 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 10 Nov 2022 10:37:18 -0800 Subject: [PATCH] [release/7.0] [mono][interp] Fix an issue with deopt and interpreter tiering. (#77059) * [mono][interp] Fix an issue with deopt and interpreter tiering. If a method is tiered while being run from interp_run_clause_with_il_state (), the clause_args argument to interp_exec_method () still contains the old IL offsets confusing the EH code, i.e. this line: ``` if (clause_args && frame == clause_args->exec_frame && context->handler_ip >= clause_args->end_at_ip) ``` Clear out clause_args at the beginning to avoid this. Hopefully fixes https://github.com/dotnet/runtime/issues/76134 https://github.com/dotnet/runtime/issues/74302 * [mono][interp] Avoid tiering up methods while running clauses. The IL offsets in the clause_args argument become out-of-date after tiering up. Co-authored-by: Zoltan Varga --- src/mono/mono/mini/interp/interp.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/src/mono/mono/mini/interp/interp.c b/src/mono/mono/mini/interp/interp.c index b89f8a7a181c7f..89a0b5962e3f85 100644 --- a/src/mono/mono/mini/interp/interp.c +++ b/src/mono/mono/mini/interp/interp.c @@ -94,6 +94,7 @@ struct FrameClauseArgs { const guint16 *end_at_ip; /* Frame that is executing this clause */ InterpFrame *exec_frame; + gboolean run_until_end; }; /* @@ -3595,6 +3596,13 @@ interp_exec_method (InterpFrame *frame, ThreadContext *context, FrameClauseArgs INIT_INTERP_STATE (frame, clause_args); + if (clause_args && clause_args->run_until_end) + /* + * Called from run_with_il_state to run the method until the end. + * Clear this out so it doesn't confuse the rest of the code. + */ + clause_args = NULL; + #ifdef ENABLE_EXPERIMENT_TIERED mini_tiered_inc (frame->imethod->method, &frame->imethod->tiered_counter, 0); #endif @@ -7067,7 +7075,7 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; MINT_IN_CASE(MINT_TIER_ENTER_METHOD) { frame->imethod->entry_count++; - if (frame->imethod->entry_count > INTERP_TIER_ENTRY_LIMIT) + if (frame->imethod->entry_count > INTERP_TIER_ENTRY_LIMIT && !clause_args) ip = mono_interp_tier_up_frame_enter (frame, context); else ip++; @@ -7075,7 +7083,7 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; } MINT_IN_CASE(MINT_TIER_PATCHPOINT) { frame->imethod->entry_count++; - if (frame->imethod->entry_count > INTERP_TIER_ENTRY_LIMIT) + if (frame->imethod->entry_count > INTERP_TIER_ENTRY_LIMIT && !clause_args) ip = mono_interp_tier_up_frame_patchpoint (frame, context, ip [1]); else ip += 2; @@ -7656,10 +7664,13 @@ interp_run_clause_with_il_state (gpointer il_state_ptr, int clause_index, MonoOb clause_args.start_with_ip = (const guint16*)ei->data.filter; else clause_args.start_with_ip = (const guint16*)ei->handler_start; - if (clause_type == MONO_EXCEPTION_CLAUSE_NONE || clause_type == MONO_EXCEPTION_CLAUSE_FILTER) - clause_args.end_at_ip = (const guint16*)clause_args.start_with_ip + 0xffffff; - else + if (clause_type == MONO_EXCEPTION_CLAUSE_NONE || clause_type == MONO_EXCEPTION_CLAUSE_FILTER) { + /* Run until the end */ + clause_args.end_at_ip = NULL; + clause_args.run_until_end = TRUE; + } else { clause_args.end_at_ip = (const guint16*)ei->data.handler_end; + } clause_args.exec_frame = &frame; if (clause_type == MONO_EXCEPTION_CLAUSE_NONE || clause_type == MONO_EXCEPTION_CLAUSE_FILTER)