Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Convert uses of the Dangerous APIs to use MemoryMarshal.GetReference #15532

Merged
merged 10 commits into from
Dec 16, 2017
2 changes: 1 addition & 1 deletion src/jit/compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -7702,7 +7702,7 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
int getSIMDTypeAlignment(var_types simdType);

// Get the number of bytes in a System.Numeric.Vector<T> for the current compilation.
// Note - cannot be used for System.Runtime.Intrinsic
// Note - cannot be used for System.Runtime.Intrinsic
unsigned getSIMDVectorRegisterByteLength()
{
#if defined(_TARGET_XARCH_) && !defined(LEGACY_BACKEND)
Expand Down
42 changes: 22 additions & 20 deletions src/mscorlib/shared/System/BitConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

using Internal.Runtime.CompilerServices;

namespace System
Expand Down Expand Up @@ -37,7 +39,7 @@ public static bool TryWriteBytes(Span<byte> destination, bool value)
if (destination.Length < sizeof(byte))
return false;

Unsafe.WriteUnaligned(ref destination.DangerousGetPinnableReference(), value ? (byte)1 : (byte)0);
Unsafe.WriteUnaligned(ref MemoryMarshal.GetReference(destination), value ? (byte)1 : (byte)0);
return true;
}

Expand All @@ -55,7 +57,7 @@ public static bool TryWriteBytes(Span<byte> destination, char value)
if (destination.Length < sizeof(char))
return false;

Unsafe.WriteUnaligned(ref destination.DangerousGetPinnableReference(), value);
Unsafe.WriteUnaligned(ref MemoryMarshal.GetReference(destination), value);
return true;
}

Expand All @@ -74,7 +76,7 @@ public static bool TryWriteBytes(Span<byte> destination, short value)
if (destination.Length < sizeof(short))
return false;

Unsafe.WriteUnaligned(ref destination.DangerousGetPinnableReference(), value);
Unsafe.WriteUnaligned(ref MemoryMarshal.GetReference(destination), value);
return true;
}

Expand All @@ -93,7 +95,7 @@ public static bool TryWriteBytes(Span<byte> destination, int value)
if (destination.Length < sizeof(int))
return false;

Unsafe.WriteUnaligned(ref destination.DangerousGetPinnableReference(), value);
Unsafe.WriteUnaligned(ref MemoryMarshal.GetReference(destination), value);
return true;
}

Expand All @@ -112,7 +114,7 @@ public static bool TryWriteBytes(Span<byte> destination, long value)
if (destination.Length < sizeof(long))
return false;

Unsafe.WriteUnaligned(ref destination.DangerousGetPinnableReference(), value);
Unsafe.WriteUnaligned(ref MemoryMarshal.GetReference(destination), value);
return true;
}

Expand All @@ -133,7 +135,7 @@ public static bool TryWriteBytes(Span<byte> destination, ushort value)
if (destination.Length < sizeof(ushort))
return false;

Unsafe.WriteUnaligned(ref destination.DangerousGetPinnableReference(), value);
Unsafe.WriteUnaligned(ref MemoryMarshal.GetReference(destination), value);
return true;
}

Expand All @@ -154,7 +156,7 @@ public static bool TryWriteBytes(Span<byte> destination, uint value)
if (destination.Length < sizeof(uint))
return false;

Unsafe.WriteUnaligned(ref destination.DangerousGetPinnableReference(), value);
Unsafe.WriteUnaligned(ref MemoryMarshal.GetReference(destination), value);
return true;
}

Expand All @@ -175,7 +177,7 @@ public static bool TryWriteBytes(Span<byte> destination, ulong value)
if (destination.Length < sizeof(ulong))
return false;

Unsafe.WriteUnaligned(ref destination.DangerousGetPinnableReference(), value);
Unsafe.WriteUnaligned(ref MemoryMarshal.GetReference(destination), value);
return true;
}

Expand All @@ -194,7 +196,7 @@ public static bool TryWriteBytes(Span<byte> destination, float value)
if (destination.Length < sizeof(float))
return false;

Unsafe.WriteUnaligned(ref destination.DangerousGetPinnableReference(), value);
Unsafe.WriteUnaligned(ref MemoryMarshal.GetReference(destination), value);
return true;
}

Expand All @@ -213,7 +215,7 @@ public static bool TryWriteBytes(Span<byte> destination, double value)
if (destination.Length < sizeof(double))
return false;

Unsafe.WriteUnaligned(ref destination.DangerousGetPinnableReference(), value);
Unsafe.WriteUnaligned(ref MemoryMarshal.GetReference(destination), value);
return true;
}

Expand All @@ -225,7 +227,7 @@ public static char ToChar(ReadOnlySpan<byte> value)
{
if (value.Length < sizeof(char))
ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.value);
return Unsafe.ReadUnaligned<char>(ref value.DangerousGetPinnableReference());
return Unsafe.ReadUnaligned<char>(ref MemoryMarshal.GetReference(value));
}

// Converts an array of bytes into a short.
Expand All @@ -246,7 +248,7 @@ public static short ToInt16(ReadOnlySpan<byte> value)
{
if (value.Length < sizeof(short))
ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.value);
return Unsafe.ReadUnaligned<short>(ref value.DangerousGetPinnableReference());
return Unsafe.ReadUnaligned<short>(ref MemoryMarshal.GetReference(value));
}

// Converts an array of bytes into an int.
Expand All @@ -267,7 +269,7 @@ public static int ToInt32(ReadOnlySpan<byte> value)
{
if (value.Length < sizeof(int))
ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.value);
return Unsafe.ReadUnaligned<int>(ref value.DangerousGetPinnableReference());
return Unsafe.ReadUnaligned<int>(ref MemoryMarshal.GetReference(value));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this compile? I would expect that you will get readonly vs. non-readonly mismatch.

Copy link
Author

@ahsonkhan ahsonkhan Dec 15, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No it won't compile. I need to add the following Unsafe API:

ref T AsRef<T>(in T source)

Doing that now.

}

// Converts an array of bytes into a long.
Expand All @@ -288,7 +290,7 @@ public static long ToInt64(ReadOnlySpan<byte> value)
{
if (value.Length < sizeof(long))
ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.value);
return Unsafe.ReadUnaligned<long>(ref value.DangerousGetPinnableReference());
return Unsafe.ReadUnaligned<long>(ref MemoryMarshal.GetReference(value));
}

// Converts an array of bytes into an ushort.
Expand All @@ -302,7 +304,7 @@ public static ushort ToUInt16(ReadOnlySpan<byte> value)
{
if (value.Length < sizeof(ushort))
ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.value);
return Unsafe.ReadUnaligned<ushort>(ref value.DangerousGetPinnableReference());
return Unsafe.ReadUnaligned<ushort>(ref MemoryMarshal.GetReference(value));
}

// Converts an array of bytes into an uint.
Expand All @@ -316,7 +318,7 @@ public static uint ToUInt32(ReadOnlySpan<byte> value)
{
if (value.Length < sizeof(uint))
ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.value);
return Unsafe.ReadUnaligned<uint>(ref value.DangerousGetPinnableReference());
return Unsafe.ReadUnaligned<uint>(ref MemoryMarshal.GetReference(value));
}

// Converts an array of bytes into an unsigned long.
Expand All @@ -330,7 +332,7 @@ public static ulong ToUInt64(ReadOnlySpan<byte> value)
{
if (value.Length < sizeof(ulong))
ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.value);
return Unsafe.ReadUnaligned<ulong>(ref value.DangerousGetPinnableReference());
return Unsafe.ReadUnaligned<ulong>(ref MemoryMarshal.GetReference(value));
}

// Converts an array of bytes into a float.
Expand All @@ -341,7 +343,7 @@ public static float ToSingle(ReadOnlySpan<byte> value)
{
if (value.Length < sizeof(float))
ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.value);
return Unsafe.ReadUnaligned<float>(ref value.DangerousGetPinnableReference());
return Unsafe.ReadUnaligned<float>(ref MemoryMarshal.GetReference(value));
}

// Converts an array of bytes into a double.
Expand All @@ -352,7 +354,7 @@ public static double ToDouble(ReadOnlySpan<byte> value)
{
if (value.Length < sizeof(double))
ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.value);
return Unsafe.ReadUnaligned<double>(ref value.DangerousGetPinnableReference());
return Unsafe.ReadUnaligned<double>(ref MemoryMarshal.GetReference(value));
}

// Converts an array of bytes into a String.
Expand Down Expand Up @@ -442,7 +444,7 @@ public static bool ToBoolean(ReadOnlySpan<byte> value)
{
if (value.Length < sizeof(byte))
ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.value);
return Unsafe.ReadUnaligned<byte>(ref value.DangerousGetPinnableReference()) != 0;
return Unsafe.ReadUnaligned<byte>(ref MemoryMarshal.GetReference(value)) != 0;
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
Expand Down
10 changes: 5 additions & 5 deletions src/mscorlib/shared/System/Convert.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2434,7 +2434,7 @@ public static string ToBase64String(ReadOnlySpan<byte> bytes, Base64FormattingOp

unsafe
{
fixed (byte* bytesPtr = &bytes.DangerousGetPinnableReference())
fixed (byte* bytesPtr = &MemoryMarshal.GetReference(bytes))
fixed (char* charsPtr = result)
{
int charsWritten = ConvertToBase64Array(charsPtr, bytesPtr, 0, bytes.Length, insertLineBreaks);
Expand Down Expand Up @@ -2527,8 +2527,8 @@ public static unsafe bool TryToBase64Chars(ReadOnlySpan<byte> bytes, Span<char>
return false;
}

fixed (char* outChars = &chars.DangerousGetPinnableReference())
fixed (byte* inData = &bytes.DangerousGetPinnableReference())
fixed (char* outChars = &MemoryMarshal.GetReference(chars))
fixed (byte* inData = &MemoryMarshal.GetReference(bytes))
{
charsWritten = ConvertToBase64Array(outChars, inData, 0, bytes.Length, insertLineBreaks);
return true;
Expand Down Expand Up @@ -2676,7 +2676,7 @@ public static unsafe bool TryFromBase64Chars(ReadOnlySpan<char> chars, Span<byte
chars = chars.Slice(0, chars.Length - 1);
}

fixed (char* charsPtr = &chars.DangerousGetPinnableReference())
fixed (char* charsPtr = &MemoryMarshal.GetReference(chars))
{
int resultLength = FromBase64_ComputeResultLength(charsPtr, chars.Length);
Debug.Assert(resultLength >= 0);
Expand All @@ -2686,7 +2686,7 @@ public static unsafe bool TryFromBase64Chars(ReadOnlySpan<char> chars, Span<byte
return false;
}

fixed (byte* bytesPtr = &bytes.DangerousGetPinnableReference())
fixed (byte* bytesPtr = &MemoryMarshal.GetReference(bytes))
{
bytesWritten = FromBase64_Decode(charsPtr, chars.Length, bytesPtr, bytes.Length);
return true;
Expand Down
5 changes: 3 additions & 2 deletions src/mscorlib/shared/System/Globalization/CompareInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

using System.Reflection;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;

namespace System.Globalization
Expand Down Expand Up @@ -555,8 +556,8 @@ internal static unsafe int CompareOrdinalIgnoreCase(ReadOnlySpan<char> strA, Rea
int length = Math.Min(strA.Length, strB.Length);
int range = length;

fixed (char* ap = &strA.DangerousGetPinnableReference())
fixed (char* bp = &strB.DangerousGetPinnableReference())
fixed (char* ap = &MemoryMarshal.GetReference(strA))
fixed (char* bp = &MemoryMarshal.GetReference(strB))
{
char* a = ap;
char* b = bp;
Expand Down
3 changes: 2 additions & 1 deletion src/mscorlib/shared/System/Guid.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

using Internal.Runtime.CompilerServices;

namespace System
Expand Down Expand Up @@ -1361,7 +1362,7 @@ public bool TryFormat(Span<char> destination, out int charsWritten, ReadOnlySpan

unsafe
{
fixed (char* guidChars = &destination.DangerousGetPinnableReference())
fixed (char* guidChars = &MemoryMarshal.GetReference(destination))
{
char * p = guidChars;

Expand Down
5 changes: 3 additions & 2 deletions src/mscorlib/shared/System/IO/FileStream.Unix.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

using Microsoft.Win32.SafeHandles;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;

Expand Down Expand Up @@ -459,7 +460,7 @@ private unsafe int ReadNative(Span<byte> buffer)
VerifyOSHandlePosition();

int bytesRead;
fixed (byte* bufPtr = &buffer.DangerousGetPinnableReference())
fixed (byte* bufPtr = &MemoryMarshal.GetReference(buffer))
{
bytesRead = CheckFileCall(Interop.Sys.Read(_fileHandle, bufPtr, buffer.Length));
Debug.Assert(bytesRead <= buffer.Length);
Expand Down Expand Up @@ -612,7 +613,7 @@ private unsafe void WriteNative(ReadOnlySpan<byte> source)
{
VerifyOSHandlePosition();

fixed (byte* bufPtr = &source.DangerousGetPinnableReference())
fixed (byte* bufPtr = &MemoryMarshal.GetReference(source))
{
int offset = 0;
int count = source.Length;
Expand Down
6 changes: 3 additions & 3 deletions src/mscorlib/shared/System/IO/FileStream.Windows.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1069,7 +1069,7 @@ private unsafe Task WriteAsyncInternalCore(ReadOnlyMemory<byte> source, Cancella
Debug.Assert(_useAsyncIO, "WriteInternalCoreAsync doesn't work on synchronous file streams!");

// Create and store async stream class library specific data in the async result
FileStreamCompletionSource completionSource = source.DangerousTryGetArray(out ArraySegment<byte> array) ?
FileStreamCompletionSource completionSource = MemoryMarshal.TryGetArray(source, out ArraySegment<byte> array) ?
new FileStreamCompletionSource(this, 0, array.Array) :
new MemoryFileStreamCompletionSource(this, 0, source);
NativeOverlapped* intOverlapped = completionSource.Overlapped;
Expand Down Expand Up @@ -1188,7 +1188,7 @@ private unsafe int ReadFileNative(SafeFileHandle handle, Span<byte> bytes, Nativ
int r;
int numBytesRead = 0;

fixed (byte* p = &bytes.DangerousGetPinnableReference())
fixed (byte* p = &MemoryMarshal.GetReference(bytes))
{
r = _useAsyncIO ?
Interop.Kernel32.ReadFile(handle, p, bytes.Length, IntPtr.Zero, overlapped) :
Expand All @@ -1215,7 +1215,7 @@ private unsafe int WriteFileNative(SafeFileHandle handle, ReadOnlySpan<byte> buf
int numBytesWritten = 0;
int r;

fixed (byte* p = &buffer.DangerousGetPinnableReference())
fixed (byte* p = &MemoryMarshal.GetReference(buffer))
{
r = _useAsyncIO ?
Interop.Kernel32.WriteFile(handle, p, buffer.Length, IntPtr.Zero, overlapped) :
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,7 @@ private sealed class MemoryFileStreamCompletionSource : FileStreamCompletionSour
internal MemoryFileStreamCompletionSource(FileStream stream, int numBufferedBytes, ReadOnlyMemory<byte> memory) :
base(stream, numBufferedBytes, bytes: null) // this type handles the pinning, so null is passed for bytes
{
Debug.Assert(!memory.DangerousTryGetArray(out ArraySegment<byte> array), "The base should be used directly if we can get the array.");
Debug.Assert(!MemoryMarshal.TryGetArray(memory, out ArraySegment<byte> array), "The base should be used directly if we can get the array.");
_handle = memory.Retain(pin: true);
}

Expand Down
3 changes: 2 additions & 1 deletion src/mscorlib/shared/System/IO/MemoryStream.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;

Expand Down Expand Up @@ -762,7 +763,7 @@ public override Task WriteAsync(Byte[] buffer, int offset, int count, Cancellati
{
// See corresponding comment in ReadAsync for why we don't just always use Write(ReadOnlySpan<byte>).
// Unlike ReadAsync, we could delegate to WriteAsync(byte[], ...) here, but we don't for consistency.
if (source.DangerousTryGetArray(out ArraySegment<byte> sourceArray))
if (MemoryMarshal.TryGetArray(source, out ArraySegment<byte> sourceArray))
{
Write(sourceArray.Array, sourceArray.Offset, sourceArray.Count);
}
Expand Down
6 changes: 3 additions & 3 deletions src/mscorlib/shared/System/IO/UnmanagedMemoryStream.cs
Original file line number Diff line number Diff line change
Expand Up @@ -418,7 +418,7 @@ internal int ReadCore(Span<byte> destination)

unsafe
{
fixed (byte* pBuffer = &destination.DangerousGetPinnableReference())
fixed (byte* pBuffer = &MemoryMarshal.GetReference(destination))
{
if (_buffer != null)
{
Expand Down Expand Up @@ -709,7 +709,7 @@ internal unsafe void WriteCore(ReadOnlySpan<byte> source)
}
}

fixed (byte* pBuffer = &source.DangerousGetPinnableReference())
fixed (byte* pBuffer = &MemoryMarshal.GetReference(source))
{
if (_buffer != null)
{
Expand Down Expand Up @@ -794,7 +794,7 @@ public override Task WriteAsync(Byte[] buffer, Int32 offset, Int32 count, Cancel
{
// See corresponding comment in ReadAsync for why we don't just always use Write(ReadOnlySpan<byte>).
// Unlike ReadAsync, we could delegate to WriteAsync(byte[], ...) here, but we don't for consistency.
if (source.DangerousTryGetArray(out ArraySegment<byte> sourceArray))
if (MemoryMarshal.TryGetArray(source, out ArraySegment<byte> sourceArray))
{
Write(sourceArray.Array, sourceArray.Offset, sourceArray.Count);
}
Expand Down
3 changes: 2 additions & 1 deletion src/mscorlib/shared/System/MemoryDebugView.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
// See the LICENSE file in the project root for more information.

using System.Diagnostics;
using System.Runtime.InteropServices;

namespace System
{
Expand All @@ -27,7 +28,7 @@ public T[] Items
// https://devdiv.visualstudio.com/DevDiv/_workitems?id=286592
get
{
if (_memory.DangerousTryGetArray(out ArraySegment<T> segment))
if (MemoryMarshal.TryGetArray(_memory, out ArraySegment<T> segment))
{
T[] array = new T[_memory.Length];
Array.Copy(segment.Array, segment.Offset, array, 0, array.Length);
Expand Down
Loading