From 872e969e63f1f25330f8ec59cdef403c2b712788 Mon Sep 17 00:00:00 2001 From: EgorBo Date: Wed, 16 Jul 2025 03:52:28 +0200 Subject: [PATCH 01/11] Inline CORINFO_HELP_ARRADDR_ST helper call --- .../Runtime/CompilerServices/CastHelpers.cs | 9 +-- src/coreclr/jit/compiler.h | 24 +++++++ src/coreclr/jit/gentree.cpp | 31 +++++++++ src/coreclr/jit/gentree.h | 2 + src/coreclr/jit/importer.cpp | 7 +- src/coreclr/jit/importercalls.cpp | 64 ++++++++++++++++++- src/coreclr/jit/morph.cpp | 11 +++- src/coreclr/jit/namedintrinsiclist.h | 1 + .../src/System/Runtime/InternalCalls.cs | 4 -- .../src/System/Runtime/TypeCast.cs | 11 ++-- src/coreclr/vm/ecalllist.h | 5 -- src/coreclr/vm/jitinterface.h | 2 - .../CompilerServices/RuntimeHelpers.cs | 5 +- 13 files changed, 151 insertions(+), 25 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/CastHelpers.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/CastHelpers.cs index d98b50f752b5be..a7f2e7a087ff97 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/CastHelpers.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/CastHelpers.cs @@ -53,9 +53,6 @@ private static object ChkCastAny_NoCacheLookup(void* toTypeHnd, object obj) return obj; } - [MethodImpl(MethodImplOptions.InternalCall)] - private static extern void WriteBarrier(ref object? dst, object? obj); - // IsInstanceOf test used for unusual cases (naked type parameters, variant generic types) // Unlike the IsInstanceOfInterface and IsInstanceOfClass functions, // this test must deal with all kinds of type tests @@ -454,7 +451,7 @@ private static void StelemRef(object?[] array, nint index, object? obj) goto notExactMatch; doWrite: - WriteBarrier(ref element, obj); + RuntimeHelpers.WriteBarrierUnchecked(ref element, obj); return; assigningNull: @@ -475,7 +472,7 @@ private static void StelemRef_Helper(ref object? element, void* elementType, obj CastResult result = CastCache.TryGet(s_table!, (nuint)RuntimeHelpers.GetMethodTable(obj), (nuint)elementType); if (result == CastResult.CanCast) { - WriteBarrier(ref element, obj); + RuntimeHelpers.WriteBarrierUnchecked(ref element, obj); return; } @@ -493,7 +490,7 @@ private static void StelemRef_Helper_NoCacheLookup(ref object? element, void* el ThrowArrayMismatchException(); } - WriteBarrier(ref element, obj2); + RuntimeHelpers.WriteBarrierUnchecked(ref element, obj2); } [DebuggerHidden] diff --git a/src/coreclr/jit/compiler.h b/src/coreclr/jit/compiler.h index d30efd26a5ea9f..3d40071f17c338 100644 --- a/src/coreclr/jit/compiler.h +++ b/src/coreclr/jit/compiler.h @@ -5129,6 +5129,30 @@ class Compiler GenTree* dereferencedAddress, InlArgInfo* inlArgInfo); + typedef JitHashTable, CORINFO_METHOD_HANDLE> HelperToManagedMap; + HelperToManagedMap* m_helperToManagedMap = nullptr; + +public: + HelperToManagedMap* GetHelperToManagedMap() + { + if (m_helperToManagedMap == nullptr) + { + m_helperToManagedMap = new (getAllocator()) HelperToManagedMap(getAllocator()); + } + return m_helperToManagedMap; + } + bool HelperToManagedMapLookup(CORINFO_METHOD_HANDLE helperCallHnd, CORINFO_METHOD_HANDLE* userCallHnd) + { + if (m_helperToManagedMap == nullptr) + { + return false; + } + bool found = m_helperToManagedMap->Lookup(helperCallHnd, userCallHnd); + return found; + } +private: + + void impConvertToUserCallAndMarkForInlining(GenTreeCall* call); void impMarkInlineCandidate(GenTree* call, CORINFO_CONTEXT_HANDLE exactContextHnd, bool exactContextNeedsRuntimeLookup, diff --git a/src/coreclr/jit/gentree.cpp b/src/coreclr/jit/gentree.cpp index 29682889d4d4c4..3724bb9a42e25f 100644 --- a/src/coreclr/jit/gentree.cpp +++ b/src/coreclr/jit/gentree.cpp @@ -2343,6 +2343,34 @@ bool GenTreeCall::IsHelperCall(Compiler* compiler, unsigned helper) const return IsHelperCall(compiler->eeFindHelper(helper)); } +//------------------------------------------------------------------------- +// IsHelperCallOrUserEquivalent: Determine if this GT_CALL node is a specific helper call +// or its CT_USER equivalent. +// +// Arguments: +// compiler - the compiler instance so that we can call eeFindHelper +// +// Return Value: +// Returns true if this GT_CALL node is a call to the specified helper. +// +bool GenTreeCall::IsHelperCallOrUserEquivalent(Compiler* compiler, unsigned helper) const +{ + CORINFO_METHOD_HANDLE helperCallHnd = Compiler::eeFindHelper(helper); + if (IsHelperCall()) + { + return helperCallHnd == gtCallMethHnd; + } + + CORINFO_METHOD_HANDLE userCallHnd = NO_METHOD_HANDLE; + + auto mmap = compiler->impInlineRoot()->m_helperToManagedMap; + auto cc = mmap != nullptr ? mmap->GetCount() : -1; + if (ISMETHOD("Test")) + printf("1"); + + return compiler->impInlineRoot()->HelperToManagedMapLookup(helperCallHnd, &userCallHnd); +} + //------------------------------------------------------------------------- // IsRuntimeLookupHelperCall: Determine if this GT_CALL node represents a runtime lookup helper call. // @@ -12846,6 +12874,9 @@ void Compiler::gtDispTree(GenTree* tree, case NI_System_Runtime_CompilerServices_RuntimeHelpers_IsKnownConstant: printf(" isKnownConst"); break; + case NI_System_Runtime_CompilerServices_RuntimeHelpers_WriteBarrierUnchecked: + printf(" writeBarrierUnchecked"); + break; #if defined(FEATURE_SIMD) case NI_SIMD_UpperRestore: printf(" simdUpperRestore"); diff --git a/src/coreclr/jit/gentree.h b/src/coreclr/jit/gentree.h index 33690a76ef9169..21a92ced962f6b 100644 --- a/src/coreclr/jit/gentree.h +++ b/src/coreclr/jit/gentree.h @@ -5715,6 +5715,8 @@ struct GenTreeCall final : public GenTree bool IsHelperCall(Compiler* compiler, unsigned helper) const; + bool IsHelperCallOrUserEquivalent(Compiler* compiler, unsigned helper) const; + bool IsRuntimeLookupHelperCall(Compiler* compiler) const; bool IsSpecialIntrinsic(Compiler* compiler, NamedIntrinsic ni) const; diff --git a/src/coreclr/jit/importer.cpp b/src/coreclr/jit/importer.cpp index bee5fe142f40ae..18e389e7319162 100644 --- a/src/coreclr/jit/importer.cpp +++ b/src/coreclr/jit/importer.cpp @@ -7364,7 +7364,12 @@ void Compiler::impImportBlockCode(BasicBlock* block) // The array helper takes a native int for array length. // So if we have an int, explicitly extend it to be a native int. index = impImplicitIorI4Cast(index, TYP_I_IMPL); - op1 = gtNewHelperCallNode(CORINFO_HELP_ARRADDR_ST, TYP_VOID, array, index, value); + + GenTreeCall* call = gtNewHelperCallNode(CORINFO_HELP_ARRADDR_ST, TYP_VOID, array, index, value); + INDEBUG(call->gtRawILOffset = opcodeOffs); + impConvertToUserCallAndMarkForInlining(call); + op1 = call; + goto SPILL_APPEND; } diff --git a/src/coreclr/jit/importercalls.cpp b/src/coreclr/jit/importercalls.cpp index 79581b183fc04c..aeec7666ea0c36 100644 --- a/src/coreclr/jit/importercalls.cpp +++ b/src/coreclr/jit/importercalls.cpp @@ -3425,6 +3425,8 @@ GenTree* Compiler::impIntrinsic(CORINFO_CLASS_HANDLE clsHnd, // This one is just `return true/false` case NI_System_Runtime_CompilerServices_RuntimeHelpers_IsKnownConstant: + case NI_System_Runtime_CompilerServices_RuntimeHelpers_WriteBarrierUnchecked: + // Not expanding this can lead to noticeable allocations in T0 case NI_System_Runtime_CompilerServices_RuntimeHelpers_CreateSpan: @@ -3657,6 +3659,14 @@ GenTree* Compiler::impIntrinsic(CORINFO_CLASS_HANDLE clsHnd, break; } + case NI_System_Runtime_CompilerServices_RuntimeHelpers_WriteBarrierUnchecked: + { + GenTree* val = impPopStack().val; + GenTree* dst = impPopStack().val; + retNode = gtNewStoreIndNode(TYP_REF, dst, val, GTF_IND_TGT_HEAP); + break; + } + case NI_System_Runtime_CompilerServices_RuntimeHelpers_IsKnownConstant: { GenTree* op1 = impPopStack().val; @@ -7702,6 +7712,47 @@ void Compiler::addGuardedDevirtualizationCandidate(GenTreeCall* call, call->AddGDVCandidateInfo(this, pInfo); } +//------------------------------------------------------------------------ +// impConvertToUserCallAndMarkForInlining: convert a helper call to a user call +// and mark it for inlining. This is used for helper calls that are +// known to be backed by a user method that can be inlined. +// +// Arguments: +// call - the helper call to convert +// +void Compiler::impConvertToUserCallAndMarkForInlining(GenTreeCall* call) +{ + assert(call->IsHelperCall()); + + if (!opts.OptEnabled(CLFLG_INLINING)) + { + return; + } + + CORINFO_METHOD_HANDLE helperCallHnd = call->gtCallMethHnd; + CORINFO_METHOD_HANDLE managedCallHnd = NO_METHOD_HANDLE; + CORINFO_CONST_LOOKUP pNativeEntrypoint = {}; + info.compCompHnd->getHelperFtn(eeGetHelperNum(helperCallHnd), &pNativeEntrypoint, &managedCallHnd); + + if (managedCallHnd != NO_METHOD_HANDLE) + { + call->gtCallMethHnd = managedCallHnd; + call->gtCallType = CT_USER_FUNC; + + CORINFO_CALL_INFO hCallInfo = {}; + hCallInfo.hMethod = managedCallHnd; + hCallInfo.methodFlags = info.compCompHnd->getMethodAttribs(hCallInfo.hMethod); + impMarkInlineCandidate(call, nullptr, false, &hCallInfo, compInlineContext); + + if (ISMETHOD("Test")) + printf(""); + + impInlineRoot()->GetHelperToManagedMap()->Set(helperCallHnd, managedCallHnd, HelperToManagedMap::Overwrite); + JITDUMP("Converting helperCall [%06u] to user call [%s] and marking for inlining\n", dspTreeID(call), + eeGetMethodFullName(managedCallHnd)); + } +} + //------------------------------------------------------------------------ // impMarkInlineCandidate: determine if this call can be subsequently inlined // @@ -10618,7 +10669,14 @@ NamedIntrinsic Compiler::lookupNamedIntrinsic(CORINFO_METHOD_HANDLE method) { namespaceName += 8; - if (strcmp(namespaceName, "CompilerServices") == 0) + if (strcmp(className, "TypeCast") == 0) + { + if (strcmp(methodName, "WriteBarrierUnchecked") == 0) + { + result = NI_System_Runtime_CompilerServices_RuntimeHelpers_WriteBarrierUnchecked; + } + } + else if (strcmp(namespaceName, "CompilerServices") == 0) { if (strcmp(className, "RuntimeHelpers") == 0) { @@ -10634,6 +10692,10 @@ NamedIntrinsic Compiler::lookupNamedIntrinsic(CORINFO_METHOD_HANDLE method) { result = NI_System_Runtime_CompilerServices_RuntimeHelpers_IsKnownConstant; } + else if (strcmp(methodName, "WriteBarrierUnchecked") == 0) + { + result = NI_System_Runtime_CompilerServices_RuntimeHelpers_WriteBarrierUnchecked; + } else if (strcmp(methodName, "IsReferenceOrContainsReferences") == 0) { result = diff --git a/src/coreclr/jit/morph.cpp b/src/coreclr/jit/morph.cpp index e00d9c3c408bcc..6d4b1565477ddd 100644 --- a/src/coreclr/jit/morph.cpp +++ b/src/coreclr/jit/morph.cpp @@ -6487,13 +6487,22 @@ GenTree* Compiler::fgMorphCall(GenTreeCall* call) // Morph stelem.ref helper call to store a null value, into a store into an array without the helper. // This needs to be done after the arguments are morphed to ensure constant propagation has already taken place. - if (opts.OptimizationEnabled() && call->IsHelperCall(this, CORINFO_HELP_ARRADDR_ST)) + if (opts.OptimizationEnabled() && call->IsHelperCallOrUserEquivalent(this, CORINFO_HELP_ARRADDR_ST)) { assert(call->gtArgs.CountArgs() == 3); GenTree* arr = call->gtArgs.GetArgByIndex(0)->GetNode(); GenTree* index = call->gtArgs.GetArgByIndex(1)->GetNode(); GenTree* value = call->gtArgs.GetArgByIndex(2)->GetNode(); + if (!call->IsHelperCall()) + { + // Convert back to helper call if it wasn't inlined. + // Currently, only helper calls are eligible to be direct calls if the target has reached + // its final tier. TODO: remove this workaround and convert this user call to direct as well. + call->gtCallMethHnd = eeFindHelper(CORINFO_HELP_ARRADDR_ST); + call->gtCallType = CT_HELPER; + } + if (gtCanSkipCovariantStoreCheck(value, arr)) { // Either or both of the array and index arguments may have been spilled to temps by `fgMorphArgs`. Copy diff --git a/src/coreclr/jit/namedintrinsiclist.h b/src/coreclr/jit/namedintrinsiclist.h index 71a7124e0974ac..d556b0371c20cb 100644 --- a/src/coreclr/jit/namedintrinsiclist.h +++ b/src/coreclr/jit/namedintrinsiclist.h @@ -123,6 +123,7 @@ enum NamedIntrinsic : unsigned short NI_System_Runtime_CompilerServices_RuntimeHelpers_IsKnownConstant, NI_System_Runtime_CompilerServices_RuntimeHelpers_IsReferenceOrContainsReferences, NI_System_Runtime_CompilerServices_RuntimeHelpers_GetMethodTable, + NI_System_Runtime_CompilerServices_RuntimeHelpers_WriteBarrierUnchecked, NI_System_Runtime_CompilerServices_AsyncHelpers_AsyncSuspend, NI_System_Runtime_CompilerServices_AsyncHelpers_Await, diff --git a/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/InternalCalls.cs b/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/InternalCalls.cs index d7557d654a7217..9e89bb50a6aa05 100644 --- a/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/InternalCalls.cs +++ b/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/InternalCalls.cs @@ -148,10 +148,6 @@ internal static int RhEndNoGCRegion() internal static extern unsafe object RhpNewFastMisalign(MethodTable * pEEType); #endif // FEATURE_64BIT_ALIGNMENT - [RuntimeImport(RuntimeLibrary, "RhpAssignRef")] - [MethodImpl(MethodImplOptions.InternalCall)] - internal static extern unsafe void RhpAssignRef(ref object? address, object? obj); - [MethodImplAttribute(MethodImplOptions.InternalCall)] [RuntimeImport(RuntimeLibrary, "RhpGcSafeZeroMemory")] internal static extern unsafe ref byte RhpGcSafeZeroMemory(ref byte dmem, nuint size); diff --git a/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/TypeCast.cs b/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/TypeCast.cs index 5ea530800784d1..3ede0619e3ba73 100644 --- a/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/TypeCast.cs +++ b/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/TypeCast.cs @@ -802,8 +802,8 @@ public static unsafe void StelemRef(object?[] array, nint index, object? obj) if (elementType != obj.GetMethodTable()) goto notExactMatch; - doWrite: - InternalCalls.RhpAssignRef(ref element, obj); + doWrite: + WriteBarrierUnchecked(ref element, obj); return; assigningNull: @@ -826,7 +826,7 @@ private static unsafe void StelemRef_Helper(ref object? element, MethodTable* el CastResult result = s_castCache.TryGet((nuint)obj.GetMethodTable() + (int)AssignmentVariation.BoxedSource, (nuint)elementType); if (result == CastResult.CanCast) { - InternalCalls.RhpAssignRef(ref element, obj); + WriteBarrierUnchecked(ref element, obj); return; } @@ -843,7 +843,7 @@ private static unsafe void StelemRef_Helper_NoCacheLookup(ref object? element, M throw elementType->GetClasslibException(ExceptionIDs.ArrayTypeMismatch); } - InternalCalls.RhpAssignRef(ref element, obj); + WriteBarrierUnchecked(ref element, obj); } private static unsafe object IsInstanceOfArray(MethodTable* pTargetType, object obj) @@ -1275,5 +1275,8 @@ private static unsafe object CheckCastAny_NoCacheLookup(MethodTable* pTargetType return obj; } + + [Intrinsic] + internal static void WriteBarrierUnchecked(ref object? dst, object? obj) => dst = obj; } } diff --git a/src/coreclr/vm/ecalllist.h b/src/coreclr/vm/ecalllist.h index c901a56b50d96a..0b421a0851eed8 100644 --- a/src/coreclr/vm/ecalllist.h +++ b/src/coreclr/vm/ecalllist.h @@ -251,10 +251,6 @@ FCFuncStart(gThreadFuncs) FCFuncElement("get_OptimalMaxSpinWaitsPerSpinIteration", ThreadNative::GetOptimalMaxSpinWaitsPerSpinIteration) FCFuncEnd() -FCFuncStart(gCastHelpers) - FCFuncElement("WriteBarrier", ::WriteBarrier_Helper) -FCFuncEnd() - FCFuncStart(gArrayFuncs) FCFuncElement("GetCorElementTypeOfElementType", ArrayNative::GetCorElementTypeOfElementType) FCFuncEnd() @@ -383,7 +379,6 @@ FCFuncEnd() FCClassElement("Array", "System", gArrayFuncs) FCClassElement("AssemblyLoadContext", "System.Runtime.Loader", gAssemblyLoadContextFuncs) FCClassElement("Buffer", "System", gBufferFuncs) -FCClassElement("CastHelpers", "System.Runtime.CompilerServices", gCastHelpers) FCClassElement("Delegate", "System", gDelegateFuncs) FCClassElement("DependentHandle", "System.Runtime", gDependentHandleFuncs) FCClassElement("Environment", "System", gEnvironmentFuncs) diff --git a/src/coreclr/vm/jitinterface.h b/src/coreclr/vm/jitinterface.h index 00ed950e5d53d5..00bffa30e41a73 100644 --- a/src/coreclr/vm/jitinterface.h +++ b/src/coreclr/vm/jitinterface.h @@ -211,8 +211,6 @@ extern "C" FCDECL2(VOID, JIT_WriteBarrierEnsureNonHeapTarget, Object **dst, Obje // Copied write barriers must be called at a different location extern "C" FCDECL2(VOID, JIT_WriteBarrier_Callable, Object **dst, Object *ref); -#define WriteBarrier_Helper JIT_WriteBarrier_Callable - EXTERN_C FCDECL2_VV(INT64, JIT_LMul, INT64 val1, INT64 val2); #ifndef HOST_64BIT diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.cs index 6543046573bf3f..a177e78786b0c4 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.cs @@ -172,6 +172,9 @@ public static ReadOnlySpan CreateSpan(RuntimeFieldHandle fldHandle) /// true if the given type is a reference type or a value type that contains references or by-refs; otherwise, false. [Intrinsic] - public static bool IsReferenceOrContainsReferences() where T: allows ref struct => IsReferenceOrContainsReferences(); + public static bool IsReferenceOrContainsReferences() where T : allows ref struct => IsReferenceOrContainsReferences(); + + [Intrinsic] + internal static void WriteBarrierUnchecked(ref object? dst, object? obj) => dst = obj; } } From e93c1cf77919574e89c30179756a2c409af93aea Mon Sep 17 00:00:00 2001 From: EgorBo Date: Wed, 16 Jul 2025 03:55:21 +0200 Subject: [PATCH 02/11] clean up --- src/coreclr/jit/gentree.cpp | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/coreclr/jit/gentree.cpp b/src/coreclr/jit/gentree.cpp index 3724bb9a42e25f..2daadc9411643b 100644 --- a/src/coreclr/jit/gentree.cpp +++ b/src/coreclr/jit/gentree.cpp @@ -2362,13 +2362,8 @@ bool GenTreeCall::IsHelperCallOrUserEquivalent(Compiler* compiler, unsigned help } CORINFO_METHOD_HANDLE userCallHnd = NO_METHOD_HANDLE; - - auto mmap = compiler->impInlineRoot()->m_helperToManagedMap; - auto cc = mmap != nullptr ? mmap->GetCount() : -1; - if (ISMETHOD("Test")) - printf("1"); - - return compiler->impInlineRoot()->HelperToManagedMapLookup(helperCallHnd, &userCallHnd); + return (gtCallType == CT_USER_FUNC) && + compiler->impInlineRoot()->HelperToManagedMapLookup(helperCallHnd, &userCallHnd); } //------------------------------------------------------------------------- From 7279b86511b9c58619946ff2e6d9fede1b95ad10 Mon Sep 17 00:00:00 2001 From: EgorBo Date: Wed, 16 Jul 2025 04:02:53 +0200 Subject: [PATCH 03/11] fix ci --- src/coreclr/jit/gentree.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/coreclr/jit/gentree.cpp b/src/coreclr/jit/gentree.cpp index 2daadc9411643b..14cb8826a394e6 100644 --- a/src/coreclr/jit/gentree.cpp +++ b/src/coreclr/jit/gentree.cpp @@ -2361,9 +2361,14 @@ bool GenTreeCall::IsHelperCallOrUserEquivalent(Compiler* compiler, unsigned help return helperCallHnd == gtCallMethHnd; } - CORINFO_METHOD_HANDLE userCallHnd = NO_METHOD_HANDLE; - return (gtCallType == CT_USER_FUNC) && - compiler->impInlineRoot()->HelperToManagedMapLookup(helperCallHnd, &userCallHnd); + if (gtCallType == CT_USER_FUNC) + { + CORINFO_METHOD_HANDLE userCallHnd = NO_METHOD_HANDLE; + return compiler->impInlineRoot()->HelperToManagedMapLookup(helperCallHnd, &userCallHnd) && + (userCallHnd == gtCallMethHnd); + } + + return false; } //------------------------------------------------------------------------- From 894c0ef1325f54b09350c21e3edb81590c8e4527 Mon Sep 17 00:00:00 2001 From: EgorBo Date: Wed, 16 Jul 2025 04:04:49 +0200 Subject: [PATCH 04/11] clean up --- src/coreclr/jit/importercalls.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/coreclr/jit/importercalls.cpp b/src/coreclr/jit/importercalls.cpp index aeec7666ea0c36..7984f5d8c18dff 100644 --- a/src/coreclr/jit/importercalls.cpp +++ b/src/coreclr/jit/importercalls.cpp @@ -7744,9 +7744,6 @@ void Compiler::impConvertToUserCallAndMarkForInlining(GenTreeCall* call) hCallInfo.methodFlags = info.compCompHnd->getMethodAttribs(hCallInfo.hMethod); impMarkInlineCandidate(call, nullptr, false, &hCallInfo, compInlineContext); - if (ISMETHOD("Test")) - printf(""); - impInlineRoot()->GetHelperToManagedMap()->Set(helperCallHnd, managedCallHnd, HelperToManagedMap::Overwrite); JITDUMP("Converting helperCall [%06u] to user call [%s] and marking for inlining\n", dspTreeID(call), eeGetMethodFullName(managedCallHnd)); From 68e68a5150450e5da9ba7899f531b4c1a7e9b596 Mon Sep 17 00:00:00 2001 From: EgorBo Date: Thu, 17 Jul 2025 12:34:44 +0200 Subject: [PATCH 05/11] remove JIT_WriteBarrier_Callable --- src/coreclr/vm/amd64/JitHelpers_Fast.asm | 5 ----- src/coreclr/vm/amd64/jithelpers_fast.S | 8 -------- src/coreclr/vm/arm/asmhelpers.S | 15 --------------- src/coreclr/vm/arm64/asmhelpers.S | 14 -------------- src/coreclr/vm/arm64/asmhelpers.asm | 15 --------------- src/coreclr/vm/i386/jithelp.S | 17 ----------------- src/coreclr/vm/i386/jithelp.asm | 8 -------- src/coreclr/vm/jitinterface.h | 4 ---- src/coreclr/vm/loongarch64/asmhelpers.S | 14 -------------- src/coreclr/vm/riscv64/asmhelpers.S | 12 ------------ 10 files changed, 112 deletions(-) diff --git a/src/coreclr/vm/amd64/JitHelpers_Fast.asm b/src/coreclr/vm/amd64/JitHelpers_Fast.asm index f5b26b662441c4..149b38f11754e9 100644 --- a/src/coreclr/vm/amd64/JitHelpers_Fast.asm +++ b/src/coreclr/vm/amd64/JitHelpers_Fast.asm @@ -265,11 +265,6 @@ Section segment para 'DATA' JIT_WriteBarrier_Loc: dq 0 -LEAF_ENTRY JIT_WriteBarrier_Callable, _TEXT - ; JIT_WriteBarrier(Object** dst, Object* src) - jmp QWORD PTR [JIT_WriteBarrier_Loc] -LEAF_END JIT_WriteBarrier_Callable, _TEXT - ; There is an even more optimized version of these helpers possible which takes ; advantage of knowledge of which way the ephemeral heap is growing to only do 1/2 ; that check (this is more significant in the JIT_WriteBarrier case). diff --git a/src/coreclr/vm/amd64/jithelpers_fast.S b/src/coreclr/vm/amd64/jithelpers_fast.S index 37c2f5f98fd19d..d559ee8e844987 100644 --- a/src/coreclr/vm/amd64/jithelpers_fast.S +++ b/src/coreclr/vm/amd64/jithelpers_fast.S @@ -224,14 +224,6 @@ LEAF_END_MARKED JIT_ByRefWriteBarrier, _TEXT .text #endif -// ------------------------------------------------------------------ -// __declspec(naked) void F_CALL_CONV JIT_WriteBarrier_Callable(Object **dst, Object* val) -.balign 16 -LEAF_ENTRY JIT_WriteBarrier_Callable, _TEXT - // JIT_WriteBarrier(Object** dst, Object* src) - jmp [rip + C_FUNC(JIT_WriteBarrier_Loc)] -LEAF_END JIT_WriteBarrier_Callable, _TEXT - // The following helper will access ("probe") a word on each page of the stack // starting with the page right beneath rsp down to the one pointed to by r11. diff --git a/src/coreclr/vm/arm/asmhelpers.S b/src/coreclr/vm/arm/asmhelpers.S index 231ea2fb156a69..da614df9f23670 100644 --- a/src/coreclr/vm/arm/asmhelpers.S +++ b/src/coreclr/vm/arm/asmhelpers.S @@ -675,21 +675,6 @@ g_rgWriteBarrierDescriptors: .global g_rgWriteBarrierDescriptors -// ------------------------------------------------------------------ -// __declspec(naked) void F_CALL_CONV JIT_WriteBarrier_Callable(Object **dst, Object* val) - LEAF_ENTRY JIT_WriteBarrier_Callable - - // Branch to the write barrier -#if defined(__clang__) - ldr r2, =JIT_WriteBarrier_Loc-(1f+4) // or R3? See targetarm.h -1: - add r2, pc -#else - ldr r2, =JIT_WriteBarrier_Loc -#endif - ldr pc, [r2] - - LEAF_END JIT_WriteBarrier_Callable #ifdef FEATURE_READYTORUN diff --git a/src/coreclr/vm/arm64/asmhelpers.S b/src/coreclr/vm/arm64/asmhelpers.S index 5a00639e6afbb4..339174bce29f76 100644 --- a/src/coreclr/vm/arm64/asmhelpers.S +++ b/src/coreclr/vm/arm64/asmhelpers.S @@ -80,20 +80,6 @@ PATCH_LABEL ThePreStubPatchLabel ret lr LEAF_END ThePreStubPatch, _TEXT -// ------------------------// ------------------------------------------------------------------ -// __declspec(naked) void F_CALL_CONV JIT_WriteBarrier_Callable(Object **dst, Object* val) -LEAF_ENTRY JIT_WriteBarrier_Callable, _TEXT - - // Setup args for JIT_WriteBarrier. x14 = dst ; x15 = val - mov x14, x0 // x14 = dst - mov x15, x1 // x15 = val - - // Branch to the write barrier - PREPARE_EXTERNAL_VAR JIT_WriteBarrier_Loc, x17 - ldr x17, [x17] - br x17 -LEAF_END JIT_WriteBarrier_Callable, _TEXT - // // x12 = UMEntryThunkData* // diff --git a/src/coreclr/vm/arm64/asmhelpers.asm b/src/coreclr/vm/arm64/asmhelpers.asm index f5de9e3488c7c4..cd44cbbc58cf70 100644 --- a/src/coreclr/vm/arm64/asmhelpers.asm +++ b/src/coreclr/vm/arm64/asmhelpers.asm @@ -883,21 +883,6 @@ CallHelper2 br x1 LEAF_END -; ------------------------------------------------------------------ -; __declspec(naked) void F_CALL_CONV JIT_WriteBarrier_Callable(Object **dst, Object* val) - LEAF_ENTRY JIT_WriteBarrier_Callable - - ; Setup args for JIT_WriteBarrier. x14 = dst ; x15 = val - mov x14, x0 ; x14 = dst - mov x15, x1 ; x15 = val - - ; Branch to the write barrier - adrp x17, JIT_WriteBarrier_Loc - ldr x17, [x17, JIT_WriteBarrier_Loc] - br x17 - - LEAF_END - #ifdef PROFILING_SUPPORTED ; ------------------------------------------------------------------ diff --git a/src/coreclr/vm/i386/jithelp.S b/src/coreclr/vm/i386/jithelp.S index dc7c8568e05097..13a6f48f167f86 100644 --- a/src/coreclr/vm/i386/jithelp.S +++ b/src/coreclr/vm/i386/jithelp.S @@ -385,23 +385,6 @@ C_FUNC(JIT_WriteBarrierEAX_Loc): .word 0 .text -LEAF_ENTRY JIT_WriteBarrier_Callable, _TEXT - mov eax, edx - mov edx, ecx - push eax - call 1f -1: - pop eax -2: -.att_syntax - addl $_GLOBAL_OFFSET_TABLE_+(2b-1b), %eax -.intel_syntax noprefix - mov eax, dword ptr [eax + C_FUNC(JIT_WriteBarrierEAX_Loc)@GOT] - mov eax, [eax] - xchg eax, dword ptr [esp] - ret -LEAF_END JIT_WriteBarrier_Callable, _TEXT - .macro UniversalWriteBarrierHelper name .align 4 diff --git a/src/coreclr/vm/i386/jithelp.asm b/src/coreclr/vm/i386/jithelp.asm index 58b4200a871b62..2c61b1da06c343 100644 --- a/src/coreclr/vm/i386/jithelp.asm +++ b/src/coreclr/vm/i386/jithelp.asm @@ -427,14 +427,6 @@ _JIT_WriteBarrierGroup@0 PROC ret _JIT_WriteBarrierGroup@0 ENDP - ALIGN 4 -PUBLIC @JIT_WriteBarrier_Callable@8 -@JIT_WriteBarrier_Callable@8 PROC - mov eax,edx - mov edx,ecx - jmp DWORD PTR [_JIT_WriteBarrierEAX_Loc] - -@JIT_WriteBarrier_Callable@8 ENDP UniversalWriteBarrierHelper MACRO name ALIGN 4 diff --git a/src/coreclr/vm/jitinterface.h b/src/coreclr/vm/jitinterface.h index 419102971a1db9..ec4f06bb306059 100644 --- a/src/coreclr/vm/jitinterface.h +++ b/src/coreclr/vm/jitinterface.h @@ -207,10 +207,6 @@ extern "C" FCDECL2(VOID, RhpAssignRef, Object **dst, Object *ref); extern "C" FCDECL2(VOID, JIT_WriteBarrier, Object **dst, Object *ref); extern "C" FCDECL2(VOID, JIT_WriteBarrierEnsureNonHeapTarget, Object **dst, Object *ref); -// ARM64 JIT_WriteBarrier uses special ABI and thus is not callable directly -// Copied write barriers must be called at a different location -extern "C" FCDECL2(VOID, JIT_WriteBarrier_Callable, Object **dst, Object *ref); - EXTERN_C FCDECL2_VV(INT64, JIT_LMul, INT64 val1, INT64 val2); #ifndef HOST_64BIT diff --git a/src/coreclr/vm/loongarch64/asmhelpers.S b/src/coreclr/vm/loongarch64/asmhelpers.S index c40821314bc2ac..4b87cbe293269c 100644 --- a/src/coreclr/vm/loongarch64/asmhelpers.S +++ b/src/coreclr/vm/loongarch64/asmhelpers.S @@ -112,20 +112,6 @@ LOCAL_LABEL(EphemeralCheckEnabled): WRITE_BARRIER_END JIT_UpdateWriteBarrierState -// ---------------------------------------------------------------------------------------- -// __declspec(naked) void F_CALL_CONV JIT_WriteBarrier_Callable(Object **dst, Object* val) -LEAF_ENTRY JIT_WriteBarrier_Callable, _TEXT - - // Setup args for JIT_WriteBarrier. $t0 = dst ; $t1 = val - ori $t6, $a0, 0 // $t6 = dst - ori $t7, $a1, 0 // $t7 = val - - // Branch to the write barrier - la.local $r21, JIT_WriteBarrier_Loc - ld.d $r21, $r21, 0 - jirl $r0, $r21, 0 -LEAF_END JIT_WriteBarrier_Callable, _TEXT - .balign 64 // Align to power of two at least as big as patchable literal pool so that it fits optimally in cache line // ------------------------------------------------------------------ diff --git a/src/coreclr/vm/riscv64/asmhelpers.S b/src/coreclr/vm/riscv64/asmhelpers.S index 69e1acee43767f..32d5896679f0e5 100644 --- a/src/coreclr/vm/riscv64/asmhelpers.S +++ b/src/coreclr/vm/riscv64/asmhelpers.S @@ -98,18 +98,6 @@ LOCAL_LABEL(EphemeralCheckEnabled): WRITE_BARRIER_END JIT_UpdateWriteBarrierState -// ---------------------------------------------------------------------------------------- -// __declspec(naked) void F_CALL_CONV JIT_WriteBarrier_Callable(Object **dst, Object* val) -LEAF_ENTRY JIT_WriteBarrier_Callable, _TEXT - // Setup args for JIT_WriteBarrier. a0 = dst ; a1 = val - addi t3, a0, 0 // t3 = dst - addi t4, a1, 0 // t4 = val - - // Branch to the write barrier - ld t1, JIT_WriteBarrier_Loc - jr t1 -LEAF_END JIT_WriteBarrier_Callable, _TEXT - .balign 64 // Align to power of two at least as big as patchable literal pool so that it fits optimally in cache line // ------------------------------------------------------------------ From c526462d7c475c0cf4cc8cfdcf569b4b5b5e4a4c Mon Sep 17 00:00:00 2001 From: EgorBo Date: Thu, 17 Jul 2025 12:38:01 +0200 Subject: [PATCH 06/11] WriteBarrierUnchecked -> WriteBarrier --- .../System/Runtime/CompilerServices/CastHelpers.cs | 6 +++--- src/coreclr/jit/gentree.cpp | 4 ++-- src/coreclr/jit/importercalls.cpp | 12 ++++++------ src/coreclr/jit/namedintrinsiclist.h | 2 +- .../Runtime.Base/src/System/Runtime/TypeCast.cs | 8 ++++---- .../Runtime/CompilerServices/RuntimeHelpers.cs | 2 +- 6 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/CastHelpers.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/CastHelpers.cs index a7f2e7a087ff97..3723dccb9b3211 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/CastHelpers.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/CastHelpers.cs @@ -451,7 +451,7 @@ private static void StelemRef(object?[] array, nint index, object? obj) goto notExactMatch; doWrite: - RuntimeHelpers.WriteBarrierUnchecked(ref element, obj); + RuntimeHelpers.WriteBarrier(ref element, obj); return; assigningNull: @@ -472,7 +472,7 @@ private static void StelemRef_Helper(ref object? element, void* elementType, obj CastResult result = CastCache.TryGet(s_table!, (nuint)RuntimeHelpers.GetMethodTable(obj), (nuint)elementType); if (result == CastResult.CanCast) { - RuntimeHelpers.WriteBarrierUnchecked(ref element, obj); + RuntimeHelpers.WriteBarrier(ref element, obj); return; } @@ -490,7 +490,7 @@ private static void StelemRef_Helper_NoCacheLookup(ref object? element, void* el ThrowArrayMismatchException(); } - RuntimeHelpers.WriteBarrierUnchecked(ref element, obj2); + RuntimeHelpers.WriteBarrier(ref element, obj2); } [DebuggerHidden] diff --git a/src/coreclr/jit/gentree.cpp b/src/coreclr/jit/gentree.cpp index 4f3ce6c4cc83b5..2d06db3d271e6f 100644 --- a/src/coreclr/jit/gentree.cpp +++ b/src/coreclr/jit/gentree.cpp @@ -12874,8 +12874,8 @@ void Compiler::gtDispTree(GenTree* tree, case NI_System_Runtime_CompilerServices_RuntimeHelpers_IsKnownConstant: printf(" isKnownConst"); break; - case NI_System_Runtime_CompilerServices_RuntimeHelpers_WriteBarrierUnchecked: - printf(" writeBarrierUnchecked"); + case NI_System_Runtime_CompilerServices_RuntimeHelpers_WriteBarrier: + printf(" WriteBarrier"); break; #if defined(FEATURE_SIMD) case NI_SIMD_UpperRestore: diff --git a/src/coreclr/jit/importercalls.cpp b/src/coreclr/jit/importercalls.cpp index 7984f5d8c18dff..ce5b0a56c6e72e 100644 --- a/src/coreclr/jit/importercalls.cpp +++ b/src/coreclr/jit/importercalls.cpp @@ -3425,7 +3425,7 @@ GenTree* Compiler::impIntrinsic(CORINFO_CLASS_HANDLE clsHnd, // This one is just `return true/false` case NI_System_Runtime_CompilerServices_RuntimeHelpers_IsKnownConstant: - case NI_System_Runtime_CompilerServices_RuntimeHelpers_WriteBarrierUnchecked: + case NI_System_Runtime_CompilerServices_RuntimeHelpers_WriteBarrier: // Not expanding this can lead to noticeable allocations in T0 case NI_System_Runtime_CompilerServices_RuntimeHelpers_CreateSpan: @@ -3659,7 +3659,7 @@ GenTree* Compiler::impIntrinsic(CORINFO_CLASS_HANDLE clsHnd, break; } - case NI_System_Runtime_CompilerServices_RuntimeHelpers_WriteBarrierUnchecked: + case NI_System_Runtime_CompilerServices_RuntimeHelpers_WriteBarrier: { GenTree* val = impPopStack().val; GenTree* dst = impPopStack().val; @@ -10668,9 +10668,9 @@ NamedIntrinsic Compiler::lookupNamedIntrinsic(CORINFO_METHOD_HANDLE method) if (strcmp(className, "TypeCast") == 0) { - if (strcmp(methodName, "WriteBarrierUnchecked") == 0) + if (strcmp(methodName, "WriteBarrier") == 0) { - result = NI_System_Runtime_CompilerServices_RuntimeHelpers_WriteBarrierUnchecked; + result = NI_System_Runtime_CompilerServices_RuntimeHelpers_WriteBarrier; } } else if (strcmp(namespaceName, "CompilerServices") == 0) @@ -10689,9 +10689,9 @@ NamedIntrinsic Compiler::lookupNamedIntrinsic(CORINFO_METHOD_HANDLE method) { result = NI_System_Runtime_CompilerServices_RuntimeHelpers_IsKnownConstant; } - else if (strcmp(methodName, "WriteBarrierUnchecked") == 0) + else if (strcmp(methodName, "WriteBarrier") == 0) { - result = NI_System_Runtime_CompilerServices_RuntimeHelpers_WriteBarrierUnchecked; + result = NI_System_Runtime_CompilerServices_RuntimeHelpers_WriteBarrier; } else if (strcmp(methodName, "IsReferenceOrContainsReferences") == 0) { diff --git a/src/coreclr/jit/namedintrinsiclist.h b/src/coreclr/jit/namedintrinsiclist.h index d556b0371c20cb..2a3ec544310bb9 100644 --- a/src/coreclr/jit/namedintrinsiclist.h +++ b/src/coreclr/jit/namedintrinsiclist.h @@ -123,7 +123,7 @@ enum NamedIntrinsic : unsigned short NI_System_Runtime_CompilerServices_RuntimeHelpers_IsKnownConstant, NI_System_Runtime_CompilerServices_RuntimeHelpers_IsReferenceOrContainsReferences, NI_System_Runtime_CompilerServices_RuntimeHelpers_GetMethodTable, - NI_System_Runtime_CompilerServices_RuntimeHelpers_WriteBarrierUnchecked, + NI_System_Runtime_CompilerServices_RuntimeHelpers_WriteBarrier, NI_System_Runtime_CompilerServices_AsyncHelpers_AsyncSuspend, NI_System_Runtime_CompilerServices_AsyncHelpers_Await, diff --git a/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/TypeCast.cs b/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/TypeCast.cs index 3ede0619e3ba73..5df945096e8cb8 100644 --- a/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/TypeCast.cs +++ b/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/TypeCast.cs @@ -803,7 +803,7 @@ public static unsafe void StelemRef(object?[] array, nint index, object? obj) goto notExactMatch; doWrite: - WriteBarrierUnchecked(ref element, obj); + WriteBarrier(ref element, obj); return; assigningNull: @@ -826,7 +826,7 @@ private static unsafe void StelemRef_Helper(ref object? element, MethodTable* el CastResult result = s_castCache.TryGet((nuint)obj.GetMethodTable() + (int)AssignmentVariation.BoxedSource, (nuint)elementType); if (result == CastResult.CanCast) { - WriteBarrierUnchecked(ref element, obj); + WriteBarrier(ref element, obj); return; } @@ -843,7 +843,7 @@ private static unsafe void StelemRef_Helper_NoCacheLookup(ref object? element, M throw elementType->GetClasslibException(ExceptionIDs.ArrayTypeMismatch); } - WriteBarrierUnchecked(ref element, obj); + WriteBarrier(ref element, obj); } private static unsafe object IsInstanceOfArray(MethodTable* pTargetType, object obj) @@ -1277,6 +1277,6 @@ private static unsafe object CheckCastAny_NoCacheLookup(MethodTable* pTargetType } [Intrinsic] - internal static void WriteBarrierUnchecked(ref object? dst, object? obj) => dst = obj; + internal static void WriteBarrier(ref object? dst, object? obj) => dst = obj; } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.cs index a177e78786b0c4..98ee117b289327 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.cs @@ -175,6 +175,6 @@ public static ReadOnlySpan CreateSpan(RuntimeFieldHandle fldHandle) public static bool IsReferenceOrContainsReferences() where T : allows ref struct => IsReferenceOrContainsReferences(); [Intrinsic] - internal static void WriteBarrierUnchecked(ref object? dst, object? obj) => dst = obj; + internal static void WriteBarrier(ref object? dst, object? obj) => dst = obj; } } From 6c036c8807817278d2682dd1e88d45884e57611d Mon Sep 17 00:00:00 2001 From: EgorBo Date: Thu, 17 Jul 2025 12:41:45 +0200 Subject: [PATCH 07/11] add an assert --- src/coreclr/jit/importercalls.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/coreclr/jit/importercalls.cpp b/src/coreclr/jit/importercalls.cpp index ce5b0a56c6e72e..adc4de12d796e1 100644 --- a/src/coreclr/jit/importercalls.cpp +++ b/src/coreclr/jit/importercalls.cpp @@ -7744,6 +7744,15 @@ void Compiler::impConvertToUserCallAndMarkForInlining(GenTreeCall* call) hCallInfo.methodFlags = info.compCompHnd->getMethodAttribs(hCallInfo.hMethod); impMarkInlineCandidate(call, nullptr, false, &hCallInfo, compInlineContext); +#if DEBUG + CORINFO_METHOD_HANDLE existingValue = NO_METHOD_HANDLE; + if (impInlineRoot()->GetHelperToManagedMap()->Lookup(helperCallHnd, &existingValue)) + { + // Let's make sure HelperToManagedMap::Overwrite behavior always overwrites the same value. + assert(existingValue == managedCallHnd); + } +#endif + impInlineRoot()->GetHelperToManagedMap()->Set(helperCallHnd, managedCallHnd, HelperToManagedMap::Overwrite); JITDUMP("Converting helperCall [%06u] to user call [%s] and marking for inlining\n", dspTreeID(call), eeGetMethodFullName(managedCallHnd)); From 7300f5cc075b40fee83258215eb347c1c4e37bac Mon Sep 17 00:00:00 2001 From: Egor Bogatov Date: Wed, 3 Sep 2025 19:04:35 +0200 Subject: [PATCH 08/11] Update src/coreclr/jit/importercalls.cpp Co-authored-by: Jan Kotas --- src/coreclr/jit/importercalls.cpp | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/coreclr/jit/importercalls.cpp b/src/coreclr/jit/importercalls.cpp index 5270017284b913..e14ac2e6f02d94 100644 --- a/src/coreclr/jit/importercalls.cpp +++ b/src/coreclr/jit/importercalls.cpp @@ -10868,14 +10868,7 @@ NamedIntrinsic Compiler::lookupNamedIntrinsic(CORINFO_METHOD_HANDLE method) { namespaceName += 8; - if (strcmp(className, "TypeCast") == 0) - { - if (strcmp(methodName, "WriteBarrier") == 0) - { - result = NI_System_Runtime_CompilerServices_RuntimeHelpers_WriteBarrier; - } - } - else if (strcmp(namespaceName, "CompilerServices") == 0) + if (strcmp(namespaceName, "CompilerServices") == 0) { if (strcmp(className, "RuntimeHelpers") == 0) { From 8c3900a8bd5e92760b9566f8e14624887842c7d2 Mon Sep 17 00:00:00 2001 From: EgorBo Date: Wed, 3 Sep 2025 19:05:30 +0200 Subject: [PATCH 09/11] FB --- .../System/Runtime/CompilerServices/RuntimeHelpers.cs | 3 +++ .../Runtime.Base/src/System/Runtime/TypeCast.cs | 11 ++++------- .../Test.CoreLib/src/System/Runtime/RuntimeHelpers.cs | 3 +++ .../System/Runtime/CompilerServices/RuntimeHelpers.cs | 3 +++ 4 files changed, 13 insertions(+), 7 deletions(-) diff --git a/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/CompilerServices/RuntimeHelpers.cs b/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/CompilerServices/RuntimeHelpers.cs index b06f2f3d5eb30c..142ba1ce162ec6 100644 --- a/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/CompilerServices/RuntimeHelpers.cs +++ b/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/CompilerServices/RuntimeHelpers.cs @@ -18,5 +18,8 @@ public static int OffsetToStringData [Intrinsic] public static extern void InitializeArray(Array array, RuntimeFieldHandle fldHandle); + + [Intrinsic] + internal static void WriteBarrier(ref object? dst, object? obj) => dst = obj; } } diff --git a/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/TypeCast.cs b/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/TypeCast.cs index 5df945096e8cb8..9c9b4c1121289a 100644 --- a/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/TypeCast.cs +++ b/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/TypeCast.cs @@ -802,8 +802,8 @@ public static unsafe void StelemRef(object?[] array, nint index, object? obj) if (elementType != obj.GetMethodTable()) goto notExactMatch; - doWrite: - WriteBarrier(ref element, obj); + doWrite: + RuntimeHelpers.WriteBarrier(ref element, obj); return; assigningNull: @@ -826,7 +826,7 @@ private static unsafe void StelemRef_Helper(ref object? element, MethodTable* el CastResult result = s_castCache.TryGet((nuint)obj.GetMethodTable() + (int)AssignmentVariation.BoxedSource, (nuint)elementType); if (result == CastResult.CanCast) { - WriteBarrier(ref element, obj); + RuntimeHelpers.WriteBarrier(ref element, obj); return; } @@ -843,7 +843,7 @@ private static unsafe void StelemRef_Helper_NoCacheLookup(ref object? element, M throw elementType->GetClasslibException(ExceptionIDs.ArrayTypeMismatch); } - WriteBarrier(ref element, obj); + RuntimeHelpers.WriteBarrier(ref element, obj); } private static unsafe object IsInstanceOfArray(MethodTable* pTargetType, object obj) @@ -1275,8 +1275,5 @@ private static unsafe object CheckCastAny_NoCacheLookup(MethodTable* pTargetType return obj; } - - [Intrinsic] - internal static void WriteBarrier(ref object? dst, object? obj) => dst = obj; } } diff --git a/src/coreclr/nativeaot/Test.CoreLib/src/System/Runtime/RuntimeHelpers.cs b/src/coreclr/nativeaot/Test.CoreLib/src/System/Runtime/RuntimeHelpers.cs index 6c91965f67a1bd..0846fa36d191db 100644 --- a/src/coreclr/nativeaot/Test.CoreLib/src/System/Runtime/RuntimeHelpers.cs +++ b/src/coreclr/nativeaot/Test.CoreLib/src/System/Runtime/RuntimeHelpers.cs @@ -15,5 +15,8 @@ public static int OffsetToStringData return string.FIRST_CHAR_OFFSET; } } + + [Intrinsic] + internal static void WriteBarrier(ref object? dst, object? obj) => dst = obj; } } diff --git a/src/libraries/Common/tests/System/Runtime/CompilerServices/RuntimeHelpers.cs b/src/libraries/Common/tests/System/Runtime/CompilerServices/RuntimeHelpers.cs index 935e279f94dc2b..f19d597bea2d67 100644 --- a/src/libraries/Common/tests/System/Runtime/CompilerServices/RuntimeHelpers.cs +++ b/src/libraries/Common/tests/System/Runtime/CompilerServices/RuntimeHelpers.cs @@ -38,6 +38,9 @@ internal static T[] GetSubArray(T[] array, Range range) return dest; } } + + [Intrinsic] + internal static void WriteBarrier(ref object? dst, object? obj) => dst = obj; } } From 5bd0911956a15bd46ce31926ef44e8b4d2e51630 Mon Sep 17 00:00:00 2001 From: Egor Bogatov Date: Wed, 3 Sep 2025 19:34:38 +0200 Subject: [PATCH 10/11] Update src/libraries/Common/tests/System/Runtime/CompilerServices/RuntimeHelpers.cs Co-authored-by: Jan Kotas --- .../tests/System/Runtime/CompilerServices/RuntimeHelpers.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/libraries/Common/tests/System/Runtime/CompilerServices/RuntimeHelpers.cs b/src/libraries/Common/tests/System/Runtime/CompilerServices/RuntimeHelpers.cs index f19d597bea2d67..935e279f94dc2b 100644 --- a/src/libraries/Common/tests/System/Runtime/CompilerServices/RuntimeHelpers.cs +++ b/src/libraries/Common/tests/System/Runtime/CompilerServices/RuntimeHelpers.cs @@ -38,9 +38,6 @@ internal static T[] GetSubArray(T[] array, Range range) return dest; } } - - [Intrinsic] - internal static void WriteBarrier(ref object? dst, object? obj) => dst = obj; } } From 2731fb3b628bfe4d1d4bdbc0c20c9e560196409a Mon Sep 17 00:00:00 2001 From: Egor Bogatov Date: Fri, 5 Sep 2025 13:21:46 +0200 Subject: [PATCH 11/11] Update src/coreclr/jit/importercalls.cpp Co-authored-by: Jakob Botsch Nielsen --- src/coreclr/jit/importercalls.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coreclr/jit/importercalls.cpp b/src/coreclr/jit/importercalls.cpp index e14ac2e6f02d94..1a4057e79c366c 100644 --- a/src/coreclr/jit/importercalls.cpp +++ b/src/coreclr/jit/importercalls.cpp @@ -7937,7 +7937,7 @@ void Compiler::impConvertToUserCallAndMarkForInlining(GenTreeCall* call) #if DEBUG CORINFO_METHOD_HANDLE existingValue = NO_METHOD_HANDLE; - if (impInlineRoot()->GetHelperToManagedMap()->Lookup(helperCallHnd, &existingValue)) + if (impInlineRoot()->HelperToManagedMapLookup(helperCallHnd, &existingValue)) { // Let's make sure HelperToManagedMap::Overwrite behavior always overwrites the same value. assert(existingValue == managedCallHnd);