From 262c43c4a22ead56d23ca44ace37c961ca613145 Mon Sep 17 00:00:00 2001 From: EgorBo Date: Sat, 2 Dec 2023 16:09:34 +0100 Subject: [PATCH] new helper --- docs/design/coreclr/botr/readytorun-format.md | 1 + src/coreclr/inc/corinfo.h | 1 + src/coreclr/inc/jiteeversionguid.h | 10 +++++----- src/coreclr/inc/jithelpers.h | 1 + src/coreclr/inc/readytorun.h | 4 +++- src/coreclr/inc/readytorunhelpers.h | 1 + src/coreclr/jit/codegenarmarch.cpp | 6 ++++-- src/coreclr/jit/codegenlinear.cpp | 5 ++++- src/coreclr/jit/codegenloongarch64.cpp | 6 ++++-- src/coreclr/jit/codegenriscv64.cpp | 6 ++++-- src/coreclr/jit/codegenxarch.cpp | 7 ++++--- src/coreclr/jit/gentree.h | 2 -- src/coreclr/jit/optimizer.cpp | 1 + .../Runtime.Base/src/System/Runtime/RuntimeExports.cs | 11 +++++++++++ .../tools/Common/Internal/Runtime/ModuleHeaders.cs | 2 +- .../Common/Internal/Runtime/ReadyToRunConstants.cs | 1 + .../tools/Common/JitInterface/CorInfoHelpFunc.cs | 1 + .../aot/ILCompiler.Compiler/Compiler/JitHelper.cs | 3 +++ .../JitInterface/CorInfoImpl.ReadyToRun.cs | 3 +++ .../ReadyToRunSignature.cs | 3 +++ .../JitInterface/CorInfoImpl.RyuJit.cs | 3 +++ src/coreclr/vm/jithelpers.cpp | 10 ++++++++++ 22 files changed, 69 insertions(+), 19 deletions(-) diff --git a/docs/design/coreclr/botr/readytorun-format.md b/docs/design/coreclr/botr/readytorun-format.md index a9a5c8b916303..8f98903d60c1e 100644 --- a/docs/design/coreclr/botr/readytorun-format.md +++ b/docs/design/coreclr/botr/readytorun-format.md @@ -903,6 +903,7 @@ enum ReadyToRunHelper // JIT32 x86-specific exception handling READYTORUN_HELPER_EndCatch = 0x110, + READYTORUN_HELPER_MemSetGc = 0x115, }; ``` diff --git a/src/coreclr/inc/corinfo.h b/src/coreclr/inc/corinfo.h index 4941bf56f7d68..551fafea7ca89 100644 --- a/src/coreclr/inc/corinfo.h +++ b/src/coreclr/inc/corinfo.h @@ -572,6 +572,7 @@ enum CorInfoHelpFunc CORINFO_HELP_INIT_PINVOKE_FRAME, // initialize an inlined PInvoke Frame for the JIT-compiler CORINFO_HELP_MEMSET, // Init block of memory + CORINFO_HELP_MEMSET_GC, // Init block of memory (with GC pointers) CORINFO_HELP_MEMCPY, // Copy block of memory CORINFO_HELP_RUNTIMEHANDLE_METHOD, // determine a type/field/method handle at run-time diff --git a/src/coreclr/inc/jiteeversionguid.h b/src/coreclr/inc/jiteeversionguid.h index 139ec31efae5d..a21e991b24f0e 100644 --- a/src/coreclr/inc/jiteeversionguid.h +++ b/src/coreclr/inc/jiteeversionguid.h @@ -43,11 +43,11 @@ typedef const GUID *LPCGUID; #define GUID_DEFINED #endif // !GUID_DEFINED -constexpr GUID JITEEVersionIdentifier = { /* e15e62ce-d9c6-418a-a5a7-26ad17fcf4bf */ - 0xe15e62ce, - 0xd9c6, - 0x418a, - {0xa5, 0xa7, 0x26, 0xad, 0x17, 0xfc, 0xf4, 0xbf} +constexpr GUID JITEEVersionIdentifier = { /* 315a2753-6b4e-4b31-b8b0-c1b9b53ba8f6 */ + 0x315a2753, + 0x6b4e, + 0x4b31, + {0xb8, 0xb0, 0xc1, 0xb9, 0xb5, 0x3b, 0xa8, 0xf6} }; ////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/coreclr/inc/jithelpers.h b/src/coreclr/inc/jithelpers.h index 06d09a1b5e15a..d91738b7d3d43 100644 --- a/src/coreclr/inc/jithelpers.h +++ b/src/coreclr/inc/jithelpers.h @@ -240,6 +240,7 @@ JITHELPER(CORINFO_HELP_MEMCPY, NULL, CORINFO_HELP_SIG_CANNOT_USE_ALIGN_STUB) #else JITHELPER(CORINFO_HELP_MEMSET, JIT_MemSet, CORINFO_HELP_SIG_REG_ONLY) + JITHELPER(CORINFO_HELP_MEMSET_GC, JIT_MemSetGc, CORINFO_HELP_SIG_REG_ONLY) JITHELPER(CORINFO_HELP_MEMCPY, JIT_MemCpy, CORINFO_HELP_SIG_REG_ONLY) #endif diff --git a/src/coreclr/inc/readytorun.h b/src/coreclr/inc/readytorun.h index 3e5e4ff500847..4c39cdc673c96 100644 --- a/src/coreclr/inc/readytorun.h +++ b/src/coreclr/inc/readytorun.h @@ -18,7 +18,7 @@ // src/coreclr/tools/Common/Internal/Runtime/ModuleHeaders.cs // src/coreclr/nativeaot/Runtime/inc/ModuleHeaders.h #define READYTORUN_MAJOR_VERSION 0x0009 -#define READYTORUN_MINOR_VERSION 0x0001 +#define READYTORUN_MINOR_VERSION 0x0002 #define MINIMUM_READYTORUN_MAJOR_VERSION 0x009 @@ -31,6 +31,7 @@ // R2R Version 8.0 Changes the alignment of the Int128 type // R2R Version 9.0 adds support for the Vector512 type // R2R Version 9.1 adds new helpers to allocate objects on frozen segments +// R2R Version 9.2 adds GC-aware memset helper struct READYTORUN_CORE_HEADER { @@ -439,6 +440,7 @@ enum ReadyToRunHelper // Array helpers for use with native ints READYTORUN_HELPER_Stelem_Ref_I = 0x113, READYTORUN_HELPER_Ldelema_Ref_I = 0x114, + READYTORUN_HELPER_MemSetGc = 0x115, }; #include "readytoruninstructionset.h" diff --git a/src/coreclr/inc/readytorunhelpers.h b/src/coreclr/inc/readytorunhelpers.h index 8691f9b9cb8c0..287201afe5fcf 100644 --- a/src/coreclr/inc/readytorunhelpers.h +++ b/src/coreclr/inc/readytorunhelpers.h @@ -29,6 +29,7 @@ HELPER(READYTORUN_HELPER_Stelem_Ref, CORINFO_HELP_ARRADDR_ST, HELPER(READYTORUN_HELPER_Ldelema_Ref, CORINFO_HELP_LDELEMA_REF, ) HELPER(READYTORUN_HELPER_MemSet, CORINFO_HELP_MEMSET, ) +HELPER(READYTORUN_HELPER_MemSetGc, CORINFO_HELP_MEMSET_GC, ) HELPER(READYTORUN_HELPER_MemCpy, CORINFO_HELP_MEMCPY, ) HELPER(READYTORUN_HELPER_LogMethodEnter, CORINFO_HELP_BBT_FCN_ENTER, ) diff --git a/src/coreclr/jit/codegenarmarch.cpp b/src/coreclr/jit/codegenarmarch.cpp index 60c6e65bbea6f..79159d90376b0 100644 --- a/src/coreclr/jit/codegenarmarch.cpp +++ b/src/coreclr/jit/codegenarmarch.cpp @@ -3232,7 +3232,9 @@ void CodeGen::genCodeForInitBlkHelper(GenTreeBlk* initBlkNode) { // Size goes in arg2, source address goes in arg1, and size goes in arg2. // genConsumeBlockOp takes care of this for us. - genConsumeBlockOp(initBlkNode, REG_ARG_0, REG_ARG_1, REG_ARG_2); + // NOTE: CORINFO_HELP_MEMSET_GC only zeroes memory so it doesn't need source arg. + const bool gcAware = initBlkNode->IsOnHeapAndContainsReferences(); + genConsumeBlockOp(initBlkNode, REG_ARG_0, gcAware ? REG_NA : REG_ARG_1, REG_ARG_2); if (initBlkNode->IsVolatile()) { @@ -3240,7 +3242,7 @@ void CodeGen::genCodeForInitBlkHelper(GenTreeBlk* initBlkNode) instGen_MemoryBarrier(); } - genEmitHelperCall(CORINFO_HELP_MEMSET, 0, EA_UNKNOWN); + genEmitHelperCall(gcAware ? CORINFO_HELP_MEMSET_GC : CORINFO_HELP_MEMSET, 0, EA_UNKNOWN); } //------------------------------------------------------------------------ diff --git a/src/coreclr/jit/codegenlinear.cpp b/src/coreclr/jit/codegenlinear.cpp index ab62d35e6e85c..99052d6a996ec 100644 --- a/src/coreclr/jit/codegenlinear.cpp +++ b/src/coreclr/jit/codegenlinear.cpp @@ -2050,7 +2050,10 @@ void CodeGen::genConsumeBlockOp(GenTreeBlk* blkNode, regNumber dstReg, regNumber // Next, perform any necessary moves. genCopyRegIfNeeded(dstAddr, dstReg); - genSetBlockSrc(blkNode, srcReg); + if (srcReg != REG_NA) + { + genSetBlockSrc(blkNode, srcReg); + } genSetBlockSize(blkNode, sizeReg); } diff --git a/src/coreclr/jit/codegenloongarch64.cpp b/src/coreclr/jit/codegenloongarch64.cpp index 44edc3fae0fee..28d2ee38d165b 100644 --- a/src/coreclr/jit/codegenloongarch64.cpp +++ b/src/coreclr/jit/codegenloongarch64.cpp @@ -6375,7 +6375,9 @@ void CodeGen::genCodeForInitBlkHelper(GenTreeBlk* initBlkNode) { // Size goes in arg2, source address goes in arg1, and size goes in arg2. // genConsumeBlockOp takes care of this for us. - genConsumeBlockOp(initBlkNode, REG_ARG_0, REG_ARG_1, REG_ARG_2); + // NOTE: CORINFO_HELP_MEMSET_GC only zeroes memory so it doesn't need source arg. + const bool gcAware = initBlkNode->IsOnHeapAndContainsReferences(); + genConsumeBlockOp(initBlkNode, REG_ARG_0, gcAware ? REG_NA : REG_ARG_1, REG_ARG_2); if (initBlkNode->IsVolatile()) { @@ -6383,7 +6385,7 @@ void CodeGen::genCodeForInitBlkHelper(GenTreeBlk* initBlkNode) instGen_MemoryBarrier(); } - genEmitHelperCall(CORINFO_HELP_MEMSET, 0, EA_UNKNOWN); + genEmitHelperCall(gcAware ? CORINFO_HELP_MEMSET_GC : CORINFO_HELP_MEMSET, 0, EA_UNKNOWN); } // Generate code for a load from some address + offset diff --git a/src/coreclr/jit/codegenriscv64.cpp b/src/coreclr/jit/codegenriscv64.cpp index c2dafce1fb0a6..ba308626d3d21 100644 --- a/src/coreclr/jit/codegenriscv64.cpp +++ b/src/coreclr/jit/codegenriscv64.cpp @@ -6073,7 +6073,9 @@ void CodeGen::genCodeForInitBlkHelper(GenTreeBlk* initBlkNode) { // Size goes in arg2, source address goes in arg1, and size goes in arg2. // genConsumeBlockOp takes care of this for us. - genConsumeBlockOp(initBlkNode, REG_ARG_0, REG_ARG_1, REG_ARG_2); + // NOTE: CORINFO_HELP_MEMSET_GC only zeroes memory so it doesn't need source arg. + const bool gcAware = initBlkNode->IsOnHeapAndContainsReferences(); + genConsumeBlockOp(initBlkNode, REG_ARG_0, gcAware ? REG_NA : REG_ARG_1, REG_ARG_2); if (initBlkNode->IsVolatile()) { @@ -6081,7 +6083,7 @@ void CodeGen::genCodeForInitBlkHelper(GenTreeBlk* initBlkNode) instGen_MemoryBarrier(); } - genEmitHelperCall(CORINFO_HELP_MEMSET, 0, EA_UNKNOWN); + genEmitHelperCall(gcAware ? CORINFO_HELP_MEMSET_GC : CORINFO_HELP_MEMSET, 0, EA_UNKNOWN); } //------------------------------------------------------------------------ diff --git a/src/coreclr/jit/codegenxarch.cpp b/src/coreclr/jit/codegenxarch.cpp index 06a44d4b3158a..e973b111f6d70 100644 --- a/src/coreclr/jit/codegenxarch.cpp +++ b/src/coreclr/jit/codegenxarch.cpp @@ -3326,9 +3326,10 @@ void CodeGen::genCodeForInitBlkHelper(GenTreeBlk* initBlkNode) { // Destination address goes in arg0, source address goes in arg1, and size goes in arg2. // genConsumeBlockOp takes care of this for us. - genConsumeBlockOp(initBlkNode, REG_ARG_0, REG_ARG_1, REG_ARG_2); - - genEmitHelperCall(CORINFO_HELP_MEMSET, 0, EA_UNKNOWN); + // NOTE: CORINFO_HELP_MEMSET_GC only zeroes memory so it doesn't need source arg. + const bool gcAware = initBlkNode->IsOnHeapAndContainsReferences(); + genConsumeBlockOp(initBlkNode, REG_ARG_0, gcAware ? REG_NA : REG_ARG_1, REG_ARG_2); + genEmitHelperCall(gcAware ? CORINFO_HELP_MEMSET_GC : CORINFO_HELP_MEMSET, 0, EA_UNKNOWN); } #endif // TARGET_AMD64 diff --git a/src/coreclr/jit/gentree.h b/src/coreclr/jit/gentree.h index ceb7399766384..74686c82756f3 100644 --- a/src/coreclr/jit/gentree.h +++ b/src/coreclr/jit/gentree.h @@ -7337,12 +7337,10 @@ struct GenTreeBlk : public GenTreeIndir bool gtBlkOpGcUnsafe; #endif -#ifdef TARGET_XARCH bool IsOnHeapAndContainsReferences() { return (m_layout != nullptr) && m_layout->HasGCPtr() && !Addr()->OperIs(GT_LCL_ADDR); } -#endif GenTreeBlk(genTreeOps oper, var_types type, GenTree* addr, ClassLayout* layout) : GenTreeIndir(oper, type, addr, nullptr) diff --git a/src/coreclr/jit/optimizer.cpp b/src/coreclr/jit/optimizer.cpp index d8c461188cc68..448bf35e8cb3c 100644 --- a/src/coreclr/jit/optimizer.cpp +++ b/src/coreclr/jit/optimizer.cpp @@ -5577,6 +5577,7 @@ PhaseStatus Compiler::optFindLoopsPhase() case CORINFO_HELP_ASSIGN_STRUCT: // Not strictly needed as we don't use this case CORINFO_HELP_MEMSET: // Not strictly needed as we don't make a GT_CALL with this + case CORINFO_HELP_MEMSET_GC: // Not strictly needed as we don't make a GT_CALL with this case CORINFO_HELP_MEMCPY: // Not strictly needed as we don't make a GT_CALL with this case CORINFO_HELP_SETFIELDSTRUCT: diff --git a/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/RuntimeExports.cs b/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/RuntimeExports.cs index b1092eb2aca6d..c3e3f945a3fc5 100644 --- a/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/RuntimeExports.cs +++ b/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/RuntimeExports.cs @@ -278,6 +278,17 @@ public static unsafe void RhUnbox(object? obj, ref byte data, MethodTable* pUnbo } } + [RuntimeExport("MemSetGc")] + public static unsafe void MemSetGc(nuint* dest, nuint size) + { + nuint numOfPointers = size / (nuint)sizeof(nuint); + Debug.Assert(size % (nuint)sizeof(nuint) == 0); + for (nuint i = 0; i < numOfPointers; i++) + { + dest[i] = 0; + } + } + [RuntimeExport("RhGetCurrentThreadStackTrace")] [MethodImpl(MethodImplOptions.NoInlining)] // Ensures that the RhGetCurrentThreadStackTrace frame is always present public static unsafe int RhGetCurrentThreadStackTrace(IntPtr[] outputBuffer) diff --git a/src/coreclr/tools/Common/Internal/Runtime/ModuleHeaders.cs b/src/coreclr/tools/Common/Internal/Runtime/ModuleHeaders.cs index 48cbf5f7518f9..bf694b29e0002 100644 --- a/src/coreclr/tools/Common/Internal/Runtime/ModuleHeaders.cs +++ b/src/coreclr/tools/Common/Internal/Runtime/ModuleHeaders.cs @@ -16,7 +16,7 @@ internal struct ReadyToRunHeaderConstants public const uint Signature = 0x00525452; // 'RTR' public const ushort CurrentMajorVersion = 9; - public const ushort CurrentMinorVersion = 1; + public const ushort CurrentMinorVersion = 2; } #if READYTORUN #pragma warning disable 0169 diff --git a/src/coreclr/tools/Common/Internal/Runtime/ReadyToRunConstants.cs b/src/coreclr/tools/Common/Internal/Runtime/ReadyToRunConstants.cs index 63383b7ddfa67..919ef982fca92 100644 --- a/src/coreclr/tools/Common/Internal/Runtime/ReadyToRunConstants.cs +++ b/src/coreclr/tools/Common/Internal/Runtime/ReadyToRunConstants.cs @@ -344,6 +344,7 @@ public enum ReadyToRunHelper StackProbe = 0x111, GetCurrentManagedThreadId = 0x112, + MemSetGc = 0x115, // ********************************************************************************************** // diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoHelpFunc.cs b/src/coreclr/tools/Common/JitInterface/CorInfoHelpFunc.cs index 7837e8c24f832..95ce234e15660 100644 --- a/src/coreclr/tools/Common/JitInterface/CorInfoHelpFunc.cs +++ b/src/coreclr/tools/Common/JitInterface/CorInfoHelpFunc.cs @@ -214,6 +214,7 @@ public enum CorInfoHelpFunc CORINFO_HELP_INIT_PINVOKE_FRAME, // initialize an inlined PInvoke Frame for the JIT-compiler CORINFO_HELP_MEMSET, // Init block of memory + CORINFO_HELP_MEMSET_GC, // Init block of memory (with GC pointers) CORINFO_HELP_MEMCPY, // Copy block of memory CORINFO_HELP_RUNTIMEHANDLE_METHOD, // determine a type/field/method handle at run-time diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/JitHelper.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/JitHelper.cs index 1eed47ef13838..6d0c661309bfe 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/JitHelper.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/JitHelper.cs @@ -121,6 +121,9 @@ public static void GetEntryPoint(TypeSystemContext context, ReadyToRunHelper id, case ReadyToRunHelper.MemSet: mangledName = "memset"; // TODO: Null reference handling break; + case ReadyToRunHelper.MemSetGc: + mangledName = "MemSetGc"; + break; case ReadyToRunHelper.GetRuntimeTypeHandle: methodDesc = context.GetHelperEntryPoint("LdTokenHelpers", "GetRuntimeTypeHandle"); diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs index 2d246d6b30df9..44e9124cf5cf0 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs @@ -1028,6 +1028,9 @@ private ISymbolNode GetHelperFtnUncached(CorInfoHelpFunc ftnNum) case CorInfoHelpFunc.CORINFO_HELP_MEMSET: id = ReadyToRunHelper.MemSet; break; + case CorInfoHelpFunc.CORINFO_HELP_MEMSET_GC: + id = ReadyToRunHelper.MemSetGc; + break; case CorInfoHelpFunc.CORINFO_HELP_MEMCPY: id = ReadyToRunHelper.MemCpy; break; diff --git a/src/coreclr/tools/aot/ILCompiler.Reflection.ReadyToRun/ReadyToRunSignature.cs b/src/coreclr/tools/aot/ILCompiler.Reflection.ReadyToRun/ReadyToRunSignature.cs index 8d325f467d600..ec40d99b5e4d8 100644 --- a/src/coreclr/tools/aot/ILCompiler.Reflection.ReadyToRun/ReadyToRunSignature.cs +++ b/src/coreclr/tools/aot/ILCompiler.Reflection.ReadyToRun/ReadyToRunSignature.cs @@ -1684,6 +1684,9 @@ private void ParseHelper(StringBuilder builder) case ReadyToRunHelper.MemSet: builder.Append("MEM_SET"); break; + case ReadyToRunHelper.MemSetGc: + builder.Append("MEM_SET_GC"); + break; case ReadyToRunHelper.MemCpy: builder.Append("MEM_CPY"); diff --git a/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs b/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs index eb988b0b604f8..196d3a5386c43 100644 --- a/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs +++ b/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs @@ -524,6 +524,9 @@ private ISymbolNode GetHelperFtnUncached(CorInfoHelpFunc ftnNum) case CorInfoHelpFunc.CORINFO_HELP_MEMSET: id = ReadyToRunHelper.MemSet; break; + case CorInfoHelpFunc.CORINFO_HELP_MEMSET_GC: + id = ReadyToRunHelper.MemSetGc; + break; case CorInfoHelpFunc.CORINFO_HELP_MEMCPY: id = ReadyToRunHelper.MemCpy; break; diff --git a/src/coreclr/vm/jithelpers.cpp b/src/coreclr/vm/jithelpers.cpp index 084da1007a9de..0e7fa5570aabf 100644 --- a/src/coreclr/vm/jithelpers.cpp +++ b/src/coreclr/vm/jithelpers.cpp @@ -5114,6 +5114,16 @@ FCIMPL0(INT32, JIT_GetCurrentManagedThreadId) } FCIMPLEND +HCIMPL2(void, JIT_MemSetGc, intptr_t* dest, size_t count) +{ + const size_t numOfPointers = count / sizeof(intptr_t); + _ASSERT(count % sizeof(intptr_t) == 0); + for (size_t i = 0; i < numOfPointers; i++) + { + dest[i] = 0; + } +} +HCIMPLEND /*********************************************************************/ /* we don't use HCIMPL macros because we don't want the overhead even in debug mode */