summaryrefslogtreecommitdiff
path: root/src/mscorlib/shared
diff options
context:
space:
mode:
authorAhson Khan <ahkha@microsoft.com>2018-03-27 17:05:33 -0700
committerGitHub <noreply@github.com>2018-03-27 17:05:33 -0700
commit0578152ed085597fd5e7f35e63ac2b9b4a5a7f28 (patch)
treedc1eee5480cff8ba1977fb2e038b8ccccb4c2145 /src/mscorlib/shared
parent65bf37cbbb7290c9f52402fa380b1d3a8dae6b83 (diff)
downloadcoreclr-0578152ed085597fd5e7f35e63ac2b9b4a5a7f28.tar.gz
coreclr-0578152ed085597fd5e7f35e63ac2b9b4a5a7f28.tar.bz2
coreclr-0578152ed085597fd5e7f35e63ac2b9b4a5a7f28.zip
Adding Memory.Pin() to eventually replace Memory.Retain(bool) (#17269)
* Adding Memory.Pin() to eventually replace Memory.Retain(bool) * Fix copy/paste error and return default for when object is null. * Fix XML comments.
Diffstat (limited to 'src/mscorlib/shared')
-rw-r--r--src/mscorlib/shared/System/Memory.cs44
-rw-r--r--src/mscorlib/shared/System/ReadOnlyMemory.cs38
2 files changed, 78 insertions, 4 deletions
diff --git a/src/mscorlib/shared/System/Memory.cs b/src/mscorlib/shared/System/Memory.cs
index 508ebcb3ee..bb2b1557a9 100644
--- a/src/mscorlib/shared/System/Memory.cs
+++ b/src/mscorlib/shared/System/Memory.cs
@@ -270,9 +270,49 @@ namespace System
public bool TryCopyTo(Memory<T> destination) => Span.TryCopyTo(destination.Span);
/// <summary>
- /// Returns a handle for the array.
- /// <param name="pin">If pin is true, the GC will not move the array and hence its address can be taken</param>
+ /// Creates a handle for the memory.
+ /// The GC will not move the array until the returned <see cref="MemoryHandle"/>
+ /// is disposed, enabling taking and using the memory's address.
/// </summary>
+ public unsafe MemoryHandle Pin()
+ {
+ if (_index < 0)
+ {
+ return ((OwnedMemory<T>)_object).Pin((_index & RemoveOwnedFlagBitMask) * Unsafe.SizeOf<T>());
+ }
+ else if (typeof(T) == typeof(char) && _object is string s)
+ {
+ // This case can only happen if a ReadOnlyMemory<char> was created around a string
+ // and then that was cast to a Memory<char> using unsafe / marshaling code. This needs
+ // to work, however, so that code that uses a single Memory<char> field to store either
+ // a readable ReadOnlyMemory<char> or a writable Memory<char> can still be pinned and
+ // used for interop purposes.
+ GCHandle handle = GCHandle.Alloc(s, GCHandleType.Pinned);
+#if FEATURE_PORTABLE_SPAN
+ void* pointer = Unsafe.Add<T>((void*)handle.AddrOfPinnedObject(), _index);
+#else
+ void* pointer = Unsafe.Add<T>(Unsafe.AsPointer(ref s.GetRawStringData()), _index);
+#endif // FEATURE_PORTABLE_SPAN
+ return new MemoryHandle(null, pointer, handle);
+ }
+ else if (_object is T[] array)
+ {
+ var handle = GCHandle.Alloc(array, GCHandleType.Pinned);
+#if FEATURE_PORTABLE_SPAN
+ void* pointer = Unsafe.Add<T>((void*)handle.AddrOfPinnedObject(), _index);
+#else
+ void* pointer = Unsafe.Add<T>(Unsafe.AsPointer(ref array.GetRawSzArrayData()), _index);
+#endif // FEATURE_PORTABLE_SPAN
+ return new MemoryHandle(null, pointer, handle);
+ }
+ return default;
+ }
+
+ /// <summary>[Obsolete, use Pin()] Creates a handle for the memory.</summary>
+ /// <param name="pin">
+ /// If pin is true, the GC will not move the array until the returned <see cref="MemoryHandle"/>
+ /// is disposed, enabling taking and using the memory's address.
+ /// </param>
public unsafe MemoryHandle Retain(bool pin = false)
{
MemoryHandle memoryHandle = default;
diff --git a/src/mscorlib/shared/System/ReadOnlyMemory.cs b/src/mscorlib/shared/System/ReadOnlyMemory.cs
index 5f3f0e1980..dca7db3dfd 100644
--- a/src/mscorlib/shared/System/ReadOnlyMemory.cs
+++ b/src/mscorlib/shared/System/ReadOnlyMemory.cs
@@ -226,10 +226,44 @@ namespace System
/// <param name="destination">The span to copy items into.</param>
public bool TryCopyTo(Memory<T> destination) => Span.TryCopyTo(destination.Span);
- /// <summary>Creates a handle for the memory.</summary>
+ /// <summary>
+ /// Creates a handle for the memory.
+ /// The GC will not move the array until the returned <see cref="MemoryHandle"/>
+ /// is disposed, enabling taking and using the memory's address.
+ /// </summary>
+ public unsafe MemoryHandle Pin()
+ {
+ if (_index < 0)
+ {
+ return ((OwnedMemory<T>)_object).Pin((_index & RemoveOwnedFlagBitMask) * Unsafe.SizeOf<T>());
+ }
+ else if (typeof(T) == typeof(char) && _object is string s)
+ {
+ GCHandle handle = GCHandle.Alloc(s, GCHandleType.Pinned);
+#if FEATURE_PORTABLE_SPAN
+ void* pointer = Unsafe.Add<T>((void*)handle.AddrOfPinnedObject(), _index);
+#else
+ void* pointer = Unsafe.Add<T>(Unsafe.AsPointer(ref s.GetRawStringData()), _index);
+#endif // FEATURE_PORTABLE_SPAN
+ return new MemoryHandle(null, pointer, handle);
+ }
+ else if (_object is T[] array)
+ {
+ var handle = GCHandle.Alloc(array, GCHandleType.Pinned);
+#if FEATURE_PORTABLE_SPAN
+ void* pointer = Unsafe.Add<T>((void*)handle.AddrOfPinnedObject(), _index);
+#else
+ void* pointer = Unsafe.Add<T>(Unsafe.AsPointer(ref array.GetRawSzArrayData()), _index);
+#endif // FEATURE_PORTABLE_SPAN
+ return new MemoryHandle(null, pointer, handle);
+ }
+ return default;
+ }
+
+ /// <summary>[Obsolete, use Pin()] Creates a handle for the memory.</summary>
/// <param name="pin">
/// If pin is true, the GC will not move the array until the returned <see cref="MemoryHandle"/>
- /// is disposed, enabling the memory's address can be taken and used.
+ /// is disposed, enabling taking and using the memory's address.
/// </param>
public unsafe MemoryHandle Retain(bool pin = false)
{