Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions src/coreclr/jit/codegenwasm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,14 @@ void CodeGen::genAllocLclFrame(unsigned frameSize, regNumber initReg, bool* pIni
GetEmitter()->emitIns_I(INS_local_get, EA_PTRSIZE, GetFramePointerRegIndex());
GetEmitter()->emitFuncletAddressConstant(0 /* funcletId for main method */);
GetEmitter()->emitIns_S(ins_Store(TYP_I_IMPL), EA_PTRSIZE, m_compiler->lvaWasmFunctionIndex, 0);

// Ensure the resume IP is initialized to a non-resuming value.
if ((m_compiler->funCurrentFuncIdx() == ROOT_FUNC_IDX) && (m_compiler->lvaWasmResumeIP != BAD_VAR_NUM))
{
GetEmitter()->emitIns_I(INS_local_get, EA_PTRSIZE, GetFramePointerRegIndex());
GetEmitter()->emitIns_I(INS_I_const, EA_4BYTE, 0);
GetEmitter()->emitIns_S(ins_Store(TYP_INT), EA_4BYTE, m_compiler->lvaWasmResumeIP, 0);
Comment on lines +192 to +196
}
}
}

Expand Down
51 changes: 40 additions & 11 deletions src/coreclr/jit/fgwasm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3254,14 +3254,14 @@ void Compiler::fgWasmEhTransformTry(ArrayStack<BasicBlock*>* catchRetBlocks,
cases[i] = nullptr;
}

// Track the unique edge per continuation block. When many cases share the
// Track the unique reset pad and edge per continuation block. When many cases share the
// same continuation (e.g. a large mutual-protect catch set whose handlers
// all `leave` to the same target) this avoids an O(N^2) cost in
// fgAddRefPred (which must do an O(preds) scan of the destination's
// pred list per call) -- we just bump dup counts directly for duplicates.
//
BlockToFlowEdgeMap* const continuationEdges =
new (this, CMK_FlowEdge) BlockToFlowEdgeMap(getAllocator(CMK_FlowEdge));
BlockToBlockMap resumePads(getAllocator(CMK_FlowEdge));
BlockToFlowEdgeMap continuationEdges(getAllocator(CMK_FlowEdge));

for (BasicBlock* const catchRetBlock : catchRetBlocks->TopDownOrder())
{
Expand All @@ -3274,23 +3274,46 @@ void Compiler::fgWasmEhTransformTry(ArrayStack<BasicBlock*>* catchRetBlocks,

JITDUMP(" case %u: " FMT_BB "\n", biasedCaseIndex, continuation->bbNum);

FlowEdge* caseEdge;
if (continuationEdges->Lookup(continuation, &caseEdge))
BasicBlock* resumePad;
FlowEdge* caseEdge;
if (resumePads.Lookup(continuation, &resumePad))
{
// Edge from switchBlock to this continuation already exists; just
// bump the dup count (and the destination's ref count) instead of
// doing another linear pred-list scan via fgAddRefPred.
//
bool const found = continuationEdges.Lookup(continuation, &caseEdge);
assert(found);
caseEdge->incrementDupCount();
continuation->bbRefs++;
resumePad->bbRefs++;
}
else
{
caseEdge = fgAddRefPred(continuation, switchBlock);
continuationEdges->Set(continuation, caseEdge);
// Clear the resume IP only after this try has accepted the resumption.
// A nonmatching inner try must preserve the value for an enclosing try.
//
resumePad = fgNewBBafter(BBJ_ALWAYS, switchBlock, /* extendRegion */ false);
resumePad->copyEHRegion(continuation);
resumePad->inheritWeightPercentage(switchBlock, 0);

FlowEdge* const padEdge = fgAddRefPred(continuation, resumePad);
padEdge->setLikelihood(1.0);
resumePad->SetTargetEdge(padEdge);

GenTree* const zero = gtNewIconNode(0, TYP_INT);
GenTree* const store = gtNewStoreLclVarNode(resumeIPLocalNum, zero);
LIR::Range range = LIR::SeqTree(this, store);
LIR::AsRange(resumePad).InsertAtEnd(std::move(range));

resumePads.Set(continuation, resumePad);

caseEdge = fgAddRefPred(resumePad, switchBlock);
continuationEdges.Set(continuation, caseEdge);

// We only get here on exception
caseEdge->setLikelihood(0);

JITDUMP("Resume pad " FMT_BB " for " FMT_BB "\n", resumePad->bbNum, continuation->bbNum);
}

assert(cases[biasedCaseIndex] == nullptr);
Expand Down Expand Up @@ -3319,7 +3342,10 @@ void Compiler::fgWasmEhTransformTry(ArrayStack<BasicBlock*>* catchRetBlocks,
for (BasicBlock* const catchRetBlock : catchRetBlocks->TopDownOrder())
{
BasicBlock* const continuation = catchRetBlock->GetTarget();
if (BitVecOps::TryAddElemD(&bitVecTraits, succBlocks, continuation->bbNum))
BasicBlock* resumePad;
bool const found = resumePads.Lookup(continuation, &resumePad);
assert(found);
if (BitVecOps::TryAddElemD(&bitVecTraits, succBlocks, resumePad->bbNum))
{
succCount++;
}
Expand All @@ -3340,10 +3366,13 @@ void Compiler::fgWasmEhTransformTry(ArrayStack<BasicBlock*>* catchRetBlocks,
for (BasicBlock* const catchRetBlock : catchRetBlocks->TopDownOrder())
{
BasicBlock* const continuation = catchRetBlock->GetTarget();
if (BitVecOps::TryAddElemD(&bitVecTraits, succBlocks, continuation->bbNum))
BasicBlock* resumePad;
bool const foundPad = resumePads.Lookup(continuation, &resumePad);
assert(foundPad);
if (BitVecOps::TryAddElemD(&bitVecTraits, succBlocks, resumePad->bbNum))
{
FlowEdge* edge = nullptr;
bool const found = continuationEdges->Lookup(continuation, &edge);
bool const found = continuationEdges.Lookup(continuation, &edge);
assert(found);
succs[succNumber] = edge;
succNumber++;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,42 @@ private static void ThrowException()
throw new Exception("Boom!");
}

[Fact]
public static void RepeatedCatch_ThrowFromSecondCatch_HandledByOuterCatch()
Comment thread
AndyAyersMS marked this conversation as resolved.
{
bool caught = false;

try
{
ThrowFromSecondCatch();
}
catch (InvalidOperationException)
{
caught = true;
}

Assert.True(caught);
}

[MethodImpl(MethodImplOptions.NoInlining)]
private static void ThrowFromSecondCatch()
{
for (int i = 0; i < 2; i++)
{
try
{
throw new Exception();
}
catch
{
if (i != 0)
{
throw new InvalidOperationException();
}
}
}
}

private static void VerifyCallStack(
(string CallerMemberName, string SourceFilePath, int SourceLineNumber) expectedStackFrame,
string reportedCallStack, int skipFrames)
Expand Down
Loading