Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove Unsafe from ChunkWriter #18450

Merged
merged 2 commits into from
Jan 22, 2020
Merged
Changes from all commits
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
19 changes: 8 additions & 11 deletions src/Servers/Kestrel/Core/src/Internal/Http/ChunkWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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<byte> 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<byte> span)
{
// Determine the most-significant non-zero nibble
Expand All @@ -29,14 +23,17 @@ public static int BeginChunkBytes(int dataCount, Span<byte> span)

count = (total >> 2) + 3;

var offset = 0;
ref var startHex = ref MemoryMarshal.GetReference(Hex);
// This must be explicity typed as ReadOnlySpan<byte>
// 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<byte> 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];
pakrym marked this conversation as resolved.
Show resolved Hide resolved
offset++;
}

Expand Down