From 644cd598283424e3d85f0f22dc612c6ff14c7a33 Mon Sep 17 00:00:00 2001 From: Radek Doulik Date: Thu, 16 Apr 2026 17:43:45 +0200 Subject: [PATCH 01/22] [wasm][coreclr] Cache calli cookies Avoid repeated expensive calls to get calli cookie by caching it --- src/coreclr/vm/method.cpp | 24 ++++++++++++++++++++++++ src/coreclr/vm/method.hpp | 9 +++++++++ src/coreclr/vm/wasm/helpers.cpp | 12 ++++++++---- 3 files changed, 41 insertions(+), 4 deletions(-) diff --git a/src/coreclr/vm/method.cpp b/src/coreclr/vm/method.cpp index 6e4772c539db5c..13451ed985399f 100644 --- a/src/coreclr/vm/method.cpp +++ b/src/coreclr/vm/method.cpp @@ -277,6 +277,29 @@ void MethodDesc::SetMethodDescOptimizationTier(NativeCodeVersion::OptimizationTi #endif // FEATURE_CODE_VERSIONING #ifdef FEATURE_INTERPRETER +#ifdef FEATURE_PORTABLE_ENTRYPOINTS +// Cache the calli cookie on the MethodDesc +// Returns true if the current call set the cookie, false if it was already set. +bool MethodDesc::SetCalliCookie(void* cookie) +{ + STANDARD_VM_CONTRACT; + + IfFailThrow(EnsureCodeDataExists(NULL)); + + _ASSERTE(m_codeData != NULL); + return InterlockedCompareExchangeT(&m_codeData->CalliCookie, cookie, (void*)NULL) == NULL; +} + +void* MethodDesc::GetCalliCookie() +{ + LIMITED_METHOD_CONTRACT; + + PTR_MethodDescCodeData codeData = VolatileLoadWithoutBarrier(&m_codeData); + if (codeData == NULL) + return NULL; + return VolatileLoadWithoutBarrier(&codeData->CalliCookie); +} +#else // Set the call stub for the interpreter to JIT/AOT calls // Returns true if the current call set the stub, false if it was already set bool MethodDesc::SetCallStub(CallStubHeader *pHeader) @@ -298,6 +321,7 @@ CallStubHeader *MethodDesc::GetCallStub() return NULL; return VolatileLoadWithoutBarrier(&codeData->CallStub); } +#endif // FEATURE_PORTABLE_ENTRYPOINTS #endif // FEATURE_INTERPRETER #endif //!DACCESS_COMPILE diff --git a/src/coreclr/vm/method.hpp b/src/coreclr/vm/method.hpp index 9188d081cd5ee4..46572b506c9d8b 100644 --- a/src/coreclr/vm/method.hpp +++ b/src/coreclr/vm/method.hpp @@ -260,7 +260,11 @@ struct MethodDescCodeData final #endif // FEATURE_CODE_VERSIONING PCODE TemporaryEntryPoint; #ifdef FEATURE_INTERPRETER +#ifdef FEATURE_PORTABLE_ENTRYPOINTS + void* CalliCookie; +#else CallStubHeader *CallStub; +#endif // FEATURE_PORTABLE_ENTRYPOINTS #endif // FEATURE_INTERPRETER }; using PTR_MethodDescCodeData = DPTR(MethodDescCodeData); @@ -1981,8 +1985,13 @@ class MethodDesc #endif //!DACCESS_COMPILE #if defined(FEATURE_INTERPRETER) && !defined(DACCESS_COMPILE) +#ifdef FEATURE_PORTABLE_ENTRYPOINTS + bool SetCalliCookie(void* cookie); + void* GetCalliCookie(); +#else bool SetCallStub(CallStubHeader *pHeader); CallStubHeader *GetCallStub(); +#endif // FEATURE_PORTABLE_ENTRYPOINTS #endif // FEATURE_INTERPRETER && !DACCESS_COMPILE #ifdef FEATURE_CODE_VERSIONING diff --git a/src/coreclr/vm/wasm/helpers.cpp b/src/coreclr/vm/wasm/helpers.cpp index afb6d2f739a8b8..8e423f5ba9ca3d 100644 --- a/src/coreclr/vm/wasm/helpers.cpp +++ b/src/coreclr/vm/wasm/helpers.cpp @@ -765,10 +765,14 @@ void* GetUnmanagedCallersOnlyThunk(MethodDesc* pMD) void InvokeManagedMethod(ManagedMethodParam *pParam) { - MetaSig sig(pParam->pMD); - void* cookie = GetCookieForCalliSig(sig, pParam->pMD); - - _ASSERTE(cookie != NULL); + void* cookie = pParam->pMD->GetCalliCookie(); + if (cookie == NULL) + { + MetaSig sig(pParam->pMD); + cookie = GetCookieForCalliSig(sig, pParam->pMD); + _ASSERTE(cookie != NULL); + pParam->pMD->SetCalliCookie(cookie); + } CalliStubParam param = { pParam->target == NULL ? pParam->pMD->GetMultiCallableAddrOfCode(CORINFO_ACCESS_ANY) : pParam->target, cookie, pParam->pArgs, pParam->pRet, pParam->pContinuationRet }; InvokeCalliStub(¶m); From 561484a9665f117591f3935c81e1151390710b82 Mon Sep 17 00:00:00 2001 From: Radek Doulik Date: Tue, 21 Apr 2026 16:26:44 +0200 Subject: [PATCH 02/22] Address PR feedback: unify CalliCookie/CallStub with InterpreterCalliCookie typedef - Define InterpreterCalliCookie typedef: function pointer on WASM, CallStubHeader* on non-WASM (Jan's feedback) - Unify SetCalliCookie/GetCalliCookie API, removing the separate SetCallStub/GetCallStub and FEATURE_PORTABLE_ENTRYPOINTS branching in MethodDesc - Cache calli cookie on targetMethod in the WASM calli path in interpexec.cpp (Jan's feedback) - Re-read cookie after SetCalliCookie in wasm/helpers.cpp to use the race-winning value (Aaron's feedback) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- src/coreclr/vm/interpexec.cpp | 19 +++++++++++------ src/coreclr/vm/method.cpp | 36 ++++++--------------------------- src/coreclr/vm/method.hpp | 21 +++++++++---------- src/coreclr/vm/wasm/helpers.cpp | 7 ++++--- 4 files changed, 33 insertions(+), 50 deletions(-) diff --git a/src/coreclr/vm/interpexec.cpp b/src/coreclr/vm/interpexec.cpp index b9ca224add2365..342f0e1f901ee2 100644 --- a/src/coreclr/vm/interpexec.cpp +++ b/src/coreclr/vm/interpexec.cpp @@ -349,7 +349,7 @@ static CallStubHeader *UpdateCallStubForMethod(MethodDesc *pMD, PCODE target) header->SetTarget(target); } - if (pMD->SetCallStub(header)) + if (pMD->SetCalliCookie(header)) { amTracker.SuppressRelease(); } @@ -357,7 +357,7 @@ static CallStubHeader *UpdateCallStubForMethod(MethodDesc *pMD, PCODE target) { // We have lost the race for generating the header, use the one that was generated by another thread // and let the amTracker release the memory of the one we generated. - header = pMD->GetCallStub(); + header = pMD->GetCalliCookie(); } return header; @@ -408,7 +408,7 @@ void InvokeManagedMethod(ManagedMethodParam* pParam) PCODE target = pParam->target; Object** pContinuationRet = pParam->pContinuationRet; - CallStubHeader *pHeader = pParam->pMD->GetCallStub(); + CallStubHeader *pHeader = pParam->pMD->GetCalliCookie(); if (pHeader == NULL) { pHeader = UpdateCallStubForMethod(pMD, target == (PCODE)NULL ? pMD->GetMultiCallableAddrOfCode(CORINFO_ACCESS_ANY) : target); @@ -467,7 +467,7 @@ void InvokeDelegateInvokeMethod(DelegateInvokeMethodParam* pParam) PCODE target = pParam->target; Object** pContinuationRet = pParam->pContinuationRet; - CallStubHeader *stubHeaderTemplate = pMDDelegateInvoke->GetCallStub(); + CallStubHeader *stubHeaderTemplate = pMDDelegateInvoke->GetCalliCookie(); if (stubHeaderTemplate == NULL) { stubHeaderTemplate = UpdateCallStubForMethod(pMDDelegateInvoke, (PCODE)pMDDelegateInvoke->GetMultiCallableAddrOfCode(CORINFO_ACCESS_ANY)); @@ -3073,8 +3073,15 @@ void InterpExecMethod(InterpreterFrame *pInterpreterFrame, InterpMethodContextFr if (!PortableEntryPoint::HasNativeEntryPoint(calliFunctionPointer)) goto CALL_INTERP_METHOD; - MetaSig sig(targetMethod); - cookie = GetCookieForCalliSig(sig, NULL); + cookie = (void*)targetMethod->GetCalliCookie(); + if (cookie == NULL) + { + MetaSig sig(targetMethod); + cookie = GetCookieForCalliSig(sig, NULL); + _ASSERTE(cookie != NULL); + targetMethod->SetCalliCookie((InterpreterCalliCookie)cookie); + cookie = (void*)targetMethod->GetCalliCookie(); + } #endif // FEATURE_PORTABLE_ENTRYPOINTS frameNeedsTailcallUpdate = false; CalliStubParam param = { calliFunctionPointer, cookie, callArgsAddress, returnValueAddress, pInterpreterFrame->GetContinuationPtr() }; diff --git a/src/coreclr/vm/method.cpp b/src/coreclr/vm/method.cpp index 13451ed985399f..3d24ff904b00e5 100644 --- a/src/coreclr/vm/method.cpp +++ b/src/coreclr/vm/method.cpp @@ -277,51 +277,27 @@ void MethodDesc::SetMethodDescOptimizationTier(NativeCodeVersion::OptimizationTi #endif // FEATURE_CODE_VERSIONING #ifdef FEATURE_INTERPRETER -#ifdef FEATURE_PORTABLE_ENTRYPOINTS // Cache the calli cookie on the MethodDesc -// Returns true if the current call set the cookie, false if it was already set. -bool MethodDesc::SetCalliCookie(void* cookie) +// Returns true if the current call set the cookie, false if it was already set +bool MethodDesc::SetCalliCookie(InterpreterCalliCookie cookie) { STANDARD_VM_CONTRACT; IfFailThrow(EnsureCodeDataExists(NULL)); _ASSERTE(m_codeData != NULL); - return InterlockedCompareExchangeT(&m_codeData->CalliCookie, cookie, (void*)NULL) == NULL; + return InterlockedCompareExchangeT(&m_codeData->CalliCookie, (void*)cookie, (void*)NULL) == NULL; } -void* MethodDesc::GetCalliCookie() +InterpreterCalliCookie MethodDesc::GetCalliCookie() { LIMITED_METHOD_CONTRACT; PTR_MethodDescCodeData codeData = VolatileLoadWithoutBarrier(&m_codeData); if (codeData == NULL) - return NULL; - return VolatileLoadWithoutBarrier(&codeData->CalliCookie); -} -#else -// Set the call stub for the interpreter to JIT/AOT calls -// Returns true if the current call set the stub, false if it was already set -bool MethodDesc::SetCallStub(CallStubHeader *pHeader) -{ - STANDARD_VM_CONTRACT; - - IfFailThrow(EnsureCodeDataExists(NULL)); - - _ASSERTE(m_codeData != NULL); - return InterlockedCompareExchangeT(&m_codeData->CallStub, pHeader, NULL) == NULL; + return (InterpreterCalliCookie)NULL; + return (InterpreterCalliCookie)VolatileLoadWithoutBarrier(&codeData->CalliCookie); } - -CallStubHeader *MethodDesc::GetCallStub() -{ - LIMITED_METHOD_CONTRACT; - - PTR_MethodDescCodeData codeData = VolatileLoadWithoutBarrier(&m_codeData); - if (codeData == NULL) - return NULL; - return VolatileLoadWithoutBarrier(&codeData->CallStub); -} -#endif // FEATURE_PORTABLE_ENTRYPOINTS #endif // FEATURE_INTERPRETER #endif //!DACCESS_COMPILE diff --git a/src/coreclr/vm/method.hpp b/src/coreclr/vm/method.hpp index 46572b506c9d8b..fc121ba7c14c2c 100644 --- a/src/coreclr/vm/method.hpp +++ b/src/coreclr/vm/method.hpp @@ -252,6 +252,14 @@ enum MethodDescFlags }; // Used for storing additional items related to native code +#ifdef FEATURE_INTERPRETER +#ifdef FEATURE_PORTABLE_ENTRYPOINTS +typedef void(*InterpreterCalliCookie)(PCODE, int8_t*, int8_t*); +#else +typedef CallStubHeader* InterpreterCalliCookie; +#endif // FEATURE_PORTABLE_ENTRYPOINTS +#endif // FEATURE_INTERPRETER + struct MethodDescCodeData final { #ifdef FEATURE_CODE_VERSIONING @@ -260,11 +268,7 @@ struct MethodDescCodeData final #endif // FEATURE_CODE_VERSIONING PCODE TemporaryEntryPoint; #ifdef FEATURE_INTERPRETER -#ifdef FEATURE_PORTABLE_ENTRYPOINTS void* CalliCookie; -#else - CallStubHeader *CallStub; -#endif // FEATURE_PORTABLE_ENTRYPOINTS #endif // FEATURE_INTERPRETER }; using PTR_MethodDescCodeData = DPTR(MethodDescCodeData); @@ -1985,13 +1989,8 @@ class MethodDesc #endif //!DACCESS_COMPILE #if defined(FEATURE_INTERPRETER) && !defined(DACCESS_COMPILE) -#ifdef FEATURE_PORTABLE_ENTRYPOINTS - bool SetCalliCookie(void* cookie); - void* GetCalliCookie(); -#else - bool SetCallStub(CallStubHeader *pHeader); - CallStubHeader *GetCallStub(); -#endif // FEATURE_PORTABLE_ENTRYPOINTS + bool SetCalliCookie(InterpreterCalliCookie cookie); + InterpreterCalliCookie GetCalliCookie(); #endif // FEATURE_INTERPRETER && !DACCESS_COMPILE #ifdef FEATURE_CODE_VERSIONING diff --git a/src/coreclr/vm/wasm/helpers.cpp b/src/coreclr/vm/wasm/helpers.cpp index 8e423f5ba9ca3d..7479a2a84317fb 100644 --- a/src/coreclr/vm/wasm/helpers.cpp +++ b/src/coreclr/vm/wasm/helpers.cpp @@ -765,16 +765,17 @@ void* GetUnmanagedCallersOnlyThunk(MethodDesc* pMD) void InvokeManagedMethod(ManagedMethodParam *pParam) { - void* cookie = pParam->pMD->GetCalliCookie(); + InterpreterCalliCookie cookie = pParam->pMD->GetCalliCookie(); if (cookie == NULL) { MetaSig sig(pParam->pMD); - cookie = GetCookieForCalliSig(sig, pParam->pMD); + cookie = (InterpreterCalliCookie)GetCookieForCalliSig(sig, pParam->pMD); _ASSERTE(cookie != NULL); pParam->pMD->SetCalliCookie(cookie); + cookie = pParam->pMD->GetCalliCookie(); } - CalliStubParam param = { pParam->target == NULL ? pParam->pMD->GetMultiCallableAddrOfCode(CORINFO_ACCESS_ANY) : pParam->target, cookie, pParam->pArgs, pParam->pRet, pParam->pContinuationRet }; + CalliStubParam param = { pParam->target == NULL ? pParam->pMD->GetMultiCallableAddrOfCode(CORINFO_ACCESS_ANY) : pParam->target, (void*)cookie, pParam->pArgs, pParam->pRet, pParam->pContinuationRet }; InvokeCalliStub(¶m); } From d7a3255709f53bfc92ccd2651e84ea3b3d9177b1 Mon Sep 17 00:00:00 2001 From: Radek Doulik Date: Sun, 26 Apr 2026 22:19:14 +0200 Subject: [PATCH 03/22] Cache the cookie in CInterpreterJitInfo::GetCookieForInterpreterCalliSig --- src/coreclr/vm/jitinterface.cpp | 37 +++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 13 deletions(-) diff --git a/src/coreclr/vm/jitinterface.cpp b/src/coreclr/vm/jitinterface.cpp index 9dd542b94c03c5..cb87c60a048361 100644 --- a/src/coreclr/vm/jitinterface.cpp +++ b/src/coreclr/vm/jitinterface.cpp @@ -11451,18 +11451,6 @@ LPVOID CInterpreterJitInfo::GetCookieForInterpreterCalliSig(CORINFO_SIG_INFO* sz void* result = NULL; JIT_TO_EE_TRANSITION(); - Instantiation classInst = Instantiation((TypeHandle*) szMetaSig->sigInst.classInst, szMetaSig->sigInst.classInstCount); - Instantiation methodInst = Instantiation((TypeHandle*) szMetaSig->sigInst.methInst, szMetaSig->sigInst.methInstCount); - SigTypeContext typeContext = SigTypeContext(classInst, methodInst); - Module* mod = GetModule(szMetaSig->scope); - - MetaSig sig(szMetaSig->pSig, szMetaSig->cbSig, mod, &typeContext); - - if (szMetaSig->isAsyncCall()) - sig.SetIsAsyncCall(); - - _ASSERTE(szMetaSig->isAsyncCall() == sig.IsAsyncCall()); - // When compiling a calli inside an IL stub for a P/Invoke, pass the target // P/Invoke MethodDesc so ComputeCallStub can detect the Swift calling convention. MethodDesc* pContextMD = nullptr; @@ -11472,9 +11460,32 @@ LPVOID CInterpreterJitInfo::GetCookieForInterpreterCalliSig(CORINFO_SIG_INFO* sz if (pTargetMD != nullptr) { pContextMD = pTargetMD; + result = (void*)pTargetMD->GetCalliCookie(); + } + } + + if (result == NULL) + { + Instantiation classInst = Instantiation((TypeHandle*) szMetaSig->sigInst.classInst, szMetaSig->sigInst.classInstCount); + Instantiation methodInst = Instantiation((TypeHandle*) szMetaSig->sigInst.methInst, szMetaSig->sigInst.methInstCount); + SigTypeContext typeContext = SigTypeContext(classInst, methodInst); + Module* mod = GetModule(szMetaSig->scope); + + MetaSig sig(szMetaSig->pSig, szMetaSig->cbSig, mod, &typeContext); + + if (szMetaSig->isAsyncCall()) + sig.SetIsAsyncCall(); + + _ASSERTE(szMetaSig->isAsyncCall() == sig.IsAsyncCall()); + + result = GetCookieForCalliSig(sig, pContextMD); + + if (pContextMD != nullptr) + { + pContextMD->SetCalliCookie((InterpreterCalliCookie)result); + result = (void*)pContextMD->GetCalliCookie(); } } - result = GetCookieForCalliSig(sig, pContextMD); EE_TO_JIT_TRANSITION(); return result; From 09c76763b940cae0b0553f3f3cfdbcdef13b8d6f Mon Sep 17 00:00:00 2001 From: Radek Doulik Date: Mon, 27 Apr 2026 12:58:56 +0200 Subject: [PATCH 04/22] Feedback --- src/coreclr/vm/interpexec.cpp | 16 ++++++++-------- src/coreclr/vm/interpexec.h | 2 +- src/coreclr/vm/wasm/helpers.cpp | 4 ++-- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/coreclr/vm/interpexec.cpp b/src/coreclr/vm/interpexec.cpp index 342f0e1f901ee2..77a0ec0e242402 100644 --- a/src/coreclr/vm/interpexec.cpp +++ b/src/coreclr/vm/interpexec.cpp @@ -206,9 +206,9 @@ static size_t CreateDispatchTokenForMethod(MethodDesc* pMD) void InvokeManagedMethod(ManagedMethodParam *pParam); void InvokeUnmanagedMethod(MethodDesc *targetMethod, int8_t *pArgs, int8_t *pRet, PCODE callTarget); void InvokeCalliStub(CalliStubParam* pParam); -void InvokeUnmanagedCalli(PCODE ftn, void *cookie, int8_t *pArgs, int8_t *pRet); +void InvokeUnmanagedCalli(PCODE ftn, InterpreterCalliCookie cookie, int8_t *pArgs, int8_t *pRet); void InvokeDelegateInvokeMethod(DelegateInvokeMethodParam* pParam); -void* GetCookieForCalliSig(MetaSig metaSig, MethodDesc *pContextMD); +InterpreterCalliCookie GetCookieForCalliSig(MetaSig metaSig, MethodDesc *pContextMD); extern "C" PCODE CID_VirtualOpenDelegateDispatch(TransitionBlock * pTransitionBlock); // Filter to ignore SEH exceptions representing C++ exceptions. @@ -287,7 +287,7 @@ void InvokeUnmanagedMethodWithTransition(UnmanagedMethodWithTransitionParam *pPa } NOINLINE -void InvokeUnmanagedCalliWithTransition(PCODE ftn, void *cookie, int8_t *stack, InterpMethodContextFrame *pFrame, int8_t *pArgs, int8_t *pRet) +void InvokeUnmanagedCalliWithTransition(PCODE ftn, InterpreterCalliCookie cookie, int8_t *stack, InterpMethodContextFrame *pFrame, int8_t *pArgs, int8_t *pRet) { CONTRACTL { @@ -490,7 +490,7 @@ void InvokeDelegateInvokeMethod(DelegateInvokeMethodParam* pParam) pHeader->Invoke(pHeader->Routines, pArgs, pRet, pHeader->TotalStackSize, pContinuationRet); } -void InvokeUnmanagedCalli(PCODE ftn, void *cookie, int8_t *pArgs, int8_t *pRet) +void InvokeUnmanagedCalli(PCODE ftn, InterpreterCalliCookie cookie, int8_t *pArgs, int8_t *pRet) { CONTRACTL { @@ -549,7 +549,7 @@ void InvokeCalliStub(CalliStubParam* pParam) pHeader->Invoke(pHeader->Routines, pArgs, pRet, pHeader->TotalStackSize, pContinuationRet); } -void* GetCookieForCalliSig(MetaSig metaSig, MethodDesc *pContextMD) +InterpreterCalliCookie GetCookieForCalliSig(MetaSig metaSig, MethodDesc *pContextMD) { STANDARD_VM_CONTRACT; @@ -3029,7 +3029,7 @@ void InterpExecMethod(InterpreterFrame *pInterpreterFrame, InterpMethodContextFr int32_t calliCookie = ip[4]; int32_t flags = ip[5]; - void* cookie = pMethod->pDataItems[calliCookie]; + InterpreterCalliCookie cookie = (InterpreterCalliCookie)pMethod->pDataItems[calliCookie]; ip += 6; // Save current execution state for when we return from called method @@ -3073,14 +3073,14 @@ void InterpExecMethod(InterpreterFrame *pInterpreterFrame, InterpMethodContextFr if (!PortableEntryPoint::HasNativeEntryPoint(calliFunctionPointer)) goto CALL_INTERP_METHOD; - cookie = (void*)targetMethod->GetCalliCookie(); + cookie = targetMethod->GetCalliCookie(); if (cookie == NULL) { MetaSig sig(targetMethod); cookie = GetCookieForCalliSig(sig, NULL); _ASSERTE(cookie != NULL); targetMethod->SetCalliCookie((InterpreterCalliCookie)cookie); - cookie = (void*)targetMethod->GetCalliCookie(); + cookie = targetMethod->GetCalliCookie(); } #endif // FEATURE_PORTABLE_ENTRYPOINTS frameNeedsTailcallUpdate = false; diff --git a/src/coreclr/vm/interpexec.h b/src/coreclr/vm/interpexec.h index 48c4c2c1a6f8ff..c1c775e1d75eba 100644 --- a/src/coreclr/vm/interpexec.h +++ b/src/coreclr/vm/interpexec.h @@ -133,7 +133,7 @@ struct ManagedMethodParam struct CalliStubParam { PCODE ftn; - void* cookie; + InterpreterCalliCookie cookie; int8_t *pArgs; int8_t *pRet; Object** pContinuationRet; diff --git a/src/coreclr/vm/wasm/helpers.cpp b/src/coreclr/vm/wasm/helpers.cpp index 7479a2a84317fb..9cfa87111f9f73 100644 --- a/src/coreclr/vm/wasm/helpers.cpp +++ b/src/coreclr/vm/wasm/helpers.cpp @@ -427,7 +427,7 @@ void InvokeCalliStub(CalliStubParam* pParam) ((void(*)(PCODE, int8_t*, int8_t*))pParam->cookie)(actualFtn, pParam->pArgs, pParam->pRet); } -void InvokeUnmanagedCalli(PCODE ftn, void *cookie, int8_t *pArgs, int8_t *pRet) +void InvokeUnmanagedCalli(PCODE ftn, InterpreterCalliCookie cookie, int8_t *pArgs, int8_t *pRet) { _ASSERTE(ftn != (PCODE)NULL); _ASSERTE(cookie != NULL); @@ -775,7 +775,7 @@ void InvokeManagedMethod(ManagedMethodParam *pParam) cookie = pParam->pMD->GetCalliCookie(); } - CalliStubParam param = { pParam->target == NULL ? pParam->pMD->GetMultiCallableAddrOfCode(CORINFO_ACCESS_ANY) : pParam->target, (void*)cookie, pParam->pArgs, pParam->pRet, pParam->pContinuationRet }; + CalliStubParam param = { pParam->target == NULL ? pParam->pMD->GetMultiCallableAddrOfCode(CORINFO_ACCESS_ANY) : pParam->target, cookie, pParam->pArgs, pParam->pRet, pParam->pContinuationRet }; InvokeCalliStub(¶m); } From bbf1b3fa227f6ac15017a74794f024047ae3bd5b Mon Sep 17 00:00:00 2001 From: Radek Doulik Date: Mon, 27 Apr 2026 15:08:19 +0200 Subject: [PATCH 05/22] Fix build --- src/coreclr/vm/interpexec.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/coreclr/vm/interpexec.h b/src/coreclr/vm/interpexec.h index c1c775e1d75eba..c41307f14e4e11 100644 --- a/src/coreclr/vm/interpexec.h +++ b/src/coreclr/vm/interpexec.h @@ -6,6 +6,7 @@ #include #include "interpframeallocator.h" +#include "method.hpp" #define INTERP_STACK_SIZE 1024*1024 #define INTERP_STACK_FRAGMENT_SIZE 4096 From dd1464f15bfa4ac94bcbcc465ff43100aa57a48d Mon Sep 17 00:00:00 2001 From: Radek Doulik Date: Mon, 27 Apr 2026 16:29:25 +0200 Subject: [PATCH 06/22] Fix build --- src/coreclr/vm/interpexec.cpp | 2 +- src/coreclr/vm/interpexec.h | 3 +-- src/coreclr/vm/method.hpp | 4 ++-- src/coreclr/vm/wasm/helpers.cpp | 2 +- 4 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/coreclr/vm/interpexec.cpp b/src/coreclr/vm/interpexec.cpp index 77a0ec0e242402..1aad7b5dab7770 100644 --- a/src/coreclr/vm/interpexec.cpp +++ b/src/coreclr/vm/interpexec.cpp @@ -3084,7 +3084,7 @@ void InterpExecMethod(InterpreterFrame *pInterpreterFrame, InterpMethodContextFr } #endif // FEATURE_PORTABLE_ENTRYPOINTS frameNeedsTailcallUpdate = false; - CalliStubParam param = { calliFunctionPointer, cookie, callArgsAddress, returnValueAddress, pInterpreterFrame->GetContinuationPtr() }; + CalliStubParam param = { calliFunctionPointer, (void*)cookie, callArgsAddress, returnValueAddress, pInterpreterFrame->GetContinuationPtr() }; InvokeCalliStub(¶m); } diff --git a/src/coreclr/vm/interpexec.h b/src/coreclr/vm/interpexec.h index c41307f14e4e11..48c4c2c1a6f8ff 100644 --- a/src/coreclr/vm/interpexec.h +++ b/src/coreclr/vm/interpexec.h @@ -6,7 +6,6 @@ #include #include "interpframeallocator.h" -#include "method.hpp" #define INTERP_STACK_SIZE 1024*1024 #define INTERP_STACK_FRAGMENT_SIZE 4096 @@ -134,7 +133,7 @@ struct ManagedMethodParam struct CalliStubParam { PCODE ftn; - InterpreterCalliCookie cookie; + void* cookie; int8_t *pArgs; int8_t *pRet; Object** pContinuationRet; diff --git a/src/coreclr/vm/method.hpp b/src/coreclr/vm/method.hpp index fc121ba7c14c2c..0e47b0915b6e0e 100644 --- a/src/coreclr/vm/method.hpp +++ b/src/coreclr/vm/method.hpp @@ -253,11 +253,11 @@ enum MethodDescFlags // Used for storing additional items related to native code #ifdef FEATURE_INTERPRETER -#ifdef FEATURE_PORTABLE_ENTRYPOINTS +#ifdef TARGET_WASM typedef void(*InterpreterCalliCookie)(PCODE, int8_t*, int8_t*); #else typedef CallStubHeader* InterpreterCalliCookie; -#endif // FEATURE_PORTABLE_ENTRYPOINTS +#endif // TARGET_WASM #endif // FEATURE_INTERPRETER struct MethodDescCodeData final diff --git a/src/coreclr/vm/wasm/helpers.cpp b/src/coreclr/vm/wasm/helpers.cpp index 9cfa87111f9f73..fc2e814c4f6e41 100644 --- a/src/coreclr/vm/wasm/helpers.cpp +++ b/src/coreclr/vm/wasm/helpers.cpp @@ -775,7 +775,7 @@ void InvokeManagedMethod(ManagedMethodParam *pParam) cookie = pParam->pMD->GetCalliCookie(); } - CalliStubParam param = { pParam->target == NULL ? pParam->pMD->GetMultiCallableAddrOfCode(CORINFO_ACCESS_ANY) : pParam->target, cookie, pParam->pArgs, pParam->pRet, pParam->pContinuationRet }; + CalliStubParam param = { pParam->target == NULL ? pParam->pMD->GetMultiCallableAddrOfCode(CORINFO_ACCESS_ANY) : pParam->target, (void*)cookie, pParam->pArgs, pParam->pRet, pParam->pContinuationRet }; InvokeCalliStub(¶m); } From 9824727ae92fb17de025edfa5c83c7bf4adee256 Mon Sep 17 00:00:00 2001 From: Radek Doulik Date: Mon, 27 Apr 2026 20:56:51 +0200 Subject: [PATCH 07/22] Feedback + fix build --- src/coreclr/vm/interpexec.cpp | 2 +- src/coreclr/vm/interpexec.h | 4 +++- src/coreclr/vm/jitinterface.cpp | 10 +++++----- src/coreclr/vm/method.hpp | 4 ++-- src/coreclr/vm/wasm/helpers.cpp | 18 +++++++++--------- 5 files changed, 20 insertions(+), 18 deletions(-) diff --git a/src/coreclr/vm/interpexec.cpp b/src/coreclr/vm/interpexec.cpp index 1aad7b5dab7770..77a0ec0e242402 100644 --- a/src/coreclr/vm/interpexec.cpp +++ b/src/coreclr/vm/interpexec.cpp @@ -3084,7 +3084,7 @@ void InterpExecMethod(InterpreterFrame *pInterpreterFrame, InterpMethodContextFr } #endif // FEATURE_PORTABLE_ENTRYPOINTS frameNeedsTailcallUpdate = false; - CalliStubParam param = { calliFunctionPointer, (void*)cookie, callArgsAddress, returnValueAddress, pInterpreterFrame->GetContinuationPtr() }; + CalliStubParam param = { calliFunctionPointer, cookie, callArgsAddress, returnValueAddress, pInterpreterFrame->GetContinuationPtr() }; InvokeCalliStub(¶m); } diff --git a/src/coreclr/vm/interpexec.h b/src/coreclr/vm/interpexec.h index 48c4c2c1a6f8ff..8444703c9f49e4 100644 --- a/src/coreclr/vm/interpexec.h +++ b/src/coreclr/vm/interpexec.h @@ -130,14 +130,16 @@ struct ManagedMethodParam Object** pContinuationRet; }; +#ifdef FEATURE_INTERPRETER struct CalliStubParam { PCODE ftn; - void* cookie; + InterpreterCalliCookie cookie; int8_t *pArgs; int8_t *pRet; Object** pContinuationRet; }; +#endif // FEATURE_INTERPRETER struct DelegateInvokeMethodParam { diff --git a/src/coreclr/vm/jitinterface.cpp b/src/coreclr/vm/jitinterface.cpp index cb87c60a048361..4069f0abef9f88 100644 --- a/src/coreclr/vm/jitinterface.cpp +++ b/src/coreclr/vm/jitinterface.cpp @@ -11444,11 +11444,11 @@ LPVOID CEEInfo::GetCookieForInterpreterCalliSig(CORINFO_SIG_INFO* szMetaSig) #ifdef FEATURE_INTERPRETER // Forward declare the function for mapping MetaSig to a cookie. -void* GetCookieForCalliSig(MetaSig metaSig, MethodDesc *pContextMD); +InterpreterCalliCookie GetCookieForCalliSig(MetaSig metaSig, MethodDesc *pContextMD); LPVOID CInterpreterJitInfo::GetCookieForInterpreterCalliSig(CORINFO_SIG_INFO* szMetaSig) { - void* result = NULL; + InterpreterCalliCookie result = NULL; JIT_TO_EE_TRANSITION(); // When compiling a calli inside an IL stub for a P/Invoke, pass the target @@ -11460,7 +11460,7 @@ LPVOID CInterpreterJitInfo::GetCookieForInterpreterCalliSig(CORINFO_SIG_INFO* sz if (pTargetMD != nullptr) { pContextMD = pTargetMD; - result = (void*)pTargetMD->GetCalliCookie(); + result = pTargetMD->GetCalliCookie(); } } @@ -11483,12 +11483,12 @@ LPVOID CInterpreterJitInfo::GetCookieForInterpreterCalliSig(CORINFO_SIG_INFO* sz if (pContextMD != nullptr) { pContextMD->SetCalliCookie((InterpreterCalliCookie)result); - result = (void*)pContextMD->GetCalliCookie(); + result = pContextMD->GetCalliCookie(); } } EE_TO_JIT_TRANSITION(); - return result; + return (void*)result; } void CInterpreterJitInfo::allocMem(AllocMemArgs *pArgs) diff --git a/src/coreclr/vm/method.hpp b/src/coreclr/vm/method.hpp index 0e47b0915b6e0e..fc121ba7c14c2c 100644 --- a/src/coreclr/vm/method.hpp +++ b/src/coreclr/vm/method.hpp @@ -253,11 +253,11 @@ enum MethodDescFlags // Used for storing additional items related to native code #ifdef FEATURE_INTERPRETER -#ifdef TARGET_WASM +#ifdef FEATURE_PORTABLE_ENTRYPOINTS typedef void(*InterpreterCalliCookie)(PCODE, int8_t*, int8_t*); #else typedef CallStubHeader* InterpreterCalliCookie; -#endif // TARGET_WASM +#endif // FEATURE_PORTABLE_ENTRYPOINTS #endif // FEATURE_INTERPRETER struct MethodDescCodeData final diff --git a/src/coreclr/vm/wasm/helpers.cpp b/src/coreclr/vm/wasm/helpers.cpp index fc2e814c4f6e41..5490bd04c10e1f 100644 --- a/src/coreclr/vm/wasm/helpers.cpp +++ b/src/coreclr/vm/wasm/helpers.cpp @@ -573,7 +573,7 @@ namespace typedef MapSHash> StringToWasmSigThunkHash; static StringToWasmSigThunkHash* thunkCache = nullptr; - void* LookupThunk(const char* key) + InterpreterCalliCookie LookupThunk(const char* key) { StringToWasmSigThunkHash* table = VolatileLoad(&thunkCache); if (table == nullptr) @@ -593,13 +593,13 @@ namespace table = thunkCache; } - void* thunk; - bool success = table->Lookup(key, &thunk); + InterpreterCalliCookie thunk; + bool success = table->Lookup(key, (void**)&thunk); return success ? thunk : nullptr; } // This is a simple signature computation routine for signatures currently supported in the wasm environment. - void* ComputeCalliSigThunk(MetaSig& sig) + InterpreterCalliCookie ComputeCalliSigThunk(MetaSig& sig) { STANDARD_VM_CONTRACT; _ASSERTE(sizeof(int32_t) == sizeof(void*)); @@ -623,7 +623,7 @@ namespace if (!GetSignatureKey(sig, keyBuffer, keyBufferLen)) return NULL; - void* thunk = LookupThunk(keyBuffer); + InterpreterCalliCookie thunk = LookupThunk(keyBuffer); #ifdef _DEBUG if (thunk == NULL) printf("WASM calli missing for key: %s\n", keyBuffer); @@ -727,11 +727,11 @@ namespace } } -void* GetCookieForCalliSig(MetaSig metaSig, MethodDesc *pContextMD) +InterpreterCalliCookie GetCookieForCalliSig(MetaSig metaSig, MethodDesc *pContextMD) { STANDARD_VM_CONTRACT; - void* thunk = ComputeCalliSigThunk(metaSig); + InterpreterCalliCookie thunk = ComputeCalliSigThunk(metaSig); if (thunk == NULL) { PORTABILITY_ASSERT("GetCookieForCalliSig: unknown thunk signature"); @@ -769,13 +769,13 @@ void InvokeManagedMethod(ManagedMethodParam *pParam) if (cookie == NULL) { MetaSig sig(pParam->pMD); - cookie = (InterpreterCalliCookie)GetCookieForCalliSig(sig, pParam->pMD); + cookie = GetCookieForCalliSig(sig, pParam->pMD); _ASSERTE(cookie != NULL); pParam->pMD->SetCalliCookie(cookie); cookie = pParam->pMD->GetCalliCookie(); } - CalliStubParam param = { pParam->target == NULL ? pParam->pMD->GetMultiCallableAddrOfCode(CORINFO_ACCESS_ANY) : pParam->target, (void*)cookie, pParam->pArgs, pParam->pRet, pParam->pContinuationRet }; + CalliStubParam param = { pParam->target == NULL ? pParam->pMD->GetMultiCallableAddrOfCode(CORINFO_ACCESS_ANY) : pParam->target, cookie, pParam->pArgs, pParam->pRet, pParam->pContinuationRet }; InvokeCalliStub(¶m); } From 9a901796164616b7581ce092706de06c2f6f5e40 Mon Sep 17 00:00:00 2001 From: Jan Kotas Date: Mon, 27 Apr 2026 20:46:46 -0700 Subject: [PATCH 08/22] Apply suggestion from @jkotas --- src/coreclr/vm/wasm/helpers.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/coreclr/vm/wasm/helpers.cpp b/src/coreclr/vm/wasm/helpers.cpp index 27384144c70615..48553e47a35be5 100644 --- a/src/coreclr/vm/wasm/helpers.cpp +++ b/src/coreclr/vm/wasm/helpers.cpp @@ -907,7 +907,8 @@ namespace StringToWasmSigThunkHash* table = thunkCache; _ASSERTE(table != nullptr && "Wasm thunk cache not initialized. Call InitializeWasmThunkCaches() at EEStartup."); InterpreterCalliCookie thunk; - bool success = table->Lookup(key, (void**)&thunk); + void* thunk; + bool success = table->Lookup(key, &thunk); return success ? thunk : nullptr; } From 180e2b63e3fbc3620b5412c21a97f2d7a886a7a7 Mon Sep 17 00:00:00 2001 From: Jan Kotas Date: Mon, 27 Apr 2026 20:47:29 -0700 Subject: [PATCH 09/22] Apply suggestion from @jkotas --- src/coreclr/vm/wasm/helpers.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coreclr/vm/wasm/helpers.cpp b/src/coreclr/vm/wasm/helpers.cpp index 48553e47a35be5..73292d0884bba6 100644 --- a/src/coreclr/vm/wasm/helpers.cpp +++ b/src/coreclr/vm/wasm/helpers.cpp @@ -909,7 +909,7 @@ namespace InterpreterCalliCookie thunk; void* thunk; bool success = table->Lookup(key, &thunk); - return success ? thunk : nullptr; + return success ? (InterpreterCalliCookie)thunk : nullptr; } void* LookupPortableEntryPointThunk(const char* key) From 7868154f66106dc19585b0d0871847de8ca2e312 Mon Sep 17 00:00:00 2001 From: Jan Kotas Date: Mon, 27 Apr 2026 20:50:15 -0700 Subject: [PATCH 10/22] Apply suggestion from @jkotas --- src/coreclr/vm/interpexec.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coreclr/vm/interpexec.cpp b/src/coreclr/vm/interpexec.cpp index ad23e01ed5120f..28c4cb190a41ec 100644 --- a/src/coreclr/vm/interpexec.cpp +++ b/src/coreclr/vm/interpexec.cpp @@ -3173,7 +3173,7 @@ void InterpExecMethod(InterpreterFrame *pInterpreterFrame, InterpMethodContextFr MetaSig sig(targetMethod); cookie = GetCookieForCalliSig(sig, NULL); _ASSERTE(cookie != NULL); - targetMethod->SetCalliCookie((InterpreterCalliCookie)cookie); + targetMethod->SetCalliCookie(cookie); cookie = targetMethod->GetCalliCookie(); } #endif // FEATURE_PORTABLE_ENTRYPOINTS From ab5a8c23587b21ae73b230a07d21d61347d4d98e Mon Sep 17 00:00:00 2001 From: Jan Kotas Date: Mon, 27 Apr 2026 20:50:26 -0700 Subject: [PATCH 11/22] Apply suggestion from @jkotas --- src/coreclr/vm/jitinterface.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coreclr/vm/jitinterface.cpp b/src/coreclr/vm/jitinterface.cpp index a398b3e1b86c67..64c4f087d9536b 100644 --- a/src/coreclr/vm/jitinterface.cpp +++ b/src/coreclr/vm/jitinterface.cpp @@ -11528,7 +11528,7 @@ LPVOID CInterpreterJitInfo::GetCookieForInterpreterCalliSig(CORINFO_SIG_INFO* sz if (pContextMD != nullptr) { - pContextMD->SetCalliCookie((InterpreterCalliCookie)result); + pContextMD->SetCalliCookie(result); result = pContextMD->GetCalliCookie(); } } From 7cc76af553f30737ce4471df9ce5372682414131 Mon Sep 17 00:00:00 2001 From: Jan Kotas Date: Mon, 27 Apr 2026 20:51:34 -0700 Subject: [PATCH 12/22] Apply suggestion from @jkotas --- src/coreclr/vm/method.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coreclr/vm/method.cpp b/src/coreclr/vm/method.cpp index ae1ab7d1e5fec2..316c8e2e5069c7 100644 --- a/src/coreclr/vm/method.cpp +++ b/src/coreclr/vm/method.cpp @@ -318,7 +318,7 @@ InterpreterCalliCookie MethodDesc::GetCalliCookie() PTR_MethodDescCodeData codeData = VolatileLoadWithoutBarrier(&m_codeData); if (codeData == NULL) - return (InterpreterCalliCookie)NULL; + return NULL; return (InterpreterCalliCookie)VolatileLoadWithoutBarrier(&codeData->CalliCookie); } #endif // FEATURE_INTERPRETER From 6df4983d3c70a1c94f5e9320009f03ee2bd904c1 Mon Sep 17 00:00:00 2001 From: Jan Kotas Date: Mon, 27 Apr 2026 21:03:53 -0700 Subject: [PATCH 13/22] Apply suggestion from @Copilot Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/coreclr/vm/wasm/helpers.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/coreclr/vm/wasm/helpers.cpp b/src/coreclr/vm/wasm/helpers.cpp index 73292d0884bba6..eede7bb20859e3 100644 --- a/src/coreclr/vm/wasm/helpers.cpp +++ b/src/coreclr/vm/wasm/helpers.cpp @@ -906,7 +906,6 @@ namespace { StringToWasmSigThunkHash* table = thunkCache; _ASSERTE(table != nullptr && "Wasm thunk cache not initialized. Call InitializeWasmThunkCaches() at EEStartup."); - InterpreterCalliCookie thunk; void* thunk; bool success = table->Lookup(key, &thunk); return success ? (InterpreterCalliCookie)thunk : nullptr; From c688974ed607f88d128b3a58dca6e43cf963b59f Mon Sep 17 00:00:00 2001 From: Radek Doulik Date: Wed, 29 Apr 2026 11:31:21 +0200 Subject: [PATCH 14/22] Feedback --- src/coreclr/vm/method.cpp | 2 +- src/coreclr/vm/method.hpp | 2 +- .../vm/wasm/callhelpers-interp-to-managed.cpp | 130 +++++++++++------- src/coreclr/vm/wasm/helpers.cpp | 7 +- .../coreclr/InterpToNativeGenerator.cs | 6 +- 5 files changed, 87 insertions(+), 60 deletions(-) diff --git a/src/coreclr/vm/method.cpp b/src/coreclr/vm/method.cpp index 316c8e2e5069c7..be6faab57943a1 100644 --- a/src/coreclr/vm/method.cpp +++ b/src/coreclr/vm/method.cpp @@ -309,7 +309,7 @@ bool MethodDesc::SetCalliCookie(InterpreterCalliCookie cookie) IfFailThrow(EnsureCodeDataExists(NULL)); _ASSERTE(m_codeData != NULL); - return InterlockedCompareExchangeT(&m_codeData->CalliCookie, (void*)cookie, (void*)NULL) == NULL; + return InterlockedCompareExchangeT((void**)&m_codeData->CalliCookie, (void*)cookie, (void*)NULL) == NULL; } InterpreterCalliCookie MethodDesc::GetCalliCookie() diff --git a/src/coreclr/vm/method.hpp b/src/coreclr/vm/method.hpp index 4bdad5689f437c..a66e10b4548c95 100644 --- a/src/coreclr/vm/method.hpp +++ b/src/coreclr/vm/method.hpp @@ -265,7 +265,7 @@ struct MethodDescCodeData final #endif // FEATURE_CODE_VERSIONING PCODE TemporaryEntryPoint; #ifdef FEATURE_INTERPRETER - void* CalliCookie; + InterpreterCalliCookie CalliCookie; #endif // FEATURE_INTERPRETER #if defined(_DEBUG) && defined(ALLOW_SXS_JIT) PatchpointInfo *AltJitPatchpointInfo; diff --git a/src/coreclr/vm/wasm/callhelpers-interp-to-managed.cpp b/src/coreclr/vm/wasm/callhelpers-interp-to-managed.cpp index c0265475c3447d..2e0086843ade1a 100644 --- a/src/coreclr/vm/wasm/callhelpers-interp-to-managed.cpp +++ b/src/coreclr/vm/wasm/callhelpers-interp-to-managed.cpp @@ -20,32 +20,36 @@ namespace { - NOINLINE static void CallFunc_F64_F64_F64_RetF64_PE(PCODE pcode, int8_t* pArgs, int8_t* pRet, PCODE pPortableEntryPointContext) + NOINLINE static void CallFunc_F64_F64_F64_RetF64_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet) { + PCODE pcode = (PCODE)PortableEntryPoint::GetActualCode(pPortableEntryPoint); alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK; double (*fptr)(int*, double, double, double, PCODE) = (double (*)(int*, double, double, double, PCODE))pcode; - *((double*)pRet) = (*fptr)(&framePointer, ARG_F64(0), ARG_F64(1), ARG_F64(2), pPortableEntryPointContext); + *((double*)pRet) = (*fptr)(&framePointer, ARG_F64(0), ARG_F64(1), ARG_F64(2), pPortableEntryPoint); } - NOINLINE static void CallFunc_F64_F64_RetF64_PE(PCODE pcode, int8_t* pArgs, int8_t* pRet, PCODE pPortableEntryPointContext) + NOINLINE static void CallFunc_F64_F64_RetF64_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet) { + PCODE pcode = (PCODE)PortableEntryPoint::GetActualCode(pPortableEntryPoint); alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK; double (*fptr)(int*, double, double, PCODE) = (double (*)(int*, double, double, PCODE))pcode; - *((double*)pRet) = (*fptr)(&framePointer, ARG_F64(0), ARG_F64(1), pPortableEntryPointContext); + *((double*)pRet) = (*fptr)(&framePointer, ARG_F64(0), ARG_F64(1), pPortableEntryPoint); } - NOINLINE static void CallFunc_F64_I32_RetF64_PE(PCODE pcode, int8_t* pArgs, int8_t* pRet, PCODE pPortableEntryPointContext) + NOINLINE static void CallFunc_F64_I32_RetF64_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet) { + PCODE pcode = (PCODE)PortableEntryPoint::GetActualCode(pPortableEntryPoint); alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK; double (*fptr)(int*, double, int32_t, PCODE) = (double (*)(int*, double, int32_t, PCODE))pcode; - *((double*)pRet) = (*fptr)(&framePointer, ARG_F64(0), ARG_I32(1), pPortableEntryPointContext); + *((double*)pRet) = (*fptr)(&framePointer, ARG_F64(0), ARG_I32(1), pPortableEntryPoint); } - NOINLINE static void CallFunc_F64_RetF64_PE(PCODE pcode, int8_t* pArgs, int8_t* pRet, PCODE pPortableEntryPointContext) + NOINLINE static void CallFunc_F64_RetF64_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet) { + PCODE pcode = (PCODE)PortableEntryPoint::GetActualCode(pPortableEntryPoint); alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK; double (*fptr)(int*, double, PCODE) = (double (*)(int*, double, PCODE))pcode; - *((double*)pRet) = (*fptr)(&framePointer, ARG_F64(0), pPortableEntryPointContext); + *((double*)pRet) = (*fptr)(&framePointer, ARG_F64(0), pPortableEntryPoint); } static void CallFunc_I32_RetF64(PCODE pcode, int8_t* pArgs, int8_t* pRet) @@ -54,32 +58,36 @@ namespace *((double*)pRet) = (*fptr)(ARG_I32(0)); } - NOINLINE static void CallFunc_F32_F32_F32_RetF32_PE(PCODE pcode, int8_t* pArgs, int8_t* pRet, PCODE pPortableEntryPointContext) + NOINLINE static void CallFunc_F32_F32_F32_RetF32_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet) { + PCODE pcode = (PCODE)PortableEntryPoint::GetActualCode(pPortableEntryPoint); alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK; float (*fptr)(int*, float, float, float, PCODE) = (float (*)(int*, float, float, float, PCODE))pcode; - *((float*)pRet) = (*fptr)(&framePointer, ARG_F32(0), ARG_F32(1), ARG_F32(2), pPortableEntryPointContext); + *((float*)pRet) = (*fptr)(&framePointer, ARG_F32(0), ARG_F32(1), ARG_F32(2), pPortableEntryPoint); } - NOINLINE static void CallFunc_F32_F32_RetF32_PE(PCODE pcode, int8_t* pArgs, int8_t* pRet, PCODE pPortableEntryPointContext) + NOINLINE static void CallFunc_F32_F32_RetF32_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet) { + PCODE pcode = (PCODE)PortableEntryPoint::GetActualCode(pPortableEntryPoint); alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK; float (*fptr)(int*, float, float, PCODE) = (float (*)(int*, float, float, PCODE))pcode; - *((float*)pRet) = (*fptr)(&framePointer, ARG_F32(0), ARG_F32(1), pPortableEntryPointContext); + *((float*)pRet) = (*fptr)(&framePointer, ARG_F32(0), ARG_F32(1), pPortableEntryPoint); } - NOINLINE static void CallFunc_F32_I32_RetF32_PE(PCODE pcode, int8_t* pArgs, int8_t* pRet, PCODE pPortableEntryPointContext) + NOINLINE static void CallFunc_F32_I32_RetF32_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet) { + PCODE pcode = (PCODE)PortableEntryPoint::GetActualCode(pPortableEntryPoint); alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK; float (*fptr)(int*, float, int32_t, PCODE) = (float (*)(int*, float, int32_t, PCODE))pcode; - *((float*)pRet) = (*fptr)(&framePointer, ARG_F32(0), ARG_I32(1), pPortableEntryPointContext); + *((float*)pRet) = (*fptr)(&framePointer, ARG_F32(0), ARG_I32(1), pPortableEntryPoint); } - NOINLINE static void CallFunc_F32_RetF32_PE(PCODE pcode, int8_t* pArgs, int8_t* pRet, PCODE pPortableEntryPointContext) + NOINLINE static void CallFunc_F32_RetF32_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet) { + PCODE pcode = (PCODE)PortableEntryPoint::GetActualCode(pPortableEntryPoint); alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK; float (*fptr)(int*, float, PCODE) = (float (*)(int*, float, PCODE))pcode; - *((float*)pRet) = (*fptr)(&framePointer, ARG_F32(0), pPortableEntryPointContext); + *((float*)pRet) = (*fptr)(&framePointer, ARG_F32(0), pPortableEntryPoint); } static void CallFunc_Void_RetI32(PCODE pcode, int8_t* pArgs, int8_t* pRet) @@ -136,25 +144,28 @@ namespace *((int32_t*)pRet) = (*fptr)(ARG_I32(0), ARG_I32(1), ARG_I32(2), ARG_I32(3), ARG_I32(4), ARG_I32(5), ARG_I32(6), ARG_I32(7), ARG_I32(8), ARG_I32(9), ARG_I32(10), ARG_I32(11), ARG_I32(12), ARG_I32(13)); } - NOINLINE static void CallFunc_I32_I32_I32_I32_I32_I32_RetI32_PE(PCODE pcode, int8_t* pArgs, int8_t* pRet, PCODE pPortableEntryPointContext) + NOINLINE static void CallFunc_I32_I32_I32_I32_I32_I32_RetI32_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet) { + PCODE pcode = (PCODE)PortableEntryPoint::GetActualCode(pPortableEntryPoint); alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK; int32_t (*fptr)(int*, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, PCODE) = (int32_t (*)(int*, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, PCODE))pcode; - *((int32_t*)pRet) = (*fptr)(&framePointer, ARG_I32(0), ARG_I32(1), ARG_I32(2), ARG_I32(3), ARG_I32(4), ARG_I32(5), pPortableEntryPointContext); + *((int32_t*)pRet) = (*fptr)(&framePointer, ARG_I32(0), ARG_I32(1), ARG_I32(2), ARG_I32(3), ARG_I32(4), ARG_I32(5), pPortableEntryPoint); } - NOINLINE static void CallFunc_I32_I32_I32_I32_I32_RetI32_PE(PCODE pcode, int8_t* pArgs, int8_t* pRet, PCODE pPortableEntryPointContext) + NOINLINE static void CallFunc_I32_I32_I32_I32_I32_RetI32_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet) { + PCODE pcode = (PCODE)PortableEntryPoint::GetActualCode(pPortableEntryPoint); alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK; int32_t (*fptr)(int*, int32_t, int32_t, int32_t, int32_t, int32_t, PCODE) = (int32_t (*)(int*, int32_t, int32_t, int32_t, int32_t, int32_t, PCODE))pcode; - *((int32_t*)pRet) = (*fptr)(&framePointer, ARG_I32(0), ARG_I32(1), ARG_I32(2), ARG_I32(3), ARG_I32(4), pPortableEntryPointContext); + *((int32_t*)pRet) = (*fptr)(&framePointer, ARG_I32(0), ARG_I32(1), ARG_I32(2), ARG_I32(3), ARG_I32(4), pPortableEntryPoint); } - NOINLINE static void CallFunc_I32_I32_I32_I32_RetI32_PE(PCODE pcode, int8_t* pArgs, int8_t* pRet, PCODE pPortableEntryPointContext) + NOINLINE static void CallFunc_I32_I32_I32_I32_RetI32_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet) { + PCODE pcode = (PCODE)PortableEntryPoint::GetActualCode(pPortableEntryPoint); alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK; int32_t (*fptr)(int*, int32_t, int32_t, int32_t, int32_t, PCODE) = (int32_t (*)(int*, int32_t, int32_t, int32_t, int32_t, PCODE))pcode; - *((int32_t*)pRet) = (*fptr)(&framePointer, ARG_I32(0), ARG_I32(1), ARG_I32(2), ARG_I32(3), pPortableEntryPointContext); + *((int32_t*)pRet) = (*fptr)(&framePointer, ARG_I32(0), ARG_I32(1), ARG_I32(2), ARG_I32(3), pPortableEntryPoint); } static void CallFunc_I32_I32_I32_I64_RetI32(PCODE pcode, int8_t* pArgs, int8_t* pRet) @@ -169,11 +180,12 @@ namespace *((int32_t*)pRet) = (*fptr)(ARG_I32(0), ARG_I32(1), ARG_I32(2), ARG_IND(3), ARG_I32(4)); } - NOINLINE static void CallFunc_I32_I32_I32_RetI32_PE(PCODE pcode, int8_t* pArgs, int8_t* pRet, PCODE pPortableEntryPointContext) + NOINLINE static void CallFunc_I32_I32_I32_RetI32_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet) { + PCODE pcode = (PCODE)PortableEntryPoint::GetActualCode(pPortableEntryPoint); alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK; int32_t (*fptr)(int*, int32_t, int32_t, int32_t, PCODE) = (int32_t (*)(int*, int32_t, int32_t, int32_t, PCODE))pcode; - *((int32_t*)pRet) = (*fptr)(&framePointer, ARG_I32(0), ARG_I32(1), ARG_I32(2), pPortableEntryPointContext); + *((int32_t*)pRet) = (*fptr)(&framePointer, ARG_I32(0), ARG_I32(1), ARG_I32(2), pPortableEntryPoint); } static void CallFunc_I32_I32_I64_RetI32(PCODE pcode, int8_t* pArgs, int8_t* pRet) @@ -194,11 +206,12 @@ namespace *((int32_t*)pRet) = (*fptr)(ARG_I32(0), ARG_I32(1), ARG_IND(2), ARG_I32(3), ARG_I32(4), ARG_IND(5)); } - NOINLINE static void CallFunc_I32_I32_RetI32_PE(PCODE pcode, int8_t* pArgs, int8_t* pRet, PCODE pPortableEntryPointContext) + NOINLINE static void CallFunc_I32_I32_RetI32_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet) { + PCODE pcode = (PCODE)PortableEntryPoint::GetActualCode(pPortableEntryPoint); alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK; int32_t (*fptr)(int*, int32_t, int32_t, PCODE) = (int32_t (*)(int*, int32_t, int32_t, PCODE))pcode; - *((int32_t*)pRet) = (*fptr)(&framePointer, ARG_I32(0), ARG_I32(1), pPortableEntryPointContext); + *((int32_t*)pRet) = (*fptr)(&framePointer, ARG_I32(0), ARG_I32(1), pPortableEntryPoint); } static void CallFunc_I32_I64_RetI32(PCODE pcode, int8_t* pArgs, int8_t* pRet) @@ -243,11 +256,12 @@ namespace *((int32_t*)pRet) = (*fptr)(ARG_I32(0), ARG_IND(1), ARG_I32(2), ARG_I32(3), ARG_I32(4)); } - NOINLINE static void CallFunc_I32_RetI32_PE(PCODE pcode, int8_t* pArgs, int8_t* pRet, PCODE pPortableEntryPointContext) + NOINLINE static void CallFunc_I32_RetI32_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet) { + PCODE pcode = (PCODE)PortableEntryPoint::GetActualCode(pPortableEntryPoint); alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK; int32_t (*fptr)(int*, int32_t, PCODE) = (int32_t (*)(int*, int32_t, PCODE))pcode; - *((int32_t*)pRet) = (*fptr)(&framePointer, ARG_I32(0), pPortableEntryPointContext); + *((int32_t*)pRet) = (*fptr)(&framePointer, ARG_I32(0), pPortableEntryPoint); } static void CallFunc_I64_I32_I64_I32_RetI32(PCODE pcode, int8_t* pArgs, int8_t* pRet) @@ -328,11 +342,12 @@ namespace *((int32_t*)pRet) = (*fptr)(ARG_IND(0), ARG_IND(1), ARG_IND(2)); } - NOINLINE static void CallFunc_Void_RetI32_PE(PCODE pcode, int8_t* pArgs, int8_t* pRet, PCODE pPortableEntryPointContext) + NOINLINE static void CallFunc_Void_RetI32_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet) { + PCODE pcode = (PCODE)PortableEntryPoint::GetActualCode(pPortableEntryPoint); alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK; int32_t (*fptr)(int*, PCODE) = (int32_t (*)(int*, PCODE))pcode; - *((int32_t*)pRet) = (*fptr)(&framePointer, pPortableEntryPointContext); + *((int32_t*)pRet) = (*fptr)(&framePointer, pPortableEntryPoint); } static void CallFunc_Void_RetI64(PCODE pcode, int8_t* pArgs, int8_t* pRet) @@ -365,39 +380,44 @@ namespace *((int64_t*)pRet) = (*fptr)(ARG_I32(0), ARG_I64(1), ARG_I32(2)); } - NOINLINE static void CallFunc_I32_I64_I64_RetI64_PE(PCODE pcode, int8_t* pArgs, int8_t* pRet, PCODE pPortableEntryPointContext) + NOINLINE static void CallFunc_I32_I64_I64_RetI64_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet) { + PCODE pcode = (PCODE)PortableEntryPoint::GetActualCode(pPortableEntryPoint); alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK; int64_t (*fptr)(int*, int32_t, int64_t, int64_t, PCODE) = (int64_t (*)(int*, int32_t, int64_t, int64_t, PCODE))pcode; - *((int64_t*)pRet) = (*fptr)(&framePointer, ARG_I32(0), ARG_I64(1), ARG_I64(2), pPortableEntryPointContext); + *((int64_t*)pRet) = (*fptr)(&framePointer, ARG_I32(0), ARG_I64(1), ARG_I64(2), pPortableEntryPoint); } - NOINLINE static void CallFunc_I32_I64_RetI64_PE(PCODE pcode, int8_t* pArgs, int8_t* pRet, PCODE pPortableEntryPointContext) + NOINLINE static void CallFunc_I32_I64_RetI64_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet) { + PCODE pcode = (PCODE)PortableEntryPoint::GetActualCode(pPortableEntryPoint); alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK; int64_t (*fptr)(int*, int32_t, int64_t, PCODE) = (int64_t (*)(int*, int32_t, int64_t, PCODE))pcode; - *((int64_t*)pRet) = (*fptr)(&framePointer, ARG_I32(0), ARG_I64(1), pPortableEntryPointContext); + *((int64_t*)pRet) = (*fptr)(&framePointer, ARG_I32(0), ARG_I64(1), pPortableEntryPoint); } - NOINLINE static void CallFunc_I32_RetI64_PE(PCODE pcode, int8_t* pArgs, int8_t* pRet, PCODE pPortableEntryPointContext) + NOINLINE static void CallFunc_I32_RetI64_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet) { + PCODE pcode = (PCODE)PortableEntryPoint::GetActualCode(pPortableEntryPoint); alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK; int64_t (*fptr)(int*, int32_t, PCODE) = (int64_t (*)(int*, int32_t, PCODE))pcode; - *((int64_t*)pRet) = (*fptr)(&framePointer, ARG_I32(0), pPortableEntryPointContext); + *((int64_t*)pRet) = (*fptr)(&framePointer, ARG_I32(0), pPortableEntryPoint); } - NOINLINE static void CallFunc_I64_I64_RetI64_PE(PCODE pcode, int8_t* pArgs, int8_t* pRet, PCODE pPortableEntryPointContext) + NOINLINE static void CallFunc_I64_I64_RetI64_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet) { + PCODE pcode = (PCODE)PortableEntryPoint::GetActualCode(pPortableEntryPoint); alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK; int64_t (*fptr)(int*, int64_t, int64_t, PCODE) = (int64_t (*)(int*, int64_t, int64_t, PCODE))pcode; - *((int64_t*)pRet) = (*fptr)(&framePointer, ARG_I64(0), ARG_I64(1), pPortableEntryPointContext); + *((int64_t*)pRet) = (*fptr)(&framePointer, ARG_I64(0), ARG_I64(1), pPortableEntryPoint); } - NOINLINE static void CallFunc_Void_RetI64_PE(PCODE pcode, int8_t* pArgs, int8_t* pRet, PCODE pPortableEntryPointContext) + NOINLINE static void CallFunc_Void_RetI64_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet) { + PCODE pcode = (PCODE)PortableEntryPoint::GetActualCode(pPortableEntryPoint); alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK; int64_t (*fptr)(int*, PCODE) = (int64_t (*)(int*, PCODE))pcode; - *((int64_t*)pRet) = (*fptr)(&framePointer, pPortableEntryPointContext); + *((int64_t*)pRet) = (*fptr)(&framePointer, pPortableEntryPoint); } static void CallFunc_Void_RetVoid(PCODE pcode, int8_t* pArgs, int8_t* pRet) @@ -406,18 +426,20 @@ namespace (*fptr)(); } - NOINLINE static void CallFunc_F64_I32_I32_RetVoid_PE(PCODE pcode, int8_t* pArgs, int8_t* pRet, PCODE pPortableEntryPointContext) + NOINLINE static void CallFunc_F64_I32_I32_RetVoid_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet) { + PCODE pcode = (PCODE)PortableEntryPoint::GetActualCode(pPortableEntryPoint); alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK; void (*fptr)(int*, double, int32_t, int32_t, PCODE) = (void (*)(int*, double, int32_t, int32_t, PCODE))pcode; - (*fptr)(&framePointer, ARG_F64(0), ARG_I32(1), ARG_I32(2), pPortableEntryPointContext); + (*fptr)(&framePointer, ARG_F64(0), ARG_I32(1), ARG_I32(2), pPortableEntryPoint); } - NOINLINE static void CallFunc_F32_I32_I32_RetVoid_PE(PCODE pcode, int8_t* pArgs, int8_t* pRet, PCODE pPortableEntryPointContext) + NOINLINE static void CallFunc_F32_I32_I32_RetVoid_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet) { + PCODE pcode = (PCODE)PortableEntryPoint::GetActualCode(pPortableEntryPoint); alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK; void (*fptr)(int*, float, int32_t, int32_t, PCODE) = (void (*)(int*, float, int32_t, int32_t, PCODE))pcode; - (*fptr)(&framePointer, ARG_F32(0), ARG_I32(1), ARG_I32(2), pPortableEntryPointContext); + (*fptr)(&framePointer, ARG_F32(0), ARG_I32(1), ARG_I32(2), pPortableEntryPoint); } static void CallFunc_I32_RetVoid(PCODE pcode, int8_t* pArgs, int8_t* pRet) @@ -468,11 +490,12 @@ namespace (*fptr)(ARG_I32(0), ARG_I32(1), ARG_I32(2), ARG_IND(3), ARG_IND(4), ARG_I32(5)); } - NOINLINE static void CallFunc_I32_I32_I32_RetVoid_PE(PCODE pcode, int8_t* pArgs, int8_t* pRet, PCODE pPortableEntryPointContext) + NOINLINE static void CallFunc_I32_I32_I32_RetVoid_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet) { + PCODE pcode = (PCODE)PortableEntryPoint::GetActualCode(pPortableEntryPoint); alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK; void (*fptr)(int*, int32_t, int32_t, int32_t, PCODE) = (void (*)(int*, int32_t, int32_t, int32_t, PCODE))pcode; - (*fptr)(&framePointer, ARG_I32(0), ARG_I32(1), ARG_I32(2), pPortableEntryPointContext); + (*fptr)(&framePointer, ARG_I32(0), ARG_I32(1), ARG_I32(2), pPortableEntryPoint); } static void CallFunc_I32_I32_IND_IND_I32_RetVoid(PCODE pcode, int8_t* pArgs, int8_t* pRet) @@ -487,11 +510,12 @@ namespace (*fptr)(ARG_I32(0), ARG_I32(1), ARG_IND(2), ARG_IND(3), ARG_I32(4), ARG_I32(5)); } - NOINLINE static void CallFunc_I32_I32_RetVoid_PE(PCODE pcode, int8_t* pArgs, int8_t* pRet, PCODE pPortableEntryPointContext) + NOINLINE static void CallFunc_I32_I32_RetVoid_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet) { + PCODE pcode = (PCODE)PortableEntryPoint::GetActualCode(pPortableEntryPoint); alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK; void (*fptr)(int*, int32_t, int32_t, PCODE) = (void (*)(int*, int32_t, int32_t, PCODE))pcode; - (*fptr)(&framePointer, ARG_I32(0), ARG_I32(1), pPortableEntryPointContext); + (*fptr)(&framePointer, ARG_I32(0), ARG_I32(1), pPortableEntryPoint); } static void CallFunc_I32_IND_I32_RetVoid(PCODE pcode, int8_t* pArgs, int8_t* pRet) @@ -500,11 +524,12 @@ namespace (*fptr)(ARG_I32(0), ARG_IND(1), ARG_I32(2)); } - NOINLINE static void CallFunc_I32_RetVoid_PE(PCODE pcode, int8_t* pArgs, int8_t* pRet, PCODE pPortableEntryPointContext) + NOINLINE static void CallFunc_I32_RetVoid_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet) { + PCODE pcode = (PCODE)PortableEntryPoint::GetActualCode(pPortableEntryPoint); alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK; void (*fptr)(int*, int32_t, PCODE) = (void (*)(int*, int32_t, PCODE))pcode; - (*fptr)(&framePointer, ARG_I32(0), pPortableEntryPointContext); + (*fptr)(&framePointer, ARG_I32(0), pPortableEntryPoint); } static void CallFunc_I64_RetVoid(PCODE pcode, int8_t* pArgs, int8_t* pRet) @@ -573,11 +598,12 @@ namespace (*fptr)(ARG_IND(0), ARG_IND(1), ARG_I32(2), ARG_I32(3), ARG_I32(4), ARG_I32(5), ARG_I32(6)); } - NOINLINE static void CallFunc_Void_RetVoid_PE(PCODE pcode, int8_t* pArgs, int8_t* pRet, PCODE pPortableEntryPointContext) + NOINLINE static void CallFunc_Void_RetVoid_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet) { + PCODE pcode = (PCODE)PortableEntryPoint::GetActualCode(pPortableEntryPoint); alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK; void (*fptr)(int*, PCODE) = (void (*)(int*, PCODE))pcode; - (*fptr)(&framePointer, pPortableEntryPointContext); + (*fptr)(&framePointer, pPortableEntryPoint); } } diff --git a/src/coreclr/vm/wasm/helpers.cpp b/src/coreclr/vm/wasm/helpers.cpp index eede7bb20859e3..191122e19fe148 100644 --- a/src/coreclr/vm/wasm/helpers.cpp +++ b/src/coreclr/vm/wasm/helpers.cpp @@ -736,15 +736,16 @@ void InvokeCalliStub(CalliStubParam* pParam) _ASSERTE(pParam->ftn != (PCODE)NULL); _ASSERTE(pParam->cookie != NULL); - PCODE actualFtn = (PCODE)PortableEntryPoint::GetActualCode(pParam->ftn); - ((void(*)(PCODE, int8_t*, int8_t*, PCODE))pParam->cookie)(actualFtn, pParam->pArgs, pParam->pRet, pParam->ftn); + MethodDesc* md = PortableEntryPoint::GetMethodDesc(pParam->ftn); + + (pParam->cookie)(pParam->ftn, pParam->pArgs, pParam->pRet); } void InvokeUnmanagedCalli(PCODE ftn, InterpreterCalliCookie cookie, int8_t *pArgs, int8_t *pRet) { _ASSERTE(ftn != (PCODE)NULL); _ASSERTE(cookie != NULL); - ((void(*)(PCODE, int8_t*, int8_t*))cookie)(ftn, pArgs, pRet); + (cookie)(ftn, pArgs, pRet); } void InvokeDelegateInvokeMethod(DelegateInvokeMethodParam* pParam) diff --git a/src/tasks/WasmAppBuilder/coreclr/InterpToNativeGenerator.cs b/src/tasks/WasmAppBuilder/coreclr/InterpToNativeGenerator.cs index 711b88198e1062..d48e1308adf72f 100644 --- a/src/tasks/WasmAppBuilder/coreclr/InterpToNativeGenerator.cs +++ b/src/tasks/WasmAppBuilder/coreclr/InterpToNativeGenerator.cs @@ -105,14 +105,14 @@ private static void Emit(StreamWriter w, IEnumerable cookies) var portableEntryPointComma = signature.Length > 1 ? ", " : ""; var portableEntrypointDeclaration = isPortableEntryPointCall ? portableEntryPointComma + "PCODE" : ""; - var portableEntrypointParam = isPortableEntryPointCall ? portableEntryPointComma + "pPortableEntryPointContext" : ""; + var portableEntrypointParam = isPortableEntryPointCall ? portableEntryPointComma + "pPortableEntryPoint" : ""; var portableEntrypointStackDeclaration = isPortableEntryPointCall ? "int*, " : ""; var portableEntrypointStackParam = isPortableEntryPointCall ? "&framePointer, " : ""; w.Write( $$""" - {{(isPortableEntryPointCall ? "NOINLINE " : "")}}static void {{CallFuncName(args, SignatureMapper.CharToNameType(signature[0]), isPortableEntryPointCall)}}(PCODE pcode, int8_t* pArgs, int8_t* pRet{{(isPortableEntryPointCall ? ", PCODE pPortableEntryPointContext" : "")}}) - {{{(isPortableEntryPointCall ? "\n alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK;" : "")}} + {{(isPortableEntryPointCall ? "NOINLINE " : "")}}static void {{CallFuncName(args, SignatureMapper.CharToNameType(signature[0]), isPortableEntryPointCall)}}(PCODE {{(isPortableEntryPointCall ? "pPortableEntryPoint" : "pcode")}}, int8_t* pArgs, int8_t* pRet) + {{{(isPortableEntryPointCall ? "\n PCODE pcode = (PCODE)PortableEntryPoint::GetActualCode(pPortableEntryPoint);\n alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK;" : "")}} {{result.nativeType}} (*fptr)({{portableEntrypointStackDeclaration}}{{args.Join(", ", (p, i) => SignatureMapper.CharToNativeType(p))}}{{portableEntrypointDeclaration}}) = ({{result.nativeType}} (*)({{portableEntrypointStackDeclaration}}{{args.Join(", ", (p, i) => SignatureMapper.CharToNativeType(p))}}{{portableEntrypointDeclaration}}))pcode; {{portabilityAssert}}{{(result.isVoid ? "" : "*" + "((" + result.nativeType + "*)pRet) = ")}}(*fptr)({{portableEntrypointStackParam}}{{args.Join(", ", (p, i) => $"{SignatureMapper.CharToArgType(p)}({i})")}}{{portableEntrypointParam}}); } From c71a8d561bcdea3c3c3ee595fa7cd43b63979a39 Mon Sep 17 00:00:00 2001 From: Radek Doulik Date: Wed, 29 Apr 2026 21:17:22 +0200 Subject: [PATCH 15/22] Feedback Co-authored-by: Jan Kotas --- src/coreclr/vm/wasm/helpers.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/coreclr/vm/wasm/helpers.cpp b/src/coreclr/vm/wasm/helpers.cpp index 191122e19fe148..01ccd1aa50da87 100644 --- a/src/coreclr/vm/wasm/helpers.cpp +++ b/src/coreclr/vm/wasm/helpers.cpp @@ -736,8 +736,6 @@ void InvokeCalliStub(CalliStubParam* pParam) _ASSERTE(pParam->ftn != (PCODE)NULL); _ASSERTE(pParam->cookie != NULL); - MethodDesc* md = PortableEntryPoint::GetMethodDesc(pParam->ftn); - (pParam->cookie)(pParam->ftn, pParam->pArgs, pParam->pRet); } From e6e8ce40c3689619f8c0db3df120022950af7da2 Mon Sep 17 00:00:00 2001 From: Radek Doulik Date: Wed, 29 Apr 2026 21:16:55 +0200 Subject: [PATCH 16/22] Feedback --- .../vm/wasm/callhelpers-interp-to-managed.cpp | 78 +++++++------------ .../coreclr/InterpToNativeGenerator.cs | 4 +- 2 files changed, 28 insertions(+), 54 deletions(-) diff --git a/src/coreclr/vm/wasm/callhelpers-interp-to-managed.cpp b/src/coreclr/vm/wasm/callhelpers-interp-to-managed.cpp index 2e0086843ade1a..7e8da989ee0681 100644 --- a/src/coreclr/vm/wasm/callhelpers-interp-to-managed.cpp +++ b/src/coreclr/vm/wasm/callhelpers-interp-to-managed.cpp @@ -22,33 +22,29 @@ namespace { NOINLINE static void CallFunc_F64_F64_F64_RetF64_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet) { - PCODE pcode = (PCODE)PortableEntryPoint::GetActualCode(pPortableEntryPoint); alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK; - double (*fptr)(int*, double, double, double, PCODE) = (double (*)(int*, double, double, double, PCODE))pcode; + double (*fptr)(int*, double, double, double, PCODE) = (double (*)(int*, double, double, double, PCODE))PortableEntryPoint::GetActualCode(pPortableEntryPoint); *((double*)pRet) = (*fptr)(&framePointer, ARG_F64(0), ARG_F64(1), ARG_F64(2), pPortableEntryPoint); } NOINLINE static void CallFunc_F64_F64_RetF64_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet) { - PCODE pcode = (PCODE)PortableEntryPoint::GetActualCode(pPortableEntryPoint); alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK; - double (*fptr)(int*, double, double, PCODE) = (double (*)(int*, double, double, PCODE))pcode; + double (*fptr)(int*, double, double, PCODE) = (double (*)(int*, double, double, PCODE))PortableEntryPoint::GetActualCode(pPortableEntryPoint); *((double*)pRet) = (*fptr)(&framePointer, ARG_F64(0), ARG_F64(1), pPortableEntryPoint); } NOINLINE static void CallFunc_F64_I32_RetF64_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet) { - PCODE pcode = (PCODE)PortableEntryPoint::GetActualCode(pPortableEntryPoint); alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK; - double (*fptr)(int*, double, int32_t, PCODE) = (double (*)(int*, double, int32_t, PCODE))pcode; + double (*fptr)(int*, double, int32_t, PCODE) = (double (*)(int*, double, int32_t, PCODE))PortableEntryPoint::GetActualCode(pPortableEntryPoint); *((double*)pRet) = (*fptr)(&framePointer, ARG_F64(0), ARG_I32(1), pPortableEntryPoint); } NOINLINE static void CallFunc_F64_RetF64_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet) { - PCODE pcode = (PCODE)PortableEntryPoint::GetActualCode(pPortableEntryPoint); alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK; - double (*fptr)(int*, double, PCODE) = (double (*)(int*, double, PCODE))pcode; + double (*fptr)(int*, double, PCODE) = (double (*)(int*, double, PCODE))PortableEntryPoint::GetActualCode(pPortableEntryPoint); *((double*)pRet) = (*fptr)(&framePointer, ARG_F64(0), pPortableEntryPoint); } @@ -60,33 +56,29 @@ namespace NOINLINE static void CallFunc_F32_F32_F32_RetF32_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet) { - PCODE pcode = (PCODE)PortableEntryPoint::GetActualCode(pPortableEntryPoint); alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK; - float (*fptr)(int*, float, float, float, PCODE) = (float (*)(int*, float, float, float, PCODE))pcode; + float (*fptr)(int*, float, float, float, PCODE) = (float (*)(int*, float, float, float, PCODE))PortableEntryPoint::GetActualCode(pPortableEntryPoint); *((float*)pRet) = (*fptr)(&framePointer, ARG_F32(0), ARG_F32(1), ARG_F32(2), pPortableEntryPoint); } NOINLINE static void CallFunc_F32_F32_RetF32_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet) { - PCODE pcode = (PCODE)PortableEntryPoint::GetActualCode(pPortableEntryPoint); alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK; - float (*fptr)(int*, float, float, PCODE) = (float (*)(int*, float, float, PCODE))pcode; + float (*fptr)(int*, float, float, PCODE) = (float (*)(int*, float, float, PCODE))PortableEntryPoint::GetActualCode(pPortableEntryPoint); *((float*)pRet) = (*fptr)(&framePointer, ARG_F32(0), ARG_F32(1), pPortableEntryPoint); } NOINLINE static void CallFunc_F32_I32_RetF32_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet) { - PCODE pcode = (PCODE)PortableEntryPoint::GetActualCode(pPortableEntryPoint); alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK; - float (*fptr)(int*, float, int32_t, PCODE) = (float (*)(int*, float, int32_t, PCODE))pcode; + float (*fptr)(int*, float, int32_t, PCODE) = (float (*)(int*, float, int32_t, PCODE))PortableEntryPoint::GetActualCode(pPortableEntryPoint); *((float*)pRet) = (*fptr)(&framePointer, ARG_F32(0), ARG_I32(1), pPortableEntryPoint); } NOINLINE static void CallFunc_F32_RetF32_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet) { - PCODE pcode = (PCODE)PortableEntryPoint::GetActualCode(pPortableEntryPoint); alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK; - float (*fptr)(int*, float, PCODE) = (float (*)(int*, float, PCODE))pcode; + float (*fptr)(int*, float, PCODE) = (float (*)(int*, float, PCODE))PortableEntryPoint::GetActualCode(pPortableEntryPoint); *((float*)pRet) = (*fptr)(&framePointer, ARG_F32(0), pPortableEntryPoint); } @@ -146,25 +138,22 @@ namespace NOINLINE static void CallFunc_I32_I32_I32_I32_I32_I32_RetI32_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet) { - PCODE pcode = (PCODE)PortableEntryPoint::GetActualCode(pPortableEntryPoint); alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK; - int32_t (*fptr)(int*, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, PCODE) = (int32_t (*)(int*, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, PCODE))pcode; + int32_t (*fptr)(int*, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, PCODE) = (int32_t (*)(int*, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, PCODE))PortableEntryPoint::GetActualCode(pPortableEntryPoint); *((int32_t*)pRet) = (*fptr)(&framePointer, ARG_I32(0), ARG_I32(1), ARG_I32(2), ARG_I32(3), ARG_I32(4), ARG_I32(5), pPortableEntryPoint); } NOINLINE static void CallFunc_I32_I32_I32_I32_I32_RetI32_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet) { - PCODE pcode = (PCODE)PortableEntryPoint::GetActualCode(pPortableEntryPoint); alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK; - int32_t (*fptr)(int*, int32_t, int32_t, int32_t, int32_t, int32_t, PCODE) = (int32_t (*)(int*, int32_t, int32_t, int32_t, int32_t, int32_t, PCODE))pcode; + int32_t (*fptr)(int*, int32_t, int32_t, int32_t, int32_t, int32_t, PCODE) = (int32_t (*)(int*, int32_t, int32_t, int32_t, int32_t, int32_t, PCODE))PortableEntryPoint::GetActualCode(pPortableEntryPoint); *((int32_t*)pRet) = (*fptr)(&framePointer, ARG_I32(0), ARG_I32(1), ARG_I32(2), ARG_I32(3), ARG_I32(4), pPortableEntryPoint); } NOINLINE static void CallFunc_I32_I32_I32_I32_RetI32_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet) { - PCODE pcode = (PCODE)PortableEntryPoint::GetActualCode(pPortableEntryPoint); alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK; - int32_t (*fptr)(int*, int32_t, int32_t, int32_t, int32_t, PCODE) = (int32_t (*)(int*, int32_t, int32_t, int32_t, int32_t, PCODE))pcode; + int32_t (*fptr)(int*, int32_t, int32_t, int32_t, int32_t, PCODE) = (int32_t (*)(int*, int32_t, int32_t, int32_t, int32_t, PCODE))PortableEntryPoint::GetActualCode(pPortableEntryPoint); *((int32_t*)pRet) = (*fptr)(&framePointer, ARG_I32(0), ARG_I32(1), ARG_I32(2), ARG_I32(3), pPortableEntryPoint); } @@ -182,9 +171,8 @@ namespace NOINLINE static void CallFunc_I32_I32_I32_RetI32_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet) { - PCODE pcode = (PCODE)PortableEntryPoint::GetActualCode(pPortableEntryPoint); alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK; - int32_t (*fptr)(int*, int32_t, int32_t, int32_t, PCODE) = (int32_t (*)(int*, int32_t, int32_t, int32_t, PCODE))pcode; + int32_t (*fptr)(int*, int32_t, int32_t, int32_t, PCODE) = (int32_t (*)(int*, int32_t, int32_t, int32_t, PCODE))PortableEntryPoint::GetActualCode(pPortableEntryPoint); *((int32_t*)pRet) = (*fptr)(&framePointer, ARG_I32(0), ARG_I32(1), ARG_I32(2), pPortableEntryPoint); } @@ -208,9 +196,8 @@ namespace NOINLINE static void CallFunc_I32_I32_RetI32_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet) { - PCODE pcode = (PCODE)PortableEntryPoint::GetActualCode(pPortableEntryPoint); alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK; - int32_t (*fptr)(int*, int32_t, int32_t, PCODE) = (int32_t (*)(int*, int32_t, int32_t, PCODE))pcode; + int32_t (*fptr)(int*, int32_t, int32_t, PCODE) = (int32_t (*)(int*, int32_t, int32_t, PCODE))PortableEntryPoint::GetActualCode(pPortableEntryPoint); *((int32_t*)pRet) = (*fptr)(&framePointer, ARG_I32(0), ARG_I32(1), pPortableEntryPoint); } @@ -258,9 +245,8 @@ namespace NOINLINE static void CallFunc_I32_RetI32_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet) { - PCODE pcode = (PCODE)PortableEntryPoint::GetActualCode(pPortableEntryPoint); alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK; - int32_t (*fptr)(int*, int32_t, PCODE) = (int32_t (*)(int*, int32_t, PCODE))pcode; + int32_t (*fptr)(int*, int32_t, PCODE) = (int32_t (*)(int*, int32_t, PCODE))PortableEntryPoint::GetActualCode(pPortableEntryPoint); *((int32_t*)pRet) = (*fptr)(&framePointer, ARG_I32(0), pPortableEntryPoint); } @@ -344,9 +330,8 @@ namespace NOINLINE static void CallFunc_Void_RetI32_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet) { - PCODE pcode = (PCODE)PortableEntryPoint::GetActualCode(pPortableEntryPoint); alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK; - int32_t (*fptr)(int*, PCODE) = (int32_t (*)(int*, PCODE))pcode; + int32_t (*fptr)(int*, PCODE) = (int32_t (*)(int*, PCODE))PortableEntryPoint::GetActualCode(pPortableEntryPoint); *((int32_t*)pRet) = (*fptr)(&framePointer, pPortableEntryPoint); } @@ -382,41 +367,36 @@ namespace NOINLINE static void CallFunc_I32_I64_I64_RetI64_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet) { - PCODE pcode = (PCODE)PortableEntryPoint::GetActualCode(pPortableEntryPoint); alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK; - int64_t (*fptr)(int*, int32_t, int64_t, int64_t, PCODE) = (int64_t (*)(int*, int32_t, int64_t, int64_t, PCODE))pcode; + int64_t (*fptr)(int*, int32_t, int64_t, int64_t, PCODE) = (int64_t (*)(int*, int32_t, int64_t, int64_t, PCODE))PortableEntryPoint::GetActualCode(pPortableEntryPoint); *((int64_t*)pRet) = (*fptr)(&framePointer, ARG_I32(0), ARG_I64(1), ARG_I64(2), pPortableEntryPoint); } NOINLINE static void CallFunc_I32_I64_RetI64_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet) { - PCODE pcode = (PCODE)PortableEntryPoint::GetActualCode(pPortableEntryPoint); alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK; - int64_t (*fptr)(int*, int32_t, int64_t, PCODE) = (int64_t (*)(int*, int32_t, int64_t, PCODE))pcode; + int64_t (*fptr)(int*, int32_t, int64_t, PCODE) = (int64_t (*)(int*, int32_t, int64_t, PCODE))PortableEntryPoint::GetActualCode(pPortableEntryPoint); *((int64_t*)pRet) = (*fptr)(&framePointer, ARG_I32(0), ARG_I64(1), pPortableEntryPoint); } NOINLINE static void CallFunc_I32_RetI64_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet) { - PCODE pcode = (PCODE)PortableEntryPoint::GetActualCode(pPortableEntryPoint); alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK; - int64_t (*fptr)(int*, int32_t, PCODE) = (int64_t (*)(int*, int32_t, PCODE))pcode; + int64_t (*fptr)(int*, int32_t, PCODE) = (int64_t (*)(int*, int32_t, PCODE))PortableEntryPoint::GetActualCode(pPortableEntryPoint); *((int64_t*)pRet) = (*fptr)(&framePointer, ARG_I32(0), pPortableEntryPoint); } NOINLINE static void CallFunc_I64_I64_RetI64_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet) { - PCODE pcode = (PCODE)PortableEntryPoint::GetActualCode(pPortableEntryPoint); alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK; - int64_t (*fptr)(int*, int64_t, int64_t, PCODE) = (int64_t (*)(int*, int64_t, int64_t, PCODE))pcode; + int64_t (*fptr)(int*, int64_t, int64_t, PCODE) = (int64_t (*)(int*, int64_t, int64_t, PCODE))PortableEntryPoint::GetActualCode(pPortableEntryPoint); *((int64_t*)pRet) = (*fptr)(&framePointer, ARG_I64(0), ARG_I64(1), pPortableEntryPoint); } NOINLINE static void CallFunc_Void_RetI64_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet) { - PCODE pcode = (PCODE)PortableEntryPoint::GetActualCode(pPortableEntryPoint); alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK; - int64_t (*fptr)(int*, PCODE) = (int64_t (*)(int*, PCODE))pcode; + int64_t (*fptr)(int*, PCODE) = (int64_t (*)(int*, PCODE))PortableEntryPoint::GetActualCode(pPortableEntryPoint); *((int64_t*)pRet) = (*fptr)(&framePointer, pPortableEntryPoint); } @@ -428,17 +408,15 @@ namespace NOINLINE static void CallFunc_F64_I32_I32_RetVoid_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet) { - PCODE pcode = (PCODE)PortableEntryPoint::GetActualCode(pPortableEntryPoint); alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK; - void (*fptr)(int*, double, int32_t, int32_t, PCODE) = (void (*)(int*, double, int32_t, int32_t, PCODE))pcode; + void (*fptr)(int*, double, int32_t, int32_t, PCODE) = (void (*)(int*, double, int32_t, int32_t, PCODE))PortableEntryPoint::GetActualCode(pPortableEntryPoint); (*fptr)(&framePointer, ARG_F64(0), ARG_I32(1), ARG_I32(2), pPortableEntryPoint); } NOINLINE static void CallFunc_F32_I32_I32_RetVoid_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet) { - PCODE pcode = (PCODE)PortableEntryPoint::GetActualCode(pPortableEntryPoint); alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK; - void (*fptr)(int*, float, int32_t, int32_t, PCODE) = (void (*)(int*, float, int32_t, int32_t, PCODE))pcode; + void (*fptr)(int*, float, int32_t, int32_t, PCODE) = (void (*)(int*, float, int32_t, int32_t, PCODE))PortableEntryPoint::GetActualCode(pPortableEntryPoint); (*fptr)(&framePointer, ARG_F32(0), ARG_I32(1), ARG_I32(2), pPortableEntryPoint); } @@ -492,9 +470,8 @@ namespace NOINLINE static void CallFunc_I32_I32_I32_RetVoid_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet) { - PCODE pcode = (PCODE)PortableEntryPoint::GetActualCode(pPortableEntryPoint); alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK; - void (*fptr)(int*, int32_t, int32_t, int32_t, PCODE) = (void (*)(int*, int32_t, int32_t, int32_t, PCODE))pcode; + void (*fptr)(int*, int32_t, int32_t, int32_t, PCODE) = (void (*)(int*, int32_t, int32_t, int32_t, PCODE))PortableEntryPoint::GetActualCode(pPortableEntryPoint); (*fptr)(&framePointer, ARG_I32(0), ARG_I32(1), ARG_I32(2), pPortableEntryPoint); } @@ -512,9 +489,8 @@ namespace NOINLINE static void CallFunc_I32_I32_RetVoid_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet) { - PCODE pcode = (PCODE)PortableEntryPoint::GetActualCode(pPortableEntryPoint); alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK; - void (*fptr)(int*, int32_t, int32_t, PCODE) = (void (*)(int*, int32_t, int32_t, PCODE))pcode; + void (*fptr)(int*, int32_t, int32_t, PCODE) = (void (*)(int*, int32_t, int32_t, PCODE))PortableEntryPoint::GetActualCode(pPortableEntryPoint); (*fptr)(&framePointer, ARG_I32(0), ARG_I32(1), pPortableEntryPoint); } @@ -526,9 +502,8 @@ namespace NOINLINE static void CallFunc_I32_RetVoid_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet) { - PCODE pcode = (PCODE)PortableEntryPoint::GetActualCode(pPortableEntryPoint); alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK; - void (*fptr)(int*, int32_t, PCODE) = (void (*)(int*, int32_t, PCODE))pcode; + void (*fptr)(int*, int32_t, PCODE) = (void (*)(int*, int32_t, PCODE))PortableEntryPoint::GetActualCode(pPortableEntryPoint); (*fptr)(&framePointer, ARG_I32(0), pPortableEntryPoint); } @@ -600,9 +575,8 @@ namespace NOINLINE static void CallFunc_Void_RetVoid_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet) { - PCODE pcode = (PCODE)PortableEntryPoint::GetActualCode(pPortableEntryPoint); alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK; - void (*fptr)(int*, PCODE) = (void (*)(int*, PCODE))pcode; + void (*fptr)(int*, PCODE) = (void (*)(int*, PCODE))PortableEntryPoint::GetActualCode(pPortableEntryPoint); (*fptr)(&framePointer, pPortableEntryPoint); } } diff --git a/src/tasks/WasmAppBuilder/coreclr/InterpToNativeGenerator.cs b/src/tasks/WasmAppBuilder/coreclr/InterpToNativeGenerator.cs index d48e1308adf72f..a4b0c384f1318d 100644 --- a/src/tasks/WasmAppBuilder/coreclr/InterpToNativeGenerator.cs +++ b/src/tasks/WasmAppBuilder/coreclr/InterpToNativeGenerator.cs @@ -112,8 +112,8 @@ private static void Emit(StreamWriter w, IEnumerable cookies) $$""" {{(isPortableEntryPointCall ? "NOINLINE " : "")}}static void {{CallFuncName(args, SignatureMapper.CharToNameType(signature[0]), isPortableEntryPointCall)}}(PCODE {{(isPortableEntryPointCall ? "pPortableEntryPoint" : "pcode")}}, int8_t* pArgs, int8_t* pRet) - {{{(isPortableEntryPointCall ? "\n PCODE pcode = (PCODE)PortableEntryPoint::GetActualCode(pPortableEntryPoint);\n alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK;" : "")}} - {{result.nativeType}} (*fptr)({{portableEntrypointStackDeclaration}}{{args.Join(", ", (p, i) => SignatureMapper.CharToNativeType(p))}}{{portableEntrypointDeclaration}}) = ({{result.nativeType}} (*)({{portableEntrypointStackDeclaration}}{{args.Join(", ", (p, i) => SignatureMapper.CharToNativeType(p))}}{{portableEntrypointDeclaration}}))pcode; + {{{(isPortableEntryPointCall ? "\n alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK;" : "")}} + {{result.nativeType}} (*fptr)({{portableEntrypointStackDeclaration}}{{args.Join(", ", (p, i) => SignatureMapper.CharToNativeType(p))}}{{portableEntrypointDeclaration}}) = ({{result.nativeType}} (*)({{portableEntrypointStackDeclaration}}{{args.Join(", ", (p, i) => SignatureMapper.CharToNativeType(p))}}{{portableEntrypointDeclaration}})){{(isPortableEntryPointCall ? "PortableEntryPoint::GetActualCode(pPortableEntryPoint)" : "pcode")}}; {{portabilityAssert}}{{(result.isVoid ? "" : "*" + "((" + result.nativeType + "*)pRet) = ")}}(*fptr)({{portableEntrypointStackParam}}{{args.Join(", ", (p, i) => $"{SignatureMapper.CharToArgType(p)}({i})")}}{{portableEntrypointParam}}); } From 7491f17adb30e71499f0a04b3cffa4d9a472db81 Mon Sep 17 00:00:00 2001 From: Radek Doulik Date: Thu, 30 Apr 2026 21:06:15 +0200 Subject: [PATCH 17/22] Fix relinking --- src/coreclr/vm/wasm/callhelpers-interp-to-managed.cpp | 1 + src/tasks/WasmAppBuilder/coreclr/InterpToNativeGenerator.cs | 1 + 2 files changed, 2 insertions(+) diff --git a/src/coreclr/vm/wasm/callhelpers-interp-to-managed.cpp b/src/coreclr/vm/wasm/callhelpers-interp-to-managed.cpp index 7e8da989ee0681..e6cd7f0783b8b9 100644 --- a/src/coreclr/vm/wasm/callhelpers-interp-to-managed.cpp +++ b/src/coreclr/vm/wasm/callhelpers-interp-to-managed.cpp @@ -9,6 +9,7 @@ #include #include +#include "precode_portable.hpp" // Arguments are passed on the stack with each argument aligned to INTERP_STACK_SLOT_SIZE. #define ARG_ADDR(i) (pArgs + (i * INTERP_STACK_SLOT_SIZE)) diff --git a/src/tasks/WasmAppBuilder/coreclr/InterpToNativeGenerator.cs b/src/tasks/WasmAppBuilder/coreclr/InterpToNativeGenerator.cs index a4b0c384f1318d..d428706bfb4402 100644 --- a/src/tasks/WasmAppBuilder/coreclr/InterpToNativeGenerator.cs +++ b/src/tasks/WasmAppBuilder/coreclr/InterpToNativeGenerator.cs @@ -75,6 +75,7 @@ private static void Emit(StreamWriter w, IEnumerable cookies) #include #include + #include "precode_portable.hpp" // Arguments are passed on the stack with each argument aligned to INTERP_STACK_SLOT_SIZE. #define ARG_ADDR(i) (pArgs + (i * INTERP_STACK_SLOT_SIZE)) From f6184641064612e84927f9ca736807031874c51d Mon Sep 17 00:00:00 2001 From: Radek Doulik Date: Sun, 3 May 2026 21:52:12 +0200 Subject: [PATCH 18/22] Fix build with relink --- src/coreclr/vm/precode_portable.hpp | 18 ++++++++++++++++-- .../build/BrowserWasmApp.CoreCLR.targets | 3 +++ 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/src/coreclr/vm/precode_portable.hpp b/src/coreclr/vm/precode_portable.hpp index 6603fd907e3a2a..4d3d9882cbe777 100644 --- a/src/coreclr/vm/precode_portable.hpp +++ b/src/coreclr/vm/precode_portable.hpp @@ -8,17 +8,27 @@ #ifndef FEATURE_PORTABLE_ENTRYPOINTS #error Requires FEATURE_PORTABLE_ENTRYPOINTS to be set #endif // !FEATURE_PORTABLE_ENTRYPOINTS + +#ifndef _PRECODE_PORTABLE_MINIMAL #include "cdacdata.h" +#endif + +// _PRECODE_PORTABLE_MINIMAL: When defined, only the PortableEntryPoint::GetActualCode +// declaration below is emitted. Used by the WASM app-level relink +// build (wasm_m2n_invoke.g.cpp) which compiles outside the full CoreCLR build context +// and only needs to resolve entry points to actual code pointers. class PortableEntryPoint final { public: // static + static void* GetActualCode(PCODE addr); +#ifndef _PRECODE_PORTABLE_MINIMAL + static void SetActualCode(PCODE addr, PCODE actualCode); + // Returns true if the _pActualCode field of a given PortableEntryPoint is set to a non-null address and that address is the preferred entry point instead of preferring InterpreterCode usage. static bool HasNativeEntryPoint(PCODE addr); static bool HasInterpreterData(PCODE addr); - static void* GetActualCode(PCODE addr); - static void SetActualCode(PCODE addr, PCODE actualCode); static MethodDesc* GetMethodDesc(PCODE addr); static void* GetInterpreterData(PCODE addr); static void SetInterpreterData(PCODE addr, PCODE interpreterData); @@ -115,7 +125,10 @@ class PortableEntryPoint final } friend struct ::cdac_data; +#endif // !_PRECODE_PORTABLE_MINIMAL }; + +#ifndef _PRECODE_PORTABLE_MINIMAL template<> struct cdac_data { @@ -162,4 +175,5 @@ BOOL DoesSlotCallPrestub(PCODE pCode); class PrecodeMachineDescriptor { }; +#endif // !_PRECODE_PORTABLE_MINIMAL #endif // __PRECODE_PORTABLE_H__ diff --git a/src/mono/browser/build/BrowserWasmApp.CoreCLR.targets b/src/mono/browser/build/BrowserWasmApp.CoreCLR.targets index ab69d2c3d8465b..60077c592fc8f9 100644 --- a/src/mono/browser/build/BrowserWasmApp.CoreCLR.targets +++ b/src/mono/browser/build/BrowserWasmApp.CoreCLR.targets @@ -269,10 +269,13 @@ <_EmccCFlags Include="$(EmccCompileOptimizationFlag)" /> <_EmccCFlags Include="@(_EmccCommonFlags)" /> <_EmccCFlags Include="-DGEN_PINVOKE=1" /> + <_EmccCFlags Include="-DFEATURE_PORTABLE_ENTRYPOINTS=1" /> + <_EmccCFlags Include="-D_PRECODE_PORTABLE_MINIMAL=1" /> <_EmccCFlags Include="$(EmccExtraCFlags)" /> <_EmccCFlags Include="-I"$(RepoRoot)src/coreclr/vm/wasm"" Condition="Exists('$(RepoRoot)src/coreclr/vm/wasm/callhelpers.hpp')" /> + <_EmccCFlags Include="-I"$(RepoRoot)src/coreclr/vm"" Condition="Exists('$(RepoRoot)src/coreclr/vm/precode_portable.hpp')" /> <_EmccCFlags Include="-I"$(RepoRoot)src/native"" Condition="Exists('$(RepoRoot)src/native/minipal/entrypoints.h')" /> <_EmccCFlags Include="-include "$(_WasmIntermediateOutputPath)coreclr_compat.h"" /> From c20fa677c2d6665ca55169d36592001f16d93416 Mon Sep 17 00:00:00 2001 From: Radek Doulik Date: Mon, 4 May 2026 12:54:18 +0200 Subject: [PATCH 19/22] Feedback Co-authored-by: Jan Kotas --- src/coreclr/vm/wasm/callhelpers-interp-to-managed.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/coreclr/vm/wasm/callhelpers-interp-to-managed.cpp b/src/coreclr/vm/wasm/callhelpers-interp-to-managed.cpp index e6cd7f0783b8b9..7e8da989ee0681 100644 --- a/src/coreclr/vm/wasm/callhelpers-interp-to-managed.cpp +++ b/src/coreclr/vm/wasm/callhelpers-interp-to-managed.cpp @@ -9,7 +9,6 @@ #include #include -#include "precode_portable.hpp" // Arguments are passed on the stack with each argument aligned to INTERP_STACK_SLOT_SIZE. #define ARG_ADDR(i) (pArgs + (i * INTERP_STACK_SLOT_SIZE)) From a871a227b0ffc707ce12acfdcd202214a731a025 Mon Sep 17 00:00:00 2001 From: Radek Doulik Date: Mon, 4 May 2026 11:57:04 +0200 Subject: [PATCH 20/22] Feedback --- src/coreclr/vm/precode_portable.hpp | 20 ++----- .../vm/wasm/callhelpers-interp-to-managed.cpp | 52 +++++++++---------- src/coreclr/vm/wasm/callhelpers-pinvoke.cpp | 4 +- .../build/BrowserWasmApp.CoreCLR.targets | 3 -- .../coreclr/InterpToNativeGenerator.cs | 3 +- 5 files changed, 34 insertions(+), 48 deletions(-) diff --git a/src/coreclr/vm/precode_portable.hpp b/src/coreclr/vm/precode_portable.hpp index 4d3d9882cbe777..a1761950e95cd0 100644 --- a/src/coreclr/vm/precode_portable.hpp +++ b/src/coreclr/vm/precode_portable.hpp @@ -8,27 +8,17 @@ #ifndef FEATURE_PORTABLE_ENTRYPOINTS #error Requires FEATURE_PORTABLE_ENTRYPOINTS to be set #endif // !FEATURE_PORTABLE_ENTRYPOINTS - -#ifndef _PRECODE_PORTABLE_MINIMAL #include "cdacdata.h" -#endif - -// _PRECODE_PORTABLE_MINIMAL: When defined, only the PortableEntryPoint::GetActualCode -// declaration below is emitted. Used by the WASM app-level relink -// build (wasm_m2n_invoke.g.cpp) which compiles outside the full CoreCLR build context -// and only needs to resolve entry points to actual code pointers. class PortableEntryPoint final { public: // static - static void* GetActualCode(PCODE addr); -#ifndef _PRECODE_PORTABLE_MINIMAL - static void SetActualCode(PCODE addr, PCODE actualCode); - // Returns true if the _pActualCode field of a given PortableEntryPoint is set to a non-null address and that address is the preferred entry point instead of preferring InterpreterCode usage. static bool HasNativeEntryPoint(PCODE addr); static bool HasInterpreterData(PCODE addr); + static void* GetActualCode(PCODE addr); + static void SetActualCode(PCODE addr, PCODE actualCode); static MethodDesc* GetMethodDesc(PCODE addr); static void* GetInterpreterData(PCODE addr); static void SetInterpreterData(PCODE addr, PCODE interpreterData); @@ -125,16 +115,15 @@ class PortableEntryPoint final } friend struct ::cdac_data; -#endif // !_PRECODE_PORTABLE_MINIMAL }; -#ifndef _PRECODE_PORTABLE_MINIMAL template<> struct cdac_data { static constexpr size_t MethodDesc = offsetof(PortableEntryPoint, _pMD); -}; + static_assert(offsetof(PortableEntryPoint, _pActualCode) == 0, "CLR ABI requires _pActualCode to be at offset 0 of PortableEntryPoint"); +}; extern InterleavedLoaderHeapConfig s_stubPrecodeHeapConfig; @@ -175,5 +164,4 @@ BOOL DoesSlotCallPrestub(PCODE pCode); class PrecodeMachineDescriptor { }; -#endif // !_PRECODE_PORTABLE_MINIMAL #endif // __PRECODE_PORTABLE_H__ diff --git a/src/coreclr/vm/wasm/callhelpers-interp-to-managed.cpp b/src/coreclr/vm/wasm/callhelpers-interp-to-managed.cpp index 7e8da989ee0681..a3b45b01811e3d 100644 --- a/src/coreclr/vm/wasm/callhelpers-interp-to-managed.cpp +++ b/src/coreclr/vm/wasm/callhelpers-interp-to-managed.cpp @@ -23,28 +23,28 @@ namespace NOINLINE static void CallFunc_F64_F64_F64_RetF64_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet) { alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK; - double (*fptr)(int*, double, double, double, PCODE) = (double (*)(int*, double, double, double, PCODE))PortableEntryPoint::GetActualCode(pPortableEntryPoint); + double (*fptr)(int*, double, double, double, PCODE) = (double (*)(int*, double, double, double, PCODE))(pPortableEntryPoint); *((double*)pRet) = (*fptr)(&framePointer, ARG_F64(0), ARG_F64(1), ARG_F64(2), pPortableEntryPoint); } NOINLINE static void CallFunc_F64_F64_RetF64_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet) { alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK; - double (*fptr)(int*, double, double, PCODE) = (double (*)(int*, double, double, PCODE))PortableEntryPoint::GetActualCode(pPortableEntryPoint); + double (*fptr)(int*, double, double, PCODE) = (double (*)(int*, double, double, PCODE))(pPortableEntryPoint); *((double*)pRet) = (*fptr)(&framePointer, ARG_F64(0), ARG_F64(1), pPortableEntryPoint); } NOINLINE static void CallFunc_F64_I32_RetF64_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet) { alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK; - double (*fptr)(int*, double, int32_t, PCODE) = (double (*)(int*, double, int32_t, PCODE))PortableEntryPoint::GetActualCode(pPortableEntryPoint); + double (*fptr)(int*, double, int32_t, PCODE) = (double (*)(int*, double, int32_t, PCODE))(pPortableEntryPoint); *((double*)pRet) = (*fptr)(&framePointer, ARG_F64(0), ARG_I32(1), pPortableEntryPoint); } NOINLINE static void CallFunc_F64_RetF64_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet) { alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK; - double (*fptr)(int*, double, PCODE) = (double (*)(int*, double, PCODE))PortableEntryPoint::GetActualCode(pPortableEntryPoint); + double (*fptr)(int*, double, PCODE) = (double (*)(int*, double, PCODE))(pPortableEntryPoint); *((double*)pRet) = (*fptr)(&framePointer, ARG_F64(0), pPortableEntryPoint); } @@ -57,28 +57,28 @@ namespace NOINLINE static void CallFunc_F32_F32_F32_RetF32_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet) { alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK; - float (*fptr)(int*, float, float, float, PCODE) = (float (*)(int*, float, float, float, PCODE))PortableEntryPoint::GetActualCode(pPortableEntryPoint); + float (*fptr)(int*, float, float, float, PCODE) = (float (*)(int*, float, float, float, PCODE))(pPortableEntryPoint); *((float*)pRet) = (*fptr)(&framePointer, ARG_F32(0), ARG_F32(1), ARG_F32(2), pPortableEntryPoint); } NOINLINE static void CallFunc_F32_F32_RetF32_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet) { alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK; - float (*fptr)(int*, float, float, PCODE) = (float (*)(int*, float, float, PCODE))PortableEntryPoint::GetActualCode(pPortableEntryPoint); + float (*fptr)(int*, float, float, PCODE) = (float (*)(int*, float, float, PCODE))(pPortableEntryPoint); *((float*)pRet) = (*fptr)(&framePointer, ARG_F32(0), ARG_F32(1), pPortableEntryPoint); } NOINLINE static void CallFunc_F32_I32_RetF32_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet) { alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK; - float (*fptr)(int*, float, int32_t, PCODE) = (float (*)(int*, float, int32_t, PCODE))PortableEntryPoint::GetActualCode(pPortableEntryPoint); + float (*fptr)(int*, float, int32_t, PCODE) = (float (*)(int*, float, int32_t, PCODE))(pPortableEntryPoint); *((float*)pRet) = (*fptr)(&framePointer, ARG_F32(0), ARG_I32(1), pPortableEntryPoint); } NOINLINE static void CallFunc_F32_RetF32_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet) { alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK; - float (*fptr)(int*, float, PCODE) = (float (*)(int*, float, PCODE))PortableEntryPoint::GetActualCode(pPortableEntryPoint); + float (*fptr)(int*, float, PCODE) = (float (*)(int*, float, PCODE))(pPortableEntryPoint); *((float*)pRet) = (*fptr)(&framePointer, ARG_F32(0), pPortableEntryPoint); } @@ -139,21 +139,21 @@ namespace NOINLINE static void CallFunc_I32_I32_I32_I32_I32_I32_RetI32_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet) { alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK; - int32_t (*fptr)(int*, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, PCODE) = (int32_t (*)(int*, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, PCODE))PortableEntryPoint::GetActualCode(pPortableEntryPoint); + int32_t (*fptr)(int*, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, PCODE) = (int32_t (*)(int*, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, PCODE))(pPortableEntryPoint); *((int32_t*)pRet) = (*fptr)(&framePointer, ARG_I32(0), ARG_I32(1), ARG_I32(2), ARG_I32(3), ARG_I32(4), ARG_I32(5), pPortableEntryPoint); } NOINLINE static void CallFunc_I32_I32_I32_I32_I32_RetI32_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet) { alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK; - int32_t (*fptr)(int*, int32_t, int32_t, int32_t, int32_t, int32_t, PCODE) = (int32_t (*)(int*, int32_t, int32_t, int32_t, int32_t, int32_t, PCODE))PortableEntryPoint::GetActualCode(pPortableEntryPoint); + int32_t (*fptr)(int*, int32_t, int32_t, int32_t, int32_t, int32_t, PCODE) = (int32_t (*)(int*, int32_t, int32_t, int32_t, int32_t, int32_t, PCODE))(pPortableEntryPoint); *((int32_t*)pRet) = (*fptr)(&framePointer, ARG_I32(0), ARG_I32(1), ARG_I32(2), ARG_I32(3), ARG_I32(4), pPortableEntryPoint); } NOINLINE static void CallFunc_I32_I32_I32_I32_RetI32_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet) { alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK; - int32_t (*fptr)(int*, int32_t, int32_t, int32_t, int32_t, PCODE) = (int32_t (*)(int*, int32_t, int32_t, int32_t, int32_t, PCODE))PortableEntryPoint::GetActualCode(pPortableEntryPoint); + int32_t (*fptr)(int*, int32_t, int32_t, int32_t, int32_t, PCODE) = (int32_t (*)(int*, int32_t, int32_t, int32_t, int32_t, PCODE))(pPortableEntryPoint); *((int32_t*)pRet) = (*fptr)(&framePointer, ARG_I32(0), ARG_I32(1), ARG_I32(2), ARG_I32(3), pPortableEntryPoint); } @@ -172,7 +172,7 @@ namespace NOINLINE static void CallFunc_I32_I32_I32_RetI32_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet) { alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK; - int32_t (*fptr)(int*, int32_t, int32_t, int32_t, PCODE) = (int32_t (*)(int*, int32_t, int32_t, int32_t, PCODE))PortableEntryPoint::GetActualCode(pPortableEntryPoint); + int32_t (*fptr)(int*, int32_t, int32_t, int32_t, PCODE) = (int32_t (*)(int*, int32_t, int32_t, int32_t, PCODE))(pPortableEntryPoint); *((int32_t*)pRet) = (*fptr)(&framePointer, ARG_I32(0), ARG_I32(1), ARG_I32(2), pPortableEntryPoint); } @@ -197,7 +197,7 @@ namespace NOINLINE static void CallFunc_I32_I32_RetI32_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet) { alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK; - int32_t (*fptr)(int*, int32_t, int32_t, PCODE) = (int32_t (*)(int*, int32_t, int32_t, PCODE))PortableEntryPoint::GetActualCode(pPortableEntryPoint); + int32_t (*fptr)(int*, int32_t, int32_t, PCODE) = (int32_t (*)(int*, int32_t, int32_t, PCODE))(pPortableEntryPoint); *((int32_t*)pRet) = (*fptr)(&framePointer, ARG_I32(0), ARG_I32(1), pPortableEntryPoint); } @@ -246,7 +246,7 @@ namespace NOINLINE static void CallFunc_I32_RetI32_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet) { alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK; - int32_t (*fptr)(int*, int32_t, PCODE) = (int32_t (*)(int*, int32_t, PCODE))PortableEntryPoint::GetActualCode(pPortableEntryPoint); + int32_t (*fptr)(int*, int32_t, PCODE) = (int32_t (*)(int*, int32_t, PCODE))(pPortableEntryPoint); *((int32_t*)pRet) = (*fptr)(&framePointer, ARG_I32(0), pPortableEntryPoint); } @@ -331,7 +331,7 @@ namespace NOINLINE static void CallFunc_Void_RetI32_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet) { alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK; - int32_t (*fptr)(int*, PCODE) = (int32_t (*)(int*, PCODE))PortableEntryPoint::GetActualCode(pPortableEntryPoint); + int32_t (*fptr)(int*, PCODE) = (int32_t (*)(int*, PCODE))(pPortableEntryPoint); *((int32_t*)pRet) = (*fptr)(&framePointer, pPortableEntryPoint); } @@ -368,35 +368,35 @@ namespace NOINLINE static void CallFunc_I32_I64_I64_RetI64_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet) { alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK; - int64_t (*fptr)(int*, int32_t, int64_t, int64_t, PCODE) = (int64_t (*)(int*, int32_t, int64_t, int64_t, PCODE))PortableEntryPoint::GetActualCode(pPortableEntryPoint); + int64_t (*fptr)(int*, int32_t, int64_t, int64_t, PCODE) = (int64_t (*)(int*, int32_t, int64_t, int64_t, PCODE))(pPortableEntryPoint); *((int64_t*)pRet) = (*fptr)(&framePointer, ARG_I32(0), ARG_I64(1), ARG_I64(2), pPortableEntryPoint); } NOINLINE static void CallFunc_I32_I64_RetI64_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet) { alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK; - int64_t (*fptr)(int*, int32_t, int64_t, PCODE) = (int64_t (*)(int*, int32_t, int64_t, PCODE))PortableEntryPoint::GetActualCode(pPortableEntryPoint); + int64_t (*fptr)(int*, int32_t, int64_t, PCODE) = (int64_t (*)(int*, int32_t, int64_t, PCODE))(pPortableEntryPoint); *((int64_t*)pRet) = (*fptr)(&framePointer, ARG_I32(0), ARG_I64(1), pPortableEntryPoint); } NOINLINE static void CallFunc_I32_RetI64_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet) { alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK; - int64_t (*fptr)(int*, int32_t, PCODE) = (int64_t (*)(int*, int32_t, PCODE))PortableEntryPoint::GetActualCode(pPortableEntryPoint); + int64_t (*fptr)(int*, int32_t, PCODE) = (int64_t (*)(int*, int32_t, PCODE))(pPortableEntryPoint); *((int64_t*)pRet) = (*fptr)(&framePointer, ARG_I32(0), pPortableEntryPoint); } NOINLINE static void CallFunc_I64_I64_RetI64_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet) { alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK; - int64_t (*fptr)(int*, int64_t, int64_t, PCODE) = (int64_t (*)(int*, int64_t, int64_t, PCODE))PortableEntryPoint::GetActualCode(pPortableEntryPoint); + int64_t (*fptr)(int*, int64_t, int64_t, PCODE) = (int64_t (*)(int*, int64_t, int64_t, PCODE))(pPortableEntryPoint); *((int64_t*)pRet) = (*fptr)(&framePointer, ARG_I64(0), ARG_I64(1), pPortableEntryPoint); } NOINLINE static void CallFunc_Void_RetI64_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet) { alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK; - int64_t (*fptr)(int*, PCODE) = (int64_t (*)(int*, PCODE))PortableEntryPoint::GetActualCode(pPortableEntryPoint); + int64_t (*fptr)(int*, PCODE) = (int64_t (*)(int*, PCODE))(pPortableEntryPoint); *((int64_t*)pRet) = (*fptr)(&framePointer, pPortableEntryPoint); } @@ -409,14 +409,14 @@ namespace NOINLINE static void CallFunc_F64_I32_I32_RetVoid_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet) { alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK; - void (*fptr)(int*, double, int32_t, int32_t, PCODE) = (void (*)(int*, double, int32_t, int32_t, PCODE))PortableEntryPoint::GetActualCode(pPortableEntryPoint); + void (*fptr)(int*, double, int32_t, int32_t, PCODE) = (void (*)(int*, double, int32_t, int32_t, PCODE))(pPortableEntryPoint); (*fptr)(&framePointer, ARG_F64(0), ARG_I32(1), ARG_I32(2), pPortableEntryPoint); } NOINLINE static void CallFunc_F32_I32_I32_RetVoid_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet) { alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK; - void (*fptr)(int*, float, int32_t, int32_t, PCODE) = (void (*)(int*, float, int32_t, int32_t, PCODE))PortableEntryPoint::GetActualCode(pPortableEntryPoint); + void (*fptr)(int*, float, int32_t, int32_t, PCODE) = (void (*)(int*, float, int32_t, int32_t, PCODE))(pPortableEntryPoint); (*fptr)(&framePointer, ARG_F32(0), ARG_I32(1), ARG_I32(2), pPortableEntryPoint); } @@ -471,7 +471,7 @@ namespace NOINLINE static void CallFunc_I32_I32_I32_RetVoid_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet) { alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK; - void (*fptr)(int*, int32_t, int32_t, int32_t, PCODE) = (void (*)(int*, int32_t, int32_t, int32_t, PCODE))PortableEntryPoint::GetActualCode(pPortableEntryPoint); + void (*fptr)(int*, int32_t, int32_t, int32_t, PCODE) = (void (*)(int*, int32_t, int32_t, int32_t, PCODE))(pPortableEntryPoint); (*fptr)(&framePointer, ARG_I32(0), ARG_I32(1), ARG_I32(2), pPortableEntryPoint); } @@ -490,7 +490,7 @@ namespace NOINLINE static void CallFunc_I32_I32_RetVoid_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet) { alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK; - void (*fptr)(int*, int32_t, int32_t, PCODE) = (void (*)(int*, int32_t, int32_t, PCODE))PortableEntryPoint::GetActualCode(pPortableEntryPoint); + void (*fptr)(int*, int32_t, int32_t, PCODE) = (void (*)(int*, int32_t, int32_t, PCODE))(pPortableEntryPoint); (*fptr)(&framePointer, ARG_I32(0), ARG_I32(1), pPortableEntryPoint); } @@ -503,7 +503,7 @@ namespace NOINLINE static void CallFunc_I32_RetVoid_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet) { alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK; - void (*fptr)(int*, int32_t, PCODE) = (void (*)(int*, int32_t, PCODE))PortableEntryPoint::GetActualCode(pPortableEntryPoint); + void (*fptr)(int*, int32_t, PCODE) = (void (*)(int*, int32_t, PCODE))(pPortableEntryPoint); (*fptr)(&framePointer, ARG_I32(0), pPortableEntryPoint); } @@ -576,7 +576,7 @@ namespace NOINLINE static void CallFunc_Void_RetVoid_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet) { alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK; - void (*fptr)(int*, PCODE) = (void (*)(int*, PCODE))PortableEntryPoint::GetActualCode(pPortableEntryPoint); + void (*fptr)(int*, PCODE) = (void (*)(int*, PCODE))(pPortableEntryPoint); (*fptr)(&framePointer, pPortableEntryPoint); } } diff --git a/src/coreclr/vm/wasm/callhelpers-pinvoke.cpp b/src/coreclr/vm/wasm/callhelpers-pinvoke.cpp index 2be5428681fe54..1c820b6d7b18ca 100644 --- a/src/coreclr/vm/wasm/callhelpers-pinvoke.cpp +++ b/src/coreclr/vm/wasm/callhelpers-pinvoke.cpp @@ -11,6 +11,7 @@ #include extern "C" { + uint32_t CompressionNative_CompressBound (uint32_t); uint32_t CompressionNative_Crc32 (uint32_t, void *, int32_t); int32_t CompressionNative_Deflate (void *, int32_t); int32_t CompressionNative_DeflateEnd (void *); @@ -192,6 +193,7 @@ static const Entry s_libSystem_Globalization_Native [] = { }; static const Entry s_libSystem_IO_Compression_Native [] = { + DllImportEntry(CompressionNative_CompressBound) // System.IO.Compression DllImportEntry(CompressionNative_Crc32) // System.IO.Compression DllImportEntry(CompressionNative_Deflate) // System.IO.Compression, System.Net.WebSockets DllImportEntry(CompressionNative_DeflateEnd) // System.IO.Compression, System.Net.WebSockets @@ -320,7 +322,7 @@ typedef struct PInvokeTable { static PInvokeTable s_PInvokeTables[] = { {"libSystem.Globalization.Native", s_libSystem_Globalization_Native, 33}, - {"libSystem.IO.Compression.Native", s_libSystem_IO_Compression_Native, 8}, + {"libSystem.IO.Compression.Native", s_libSystem_IO_Compression_Native, 9}, {"libSystem.Native", s_libSystem_Native, 94}, {"libSystem.Native.Browser", s_libSystem_Native_Browser, 1}, {"libSystem.Runtime.InteropServices.JavaScript.Native", s_libSystem_Runtime_InteropServices_JavaScript_Native, 6} diff --git a/src/mono/browser/build/BrowserWasmApp.CoreCLR.targets b/src/mono/browser/build/BrowserWasmApp.CoreCLR.targets index 60077c592fc8f9..ab69d2c3d8465b 100644 --- a/src/mono/browser/build/BrowserWasmApp.CoreCLR.targets +++ b/src/mono/browser/build/BrowserWasmApp.CoreCLR.targets @@ -269,13 +269,10 @@ <_EmccCFlags Include="$(EmccCompileOptimizationFlag)" /> <_EmccCFlags Include="@(_EmccCommonFlags)" /> <_EmccCFlags Include="-DGEN_PINVOKE=1" /> - <_EmccCFlags Include="-DFEATURE_PORTABLE_ENTRYPOINTS=1" /> - <_EmccCFlags Include="-D_PRECODE_PORTABLE_MINIMAL=1" /> <_EmccCFlags Include="$(EmccExtraCFlags)" /> <_EmccCFlags Include="-I"$(RepoRoot)src/coreclr/vm/wasm"" Condition="Exists('$(RepoRoot)src/coreclr/vm/wasm/callhelpers.hpp')" /> - <_EmccCFlags Include="-I"$(RepoRoot)src/coreclr/vm"" Condition="Exists('$(RepoRoot)src/coreclr/vm/precode_portable.hpp')" /> <_EmccCFlags Include="-I"$(RepoRoot)src/native"" Condition="Exists('$(RepoRoot)src/native/minipal/entrypoints.h')" /> <_EmccCFlags Include="-include "$(_WasmIntermediateOutputPath)coreclr_compat.h"" /> diff --git a/src/tasks/WasmAppBuilder/coreclr/InterpToNativeGenerator.cs b/src/tasks/WasmAppBuilder/coreclr/InterpToNativeGenerator.cs index d428706bfb4402..b076e8ce5f1a77 100644 --- a/src/tasks/WasmAppBuilder/coreclr/InterpToNativeGenerator.cs +++ b/src/tasks/WasmAppBuilder/coreclr/InterpToNativeGenerator.cs @@ -75,7 +75,6 @@ private static void Emit(StreamWriter w, IEnumerable cookies) #include #include - #include "precode_portable.hpp" // Arguments are passed on the stack with each argument aligned to INTERP_STACK_SLOT_SIZE. #define ARG_ADDR(i) (pArgs + (i * INTERP_STACK_SLOT_SIZE)) @@ -114,7 +113,7 @@ private static void Emit(StreamWriter w, IEnumerable cookies) {{(isPortableEntryPointCall ? "NOINLINE " : "")}}static void {{CallFuncName(args, SignatureMapper.CharToNameType(signature[0]), isPortableEntryPointCall)}}(PCODE {{(isPortableEntryPointCall ? "pPortableEntryPoint" : "pcode")}}, int8_t* pArgs, int8_t* pRet) {{{(isPortableEntryPointCall ? "\n alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK;" : "")}} - {{result.nativeType}} (*fptr)({{portableEntrypointStackDeclaration}}{{args.Join(", ", (p, i) => SignatureMapper.CharToNativeType(p))}}{{portableEntrypointDeclaration}}) = ({{result.nativeType}} (*)({{portableEntrypointStackDeclaration}}{{args.Join(", ", (p, i) => SignatureMapper.CharToNativeType(p))}}{{portableEntrypointDeclaration}})){{(isPortableEntryPointCall ? "PortableEntryPoint::GetActualCode(pPortableEntryPoint)" : "pcode")}}; + {{result.nativeType}} (*fptr)({{portableEntrypointStackDeclaration}}{{args.Join(", ", (p, i) => SignatureMapper.CharToNativeType(p))}}{{portableEntrypointDeclaration}}) = ({{result.nativeType}} (*)({{portableEntrypointStackDeclaration}}{{args.Join(", ", (p, i) => SignatureMapper.CharToNativeType(p))}}{{portableEntrypointDeclaration}})){{(isPortableEntryPointCall ? "(pPortableEntryPoint)" : "pcode")}}; {{portabilityAssert}}{{(result.isVoid ? "" : "*" + "((" + result.nativeType + "*)pRet) = ")}}(*fptr)({{portableEntrypointStackParam}}{{args.Join(", ", (p, i) => $"{SignatureMapper.CharToArgType(p)}({i})")}}{{portableEntrypointParam}}); } From 022523e2d20c5bb078b6693ad70304448da47c6e Mon Sep 17 00:00:00 2001 From: Radek Doulik Date: Mon, 4 May 2026 14:26:00 +0200 Subject: [PATCH 21/22] Don't forget the pointer dereference --- src/tasks/WasmAppBuilder/coreclr/InterpToNativeGenerator.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tasks/WasmAppBuilder/coreclr/InterpToNativeGenerator.cs b/src/tasks/WasmAppBuilder/coreclr/InterpToNativeGenerator.cs index b076e8ce5f1a77..cf03dc8a1415c2 100644 --- a/src/tasks/WasmAppBuilder/coreclr/InterpToNativeGenerator.cs +++ b/src/tasks/WasmAppBuilder/coreclr/InterpToNativeGenerator.cs @@ -113,7 +113,7 @@ private static void Emit(StreamWriter w, IEnumerable cookies) {{(isPortableEntryPointCall ? "NOINLINE " : "")}}static void {{CallFuncName(args, SignatureMapper.CharToNameType(signature[0]), isPortableEntryPointCall)}}(PCODE {{(isPortableEntryPointCall ? "pPortableEntryPoint" : "pcode")}}, int8_t* pArgs, int8_t* pRet) {{{(isPortableEntryPointCall ? "\n alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK;" : "")}} - {{result.nativeType}} (*fptr)({{portableEntrypointStackDeclaration}}{{args.Join(", ", (p, i) => SignatureMapper.CharToNativeType(p))}}{{portableEntrypointDeclaration}}) = ({{result.nativeType}} (*)({{portableEntrypointStackDeclaration}}{{args.Join(", ", (p, i) => SignatureMapper.CharToNativeType(p))}}{{portableEntrypointDeclaration}})){{(isPortableEntryPointCall ? "(pPortableEntryPoint)" : "pcode")}}; + {{result.nativeType}} (*fptr)({{portableEntrypointStackDeclaration}}{{args.Join(", ", (p, i) => SignatureMapper.CharToNativeType(p))}}{{portableEntrypointDeclaration}}) = *({{result.nativeType}} (**)({{portableEntrypointStackDeclaration}}{{args.Join(", ", (p, i) => SignatureMapper.CharToNativeType(p))}}{{portableEntrypointDeclaration}})){{(isPortableEntryPointCall ? "(pPortableEntryPoint)" : "pcode")}}; {{portabilityAssert}}{{(result.isVoid ? "" : "*" + "((" + result.nativeType + "*)pRet) = ")}}(*fptr)({{portableEntrypointStackParam}}{{args.Join(", ", (p, i) => $"{SignatureMapper.CharToArgType(p)}({i})")}}{{portableEntrypointParam}}); } From bec30ff348f004b4865e31a4d967d3a355b99cee Mon Sep 17 00:00:00 2001 From: Radek Doulik Date: Mon, 4 May 2026 14:34:57 +0200 Subject: [PATCH 22/22] Regenerate and fix non-pe case --- .../vm/wasm/callhelpers-interp-to-managed.cpp | 52 +++++++++---------- .../coreclr/InterpToNativeGenerator.cs | 3 +- 2 files changed, 28 insertions(+), 27 deletions(-) diff --git a/src/coreclr/vm/wasm/callhelpers-interp-to-managed.cpp b/src/coreclr/vm/wasm/callhelpers-interp-to-managed.cpp index a3b45b01811e3d..7a87bbde0e76b8 100644 --- a/src/coreclr/vm/wasm/callhelpers-interp-to-managed.cpp +++ b/src/coreclr/vm/wasm/callhelpers-interp-to-managed.cpp @@ -23,28 +23,28 @@ namespace NOINLINE static void CallFunc_F64_F64_F64_RetF64_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet) { alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK; - double (*fptr)(int*, double, double, double, PCODE) = (double (*)(int*, double, double, double, PCODE))(pPortableEntryPoint); + double (*fptr)(int*, double, double, double, PCODE) = *(double (**)(int*, double, double, double, PCODE))(pPortableEntryPoint); *((double*)pRet) = (*fptr)(&framePointer, ARG_F64(0), ARG_F64(1), ARG_F64(2), pPortableEntryPoint); } NOINLINE static void CallFunc_F64_F64_RetF64_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet) { alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK; - double (*fptr)(int*, double, double, PCODE) = (double (*)(int*, double, double, PCODE))(pPortableEntryPoint); + double (*fptr)(int*, double, double, PCODE) = *(double (**)(int*, double, double, PCODE))(pPortableEntryPoint); *((double*)pRet) = (*fptr)(&framePointer, ARG_F64(0), ARG_F64(1), pPortableEntryPoint); } NOINLINE static void CallFunc_F64_I32_RetF64_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet) { alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK; - double (*fptr)(int*, double, int32_t, PCODE) = (double (*)(int*, double, int32_t, PCODE))(pPortableEntryPoint); + double (*fptr)(int*, double, int32_t, PCODE) = *(double (**)(int*, double, int32_t, PCODE))(pPortableEntryPoint); *((double*)pRet) = (*fptr)(&framePointer, ARG_F64(0), ARG_I32(1), pPortableEntryPoint); } NOINLINE static void CallFunc_F64_RetF64_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet) { alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK; - double (*fptr)(int*, double, PCODE) = (double (*)(int*, double, PCODE))(pPortableEntryPoint); + double (*fptr)(int*, double, PCODE) = *(double (**)(int*, double, PCODE))(pPortableEntryPoint); *((double*)pRet) = (*fptr)(&framePointer, ARG_F64(0), pPortableEntryPoint); } @@ -57,28 +57,28 @@ namespace NOINLINE static void CallFunc_F32_F32_F32_RetF32_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet) { alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK; - float (*fptr)(int*, float, float, float, PCODE) = (float (*)(int*, float, float, float, PCODE))(pPortableEntryPoint); + float (*fptr)(int*, float, float, float, PCODE) = *(float (**)(int*, float, float, float, PCODE))(pPortableEntryPoint); *((float*)pRet) = (*fptr)(&framePointer, ARG_F32(0), ARG_F32(1), ARG_F32(2), pPortableEntryPoint); } NOINLINE static void CallFunc_F32_F32_RetF32_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet) { alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK; - float (*fptr)(int*, float, float, PCODE) = (float (*)(int*, float, float, PCODE))(pPortableEntryPoint); + float (*fptr)(int*, float, float, PCODE) = *(float (**)(int*, float, float, PCODE))(pPortableEntryPoint); *((float*)pRet) = (*fptr)(&framePointer, ARG_F32(0), ARG_F32(1), pPortableEntryPoint); } NOINLINE static void CallFunc_F32_I32_RetF32_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet) { alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK; - float (*fptr)(int*, float, int32_t, PCODE) = (float (*)(int*, float, int32_t, PCODE))(pPortableEntryPoint); + float (*fptr)(int*, float, int32_t, PCODE) = *(float (**)(int*, float, int32_t, PCODE))(pPortableEntryPoint); *((float*)pRet) = (*fptr)(&framePointer, ARG_F32(0), ARG_I32(1), pPortableEntryPoint); } NOINLINE static void CallFunc_F32_RetF32_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet) { alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK; - float (*fptr)(int*, float, PCODE) = (float (*)(int*, float, PCODE))(pPortableEntryPoint); + float (*fptr)(int*, float, PCODE) = *(float (**)(int*, float, PCODE))(pPortableEntryPoint); *((float*)pRet) = (*fptr)(&framePointer, ARG_F32(0), pPortableEntryPoint); } @@ -139,21 +139,21 @@ namespace NOINLINE static void CallFunc_I32_I32_I32_I32_I32_I32_RetI32_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet) { alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK; - int32_t (*fptr)(int*, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, PCODE) = (int32_t (*)(int*, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, PCODE))(pPortableEntryPoint); + int32_t (*fptr)(int*, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, PCODE) = *(int32_t (**)(int*, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, PCODE))(pPortableEntryPoint); *((int32_t*)pRet) = (*fptr)(&framePointer, ARG_I32(0), ARG_I32(1), ARG_I32(2), ARG_I32(3), ARG_I32(4), ARG_I32(5), pPortableEntryPoint); } NOINLINE static void CallFunc_I32_I32_I32_I32_I32_RetI32_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet) { alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK; - int32_t (*fptr)(int*, int32_t, int32_t, int32_t, int32_t, int32_t, PCODE) = (int32_t (*)(int*, int32_t, int32_t, int32_t, int32_t, int32_t, PCODE))(pPortableEntryPoint); + int32_t (*fptr)(int*, int32_t, int32_t, int32_t, int32_t, int32_t, PCODE) = *(int32_t (**)(int*, int32_t, int32_t, int32_t, int32_t, int32_t, PCODE))(pPortableEntryPoint); *((int32_t*)pRet) = (*fptr)(&framePointer, ARG_I32(0), ARG_I32(1), ARG_I32(2), ARG_I32(3), ARG_I32(4), pPortableEntryPoint); } NOINLINE static void CallFunc_I32_I32_I32_I32_RetI32_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet) { alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK; - int32_t (*fptr)(int*, int32_t, int32_t, int32_t, int32_t, PCODE) = (int32_t (*)(int*, int32_t, int32_t, int32_t, int32_t, PCODE))(pPortableEntryPoint); + int32_t (*fptr)(int*, int32_t, int32_t, int32_t, int32_t, PCODE) = *(int32_t (**)(int*, int32_t, int32_t, int32_t, int32_t, PCODE))(pPortableEntryPoint); *((int32_t*)pRet) = (*fptr)(&framePointer, ARG_I32(0), ARG_I32(1), ARG_I32(2), ARG_I32(3), pPortableEntryPoint); } @@ -172,7 +172,7 @@ namespace NOINLINE static void CallFunc_I32_I32_I32_RetI32_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet) { alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK; - int32_t (*fptr)(int*, int32_t, int32_t, int32_t, PCODE) = (int32_t (*)(int*, int32_t, int32_t, int32_t, PCODE))(pPortableEntryPoint); + int32_t (*fptr)(int*, int32_t, int32_t, int32_t, PCODE) = *(int32_t (**)(int*, int32_t, int32_t, int32_t, PCODE))(pPortableEntryPoint); *((int32_t*)pRet) = (*fptr)(&framePointer, ARG_I32(0), ARG_I32(1), ARG_I32(2), pPortableEntryPoint); } @@ -197,7 +197,7 @@ namespace NOINLINE static void CallFunc_I32_I32_RetI32_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet) { alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK; - int32_t (*fptr)(int*, int32_t, int32_t, PCODE) = (int32_t (*)(int*, int32_t, int32_t, PCODE))(pPortableEntryPoint); + int32_t (*fptr)(int*, int32_t, int32_t, PCODE) = *(int32_t (**)(int*, int32_t, int32_t, PCODE))(pPortableEntryPoint); *((int32_t*)pRet) = (*fptr)(&framePointer, ARG_I32(0), ARG_I32(1), pPortableEntryPoint); } @@ -246,7 +246,7 @@ namespace NOINLINE static void CallFunc_I32_RetI32_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet) { alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK; - int32_t (*fptr)(int*, int32_t, PCODE) = (int32_t (*)(int*, int32_t, PCODE))(pPortableEntryPoint); + int32_t (*fptr)(int*, int32_t, PCODE) = *(int32_t (**)(int*, int32_t, PCODE))(pPortableEntryPoint); *((int32_t*)pRet) = (*fptr)(&framePointer, ARG_I32(0), pPortableEntryPoint); } @@ -331,7 +331,7 @@ namespace NOINLINE static void CallFunc_Void_RetI32_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet) { alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK; - int32_t (*fptr)(int*, PCODE) = (int32_t (*)(int*, PCODE))(pPortableEntryPoint); + int32_t (*fptr)(int*, PCODE) = *(int32_t (**)(int*, PCODE))(pPortableEntryPoint); *((int32_t*)pRet) = (*fptr)(&framePointer, pPortableEntryPoint); } @@ -368,35 +368,35 @@ namespace NOINLINE static void CallFunc_I32_I64_I64_RetI64_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet) { alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK; - int64_t (*fptr)(int*, int32_t, int64_t, int64_t, PCODE) = (int64_t (*)(int*, int32_t, int64_t, int64_t, PCODE))(pPortableEntryPoint); + int64_t (*fptr)(int*, int32_t, int64_t, int64_t, PCODE) = *(int64_t (**)(int*, int32_t, int64_t, int64_t, PCODE))(pPortableEntryPoint); *((int64_t*)pRet) = (*fptr)(&framePointer, ARG_I32(0), ARG_I64(1), ARG_I64(2), pPortableEntryPoint); } NOINLINE static void CallFunc_I32_I64_RetI64_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet) { alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK; - int64_t (*fptr)(int*, int32_t, int64_t, PCODE) = (int64_t (*)(int*, int32_t, int64_t, PCODE))(pPortableEntryPoint); + int64_t (*fptr)(int*, int32_t, int64_t, PCODE) = *(int64_t (**)(int*, int32_t, int64_t, PCODE))(pPortableEntryPoint); *((int64_t*)pRet) = (*fptr)(&framePointer, ARG_I32(0), ARG_I64(1), pPortableEntryPoint); } NOINLINE static void CallFunc_I32_RetI64_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet) { alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK; - int64_t (*fptr)(int*, int32_t, PCODE) = (int64_t (*)(int*, int32_t, PCODE))(pPortableEntryPoint); + int64_t (*fptr)(int*, int32_t, PCODE) = *(int64_t (**)(int*, int32_t, PCODE))(pPortableEntryPoint); *((int64_t*)pRet) = (*fptr)(&framePointer, ARG_I32(0), pPortableEntryPoint); } NOINLINE static void CallFunc_I64_I64_RetI64_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet) { alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK; - int64_t (*fptr)(int*, int64_t, int64_t, PCODE) = (int64_t (*)(int*, int64_t, int64_t, PCODE))(pPortableEntryPoint); + int64_t (*fptr)(int*, int64_t, int64_t, PCODE) = *(int64_t (**)(int*, int64_t, int64_t, PCODE))(pPortableEntryPoint); *((int64_t*)pRet) = (*fptr)(&framePointer, ARG_I64(0), ARG_I64(1), pPortableEntryPoint); } NOINLINE static void CallFunc_Void_RetI64_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet) { alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK; - int64_t (*fptr)(int*, PCODE) = (int64_t (*)(int*, PCODE))(pPortableEntryPoint); + int64_t (*fptr)(int*, PCODE) = *(int64_t (**)(int*, PCODE))(pPortableEntryPoint); *((int64_t*)pRet) = (*fptr)(&framePointer, pPortableEntryPoint); } @@ -409,14 +409,14 @@ namespace NOINLINE static void CallFunc_F64_I32_I32_RetVoid_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet) { alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK; - void (*fptr)(int*, double, int32_t, int32_t, PCODE) = (void (*)(int*, double, int32_t, int32_t, PCODE))(pPortableEntryPoint); + void (*fptr)(int*, double, int32_t, int32_t, PCODE) = *(void (**)(int*, double, int32_t, int32_t, PCODE))(pPortableEntryPoint); (*fptr)(&framePointer, ARG_F64(0), ARG_I32(1), ARG_I32(2), pPortableEntryPoint); } NOINLINE static void CallFunc_F32_I32_I32_RetVoid_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet) { alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK; - void (*fptr)(int*, float, int32_t, int32_t, PCODE) = (void (*)(int*, float, int32_t, int32_t, PCODE))(pPortableEntryPoint); + void (*fptr)(int*, float, int32_t, int32_t, PCODE) = *(void (**)(int*, float, int32_t, int32_t, PCODE))(pPortableEntryPoint); (*fptr)(&framePointer, ARG_F32(0), ARG_I32(1), ARG_I32(2), pPortableEntryPoint); } @@ -471,7 +471,7 @@ namespace NOINLINE static void CallFunc_I32_I32_I32_RetVoid_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet) { alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK; - void (*fptr)(int*, int32_t, int32_t, int32_t, PCODE) = (void (*)(int*, int32_t, int32_t, int32_t, PCODE))(pPortableEntryPoint); + void (*fptr)(int*, int32_t, int32_t, int32_t, PCODE) = *(void (**)(int*, int32_t, int32_t, int32_t, PCODE))(pPortableEntryPoint); (*fptr)(&framePointer, ARG_I32(0), ARG_I32(1), ARG_I32(2), pPortableEntryPoint); } @@ -490,7 +490,7 @@ namespace NOINLINE static void CallFunc_I32_I32_RetVoid_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet) { alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK; - void (*fptr)(int*, int32_t, int32_t, PCODE) = (void (*)(int*, int32_t, int32_t, PCODE))(pPortableEntryPoint); + void (*fptr)(int*, int32_t, int32_t, PCODE) = *(void (**)(int*, int32_t, int32_t, PCODE))(pPortableEntryPoint); (*fptr)(&framePointer, ARG_I32(0), ARG_I32(1), pPortableEntryPoint); } @@ -503,7 +503,7 @@ namespace NOINLINE static void CallFunc_I32_RetVoid_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet) { alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK; - void (*fptr)(int*, int32_t, PCODE) = (void (*)(int*, int32_t, PCODE))(pPortableEntryPoint); + void (*fptr)(int*, int32_t, PCODE) = *(void (**)(int*, int32_t, PCODE))(pPortableEntryPoint); (*fptr)(&framePointer, ARG_I32(0), pPortableEntryPoint); } @@ -576,7 +576,7 @@ namespace NOINLINE static void CallFunc_Void_RetVoid_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet) { alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK; - void (*fptr)(int*, PCODE) = (void (*)(int*, PCODE))(pPortableEntryPoint); + void (*fptr)(int*, PCODE) = *(void (**)(int*, PCODE))(pPortableEntryPoint); (*fptr)(&framePointer, pPortableEntryPoint); } } diff --git a/src/tasks/WasmAppBuilder/coreclr/InterpToNativeGenerator.cs b/src/tasks/WasmAppBuilder/coreclr/InterpToNativeGenerator.cs index cf03dc8a1415c2..a358f74c4c57a8 100644 --- a/src/tasks/WasmAppBuilder/coreclr/InterpToNativeGenerator.cs +++ b/src/tasks/WasmAppBuilder/coreclr/InterpToNativeGenerator.cs @@ -108,12 +108,13 @@ private static void Emit(StreamWriter w, IEnumerable cookies) var portableEntrypointParam = isPortableEntryPointCall ? portableEntryPointComma + "pPortableEntryPoint" : ""; var portableEntrypointStackDeclaration = isPortableEntryPointCall ? "int*, " : ""; var portableEntrypointStackParam = isPortableEntryPointCall ? "&framePointer, " : ""; + var portableEntrypointPointerRD = isPortableEntryPointCall ? "*" : ""; w.Write( $$""" {{(isPortableEntryPointCall ? "NOINLINE " : "")}}static void {{CallFuncName(args, SignatureMapper.CharToNameType(signature[0]), isPortableEntryPointCall)}}(PCODE {{(isPortableEntryPointCall ? "pPortableEntryPoint" : "pcode")}}, int8_t* pArgs, int8_t* pRet) {{{(isPortableEntryPointCall ? "\n alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK;" : "")}} - {{result.nativeType}} (*fptr)({{portableEntrypointStackDeclaration}}{{args.Join(", ", (p, i) => SignatureMapper.CharToNativeType(p))}}{{portableEntrypointDeclaration}}) = *({{result.nativeType}} (**)({{portableEntrypointStackDeclaration}}{{args.Join(", ", (p, i) => SignatureMapper.CharToNativeType(p))}}{{portableEntrypointDeclaration}})){{(isPortableEntryPointCall ? "(pPortableEntryPoint)" : "pcode")}}; + {{result.nativeType}} (*fptr)({{portableEntrypointStackDeclaration}}{{args.Join(", ", (p, i) => SignatureMapper.CharToNativeType(p))}}{{portableEntrypointDeclaration}}) = {{portableEntrypointPointerRD}}({{result.nativeType}} ({{portableEntrypointPointerRD}}*)({{portableEntrypointStackDeclaration}}{{args.Join(", ", (p, i) => SignatureMapper.CharToNativeType(p))}}{{portableEntrypointDeclaration}})){{(isPortableEntryPointCall ? "(pPortableEntryPoint)" : "pcode")}}; {{portabilityAssert}}{{(result.isVoid ? "" : "*" + "((" + result.nativeType + "*)pRet) = ")}}(*fptr)({{portableEntrypointStackParam}}{{args.Join(", ", (p, i) => $"{SignatureMapper.CharToArgType(p)}({i})")}}{{portableEntrypointParam}}); }