Skip to content

Commit

Permalink
Use BinaryPrimitives for ObjectDataBuilder primitive emit logic (#1…
Browse files Browse the repository at this point in the history
…02394)

* Add ArrayBuilder.Append(ROS<T>)

- Only for .NET because of NS2.0 projects use it too: Microsoft.NET.HostModel and ILVerification

* Use BinaryPrimitives to emit integer primitives in ObjectDataBuilder

* Use BinaryPrimitives to emit reserved integer primitives in ObjectDataBuilder

* Add ArrayBuilder.AsSpan overload to make this possible

* Mark some ArrayBuilder members as readonly

* Ask ArrayBuilder for a buffer instead of stackalloc + append

* Follow ValueStringBuilder's AppendSpan implementation

* Don't inline ArrayBuilder resize

* This follows ValueStringBuilder and other buffer builder types.
  • Loading branch information
PaulusParssinen authored May 18, 2024
1 parent 0d8c6b7 commit 5474ab5
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 48 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.Buffers.Binary;
using System.Collections.Generic;
using Internal.TypeSystem;

Expand Down Expand Up @@ -85,42 +86,27 @@ public void EmitByte(byte emit)

public void EmitShort(short emit)
{
EmitByte((byte)(emit & 0xFF));
EmitByte((byte)((emit >> 8) & 0xFF));
BinaryPrimitives.WriteInt16LittleEndian(_data.AppendSpan(sizeof(short)), emit);
}

public void EmitUShort(ushort emit)
{
EmitByte((byte)(emit & 0xFF));
EmitByte((byte)((emit >> 8) & 0xFF));
BinaryPrimitives.WriteUInt16LittleEndian(_data.AppendSpan(sizeof(ushort)), emit);
}

public void EmitInt(int emit)
{
EmitByte((byte)(emit & 0xFF));
EmitByte((byte)((emit >> 8) & 0xFF));
EmitByte((byte)((emit >> 16) & 0xFF));
EmitByte((byte)((emit >> 24) & 0xFF));
BinaryPrimitives.WriteInt32LittleEndian(_data.AppendSpan(sizeof(int)), emit);
}

public void EmitUInt(uint emit)
{
EmitByte((byte)(emit & 0xFF));
EmitByte((byte)((emit >> 8) & 0xFF));
EmitByte((byte)((emit >> 16) & 0xFF));
EmitByte((byte)((emit >> 24) & 0xFF));
BinaryPrimitives.WriteUInt32LittleEndian(_data.AppendSpan(sizeof(uint)), emit);
}

public void EmitLong(long emit)
{
EmitByte((byte)(emit & 0xFF));
EmitByte((byte)((emit >> 8) & 0xFF));
EmitByte((byte)((emit >> 16) & 0xFF));
EmitByte((byte)((emit >> 24) & 0xFF));
EmitByte((byte)((emit >> 32) & 0xFF));
EmitByte((byte)((emit >> 40) & 0xFF));
EmitByte((byte)((emit >> 48) & 0xFF));
EmitByte((byte)((emit >> 56) & 0xFF));
BinaryPrimitives.WriteInt64LittleEndian(_data.AppendSpan(sizeof(long)), emit);
}

public void EmitNaturalInt(int emit)
Expand Down Expand Up @@ -245,8 +231,7 @@ public Reservation ReserveShort()
public void EmitShort(Reservation reservation, short emit)
{
int offset = ReturnReservationTicket(reservation);
_data[offset] = (byte)(emit & 0xFF);
_data[offset + 1] = (byte)((emit >> 8) & 0xFF);
BinaryPrimitives.WriteInt16LittleEndian(_data.AsSpan(offset), emit);
}

public Reservation ReserveInt()
Expand All @@ -257,19 +242,13 @@ public Reservation ReserveInt()
public void EmitInt(Reservation reservation, int emit)
{
int offset = ReturnReservationTicket(reservation);
_data[offset] = (byte)(emit & 0xFF);
_data[offset + 1] = (byte)((emit >> 8) & 0xFF);
_data[offset + 2] = (byte)((emit >> 16) & 0xFF);
_data[offset + 3] = (byte)((emit >> 24) & 0xFF);
BinaryPrimitives.WriteInt32LittleEndian(_data.AsSpan(offset), emit);
}

public void EmitUInt(Reservation reservation, uint emit)
{
int offset = ReturnReservationTicket(reservation);
_data[offset] = (byte)(emit & 0xFF);
_data[offset + 1] = (byte)((emit >> 8) & 0xFF);
_data[offset + 2] = (byte)((emit >> 16) & 0xFF);
_data[offset + 3] = (byte)((emit >> 24) & 0xFF);
BinaryPrimitives.WriteUInt32LittleEndian(_data.AsSpan(offset), emit);
}

public void EmitReloc(ISymbolNode symbol, RelocType relocType, int delta = 0)
Expand Down
45 changes: 27 additions & 18 deletions src/coreclr/tools/Common/System/Collections/Generic/ArrayBuilder.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Runtime.CompilerServices;

using Debug = System.Diagnostics.Debug;

namespace System.Collections.Generic
Expand Down Expand Up @@ -29,6 +31,19 @@ public void Add(T item)
_items[_count++] = item;
}

#if NET
public readonly Span<T> AsSpan(int start) => _items.AsSpan(start);

public Span<T> AppendSpan(int length)
{
int origCount = _count;
EnsureCapacity(origCount + length);

_count = origCount + length;
return _items.AsSpan(origCount, length);
}
#endif

public void Append(T[] newItems)
{
Append(newItems, 0, newItems.Length);
Expand Down Expand Up @@ -67,32 +82,26 @@ public void EnsureCapacity(int requestedCapacity)
{
if (requestedCapacity > ((_items != null) ? _items.Length : 0))
{
int newCount = Math.Max(2 * _count + 1, requestedCapacity);
Array.Resize(ref _items, newCount);
Grow(requestedCapacity);
}
}

public int Count
[MethodImpl(MethodImplOptions.NoInlining)]
private void Grow(int requestedCapacity)
{
get
{
return _count;
}
int newCount = Math.Max(2 * _count + 1, requestedCapacity);
Array.Resize(ref _items, newCount);
}

public T this[int index]
public readonly int Count => _count;

public readonly T this[int index]
{
get
{
return _items[index];
}
set
{
_items[index] = value;
}
get => _items[index];
set => _items[index] = value;
}

public bool Contains(T t)
public readonly bool Contains(T t)
{
for (int i = 0; i < _count; i++)
{
Expand All @@ -105,7 +114,7 @@ public bool Contains(T t)
return false;
}

public bool Any(Func<T, bool> func)
public readonly bool Any(Func<T, bool> func)
{
for (int i = 0; i < _count; i++)
{
Expand Down

0 comments on commit 5474ab5

Please sign in to comment.