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

Remove replaced Span/ReadOnlySpan methods. #16086

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 0 additions & 13 deletions src/mscorlib/shared/System/ReadOnlySpan.cs
Original file line number Diff line number Diff line change
Expand Up @@ -102,19 +102,6 @@ public unsafe ReadOnlySpan(void* pointer, int length)
_length = length;
}

/// <summary>
/// Create a new read-only span over a portion of a regular managed object. This can be useful
/// if part of a managed object represents a "fixed array." This is dangerous because neither the
/// <paramref name="length"/> is checked, nor <paramref name="obj"/> being null, nor the fact that
/// "rawPointer" actually lies within <paramref name="obj"/>.
/// </summary>
/// <param name="obj">The managed object that contains the data to span over.</param>
/// <param name="objectData">A reference to data within that object.</param>
/// <param name="length">The number of <typeparamref name="T"/> elements the memory contains.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[EditorBrowsable(EditorBrowsableState.Never)]
public static ReadOnlySpan<T> DangerousCreate(object obj, ref T objectData, int length) => new ReadOnlySpan<T>(ref objectData, length);

// Constructor for internal use only.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal ReadOnlySpan(ref T ptr, int length)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@ public static Memory<T> AsMemory<T>(ReadOnlyMemory<T> readOnlyMemory) =>
/// <exception cref="System.ArgumentException">
/// Thrown when <typeparamref name="TFrom"/> or <typeparamref name="TTo"/> contains pointers.
/// </exception>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Span<TTo> Cast<TFrom, TTo>(Span<TFrom> source)
where TFrom : struct
where TTo : struct
Expand All @@ -76,7 +75,6 @@ ref Unsafe.As<TFrom, TTo>(ref source.DangerousGetPinnableReference()),
/// <exception cref="System.ArgumentException">
/// Thrown when <typeparamref name="TFrom"/> or <typeparamref name="TTo"/> contains pointers.
/// </exception>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ReadOnlySpan<TTo> Cast<TFrom, TTo>(ReadOnlySpan<TFrom> source)
where TFrom : struct
where TTo : struct
Expand Down
52 changes: 0 additions & 52 deletions src/mscorlib/shared/System/Span.NonGeneric.cs
Original file line number Diff line number Diff line change
Expand Up @@ -131,58 +131,6 @@ ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(source)),
checked(source.Length * Unsafe.SizeOf<T>()));
}

/// <summary>
/// Casts a Span of one primitive type <typeparamref name="TFrom"/> to another primitive type <typeparamref name="TTo"/>.
/// These types may not contain pointers or references. This is checked at runtime in order to preserve type safety.
/// </summary>
/// <remarks>
/// Supported only for platforms that support misaligned memory access.
/// </remarks>
/// <param name="source">The source slice, of type <typeparamref name="TFrom"/>.</param>
/// <exception cref="System.ArgumentException">
/// Thrown when <typeparamref name="TFrom"/> or <typeparamref name="TTo"/> contains pointers.
/// </exception>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Span<TTo> NonPortableCast<TFrom, TTo>(this Span<TFrom> source)
where TFrom : struct
where TTo : struct
{
if (RuntimeHelpers.IsReferenceOrContainsReferences<TFrom>())
ThrowHelper.ThrowInvalidTypeWithPointersNotSupported(typeof(TFrom));
if (RuntimeHelpers.IsReferenceOrContainsReferences<TTo>())
ThrowHelper.ThrowInvalidTypeWithPointersNotSupported(typeof(TTo));

return new Span<TTo>(
ref Unsafe.As<TFrom, TTo>(ref source.DangerousGetPinnableReference()),
checked((int)((long)source.Length * Unsafe.SizeOf<TFrom>() / Unsafe.SizeOf<TTo>())));
}

/// <summary>
/// Casts a ReadOnlySpan of one primitive type <typeparamref name="TFrom"/> to another primitive type <typeparamref name="TTo"/>.
/// These types may not contain pointers or references. This is checked at runtime in order to preserve type safety.
/// </summary>
/// <remarks>
/// Supported only for platforms that support misaligned memory access.
/// </remarks>
/// <param name="source">The source slice, of type <typeparamref name="TFrom"/>.</param>
/// <exception cref="System.ArgumentException">
/// Thrown when <typeparamref name="TFrom"/> or <typeparamref name="TTo"/> contains pointers.
/// </exception>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ReadOnlySpan<TTo> NonPortableCast<TFrom, TTo>(this ReadOnlySpan<TFrom> source)
where TFrom : struct
where TTo : struct
{
if (RuntimeHelpers.IsReferenceOrContainsReferences<TFrom>())
ThrowHelper.ThrowInvalidTypeWithPointersNotSupported(typeof(TFrom));
if (RuntimeHelpers.IsReferenceOrContainsReferences<TTo>())
ThrowHelper.ThrowInvalidTypeWithPointersNotSupported(typeof(TTo));

return new ReadOnlySpan<TTo>(
ref Unsafe.As<TFrom, TTo>(ref MemoryMarshal.GetReference(source)),
checked((int)((long)source.Length * Unsafe.SizeOf<TFrom>() / Unsafe.SizeOf<TTo>())));
}

/// <summary>
/// Creates a new readonly span over the portion of the target string.
/// </summary>
Expand Down
13 changes: 0 additions & 13 deletions src/mscorlib/shared/System/Span.cs
Original file line number Diff line number Diff line change
Expand Up @@ -108,19 +108,6 @@ public unsafe Span(void* pointer, int length)
_length = length;
}

/// <summary>
/// Create a new span over a portion of a regular managed object. This can be useful
/// if part of a managed object represents a "fixed array." This is dangerous because neither the
/// <paramref name="length"/> is checked, nor <paramref name="obj"/> being null, nor the fact that
/// "rawPointer" actually lies within <paramref name="obj"/>.
/// </summary>
/// <param name="obj">The managed object that contains the data to span over.</param>
/// <param name="objectData">A reference to data within that object.</param>
/// <param name="length">The number of <typeparamref name="T"/> elements the memory contains.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[EditorBrowsable(EditorBrowsableState.Never)]
public static Span<T> DangerousCreate(object obj, ref T objectData, int length) => new Span<T>(ref objectData, length);

// Constructor for internal use only.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal Span(ref T ptr, int length)
Expand Down
42 changes: 21 additions & 21 deletions tests/src/JIT/Performance/CodeQuality/Span/SpanBench.cs
Original file line number Diff line number Diff line change
Expand Up @@ -475,41 +475,41 @@ static void TestSpanConstructor<T>(T[] array, int iterationCount, bool untrue)
}
#endregion

#region TestSpanDangerousCreate<T>
#region TestSpanCreate<T>
[Benchmark(InnerIterationCount = BaseIterations)]
[InlineData(100)]
public static void TestSpanDangerousCreateByte(int length)
public static void TestSpanCreateByte(int length)
{
InvokeTestSpanDangerousCreate<byte>(length);
InvokeTestSpanCreate<byte>(length);
}

[Benchmark(InnerIterationCount = BaseIterations)]
[InlineData(100)]
public static void TestSpanDangerousCreateString(int length)
public static void TestSpanCreateString(int length)
{
InvokeTestSpanDangerousCreate<string>(length);
InvokeTestSpanCreate<string>(length);
}

static void InvokeTestSpanDangerousCreate<T>(int length)
static void InvokeTestSpanCreate<T>(int length)
{
TestClass<T> testClass = new TestClass<T>();
testClass.C0 = new T[length];

Invoke((int innerIterationCount) => TestSpanDangerousCreate<T>(testClass, innerIterationCount, false),
"TestSpanDangerousCreate<{0}>({1})", typeof(T).Name, length);
Invoke((int innerIterationCount) => TestSpanCreate<T>(testClass, innerIterationCount, false),
"TestSpanCreate<{0}>({1})", typeof(T).Name, length);
}

[MethodImpl(MethodImplOptions.NoInlining)]
static void TestSpanDangerousCreate<T>(TestClass<T> testClass, int iterationCount, bool untrue)
static void TestSpanCreate<T>(TestClass<T> testClass, int iterationCount, bool untrue)
{
var sink = Sink<T>.Instance;

for (int i = 0; i < iterationCount; i++)
{
var span = Span<T>.DangerousCreate(testClass, ref testClass.C0[0], testClass.C0.Length);
var span = MemoryMarshal.CreateSpan<T>(ref testClass.C0[0], testClass.C0.Length);
// Under a condition that we know is false but the jit doesn't,
// add a read from 'span' to make sure it's not dead, and an assignment
// to 'testClass' so the DangerousCreate call won't get hoisted.
// to 'testClass' so the Create call won't get hoisted.
if (untrue) { sink.Data = span[0]; testClass = new TestClass<T>(); }
}
}
Expand Down Expand Up @@ -967,33 +967,33 @@ static void TestSpanAsBytes<T>(T[] array, int iterationCount, bool untrue)
}
#endregion

#region TestSpanNonPortableCast<T>
#region TestSpanCast<T>
[Benchmark(InnerIterationCount = BaseIterations)]
[InlineData(100)]
public static void TestSpanNonPortableCastFromByteToInt(int length)
public static void TestSpanCastFromByteToInt(int length)
{
InvokeTestSpanNonPortableCast<byte, int>(length);
InvokeTestSpanCast<byte, int>(length);
}

[Benchmark(InnerIterationCount = BaseIterations)]
[InlineData(100)]
public static void TestSpanNonPortableCastFromIntToByte(int length)
public static void TestSpanCastFromIntToByte(int length)
{
InvokeTestSpanNonPortableCast<int, byte>(length);
InvokeTestSpanCast<int, byte>(length);
}

static void InvokeTestSpanNonPortableCast<From, To>(int length)
static void InvokeTestSpanCast<From, To>(int length)
where From : struct
where To : struct
{
var array = new From[length];

Invoke((int innerIterationCount) => TestSpanNonPortableCast<From, To>(array, innerIterationCount, false),
"TestSpanNonPortableCast<{0}, {1}>({2})", typeof(From).Name, typeof(To).Name, length);
Invoke((int innerIterationCount) => TestSpanCast<From, To>(array, innerIterationCount, false),
"TestSpanCast<{0}, {1}>({2})", typeof(From).Name, typeof(To).Name, length);
}

[MethodImpl(MethodImplOptions.NoInlining)]
static void TestSpanNonPortableCast<From, To>(From[] array, int iterationCount, bool untrue)
static void TestSpanCast<From, To>(From[] array, int iterationCount, bool untrue)
where From : struct
where To : struct
{
Expand All @@ -1002,7 +1002,7 @@ static void TestSpanNonPortableCast<From, To>(From[] array, int iterationCount,

for (int i = 0; i < iterationCount; i++)
{
var toSpan = span.NonPortableCast<From, To>();
var toSpan = MemoryMarshal.Cast<From, To>(span);
// Under a condition that we know is false but the jit doesn't,
// add a read from 'toSpan' to make sure it's not dead, and an assignment
// to 'span' so the AsBytes call won't get hoisted.
Expand Down