Skip to content
Merged
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
74 changes: 33 additions & 41 deletions src/coreclr/jit/codegencommon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2542,14 +2542,6 @@ void CodeGen::genReportEH()
if (m_compiler->opts.dspEHTable)
{
printf("*************** EH table for %s\n", m_compiler->info.compFullName);
}
#endif // DEBUG

unsigned XTnum;

#ifdef DEBUG
if (m_compiler->opts.dspEHTable)
{
printf("%d EH table entries\n", m_compiler->compHndBBtabCount);
}
#endif // DEBUG
Expand All @@ -2561,10 +2553,11 @@ void CodeGen::genReportEH()
EHClauseInfo* clauses = new (m_compiler, CMK_Codegen) EHClauseInfo[m_compiler->compHndBBtabCount];

// Set up EH clause table, but don't report anything to the VM, yet.
XTnum = 0;
for (EHblkDsc* const HBtab : EHClauses(m_compiler))
//
for (unsigned int XTnum = 0; XTnum < m_compiler->compHndBBtabCount; XTnum++)
{
UNATIVE_OFFSET tryBeg, tryEnd, hndBeg, hndEnd, hndTyp;
EHblkDsc* const HBtab = &m_compiler->compHndBBtab[XTnum];
UNATIVE_OFFSET tryBeg, tryEnd, hndBeg, hndEnd, hndTyp;

tryBeg = m_compiler->ehCodeOffset(HBtab->ebdTryBeg);
hndBeg = m_compiler->ehCodeOffset(HBtab->ebdHndBeg);
Expand Down Expand Up @@ -2593,7 +2586,10 @@ void CodeGen::genReportEH()
clause.TryLength = tryEnd;
clause.HandlerOffset = hndBeg;
clause.HandlerLength = hndEnd;
clauses[XTnum++] = {clause, HBtab};

unsigned const vmIndex = m_compiler->compEHTabOrderToVMClauseOrder[XTnum];

clauses[vmIndex] = {clause, HBtab};
}

genReportEHClauses(clauses);
Expand All @@ -2605,45 +2601,43 @@ void CodeGen::genReportEH()
// genReportEH: create and report EH info to the VM
//
// Arguments:
// clauses -- eh clause data to report
// clauses -- eh clause data to fill in and report
//
void CodeGen::genReportEHClauses(EHClauseInfo* clauses)
{
// The JIT's ordering of EH clauses does not guarantee that clauses covering the same try region are contiguous.
// We need this property to hold true so the CORINFO_EH_CLAUSE_SAMETRY flag is accurate.
jitstd::sort(clauses, clauses + m_compiler->compHndBBtabCount,
[this](const EHClauseInfo& left, const EHClauseInfo& right) {
const unsigned short leftTryIndex = left.HBtab->ebdTryBeg->bbTryIndex;
const unsigned short rightTryIndex = right.HBtab->ebdTryBeg->bbTryIndex;
// Now, report EH clauses to the VM
//
INDEBUG(unsigned lastFuncletIndex = 0);

for (unsigned vmIndex = 0; vmIndex < m_compiler->compHndBBtabCount; vmIndex++)
{
CORINFO_EH_CLAUSE& clause = clauses[vmIndex].clause;
unsigned const XTnum = m_compiler->compVMClauseOrderToEHTabOrder[vmIndex];
EHblkDsc* const HBtab = &m_compiler->compHndBBtab[XTnum];

if (leftTryIndex == rightTryIndex)
#ifdef DEBUG
// We should be seeing funclet numbers increase predictably
// as we go through the EH table in VM order.
//
if (HBtab->HasFilter())
{
// We have two clauses mapped to the same try region.
// Make sure we report the clause with the smaller index first.
const ptrdiff_t leftIndex = left.HBtab - this->m_compiler->compHndBBtab;
const ptrdiff_t rightIndex = right.HBtab - this->m_compiler->compHndBBtab;
return leftIndex < rightIndex;
assert(HBtab->ebdFuncIndex == (lastFuncletIndex + 2));
}
else
{
assert(HBtab->ebdFuncIndex == (lastFuncletIndex + 1));
}
lastFuncletIndex = HBtab->ebdFuncIndex;
#endif

return leftTryIndex < rightTryIndex;
});

unsigned XTnum;

// Now, report EH clauses to the VM in order of increasing try region index.
for (XTnum = 0; XTnum < m_compiler->compHndBBtabCount; XTnum++)
{
CORINFO_EH_CLAUSE& clause = clauses[XTnum].clause;
EHblkDsc* const HBtab = clauses[XTnum].HBtab;

if (XTnum > 0)
if (vmIndex > 0)
{
// CORINFO_EH_CLAUSE_SAMETRY flag means that the current clause covers same
// try block as the previous one. The runtime cannot reliably infer this information from
// native code offsets because of different try blocks can have same offsets. Alternative
// solution to this problem would be inserting extra nops to ensure that different try
// blocks have different offsets.
if (EHblkDsc::ebdIsSameTry(HBtab, clauses[XTnum - 1].HBtab))
if (EHblkDsc::ebdIsSameTry(HBtab, clauses[vmIndex - 1].HBtab))
{
// The SAMETRY bit should only be set on catch clauses. This is ensured in IL, where only 'catch' is
// allowed to be mutually-protect. E.g., the C# "try {} catch {} catch {} finally {}" actually exists in
Expand All @@ -2653,10 +2647,8 @@ void CodeGen::genReportEHClauses(EHClauseInfo* clauses)
}
}

m_compiler->eeSetEHinfo(XTnum, &clause);
m_compiler->eeSetEHinfo(vmIndex, &clause);
}

assert(XTnum == m_compiler->compHndBBtabCount);
}

#ifndef TARGET_WASM
Expand Down
8 changes: 5 additions & 3 deletions src/coreclr/jit/compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -9459,9 +9459,11 @@ class Compiler
}

// Things that MAY belong either in CodeGen or CodeGenContext
FuncInfoDsc* compFuncInfos;
unsigned short compCurrFuncIdx;
unsigned short compFuncInfoCount;
FuncInfoDsc* compFuncInfos;
unsigned short compCurrFuncIdx;
unsigned short compFuncInfoCount;
unsigned short* compVMClauseOrderToEHTabOrder;
unsigned short* compEHTabOrderToVMClauseOrder;

unsigned short compFuncCount()
{
Expand Down
4 changes: 0 additions & 4 deletions src/coreclr/jit/fgbasic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5380,10 +5380,6 @@ void Compiler::fgMoveBlocksAfter(BasicBlock* bStart, BasicBlock* bEnd, BasicBloc
// Return Value:
// The last block that was relocated, or nullptr on failure.
//
// Notes:
Comment thread
adamperlin marked this conversation as resolved.
// This function can invalidate all pointers into the EH table, as well as
// change the size of the EH table!
//
BasicBlock* Compiler::fgRelocateEHRange(unsigned regionIndex, FG_RELOCATE_TYPE relocateType)
{
INDEBUG(const char* reason = "None";)
Expand Down
69 changes: 45 additions & 24 deletions src/coreclr/jit/fgwasm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2478,26 +2478,33 @@ PhaseStatus Compiler::fgWasmVirtualIP()
unsigned virtualIP = 0;
unsigned updatesAdded = 0;

// Prefill the EH data fields that are not dependent on
// the Virtual IP.
// Prefill the EH data fields that are not dependent on the Virtual IP.
//
// Note this and subsequent accesses to the clause info must respect
// the order in which clauses will be reported to the VM, not the order
// in the compHndBBtab.
//
EHClauseInfo* clauses = nullptr;

if (compHndBBtabCount > 0)
{
clauses = new (this, CMK_WasmEH) EHClauseInfo[compHndBBtabCount];

for (EHblkDsc* const dsc : EHClauses(this))
for (unsigned XTnum = 0; XTnum < compHndBBtabCount; XTnum++)
{
const unsigned index = ehGetIndex(dsc);
EHblkDsc* const dsc = ehGetDsc(XTnum);

CORINFO_EH_CLAUSE clause;
clause.ClassToken = dsc->HasFilter() ? 0 : dsc->ebdTyp;
clause.Flags = ToCORINFO_EH_CLAUSE_FLAGS(dsc->ebdHandlerType);
clause.TryOffset = 0;
clause.TryLength = 0;
clause.HandlerOffset = 0;
clause.HandlerLength = 0;
clauses[index] = {clause, dsc};

unsigned const vmIndex = compEHTabOrderToVMClauseOrder[XTnum];

clauses[vmIndex] = {clause, dsc};
Comment thread
AndyAyersMS marked this conversation as resolved.
}
}

Expand Down Expand Up @@ -2588,7 +2595,10 @@ PhaseStatus Compiler::fgWasmVirtualIP()
if ((tryDsc != nullptr) && (block == tryDsc->ebdTryBeg))
{
virtualIP++;
clauses[block->getTryIndex()].clause.TryOffset = virtualIP;

const unsigned tryIndex = block->getTryIndex();
const unsigned clauseIndex = compEHTabOrderToVMClauseOrder[tryIndex];
clauses[clauseIndex].clause.TryOffset = virtualIP;

Comment thread
AndyAyersMS marked this conversation as resolved.
// Multiple try regions can begin at the same block.
// Update all of their offsets here.
Expand All @@ -2600,24 +2610,29 @@ PhaseStatus Compiler::fgWasmVirtualIP()
// These should be mutual-protect trys.
//
assert(EHblkDsc::ebdIsSameTry(tryDsc, enclosingDsc));
const unsigned enclosingIndex = ehGetIndex(enclosingDsc);
clauses[enclosingIndex].clause.TryOffset = virtualIP;
const unsigned enclosingTryIndex = ehGetIndex(enclosingDsc);
const unsigned enclosingClauseIndex = compEHTabOrderToVMClauseOrder[enclosingTryIndex];
clauses[enclosingClauseIndex].clause.TryOffset = virtualIP;
}
}
}

if ((hndDsc != nullptr) && (block == hndDsc->ebdHndBeg))
{
virtualIP++;
clauses[block->getHndIndex()].clause.HandlerOffset = virtualIP;
const unsigned hndIndex = block->getHndIndex();
const unsigned clauseIndex = compEHTabOrderToVMClauseOrder[hndIndex];
clauses[clauseIndex].clause.HandlerOffset = virtualIP;
}
Comment thread
AndyAyersMS marked this conversation as resolved.

if ((hndDsc != nullptr) && hndDsc->HasFilter() && (block == hndDsc->ebdFilter))
{
virtualIP++;
// For filters we store the offset in the class token field.
//
clauses[block->getHndIndex()].clause.ClassToken = virtualIP;
const unsigned filterIndex = block->getHndIndex();
const unsigned clauseIndex = compEHTabOrderToVMClauseOrder[filterIndex];
clauses[clauseIndex].clause.ClassToken = virtualIP;
Comment thread
AndyAyersMS marked this conversation as resolved.
}

// For now, just refresh the stack Virtual IP at the start of each non-empty
Expand All @@ -2635,8 +2650,10 @@ PhaseStatus Compiler::fgWasmVirtualIP()
if ((tryDsc != nullptr) && (block == tryDsc->ebdTryLast))
{
virtualIP++;
assert(virtualIP > clauses[block->getTryIndex()].clause.TryOffset);
clauses[block->getTryIndex()].clause.TryLength = virtualIP;
const unsigned tryIndex = block->getTryIndex();
const unsigned clauseIndex = compEHTabOrderToVMClauseOrder[tryIndex];
assert(virtualIP > clauses[clauseIndex].clause.TryOffset);
clauses[clauseIndex].clause.TryLength = virtualIP;
Comment thread
AndyAyersMS marked this conversation as resolved.

// Multiple try regions can end at the same block.
// Update all of their extents here.
Expand All @@ -2647,18 +2664,21 @@ PhaseStatus Compiler::fgWasmVirtualIP()
{
if (enclosingDsc->ebdTryLast == block)
{
const unsigned enclosingIndex = ehGetIndex(enclosingDsc);
assert(virtualIP > clauses[enclosingIndex].clause.TryOffset);
clauses[enclosingIndex].clause.TryLength = virtualIP;
const unsigned enclosingTryIndex = ehGetIndex(enclosingDsc);
const unsigned enclosingClauseIndex = compEHTabOrderToVMClauseOrder[enclosingTryIndex];
assert(virtualIP > clauses[enclosingClauseIndex].clause.TryOffset);
clauses[enclosingClauseIndex].clause.TryLength = virtualIP;
}
}
}

if ((hndDsc != nullptr) && (block == hndDsc->ebdHndLast))
{
virtualIP++;
assert(virtualIP > clauses[block->getHndIndex()].clause.HandlerOffset);
clauses[block->getHndIndex()].clause.HandlerLength = virtualIP;
const unsigned hndIndex = block->getHndIndex();
const unsigned clauseIndex = compEHTabOrderToVMClauseOrder[hndIndex];
assert(virtualIP > clauses[clauseIndex].clause.HandlerOffset);
clauses[clauseIndex].clause.HandlerLength = virtualIP;
}

if ((hndDsc != nullptr) && hndDsc->HasFilter() && (block->Next() == hndDsc->ebdHndBeg))
Expand All @@ -2677,19 +2697,20 @@ PhaseStatus Compiler::fgWasmVirtualIP()
JITDUMP("EH virtual IP ranges\n");
for (EHblkDsc* const dsc : EHClauses(this))
{
const unsigned index = ehGetIndex(dsc);
const unsigned index = ehGetIndex(dsc);
const unsigned clauseIndex = compEHTabOrderToVMClauseOrder[index];

JITDUMP("EH#%02u: Try [%04u..%04u)", index, clauses[index].clause.TryOffset,
clauses[index].clause.TryLength);
JITDUMP("EH#%02u: Try [%04u..%04u)", index, clauses[clauseIndex].clause.TryOffset,
clauses[clauseIndex].clause.TryLength);

if (dsc->HasFilter())
{
JITDUMP(" Filter [%04u..%04u)\n", clauses[index].clause.ClassToken,
clauses[index].clause.HandlerOffset);
JITDUMP(" Filter [%04u..%04u)\n", clauses[clauseIndex].clause.ClassToken,
clauses[clauseIndex].clause.HandlerOffset);
}

JITDUMP(" Handler [%04u..%04u)\n", clauses[index].clause.HandlerOffset,
clauses[index].clause.HandlerLength);
JITDUMP(" Handler [%04u..%04u)\n", clauses[clauseIndex].clause.HandlerOffset,
clauses[clauseIndex].clause.HandlerLength);
}
}
#endif // DEBUG
Expand Down
Loading
Loading