diff --git a/src/mscorlib/shared/System/Memory.cs b/src/mscorlib/shared/System/Memory.cs index 98ec23fd67f1..577b76b96905 100644 --- a/src/mscorlib/shared/System/Memory.cs +++ b/src/mscorlib/shared/System/Memory.cs @@ -225,13 +225,16 @@ public override string ToString() [MethodImpl(MethodImplOptions.AggressiveInlining)] public Memory Slice(int start) { - int actualLength = _length & RemoveFlagsBitMask; + // Used to maintain the high-bit which indicates whether the Memory has been pre-pinned or not. + int capturedLength = _length; + int actualLength = capturedLength & RemoveFlagsBitMask; if ((uint)start > (uint)actualLength) { ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.start); } - return new Memory(_object, _index + start, actualLength - start); + // It is expected for (capturedLength - start) to be negative if the memory is already pre-pinned. + return new Memory(_object, _index + start, capturedLength - start); } /// @@ -245,13 +248,16 @@ public Memory Slice(int start) [MethodImpl(MethodImplOptions.AggressiveInlining)] public Memory Slice(int start, int length) { - int actualLength = _length & RemoveFlagsBitMask; + // Used to maintain the high-bit which indicates whether the Memory has been pre-pinned or not. + int capturedLength = _length; + int actualLength = capturedLength & RemoveFlagsBitMask; if ((uint)start > (uint)actualLength || (uint)length > (uint)(actualLength - start)) { ThrowHelper.ThrowArgumentOutOfRangeException(); } - return new Memory(_object, _index + start, length); + // Set the high-bit to match the this._length high bit (1 for pre-pinned, 0 for unpinned). + return new Memory(_object, _index + start, length | (capturedLength & ~RemoveFlagsBitMask)); } /// diff --git a/src/mscorlib/shared/System/ReadOnlyMemory.cs b/src/mscorlib/shared/System/ReadOnlyMemory.cs index ae8a7c3001b8..a7a64460569d 100644 --- a/src/mscorlib/shared/System/ReadOnlyMemory.cs +++ b/src/mscorlib/shared/System/ReadOnlyMemory.cs @@ -147,13 +147,16 @@ public override string ToString() [MethodImpl(MethodImplOptions.AggressiveInlining)] public ReadOnlyMemory Slice(int start) { - int actualLength = _length & RemoveFlagsBitMask; + // Used to maintain the high-bit which indicates whether the Memory has been pre-pinned or not. + int capturedLength = _length; + int actualLength = capturedLength & RemoveFlagsBitMask; if ((uint)start > (uint)actualLength) { ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.start); } - return new ReadOnlyMemory(_object, _index + start, actualLength - start); + // It is expected for (capturedLength - start) to be negative if the memory is already pre-pinned. + return new ReadOnlyMemory(_object, _index + start, capturedLength - start); } /// @@ -167,13 +170,16 @@ public ReadOnlyMemory Slice(int start) [MethodImpl(MethodImplOptions.AggressiveInlining)] public ReadOnlyMemory Slice(int start, int length) { + // Used to maintain the high-bit which indicates whether the Memory has been pre-pinned or not. + int capturedLength = _length; int actualLength = _length & RemoveFlagsBitMask; if ((uint)start > (uint)actualLength || (uint)length > (uint)(actualLength - start)) { ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.start); } - return new ReadOnlyMemory(_object, _index + start, length); + // Set the high-bit to match the this._length high bit (1 for pre-pinned, 0 for unpinned). + return new ReadOnlyMemory(_object, _index + start, length | (capturedLength & ~RemoveFlagsBitMask)); } ///