diff --git a/src/inc/corinfo.h b/src/inc/corinfo.h index cb736cdde589..e899a2337929 100644 --- a/src/inc/corinfo.h +++ b/src/inc/corinfo.h @@ -911,10 +911,12 @@ enum CORINFO_ACCESS_FLAGS // These are the flags set on an CORINFO_EH_CLAUSE enum CORINFO_EH_CLAUSE_FLAGS { - CORINFO_EH_CLAUSE_NONE = 0, - CORINFO_EH_CLAUSE_FILTER = 0x0001, // If this bit is on, then this EH entry is for a filter - CORINFO_EH_CLAUSE_FINALLY = 0x0002, // This clause is a finally clause - CORINFO_EH_CLAUSE_FAULT = 0x0004, // This clause is a fault clause + CORINFO_EH_CLAUSE_NONE = 0, + CORINFO_EH_CLAUSE_FILTER = 0x0001, // If this bit is on, then this EH entry is for a filter + CORINFO_EH_CLAUSE_FINALLY = 0x0002, // This clause is a finally clause + CORINFO_EH_CLAUSE_FAULT = 0x0004, // This clause is a fault clause + CORINFO_EH_CLAUSE_DUPLICATE = 0x0008, // Duplicated clause. This clause was duplicated to a funclet which was pulled out of line + CORINFO_EH_CLAUSE_SAMETRY = 0x0010, // This clause covers same try block as the previous one. (Used by CoreRT ABI.) }; // This enumeration is passed to InternalThrow diff --git a/src/jit/codegencommon.cpp b/src/jit/codegencommon.cpp index f2de5d18b468..b30021d3bfb4 100644 --- a/src/jit/codegencommon.cpp +++ b/src/jit/codegencommon.cpp @@ -3319,6 +3319,8 @@ void CodeGen::genReportEH() EHblkDsc* HBtab; EHblkDsc* HBtabEnd; + bool isCoreRTABI = compiler->IsTargetAbi(CORINFO_CORERT_ABI); + unsigned EHCount = compiler->compHndBBtabCount; #if FEATURE_EH_FUNCLETS @@ -3328,7 +3330,7 @@ void CodeGen::genReportEH() unsigned enclosingTryIndex; // Duplicate clauses are not used by CoreRT ABI - if (!compiler->IsTargetAbi(CORINFO_CORERT_ABI)) + if (!isCoreRTABI) { for (XTnum = 0; XTnum < compiler->compHndBBtabCount; XTnum++) { @@ -3347,7 +3349,7 @@ void CodeGen::genReportEH() unsigned clonedFinallyCount = 0; // Duplicate clauses are not used by CoreRT ABI - if (!compiler->IsTargetAbi(CORINFO_CORERT_ABI)) + if (!isCoreRTABI) { // We don't keep track of how many cloned finally there are. So, go through and count. // We do a quick pass first through the EH table to see if there are any try/finally @@ -3429,6 +3431,23 @@ void CodeGen::genReportEH() CORINFO_EH_CLAUSE_FLAGS flags = ToCORINFO_EH_CLAUSE_FLAGS(HBtab->ebdHandlerType); + if (isCoreRTABI && (XTnum > 0)) + { + // For CoreRT, 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, HBtab - 1)) + { + // 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); + } + } + // Note that we reuse the CORINFO_EH_CLAUSE type, even though the names of // the fields aren't accurate. @@ -3634,9 +3653,7 @@ void CodeGen::genReportEH() CORINFO_EH_CLAUSE_FLAGS flags = ToCORINFO_EH_CLAUSE_FLAGS(encTab->ebdHandlerType); // Tell the VM this is an extra clause caused by moving funclets out of line. - // It seems weird this is from the CorExceptionFlag enum in corhdr.h, - // not the CORINFO_EH_CLAUSE_FLAGS enum in corinfo.h. - flags = (CORINFO_EH_CLAUSE_FLAGS)(flags | COR_ILEXCEPTION_CLAUSE_DUPLICATED); + flags = (CORINFO_EH_CLAUSE_FLAGS)(flags | CORINFO_EH_CLAUSE_DUPLICATE); // Note that the JIT-EE interface reuses the CORINFO_EH_CLAUSE type, even though the names of // the fields aren't really accurate. For example, we set "TryLength" to the offset of the @@ -3703,9 +3720,9 @@ void CodeGen::genReportEH() CORINFO_EH_CLAUSE clause; clause.ClassToken = 0; // unused - clause.Flags = (CORINFO_EH_CLAUSE_FLAGS)(CORINFO_EH_CLAUSE_FINALLY | COR_ILEXCEPTION_CLAUSE_DUPLICATED); - clause.TryOffset = hndBeg; - clause.TryLength = hndBeg; + clause.Flags = (CORINFO_EH_CLAUSE_FLAGS)(CORINFO_EH_CLAUSE_FINALLY | CORINFO_EH_CLAUSE_DUPLICATE); + clause.TryOffset = hndBeg; + clause.TryLength = hndBeg; clause.HandlerOffset = hndBeg; clause.HandlerLength = hndEnd; diff --git a/src/jit/jiteh.cpp b/src/jit/jiteh.cpp index b20c2f8a9a6f..4b3ceaecf6c1 100644 --- a/src/jit/jiteh.cpp +++ b/src/jit/jiteh.cpp @@ -2979,7 +2979,7 @@ void Compiler::dispOutgoingEHClause(unsigned num, const CORINFO_EH_CLAUSE& claus // Note: the flags field is kind of weird. It should be compared for equality // to determine the type of clause, even though it looks like a bitfield. In // Particular, CORINFO_EH_CLAUSE_NONE is zero, so you can "&" to check it. - // You do need to mask off the bits, though, because COR_ILEXCEPTION_CLAUSE_DUPLICATED + // You do need to mask off the bits, though, because CORINFO_EH_CLAUSE_DUPLICATE // is and'ed in. const DWORD CORINFO_EH_CLAUSE_TYPE_MASK = 0x7; switch (clause.Flags & CORINFO_EH_CLAUSE_TYPE_MASK) @@ -3013,15 +3013,19 @@ void Compiler::dispOutgoingEHClause(unsigned num, const CORINFO_EH_CLAUSE& claus } if ((clause.TryOffset == clause.TryLength) && (clause.TryOffset == clause.HandlerOffset) && - ((clause.Flags & (COR_ILEXCEPTION_CLAUSE_DUPLICATED | COR_ILEXCEPTION_CLAUSE_FINALLY)) == - (COR_ILEXCEPTION_CLAUSE_DUPLICATED | COR_ILEXCEPTION_CLAUSE_FINALLY))) + ((clause.Flags & (CORINFO_EH_CLAUSE_DUPLICATE | CORINFO_EH_CLAUSE_FINALLY)) == + (CORINFO_EH_CLAUSE_DUPLICATE | CORINFO_EH_CLAUSE_FINALLY))) { printf(" cloned finally"); } - else if (clause.Flags & COR_ILEXCEPTION_CLAUSE_DUPLICATED) + else if (clause.Flags & CORINFO_EH_CLAUSE_DUPLICATE) { printf(" duplicated"); } + else if (clause.Flags & CORINFO_EH_CLAUSE_SAMETRY) + { + printf(" same try"); + } printf("\n"); }