summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPat Gavlin <pagavlin@microsoft.com>2016-05-03 12:58:16 -0700
committerPat Gavlin <pagavlin@microsoft.com>2016-05-03 12:58:16 -0700
commit8f71b159a1edb4fbb187bcc95c6e20bc9e2ea4d8 (patch)
tree5d88aeed51400b36d38af662acff9ad60f3e2703
parentadce1932c1138b9e6b48592aa21b6729d4dedcc8 (diff)
downloadcoreclr-8f71b159a1edb4fbb187bcc95c6e20bc9e2ea4d8.tar.gz
coreclr-8f71b159a1edb4fbb187bcc95c6e20bc9e2ea4d8.tar.bz2
coreclr-8f71b159a1edb4fbb187bcc95c6e20bc9e2ea4d8.zip
Remove SEH interactions between the JIT and the EE.
This change replaces the final uses of SEH between the JIT and the EE with a new method on ICorJitInfo, `ICorJitInfo::runWithErrorTrap`. This method runs a given function under an error trap that prevents recoverable errors from propagating out of the call. This allows the JIT to make calls to JIT/EE interface functions that may throw exceptions without needing to be aware of the EH ABI, exception types, etc. The method returns true if the given function completed successfully and false otherwise. This change deprecates all other SEH-related functionality on the JIT/EE interface (e.g. `ICJI::FilterException` and `ICJI::HandleException`). This change does not completely eliminate SEH over the JIT/EE interface: there are still a handful of places where the JIT expects to be able to catch exceptions thrown by SuperPMI. These uses of SEH will be removed later on. Fixes #3058 and #4130. [tfs-changeset: 1601288]
-rw-r--r--src/inc/corinfo.h21
-rw-r--r--src/jit/compiler.h8
-rw-r--r--src/jit/ee_il_dll.cpp44
-rw-r--r--src/jit/error.cpp9
-rw-r--r--src/jit/error.h12
-rw-r--r--src/jit/flowgraph.cpp7
-rw-r--r--src/jit/importer.cpp7
-rw-r--r--src/vm/jitinterface.cpp75
-rw-r--r--src/vm/jitinterface.h2
-rw-r--r--src/zap/zapinfo.cpp5
-rw-r--r--src/zap/zapinfo.h2
11 files changed, 160 insertions, 32 deletions
diff --git a/src/inc/corinfo.h b/src/inc/corinfo.h
index 8978b951a5..0eca760f38 100644
--- a/src/inc/corinfo.h
+++ b/src/inc/corinfo.h
@@ -231,11 +231,11 @@ TODO: Talk about initializing strutures before use
#if COR_JIT_EE_VERSION > 460
// Update this one
-SELECTANY const GUID JITEEVersionIdentifier = { /* 8c8e61ca-2b88-4bc5-b03f-d390acdc7fc3 */
- 0x8c8e61ca,
- 0x2b88,
- 0x4bc5,
- { 0xb0, 0x3f, 0xd3, 0x90, 0xac, 0xdc, 0x7f, 0xc3 }
+SELECTANY const GUID JITEEVersionIdentifier = { /* 57813506-0058-41df-8b1b-e0b68c3a9da3 */
+ 0x57813506,
+ 0x58,
+ 0x41df,
+ { 0x8b, 0x1b, 0xe0, 0xb6, 0x8c, 0x3a, 0x9d, 0xa3 }
};
#else
@@ -2723,6 +2723,17 @@ public:
virtual void ThrowExceptionForHelper(
const CORINFO_HELPER_DESC * throwHelper) = 0;
+#if COR_JIT_EE_VERSION > 460
+ // Runs the given function under an error trap. This allows the JIT to make calls
+ // to interface functions that may throw exceptions without needing to be aware of
+ // the EH ABI, exception types, etc. Returns true if the given function completed
+ // successfully and false otherwise.
+ virtual bool runWithErrorTrap(
+ void (*function)(void*), // The function to run
+ void* parameter // The context parameter that will be passed to the function and the handler
+ ) = 0;
+#endif
+
/*****************************************************************************
* ICorStaticInfo contains EE interface methods which return values that are
* constant from invocation to invocation. Thus they may be embedded in
diff --git a/src/jit/compiler.h b/src/jit/compiler.h
index e1c0046575..818408a35d 100644
--- a/src/jit/compiler.h
+++ b/src/jit/compiler.h
@@ -6456,6 +6456,14 @@ public :
bool eeTryResolveToken(CORINFO_RESOLVED_TOKEN* resolvedToken);
+ template<typename ParamType>
+ bool eeRunWithErrorTrap(void (*function)(ParamType*), ParamType* param)
+ {
+ return eeRunWithErrorTrapImp(reinterpret_cast<void (*)(void*)>(function), reinterpret_cast<void*>(param));
+ }
+
+ bool eeRunWithErrorTrapImp(void (*function)(void*), void* param);
+
// Utility functions
#if defined(DEBUG)
diff --git a/src/jit/ee_il_dll.cpp b/src/jit/ee_il_dll.cpp
index 8193b1573b..004642e4a8 100644
--- a/src/jit/ee_il_dll.cpp
+++ b/src/jit/ee_il_dll.cpp
@@ -1227,6 +1227,45 @@ bool Compiler::eeTryResolveToken(CORINFO_RESOLVED_TOKEN* resolvedToken)
return param.m_success;
}
+struct TrapParam
+{
+ ICorJitInfo* m_corInfo;
+ EXCEPTION_POINTERS m_exceptionPointers;
+
+ void (*m_function)(void*);
+ void* m_param;
+ bool m_success;
+};
+
+static LONG __EEFilter(PEXCEPTION_POINTERS exceptionPointers, void* param)
+{
+ auto* trapParam = reinterpret_cast<TrapParam*>(param);
+ trapParam->m_exceptionPointers = *exceptionPointers;
+ return trapParam->m_corInfo->FilterException(exceptionPointers);
+}
+
+bool Compiler::eeRunWithErrorTrapImp(void (*function)(void*), void* param)
+{
+ TrapParam trapParam;
+ trapParam.m_corInfo = info.compCompHnd;
+ trapParam.m_function = function;
+ trapParam.m_param = param;
+ trapParam.m_success = true;
+
+ PAL_TRY(TrapParam*, __trapParam, &trapParam)
+ {
+ __trapParam->m_function(__trapParam->m_param);
+ }
+ PAL_EXCEPT_FILTER(__EEFilter)
+ {
+ trapParam.m_corInfo->HandleException(&trapParam.m_exceptionPointers);
+ trapParam.m_success = false;
+ }
+ PAL_ENDTRY
+
+ return trapParam.m_success;
+}
+
#else // CORJIT_EE_VER <= 460
bool Compiler::eeTryResolveToken(CORINFO_RESOLVED_TOKEN* resolvedToken)
@@ -1234,6 +1273,11 @@ bool Compiler::eeTryResolveToken(CORINFO_RESOLVED_TOKEN* resolvedToken)
return info.compCompHnd->tryResolveToken(resolvedToken);
}
+bool Compiler::eeRunWithErrorTrapImp(void (*function)(void*), void* param)
+{
+ return info.compCompHnd->runWithErrorTrap(function, param);
+}
+
#endif // CORJIT_EE_VER > 460
/*****************************************************************************
diff --git a/src/jit/error.cpp b/src/jit/error.cpp
index 91b4f7a056..a52f9e5836 100644
--- a/src/jit/error.cpp
+++ b/src/jit/error.cpp
@@ -197,15 +197,6 @@ void notYetImplemented(const char * msg, const char * filename, unsigned line)
#endif // #if !defined(_TARGET_X86_) || !defined(LEGACY_BACKEND)
/*****************************************************************************/
-LONG __EEfilter(PEXCEPTION_POINTERS pExceptionPointers, LPVOID lpvParam)
-{
- ErrorTrapParam *pErrorTrapParam = (ErrorTrapParam *)lpvParam;
- ICorJitInfo * m_jitInfo = pErrorTrapParam->jitInfo;
- pErrorTrapParam->exceptionPointers = *pExceptionPointers;
- return m_jitInfo->FilterException(pExceptionPointers);
-}
-
-/*****************************************************************************/
LONG __JITfilter(PEXCEPTION_POINTERS pExceptionPointers, LPVOID lpvParam)
{
DWORD exceptCode = pExceptionPointers->ExceptionRecord->ExceptionCode;
diff --git a/src/jit/error.h b/src/jit/error.h
index d883fb08c9..fa4ba0d636 100644
--- a/src/jit/error.h
+++ b/src/jit/error.h
@@ -21,8 +21,7 @@ struct ErrorTrapParam
ErrorTrapParam() { jitInfo = NULL; }
};
-extern LONG __EEfilter(PEXCEPTION_POINTERS pExceptionPointers, LPVOID lpvParam);
- // Only catch JIT internal errors (will not catch EE generated Errors)
+// Only catch JIT internal errors (will not catch EE generated Errors)
extern LONG __JITfilter(PEXCEPTION_POINTERS pExceptionPointers, LPVOID lpvParam);
#define setErrorTrap(compHnd, ParamType, paramDef, paramRef) \
@@ -37,20 +36,13 @@ extern LONG __JITfilter(PEXCEPTION_POINTERS pExceptionPointers, LPVO
{ \
ParamType paramDef = __JITpParam->param;
- // Catch only JitGeneratedErrors
+// Only catch JIT internal errors (will not catch EE generated Errors)
#define impJitErrorTrap() \
} \
PAL_EXCEPT_FILTER(__JITfilter) \
{ \
int __errc = __JITparam.errc; (void) __errc;
- // Catch all errors (including recoverable ones from the EE)
-#define impErrorTrap() \
- } \
- PAL_EXCEPT_FILTER(__EEfilter) \
- { \
- __JITparam.jitInfo->HandleException(&__JITparam.exceptionPointers);
-
#define endErrorTrap() \
} \
PAL_ENDTRY
diff --git a/src/jit/flowgraph.cpp b/src/jit/flowgraph.cpp
index a847091f51..2cfed2e23c 100644
--- a/src/jit/flowgraph.cpp
+++ b/src/jit/flowgraph.cpp
@@ -21922,7 +21922,7 @@ void Compiler::fgInvokeInlineeCompiler(GenTreeCall* call,
param.fncHandle = fncHandle;
param.inlineCandidateInfo = inlineCandidateInfo;
param.inlineInfo = &inlineInfo;
- setErrorTrap(info.compCompHnd, Param*, pParam, &param)
+ bool success = eeRunWithErrorTrap<Param>([](Param* pParam)
{
// Init the local var info of the inlinee
pParam->pThis->impInlineInitVars(pParam->inlineInfo);
@@ -21988,8 +21988,8 @@ void Compiler::fgInvokeInlineeCompiler(GenTreeCall* call,
}
}
}
- }
- impErrorTrap()
+ }, &param);
+ if (!success)
{
#ifdef DEBUG
if (verbose)
@@ -22006,7 +22006,6 @@ void Compiler::fgInvokeInlineeCompiler(GenTreeCall* call,
inlineResult->NoteFatal(InlineObservation::CALLSITE_COMPILATION_ERROR);
}
}
- endErrorTrap();
if (inlineResult->IsFailure())
{
diff --git a/src/jit/importer.cpp b/src/jit/importer.cpp
index 7c24aa87e4..707f4fe417 100644
--- a/src/jit/importer.cpp
+++ b/src/jit/importer.cpp
@@ -15605,7 +15605,7 @@ void Compiler::impCheckCanInline(GenTreePtr call,
param.result = inlineResult;
param.ppInlineCandidateInfo = ppInlineCandidateInfo;
- setErrorTrap(info.compCompHnd, Param *, pParam, &param)
+ bool success = eeRunWithErrorTrap<Param>([](Param* pParam)
{
DWORD dwRestrictions = 0;
CorInfoInitClassResult initClassResult;
@@ -15741,12 +15741,11 @@ void Compiler::impCheckCanInline(GenTreePtr call,
_exit:
;
- }
- impErrorTrap()
+ }, &param);
+ if (!success)
{
param.result->NoteFatal(InlineObservation::CALLSITE_COMPILATION_ERROR);
}
- endErrorTrap();
}
void Compiler::impInlineRecordArgInfo(InlineInfo * pInlineInfo,
diff --git a/src/vm/jitinterface.cpp b/src/vm/jitinterface.cpp
index 2cf2ab4838..8316f88c6f 100644
--- a/src/vm/jitinterface.cpp
+++ b/src/vm/jitinterface.cpp
@@ -10063,6 +10063,81 @@ DWORD CEEInfo::getJitFlags(CORJIT_FLAGS* jitFlags, DWORD sizeInBytes)
}
/*********************************************************************/
+#if !defined(PLATFORM_UNIX)
+
+struct RunWithErrorTrapFilterParam
+{
+ ICorDynamicInfo* m_corInfo;
+ void (*m_function)(void*);
+ void* m_param;
+ EXCEPTION_POINTERS m_exceptionPointers;
+};
+
+static LONG RunWithErrorTrapFilter(struct _EXCEPTION_POINTERS* exceptionPointers, void* theParam)
+{
+ WRAPPER_NO_CONTRACT;
+
+ auto* param = reinterpret_cast<RunWithErrorTrapFilterParam*>(theParam);
+ param->m_exceptionPointers = *exceptionPointers;
+ return param->m_corInfo->FilterException(exceptionPointers);
+}
+
+#endif // !defined(PLATFORM_UNIX)
+
+bool CEEInfo::runWithErrorTrap(void (*function)(void*), void* param)
+{
+ // No dynamic contract here because SEH is used
+ STATIC_CONTRACT_THROWS;
+ STATIC_CONTRACT_GC_TRIGGERS;
+ STATIC_CONTRACT_SO_INTOLERANT;
+ STATIC_CONTRACT_MODE_PREEMPTIVE;
+
+ // NOTE: the lack of JIT/EE transition markers in this method is intentional. Any
+ // transitions into the EE proper should occur either via the call to
+ // `EEFilterException` (which is appropraitely marked) or via JIT/EE
+ // interface calls made by `function`.
+
+ bool success = true;
+
+#if !defined(PLATFORM_UNIX)
+
+ RunWithErrorTrapFilterParam trapParam;
+ trapParam.m_corInfo = m_pOverride == nullptr ? this : m_pOverride;
+ trapParam.m_function = function;
+ trapParam.m_param = param;
+
+ PAL_TRY(RunWithErrorTrapFilterParam*, pTrapParam, &trapParam)
+ {
+ pTrapParam->m_function(pTrapParam->m_param);
+ }
+ PAL_EXCEPT_FILTER(RunWithErrorTrapFilter)
+ {
+ HandleException(&trapParam.m_exceptionPointers);
+ success = false;
+ }
+ PAL_ENDTRY
+
+#else // !defined(PLATFORM_UNIX)
+
+ // We shouldn't need PAL_TRY on *nix: any exceptions that we are able to catch
+ // ought to originate from the runtime itself and should be catchable inside of
+ // EX_TRY/EX_CATCH, including emulated SEH exceptions.
+ EX_TRY
+ {
+ function(param);
+ }
+ EX_CATCH
+ {
+ success = false;
+ }
+ EX_END_CATCH(RethrowTerminalExceptions);
+
+#endif
+
+ return success;
+}
+
+/*********************************************************************/
IEEMemoryManager* CEEInfo::getMemoryManager()
{
CONTRACTL {
diff --git a/src/vm/jitinterface.h b/src/vm/jitinterface.h
index e31a07d17b..ace9608f0e 100644
--- a/src/vm/jitinterface.h
+++ b/src/vm/jitinterface.h
@@ -1097,6 +1097,8 @@ public:
DWORD getJitFlags(CORJIT_FLAGS* jitFlags, DWORD sizeInBytes);
+ bool runWithErrorTrap(void (*function)(void*), void* param);
+
private:
// Shrinking these buffers drastically reduces the amount of stack space
// required for each instance of the interpreter, and thereby reduces SOs.
diff --git a/src/zap/zapinfo.cpp b/src/zap/zapinfo.cpp
index d9c984c93b..2a2760f76a 100644
--- a/src/zap/zapinfo.cpp
+++ b/src/zap/zapinfo.cpp
@@ -867,6 +867,11 @@ IEEMemoryManager* ZapInfo::getMemoryManager()
{
return GetEEMemoryManager();
}
+
+bool ZapInfo::runWithErrorTrap(void (*function)(void*), void* param)
+{
+ return m_pEEJitInfo->runWithErrorTrap(function, param);
+}
HRESULT ZapInfo::allocBBProfileBuffer (
ULONG cBlock,
diff --git a/src/zap/zapinfo.h b/src/zap/zapinfo.h
index 7fc93820d2..b472d4870b 100644
--- a/src/zap/zapinfo.h
+++ b/src/zap/zapinfo.h
@@ -317,6 +317,8 @@ public:
DWORD getJitFlags(CORJIT_FLAGS* jitFlags, DWORD sizeInBytes);
+ bool runWithErrorTrap(void (*function)(void*), void* param);
+
// ICorDynamicInfo
DWORD getThreadTLSIndex(void **ppIndirection);