diff --git a/src/Servers/Kestrel/Core/src/Internal/Http/ChunkWriter.cs b/src/Servers/Kestrel/Core/src/Internal/Http/ChunkWriter.cs index ba4722a1e2a6..6decc434a238 100644 --- a/src/Servers/Kestrel/Core/src/Internal/Http/ChunkWriter.cs +++ b/src/Servers/Kestrel/Core/src/Internal/Http/ChunkWriter.cs @@ -4,17 +4,11 @@ using System; using System.Buffers; using System.IO.Pipelines; -using System.Text; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http { internal static class ChunkWriter { - // This uses C# compiler's ability to refer to static data directly. For more information see https://vcsjones.dev/2019/02/01/csharp-readonly-span-bytes-static - private static ReadOnlySpan Hex => new byte[16] { (byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4', (byte)'5', (byte)'6', (byte)'7', (byte)'8', (byte)'9', (byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e', (byte)'f' }; - public static int BeginChunkBytes(int dataCount, Span span) { // Determine the most-significant non-zero nibble @@ -29,14 +23,17 @@ public static int BeginChunkBytes(int dataCount, Span span) count = (total >> 2) + 3; - var offset = 0; - ref var startHex = ref MemoryMarshal.GetReference(Hex); + // This must be explicity typed as ReadOnlySpan + // It then becomes a non-allocating mapping to the data section of the assembly. + // For more information see https://vcsjones.dev/2019/02/01/csharp-readonly-span-bytes-static + ReadOnlySpan hex = new byte[16] { (byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4', (byte)'5', (byte)'6', (byte)'7', (byte)'8', (byte)'9', (byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e', (byte)'f' }; + var offset = 0; for (shift = total; shift >= 0; shift -= 4) { - // Using Unsafe.Add to elide the bounds check on _hex as the & 0x0f definitely - // constrains it to the range 0x0 - 0xf, matching the bounds of the array - span[offset] = Unsafe.Add(ref startHex, ((dataCount >> shift) & 0x0f)); + // Uses dotnet/runtime#1644 to elide the bounds check on hex as the & 0x0f definitely + // constrains it to the range 0x0 - 0xf, matching the bounds of the array. + span[offset] = hex[(dataCount >> shift) & 0x0f]; offset++; }