1313
1414// Call invoker helpers provided by platform.
1515void InvokeManagedMethod (MethodDesc *pMD, int8_t *pArgs, int8_t *pRet, PCODE target);
16- void InvokeUnmanagedMethod (MethodDesc *targetMethod, int8_t *stack, InterpMethodContextFrame *pFrame, int32_t callArgsOffset, int32_t returnOffset, PCODE callTarget);
17- void InvokeCalliStub (PCODE ftn, void * stubHeaderTemplate, int8_t *pArgs, int8_t *pRet);
16+ void InvokeUnmanagedMethod (MethodDesc *targetMethod, int8_t *pArgs, int8_t *pRet, PCODE callTarget);
17+ void InvokeCalliStub (PCODE ftn, void * cookie, int8_t *pArgs, int8_t *pRet);
18+ void InvokeUnmanagedCalli (PCODE ftn, void *cookie, int8_t *pArgs, int8_t *pRet);
1819void InvokeDelegateInvokeMethod (MethodDesc *pMDDelegateInvoke, int8_t *pArgs, int8_t *pRet, PCODE target);
1920
2021// Use the NOINLINE to ensure that the InlinedCallFrame in this method is a lower stack address than any InterpMethodContextFrame values.
2122NOINLINE
22- void InvokeUnmanagedMethodWithTransition (MethodDesc *targetMethod, int8_t *stack, InterpMethodContextFrame *pFrame, int32_t callArgsOffset, int32_t returnOffset , PCODE callTarget)
23+ void InvokeUnmanagedMethodWithTransition (MethodDesc *targetMethod, int8_t *stack, InterpMethodContextFrame *pFrame, int8_t *pArgs, int8_t *pRet , PCODE callTarget)
2324{
2425 InlinedCallFrame inlinedCallFrame;
2526 inlinedCallFrame.m_pCallerReturnAddress = (TADDR)pFrame->ip ;
@@ -32,12 +33,38 @@ void InvokeUnmanagedMethodWithTransition(MethodDesc *targetMethod, int8_t *stack
3233 {
3334 GCX_PREEMP ();
3435 // WASM-TODO: Handle unmanaged calling conventions
35- InvokeManagedMethod (targetMethod, stack + callArgsOffset, stack + returnOffset , callTarget);
36+ InvokeManagedMethod (targetMethod, pArgs, pRet , callTarget);
3637 }
3738
3839 inlinedCallFrame.Pop ();
3940}
4041
42+ NOINLINE
43+ void InvokeUnmanagedCalliWithTransition (PCODE ftn, void *cookie, int8_t *stack, InterpMethodContextFrame *pFrame, int8_t *pArgs, int8_t *pRet)
44+ {
45+ CONTRACTL
46+ {
47+ THROWS;
48+ MODE_COOPERATIVE;
49+ PRECONDITION (CheckPointer ((void *)ftn));
50+ PRECONDITION (CheckPointer (cookie));
51+ }
52+ CONTRACTL_END
53+
54+ InlinedCallFrame inlinedCallFrame;
55+ inlinedCallFrame.m_pCallerReturnAddress = (TADDR)pFrame->ip ;
56+ inlinedCallFrame.m_pCallSiteSP = pFrame;
57+ inlinedCallFrame.m_pCalleeSavedFP = (TADDR)stack;
58+ inlinedCallFrame.m_pThread = GetThread ();
59+ inlinedCallFrame.m_Datum = NULL ;
60+ inlinedCallFrame.Push ();
61+ {
62+ GCX_PREEMP ();
63+ InvokeUnmanagedCalli (ftn, cookie, pArgs, pRet);
64+ }
65+ inlinedCallFrame.Pop ();
66+ }
67+
4168#ifndef TARGET_WASM
4269#include " callstubgenerator.h"
4370
@@ -96,9 +123,9 @@ void InvokeManagedMethod(MethodDesc *pMD, int8_t *pArgs, int8_t *pRet, PCODE tar
96123 pHeader->Invoke (pHeader->Routines , pArgs, pRet, pHeader->TotalStackSize );
97124}
98125
99- void InvokeUnmanagedMethod (MethodDesc *targetMethod, int8_t *stack, InterpMethodContextFrame *pFrame, int32_t callArgsOffset, int32_t returnOffset , PCODE callTarget)
126+ void InvokeUnmanagedMethod (MethodDesc *targetMethod, int8_t *pArgs, int8_t *pRet , PCODE callTarget)
100127{
101- InvokeManagedMethod (targetMethod, stack + callArgsOffset, stack + returnOffset , callTarget);
128+ InvokeManagedMethod (targetMethod, pArgs, pRet , callTarget);
102129}
103130
104131void InvokeDelegateInvokeMethod (MethodDesc *pMDDelegateInvoke, int8_t *pArgs, int8_t *pRet, PCODE target)
@@ -129,6 +156,29 @@ void InvokeDelegateInvokeMethod(MethodDesc *pMDDelegateInvoke, int8_t *pArgs, in
129156 pHeader->Invoke (pHeader->Routines , pArgs, pRet, pHeader->TotalStackSize );
130157}
131158
159+ void InvokeUnmanagedCalli (PCODE ftn, void *cookie, int8_t *pArgs, int8_t *pRet)
160+ {
161+ CONTRACTL
162+ {
163+ THROWS;
164+ MODE_ANY;
165+ PRECONDITION (CheckPointer ((void *)ftn));
166+ PRECONDITION (CheckPointer (cookie));
167+ }
168+ CONTRACTL_END
169+
170+ // CallStubHeaders encode their destination addresses in the Routines array, so they need to be
171+ // copied to a local buffer before we can actually set their target address.
172+ CallStubHeader* stubHeaderTemplate = (CallStubHeader*)cookie;
173+ size_t templateSize = stubHeaderTemplate->GetSize ();
174+ uint8_t * actualCallStub = (uint8_t *)alloca (templateSize);
175+ memcpy (actualCallStub, stubHeaderTemplate, templateSize);
176+ CallStubHeader *pHeader = (CallStubHeader*)actualCallStub;
177+ pHeader->SetTarget (ftn); // The method to call
178+
179+ pHeader->Invoke (pHeader->Routines , pArgs, pRet, pHeader->TotalStackSize );
180+ }
181+
132182void InvokeCalliStub (PCODE ftn, void *cookie, int8_t *pArgs, int8_t *pRet)
133183{
134184 CONTRACTL
@@ -2117,15 +2167,31 @@ void InterpExecMethod(InterpreterFrame *pInterpreterFrame, InterpMethodContextFr
21172167 callArgsOffset = ip[2 ];
21182168 int32_t calliFunctionPointerVar = ip[3 ];
21192169 int32_t calliCookie = ip[4 ];
2170+ int32_t flags = ip[5 ];
21202171
21212172 void * cookie = pMethod->pDataItems [calliCookie];
2122- ip += 5 ;
2173+ ip += 6 ;
21232174
21242175 // Save current execution state for when we return from called method
21252176 pFrame->ip = ip;
21262177
21272178 // Interpreter-FIXME: isTailcall
2128- InvokeCalliStub (LOCAL_VAR (calliFunctionPointerVar, PCODE), cookie, stack + callArgsOffset, stack + returnOffset);
2179+ if (flags & (int32_t )CalliFlags::PInvoke)
2180+ {
2181+ if (flags & (int32_t )CalliFlags::SuppressGCTransition)
2182+ {
2183+ InvokeUnmanagedCalli (LOCAL_VAR (calliFunctionPointerVar, PCODE), cookie, stack + callArgsOffset, stack + returnOffset);
2184+ }
2185+ else
2186+ {
2187+ InvokeUnmanagedCalliWithTransition (LOCAL_VAR (calliFunctionPointerVar, PCODE), cookie, stack, pFrame, stack + callArgsOffset, stack + returnOffset);
2188+ }
2189+ }
2190+ else
2191+ {
2192+ InvokeCalliStub (LOCAL_VAR (calliFunctionPointerVar, PCODE), cookie, stack + callArgsOffset, stack + returnOffset);
2193+ }
2194+
21292195 break ;
21302196 }
21312197
@@ -2152,11 +2218,11 @@ void InterpExecMethod(InterpreterFrame *pInterpreterFrame, InterpMethodContextFr
21522218
21532219 if (flags & (int32_t )PInvokeCallFlags::SuppressGCTransition)
21542220 {
2155- InvokeUnmanagedMethod (targetMethod, stack, pFrame, callArgsOffset, returnOffset, callTarget);
2221+ InvokeUnmanagedMethod (targetMethod, stack + callArgsOffset, stack + returnOffset, callTarget);
21562222 }
21572223 else
21582224 {
2159- InvokeUnmanagedMethodWithTransition (targetMethod, stack, pFrame, callArgsOffset, returnOffset, callTarget);
2225+ InvokeUnmanagedMethodWithTransition (targetMethod, stack, pFrame, stack + callArgsOffset, stack + returnOffset, callTarget);
21602226 }
21612227
21622228 break ;
0 commit comments