1212
1313// for numeric_limits
1414#include < limits>
15+ #include < functional>
1516
1617#ifdef TARGET_WASM
1718// Unused on WASM
@@ -37,6 +38,36 @@ LONG IgnoreCppExceptionFilter(PEXCEPTION_POINTERS pExceptionInfo, PVOID pv)
3738 : EXCEPTION_EXECUTE_HANDLER;
3839}
3940
41+ template <typename Function>
42+ std::invoke_result_t <Function> CallWithSEHWrapper (Function function)
43+ {
44+ struct Local
45+ {
46+ Function function;
47+ std::invoke_result_t <Function> result;
48+ } local { function };
49+
50+ PAL_TRY (Local *, pParam, &local)
51+ {
52+ pParam->result = pParam->function ();
53+ }
54+ PAL_EXCEPT_FILTER (IgnoreCppExceptionFilter)
55+ {
56+ // There can be both C++ (thrown by the COMPlusThrow) and managed exceptions thrown
57+ // from the called method's call chain.
58+ // We need to process only managed ones here, the C++ ones are handled by the
59+ // INSTALL_/UNINSTALL_UNWIND_AND_CONTINUE_HANDLER in the InterpExecMethod.
60+ // The managed ones are represented by SEH exception, which cannot be handled there
61+ // because it is not possible to handle both SEH and C++ exceptions in the same frame.
62+ GCX_COOP_NO_DTOR ();
63+ OBJECTREF ohThrowable = GetThread ()->LastThrownObject ();
64+ DispatchManagedException (ohThrowable);
65+ }
66+ PAL_ENDTRY
67+
68+ return local.result ;
69+ }
70+
4071// Use the NOINLINE to ensure that the InlinedCallFrame in this method is a lower stack address than any InterpMethodContextFrame values.
4172NOINLINE
4273void InvokeUnmanagedMethodWithTransition (MethodDesc *targetMethod, int8_t *stack, InterpMethodContextFrame *pFrame, int8_t *pArgs, int8_t *pRet, PCODE callTarget)
@@ -699,74 +730,6 @@ void* DoGenericLookup(void* genericVarAsPtr, InterpGenericLookup* pLookup)
699730 return result;
700731}
701732
702- // Wrapper around MethodDesc::DoPrestub to handle possible managed exceptions thrown by it.
703- static void CallPreStub (MethodDesc *pMD)
704- {
705- STATIC_STANDARD_VM_CONTRACT;
706- _ASSERTE (pMD != NULL );
707-
708- if (!pMD->ShouldCallPrestub ())
709- return ;
710-
711- struct Param
712- {
713- MethodDesc *pMethodDesc;
714- }
715- param = { pMD };
716-
717- PAL_TRY (Param *, pParam, ¶m)
718- {
719- (void )pParam->pMethodDesc ->DoPrestub (NULL /* MethodTable */ , CallerGCMode::Coop);
720- }
721- PAL_EXCEPT_FILTER (IgnoreCppExceptionFilter)
722- {
723- // There can be both C++ (thrown by the COMPlusThrow) and managed exceptions thrown
724- // from the PrepareInitialCode call chain.
725- // We need to process only managed ones here, the C++ ones are handled by the
726- // INSTALL_/UNINSTALL_UNWIND_AND_CONTINUE_HANDLER in the InterpExecMethod.
727- // The managed ones are represented by SEH exception, which cannot be handled there
728- // because it is not possible to handle both SEH and C++ exceptions in the same frame.
729- GCX_COOP_NO_DTOR ();
730- OBJECTREF ohThrowable = GetThread ()->LastThrownObject ();
731- DispatchManagedException (ohThrowable);
732- }
733- PAL_ENDTRY
734- }
735-
736- MethodDesc* CallGetMethodDescOfVirtualizedCode (MethodDesc *pMD, OBJECTREF *orThis)
737- {
738- STATIC_STANDARD_VM_CONTRACT;
739- _ASSERTE (pMD != NULL );
740-
741- struct Param
742- {
743- MethodDesc *pMD;
744- OBJECTREF *orThis;
745- MethodDesc *pRetMD;
746- }
747- param = { pMD, orThis, NULL };
748-
749- PAL_TRY (Param *, pParam, ¶m)
750- {
751- pParam->pRetMD = pParam->pMD ->GetMethodDescOfVirtualizedCode (pParam->orThis , pParam->pMD ->GetMethodTable ());
752- }
753- PAL_EXCEPT_FILTER (IgnoreCppExceptionFilter)
754- {
755- // There can be both C++ (thrown by the COMPlusThrow) and managed exceptions thrown
756- // from the GetMethodDescOfVirtualizedCode call chain.
757- // We need to process only managed ones here, the C++ ones are handled by the
758- // INSTALL_/UNINSTALL_UNWIND_AND_CONTINUE_HANDLER in the InterpExecMethod.
759- // The managed ones are represented by SEH exception, which cannot be handled there
760- // because it is not possible to handle both SEH and C++ exceptions in the same frame.
761- GCX_COOP_NO_DTOR ();
762- OBJECTREF ohThrowable = GetThread ()->LastThrownObject ();
763- DispatchManagedException (ohThrowable);
764- }
765- PAL_ENDTRY
766-
767- return param.pRetMD ;
768- }
769-
770733void InterpExecMethod (InterpreterFrame *pInterpreterFrame, InterpMethodContextFrame *pFrame, InterpThreadContext *pThreadContext, ExceptionClauseArgs *pExceptionClauseArgs)
771734{
772735 CONTRACTL
@@ -2460,7 +2423,11 @@ void InterpExecMethod(InterpreterFrame *pInterpreterFrame, InterpMethodContextFr
24602423 // Interpreter-TODO
24612424 // This needs to be optimized, not operating at MethodDesc level, rather with ftnptr
24622425 // slots containing the interpreter IR pointer
2463- targetMethod = CallGetMethodDescOfVirtualizedCode (pMD, pThisArg);
2426+ targetMethod = CallWithSEHWrapper (
2427+ [&pMD, &pThisArg]() {
2428+ return pMD->GetMethodDescOfVirtualizedCode (pThisArg, pMD->GetMethodTable ());
2429+ });
2430+
24642431 ip += 4 ;
24652432 goto CALL_INTERP_METHOD;
24662433 }
@@ -2601,7 +2568,11 @@ void InterpExecMethod(InterpreterFrame *pInterpreterFrame, InterpMethodContextFr
26012568 if (isOpenVirtual)
26022569 {
26032570 targetMethod = COMDelegate::GetMethodDescForOpenVirtualDelegate (*delegateObj);
2604- targetMethod = CallGetMethodDescOfVirtualizedCode (targetMethod, LOCAL_VAR_ADDR (callArgsOffset + INTERP_STACK_SLOT_SIZE, OBJECTREF));
2571+ targetMethod = CallWithSEHWrapper (
2572+ [&targetMethod, &callArgsOffset, &stack]() {
2573+ return targetMethod->GetMethodDescOfVirtualizedCode (LOCAL_VAR_ADDR (callArgsOffset + INTERP_STACK_SLOT_SIZE, OBJECTREF), targetMethod->GetMethodTable ());
2574+ });
2575+
26052576 }
26062577 else
26072578 {
@@ -2709,7 +2680,14 @@ void InterpExecMethod(InterpreterFrame *pInterpreterFrame, InterpMethodContextFr
27092680 // small subset of frames high.
27102681 pInterpreterFrame->SetTopInterpMethodContextFrame (pFrame);
27112682 GCX_PREEMP ();
2712- CallPreStub (targetMethod);
2683+
2684+ if (targetMethod->ShouldCallPrestub ())
2685+ {
2686+ CallWithSEHWrapper (
2687+ [&targetMethod]() {
2688+ return targetMethod->DoPrestub (nullptr , CallerGCMode::Coop);
2689+ });
2690+ }
27132691
27142692 targetIp = targetMethod->GetInterpreterCode ();
27152693 if (targetIp == NULL )
0 commit comments