From 379d0eca364b0d132851b0762280e290d0531c5e Mon Sep 17 00:00:00 2001 From: xtqqczze <45661989+xtqqczze@users.noreply.github.com> Date: Sat, 6 Apr 2024 12:55:59 +0100 Subject: [PATCH] Optimize `MemoryMarshal.Cast` for same type --- .../System/Runtime/InteropServices/MemoryMarshal.cs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/MemoryMarshal.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/MemoryMarshal.cs index 0b0da448e4eba..6f3dd4c01b73c 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/MemoryMarshal.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/MemoryMarshal.cs @@ -113,7 +113,7 @@ public static Memory AsMemory(ReadOnlyMemory memory) => /// Thrown when or contains pointers. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Span Cast(Span span) + public static unsafe Span Cast(Span span) where TFrom : struct where TTo : struct { @@ -122,6 +122,9 @@ public static Span Cast(Span span) if (RuntimeHelpers.IsReferenceOrContainsReferences()) ThrowHelper.ThrowInvalidTypeWithPointersNotSupported(typeof(TTo)); + if (typeof(TFrom) == typeof(TTo)) + return *(Span*)&span; + // Use unsigned integers - unsigned division by constant (especially by power of 2) // and checked casts are faster and smaller. uint fromSize = (uint)Unsafe.SizeOf(); @@ -168,7 +171,7 @@ ref Unsafe.As(ref span._reference), /// Thrown when or contains pointers. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static ReadOnlySpan Cast(ReadOnlySpan span) + public static unsafe ReadOnlySpan Cast(ReadOnlySpan span) where TFrom : struct where TTo : struct { @@ -177,6 +180,9 @@ public static ReadOnlySpan Cast(ReadOnlySpan span) if (RuntimeHelpers.IsReferenceOrContainsReferences()) ThrowHelper.ThrowInvalidTypeWithPointersNotSupported(typeof(TTo)); + if (typeof(TFrom) == typeof(TTo)) + return *(ReadOnlySpan*)&span; + // Use unsigned integers - unsigned division by constant (especially by power of 2) // and checked casts are faster and smaller. uint fromSize = (uint)Unsafe.SizeOf();