From eb590d4ce19fcb3d39863a18c7f9921eb5a4408a Mon Sep 17 00:00:00 2001 From: Jan Kotas Date: Thu, 1 Dec 2016 16:52:38 -0800 Subject: [PATCH] Introduce CORINFO_EH_CLAUSE_SAMEBLOCK flag for CoreRT ABI CORINFO_EH_CLAUSE_SAMEBLOCK flag is returned on mutually protecting EH clauses for CoreRT ABI. It is set on EH clauses that cover same try block as the previous one. The runtime cannot reliably infer this information from native code offsets without full description of duplicate clauses 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. --- src/inc/corinfo.h | 4 +++- src/jit/codegencommon.cpp | 24 ++++++++++++++++++------ src/jit/jiteh.cpp | 12 ++++++++---- 3 files changed, 29 insertions(+), 11 deletions(-) diff --git a/src/inc/corinfo.h b/src/inc/corinfo.h index cb736cdde589..6e74fd70d24f 100644 --- a/src/inc/corinfo.h +++ b/src/inc/corinfo.h @@ -914,7 +914,9 @@ 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_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_SAMEBLOCK = 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..eaf2a1ce744e 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,18 @@ void CodeGen::genReportEH() CORINFO_EH_CLAUSE_FLAGS flags = ToCORINFO_EH_CLAUSE_FLAGS(HBtab->ebdHandlerType); + if (isCoreRTABI && (XTnum > 0)) + { + // For CoreRT, CORINFO_EH_CLAUSE_SAMEBLOCK 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. + EHblkDsc* HBtabPrev = HBtab - 1; + if ((HBtab->ebdTryBeg == HBtabPrev->ebdTryBeg) && (HBtab->ebdTryLast == HBtabPrev->ebdTryLast)) + flags = (CORINFO_EH_CLAUSE_FLAGS)(flags | CORINFO_EH_CLAUSE_SAMEBLOCK); + } + // Note that we reuse the CORINFO_EH_CLAUSE type, even though the names of // the fields aren't accurate. @@ -3634,9 +3648,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,7 +3715,7 @@ 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.Flags = (CORINFO_EH_CLAUSE_FLAGS)(CORINFO_EH_CLAUSE_FINALLY | CORINFO_EH_CLAUSE_DUPLICATE); clause.TryOffset = hndBeg; clause.TryLength = hndBeg; clause.HandlerOffset = hndBeg; diff --git a/src/jit/jiteh.cpp b/src/jit/jiteh.cpp index b20c2f8a9a6f..cbcbb76bacef 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_SAMEBLOCK) + { + printf(" same block"); + } printf("\n"); }