From 02065c679a88fa6e68aa8697e4920abd96b8bb70 Mon Sep 17 00:00:00 2001 From: Radek Doulik Date: Wed, 25 Feb 2026 19:45:36 +0100 Subject: [PATCH 1/3] [wasm][coreclr] Fix method portable entrypoints lifecycle Reset the portable entrypoint in places where we clear the interpreter code pointer Re-enable running of finalizers Re-enable access checks in the interpreter compiler This fixes https://github.com/dotnet/runtime/issues/123712 and possibly https://github.com/dotnet/runtime/issues/121955 --- src/coreclr/interpreter/compiler.cpp | 3 --- src/coreclr/vm/codeversion.cpp | 3 +++ src/coreclr/vm/finalizerthread.cpp | 3 +-- src/coreclr/vm/method.cpp | 24 ++++++++++++++++++++++-- src/coreclr/vm/method.hpp | 2 ++ 5 files changed, 28 insertions(+), 7 deletions(-) diff --git a/src/coreclr/interpreter/compiler.cpp b/src/coreclr/interpreter/compiler.cpp index b5924423564ee6..c48bc08ac7d2fb 100644 --- a/src/coreclr/interpreter/compiler.cpp +++ b/src/coreclr/interpreter/compiler.cpp @@ -4097,8 +4097,6 @@ void InterpCompiler::EmitCanAccessCallout(CORINFO_RESOLVED_TOKEN *pResolvedToken void InterpCompiler::EmitCallsiteCallout(CorInfoIsAccessAllowedResult accessAllowed, CORINFO_HELPER_DESC* calloutDesc) { -// WASM-TODO: https://github.com/dotnet/runtime/issues/121955 -#ifndef TARGET_WASM if (accessAllowed == CORINFO_ACCESS_ILLEGAL) { int32_t svars[CORINFO_ACCESS_ALLOWED_MAX_ARGS]; @@ -4169,7 +4167,6 @@ void InterpCompiler::EmitCallsiteCallout(CorInfoIsAccessAllowedResult accessAllo } m_pLastNewIns->data[0] = GetDataForHelperFtn(calloutDesc->helperNum); } -#endif // !TARGET_WASM } static OpcodePeepElement peepRuntimeAsyncCall[] = { diff --git a/src/coreclr/vm/codeversion.cpp b/src/coreclr/vm/codeversion.cpp index d8ce701e499898..0333d2d7941422 100644 --- a/src/coreclr/vm/codeversion.cpp +++ b/src/coreclr/vm/codeversion.cpp @@ -1984,6 +1984,9 @@ HRESULT CodeVersionManager::PublishNativeCodeVersion(MethodDesc* pMethod, Native // When we hit the Precode that should fixup any issues with an unset interpreter code pointer. This is notably most important in ReJIT scenarios pMethod->ClearInterpreterCodePointer(); #endif +#ifdef FEATURE_PORTABLE_ENTRYPOINTS + pMethod->ResetPortableEntryPoint(); +#endif // FEATURE_PORTABLE_ENTRYPOINTS #ifdef FEATURE_TIERED_COMPILATION bool wasSet = CallCountingManager::SetCodeEntryPoint(nativeCodeVersion, pCode, false, nullptr); _ASSERTE(wasSet); diff --git a/src/coreclr/vm/finalizerthread.cpp b/src/coreclr/vm/finalizerthread.cpp index e9f701b169316c..4e982c1c527119 100644 --- a/src/coreclr/vm/finalizerthread.cpp +++ b/src/coreclr/vm/finalizerthread.cpp @@ -58,8 +58,7 @@ extern "C" void SystemJS_ExecuteFinalizationCallback() INSTALL_UNHANDLED_MANAGED_EXCEPTION_TRAP; { GCX_COOP(); - // TODO-WASM https://github.com/dotnet/runtime/issues/123712 - // ManagedThreadBase::KickOff(FinalizerThread::FinalizerThreadWorkerIteration, NULL); + ManagedThreadBase::KickOff(FinalizerThread::FinalizerThreadWorkerIteration, NULL); } UNINSTALL_UNHANDLED_MANAGED_EXCEPTION_TRAP; } diff --git a/src/coreclr/vm/method.cpp b/src/coreclr/vm/method.cpp index 8d07d3155bce32..8c529c309a190f 100644 --- a/src/coreclr/vm/method.cpp +++ b/src/coreclr/vm/method.cpp @@ -2474,6 +2474,18 @@ BOOL MethodDesc::ShouldCallPrestub() #endif // FEATURE_PORTABLE_ENTRYPOINTS } +#ifdef FEATURE_PORTABLE_ENTRYPOINTS +void MethodDesc::ResetPortableEntryPoint() +{ + PCODE tempEntry = GetTemporaryEntryPointIfExists(); + if (tempEntry != (PCODE)NULL) + { + PortableEntryPoint* pep = PortableEntryPoint::ToPortableEntryPoint(tempEntry); + pep->Init(this); // Re-initializes: clears _pActualCode, _pInterpreterData, _flags + } +} +#endif // !FEATURE_PORTABLE_ENTRYPOINTS + //******************************************************************************* void MethodDesc::Reset() { @@ -2490,7 +2502,9 @@ void MethodDesc::Reset() // Reset any flags relevant to the old code ClearFlagsOnUpdate(); -#ifndef FEATURE_PORTABLE_ENTRYPOINTS +#ifdef FEATURE_PORTABLE_ENTRYPOINTS + ResetPortableEntryPoint(); +#else // !FEATURE_PORTABLE_ENTRYPOINTS _ASSERTE(HasPrecode()); GetPrecode()->Reset(); #endif // !FEATURE_PORTABLE_ENTRYPOINTS @@ -3276,6 +3290,10 @@ void MethodDesc::ResetCodeEntryPoint() ClearInterpreterCodePointer(); #endif +#ifdef FEATURE_PORTABLE_ENTRYPOINTS + ResetPortableEntryPoint(); +#endif // FEATURE_PORTABLE_ENTRYPOINTS + if (MayHaveEntryPointSlotsToBackpatch()) { BackpatchToResetEntryPointSlots(); @@ -3313,7 +3331,9 @@ void MethodDesc::ResetCodeEntryPointForEnC() #endif LOG((LF_ENC, LL_INFO100000, "MD::RCEPFENC: this:%p - %s::%s\n", this, m_pszDebugClassName, m_pszDebugMethodName)); -#ifndef FEATURE_PORTABLE_ENTRYPOINTS +#ifdef FEATURE_PORTABLE_ENTRYPOINTS + ResetPortableEntryPoint(); +#else // !FEATURE_PORTABLE_ENTRYPOINTS LOG((LF_ENC, LL_INFO100000, "MD::RCEPFENC: HasPrecode():%s, HasNativeCodeSlot():%s\n", (HasPrecode() ? "true" : "false"), (HasNativeCodeSlot() ? "true" : "false"))); if (HasPrecode()) diff --git a/src/coreclr/vm/method.hpp b/src/coreclr/vm/method.hpp index abdd36fc0931f8..c7f43d25b6123d 100644 --- a/src/coreclr/vm/method.hpp +++ b/src/coreclr/vm/method.hpp @@ -1619,6 +1619,8 @@ class MethodDesc void EnsurePortableEntryPoint(); PCODE GetPortableEntryPoint(); + + void ResetPortableEntryPoint(); #endif // FEATURE_PORTABLE_ENTRYPOINTS //******************************************************************************* From d908053af2de473293ce6c93766b771175c32830 Mon Sep 17 00:00:00 2001 From: Radek Doulik Date: Wed, 25 Feb 2026 22:04:01 +0100 Subject: [PATCH 2/3] Disable access checks again --- src/coreclr/interpreter/compiler.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/coreclr/interpreter/compiler.cpp b/src/coreclr/interpreter/compiler.cpp index c48bc08ac7d2fb..b5924423564ee6 100644 --- a/src/coreclr/interpreter/compiler.cpp +++ b/src/coreclr/interpreter/compiler.cpp @@ -4097,6 +4097,8 @@ void InterpCompiler::EmitCanAccessCallout(CORINFO_RESOLVED_TOKEN *pResolvedToken void InterpCompiler::EmitCallsiteCallout(CorInfoIsAccessAllowedResult accessAllowed, CORINFO_HELPER_DESC* calloutDesc) { +// WASM-TODO: https://github.com/dotnet/runtime/issues/121955 +#ifndef TARGET_WASM if (accessAllowed == CORINFO_ACCESS_ILLEGAL) { int32_t svars[CORINFO_ACCESS_ALLOWED_MAX_ARGS]; @@ -4167,6 +4169,7 @@ void InterpCompiler::EmitCallsiteCallout(CorInfoIsAccessAllowedResult accessAllo } m_pLastNewIns->data[0] = GetDataForHelperFtn(calloutDesc->helperNum); } +#endif // !TARGET_WASM } static OpcodePeepElement peepRuntimeAsyncCall[] = { From a3c7ac1dd5eff4b1349037f54186014db1b028c0 Mon Sep 17 00:00:00 2001 From: Radek Doulik Date: Wed, 25 Feb 2026 22:05:08 +0100 Subject: [PATCH 3/3] Apply suggestions from code review Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: Aaron R Robinson --- src/coreclr/vm/method.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/coreclr/vm/method.cpp b/src/coreclr/vm/method.cpp index 8c529c309a190f..bb08e6f9c6de63 100644 --- a/src/coreclr/vm/method.cpp +++ b/src/coreclr/vm/method.cpp @@ -2484,7 +2484,7 @@ void MethodDesc::ResetPortableEntryPoint() pep->Init(this); // Re-initializes: clears _pActualCode, _pInterpreterData, _flags } } -#endif // !FEATURE_PORTABLE_ENTRYPOINTS +#endif // FEATURE_PORTABLE_ENTRYPOINTS //******************************************************************************* void MethodDesc::Reset() @@ -2507,7 +2507,7 @@ void MethodDesc::Reset() #else // !FEATURE_PORTABLE_ENTRYPOINTS _ASSERTE(HasPrecode()); GetPrecode()->Reset(); -#endif // !FEATURE_PORTABLE_ENTRYPOINTS +#endif // FEATURE_PORTABLE_ENTRYPOINTS if (HasNativeCodeSlot()) {