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
35 changes: 35 additions & 0 deletions src/coreclr/vm/exceptionhandling.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1530,6 +1530,41 @@ void FirstChanceExceptionNotification()
#endif // TARGET_WINDOWS
}

void NormalizeThrownObject(OBJECTREF *ppThrowable)
{
CONTRACTL
{
THROWS;
GC_TRIGGERS;
MODE_COOPERATIVE;
}
CONTRACTL_END;

Thread *pThread = GetThread();
if (!IsException((*ppThrowable)->GetMethodTable()))
{
GCPROTECT_BEGIN(*ppThrowable);

WrapNonCompliantException(ppThrowable);

GCPROTECT_END();
}
else
{ // We know that the object derives from System.Exception

// If the flag indicating ForeignExceptionRaise has been set,
// then do not clear the "_stackTrace" field of the exception object.
if (pThread->GetExceptionState()->IsRaisingForeignException())
{
((EXCEPTIONREF)(*ppThrowable))->SetStackTraceString(NULL);
}
else
{
((EXCEPTIONREF)(*ppThrowable))->ClearStackTracePreservingRemoteStackTrace();
}
}
}

VOID DECLSPEC_NORETURN DispatchManagedException(OBJECTREF throwable, CONTEXT* pExceptionContext, EXCEPTION_RECORD* pExceptionRecord)
{
STATIC_CONTRACT_THROWS;
Expand Down
2 changes: 2 additions & 0 deletions src/coreclr/vm/exceptionhandling.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ CallDescrWorkerUnwindFrameChainHandler(IN PEXCEPTION_RECORD pExceptionRe
IN OUT PT_CONTEXT pContextRecord,
IN OUT PT_DISPATCHER_CONTEXT pDispatcherContext);

void NormalizeThrownObject(OBJECTREF *ppThrowable);

VOID DECLSPEC_NORETURN DispatchManagedException(OBJECTREF throwable, CONTEXT *pExceptionContext, EXCEPTION_RECORD *pExceptionRecord = NULL);
VOID DECLSPEC_NORETURN DispatchManagedException(OBJECTREF throwable);
VOID DECLSPEC_NORETURN DispatchManagedException(RuntimeExceptionKind reKind);
Expand Down
59 changes: 44 additions & 15 deletions src/coreclr/vm/interpexec.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,14 @@ void InvokeUnmanagedCalli(PCODE ftn, void *cookie, int8_t *pArgs, int8_t *pRet);
void InvokeDelegateInvokeMethod(MethodDesc *pMDDelegateInvoke, int8_t *pArgs, int8_t *pRet, PCODE target);
extern "C" PCODE CID_VirtualOpenDelegateDispatch(TransitionBlock * pTransitionBlock);

// Filter to ignore SEH exceptions representing C++ exceptions.
LONG IgnoreCppExceptionFilter(PEXCEPTION_POINTERS pExceptionInfo, PVOID pv)
{
return (pExceptionInfo->ExceptionRecord->ExceptionCode == EXCEPTION_MSVC)
? EXCEPTION_CONTINUE_SEARCH
: EXCEPTION_EXECUTE_HANDLER;
}

// Use the NOINLINE to ensure that the InlinedCallFrame in this method is a lower stack address than any InterpMethodContextFrame values.
NOINLINE
void InvokeUnmanagedMethodWithTransition(MethodDesc *targetMethod, int8_t *stack, InterpMethodContextFrame *pFrame, int8_t *pArgs, int8_t *pRet, PCODE callTarget)
Expand All @@ -33,11 +41,35 @@ void InvokeUnmanagedMethodWithTransition(MethodDesc *targetMethod, int8_t *stack
inlinedCallFrame.m_Datum = NULL;
inlinedCallFrame.Push();

struct Param
{
GCX_PREEMP();
MethodDesc *targetMethod;
int8_t *pArgs;
int8_t *pRet;
PCODE callTarget;
}
param = { targetMethod, pArgs, pRet, callTarget };

PAL_TRY(Param *, pParam, &param)
{
GCX_PREEMP_NO_DTOR();
// WASM-TODO: Handle unmanaged calling conventions
InvokeManagedMethod(targetMethod, pArgs, pRet, callTarget);
InvokeManagedMethod(pParam->targetMethod, pParam->pArgs, pParam->pRet, pParam->callTarget);
GCX_PREEMP_NO_DTOR_END();
}
PAL_EXCEPT_FILTER(IgnoreCppExceptionFilter)
{
// There can be both C++ (thrown by the COMPlusThrow) and managed exceptions thrown
// from the native method (QCALL) call chain.
// We need to process only managed ones here, the C++ ones are handled by the
// INSTALL_/UNINSTALL_UNWIND_AND_CONTINUE_HANDLER in the InterpExecMethod.
// The managed ones are represented by SEH exception, which cannot be handled there
// because it is not possible to handle both SEH and C++ exceptions in the same frame.
GCX_COOP_NO_DTOR();
OBJECTREF ohThrowable = GetThread()->LastThrownObject();
DispatchManagedException(ohThrowable);
}
PAL_ENDTRY

inlinedCallFrame.Pop();
}
Expand Down Expand Up @@ -665,14 +697,6 @@ void* DoGenericLookup(void* genericVarAsPtr, InterpGenericLookup* pLookup)
return result;
}

// Filter to ignore SEH exceptions representing C++ exceptions.
LONG IgnoreCppExceptionFilter(PEXCEPTION_POINTERS pExceptionInfo, PVOID pv)
{
return (pExceptionInfo->ExceptionRecord->ExceptionCode == EXCEPTION_MSVC)
? EXCEPTION_CONTINUE_SEARCH
: EXCEPTION_EXECUTE_HANDLER;
}

// Wrapper around MethodDesc::DoPrestub to handle possible managed exceptions thrown by it.
static void CallPreStub(MethodDesc *pMD)
{
Expand Down Expand Up @@ -703,7 +727,7 @@ static void CallPreStub(MethodDesc *pMD)
// The managed ones are represented by SEH exception, which cannot be handled there
// because it is not possible to handle both SEH and C++ exceptions in the same frame.
GCX_COOP_NO_DTOR();
OBJECTREF ohThrowable = GET_THREAD()->LastThrownObject();
OBJECTREF ohThrowable = GetThread()->LastThrownObject();
DispatchManagedException(ohThrowable);
}
PAL_ENDTRY
Expand Down Expand Up @@ -2782,9 +2806,13 @@ void InterpExecMethod(InterpreterFrame *pInterpreterFrame, InterpMethodContextFr
goto CALL_INTERP_SLOT;
}
case INTOP_ZEROBLK_IMM:
memset(LOCAL_VAR(ip[1], void*), 0, ip[2]);
{
void* dst = LOCAL_VAR(ip[1], void*);
NULL_CHECK(dst);
memset(dst, 0, ip[2]);
ip += 3;
break;
}
case INTOP_CPBLK:
{
void* dst = LOCAL_VAR(ip[1], void*);
Expand Down Expand Up @@ -2833,16 +2861,17 @@ void InterpExecMethod(InterpreterFrame *pInterpreterFrame, InterpMethodContextFr
}
case INTOP_THROW:
{
OBJECTREF throwable;
if (LOCAL_VAR(ip[1], OBJECTREF) == NULL)
OBJECTREF throwable = LOCAL_VAR(ip[1], OBJECTREF);
if (!throwable)
{
EEException ex(kNullReferenceException);
throwable = ex.CreateThrowable();
}
else
{
throwable = LOCAL_VAR(ip[1], OBJECTREF);
NormalizeThrownObject(&throwable);
}

pInterpreterFrame->SetIsFaulting(true);
DispatchManagedException(throwable);
UNREACHABLE();
Expand Down
48 changes: 2 additions & 46 deletions src/coreclr/vm/jithelpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -797,30 +797,8 @@ HCIMPL1(void, IL_Throw, Object* obj)
#ifdef FEATURE_EH_FUNCLETS
if (oref == 0)
DispatchManagedException(kNullReferenceException);
else
if (!IsException(oref->GetMethodTable()))
{
GCPROTECT_BEGIN(oref);

WrapNonCompliantException(&oref);

GCPROTECT_END();
}
else
{ // We know that the object derives from System.Exception

// If the flag indicating ForeignExceptionRaise has been set,
// then do not clear the "_stackTrace" field of the exception object.
if (pThread->GetExceptionState()->IsRaisingForeignException())
{
((EXCEPTIONREF)oref)->SetStackTraceString(NULL);
}
else
{
((EXCEPTIONREF)oref)->ClearStackTracePreservingRemoteStackTrace();
}
}

NormalizeThrownObject(&oref);
DispatchManagedException(oref, exceptionFrame.GetContext());
#elif defined(TARGET_X86)
INSTALL_MANAGED_EXCEPTION_DISPATCHER;
Expand All @@ -832,30 +810,8 @@ HCIMPL1(void, IL_Throw, Object* obj)

if (oref == 0)
COMPlusThrow(kNullReferenceException);
else
if (!IsException(oref->GetMethodTable()))
{
GCPROTECT_BEGIN(oref);

WrapNonCompliantException(&oref);

GCPROTECT_END();
}
else
{ // We know that the object derives from System.Exception

// If the flag indicating ForeignExceptionRaise has been set,
// then do not clear the "_stackTrace" field of the exception object.
if (GetThread()->GetExceptionState()->IsRaisingForeignException())
{
((EXCEPTIONREF)oref)->SetStackTraceString(NULL);
}
else
{
((EXCEPTIONREF)oref)->ClearStackTracePreservingRemoteStackTrace();
}
}

NormalizeThrownObject(&oref);
RaiseTheExceptionInternalOnly(oref, FALSE);

UNINSTALL_UNWIND_AND_CONTINUE_HANDLER;
Expand Down
Loading