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

Commit 1a22cee

Browse files
ahsonkhanPetermarcu
authored andcommitted
Preserve pinned flag in {ReadOnly}Memory<T>.Slice (dotnet/corefx#29246) (#17712) (#17714)
* Preserve pinned flag in {ReadOnly}Memory<T>.Slice * Address PR feedback. Signed-off-by: dotnet-bot-corefx-mirror <[email protected]>
1 parent 562bc0a commit 1a22cee

File tree

2 files changed

+19
-7
lines changed

2 files changed

+19
-7
lines changed

src/mscorlib/shared/System/Memory.cs

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -225,13 +225,16 @@ public override string ToString()
225225
[MethodImpl(MethodImplOptions.AggressiveInlining)]
226226
public Memory<T> Slice(int start)
227227
{
228-
int actualLength = _length & RemoveFlagsBitMask;
228+
// Used to maintain the high-bit which indicates whether the Memory has been pre-pinned or not.
229+
int capturedLength = _length;
230+
int actualLength = capturedLength & RemoveFlagsBitMask;
229231
if ((uint)start > (uint)actualLength)
230232
{
231233
ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.start);
232234
}
233235

234-
return new Memory<T>(_object, _index + start, actualLength - start);
236+
// It is expected for (capturedLength - start) to be negative if the memory is already pre-pinned.
237+
return new Memory<T>(_object, _index + start, capturedLength - start);
235238
}
236239

237240
/// <summary>
@@ -245,13 +248,16 @@ public Memory<T> Slice(int start)
245248
[MethodImpl(MethodImplOptions.AggressiveInlining)]
246249
public Memory<T> Slice(int start, int length)
247250
{
248-
int actualLength = _length & RemoveFlagsBitMask;
251+
// Used to maintain the high-bit which indicates whether the Memory has been pre-pinned or not.
252+
int capturedLength = _length;
253+
int actualLength = capturedLength & RemoveFlagsBitMask;
249254
if ((uint)start > (uint)actualLength || (uint)length > (uint)(actualLength - start))
250255
{
251256
ThrowHelper.ThrowArgumentOutOfRangeException();
252257
}
253258

254-
return new Memory<T>(_object, _index + start, length);
259+
// Set the high-bit to match the this._length high bit (1 for pre-pinned, 0 for unpinned).
260+
return new Memory<T>(_object, _index + start, length | (capturedLength & ~RemoveFlagsBitMask));
255261
}
256262

257263
/// <summary>

src/mscorlib/shared/System/ReadOnlyMemory.cs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -147,13 +147,16 @@ public override string ToString()
147147
[MethodImpl(MethodImplOptions.AggressiveInlining)]
148148
public ReadOnlyMemory<T> Slice(int start)
149149
{
150-
int actualLength = _length & RemoveFlagsBitMask;
150+
// Used to maintain the high-bit which indicates whether the Memory has been pre-pinned or not.
151+
int capturedLength = _length;
152+
int actualLength = capturedLength & RemoveFlagsBitMask;
151153
if ((uint)start > (uint)actualLength)
152154
{
153155
ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.start);
154156
}
155157

156-
return new ReadOnlyMemory<T>(_object, _index + start, actualLength - start);
158+
// It is expected for (capturedLength - start) to be negative if the memory is already pre-pinned.
159+
return new ReadOnlyMemory<T>(_object, _index + start, capturedLength - start);
157160
}
158161

159162
/// <summary>
@@ -167,13 +170,16 @@ public ReadOnlyMemory<T> Slice(int start)
167170
[MethodImpl(MethodImplOptions.AggressiveInlining)]
168171
public ReadOnlyMemory<T> Slice(int start, int length)
169172
{
173+
// Used to maintain the high-bit which indicates whether the Memory has been pre-pinned or not.
174+
int capturedLength = _length;
170175
int actualLength = _length & RemoveFlagsBitMask;
171176
if ((uint)start > (uint)actualLength || (uint)length > (uint)(actualLength - start))
172177
{
173178
ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.start);
174179
}
175180

176-
return new ReadOnlyMemory<T>(_object, _index + start, length);
181+
// Set the high-bit to match the this._length high bit (1 for pre-pinned, 0 for unpinned).
182+
return new ReadOnlyMemory<T>(_object, _index + start, length | (capturedLength & ~RemoveFlagsBitMask));
177183
}
178184

179185
/// <summary>

0 commit comments

Comments
 (0)