From 70c1e9dbebe2d737e93b7900c34c6f1dff6a2d77 Mon Sep 17 00:00:00 2001 From: Levi Broderick Date: Thu, 20 Feb 2020 20:54:32 -0800 Subject: [PATCH] Remove some calls to wstrcpy (#32342) --- .../src/System/String.Manipulation.cs | 22 +++---- .../System.Private.CoreLib/src/System/String.cs | 72 ++++++++++++++-------- 2 files changed, 58 insertions(+), 36 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/String.Manipulation.cs b/src/libraries/System.Private.CoreLib/src/System/String.Manipulation.cs index 486145d..a15d9b9 100644 --- a/src/libraries/System.Private.CoreLib/src/System/String.Manipulation.cs +++ b/src/libraries/System.Private.CoreLib/src/System/String.Manipulation.cs @@ -15,7 +15,7 @@ namespace System { private const int StackallocIntBufferSizeLimit = 128; - private static unsafe void FillStringChecked(string dest, int destPos, string src) + private static void FillStringChecked(string dest, int destPos, string src) { Debug.Assert(dest != null); Debug.Assert(src != null); @@ -24,11 +24,10 @@ namespace System throw new IndexOutOfRangeException(); } - fixed (char* pDest = &dest._firstChar) - fixed (char* pSrc = &src._firstChar) - { - wstrcpy(pDest + destPos, pSrc, src.Length); - } + Buffer.Memmove( + destination: ref Unsafe.Add(ref dest._firstChar, destPos), + source: ref src._firstChar, + elementCount: (uint)src.Length); } public static string Concat(object? arg0) => arg0?.ToString() ?? string.Empty; @@ -1665,18 +1664,17 @@ namespace System return InternalSubString(startIndex, length); } - private unsafe string InternalSubString(int startIndex, int length) + private string InternalSubString(int startIndex, int length) { Debug.Assert(startIndex >= 0 && startIndex <= this.Length, "StartIndex is out of range!"); Debug.Assert(length >= 0 && startIndex <= this.Length - length, "length is out of range!"); string result = FastAllocateString(length); - fixed (char* dest = &result._firstChar) - fixed (char* src = &_firstChar) - { - wstrcpy(dest, src + startIndex, length); - } + Buffer.Memmove( + elementCount: (uint)result.Length, // derefing Length now allows JIT to prove 'result' not null below + destination: ref result._firstChar, + source: ref Unsafe.Add(ref _firstChar, startIndex)); return result; } diff --git a/src/libraries/System.Private.CoreLib/src/System/String.cs b/src/libraries/System.Private.CoreLib/src/System/String.cs index 177ded2..ec6fc18 100644 --- a/src/libraries/System.Private.CoreLib/src/System/String.cs +++ b/src/libraries/System.Private.CoreLib/src/System/String.cs @@ -58,11 +58,12 @@ namespace System return Empty; string result = FastAllocateString(value.Length); - unsafe - { - fixed (char* dest = &result._firstChar, source = value) - wstrcpy(dest, source, value.Length); - } + + Buffer.Memmove( + elementCount: (uint)result.Length, // derefing Length now allows JIT to prove 'result' not null below + destination: ref result._firstChar, + source: ref MemoryMarshal.GetArrayDataReference(value)); + return result; } @@ -91,11 +92,12 @@ namespace System return Empty; string result = FastAllocateString(length); - unsafe - { - fixed (char* dest = &result._firstChar, source = value) - wstrcpy(dest, source + startIndex, length); - } + + Buffer.Memmove( + elementCount: (uint)result.Length, // derefing Length now allows JIT to prove 'result' not null below + destination: ref result._firstChar, + source: ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(value), startIndex)); + return result; } @@ -117,8 +119,12 @@ namespace System return Empty; string result = FastAllocateString(count); - fixed (char* dest = &result._firstChar) - wstrcpy(dest, ptr, count); + + Buffer.Memmove( + elementCount: (uint)result.Length, // derefing Length now allows JIT to prove 'result' not null below + destination: ref result._firstChar, + source: ref *ptr); + return result; } @@ -151,8 +157,12 @@ namespace System throw new ArgumentOutOfRangeException(nameof(ptr), SR.ArgumentOutOfRange_PartialWCHAR); string result = FastAllocateString(length); - fixed (char* dest = &result._firstChar) - wstrcpy(dest, pStart, length); + + Buffer.Memmove( + elementCount: (uint)result.Length, // derefing Length now allows JIT to prove 'result' not null below + destination: ref result._firstChar, + source: ref *pStart); + return result; } @@ -370,8 +380,12 @@ namespace System throw new ArgumentNullException(nameof(str)); string result = FastAllocateString(str.Length); - fixed (char* dest = &result._firstChar, src = &str._firstChar) - wstrcpy(dest, src, str.Length); + + Buffer.Memmove( + elementCount: (uint)result.Length, // derefing Length now allows JIT to prove 'result' not null below + destination: ref result._firstChar, + source: ref str._firstChar); + return result; } @@ -393,25 +407,31 @@ namespace System if (destinationIndex > destination.Length - count || destinationIndex < 0) throw new ArgumentOutOfRangeException(nameof(destinationIndex), SR.ArgumentOutOfRange_IndexCount); - fixed (char* src = &_firstChar, dest = destination) - wstrcpy(dest + destinationIndex, src + sourceIndex, count); + Buffer.Memmove( + destination: ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(destination), destinationIndex), + source: ref Unsafe.Add(ref _firstChar, sourceIndex), + elementCount: (uint)count); } // Returns the entire string as an array of characters. - public unsafe char[] ToCharArray() + public char[] ToCharArray() { if (Length == 0) return Array.Empty(); char[] chars = new char[Length]; - fixed (char* src = &_firstChar, dest = &chars[0]) - wstrcpy(dest, src, Length); + + Buffer.Memmove( + destination: ref MemoryMarshal.GetArrayDataReference(chars), + source: ref _firstChar, + elementCount: (uint)Length); + return chars; } // Returns a substring of this string as an array of characters. // - public unsafe char[] ToCharArray(int startIndex, int length) + public char[] ToCharArray(int startIndex, int length) { // Range check everything. if (startIndex < 0 || startIndex > Length || startIndex > Length - length) @@ -425,8 +445,12 @@ namespace System } char[] chars = new char[length]; - fixed (char* src = &_firstChar, dest = &chars[0]) - wstrcpy(dest, src + startIndex, length); + + Buffer.Memmove( + destination: ref MemoryMarshal.GetArrayDataReference(chars), + source: ref Unsafe.Add(ref _firstChar, startIndex), + elementCount: (uint)length); + return chars; } -- 2.7.4