-
Notifications
You must be signed in to change notification settings - Fork 4.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
JIT: Ensure EH clauses with same try region are reported contiguously to the VM #104531
Changes from 3 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -30,6 +30,8 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX | |
#include "patchpointinfo.h" | ||
#include "optcse.h" // for cse metrics | ||
|
||
#include "jitstd/algorithm.h" | ||
|
||
/*****************************************************************************/ | ||
|
||
void CodeGenInterface::setFramePointerRequiredEH(bool value) | ||
|
@@ -2404,8 +2406,16 @@ void CodeGen::genReportEH() | |
// Tell the VM how many EH clauses to expect. | ||
compiler->eeSetEHcount(EHCount); | ||
|
||
XTnum = 0; // This is the index we pass to the VM | ||
struct EHClauseInfo | ||
{ | ||
CORINFO_EH_CLAUSE clause; | ||
EHblkDsc* HBtab; | ||
}; | ||
|
||
EHClauseInfo* clauses = new (compiler, CMK_Codegen) EHClauseInfo[compiler->compHndBBtabCount]; | ||
|
||
// Set up EH clause table, but don't report anything to the VM, yet. | ||
XTnum = 0; | ||
for (EHblkDsc* const HBtab : EHClauses(compiler)) | ||
{ | ||
UNATIVE_OFFSET tryBeg, tryEnd, hndBeg, hndEnd, hndTyp; | ||
|
@@ -2427,7 +2437,43 @@ void CodeGen::genReportEH() | |
hndTyp = HBtab->ebdTyp; | ||
} | ||
|
||
CORINFO_EH_CLAUSE_FLAGS flags = ToCORINFO_EH_CLAUSE_FLAGS(HBtab->ebdHandlerType); | ||
// Note that we reuse the CORINFO_EH_CLAUSE type, even though the names of | ||
// the fields aren't accurate. | ||
|
||
CORINFO_EH_CLAUSE clause; | ||
clause.ClassToken = hndTyp; /* filter offset is passed back here for filter-based exception handlers */ | ||
clause.Flags = ToCORINFO_EH_CLAUSE_FLAGS(HBtab->ebdHandlerType); | ||
clause.TryOffset = tryBeg; | ||
clause.TryLength = tryEnd; | ||
clause.HandlerOffset = hndBeg; | ||
clause.HandlerLength = hndEnd; | ||
clauses[XTnum++] = {clause, HBtab}; | ||
} | ||
|
||
// 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 + 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; | ||
|
||
if (leftTryIndex == rightTryIndex) | ||
{ | ||
// We have two clauses mapped to the same try region. | ||
// Make sure we report the clause with the smaller index first. | ||
const auto leftIndex = left.HBtab - this->compiler->compHndBBtab; | ||
const auto rightIndex = right.HBtab - this->compiler->compHndBBtab; | ||
return leftIndex < rightIndex; | ||
} | ||
|
||
return leftTryIndex < rightTryIndex; | ||
}); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We don't use any of the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I initially tried doing this, and then iterating over the sorted table to build the clauses in the above loop, but changing the order in which we call There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thats fine. EH is relatively rare and lots of EH clauses even more so. I don't see why there'd be such an order dependence in the emitter, so it is worth digging into more deeply. |
||
|
||
// Now, report EH clauses to the VM in order of increasing try region index. | ||
for (XTnum = 0; XTnum < compiler->compHndBBtabCount; XTnum++) | ||
{ | ||
CORINFO_EH_CLAUSE& clause = clauses[XTnum].clause; | ||
EHblkDsc* const HBtab = clauses[XTnum].HBtab; | ||
|
||
if (XTnum > 0) | ||
{ | ||
|
@@ -2436,33 +2482,18 @@ void CodeGen::genReportEH() | |
// 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, HBtab - 1)) | ||
if (EHblkDsc::ebdIsSameTry(HBtab, clauses[XTnum - 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 | ||
// IL as "try { try {} catch {} catch {} } finally {}". | ||
assert(HBtab->HasCatchHandler()); | ||
flags = (CORINFO_EH_CLAUSE_FLAGS)(flags | CORINFO_EH_CLAUSE_SAMETRY); | ||
clause.Flags = (CORINFO_EH_CLAUSE_FLAGS)(clause.Flags | CORINFO_EH_CLAUSE_SAMETRY); | ||
} | ||
} | ||
|
||
// Note that we reuse the CORINFO_EH_CLAUSE type, even though the names of | ||
// the fields aren't accurate. | ||
|
||
CORINFO_EH_CLAUSE clause; | ||
clause.ClassToken = hndTyp; /* filter offset is passed back here for filter-based exception handlers */ | ||
clause.Flags = flags; | ||
clause.TryOffset = tryBeg; | ||
clause.TryLength = tryEnd; | ||
clause.HandlerOffset = hndBeg; | ||
clause.HandlerLength = hndEnd; | ||
|
||
assert(XTnum < EHCount); | ||
|
||
// Tell the VM about this EH clause. | ||
compiler->eeSetEHinfo(XTnum, &clause); | ||
|
||
++XTnum; | ||
} | ||
|
||
// Now output duplicated clauses. | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we have used
auto
for anything but function types. Useptrdiff_t
?