From c00414de3bb7c637bdd7afad3e1e4001751a5cf5 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Mon, 21 Nov 2022 15:07:47 -0500 Subject: [PATCH] [mono][wasm] Disable AOTing methods which contain catch clauses inside finally/filter clauses. When the ENDFINALLY opcode of the outer clause is encountered while executing the inner catch clause from run_with_il_state (), it will assert since it doesn't know where to continue execution. --- src/mono/mono/mini/method-to-ir.c | 2 -- src/mono/mono/mini/mini.c | 28 +++++++++++++++++++++++++--- 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/src/mono/mono/mini/method-to-ir.c b/src/mono/mono/mini/method-to-ir.c index 41bece492d72d..c00b9d6cd1018 100644 --- a/src/mono/mono/mini/method-to-ir.c +++ b/src/mono/mono/mini/method-to-ir.c @@ -6554,8 +6554,6 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b if (cfg->llvm_only && cfg->interp && cfg->method == method && !cfg->deopt && !cfg->interp_entry_only) { if (header->num_clauses) { - /* deopt is only disabled for gsharedvt */ - g_assert (cfg->gsharedvt); for (guint i = 0; i < header->num_clauses; ++i) { MonoExceptionClause *clause = &header->clauses [i]; /* Finally clauses are checked after the remove_finally pass */ diff --git a/src/mono/mono/mini/mini.c b/src/mono/mono/mini/mini.c index 168d3d3a3c093..92d158c1ab410 100644 --- a/src/mono/mono/mini/mini.c +++ b/src/mono/mono/mini/mini.c @@ -3303,9 +3303,31 @@ mini_method_compile (MonoMethod *method, guint32 opts, JitFlags flags, int parts } if (cfg->llvm_only && cfg->interp && !cfg->interp_entry_only && header->num_clauses) { - cfg->deopt = TRUE; - /* Can't reconstruct inlined state */ - cfg->disable_inline = TRUE; + gboolean can_deopt = TRUE; + /* + * Can't handle catch clauses inside finally clauses right now. + * When the ENDFINALLY opcode of the outer clause is encountered + * while executing the inner catch clause from run_with_il_state (), + * it will assert since it doesn't know where to continue execution. + */ + for (guint i = 0; i < cfg->header->num_clauses; ++i) { + for (guint j = 0; j < cfg->header->num_clauses; ++j) { + MonoExceptionClause *clause1 = &cfg->header->clauses [i]; + MonoExceptionClause *clause2 = &cfg->header->clauses [j]; + + if (i != j && clause1->try_offset >= clause2->try_offset && clause1->handler_offset <= clause2->handler_offset) { + if (clause1->flags == MONO_EXCEPTION_CLAUSE_NONE && clause2->flags != MONO_EXCEPTION_CLAUSE_NONE) { + can_deopt = FALSE; + break; + } + } + } + } + if (can_deopt) { + cfg->deopt = TRUE; + /* Can't reconstruct inlined state */ + cfg->disable_inline = TRUE; + } } #ifdef ENABLE_LLVM