diff options
author | github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> | 2022-11-10 21:37:18 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-11-10 21:37:18 +0300 |
commit | d933222dc9c9324694a95049279674b2e502d230 (patch) | |
tree | ec2af1a0ff770ae175f60bcb5e449e3beb2c2b30 | |
parent | 00816bfb6f041fecab48ca9b467c5caba1b8ef3d (diff) |
[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 <vargaz@gmail.com>
-rw-r--r-- | src/mono/mono/mini/interp/interp.c | 21 |
1 files changed, 16 insertions, 5 deletions
diff --git a/src/mono/mono/mini/interp/interp.c b/src/mono/mono/mini/interp/interp.c index b89f8a7a181..89a0b5962e3 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) |