diff --git a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/BlobWriterImpl.cs b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/BlobWriterImpl.cs
index 972def9f6955cb..a7fa067e3435b7 100644
--- a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/BlobWriterImpl.cs
+++ b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/BlobWriterImpl.cs
@@ -1,6 +1,7 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
+using System.Buffers.Binary;
using System.Diagnostics;
namespace System.Reflection.Metadata
@@ -144,72 +145,102 @@ internal static void WriteCompressedSignedInteger(BlobBuilder writer, int value)
}
}
- internal static void WriteConstant(ref BlobWriter writer, object? value)
+ ///
+ /// Writes a scalar (non-string) constant to a span.
+ ///
+ /// The span where the content will be encoded.
+ /// The constant value.
+ /// The number of bytes that was written.
+ internal static int WriteScalarConstant(Span bytes, object? value)
{
if (value == null)
{
// The encoding of Type for the nullref value for FieldInit is ELEMENT_TYPE_CLASS with a Value of a 32-bit.
- writer.WriteUInt32(0);
- return;
+ BinaryPrimitives.WriteUInt32LittleEndian(bytes, 0);
+ return sizeof(uint);
}
var type = value.GetType();
- if (type.GetTypeInfo().IsEnum)
+ if (type.IsEnum)
{
type = Enum.GetUnderlyingType(type);
}
if (type == typeof(bool))
{
- writer.WriteBoolean((bool)value);
+ bytes[0] = (byte)((bool)value ? 1 : 0);
+ return sizeof(bool);
}
else if (type == typeof(int))
{
- writer.WriteInt32((int)value);
- }
- else if (type == typeof(string))
- {
- writer.WriteUTF16((string)value);
+ BinaryPrimitives.WriteInt32LittleEndian(bytes, (int)value);
+ return sizeof(int);
}
else if (type == typeof(byte))
{
- writer.WriteByte((byte)value);
+ bytes[0] = (byte)value;
+ return sizeof(byte);
}
else if (type == typeof(char))
{
- writer.WriteUInt16((char)value);
+ BinaryPrimitives.WriteUInt16LittleEndian(bytes, (char)value);
+ return sizeof(char);
}
else if (type == typeof(double))
{
- writer.WriteDouble((double)value);
+#if NET
+ BinaryPrimitives.WriteDoubleLittleEndian(bytes, (double)value);
+#else
+ double v = (double)value;
+ unsafe
+ {
+ BinaryPrimitives.WriteUInt64LittleEndian(bytes, *(ulong*)(&v));
+ }
+#endif
+ return sizeof(double);
}
else if (type == typeof(short))
{
- writer.WriteInt16((short)value);
+ BinaryPrimitives.WriteInt16LittleEndian(bytes, (short)value);
+ return sizeof(short);
}
else if (type == typeof(long))
{
- writer.WriteInt64((long)value);
+ BinaryPrimitives.WriteInt64LittleEndian(bytes, (long)value);
+ return sizeof(long);
}
else if (type == typeof(sbyte))
{
- writer.WriteSByte((sbyte)value);
+ bytes[0] = (byte)(sbyte)value;
+ return sizeof(sbyte);
}
else if (type == typeof(float))
{
- writer.WriteSingle((float)value);
+#if NET
+ BinaryPrimitives.WriteSingleLittleEndian(bytes, (float)value);
+#else
+ float v = (float)value;
+ unsafe
+ {
+ BinaryPrimitives.WriteUInt32LittleEndian(bytes, *(uint*)(&v));
+ }
+#endif
+ return sizeof(float);
}
else if (type == typeof(ushort))
{
- writer.WriteUInt16((ushort)value);
+ BinaryPrimitives.WriteUInt16LittleEndian(bytes, (ushort)value);
+ return sizeof(ushort);
}
else if (type == typeof(uint))
{
- writer.WriteUInt32((uint)value);
+ BinaryPrimitives.WriteUInt32LittleEndian(bytes, (uint)value);
+ return sizeof(uint);
}
else if (type == typeof(ulong))
{
- writer.WriteUInt64((ulong)value);
+ BinaryPrimitives.WriteUInt64LittleEndian(bytes, (ulong)value);
+ return sizeof(ulong);
}
else
{
@@ -217,77 +248,30 @@ internal static void WriteConstant(ref BlobWriter writer, object? value)
}
}
- internal static void WriteConstant(BlobBuilder writer, object? value)
+ internal static void WriteConstant(ref BlobWriter writer, object? value)
{
- if (value == null)
+ if (value is string s)
{
- // The encoding of Type for the nullref value for FieldInit is ELEMENT_TYPE_CLASS with a Value of a 32-bit.
- writer.WriteUInt32(0);
+ writer.WriteUTF16(s);
return;
}
- var type = value.GetType();
- if (type.GetTypeInfo().IsEnum)
- {
- type = Enum.GetUnderlyingType(type);
- }
+ Span bytes = stackalloc byte[sizeof(ulong)];
+ int written = WriteScalarConstant(bytes, value);
+ writer.WriteBytes(bytes.Slice(0, written));
+ }
- if (type == typeof(bool))
- {
- writer.WriteBoolean((bool)value);
- }
- else if (type == typeof(int))
- {
- writer.WriteInt32((int)value);
- }
- else if (type == typeof(string))
- {
- writer.WriteUTF16((string)value);
- }
- else if (type == typeof(byte))
- {
- writer.WriteByte((byte)value);
- }
- else if (type == typeof(char))
- {
- writer.WriteUInt16((char)value);
- }
- else if (type == typeof(double))
- {
- writer.WriteDouble((double)value);
- }
- else if (type == typeof(short))
- {
- writer.WriteInt16((short)value);
- }
- else if (type == typeof(long))
- {
- writer.WriteInt64((long)value);
- }
- else if (type == typeof(sbyte))
- {
- writer.WriteSByte((sbyte)value);
- }
- else if (type == typeof(float))
- {
- writer.WriteSingle((float)value);
- }
- else if (type == typeof(ushort))
- {
- writer.WriteUInt16((ushort)value);
- }
- else if (type == typeof(uint))
- {
- writer.WriteUInt32((uint)value);
- }
- else if (type == typeof(ulong))
- {
- writer.WriteUInt64((ulong)value);
- }
- else
+ internal static void WriteConstant(BlobBuilder writer, object? value)
+ {
+ if (value is string s)
{
- throw new ArgumentException(SR.Format(SR.InvalidConstantValueOfType, type));
+ writer.WriteUTF16(s);
+ return;
}
+
+ Span bytes = stackalloc byte[sizeof(ulong)];
+ int written = WriteScalarConstant(bytes, value);
+ writer.WriteBytes(bytes.Slice(0, written));
}
}
}
diff --git a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/Ecma335/MetadataBuilder.Heaps.cs b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/Ecma335/MetadataBuilder.Heaps.cs
index 16a2007781507e..70ce8278adfb89 100644
--- a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/Ecma335/MetadataBuilder.Heaps.cs
+++ b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/Ecma335/MetadataBuilder.Heaps.cs
@@ -256,11 +256,9 @@ public BlobHandle GetOrAddConstantBlob(object? value)
return GetOrAddBlobUTF16(str);
}
- var builder = PooledBlobBuilder.GetInstance();
- builder.WriteConstant(value);
- var result = GetOrAddBlob(builder);
- builder.Free();
- return result;
+ Span buffer = stackalloc byte[sizeof(ulong)];
+ int length = BlobWriterImpl.WriteScalarConstant(buffer, value);
+ return GetOrAddBlob(buffer.Slice(0, length));
}
///