From f6ad03c772831d4358912f424b6f7e54571058f8 Mon Sep 17 00:00:00 2001 From: ahsonkhan Date: Thu, 7 Dec 2017 10:54:45 -0800 Subject: [PATCH 1/4] Add GetReference and TryGetArray to MemoryMarshal --- src/mscorlib/shared/System/ReadOnlyMemory.cs | 2 +- src/mscorlib/shared/System/ReadOnlySpan.cs | 3 ++ .../Runtime/InteropServices/MemoryMarshal.cs | 32 +++++++++++++++++++ src/mscorlib/shared/System/Span.cs | 3 ++ 4 files changed, 39 insertions(+), 1 deletion(-) diff --git a/src/mscorlib/shared/System/ReadOnlyMemory.cs b/src/mscorlib/shared/System/ReadOnlyMemory.cs index d68f622cce7a..bdf92ff65dd1 100644 --- a/src/mscorlib/shared/System/ReadOnlyMemory.cs +++ b/src/mscorlib/shared/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/mscorlib/shared/System/ReadOnlySpan.cs b/src/mscorlib/shared/System/ReadOnlySpan.cs index 7a8243d669a0..f9feb29918e2 100644 --- a/src/mscorlib/shared/System/ReadOnlySpan.cs +++ b/src/mscorlib/shared/System/ReadOnlySpan.cs @@ -322,6 +322,9 @@ public T[] ToArray() /// public static ReadOnlySpan Empty => default(ReadOnlySpan); + // This exposes the internal representation for Span-related apis use only. + internal ByReference Pointer => _pointer; + /// Gets an enumerator for this span. public Enumerator GetEnumerator() => new Enumerator(this); diff --git a/src/mscorlib/shared/System/Runtime/InteropServices/MemoryMarshal.cs b/src/mscorlib/shared/System/Runtime/InteropServices/MemoryMarshal.cs index 5301f8771384..1a66e22e4b27 100644 --- a/src/mscorlib/shared/System/Runtime/InteropServices/MemoryMarshal.cs +++ b/src/mscorlib/shared/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,36 @@ public static class MemoryMarshal /// public static Memory AsMemory(ReadOnlyMemory readOnlyMemory) => Unsafe.As, Memory>(ref readOnlyMemory); + + public static ref T GetReference(in Span span) + { + return ref span.Pointer.Value; + } + + public static ref readonly T GetReference(in ReadOnlySpan span) + { + return ref span.Pointer.Value; + } + + 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/mscorlib/shared/System/Span.cs b/src/mscorlib/shared/System/Span.cs index ca146aef6597..e830ab215057 100644 --- a/src/mscorlib/shared/System/Span.cs +++ b/src/mscorlib/shared/System/Span.cs @@ -409,6 +409,9 @@ public T[] ToArray() /// public static Span Empty => default(Span); + // This exposes the internal representation for Span-related apis use only. + internal ByReference Pointer => _pointer; + /// Gets an enumerator for this span. public Enumerator GetEnumerator() => new Enumerator(this); From 1a375101a0505839a088b1cb65079aa3df030169 Mon Sep 17 00:00:00 2001 From: ahsonkhan Date: Thu, 7 Dec 2017 11:11:05 -0800 Subject: [PATCH 2/4] Marking GetReference with AggressiveInlining --- .../shared/System/Runtime/InteropServices/MemoryMarshal.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/mscorlib/shared/System/Runtime/InteropServices/MemoryMarshal.cs b/src/mscorlib/shared/System/Runtime/InteropServices/MemoryMarshal.cs index 1a66e22e4b27..8fa4d036c9f5 100644 --- a/src/mscorlib/shared/System/Runtime/InteropServices/MemoryMarshal.cs +++ b/src/mscorlib/shared/System/Runtime/InteropServices/MemoryMarshal.cs @@ -25,11 +25,13 @@ public static class MemoryMarshal public static Memory AsMemory(ReadOnlyMemory readOnlyMemory) => Unsafe.As, Memory>(ref readOnlyMemory); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static ref T GetReference(in Span span) { return ref span.Pointer.Value; } + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static ref readonly T GetReference(in ReadOnlySpan span) { return ref span.Pointer.Value; From b5d48fc364cd1231efdc26a46dc66f3c369e18e4 Mon Sep 17 00:00:00 2001 From: ahsonkhan Date: Thu, 7 Dec 2017 11:42:36 -0800 Subject: [PATCH 3/4] Do not use ByReference as a return type. --- src/mscorlib/shared/System/ReadOnlySpan.cs | 2 +- .../System/Runtime/InteropServices/MemoryMarshal.cs | 10 ++-------- src/mscorlib/shared/System/Span.cs | 2 +- 3 files changed, 4 insertions(+), 10 deletions(-) diff --git a/src/mscorlib/shared/System/ReadOnlySpan.cs b/src/mscorlib/shared/System/ReadOnlySpan.cs index f9feb29918e2..6ce3fa04a528 100644 --- a/src/mscorlib/shared/System/ReadOnlySpan.cs +++ b/src/mscorlib/shared/System/ReadOnlySpan.cs @@ -323,7 +323,7 @@ public T[] ToArray() public static ReadOnlySpan Empty => default(ReadOnlySpan); // This exposes the internal representation for Span-related apis use only. - internal ByReference Pointer => _pointer; + internal ref readonly T Reference => ref _pointer.Value; /// Gets an enumerator for this span. public Enumerator GetEnumerator() => new Enumerator(this); diff --git a/src/mscorlib/shared/System/Runtime/InteropServices/MemoryMarshal.cs b/src/mscorlib/shared/System/Runtime/InteropServices/MemoryMarshal.cs index 8fa4d036c9f5..81dddd13f1ab 100644 --- a/src/mscorlib/shared/System/Runtime/InteropServices/MemoryMarshal.cs +++ b/src/mscorlib/shared/System/Runtime/InteropServices/MemoryMarshal.cs @@ -26,16 +26,10 @@ public static Memory AsMemory(ReadOnlyMemory readOnlyMemory) => Unsafe.As, Memory>(ref readOnlyMemory); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static ref T GetReference(in Span span) - { - return ref span.Pointer.Value; - } + public static ref T GetReference(in Span span) => ref span.Reference; [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static ref readonly T GetReference(in ReadOnlySpan span) - { - return ref span.Pointer.Value; - } + public static ref readonly T GetReference(in ReadOnlySpan span) => ref span.Reference; public static bool TryGetArray(ReadOnlyMemory readOnlyMemory, out ArraySegment arraySegment) { diff --git a/src/mscorlib/shared/System/Span.cs b/src/mscorlib/shared/System/Span.cs index e830ab215057..16a4c949fa7b 100644 --- a/src/mscorlib/shared/System/Span.cs +++ b/src/mscorlib/shared/System/Span.cs @@ -410,7 +410,7 @@ public T[] ToArray() public static Span Empty => default(Span); // This exposes the internal representation for Span-related apis use only. - internal ByReference Pointer => _pointer; + internal ref T Reference => ref _pointer.Value; /// Gets an enumerator for this span. public Enumerator GetEnumerator() => new Enumerator(this); From eefba81d84643265207525907ab3bad2d81e10e9 Mon Sep 17 00:00:00 2001 From: ahsonkhan Date: Thu, 7 Dec 2017 20:41:11 -0800 Subject: [PATCH 4/4] Addressing PR feedback. --- src/mscorlib/shared/System/ReadOnlySpan.cs | 5 +---- .../System/Runtime/InteropServices/MemoryMarshal.cs | 8 +++----- src/mscorlib/shared/System/Span.cs | 5 +---- 3 files changed, 5 insertions(+), 13 deletions(-) diff --git a/src/mscorlib/shared/System/ReadOnlySpan.cs b/src/mscorlib/shared/System/ReadOnlySpan.cs index 6ce3fa04a528..a7f6f6e64eb1 100644 --- a/src/mscorlib/shared/System/ReadOnlySpan.cs +++ b/src/mscorlib/shared/System/ReadOnlySpan.cs @@ -21,7 +21,7 @@ namespace System public readonly ref struct ReadOnlySpan { /// A byref or a native ptr. - private readonly ByReference _pointer; + internal readonly ByReference _pointer; /// The number of elements this ReadOnlySpan contains. #if PROJECTN [Bound] @@ -322,9 +322,6 @@ public T[] ToArray() /// public static ReadOnlySpan Empty => default(ReadOnlySpan); - // This exposes the internal representation for Span-related apis use only. - internal ref readonly T Reference => ref _pointer.Value; - /// Gets an enumerator for this span. public Enumerator GetEnumerator() => new Enumerator(this); diff --git a/src/mscorlib/shared/System/Runtime/InteropServices/MemoryMarshal.cs b/src/mscorlib/shared/System/Runtime/InteropServices/MemoryMarshal.cs index 81dddd13f1ab..5ee643f2d2e3 100644 --- a/src/mscorlib/shared/System/Runtime/InteropServices/MemoryMarshal.cs +++ b/src/mscorlib/shared/System/Runtime/InteropServices/MemoryMarshal.cs @@ -24,12 +24,10 @@ public static class MemoryMarshal /// public static Memory AsMemory(ReadOnlyMemory readOnlyMemory) => Unsafe.As, Memory>(ref readOnlyMemory); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static ref T GetReference(in Span span) => ref span.Reference; - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static ref readonly T GetReference(in ReadOnlySpan span) => ref span.Reference; + public static ref T GetReference(Span span) => ref span._pointer.Value; + + public static ref readonly T GetReference(ReadOnlySpan span) => ref span._pointer.Value; public static bool TryGetArray(ReadOnlyMemory readOnlyMemory, out ArraySegment arraySegment) { diff --git a/src/mscorlib/shared/System/Span.cs b/src/mscorlib/shared/System/Span.cs index 16a4c949fa7b..45d630d18595 100644 --- a/src/mscorlib/shared/System/Span.cs +++ b/src/mscorlib/shared/System/Span.cs @@ -27,7 +27,7 @@ namespace System public readonly ref struct Span { /// A byref or a native ptr. - private readonly ByReference _pointer; + internal readonly ByReference _pointer; /// The number of elements this Span contains. #if PROJECTN [Bound] @@ -409,9 +409,6 @@ public T[] ToArray() /// public static Span Empty => default(Span); - // This exposes the internal representation for Span-related apis use only. - internal ref T Reference => ref _pointer.Value; - /// Gets an enumerator for this span. public Enumerator GetEnumerator() => new Enumerator(this);