From e2468033a09f776525b6a8c8eb26ca61155bd886 Mon Sep 17 00:00:00 2001 From: Andy Ayers Date: Thu, 16 Jul 2026 16:47:51 -0700 Subject: [PATCH] [Wasm RyuJit] fix throw helper layout for side try entries in enclosed regions If an enclosed try region has a side entry (say from an async resume), add edges to (eagerly visit) the helper blocks in this region and in all enclosing try regions, so that the throw helpers end up being placed after any blocks in the respective regions. This generalizes the fix from #130153. --- src/coreclr/jit/compiler.h | 28 ++++++++++++++++++++++++++++ src/coreclr/jit/fgwasm.h | 19 +++++++++++++++---- src/coreclr/jit/flowgraph.cpp | 8 ++++---- 3 files changed, 47 insertions(+), 8 deletions(-) diff --git a/src/coreclr/jit/compiler.h b/src/coreclr/jit/compiler.h index 7f733cd3e44006..5576bec68bf6ea 100644 --- a/src/coreclr/jit/compiler.h +++ b/src/coreclr/jit/compiler.h @@ -7405,6 +7405,34 @@ class Compiler unsigned Data() const { return acdData; } + // Region-kind flag bits packed into acdData by bbThrowIndex. + static const unsigned AcdHandlerFlag = 0x40000000; + static const unsigned AcdFilterFlag = 0x80000000; + + // The EH region kind that keys this helper. + AcdKeyDesignator Designator() const + { + if (acdData == 0) + { + return AcdKeyDesignator::KD_NONE; + } + if ((acdData & AcdFilterFlag) != 0) + { + return AcdKeyDesignator::KD_FLT; + } + if ((acdData & AcdHandlerFlag) != 0) + { + return AcdKeyDesignator::KD_HND; + } + return AcdKeyDesignator::KD_TRY; + } + + // The 0-based EH region index this helper is keyed to (not valid for KD_NONE). + unsigned RegionIndex() const + { + return (acdData & ~(AcdHandlerFlag | AcdFilterFlag)) - 1; + } + private: SpecialCodeKind acdKind; diff --git a/src/coreclr/jit/fgwasm.h b/src/coreclr/jit/fgwasm.h index c5be5ccf3cd717..5070be0da26f61 100644 --- a/src/coreclr/jit/fgwasm.h +++ b/src/coreclr/jit/fgwasm.h @@ -436,19 +436,30 @@ BasicBlockVisit FgWasm::VisitWasmSuccs(Compiler* comp, BasicBlock* block, TFunc Compiler::AddCodeDscMap* const acdMap = comp->fgGetAddCodeDscMap(); if (acdMap != nullptr) { + const bool isTrySideEntry = isGeneralizedTryEntry(block); + // Behave as if these blocks have edges from their respective region entry blocks. // - if ((block == comp->fgFirstBB) || comp->bbIsFuncletBeg(block) || isGeneralizedTryEntry(block)) + if ((block == comp->fgFirstBB) || comp->bbIsFuncletBeg(block) || isTrySideEntry) { Compiler::AcdKeyDesignator dsg; const unsigned blockData = comp->bbThrowIndex(block, &dsg); for (const Compiler::AddCodeDscKey& key : Compiler::AddCodeDscMap::KeyIteration(acdMap)) { - if (key.Data() == blockData) + const unsigned acdData = key.Data(); + bool matches = (acdData == blockData); + + if (!matches && isTrySideEntry && (key.Designator() == Compiler::AcdKeyDesignator::KD_TRY)) + { + // Also add edges from all enclosing try regions + matches = comp->bbInTryRegions(key.RegionIndex(), block); + } + + if (matches) { - // This ACD refers to a throw helper block in the right region. - // Make the block a successor. + // This ACD refers to a throw helper block in this or an enclosed try region. + // Make the throw helper block a successor of the try entry. // Compiler::AddCodeDsc* acd = nullptr; acdMap->Lookup(key, &acd); diff --git a/src/coreclr/jit/flowgraph.cpp b/src/coreclr/jit/flowgraph.cpp index 8d0eb82c81e30c..68cbb0d2887108 100644 --- a/src/coreclr/jit/flowgraph.cpp +++ b/src/coreclr/jit/flowgraph.cpp @@ -3898,11 +3898,11 @@ unsigned Compiler::bbThrowIndex(BasicBlock* blk, AcdKeyDesignator* dsg) if (ehGetDsc(hndIndex - 1)->InFilterRegionBBRange(blk)) { *dsg = AcdKeyDesignator::KD_FLT; - return hndIndex | 0x80000000; + return hndIndex | AddCodeDscKey::AcdFilterFlag; } *dsg = AcdKeyDesignator::KD_HND; - return hndIndex | 0x40000000; + return hndIndex | AddCodeDscKey::AcdHandlerFlag; } //------------------------------------------------------------------------ @@ -3956,10 +3956,10 @@ Compiler::AddCodeDscKey::AddCodeDscKey(AddCodeDsc* add) acdData = add->acdTryIndex; break; case AcdKeyDesignator::KD_HND: - acdData = add->acdHndIndex | 0x40000000; + acdData = add->acdHndIndex | AcdHandlerFlag; break; case AcdKeyDesignator::KD_FLT: - acdData = add->acdHndIndex | 0x80000000; + acdData = add->acdHndIndex | AcdFilterFlag; break; default: unreached();