diff --git a/src/System.Memory/ref/System.Memory.cs b/src/System.Memory/ref/System.Memory.cs index ddbb5f8004e6..a8e2420f3792 100644 --- a/src/System.Memory/ref/System.Memory.cs +++ b/src/System.Memory/ref/System.Memory.cs @@ -429,5 +429,10 @@ namespace System.Runtime.InteropServices public static class MemoryMarshal { public static Memory AsMemory(ReadOnlyMemory readOnlyMemory) { throw null; } + + public static ref T GetReference(Span span) { throw null; } + public static ref readonly T GetReference(ReadOnlySpan span) { throw null; } + + public static bool TryGetArray(ReadOnlyMemory readOnlyMemory, out ArraySegment arraySegment) { throw null; } } } diff --git a/src/System.Memory/src/System/MemoryDebugView.cs b/src/System.Memory/src/System/MemoryDebugView.cs index 9093eb7aa413..7ac5a53d7f40 100644 --- a/src/System.Memory/src/System/MemoryDebugView.cs +++ b/src/System.Memory/src/System/MemoryDebugView.cs @@ -3,6 +3,7 @@ // See the LICENSE file in the project root for more information. using System.Diagnostics; +using System.Runtime.InteropServices; namespace System { @@ -27,7 +28,7 @@ public T[] Items // https://devdiv.visualstudio.com/DevDiv/_workitems?id=286592 get { - if (_memory.DangerousTryGetArray(out ArraySegment segment)) + if (MemoryMarshal.TryGetArray(_memory, out ArraySegment segment)) { T[] array = new T[_memory.Length]; Array.Copy(segment.Array, segment.Offset, array, 0, array.Length); diff --git a/src/System.Memory/src/System/ReadOnlyMemory.cs b/src/System.Memory/src/System/ReadOnlyMemory.cs index 60af54a1be13..9a41d45e7ade 100644 --- a/src/System.Memory/src/System/ReadOnlyMemory.cs +++ b/src/System.Memory/src/System/ReadOnlyMemory.cs @@ -29,7 +29,7 @@ public readonly struct ReadOnlyMemory private readonly int _index; private readonly int _length; - private const int RemoveOwnedFlagBitMask = 0x7FFFFFFF; + internal const int RemoveOwnedFlagBitMask = 0x7FFFFFFF; /// /// Creates a new memory over the entirety of the target array. diff --git a/src/System.Memory/src/System/ReadOnlySpan.cs b/src/System.Memory/src/System/ReadOnlySpan.cs index 8dae95629f23..57267bac96a8 100644 --- a/src/System.Memory/src/System/ReadOnlySpan.cs +++ b/src/System.Memory/src/System/ReadOnlySpan.cs @@ -308,6 +308,7 @@ public T[] ToArray() public static ReadOnlySpan Empty => default(ReadOnlySpan); /// + /// This method is obsolete, use System.Runtime.InteropServices.MemoryMarshal.GetReference instead. /// Returns a reference to the 0th element of the Span. If the Span is empty, returns a reference to the location where the 0th element /// would have been stored. Such a reference can be used for pinning but must never be dereferenced. /// diff --git a/src/System.Memory/src/System/Runtime/InteropServices/MemoryMarshal.cs b/src/System.Memory/src/System/Runtime/InteropServices/MemoryMarshal.cs index 5301f8771384..24009ae886df 100644 --- a/src/System.Memory/src/System/Runtime/InteropServices/MemoryMarshal.cs +++ b/src/System.Memory/src/System/Runtime/InteropServices/MemoryMarshal.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using System.Buffers; using System.Runtime.CompilerServices; namespace System.Runtime.InteropServices @@ -23,5 +24,54 @@ public static class MemoryMarshal /// public static Memory AsMemory(ReadOnlyMemory readOnlyMemory) => Unsafe.As, Memory>(ref readOnlyMemory); + + /// + /// Returns a reference to the 0th element of the Span. If the Span is empty, returns a reference to the location where the 0th element + /// would have been stored. Such a reference can be used for pinning but must never be dereferenced. + /// + public static ref T GetReference(Span span) + { + if (span.Pinnable == null) + unsafe { return ref Unsafe.AsRef(span.ByteOffset.ToPointer()); } + else + return ref Unsafe.AddByteOffset(ref span.Pinnable.Data, span.ByteOffset); + } + + /// + /// Returns a reference to the 0th element of the ReadOnlySpan. If the Span is empty, returns a reference to the location where the 0th element + /// would have been stored. Such a reference can be used for pinning but must never be dereferenced. + /// + public static ref readonly T GetReference(ReadOnlySpan span) + { + if (span.Pinnable == null) + unsafe { return ref Unsafe.AsRef(span.ByteOffset.ToPointer()); } + else + return ref Unsafe.AddByteOffset(ref span.Pinnable.Data, span.ByteOffset); + } + + /// + /// Get an array segment from the underlying memory. + /// If unable to get the array segment, return false with a default array segment. + /// + public static bool TryGetArray(ReadOnlyMemory readOnlyMemory, out ArraySegment arraySegment) + { + object obj = readOnlyMemory.GetObjectStartLength(out int index, out int length); + if (index < 0) + { + if (((OwnedMemory)obj).TryGetArray(out var segment)) + { + arraySegment = new ArraySegment(segment.Array, segment.Offset + (index & ReadOnlyMemory.RemoveOwnedFlagBitMask), length); + return true; + } + } + else if (obj is T[] arr) + { + arraySegment = new ArraySegment(arr, index, length); + return true; + } + + arraySegment = default; + return false; + } } } diff --git a/src/System.Memory/src/System/Span.cs b/src/System.Memory/src/System/Span.cs index 14ef12257618..159b996374aa 100644 --- a/src/System.Memory/src/System/Span.cs +++ b/src/System.Memory/src/System/Span.cs @@ -419,6 +419,7 @@ public T[] ToArray() public static Span Empty => default(Span); /// + /// This method is obsolete, use System.Runtime.InteropServices.MemoryMarshal.GetReference instead. /// Returns a reference to the 0th element of the Span. If the Span is empty, returns a reference to the location where the 0th element /// would have been stored. Such a reference can be used for pinning but must never be dereferenced. /// diff --git a/src/System.Memory/tests/Memory/Slice.cs b/src/System.Memory/tests/Memory/Slice.cs index 0f412114c208..c047472175fa 100644 --- a/src/System.Memory/tests/Memory/Slice.cs +++ b/src/System.Memory/tests/Memory/Slice.cs @@ -3,8 +3,9 @@ // See the LICENSE file in the project root for more information. using Xunit; -using System.Runtime.CompilerServices; using System.Buffers; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; namespace System.MemoryTests { @@ -16,13 +17,13 @@ public static void SliceWithStart() int[] a = { 90, 91, 92, 93, 94, 95, 96, 97, 98, 99 }; Memory memory = new Memory(a).Slice(6); Assert.Equal(4, memory.Length); - Assert.True(Unsafe.AreSame(ref a[6], ref memory.Span.DangerousGetPinnableReference())); + Assert.True(Unsafe.AreSame(ref a[6], ref MemoryMarshal.GetReference(memory.Span))); OwnedMemory owner = new CustomMemoryForTest(a); Memory memoryFromOwner = owner.Memory.Slice(6); Assert.Equal(4, memoryFromOwner.Length); - Assert.True(Unsafe.AreSame(ref a[6], ref memoryFromOwner.Span.DangerousGetPinnableReference())); + Assert.True(Unsafe.AreSame(ref a[6], ref MemoryMarshal.GetReference(memoryFromOwner.Span))); } [Fact] @@ -31,13 +32,13 @@ public static void SliceWithStartPastEnd() int[] a = { 90, 91, 92, 93, 94, 95, 96, 97, 98, 99 }; Memory memory = new Memory(a).Slice(a.Length); Assert.Equal(0, memory.Length); - Assert.True(Unsafe.AreSame(ref a[a.Length - 1], ref Unsafe.Subtract(ref memory.Span.DangerousGetPinnableReference(), 1))); + Assert.True(Unsafe.AreSame(ref a[a.Length - 1], ref Unsafe.Subtract(ref MemoryMarshal.GetReference(memory.Span), 1))); OwnedMemory owner = new CustomMemoryForTest(a); Memory memoryFromOwner = owner.Memory.Slice(a.Length); Assert.Equal(0, memoryFromOwner.Length); - Assert.True(Unsafe.AreSame(ref a[a.Length - 1], ref Unsafe.Subtract(ref memoryFromOwner.Span.DangerousGetPinnableReference(), 1))); + Assert.True(Unsafe.AreSame(ref a[a.Length - 1], ref Unsafe.Subtract(ref MemoryMarshal.GetReference(memoryFromOwner.Span), 1))); } [Fact] @@ -46,13 +47,13 @@ public static void SliceWithStartAndLength() int[] a = { 90, 91, 92, 93, 94, 95, 96, 97, 98, 99 }; Memory memory = new Memory(a).Slice(3, 5); Assert.Equal(5, memory.Length); - Assert.True(Unsafe.AreSame(ref a[3], ref memory.Span.DangerousGetPinnableReference())); + Assert.True(Unsafe.AreSame(ref a[3], ref MemoryMarshal.GetReference(memory.Span))); OwnedMemory owner = new CustomMemoryForTest(a); Memory memoryFromOwner = owner.Memory.Slice(3, 5); Assert.Equal(5, memoryFromOwner.Length); - Assert.True(Unsafe.AreSame(ref a[3], ref memoryFromOwner.Span.DangerousGetPinnableReference())); + Assert.True(Unsafe.AreSame(ref a[3], ref MemoryMarshal.GetReference(memoryFromOwner.Span))); } [Fact] @@ -61,13 +62,13 @@ public static void SliceWithStartAndLengthUpToEnd() int[] a = { 90, 91, 92, 93, 94, 95, 96, 97, 98, 99 }; Memory memory = new Memory(a).Slice(4, 6); Assert.Equal(6, memory.Length); - Assert.True(Unsafe.AreSame(ref a[4], ref memory.Span.DangerousGetPinnableReference())); + Assert.True(Unsafe.AreSame(ref a[4], ref MemoryMarshal.GetReference(memory.Span))); OwnedMemory owner = new CustomMemoryForTest(a); Memory memoryFromOwner = owner.Memory.Slice(4, 6); Assert.Equal(6, memoryFromOwner.Length); - Assert.True(Unsafe.AreSame(ref a[4], ref memoryFromOwner.Span.DangerousGetPinnableReference())); + Assert.True(Unsafe.AreSame(ref a[4], ref MemoryMarshal.GetReference(memoryFromOwner.Span))); } [Fact] @@ -76,13 +77,13 @@ public static void SliceWithStartAndLengthPastEnd() int[] a = { 90, 91, 92, 93, 94, 95, 96, 97, 98, 99 }; Memory memory = new Memory(a).Slice(a.Length, 0); Assert.Equal(0, memory.Length); - Assert.True(Unsafe.AreSame(ref a[a.Length - 1], ref Unsafe.Subtract(ref memory.Span.DangerousGetPinnableReference(), 1))); + Assert.True(Unsafe.AreSame(ref a[a.Length - 1], ref Unsafe.Subtract(ref MemoryMarshal.GetReference(memory.Span), 1))); OwnedMemory owner = new CustomMemoryForTest(a); Memory memoryFromOwner = owner.Memory.Slice(a.Length, 0); Assert.Equal(0, memoryFromOwner.Length); - Assert.True(Unsafe.AreSame(ref a[a.Length - 1], ref Unsafe.Subtract(ref memoryFromOwner.Span.DangerousGetPinnableReference(), 1))); + Assert.True(Unsafe.AreSame(ref a[a.Length - 1], ref Unsafe.Subtract(ref MemoryMarshal.GetReference(memoryFromOwner.Span), 1))); } [Fact] diff --git a/src/System.Memory/tests/MemoryMarshal/AsMemory.cs b/src/System.Memory/tests/MemoryMarshal/AsMemory.cs index f1ffa862ca18..0d9e9fc08b0e 100644 --- a/src/System.Memory/tests/MemoryMarshal/AsMemory.cs +++ b/src/System.Memory/tests/MemoryMarshal/AsMemory.cs @@ -81,7 +81,7 @@ private static unsafe void AsMemory_Roundtrips_Core(ReadOnlyMemory readOnl Assert.True(readOnlyMemory.Span == memory.Span); // TryGetArray - Assert.True(readOnlyMemory.DangerousTryGetArray(out ArraySegment array1) == memory.TryGetArray(out ArraySegment array2)); + Assert.True(MemoryMarshal.TryGetArray(readOnlyMemory, out ArraySegment array1) == memory.TryGetArray(out ArraySegment array2)); Assert.Same(array1.Array, array2.Array); Assert.Equal(array1.Offset, array2.Offset); Assert.Equal(array1.Count, array2.Count); diff --git a/src/System.Memory/tests/MemoryMarshal/GetReference.cs b/src/System.Memory/tests/MemoryMarshal/GetReference.cs new file mode 100644 index 000000000000..f0a58c7a8cf6 --- /dev/null +++ b/src/System.Memory/tests/MemoryMarshal/GetReference.cs @@ -0,0 +1,125 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Xunit; +using System.Runtime.CompilerServices; + +using static System.TestHelpers; +using System.Runtime.InteropServices; + +namespace System.SpanTests +{ + public static partial class MemoryMarshalTests + { + [Fact] + public static void SpanGetReferenceArray() + { + int[] a = { 91, 92, 93, 94, 95 }; + Span span = new Span(a, 1, 3); + ref int pinnableReference = ref MemoryMarshal.GetReference(span); + Assert.True(Unsafe.AreSame(ref a[1], ref pinnableReference)); + } + + [Fact] + public static void SpanGetReferenceArrayPastEnd() + { + // The only real difference between GetReference() and "ref span[0]" is that + // GetReference() of a zero-length won't throw an IndexOutOfRange. + + int[] a = { 91, 92, 93, 94, 95 }; + Span span = new Span(a, a.Length, 0); + ref int pinnableReference = ref MemoryMarshal.GetReference(span); + ref int expected = ref Unsafe.Add(ref a[a.Length - 1], 1); + Assert.True(Unsafe.AreSame(ref expected, ref pinnableReference)); + } + + [Fact] + public static void SpanGetReferencePointer() + { + unsafe + { + int i = 42; + Span span = new Span(&i, 1); + ref int pinnableReference = ref MemoryMarshal.GetReference(span); + Assert.True(Unsafe.AreSame(ref i, ref pinnableReference)); + } + } + + [Fact] + public static void SpanGetReferencePointerDangerousCreate1() + { + TestClass testClass = new TestClass(); + Span span = Span.DangerousCreate(testClass, ref testClass.C1, 3); + + ref char pinnableReference = ref MemoryMarshal.GetReference(span); + Assert.True(Unsafe.AreSame(ref testClass.C1, ref pinnableReference)); + } + + [Fact] + public static void SpanGetReferenceEmpty() + { + unsafe + { + Span span = Span.Empty; + ref int pinnableReference = ref MemoryMarshal.GetReference(span); + Assert.True(Unsafe.AreSame(ref Unsafe.AsRef(null), ref pinnableReference)); + } + } + + [Fact] + public static void ReadOnlySpanGetReferenceArray() + { + int[] a = { 91, 92, 93, 94, 95 }; + ReadOnlySpan span = new ReadOnlySpan(a, 1, 3); + ref int pinnableReference = ref Unsafe.AsRef(in MemoryMarshal.GetReference(span)); + Assert.True(Unsafe.AreSame(ref a[1], ref pinnableReference)); + } + + [Fact] + public static void ReadOnlySpanGetReferenceArrayPastEnd() + { + // The only real difference between GetReference() and "ref span[0]" is that + // GetReference() of a zero-length won't throw an IndexOutOfRange. + + int[] a = { 91, 92, 93, 94, 95 }; + ReadOnlySpan span = new ReadOnlySpan(a, a.Length, 0); + ref int pinnableReference = ref Unsafe.AsRef(in MemoryMarshal.GetReference(span)); + ref int expected = ref Unsafe.Add(ref a[a.Length - 1], 1); + Assert.True(Unsafe.AreSame(ref expected, ref pinnableReference)); + } + + [Fact] + public static void ReadOnlySpanGetReferencePointer() + { + unsafe + { + int i = 42; + ReadOnlySpan span = new ReadOnlySpan(&i, 1); + ref int pinnableReference = ref Unsafe.AsRef(in MemoryMarshal.GetReference(span)); + Assert.True(Unsafe.AreSame(ref i, ref pinnableReference)); + } + } + + [Fact] + public static void ReadOnlySpanGetReferencePointerDangerousCreate1() + { + TestClass testClass = new TestClass(); + ReadOnlySpan span = ReadOnlySpan.DangerousCreate(testClass, ref testClass.C1, 3); + + ref char pinnableReference = ref Unsafe.AsRef(in MemoryMarshal.GetReference(span)); + Assert.True(Unsafe.AreSame(ref testClass.C1, ref pinnableReference)); + } + + [Fact] + public static void ReadOnlySpanGetReferenceEmpty() + { + unsafe + { + ReadOnlySpan span = ReadOnlySpan.Empty; + ref int pinnableReference = ref Unsafe.AsRef(in MemoryMarshal.GetReference(span)); + Assert.True(Unsafe.AreSame(ref Unsafe.AsRef(null), ref pinnableReference)); + } + } + } +} diff --git a/src/System.Memory/tests/MemoryMarshal/TryGetArray.cs b/src/System.Memory/tests/MemoryMarshal/TryGetArray.cs new file mode 100644 index 000000000000..ebdc2ce438c6 --- /dev/null +++ b/src/System.Memory/tests/MemoryMarshal/TryGetArray.cs @@ -0,0 +1,50 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Buffers; +using System.Runtime.InteropServices; +using Xunit; + +namespace System.MemoryTests +{ + public static partial class MemoryMarshalTests + { + [Fact] + public static void ReadOnlyMemoryTryGetArray() + { + int[] array = new int[10]; + ReadOnlyMemory memory = array; + Assert.True(MemoryMarshal.TryGetArray(memory, out ArraySegment segment)); + Assert.Equal(array.Length, segment.Count); + + for (int i = segment.Offset; i < segment.Count + segment.Offset; i++) + { + Assert.Equal(array[i], segment.Array[i]); + } + } + + [Fact] + public static void TryGetArrayFromDefaultMemory() + { + ReadOnlyMemory memory = default; + Assert.False(MemoryMarshal.TryGetArray(memory, out ArraySegment segment)); + Assert.True(segment.Equals(default)); + } + + [Fact] + public static void OwnedMemoryTryGetArray() + { + int[] array = new int[10]; + OwnedMemory owner = new CustomMemoryForTest(array); + ReadOnlyMemory memory = owner.Memory; + Assert.True(MemoryMarshal.TryGetArray(memory, out ArraySegment segment)); + Assert.Equal(array.Length, segment.Count); + + for (int i = segment.Offset; i < segment.Count + segment.Offset; i++) + { + Assert.Equal(array[i], segment.Array[i]); + } + } + } +} diff --git a/src/System.Memory/tests/Performance/Perf.MemorySlice.cs b/src/System.Memory/tests/Performance/Perf.MemorySlice.cs index f8f3aa2f3fe6..d09774e0fbcf 100644 --- a/src/System.Memory/tests/Performance/Perf.MemorySlice.cs +++ b/src/System.Memory/tests/Performance/Perf.MemorySlice.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using System.Runtime.InteropServices; using Microsoft.Xunit.Performance; using Xunit; @@ -131,7 +132,7 @@ public static void ReadOnlyMemory_Byte_TryGetArray() { for (int i = 0; i < iters; i++) { - memory.DangerousTryGetArray(out result); + MemoryMarshal.TryGetArray(memory, out result); } } } @@ -152,7 +153,7 @@ public static void ReadOnlyMemory_Char_TryGetArray() { for (int i = 0; i < iters; i++) { - memory.DangerousTryGetArray(out result); + MemoryMarshal.TryGetArray(memory, out result); } } } diff --git a/src/System.Memory/tests/ReadOnlyMemory/Slice.cs b/src/System.Memory/tests/ReadOnlyMemory/Slice.cs index 7320aeeef95f..70404ecca401 100644 --- a/src/System.Memory/tests/ReadOnlyMemory/Slice.cs +++ b/src/System.Memory/tests/ReadOnlyMemory/Slice.cs @@ -3,8 +3,9 @@ // See the LICENSE file in the project root for more information. using Xunit; -using System.Runtime.CompilerServices; using System.Buffers; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; namespace System.MemoryTests { @@ -16,13 +17,13 @@ public static void SliceWithStart() int[] a = { 90, 91, 92, 93, 94, 95, 96, 97, 98, 99 }; ReadOnlyMemory memory = new ReadOnlyMemory(a).Slice(6); Assert.Equal(4, memory.Length); - Assert.True(Unsafe.AreSame(ref a[6], ref memory.Span.DangerousGetPinnableReference())); + Assert.True(Unsafe.AreSame(ref a[6], ref Unsafe.AsRef(in MemoryMarshal.GetReference(memory.Span)))); OwnedMemory owner = new CustomMemoryForTest(a); ReadOnlyMemory memoryFromOwner = ((ReadOnlyMemory)owner.Memory).Slice(6); Assert.Equal(4, memoryFromOwner.Length); - Assert.True(Unsafe.AreSame(ref a[6], ref memoryFromOwner.Span.DangerousGetPinnableReference())); + Assert.True(Unsafe.AreSame(ref a[6], ref Unsafe.AsRef(in MemoryMarshal.GetReference(memoryFromOwner.Span)))); } [Fact] @@ -31,13 +32,13 @@ public static void SliceWithStartPastEnd() int[] a = { 90, 91, 92, 93, 94, 95, 96, 97, 98, 99 }; ReadOnlyMemory memory = new ReadOnlyMemory(a).Slice(a.Length); Assert.Equal(0, memory.Length); - Assert.True(Unsafe.AreSame(ref a[a.Length - 1], ref Unsafe.Subtract(ref memory.Span.DangerousGetPinnableReference(), 1))); + Assert.True(Unsafe.AreSame(ref a[a.Length - 1], ref Unsafe.Subtract(ref Unsafe.AsRef(in MemoryMarshal.GetReference(memory.Span)), 1))); OwnedMemory owner = new CustomMemoryForTest(a); ReadOnlyMemory memoryFromOwner = ((ReadOnlyMemory)owner.Memory).Slice(a.Length); Assert.Equal(0, memoryFromOwner.Length); - Assert.True(Unsafe.AreSame(ref a[a.Length - 1], ref Unsafe.Subtract(ref memoryFromOwner.Span.DangerousGetPinnableReference(), 1))); + Assert.True(Unsafe.AreSame(ref a[a.Length - 1], ref Unsafe.Subtract(ref Unsafe.AsRef(in MemoryMarshal.GetReference(memoryFromOwner.Span)), 1))); } [Fact] @@ -46,13 +47,13 @@ public static void SliceWithStartAndLength() int[] a = { 90, 91, 92, 93, 94, 95, 96, 97, 98, 99 }; ReadOnlyMemory memory = new ReadOnlyMemory(a).Slice(3, 5); Assert.Equal(5, memory.Length); - Assert.True(Unsafe.AreSame(ref a[3], ref memory.Span.DangerousGetPinnableReference())); + Assert.True(Unsafe.AreSame(ref a[3], ref Unsafe.AsRef(in MemoryMarshal.GetReference(memory.Span)))); OwnedMemory owner = new CustomMemoryForTest(a); ReadOnlyMemory memoryFromOwner = ((ReadOnlyMemory)owner.Memory).Slice(3, 5); Assert.Equal(5, memoryFromOwner.Length); - Assert.True(Unsafe.AreSame(ref a[3], ref memoryFromOwner.Span.DangerousGetPinnableReference())); + Assert.True(Unsafe.AreSame(ref a[3], ref Unsafe.AsRef(in MemoryMarshal.GetReference(memoryFromOwner.Span)))); } [Fact] @@ -61,13 +62,13 @@ public static void SliceWithStartAndLengthUpToEnd() int[] a = { 90, 91, 92, 93, 94, 95, 96, 97, 98, 99 }; ReadOnlyMemory memory = new ReadOnlyMemory(a).Slice(4, 6); Assert.Equal(6, memory.Length); - Assert.True(Unsafe.AreSame(ref a[4], ref memory.Span.DangerousGetPinnableReference())); + Assert.True(Unsafe.AreSame(ref a[4], ref Unsafe.AsRef(in MemoryMarshal.GetReference(memory.Span)))); OwnedMemory owner = new CustomMemoryForTest(a); ReadOnlyMemory memoryFromOwner = ((ReadOnlyMemory)owner.Memory).Slice(4, 6); Assert.Equal(6, memoryFromOwner.Length); - Assert.True(Unsafe.AreSame(ref a[4], ref memoryFromOwner.Span.DangerousGetPinnableReference())); + Assert.True(Unsafe.AreSame(ref a[4], ref Unsafe.AsRef(in MemoryMarshal.GetReference(memoryFromOwner.Span)))); } [Fact] @@ -76,13 +77,13 @@ public static void SliceWithStartAndLengthPastEnd() int[] a = { 90, 91, 92, 93, 94, 95, 96, 97, 98, 99 }; ReadOnlyMemory memory = new ReadOnlyMemory(a).Slice(a.Length, 0); Assert.Equal(0, memory.Length); - Assert.True(Unsafe.AreSame(ref a[a.Length - 1], ref Unsafe.Subtract(ref memory.Span.DangerousGetPinnableReference(), 1))); + Assert.True(Unsafe.AreSame(ref a[a.Length - 1], ref Unsafe.Subtract(ref Unsafe.AsRef(in MemoryMarshal.GetReference(memory.Span)), 1))); OwnedMemory owner = new CustomMemoryForTest(a); ReadOnlyMemory memoryFromOwner = ((ReadOnlyMemory)owner.Memory).Slice(a.Length, 0); Assert.Equal(0, memoryFromOwner.Length); - Assert.True(Unsafe.AreSame(ref a[a.Length - 1], ref Unsafe.Subtract(ref memoryFromOwner.Span.DangerousGetPinnableReference(), 1))); + Assert.True(Unsafe.AreSame(ref a[a.Length - 1], ref Unsafe.Subtract(ref Unsafe.AsRef(in MemoryMarshal.GetReference(memoryFromOwner.Span)), 1))); } [Fact] diff --git a/src/System.Memory/tests/ReadOnlyMemory/Strings.cs b/src/System.Memory/tests/ReadOnlyMemory/Strings.cs index 6b77f3301b04..785144ac8c46 100644 --- a/src/System.Memory/tests/ReadOnlyMemory/Strings.cs +++ b/src/System.Memory/tests/ReadOnlyMemory/Strings.cs @@ -5,6 +5,7 @@ using Xunit; using System.Buffers; using System.Collections.Generic; +using System.Runtime.InteropServices; namespace System.MemoryTests { @@ -127,7 +128,7 @@ public static void Array_TryGetString_ReturnsFalse() public static void AsReadOnlyMemory_TryGetArray_ReturnsFalse() { ReadOnlyMemory m = "0123456789".AsReadOnlyMemory(); - Assert.False(m.DangerousTryGetArray(out ArraySegment array)); + Assert.False(MemoryMarshal.TryGetArray(m, out ArraySegment array)); Assert.Null(array.Array); Assert.Equal(0, array.Offset); Assert.Equal(0, array.Count); diff --git a/src/System.Memory/tests/ReadOnlySpan/AsBytes.cs b/src/System.Memory/tests/ReadOnlySpan/AsBytes.cs index 9493f7a1b27d..66aad3d6cf2b 100644 --- a/src/System.Memory/tests/ReadOnlySpan/AsBytes.cs +++ b/src/System.Memory/tests/ReadOnlySpan/AsBytes.cs @@ -4,6 +4,7 @@ using Xunit; using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; namespace System.SpanTests { @@ -16,7 +17,7 @@ public static void AsBytesUIntToByte() ReadOnlySpan span = new ReadOnlySpan(a); ReadOnlySpan asBytes = span.AsBytes(); - Assert.True(Unsafe.AreSame(ref Unsafe.As(ref span.DangerousGetPinnableReference()), ref asBytes.DangerousGetPinnableReference())); + Assert.True(Unsafe.AreSame(ref Unsafe.As(ref Unsafe.AsRef(in MemoryMarshal.GetReference(span))), ref Unsafe.AsRef(in MemoryMarshal.GetReference(asBytes)))); asBytes.Validate(0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88); } diff --git a/src/System.Memory/tests/ReadOnlySpan/CtorPointerInt.cs b/src/System.Memory/tests/ReadOnlySpan/CtorPointerInt.cs index 3cf399b05531..5cfcb97d4f68 100644 --- a/src/System.Memory/tests/ReadOnlySpan/CtorPointerInt.cs +++ b/src/System.Memory/tests/ReadOnlySpan/CtorPointerInt.cs @@ -4,6 +4,7 @@ using Xunit; using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; #pragma warning disable 0649 //Field 'SpanTests.InnerStruct.J' is never assigned to, and will always have its default value 0 @@ -21,7 +22,7 @@ public static void CtorPointerInt() { ReadOnlySpan span = new ReadOnlySpan(pa, 3); span.Validate(90, 91, 92); - Assert.True(Unsafe.AreSame(ref Unsafe.AsRef(pa), ref span.DangerousGetPinnableReference())); + Assert.True(Unsafe.AreSame(ref Unsafe.AsRef(pa), ref Unsafe.AsRef(in MemoryMarshal.GetReference(span)))); } } } @@ -33,7 +34,7 @@ public static void CtorPointerNull() { ReadOnlySpan span = new ReadOnlySpan((void*)null, 0); span.Validate(); - Assert.True(Unsafe.AreSame(ref Unsafe.AsRef((void*)null), ref span.DangerousGetPinnableReference())); + Assert.True(Unsafe.AreSame(ref Unsafe.AsRef((void*)null), ref Unsafe.AsRef(in MemoryMarshal.GetReference(span)))); } } diff --git a/src/System.Memory/tests/ReadOnlySpan/DangerousCreate.cs b/src/System.Memory/tests/ReadOnlySpan/DangerousCreate.cs index fd1be1656b04..e9feb2f935fd 100644 --- a/src/System.Memory/tests/ReadOnlySpan/DangerousCreate.cs +++ b/src/System.Memory/tests/ReadOnlySpan/DangerousCreate.cs @@ -4,6 +4,8 @@ using Xunit; using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + using static System.TestHelpers; namespace System.SpanTests @@ -24,7 +26,7 @@ public static void DangerousCreate1() ReadOnlySpan span = ReadOnlySpan.DangerousCreate(testClass, ref testClass.C1, 3); span.Validate('b', 'c', 'd'); - ref char pc1 = ref span.DangerousGetPinnableReference(); + ref char pc1 = ref Unsafe.AsRef(in MemoryMarshal.GetReference(span)); Assert.True(Unsafe.AreSame(ref testClass.C1, ref pc1)); } } diff --git a/src/System.Memory/tests/ReadOnlySpan/DangerousGetPinnableReference.cs b/src/System.Memory/tests/ReadOnlySpan/DangerousGetPinnableReference.cs index 9f93501235a2..1aa4a9c5b9c8 100644 --- a/src/System.Memory/tests/ReadOnlySpan/DangerousGetPinnableReference.cs +++ b/src/System.Memory/tests/ReadOnlySpan/DangerousGetPinnableReference.cs @@ -4,6 +4,7 @@ using Xunit; using System.Runtime.CompilerServices; + using static System.TestHelpers; namespace System.SpanTests diff --git a/src/System.Memory/tests/ReadOnlySpan/Empty.cs b/src/System.Memory/tests/ReadOnlySpan/Empty.cs index 0af910dfecaf..3f6339bdeaf5 100644 --- a/src/System.Memory/tests/ReadOnlySpan/Empty.cs +++ b/src/System.Memory/tests/ReadOnlySpan/Empty.cs @@ -4,6 +4,7 @@ using Xunit; using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; namespace System.SpanTests { @@ -18,7 +19,7 @@ public static void Empty() unsafe { ref int expected = ref Unsafe.AsRef(null); - ref int actual = ref empty.DangerousGetPinnableReference(); + ref int actual = ref Unsafe.AsRef(in MemoryMarshal.GetReference(empty)); Assert.True(Unsafe.AreSame(ref expected, ref actual)); } } diff --git a/src/System.Memory/tests/ReadOnlySpan/NonPortableCast.cs b/src/System.Memory/tests/ReadOnlySpan/NonPortableCast.cs index 2a360a205c3b..20487996fe72 100644 --- a/src/System.Memory/tests/ReadOnlySpan/NonPortableCast.cs +++ b/src/System.Memory/tests/ReadOnlySpan/NonPortableCast.cs @@ -4,6 +4,7 @@ using Xunit; using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; namespace System.SpanTests { @@ -16,7 +17,7 @@ public static void PortableCastUIntToUShort() ReadOnlySpan span = new ReadOnlySpan(a); ReadOnlySpan asUShort = span.NonPortableCast(); - Assert.True(Unsafe.AreSame(ref Unsafe.As(ref span.DangerousGetPinnableReference()), ref asUShort.DangerousGetPinnableReference())); + Assert.True(Unsafe.AreSame(ref Unsafe.As(ref Unsafe.AsRef(in MemoryMarshal.GetReference(span))), ref Unsafe.AsRef(in MemoryMarshal.GetReference(asUShort)))); asUShort.Validate(0x2211, 0x4433, 0x6655, 0x8877); } diff --git a/src/System.Memory/tests/ReadOnlySpan/Overflow.cs b/src/System.Memory/tests/ReadOnlySpan/Overflow.cs index dc9ed088e7a6..3c29d866a626 100644 --- a/src/System.Memory/tests/ReadOnlySpan/Overflow.cs +++ b/src/System.Memory/tests/ReadOnlySpan/Overflow.cs @@ -4,6 +4,7 @@ using Xunit; using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; namespace System.SpanTests { @@ -48,10 +49,10 @@ public static void IndexOverflow() Assert.Equal(expectedGuid, actualGuid); ReadOnlySpan slice = span.Slice(bigIndex); - Assert.True(Unsafe.AreSame(ref expected, ref slice.DangerousGetPinnableReference())); + Assert.True(Unsafe.AreSame(ref expected, ref Unsafe.AsRef(in MemoryMarshal.GetReference(slice)))); slice = span.Slice(bigIndex, 1); - Assert.True(Unsafe.AreSame(ref expected, ref slice.DangerousGetPinnableReference())); + Assert.True(Unsafe.AreSame(ref expected, ref Unsafe.AsRef(in MemoryMarshal.GetReference(slice)))); } finally { diff --git a/src/System.Memory/tests/ReadOnlySpan/Slice.cs b/src/System.Memory/tests/ReadOnlySpan/Slice.cs index 5efa1f1b3ebd..d4aa7f076e9a 100644 --- a/src/System.Memory/tests/ReadOnlySpan/Slice.cs +++ b/src/System.Memory/tests/ReadOnlySpan/Slice.cs @@ -4,6 +4,7 @@ using Xunit; using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; namespace System.SpanTests { @@ -15,7 +16,7 @@ public static void SliceInt() int[] a = { 90, 91, 92, 93, 94, 95, 96, 97, 98, 99 }; ReadOnlySpan span = new ReadOnlySpan(a).Slice(6); Assert.Equal(4, span.Length); - Assert.True(Unsafe.AreSame(ref a[6], ref span.DangerousGetPinnableReference())); + Assert.True(Unsafe.AreSame(ref a[6], ref Unsafe.AsRef(in MemoryMarshal.GetReference(span)))); } [Fact] @@ -24,7 +25,7 @@ public static void SliceIntPastEnd() int[] a = { 90, 91, 92, 93, 94, 95, 96, 97, 98, 99 }; ReadOnlySpan span = new ReadOnlySpan(a).Slice(a.Length); Assert.Equal(0, span.Length); - Assert.True(Unsafe.AreSame(ref a[a.Length - 1], ref Unsafe.Subtract(ref span.DangerousGetPinnableReference(), 1))); + Assert.True(Unsafe.AreSame(ref a[a.Length - 1], ref Unsafe.Subtract(ref Unsafe.AsRef(in MemoryMarshal.GetReference(span)), 1))); } [Fact] @@ -33,7 +34,7 @@ public static void SliceIntInt() int[] a = { 90, 91, 92, 93, 94, 95, 96, 97, 98, 99 }; ReadOnlySpan span = new ReadOnlySpan(a).Slice(3, 5); Assert.Equal(5, span.Length); - Assert.True(Unsafe.AreSame(ref a[3], ref span.DangerousGetPinnableReference())); + Assert.True(Unsafe.AreSame(ref a[3], ref Unsafe.AsRef(in MemoryMarshal.GetReference(span)))); } [Fact] @@ -42,7 +43,7 @@ public static void SliceIntIntUpToEnd() int[] a = { 90, 91, 92, 93, 94, 95, 96, 97, 98, 99 }; ReadOnlySpan span = new ReadOnlySpan(a).Slice(4, 6); Assert.Equal(6, span.Length); - Assert.True(Unsafe.AreSame(ref a[4], ref span.DangerousGetPinnableReference())); + Assert.True(Unsafe.AreSame(ref a[4], ref Unsafe.AsRef(in MemoryMarshal.GetReference(span)))); } [Fact] @@ -51,7 +52,7 @@ public static void SliceIntIntPastEnd() int[] a = { 90, 91, 92, 93, 94, 95, 96, 97, 98, 99 }; ReadOnlySpan span = new ReadOnlySpan(a).Slice(a.Length, 0); Assert.Equal(0, span.Length); - Assert.True(Unsafe.AreSame(ref a[a.Length - 1], ref Unsafe.Subtract(ref span.DangerousGetPinnableReference(), 1))); + Assert.True(Unsafe.AreSame(ref a[a.Length - 1], ref Unsafe.Subtract(ref Unsafe.AsRef(in MemoryMarshal.GetReference(span)), 1))); } [Fact] diff --git a/src/System.Memory/tests/Span/AsBytes.cs b/src/System.Memory/tests/Span/AsBytes.cs index 0eabb23abab9..dbbe885aaa82 100644 --- a/src/System.Memory/tests/Span/AsBytes.cs +++ b/src/System.Memory/tests/Span/AsBytes.cs @@ -4,6 +4,7 @@ using Xunit; using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; namespace System.SpanTests { @@ -16,7 +17,7 @@ public static void AsBytesUIntToByte() Span span = new Span(a); Span asBytes = span.AsBytes(); - Assert.True(Unsafe.AreSame(ref Unsafe.As(ref span.DangerousGetPinnableReference()), ref asBytes.DangerousGetPinnableReference())); + Assert.True(Unsafe.AreSame(ref Unsafe.As(ref MemoryMarshal.GetReference(span)), ref MemoryMarshal.GetReference(asBytes))); asBytes.Validate(0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88); } diff --git a/src/System.Memory/tests/Span/CtorPointerInt.cs b/src/System.Memory/tests/Span/CtorPointerInt.cs index 2d11fa5829a0..9194da2fcae7 100644 --- a/src/System.Memory/tests/Span/CtorPointerInt.cs +++ b/src/System.Memory/tests/Span/CtorPointerInt.cs @@ -4,6 +4,7 @@ using Xunit; using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; #pragma warning disable 0649 //Field 'SpanTests.InnerStruct.J' is never assigned to, and will always have its default value 0 @@ -21,7 +22,7 @@ public static void CtorPointerInt() { Span span = new Span(pa, 3); span.Validate(90, 91, 92); - Assert.True(Unsafe.AreSame(ref Unsafe.AsRef(pa), ref span.DangerousGetPinnableReference())); + Assert.True(Unsafe.AreSame(ref Unsafe.AsRef(pa), ref MemoryMarshal.GetReference(span))); } } } @@ -33,7 +34,7 @@ public static void CtorPointerNull() { Span span = new Span((void*)null, 0); span.Validate(); - Assert.True(Unsafe.AreSame(ref Unsafe.AsRef((void*)null), ref span.DangerousGetPinnableReference())); + Assert.True(Unsafe.AreSame(ref Unsafe.AsRef((void*)null), ref MemoryMarshal.GetReference(span))); } } diff --git a/src/System.Memory/tests/Span/DangerousCreate.cs b/src/System.Memory/tests/Span/DangerousCreate.cs index f41fa1e9ec45..ad6e968b8b9b 100644 --- a/src/System.Memory/tests/Span/DangerousCreate.cs +++ b/src/System.Memory/tests/Span/DangerousCreate.cs @@ -4,6 +4,8 @@ using Xunit; using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + using static System.TestHelpers; namespace System.SpanTests @@ -24,7 +26,7 @@ public static void DangerousCreate1() Span span = Span.DangerousCreate(testClass, ref testClass.C1, 3); span.Validate('b', 'c', 'd'); - ref char pc1 = ref span.DangerousGetPinnableReference(); + ref char pc1 = ref MemoryMarshal.GetReference(span); Assert.True(Unsafe.AreSame(ref testClass.C1, ref pc1)); } } diff --git a/src/System.Memory/tests/Span/DangerousGetPinnableReference.cs b/src/System.Memory/tests/Span/DangerousGetPinnableReference.cs index 11e0bcf31c42..40109f0aa31c 100644 --- a/src/System.Memory/tests/Span/DangerousGetPinnableReference.cs +++ b/src/System.Memory/tests/Span/DangerousGetPinnableReference.cs @@ -4,6 +4,7 @@ using Xunit; using System.Runtime.CompilerServices; + using static System.TestHelpers; namespace System.SpanTests diff --git a/src/System.Memory/tests/Span/Empty.cs b/src/System.Memory/tests/Span/Empty.cs index 8d8d1a4dc729..60104e52f9df 100644 --- a/src/System.Memory/tests/Span/Empty.cs +++ b/src/System.Memory/tests/Span/Empty.cs @@ -4,6 +4,7 @@ using Xunit; using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; namespace System.SpanTests { @@ -18,7 +19,7 @@ public static void Empty() unsafe { ref int expected = ref Unsafe.AsRef(null); - ref int actual = ref empty.DangerousGetPinnableReference(); + ref int actual = ref MemoryMarshal.GetReference(empty); Assert.True(Unsafe.AreSame(ref expected, ref actual)); } } diff --git a/src/System.Memory/tests/Span/NonPortableCast.cs b/src/System.Memory/tests/Span/NonPortableCast.cs index 18b80f7b4965..96326957e5dc 100644 --- a/src/System.Memory/tests/Span/NonPortableCast.cs +++ b/src/System.Memory/tests/Span/NonPortableCast.cs @@ -4,6 +4,7 @@ using Xunit; using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; namespace System.SpanTests { @@ -16,7 +17,7 @@ public static void PortableCastUIntToUShort() Span span = new Span(a); Span asUShort = span.NonPortableCast(); - Assert.True(Unsafe.AreSame(ref Unsafe.As(ref span.DangerousGetPinnableReference()), ref asUShort.DangerousGetPinnableReference())); + Assert.True(Unsafe.AreSame(ref Unsafe.As(ref MemoryMarshal.GetReference(span)), ref MemoryMarshal.GetReference(asUShort))); asUShort.Validate(0x2211, 0x4433, 0x6655, 0x8877); } diff --git a/src/System.Memory/tests/Span/Overflow.cs b/src/System.Memory/tests/Span/Overflow.cs index b9f9070f1b99..1532bf54e3d7 100644 --- a/src/System.Memory/tests/Span/Overflow.cs +++ b/src/System.Memory/tests/Span/Overflow.cs @@ -4,6 +4,7 @@ using Xunit; using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; namespace System.SpanTests { @@ -46,10 +47,10 @@ public static void IndexOverflow() Assert.True(Unsafe.AreSame(ref expected, ref span[bigIndex])); Span slice = span.Slice(bigIndex); - Assert.True(Unsafe.AreSame(ref expected, ref slice.DangerousGetPinnableReference())); + Assert.True(Unsafe.AreSame(ref expected, ref MemoryMarshal.GetReference(slice))); slice = span.Slice(bigIndex, 1); - Assert.True(Unsafe.AreSame(ref expected, ref slice.DangerousGetPinnableReference())); + Assert.True(Unsafe.AreSame(ref expected, ref MemoryMarshal.GetReference(slice))); } finally { diff --git a/src/System.Memory/tests/Span/Slice.cs b/src/System.Memory/tests/Span/Slice.cs index 968f66ca00a2..2cda00f23a3d 100644 --- a/src/System.Memory/tests/Span/Slice.cs +++ b/src/System.Memory/tests/Span/Slice.cs @@ -4,6 +4,7 @@ using Xunit; using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; namespace System.SpanTests { @@ -15,7 +16,7 @@ public static void SliceInt() int[] a = { 90, 91, 92, 93, 94, 95, 96, 97, 98, 99 }; Span span = new Span(a).Slice(6); Assert.Equal(4, span.Length); - Assert.True(Unsafe.AreSame(ref a[6], ref span.DangerousGetPinnableReference())); + Assert.True(Unsafe.AreSame(ref a[6], ref MemoryMarshal.GetReference(span))); } [Fact] @@ -24,7 +25,7 @@ public static void SliceIntPastEnd() int[] a = { 90, 91, 92, 93, 94, 95, 96, 97, 98, 99 }; Span span = new Span(a).Slice(a.Length); Assert.Equal(0, span.Length); - Assert.True(Unsafe.AreSame(ref a[a.Length - 1], ref Unsafe.Subtract(ref span.DangerousGetPinnableReference(), 1))); + Assert.True(Unsafe.AreSame(ref a[a.Length - 1], ref Unsafe.Subtract(ref MemoryMarshal.GetReference(span), 1))); } [Fact] @@ -33,7 +34,7 @@ public static void SliceIntInt() int[] a = { 90, 91, 92, 93, 94, 95, 96, 97, 98, 99 }; Span span = new Span(a).Slice(3, 5); Assert.Equal(5, span.Length); - Assert.True(Unsafe.AreSame(ref a[3], ref span.DangerousGetPinnableReference())); + Assert.True(Unsafe.AreSame(ref a[3], ref MemoryMarshal.GetReference(span))); } [Fact] @@ -42,7 +43,7 @@ public static void SliceIntIntUpToEnd() int[] a = { 90, 91, 92, 93, 94, 95, 96, 97, 98, 99 }; Span span = new Span(a).Slice(4, 6); Assert.Equal(6, span.Length); - Assert.True(Unsafe.AreSame(ref a[4], ref span.DangerousGetPinnableReference())); + Assert.True(Unsafe.AreSame(ref a[4], ref MemoryMarshal.GetReference(span))); } [Fact] @@ -51,7 +52,7 @@ public static void SliceIntIntPastEnd() int[] a = { 90, 91, 92, 93, 94, 95, 96, 97, 98, 99 }; Span span = new Span(a).Slice(a.Length, 0); Assert.Equal(0, span.Length); - Assert.True(Unsafe.AreSame(ref a[a.Length - 1], ref Unsafe.Subtract(ref span.DangerousGetPinnableReference(), 1))); + Assert.True(Unsafe.AreSame(ref a[a.Length - 1], ref Unsafe.Subtract(ref MemoryMarshal.GetReference(span), 1))); } [Fact] diff --git a/src/System.Memory/tests/System.Memory.Tests.csproj b/src/System.Memory/tests/System.Memory.Tests.csproj index f85ef2582814..ac818c4f5d80 100644 --- a/src/System.Memory/tests/System.Memory.Tests.csproj +++ b/src/System.Memory/tests/System.Memory.Tests.csproj @@ -101,6 +101,8 @@ + +