From a4ad7b09fc8dda2f0efa9e0f7abcf4e6f0a4ac67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCnther=20Foidl?= Date: Sun, 26 Mar 2023 14:20:24 +0200 Subject: [PATCH] Avoid length-check in pinning spans Only where it seems profitable. E.g. not when a UnmanagedMemoryStream is constructed of that pointer. --- .../ColorSpaces/Companding/SRgbCompanding.cs | 4 ++-- .../Common/Helpers/SimdUtils.HwIntrinsics.cs | 2 +- src/ImageSharp/Compression/Zlib/Adler32.cs | 2 +- src/ImageSharp/Compression/Zlib/Crc32.cs | 6 +++--- src/ImageSharp/Formats/Webp/Lossless/LosslessUtils.cs | 9 ++++----- .../Formats/Webp/Lossless/PredictorEncoder.cs | 10 +++++----- src/ImageSharp/Formats/Webp/WebpCommonUtils.cs | 4 ++-- src/ImageSharp/Memory/Buffer2DExtensions.cs | 2 +- 8 files changed, 19 insertions(+), 20 deletions(-) diff --git a/src/ImageSharp/ColorSpaces/Companding/SRgbCompanding.cs b/src/ImageSharp/ColorSpaces/Companding/SRgbCompanding.cs index 2a6fcb083..4c3923c88 100644 --- a/src/ImageSharp/ColorSpaces/Companding/SRgbCompanding.cs +++ b/src/ImageSharp/ColorSpaces/Companding/SRgbCompanding.cs @@ -167,7 +167,7 @@ public static class SRgbCompanding [MethodImpl(MethodImplOptions.AggressiveInlining)] private static unsafe void CompandAvx2(Span vectors, float[] table) { - fixed (float* tablePointer = &table[0]) + fixed (float* tablePointer = &MemoryMarshal.GetArrayDataReference(table)) { var scale = Vector256.Create((float)Scale); Vector256 zero = Vector256.Zero; @@ -199,7 +199,7 @@ public static class SRgbCompanding [MethodImpl(MethodImplOptions.AggressiveInlining)] private static unsafe void CompandScalar(Span vectors, float[] table) { - fixed (float* tablePointer = &table[0]) + fixed (float* tablePointer = &MemoryMarshal.GetArrayDataReference(table)) { Vector4 zero = Vector4.Zero; var scale = new Vector4(Scale); diff --git a/src/ImageSharp/Common/Helpers/SimdUtils.HwIntrinsics.cs b/src/ImageSharp/Common/Helpers/SimdUtils.HwIntrinsics.cs index ce6f335a8..7871eee6b 100644 --- a/src/ImageSharp/Common/Helpers/SimdUtils.HwIntrinsics.cs +++ b/src/ImageSharp/Common/Helpers/SimdUtils.HwIntrinsics.cs @@ -644,7 +644,7 @@ internal static partial class SimdUtils ReadOnlySpan source, Span dest) { - fixed (byte* sourceBase = source) + fixed (byte* sourceBase = &MemoryMarshal.GetReference(source)) { if (Avx2.IsSupported) { diff --git a/src/ImageSharp/Compression/Zlib/Adler32.cs b/src/ImageSharp/Compression/Zlib/Adler32.cs index dd8217541..3ecdf8153 100644 --- a/src/ImageSharp/Compression/Zlib/Adler32.cs +++ b/src/ImageSharp/Compression/Zlib/Adler32.cs @@ -387,7 +387,7 @@ internal static class Adler32 uint s1 = adler & 0xFFFF; uint s2 = (adler >> 16) & 0xFFFF; - fixed (byte* bufferPtr = buffer) + fixed (byte* bufferPtr = &MemoryMarshal.GetReference(buffer)) { byte* localBufferPtr = bufferPtr; uint length = (uint)buffer.Length; diff --git a/src/ImageSharp/Compression/Zlib/Crc32.cs b/src/ImageSharp/Compression/Zlib/Crc32.cs index 2d0a09bd4..e21621ab7 100644 --- a/src/ImageSharp/Compression/Zlib/Crc32.cs +++ b/src/ImageSharp/Compression/Zlib/Crc32.cs @@ -81,7 +81,7 @@ internal static partial class Crc32 int chunksize = buffer.Length & ~ChunksizeMask; int length = chunksize; - fixed (byte* bufferPtr = buffer) + fixed (byte* bufferPtr = &MemoryMarshal.GetReference(buffer)) { fixed (ulong* k05PolyPtr = K05Poly) { @@ -201,7 +201,7 @@ internal static partial class Crc32 [MethodImpl(InliningOptions.HotPath | InliningOptions.ShortMethod)] private static unsafe uint CalculateArm(uint crc, ReadOnlySpan buffer) { - fixed (byte* bufferPtr = buffer) + fixed (byte* bufferPtr = &MemoryMarshal.GetReference(buffer)) { byte* localBufferPtr = bufferPtr; int len = buffer.Length; @@ -248,7 +248,7 @@ internal static partial class Crc32 [MethodImpl(InliningOptions.HotPath | InliningOptions.ShortMethod)] private static unsafe uint CalculateArm64(uint crc, ReadOnlySpan buffer) { - fixed (byte* bufferPtr = buffer) + fixed (byte* bufferPtr = &MemoryMarshal.GetReference(buffer)) { byte* localBufferPtr = bufferPtr; int len = buffer.Length; diff --git a/src/ImageSharp/Formats/Webp/Lossless/LosslessUtils.cs b/src/ImageSharp/Formats/Webp/Lossless/LosslessUtils.cs index 8d64a09df..ab6e4cfcc 100644 --- a/src/ImageSharp/Formats/Webp/Lossless/LosslessUtils.cs +++ b/src/ImageSharp/Formats/Webp/Lossless/LosslessUtils.cs @@ -569,7 +569,7 @@ internal static unsafe class LosslessUtils Span pixelData, Span outputSpan) { - fixed (uint* inputFixed = pixelData) + fixed (uint* inputFixed = &MemoryMarshal.GetReference(pixelData)) { fixed (uint* outputFixed = outputSpan) { @@ -1474,8 +1474,7 @@ internal static unsafe class LosslessUtils { if (Sse2.IsSupported) { - Span output = scratch; - fixed (short* p = output) + fixed (short* ptr = &MemoryMarshal.GetReference(scratch)) { Vector128 a0 = Sse2.ConvertScalarToVector128UInt32(a).AsByte(); Vector128 b0 = Sse2.ConvertScalarToVector128UInt32(b).AsByte(); @@ -1489,8 +1488,8 @@ internal static unsafe class LosslessUtils Vector128 pa = Sse2.UnpackLow(ac, Vector128.Zero); // |a - c| Vector128 pb = Sse2.UnpackLow(bc, Vector128.Zero); // |b - c| Vector128 diff = Sse2.Subtract(pb.AsUInt16(), pa.AsUInt16()); - Sse2.Store((ushort*)p, diff); - int paMinusPb = output[3] + output[2] + output[1] + output[0]; + Sse2.Store((ushort*)ptr, diff); + int paMinusPb = ptr[3] + ptr[2] + ptr[1] + ptr[0]; return (paMinusPb <= 0) ? a : b; } } diff --git a/src/ImageSharp/Formats/Webp/Lossless/PredictorEncoder.cs b/src/ImageSharp/Formats/Webp/Lossless/PredictorEncoder.cs index 689c63f5b..411357963 100644 --- a/src/ImageSharp/Formats/Webp/Lossless/PredictorEncoder.cs +++ b/src/ImageSharp/Formats/Webp/Lossless/PredictorEncoder.cs @@ -353,8 +353,8 @@ internal static unsafe class PredictorEncoder else { #pragma warning disable SA1503 // Braces should not be omitted - fixed (uint* currentRow = currentRowSpan) - fixed (uint* upperRow = upperRowSpan) + fixed (uint* currentRow = &MemoryMarshal.GetReference(currentRowSpan)) + fixed (uint* upperRow = &MemoryMarshal.GetReference(upperRowSpan)) { for (int x = xStart; x < xEnd; x++) { @@ -664,9 +664,9 @@ internal static unsafe class PredictorEncoder Span scratch) { #pragma warning disable SA1503 // Braces should not be omitted - fixed (uint* current = currentSpan) - fixed (uint* upper = upperSpan) - fixed (uint* outputFixed = outputSpan) + fixed (uint* current = &MemoryMarshal.GetReference(currentSpan)) + fixed (uint* upper = &MemoryMarshal.GetReference(upperSpan)) + fixed (uint* outputFixed = &MemoryMarshal.GetReference(outputSpan)) { uint* output = outputFixed; if (xStart == 0) diff --git a/src/ImageSharp/Formats/Webp/WebpCommonUtils.cs b/src/ImageSharp/Formats/Webp/WebpCommonUtils.cs index 1a8fcbafc..735d0bf55 100644 --- a/src/ImageSharp/Formats/Webp/WebpCommonUtils.cs +++ b/src/ImageSharp/Formats/Webp/WebpCommonUtils.cs @@ -25,7 +25,7 @@ internal static class WebpCommonUtils ReadOnlySpan rowBytes = MemoryMarshal.AsBytes(row); int i = 0; int length = (row.Length * 4) - 3; - fixed (byte* src = rowBytes) + fixed (byte* src = &MemoryMarshal.GetReference(rowBytes)) { var alphaMaskVector256 = Vector256.Create(0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255); Vector256 all0x80Vector256 = Vector256.Create((byte)0x80).AsByte(); @@ -81,7 +81,7 @@ internal static class WebpCommonUtils ReadOnlySpan rowBytes = MemoryMarshal.AsBytes(row); int i = 0; int length = (row.Length * 4) - 3; - fixed (byte* src = rowBytes) + fixed (byte* src = &MemoryMarshal.GetReference(rowBytes)) { for (; i + 64 <= length; i += 64) { diff --git a/src/ImageSharp/Memory/Buffer2DExtensions.cs b/src/ImageSharp/Memory/Buffer2DExtensions.cs index 2eb05ea93..31617c163 100644 --- a/src/ImageSharp/Memory/Buffer2DExtensions.cs +++ b/src/ImageSharp/Memory/Buffer2DExtensions.cs @@ -50,7 +50,7 @@ public static class Buffer2DExtensions Span span = MemoryMarshal.AsBytes(buffer.DangerousGetSingleMemory().Span); - fixed (byte* ptr = span) + fixed (byte* ptr = &MemoryMarshal.GetReference(span)) { byte* basePtr = ptr; for (int y = 0; y < buffer.Height; y++)