From 4dadf328f6007d510ddcf6d416af2f9359738399 Mon Sep 17 00:00:00 2001 From: vsadov <8218165+VSadov@users.noreply.github.com> Date: Tue, 4 Apr 2023 09:52:17 -0700 Subject: [PATCH 1/2] Remove unused (and in some cases broken) RhpCopy helpers. --- .../src/System/Runtime/InternalCalls.cs | 2 +- .../src/System/Runtime/RuntimeExports.cs | 1 - src/coreclr/nativeaot/Runtime/EHHelpers.cpp | 8 - .../nativeaot/Runtime/GCMemoryHelpers.cpp | 84 +-------- .../nativeaot/Runtime/GCMemoryHelpers.h | 2 - .../nativeaot/Runtime/amd64/MiscStubs.asm | 142 -------------- .../nativeaot/Runtime/arm/MiscStubs.asm | 146 --------------- .../nativeaot/Runtime/arm64/MiscStubs.S | 145 --------------- .../nativeaot/Runtime/arm64/MiscStubs.asm | 146 --------------- .../nativeaot/Runtime/i386/MiscStubs.asm | 174 ------------------ 10 files changed, 3 insertions(+), 847 deletions(-) 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 e7058119cb7f4..7d4bb10ef9a19 100644 --- a/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/InternalCalls.cs +++ b/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/InternalCalls.cs @@ -156,7 +156,7 @@ internal static int RhEndNoGCRegion() [MethodImplAttribute(MethodImplOptions.InternalCall)] [RuntimeImport(Redhawk.BaseName, "RhpInitMultibyte")] - internal static extern unsafe ref byte RhpInitMultibyte(ref byte dmem, int c, nuint size); + internal static extern unsafe ref byte RhpInitMultibyte(ref byte dmem, nuint size); [MethodImplAttribute(MethodImplOptions.InternalCall)] [RuntimeImport(Redhawk.BaseName, "memmove")] 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 da166f2dd2f8a..dd2f10bc117e5 100644 --- a/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/RuntimeExports.cs +++ b/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/RuntimeExports.cs @@ -236,7 +236,6 @@ public static unsafe void RhUnbox(object? obj, ref byte data, MethodTable* pUnbo // Set HasValue to false and clear the value (in case there were GC references we wish to stop reporting). InternalCalls.RhpInitMultibyte( ref data, - 0, pUnboxToEEType->ValueTypeSize); return; diff --git a/src/coreclr/nativeaot/Runtime/EHHelpers.cpp b/src/coreclr/nativeaot/Runtime/EHHelpers.cpp index b25beb3bb0c58..37d593b6c7afc 100644 --- a/src/coreclr/nativeaot/Runtime/EHHelpers.cpp +++ b/src/coreclr/nativeaot/Runtime/EHHelpers.cpp @@ -286,14 +286,6 @@ EXTERN_C void * RhpCheckedLockCmpXchgAVLocation; EXTERN_C void * RhpCheckedXchgAVLocation; EXTERN_C void * RhpLockCmpXchg32AVLocation; EXTERN_C void * RhpLockCmpXchg64AVLocation; -EXTERN_C void * RhpCopyMultibyteDestAVLocation; -EXTERN_C void * RhpCopyMultibyteSrcAVLocation; -EXTERN_C void * RhpCopyMultibyteNoGCRefsDestAVLocation; -EXTERN_C void * RhpCopyMultibyteNoGCRefsSrcAVLocation; -EXTERN_C void * RhpCopyMultibyteWithWriteBarrierDestAVLocation; -EXTERN_C void * RhpCopyMultibyteWithWriteBarrierSrcAVLocation; -EXTERN_C void * RhpCopyAnyWithWriteBarrierDestAVLocation; -EXTERN_C void * RhpCopyAnyWithWriteBarrierSrcAVLocation; static bool InWriteBarrierHelper(uintptr_t faultingIP) { diff --git a/src/coreclr/nativeaot/Runtime/GCMemoryHelpers.cpp b/src/coreclr/nativeaot/Runtime/GCMemoryHelpers.cpp index 15dc03a9bbceb..95d9c77d23b7b 100644 --- a/src/coreclr/nativeaot/Runtime/GCMemoryHelpers.cpp +++ b/src/coreclr/nativeaot/Runtime/GCMemoryHelpers.cpp @@ -21,91 +21,17 @@ // // USAGE: The caller is responsible for hoisting any null reference exceptions to a place where the hardware exception // can be properly translated to a managed exception. -COOP_PINVOKE_CDECL_HELPER(void *, RhpInitMultibyte, (void * mem, int c, size_t size)) +COOP_PINVOKE_CDECL_HELPER(void *, RhpInitMultibyte, (void * mem, size_t size)) { // The caller must do the null-check because we cannot take an AV in the runtime and translate it to managed. ASSERT(mem != nullptr); - uintptr_t bv = (uint8_t)c; - uintptr_t pv = 0; - - if (bv != 0) - { - pv = -#if (POINTER_SIZE == 8) - bv << 7*8 | bv << 6*8 | bv << 5*8 | bv << 4*8 | -#endif - bv << 3*8 | bv << 2*8 | bv << 1*8 | bv; - } - - InlineGCSafeFillMemory(mem, size, pv); + InlineGCSafeFillMemory(mem, size, 0); // memset returns the destination buffer return mem; } - -// This is a GC-safe variant of memcpy. It guarantees that the object references in the GC heap are updated atomically. -// This is required for type safety and proper operation of the background GC. -// -// USAGE: 1) The caller is responsible for performing the appropriate bulk write barrier. -// 2) The caller is responsible for hoisting any null reference exceptions to a place where the hardware -// exception can be properly translated to a managed exception. This is handled by RhpCopyMultibyte. -// 3) The caller must ensure that all three parameters are pointer-size-aligned. This should be the case for -// value types which contain GC refs anyway, so if you want to copy structs without GC refs which might be -// unaligned, then you must use RhpCopyMultibyteNoGCRefs. -COOP_PINVOKE_CDECL_HELPER(void *, memcpyGCRefs, (void * dest, const void *src, size_t len)) -{ - // null pointers are not allowed (they are checked by RhpCopyMultibyte) - ASSERT(dest != nullptr); - ASSERT(src != nullptr); - - InlineForwardGCSafeCopy(dest, src, len); - - // memcpy returns the destination buffer - return dest; -} - -// This is a GC-safe variant of memcpy. It guarantees that the object references in the GC heap are updated atomically. -// This is required for type safety and proper operation of the background GC. -// Writebarrier is included. -// -// USAGE: -// 1) The caller is responsible for hoisting any null reference exceptions to a place where the hardware -// exception can be properly translated to a managed exception. This is handled by RhpCopyMultibyte. -// 2) The caller must ensure that all three parameters are pointer-size-aligned. This should be the case for -// value types which contain GC refs anyway, so if you want to copy structs without GC refs which might be -// unaligned, then you must use RhpCopyMultibyteNoGCRefs. -COOP_PINVOKE_CDECL_HELPER(void *, memcpyGCRefsWithWriteBarrier, (void * dest, const void *src, size_t len)) -{ - // null pointers are not allowed (they are checked by RhpCopyMultibyteWithWriteBarrier) - ASSERT(dest != nullptr); - ASSERT(src != nullptr); - - InlineForwardGCSafeCopy(dest, src, len); - InlinedBulkWriteBarrier(dest, len); - - // memcpy returns the destination buffer - return dest; -} - -// Same as memcpyGCRefsWithWriteBarrier, except it checks if memory might contain GC pointers -// and if so dispatches to memcpyGCRefsWithWriteBarrier and if not uses traditional memcpy -COOP_PINVOKE_CDECL_HELPER(void *, memcpyAnyWithWriteBarrier, (void * dest, const void *src, size_t len)) -{ - // null pointers are not allowed (they are checked by RhpCopyMultibyteWithWriteBarrier) - ASSERT(dest != nullptr); - ASSERT(src != nullptr); - - // Use GC safe copy whenever there might be GC pointers - if (IS_ALIGNED(dest, sizeof(size_t)) && IS_ALIGNED(src, sizeof(size_t)) && IS_ALIGNED(len, sizeof(size_t))) - { - return memcpyGCRefsWithWriteBarrier(dest, src, len); - } - - return memcpy(dest, src, len); -} - // Move memory, in a way that is compatible with a move onto the heap, but // does not require the destination pointer to be on the heap. @@ -119,12 +45,6 @@ COOP_PINVOKE_HELPER(void, RhBulkMoveWithWriteBarrier, (uint8_t* pDest, uint8_t* InlinedBulkWriteBarrier(pDest, cbDest); } -void GCSafeCopyMemoryWithWriteBarrier(void * dest, const void *src, size_t len) -{ - InlineForwardGCSafeCopy(dest, src, len); - InlinedBulkWriteBarrier(dest, len); -} - void REDHAWK_CALLCONV RhpBulkWriteBarrier(void* pMemStart, uint32_t cbMemSize) { InlinedBulkWriteBarrier(pMemStart, cbMemSize); diff --git a/src/coreclr/nativeaot/Runtime/GCMemoryHelpers.h b/src/coreclr/nativeaot/Runtime/GCMemoryHelpers.h index 8f1d9cf8c23c5..127b4d772040a 100644 --- a/src/coreclr/nativeaot/Runtime/GCMemoryHelpers.h +++ b/src/coreclr/nativeaot/Runtime/GCMemoryHelpers.h @@ -5,6 +5,4 @@ // Unmanaged GC memory helpers // -void GCSafeCopyMemoryWithWriteBarrier(void * dest, const void *src, size_t len); - EXTERN_C void REDHAWK_CALLCONV RhpBulkWriteBarrier(void* pMemStart, uint32_t cbMemSize); diff --git a/src/coreclr/nativeaot/Runtime/amd64/MiscStubs.asm b/src/coreclr/nativeaot/Runtime/amd64/MiscStubs.asm index 429ace3d84fd5..9f11b73c4444d 100644 --- a/src/coreclr/nativeaot/Runtime/amd64/MiscStubs.asm +++ b/src/coreclr/nativeaot/Runtime/amd64/MiscStubs.asm @@ -3,150 +3,8 @@ include AsmMacros.inc -EXTERN memcpy : PROC -EXTERN memcpyGCRefs : PROC -EXTERN memcpyGCRefsWithWriteBarrier : PROC -EXTERN memcpyAnyWithWriteBarrier : PROC EXTERN RhpGetThreadStaticBaseForTypeSlow : PROC -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; -;; void* RhpCopyMultibyteNoGCRefs(void*, void*, size_t) -;; -;; The purpose of this wrapper is to hoist the potential null reference exceptions of copying memory up to a place where -;; the stack unwinder and exception dispatch can properly transform the exception into a managed exception and dispatch -;; it to managed code. -;; -LEAF_ENTRY RhpCopyMultibyteNoGCRefs, _TEXT - - ; rcx dest - ; rdx src - ; r8 count - - test r8, r8 ; check for a zero-length copy - jz NothingToCopy - - ; Now check the dest and src pointers. If they AV, the EH subsystem will recognize the address of the AV, - ; unwind the frame, and fixup the stack to make it look like the (managed) caller AV'ed, which will be - ; translated to a managed exception as usual. -ALTERNATE_ENTRY RhpCopyMultibyteNoGCRefsDestAVLocation - cmp byte ptr [rcx], 0 -ALTERNATE_ENTRY RhpCopyMultibyteNoGCRefsSrcAVLocation - cmp byte ptr [rdx], 0 - - ; tail-call to plain-old-memcpy - jmp memcpy - -NothingToCopy: - mov rax, rcx ; return dest - ret - -LEAF_END RhpCopyMultibyteNoGCRefs, _TEXT - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; -;; void* RhpCopyMultibyte(void*, void*, size_t) -;; -;; The purpose of this wrapper is to hoist the potential null reference exceptions of copying memory up to a place where -;; the stack unwinder and exception dispatch can properly transform the exception into a managed exception and dispatch -;; it to managed code. -;; -LEAF_ENTRY RhpCopyMultibyte, _TEXT - - ; rcx dest - ; rdx src - ; r8 count - - test r8, r8 ; check for a zero-length copy - jz NothingToCopy - - ; Now check the dest and src pointers. If they AV, the EH subsystem will recognize the address of the AV, - ; unwind the frame, and fixup the stack to make it look like the (managed) caller AV'ed, which will be - ; translated to a managed exception as usual. -ALTERNATE_ENTRY RhpCopyMultibyteDestAVLocation - cmp byte ptr [rcx], 0 -ALTERNATE_ENTRY RhpCopyMultibyteSrcAVLocation - cmp byte ptr [rdx], 0 - - ; tail-call to the GC-safe memcpy implementation - jmp memcpyGCRefs - -NothingToCopy: - mov rax, rcx ; return dest - ret - -LEAF_END RhpCopyMultibyte, _TEXT - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; -;; void* RhpCopyMultibyteWithWriteBarrier(void*, void*, size_t) -;; -;; The purpose of this wrapper is to hoist the potential null reference exceptions of copying memory up to a place where -;; the stack unwinder and exception dispatch can properly transform the exception into a managed exception and dispatch -;; it to managed code. -;; Runs a card table update via RhpBulkWriteBarrier after the copy -;; -LEAF_ENTRY RhpCopyMultibyteWithWriteBarrier, _TEXT - - ; rcx dest - ; rdx src - ; r8 count - - test r8, r8 ; check for a zero-length copy - jz NothingToCopy - - ; Now check the dest and src pointers. If they AV, the EH subsystem will recognize the address of the AV, - ; unwind the frame, and fixup the stack to make it look like the (managed) caller AV'ed, which will be - ; translated to a managed exception as usual. -ALTERNATE_ENTRY RhpCopyMultibyteWithWriteBarrierDestAVLocation - cmp byte ptr [rcx], 0 -ALTERNATE_ENTRY RhpCopyMultibyteWithWriteBarrierSrcAVLocation - cmp byte ptr [rdx], 0 - - ; tail-call to the GC-safe memcpy implementation - jmp memcpyGCRefsWithWriteBarrier - -NothingToCopy: - mov rax, rcx ; return dest - ret - -LEAF_END RhpCopyMultibyteWithWriteBarrier, _TEXT - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; -;; void* RhpCopyAnyWithWriteBarrier(void*, void*, size_t) -;; -;; The purpose of this wrapper is to hoist the potential null reference exceptions of copying memory up to a place where -;; the stack unwinder and exception dispatch can properly transform the exception into a managed exception and dispatch -;; it to managed code. -;; Runs a card table update via RhpBulkWriteBarrier after the copy if the copy may contain GC pointers -;; -LEAF_ENTRY RhpCopyAnyWithWriteBarrier, _TEXT - - ; rcx dest - ; rdx src - ; r8 count - - test r8, r8 ; check for a zero-length copy - jz NothingToCopy - - ; Now check the dest and src pointers. If they AV, the EH subsystem will recognize the address of the AV, - ; unwind the frame, and fixup the stack to make it look like the (managed) caller AV'ed, which will be - ; translated to a managed exception as usual. -ALTERNATE_ENTRY RhpCopyAnyWithWriteBarrierDestAVLocation - cmp byte ptr [rcx], 0 -ALTERNATE_ENTRY RhpCopyAnyWithWriteBarrierSrcAVLocation - cmp byte ptr [rdx], 0 - - ; tail-call to the GC-safe memcpy implementation - jmp memcpyAnyWithWriteBarrier - -NothingToCopy: - mov rax, rcx ; return dest - ret - -LEAF_END RhpCopyAnyWithWriteBarrier, _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/nativeaot/Runtime/arm/MiscStubs.asm b/src/coreclr/nativeaot/Runtime/arm/MiscStubs.asm index 9585ff2b7de94..cdb86ce1b4136 100644 --- a/src/coreclr/nativeaot/Runtime/arm/MiscStubs.asm +++ b/src/coreclr/nativeaot/Runtime/arm/MiscStubs.asm @@ -3,154 +3,8 @@ #include "AsmMacros.h" - EXTERN memcpy - EXTERN memcpyGCRefs - EXTERN memcpyGCRefsWithWriteBarrier - EXTERN memcpyAnyWithWriteBarrier - TEXTAREA -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; -;; void* RhpCopyMultibyteNoGCRefs(void*, void*, size_t) -;; -;; The purpose of this wrapper is to hoist the potential null reference exceptions of copying memory up to a place where -;; the stack unwinder and exception dispatch can properly transform the exception into a managed exception and dispatch -;; it to managed code. -;; - - LEAF_ENTRY RhpCopyMultibyteNoGCRefs - - ; r0 dest - ; r1 src - ; r2 count - - cmp r2, #0 ; check for a zero-length copy - beq NothingToCopy_NoGCRefs - - ; Now check the dest and src pointers. If they AV, the EH subsystem will recognize the address of the AV, - ; unwind the frame, and fixup the stack to make it look like the (managed) caller AV'ed, which will be - ; translated to a managed exception as usual. - ALTERNATE_ENTRY RhpCopyMultibyteNoGCRefsDestAVLocation - ldrb r3, [r0] - ALTERNATE_ENTRY RhpCopyMultibyteNoGCRefsSrcAVLocation - ldrb r3, [r1] - - ; tail-call to plain-old-memcpy - b memcpy - -NothingToCopy_NoGCRefs - ; dest is already still in r0 - bx lr - - LEAF_END - - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; -;; void* RhpCopyMultibyte(void*, void*, size_t) -;; -;; The purpose of this wrapper is to hoist the potential null reference exceptions of copying memory up to a place where -;; the stack unwinder and exception dispatch can properly transform the exception into a managed exception and dispatch -;; it to managed code. -;; - - LEAF_ENTRY RhpCopyMultibyte - - ; r0 dest - ; r1 src - ; r2 count - - cmp r2, #0 ; check for a zero-length copy - beq NothingToCopy_RhpCopyMultibyte - - ; Now check the dest and src pointers. If they AV, the EH subsystem will recognize the address of the AV, - ; unwind the frame, and fixup the stack to make it look like the (managed) caller AV'ed, which will be - ; translated to a managed exception as usual. - ALTERNATE_ENTRY RhpCopyMultibyteDestAVLocation - ldrb r3, [r0] - ALTERNATE_ENTRY RhpCopyMultibyteSrcAVLocation - ldrb r3, [r1] - - ; tail-call to the GC-safe memcpy implementation - b memcpyGCRefs - -NothingToCopy_RhpCopyMultibyte - ; dest is already still in r0 - bx lr - - LEAF_END - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; -;; void* RhpCopyMultibyteWithWriteBarrier(void*, void*, size_t) -;; -;; The purpose of this wrapper is to hoist the potential null reference exceptions of copying memory up to a place where -;; the stack unwinder and exception dispatch can properly transform the exception into a managed exception and dispatch -;; it to managed code. -;; Runs a card table update via RhpBulkWriteBarrier after the copy -;; - - LEAF_ENTRY RhpCopyMultibyteWithWriteBarrier - - ; r0 dest - ; r1 src - ; r2 count - - cmp r2, #0 ; check for a zero-length copy - beq NothingToCopy_RhpCopyMultibyteWithWriteBarrier - - ; Now check the dest and src pointers. If they AV, the EH subsystem will recognize the address of the AV, - ; unwind the frame, and fixup the stack to make it look like the (managed) caller AV'ed, which will be - ; translated to a managed exception as usual. - ALTERNATE_ENTRY RhpCopyMultibyteWithWriteBarrierDestAVLocation - ldrb r3, [r0] - ALTERNATE_ENTRY RhpCopyMultibyteWithWriteBarrierSrcAVLocation - ldrb r3, [r1] - - ; tail-call to the GC-safe memcpy implementation - b memcpyGCRefsWithWriteBarrier - -NothingToCopy_RhpCopyMultibyteWithWriteBarrier - ; dest is already still in r0 - bx lr - - LEAF_END - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; -;; void* RhpCopyAnyWithWriteBarrier(void*, void*, size_t) -;; -;; The purpose of this wrapper is to hoist the potential null reference exceptions of copying memory up to a place where -;; the stack unwinder and exception dispatch can properly transform the exception into a managed exception and dispatch -;; it to managed code. -;; Runs a card table update via RhpBulkWriteBarrier after the copy if it contained GC pointers -;; - - LEAF_ENTRY RhpCopyAnyWithWriteBarrier - - ; r0 dest - ; r1 src - ; r2 count - - cmp r2, #0 ; check for a zero-length copy - beq NothingToCopy_RhpCopyAnyWithWriteBarrier - - ; Now check the dest and src pointers. If they AV, the EH subsystem will recognize the address of the AV, - ; unwind the frame, and fixup the stack to make it look like the (managed) caller AV'ed, which will be - ; translated to a managed exception as usual. - ALTERNATE_ENTRY RhpCopyAnyWithWriteBarrierDestAVLocation - ldrb r3, [r0] - ALTERNATE_ENTRY RhpCopyAnyWithWriteBarrierSrcAVLocation - ldrb r3, [r1] - - ; tail-call to the GC-safe memcpy implementation - b memcpyAnyWithWriteBarrier - -NothingToCopy_RhpCopyAnyWithWriteBarrier - ; dest is already still in r0 - bx lr - LEAF_END end diff --git a/src/coreclr/nativeaot/Runtime/arm64/MiscStubs.S b/src/coreclr/nativeaot/Runtime/arm64/MiscStubs.S index 61ae4e4046c6b..fc1f6d465ca2d 100644 --- a/src/coreclr/nativeaot/Runtime/arm64/MiscStubs.S +++ b/src/coreclr/nativeaot/Runtime/arm64/MiscStubs.S @@ -4,148 +4,3 @@ #include #include "AsmOffsets.inc" - .global memcpy - .global memcpyGCRefs - .global memcpyGCRefsWithWriteBarrier - .global memcpyAnyWithWriteBarrier - -//;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -// -// void* RhpCopyMultibyteNoGCRefs(void*, void*, size_t) -// -// The purpose of this wrapper is to hoist the potential null reference exceptions of copying memory up to a place where -// the stack unwinder and exception dispatch can properly transform the exception into a managed exception and dispatch -// it to managed code. -// - - LEAF_ENTRY RhpCopyMultibyteNoGCRefs, _TEXT - - // x0 dest - // x1 src - // x2 count - - cbz x2, NothingToCopy_NoGCRefs // check for a zero-length copy - - // Now check the dest and src pointers. If they AV, the EH subsystem will recognize the address of the AV, - // unwind the frame, and fixup the stack to make it look like the (managed) caller AV'ed, which will be - // translated to a managed exception as usual. - ALTERNATE_ENTRY RhpCopyMultibyteNoGCRefsDestAVLocation - ldrb wzr, [x0] - ALTERNATE_ENTRY RhpCopyMultibyteNoGCRefsSrcAVLocation - ldrb wzr, [x1] - - // tail-call to plain-old-memcpy - b memcpy - -NothingToCopy_NoGCRefs: - // dest is already in x0 - ret - - LEAF_END RhpCopyMultibyteNoGCRefs, _TEXT - - -//;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -// -// void* RhpCopyMultibyte(void*, void*, size_t) -// -// The purpose of this wrapper is to hoist the potential null reference exceptions of copying memory up to a place where -// the stack unwinder and exception dispatch can properly transform the exception into a managed exception and dispatch -// it to managed code. -// - - LEAF_ENTRY RhpCopyMultibyte, _TEXT - - // x0 dest - // x1 src - // x2 count - - // check for a zero-length copy - cbz x2, NothingToCopy_RhpCopyMultibyte - - // Now check the dest and src pointers. If they AV, the EH subsystem will recognize the address of the AV, - // unwind the frame, and fixup the stack to make it look like the (managed) caller AV'ed, which will be - // translated to a managed exception as usual. - ALTERNATE_ENTRY RhpCopyMultibyteDestAVLocation - ldrb wzr, [x0] - ALTERNATE_ENTRY RhpCopyMultibyteSrcAVLocation - ldrb wzr, [x1] - - // tail-call to the GC-safe memcpy implementation - b memcpyGCRefs - -NothingToCopy_RhpCopyMultibyte: - // dest is already still in x0 - ret - - LEAF_END RhpCopyMultibyte, _TEXT - -//;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -// -// void* RhpCopyMultibyteWithWriteBarrier(void*, void*, size_t) -// -// The purpose of this wrapper is to hoist the potential null reference exceptions of copying memory up to a place where -// the stack unwinder and exception dispatch can properly transform the exception into a managed exception and dispatch -// it to managed code. -// Runs a card table update via RhpBulkWriteBarrier after the copy -// - - LEAF_ENTRY RhpCopyMultibyteWithWriteBarrier, _TEXT - - // x0 dest - // x1 src - // x2 count - - // check for a zero-length copy - cbz x2, NothingToCopy_RhpCopyMultibyteWithWriteBarrier - - // Now check the dest and src pointers. If they AV, the EH subsystem will recognize the address of the AV, - // unwind the frame, and fixup the stack to make it look like the (managed) caller AV'ed, which will be - // translated to a managed exception as usual. - ALTERNATE_ENTRY RhpCopyMultibyteWithWriteBarrierDestAVLocation - ldrb wzr, [x0] - ALTERNATE_ENTRY RhpCopyMultibyteWithWriteBarrierSrcAVLocation - ldrb wzr, [x1] - - // tail-call to the GC-safe memcpy implementation - b memcpyGCRefsWithWriteBarrier - -NothingToCopy_RhpCopyMultibyteWithWriteBarrier: - // dest is already still in x0 - ret - LEAF_END RhpCopyMultibyteWithWriteBarrier, _TEXT - -//;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -// -// void* RhpCopyAnyWithWriteBarrier(void*, void*, size_t) -// -// The purpose of this wrapper is to hoist the potential null reference exceptions of copying memory up to a place where -// the stack unwinder and exception dispatch can properly transform the exception into a managed exception and dispatch -// it to managed code. -// Runs a card table update via RhpBulkWriteBarrier after the copy if it contained GC pointers -// - - LEAF_ENTRY RhpCopyAnyWithWriteBarrier, _TEXT - - // x0 dest - // x1 src - // x2 count - - // check for a zero-length copy - cbz x2, NothingToCopy_RhpCopyAnyWithWriteBarrier - - // Now check the dest and src pointers. If they AV, the EH subsystem will recognize the address of the AV, - // unwind the frame, and fixup the stack to make it look like the (managed) caller AV'ed, which will be - // translated to a managed exception as usual. - ALTERNATE_ENTRY RhpCopyAnyWithWriteBarrierDestAVLocation - ldrb wzr, [x0] - ALTERNATE_ENTRY RhpCopyAnyWithWriteBarrierSrcAVLocation - ldrb wzr, [x1] - - // tail-call to the GC-safe memcpy implementation - b memcpyAnyWithWriteBarrier - -NothingToCopy_RhpCopyAnyWithWriteBarrier: - // dest is already still in x0 - ret - - LEAF_END RhpCopyAnyWithWriteBarrier, _TEXT diff --git a/src/coreclr/nativeaot/Runtime/arm64/MiscStubs.asm b/src/coreclr/nativeaot/Runtime/arm64/MiscStubs.asm index b845854cdb265..49baea4977259 100644 --- a/src/coreclr/nativeaot/Runtime/arm64/MiscStubs.asm +++ b/src/coreclr/nativeaot/Runtime/arm64/MiscStubs.asm @@ -3,152 +3,6 @@ #include "AsmMacros.h" - EXTERN memcpy - EXTERN memcpyGCRefs - EXTERN memcpyGCRefsWithWriteBarrier - EXTERN memcpyAnyWithWriteBarrier - TEXTAREA -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; -;; void* RhpCopyMultibyteNoGCRefs(void*, void*, size_t) -;; -;; The purpose of this wrapper is to hoist the potential null reference exceptions of copying memory up to a place where -;; the stack unwinder and exception dispatch can properly transform the exception into a managed exception and dispatch -;; it to managed code. -;; - - LEAF_ENTRY RhpCopyMultibyteNoGCRefs - - ; x0 dest - ; x1 src - ; x2 count - - cbz x2, NothingToCopy_NoGCRefs ; check for a zero-length copy - - ; Now check the dest and src pointers. If they AV, the EH subsystem will recognize the address of the AV, - ; unwind the frame, and fixup the stack to make it look like the (managed) caller AV'ed, which will be - ; translated to a managed exception as usual. - ALTERNATE_ENTRY RhpCopyMultibyteNoGCRefsDestAVLocation - ldrb wzr, [x0] - ALTERNATE_ENTRY RhpCopyMultibyteNoGCRefsSrcAVLocation - ldrb wzr, [x1] - - ; tail-call to plain-old-memcpy - b memcpy - -NothingToCopy_NoGCRefs - ; dest is already in x0 - ret - - LEAF_END - - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; -;; void* RhpCopyMultibyte(void*, void*, size_t) -;; -;; The purpose of this wrapper is to hoist the potential null reference exceptions of copying memory up to a place where -;; the stack unwinder and exception dispatch can properly transform the exception into a managed exception and dispatch -;; it to managed code. -;; - - LEAF_ENTRY RhpCopyMultibyte - - ; x0 dest - ; x1 src - ; x2 count - - ; check for a zero-length copy - cbz x2, NothingToCopy_RhpCopyMultibyte - - ; Now check the dest and src pointers. If they AV, the EH subsystem will recognize the address of the AV, - ; unwind the frame, and fixup the stack to make it look like the (managed) caller AV'ed, which will be - ; translated to a managed exception as usual. - ALTERNATE_ENTRY RhpCopyMultibyteDestAVLocation - ldrb wzr, [x0] - ALTERNATE_ENTRY RhpCopyMultibyteSrcAVLocation - ldrb wzr, [x1] - - ; tail-call to the GC-safe memcpy implementation - b memcpyGCRefs - -NothingToCopy_RhpCopyMultibyte - ; dest is already still in x0 - ret - - LEAF_END - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; -;; void* RhpCopyMultibyteWithWriteBarrier(void*, void*, size_t) -;; -;; The purpose of this wrapper is to hoist the potential null reference exceptions of copying memory up to a place where -;; the stack unwinder and exception dispatch can properly transform the exception into a managed exception and dispatch -;; it to managed code. -;; Runs a card table update via RhpBulkWriteBarrier after the copy -;; - - LEAF_ENTRY RhpCopyMultibyteWithWriteBarrier - - ; x0 dest - ; x1 src - ; x2 count - - ; check for a zero-length copy - cbz x2, NothingToCopy_RhpCopyMultibyteWithWriteBarrier - - ; Now check the dest and src pointers. If they AV, the EH subsystem will recognize the address of the AV, - ; unwind the frame, and fixup the stack to make it look like the (managed) caller AV'ed, which will be - ; translated to a managed exception as usual. - ALTERNATE_ENTRY RhpCopyMultibyteWithWriteBarrierDestAVLocation - ldrb wzr, [x0] - ALTERNATE_ENTRY RhpCopyMultibyteWithWriteBarrierSrcAVLocation - ldrb wzr, [x1] - - ; tail-call to the GC-safe memcpy implementation - b memcpyGCRefsWithWriteBarrier - -NothingToCopy_RhpCopyMultibyteWithWriteBarrier - ; dest is already still in x0 - ret - LEAF_END - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; -;; void* RhpCopyAnyWithWriteBarrier(void*, void*, size_t) -;; -;; The purpose of this wrapper is to hoist the potential null reference exceptions of copying memory up to a place where -;; the stack unwinder and exception dispatch can properly transform the exception into a managed exception and dispatch -;; it to managed code. -;; Runs a card table update via RhpBulkWriteBarrier after the copy if it contained GC pointers -;; - - LEAF_ENTRY RhpCopyAnyWithWriteBarrier - - ; x0 dest - ; x1 src - ; x2 count - - ; check for a zero-length copy - cbz x2, NothingToCopy_RhpCopyAnyWithWriteBarrier - - ; Now check the dest and src pointers. If they AV, the EH subsystem will recognize the address of the AV, - ; unwind the frame, and fixup the stack to make it look like the (managed) caller AV'ed, which will be - ; translated to a managed exception as usual. - ALTERNATE_ENTRY RhpCopyAnyWithWriteBarrierDestAVLocation - ldrb wzr, [x0] - ALTERNATE_ENTRY RhpCopyAnyWithWriteBarrierSrcAVLocation - ldrb wzr, [x1] - - ; tail-call to the GC-safe memcpy implementation - b memcpyAnyWithWriteBarrier - -NothingToCopy_RhpCopyAnyWithWriteBarrier - ; dest is already still in x0 - ret - - LEAF_END - end diff --git a/src/coreclr/nativeaot/Runtime/i386/MiscStubs.asm b/src/coreclr/nativeaot/Runtime/i386/MiscStubs.asm index 3bd8a528cbaf1..f80ca3301f245 100644 --- a/src/coreclr/nativeaot/Runtime/i386/MiscStubs.asm +++ b/src/coreclr/nativeaot/Runtime/i386/MiscStubs.asm @@ -8,180 +8,6 @@ include AsmMacros.inc -EXTERN _memcpy : PROC -EXTERN _memcpyGCRefs : PROC -EXTERN _memcpyGCRefsWithWriteBarrier : PROC -EXTERN _memcpyAnyWithWriteBarrier : PROC - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; -;; void* __cdecl RhpCopyMultibyteNoGCRefs(void*, void*, size_t) -;; -;; The purpose of this wrapper is to hoist the potential null reference exceptions of copying memory up to a place where -;; the stack unwinder and exception dispatch can properly transform the exception into a managed exception and dispatch -;; it to managed code. -;; -_RhpCopyMultibyteNoGCRefs PROC PUBLIC - - ; #locals, num_params, prolog bytes, #regs saved, use ebp, frame type (0 == FRAME_FPO) - .FPO( 0, 3, 0, 0, 0, 0) - - ; [esp + 0] return address - ; [esp + 4] dest - ; [esp + 8] src - ; [esp + c] count - - cmp dword ptr [esp + 0Ch], 0 ; check for a zero-length copy - jz NothingToCopy - - mov ecx, [esp + 4] ; ecx <- dest - mov edx, [esp + 8] ; edx <- src - - ; Now check the dest and src pointers. If they AV, the EH subsystem will recognize the address of the AV, - ; unwind the frame, and fixup the stack to make it look like the (managed) caller AV'ed, which will be - ; translated to a managed exception as usual. -ALTERNATE_ENTRY RhpCopyMultibyteNoGCRefsDestAVLocation - cmp byte ptr [ecx], 0 -ALTERNATE_ENTRY RhpCopyMultibyteNoGCRefsSrcAVLocation - cmp byte ptr [edx], 0 - - ; tail-call to plain-old-memcpy - jmp _memcpy - -NothingToCopy: - mov eax, [esp + 4] ; return dest - ret - -_RhpCopyMultibyteNoGCRefs ENDP - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; -;; void* __cdecl RhpCopyMultibyte(void*, void*, size_t) -;; -;; The purpose of this wrapper is to hoist the potential null reference exceptions of copying memory up to a place where -;; the stack unwinder and exception dispatch can properly transform the exception into a managed exception and dispatch -;; it to managed code. -;; -_RhpCopyMultibyte PROC PUBLIC - - ; #locals, num_params, prolog bytes, #regs saved, use ebp, frame type (0 == FRAME_FPO) - .FPO( 0, 3, 0, 0, 0, 0) - - ; [esp + 0] return address - ; [esp + 4] dest - ; [esp + 8] src - ; [esp + c] count - - cmp dword ptr [esp + 0Ch], 0 ; check for a zero-length copy - jz NothingToCopy - - mov ecx, [esp + 4] ; ecx <- dest - mov edx, [esp + 8] ; edx <- src - - ; Now check the dest and src pointers. If they AV, the EH subsystem will recognize the address of the AV, - ; unwind the frame, and fixup the stack to make it look like the (managed) caller AV'ed, which will be - ; translated to a managed exception as usual. -ALTERNATE_ENTRY RhpCopyMultibyteDestAVLocation - cmp byte ptr [ecx], 0 -ALTERNATE_ENTRY RhpCopyMultibyteSrcAVLocation - cmp byte ptr [edx], 0 - - ; tail-call to the GC-safe memcpy implementation - ; NOTE: this is also a __cdecl function - jmp _memcpyGCRefs - -NothingToCopy: - mov eax, [esp + 4] ; return dest - ret - -_RhpCopyMultibyte ENDP - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; -;; void* __cdecl RhpCopyMultibyteWithWriteBarrier(void*, void*, size_t) -;; -;; The purpose of this wrapper is to hoist the potential null reference exceptions of copying memory up to a place where -;; the stack unwinder and exception dispatch can properly transform the exception into a managed exception and dispatch -;; it to managed code. -;; Runs a card table update via RhpBulkWriteBarrier after the copy -;; -_RhpCopyMultibyteWithWriteBarrier PROC PUBLIC - - ; #locals, num_params, prolog bytes, #regs saved, use ebp, frame type (0 == FRAME_FPO) - .FPO( 0, 3, 0, 0, 0, 0) - - ; [esp + 0] return address - ; [esp + 4] dest - ; [esp + 8] src - ; [esp + c] count - - cmp dword ptr [esp + 0Ch], 0 ; check for a zero-length copy - jz NothingToCopy - - mov ecx, [esp + 4] ; ecx <- dest - mov edx, [esp + 8] ; edx <- src - - ; Now check the dest and src pointers. If they AV, the EH subsystem will recognize the address of the AV, - ; unwind the frame, and fixup the stack to make it look like the (managed) caller AV'ed, which will be - ; translated to a managed exception as usual. -ALTERNATE_ENTRY RhpCopyMultibyteWithWriteBarrierDestAVLocation - cmp byte ptr [ecx], 0 -ALTERNATE_ENTRY RhpCopyMultibyteWithWriteBarrierSrcAVLocation - cmp byte ptr [edx], 0 - - ; tail-call to the GC-safe memcpy implementation - ; NOTE: this is also a __cdecl function - jmp _memcpyGCRefsWithWriteBarrier - -NothingToCopy: - mov eax, [esp + 4] ; return dest - ret - -_RhpCopyMultibyteWithWriteBarrier ENDP - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; -;; void* __cdecl RhpCopyAnyWithWriteBarrier(void*, void*, size_t) -;; -;; The purpose of this wrapper is to hoist the potential null reference exceptions of copying memory up to a place where -;; the stack unwinder and exception dispatch can properly transform the exception into a managed exception and dispatch -;; it to managed code. -;; Runs a card table update via RhpBulkWriteBarrier after the copy if it contained GC pointers -;; -_RhpCopyAnyWithWriteBarrier PROC PUBLIC - - ; #locals, num_params, prolog bytes, #regs saved, use ebp, frame type (0 == FRAME_FPO) - .FPO( 0, 3, 0, 0, 0, 0) - - ; [esp + 0] return address - ; [esp + 4] dest - ; [esp + 8] src - ; [esp + c] count - - cmp dword ptr [esp + 0Ch], 0 ; check for a zero-length copy - jz NothingToCopy - - mov ecx, [esp + 4] ; ecx <- dest - mov edx, [esp + 8] ; edx <- src - - ; Now check the dest and src pointers. If they AV, the EH subsystem will recognize the address of the AV, - ; unwind the frame, and fixup the stack to make it look like the (managed) caller AV'ed, which will be - ; translated to a managed exception as usual. -ALTERNATE_ENTRY RhpCopyAnyWithWriteBarrierDestAVLocation - cmp byte ptr [ecx], 0 -ALTERNATE_ENTRY RhpCopyAnyWithWriteBarrierSrcAVLocation - cmp byte ptr [edx], 0 - - ; tail-call to the GC-safe memcpy implementation - ; NOTE: this is also a __cdecl function - jmp _memcpyAnyWithWriteBarrier - -NothingToCopy: - mov eax, [esp + 4] ; return dest - ret - -_RhpCopyAnyWithWriteBarrier ENDP - ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; The following helper will access ("probe") a word on each page of the stack ; starting with the page right beneath esp down to the one pointed to by eax. From 328eb6e69f45e57c2b962b52eade2ef712d56690 Mon Sep 17 00:00:00 2001 From: vsadov <8218165+VSadov@users.noreply.github.com> Date: Tue, 4 Apr 2023 12:53:13 -0700 Subject: [PATCH 2/2] PR feedback --- .../src/System/Runtime/InternalCalls.cs | 4 ++-- .../src/System/Runtime/RuntimeExports.cs | 2 +- .../nativeaot/Runtime/GCMemoryHelpers.cpp | 15 +++++++-------- .../nativeaot/Runtime/GCMemoryHelpers.inl | 19 ++++++++++--------- 4 files changed, 20 insertions(+), 20 deletions(-) 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 7d4bb10ef9a19..261868c21adf4 100644 --- a/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/InternalCalls.cs +++ b/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/InternalCalls.cs @@ -155,8 +155,8 @@ internal static int RhEndNoGCRegion() internal static extern unsafe void RhpAssignRef(ref object address, object obj); [MethodImplAttribute(MethodImplOptions.InternalCall)] - [RuntimeImport(Redhawk.BaseName, "RhpInitMultibyte")] - internal static extern unsafe ref byte RhpInitMultibyte(ref byte dmem, nuint size); + [RuntimeImport(Redhawk.BaseName, "RhpGcSafeZeroMemory")] + internal static extern unsafe ref byte RhpGcSafeZeroMemory(ref byte dmem, nuint size); [MethodImplAttribute(MethodImplOptions.InternalCall)] [RuntimeImport(Redhawk.BaseName, "memmove")] 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 dd2f10bc117e5..0379da95f70d7 100644 --- a/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/RuntimeExports.cs +++ b/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/RuntimeExports.cs @@ -234,7 +234,7 @@ public static unsafe void RhUnbox(object? obj, ref byte data, MethodTable* pUnbo Debug.Assert(pUnboxToEEType != null && pUnboxToEEType->IsNullable); // Set HasValue to false and clear the value (in case there were GC references we wish to stop reporting). - InternalCalls.RhpInitMultibyte( + InternalCalls.RhpGcSafeZeroMemory( ref data, pUnboxToEEType->ValueTypeSize); diff --git a/src/coreclr/nativeaot/Runtime/GCMemoryHelpers.cpp b/src/coreclr/nativeaot/Runtime/GCMemoryHelpers.cpp index 95d9c77d23b7b..27126acbdb839 100644 --- a/src/coreclr/nativeaot/Runtime/GCMemoryHelpers.cpp +++ b/src/coreclr/nativeaot/Runtime/GCMemoryHelpers.cpp @@ -13,20 +13,19 @@ #include "GCMemoryHelpers.h" #include "GCMemoryHelpers.inl" -// This function clears a piece of memory in a GC safe way. It makes the guarantee that it will clear memory in at -// least pointer sized chunks whenever possible. Unaligned memory at the beginning and remaining bytes at the end are -// written bytewise. We must make this guarantee whenever we clear memory in the GC heap that could contain object +// This function clears a piece of memory in a GC safe way. +// Object-aligned memory is zeroed with no smaller than pointer-size granularity. +// We must make this guarantee whenever we clear memory in the GC heap that could contain object // references. The GC or other user threads can read object references at any time, clearing them bytewise can result // in a read on another thread getting incorrect data. -// -// USAGE: The caller is responsible for hoisting any null reference exceptions to a place where the hardware exception -// can be properly translated to a managed exception. -COOP_PINVOKE_CDECL_HELPER(void *, RhpInitMultibyte, (void * mem, size_t size)) +// Unaligned memory at the beginning and remaining bytes at the end are written bytewise. +// USAGE: The caller is responsible for null-checking the reference. +COOP_PINVOKE_CDECL_HELPER(void *, RhpGcSafeZeroMemory, (void * mem, size_t size)) { // The caller must do the null-check because we cannot take an AV in the runtime and translate it to managed. ASSERT(mem != nullptr); - InlineGCSafeFillMemory(mem, size, 0); + InlineGcSafeZeroMemory(mem, size); // memset returns the destination buffer return mem; diff --git a/src/coreclr/nativeaot/Runtime/GCMemoryHelpers.inl b/src/coreclr/nativeaot/Runtime/GCMemoryHelpers.inl index e632a78ecb3e1..e5d157c7c7019 100644 --- a/src/coreclr/nativeaot/Runtime/GCMemoryHelpers.inl +++ b/src/coreclr/nativeaot/Runtime/GCMemoryHelpers.inl @@ -19,32 +19,33 @@ static const int card_byte_shift = 10; #endif -// This function fills a piece of memory in a GC safe way. It makes the guarantee -// that it will fill memory in at least pointer sized chunks whenever possible. +// This function clears a piece of memory in a GC safe way. +// Object-aligned memory is zeroed with no smaller than pointer-size granularity. +// We must make this guarantee whenever we clear memory in the GC heap that could contain object +// references. The GC or other user threads can read object references at any time, clearing them bytewise can result +// in a read on another thread getting incorrect data. // Unaligned memory at the beginning and remaining bytes at the end are written bytewise. -// We must make this guarantee whenever we clear memory in the GC heap that could contain -// object references. The GC or other user threads can read object references at any time, -// clearing them bytewise can result in a read on another thread getting incorrect data. -FORCEINLINE void InlineGCSafeFillMemory(void * mem, size_t size, size_t pv) +// USAGE: The caller is responsible for null-checking the reference. +FORCEINLINE void InlineGcSafeZeroMemory(void * mem, size_t size) { uint8_t * memBytes = (uint8_t *)mem; uint8_t * endBytes = &memBytes[size]; // handle unaligned bytes at the beginning while (!IS_ALIGNED(memBytes, sizeof(void *)) && (memBytes < endBytes)) - *memBytes++ = (uint8_t)pv; + *memBytes++ = 0; // now write pointer sized pieces // volatile ensures that this doesn't get optimized back into a memset call size_t nPtrs = (endBytes - memBytes) / sizeof(void *); volatile uintptr_t* memPtr = (uintptr_t*)memBytes; for (size_t i = 0; i < nPtrs; i++) - *memPtr++ = pv; + *memPtr++ = 0; // handle remaining bytes at the end memBytes = (uint8_t*)memPtr; while (memBytes < endBytes) - *memBytes++ = (uint8_t)pv; + *memBytes++ = 0; } // These functions copy memory in a GC safe way. They makes the guarantee