1
0
Fork 0
mirror of https://github.com/VSadov/Satori.git synced 2025-06-10 18:11:04 +09:00

Clean up some [InlineArray] use (#99766)

* Clean up some [InlineArray] use

* Remove AsSpan method
This commit is contained in:
Stephen Toub 2024-03-15 09:16:07 -04:00 committed by GitHub
parent 516f5c4b92
commit f36aa7ec73
Signed by: github
GPG key ID: B5690EEEBB952194
15 changed files with 73 additions and 140 deletions

View file

@ -53,7 +53,7 @@ namespace System.Reflection
ThrowForArgCountMismatch();
}
object result = _methodBaseInvoker.CreateInstanceWithFewArgs(new Span<object?>(ref arg1, _parameterCount));
object result = _methodBaseInvoker.CreateInstanceWithFewArgs(new Span<object?>(ref arg1));
DebugAnnotations.PreviousCallContainsDebuggerStepInCode();
return result;
}
@ -67,9 +67,9 @@ namespace System.Reflection
}
StackAllocatedArguments argStorage = default;
argStorage._args.Set(0, arg1);
argStorage._args.Set(1, arg2);
object result = _methodBaseInvoker.CreateInstanceWithFewArgs(argStorage._args.AsSpan(_parameterCount));
argStorage._args[0] = arg1;
argStorage._args[1] = arg2;
object result = _methodBaseInvoker.CreateInstanceWithFewArgs(((Span<object?>)argStorage._args).Slice(0, 2));
DebugAnnotations.PreviousCallContainsDebuggerStepInCode();
return result;
}
@ -83,10 +83,10 @@ namespace System.Reflection
}
StackAllocatedArguments argStorage = default;
argStorage._args.Set(0, arg1);
argStorage._args.Set(1, arg2);
argStorage._args.Set(2, arg3);
object result = _methodBaseInvoker.CreateInstanceWithFewArgs(argStorage._args.AsSpan(_parameterCount));
argStorage._args[0] = arg1;
argStorage._args[1] = arg2;
argStorage._args[2] = arg3;
object result = _methodBaseInvoker.CreateInstanceWithFewArgs(((Span<object?>)argStorage._args).Slice(0, 3));
DebugAnnotations.PreviousCallContainsDebuggerStepInCode();
return result;
}
@ -100,11 +100,11 @@ namespace System.Reflection
}
StackAllocatedArguments argStorage = default;
argStorage._args.Set(0, arg1);
argStorage._args.Set(1, arg2);
argStorage._args.Set(2, arg3);
argStorage._args.Set(3, arg4);
object result = _methodBaseInvoker.CreateInstanceWithFewArgs(argStorage._args.AsSpan(_parameterCount));
argStorage._args[0] = arg1;
argStorage._args[1] = arg2;
argStorage._args[2] = arg3;
argStorage._args[3] = arg4;
object result = _methodBaseInvoker.CreateInstanceWithFewArgs(((Span<object?>)argStorage._args).Slice(0, 4));
DebugAnnotations.PreviousCallContainsDebuggerStepInCode();
return result;
}

View file

@ -497,10 +497,9 @@ namespace System.Reflection
object?[] parameters, BinderBundle? binderBundle, bool wrapInTargetInvocationException)
{
Debug.Assert(_argumentCount <= MaxStackAllocArgCount);
int argCount = _argumentCount;
StackAllocatedArguments argStorage = default;
Span<object?> copyOfParameters = argStorage._args.AsSpan(argCount);
Span<object?> copyOfParameters = ((Span<object?>)argStorage._args).Slice(0, _argumentCount);
StackAllocatedByRefs byrefStorage = default;
#pragma warning disable CS8500
void* pByRefStorage = (ByReference*)&byrefStorage;
@ -532,10 +531,9 @@ namespace System.Reflection
IntPtr methodToCall, ref byte thisArg, ref byte ret, Span<object?> parameters)
{
Debug.Assert(_argumentCount <= MaxStackAllocArgCount);
int argCount = _argumentCount;
StackAllocatedArguments argStorage = default;
Span<object?> copyOfParameters = argStorage._args.AsSpan(argCount);
Span<object?> copyOfParameters = ((Span<object?>)argStorage._args).Slice(0, _argumentCount);
StackAllocatedByRefs byrefStorage = default;
#pragma warning disable CS8500
void* pByRefStorage = (ByReference*)&byrefStorage;
@ -884,19 +882,6 @@ namespace System.Reflection
internal struct ArgumentData<T>
{
private T _arg0;
[UnscopedRef]
public Span<T> AsSpan(int length)
{
Debug.Assert((uint)length <= MaxStackAllocArgCount);
return new Span<T>(ref _arg0, length);
}
public void Set(int index, T value)
{
Debug.Assert((uint)index < MaxStackAllocArgCount);
Unsafe.Add(ref _arg0, index) = value;
}
}
// Helper struct to avoid intermediate object[] allocation in calls to the native reflection stack.

View file

@ -81,10 +81,10 @@ namespace System.Reflection
}
StackAllocatedArguments argStorage = default;
argStorage._args.Set(0, arg1);
argStorage._args.Set(1, arg2);
argStorage._args[0] = arg1;
argStorage._args[1] = arg2;
object? result = _methodBaseInvoker.InvokeDirectWithFewArgs(obj, argStorage._args.AsSpan(_parameterCount));
object? result = _methodBaseInvoker.InvokeDirectWithFewArgs(obj, ((Span<object?>)argStorage._args).Slice(0, 2));
DebugAnnotations.PreviousCallContainsDebuggerStepInCode();
return result;
}
@ -98,11 +98,11 @@ namespace System.Reflection
}
StackAllocatedArguments argStorage = default;
argStorage._args.Set(0, arg1);
argStorage._args.Set(1, arg2);
argStorage._args.Set(2, arg3);
argStorage._args[0] = arg1;
argStorage._args[1] = arg2;
argStorage._args[2] = arg3;
object? result = _methodBaseInvoker.InvokeDirectWithFewArgs(obj, argStorage._args.AsSpan(_parameterCount));
object? result = _methodBaseInvoker.InvokeDirectWithFewArgs(obj, ((Span<object?>)argStorage._args).Slice(0, 3));
DebugAnnotations.PreviousCallContainsDebuggerStepInCode();
return result;
}
@ -116,12 +116,12 @@ namespace System.Reflection
}
StackAllocatedArguments argStorage = default;
argStorage._args.Set(0, arg1);
argStorage._args.Set(1, arg2);
argStorage._args.Set(2, arg3);
argStorage._args.Set(3, arg4);
argStorage._args[0] = arg1;
argStorage._args[1] = arg2;
argStorage._args[2] = arg3;
argStorage._args[3] = arg4;
object? result = _methodBaseInvoker.InvokeDirectWithFewArgs(obj, argStorage._args.AsSpan(_parameterCount));
object? result = _methodBaseInvoker.InvokeDirectWithFewArgs(obj, ((Span<object?>)argStorage._args).Slice(0, 4));
DebugAnnotations.PreviousCallContainsDebuggerStepInCode();
return result;
}

View file

@ -67,27 +67,21 @@ namespace Microsoft.Extensions.DependencyInjection
}
// Attempt to use the stack allocated arg values if <= 4 ctor args.
Span<object?> values;
StackAllocatedObjects stackValues = default;
int maxArgs = GetMaxArgCount();
if (maxArgs <= StackAllocatedObjects.MaxStackAllocArgCount / 2)
{
values = MemoryMarshal.CreateSpan(ref stackValues._args._arg0, maxArgs * 2);
}
else
{
values = new Span<object?>(new object?[maxArgs * 2], 0, maxArgs * 2);
}
Span<object?> values = maxArgs <= StackAllocatedObjects.MaxStackAllocArgCount / 2 ?
stackValues :
new object?[maxArgs * 2];
Span<object?> ctorArgs = values.Slice(0, maxArgs);
Span<object?> bestCtorArgs = values.Slice(maxArgs);
Span<object?> bestCtorArgs = values.Slice(maxArgs, maxArgs);
#else
constructors = CreateConstructorInfoExs(instanceType);
object?[]? ctorArgs = null;
object?[]? bestCtorArgs = null;
#endif
ConstructorMatcher matcher = default;
scoped ConstructorMatcher matcher = default;
ConstructorInfoEx? constructor;
IServiceProviderIsService? serviceProviderIsService = provider.GetService<IServiceProviderIsService>();
// if container supports using IServiceProviderIsService, we try to find the longest ctor that
@ -124,7 +118,7 @@ namespace Microsoft.Extensions.DependencyInjection
}
int bestLength = -1;
ConstructorMatcher bestMatcher = default;
scoped ConstructorMatcher bestMatcher = default;
bool multipleBestLengthFound = false;
// Find the constructor with the most matches.
@ -1223,17 +1217,11 @@ namespace Microsoft.Extensions.DependencyInjection
}
}
[StructLayout(LayoutKind.Sequential)]
private ref struct StackAllocatedObjects
[InlineArray(MaxStackAllocArgCount)]
private struct StackAllocatedObjects
{
internal const int MaxStackAllocArgCount = 8;
internal StackAllocatedObjectValues _args;
[InlineArray(MaxStackAllocArgCount)]
internal struct StackAllocatedObjectValues
{
internal object? _arg0;
}
private object? _arg0;
}
#endif

View file

@ -454,7 +454,6 @@
<Compile Include="$(MSBuildThisFileDirectory)System\SearchValues\Strings\Helpers\AhoCorasickBuilder.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\SearchValues\Strings\Helpers\AhoCorasickNode.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\SearchValues\Strings\Helpers\CharacterFrequencyHelper.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\SearchValues\Strings\Helpers\EightPackedReferences.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\SearchValues\Strings\Helpers\RabinKarp.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\SearchValues\Strings\Helpers\StringSearchValuesHelper.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\SearchValues\Strings\Helpers\TeddyBucketizer.cs" />
@ -472,6 +471,7 @@
<Compile Include="$(MSBuildThisFileDirectory)System\SearchValues\Strings\StringSearchValuesAhoCorasick.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\SearchValues\Strings\StringSearchValuesRabinKarp.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\IndexOutOfRangeException.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\InlineArrays.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\InsufficientExecutionStackException.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\InsufficientMemoryException.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Int16.cs" />
@ -615,7 +615,6 @@
<Compile Include="$(MSBuildThisFileDirectory)System\OutOfMemoryException.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\OverflowException.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\ParamArrayAttribute.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\ParamsArray.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\ParseNumbers.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\PasteArguments.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\PlatformID.cs" />
@ -2766,4 +2765,4 @@
<Compile Include="$(MSBuildThisFileDirectory)System\Numerics\IUnaryPlusOperators.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Numerics\IUnsignedNumber.cs" />
</ItemGroup>
</Project>
</Project>

View file

@ -531,7 +531,7 @@ namespace System.IO
if (GetType() == typeof(StreamWriter))
{
TwoObjects two = new TwoObjects(arg0, arg1);
WriteFormatHelper(format, MemoryMarshal.CreateReadOnlySpan(ref two.Arg0, 2), appendNewLine: false);
WriteFormatHelper(format, two, appendNewLine: false);
}
else
{
@ -544,7 +544,7 @@ namespace System.IO
if (GetType() == typeof(StreamWriter))
{
ThreeObjects three = new ThreeObjects(arg0, arg1, arg2);
WriteFormatHelper(format, MemoryMarshal.CreateReadOnlySpan(ref three.Arg0, 3), appendNewLine: false);
WriteFormatHelper(format, three, appendNewLine: false);
}
else
{
@ -585,7 +585,7 @@ namespace System.IO
if (GetType() == typeof(StreamWriter))
{
TwoObjects two = new TwoObjects(arg0, arg1);
WriteFormatHelper(format, MemoryMarshal.CreateReadOnlySpan(ref two.Arg0, 2), appendNewLine: true);
WriteFormatHelper(format, two, appendNewLine: true);
}
else
{
@ -598,7 +598,7 @@ namespace System.IO
if (GetType() == typeof(StreamWriter))
{
ThreeObjects three = new ThreeObjects(arg0, arg1, arg2);
WriteFormatHelper(format, MemoryMarshal.CreateReadOnlySpan(ref three.Arg0, 3), appendNewLine: true);
WriteFormatHelper(format, three, appendNewLine: true);
}
else
{

View file

@ -1,13 +1,6 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// These types are temporary workarounds for an inability to stackalloc object references.
// Once we're able to do `stackalloc object[n]`, these can be removed.
// Suppress warnings for unused private fields
#pragma warning disable CS0169, CA1823, IDE0051, IDE0044
using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
namespace System
@ -15,7 +8,7 @@ namespace System
[InlineArray(2)]
internal struct TwoObjects
{
internal object? Arg0;
private object? _arg0;
public TwoObjects(object? arg0, object? arg1)
{
@ -27,7 +20,7 @@ namespace System
[InlineArray(3)]
internal struct ThreeObjects
{
internal object? Arg0;
private object? _arg0;
public ThreeObjects(object? arg0, object? arg1, object? arg2)
{
@ -36,4 +29,10 @@ namespace System
this[2] = arg2;
}
}
[InlineArray(8)]
internal struct EightObjects
{
private object? _ref0;
}
}

View file

@ -245,8 +245,8 @@ namespace System.Reflection
Debug.Assert(_argCount <= MaxStackAllocArgCount);
StackAllocatedArgumentsWithCopyBack stackArgStorage = default;
Span<object?> copyOfArgs = stackArgStorage._args.AsSpan(_argCount);
scoped Span<bool> shouldCopyBack = stackArgStorage._shouldCopyBack.AsSpan(_argCount);
Span<object?> copyOfArgs = ((Span<object?>)stackArgStorage._args).Slice(0, _argCount);
scoped Span<bool> shouldCopyBack = ((Span<bool>)stackArgStorage._shouldCopyBack).Slice(0, _argCount);
for (int i = 0; i < _argCount; i++)
{
@ -279,7 +279,7 @@ namespace System.Reflection
internal object InvokeDirectByRef(object? arg1 = null, object? arg2 = null, object? arg3 = null, object? arg4 = null)
{
StackAllocatedArguments stackStorage = new(arg1, arg2, arg3, arg4);
return InvokeDirectByRefWithFewArgs(stackStorage._args.AsSpan(_argCount));
return InvokeDirectByRefWithFewArgs(((Span<object?>)stackStorage._args).Slice(0, _argCount));
}
internal unsafe object InvokeDirectByRefWithFewArgs(Span<object?> copyOfArgs)

View file

@ -190,19 +190,6 @@ namespace System.Reflection
internal struct ArgumentData<T>
{
private T _arg0;
[UnscopedRef]
public Span<T> AsSpan(int length)
{
Debug.Assert((uint)length <= MaxStackAllocArgCount);
return new Span<T>(ref _arg0, length);
}
public void Set(int index, T value)
{
Debug.Assert((uint)index < MaxStackAllocArgCount);
Unsafe.Add(ref _arg0, index) = value;
}
}
// Helper struct to avoid intermediate object[] allocation in calls to the native reflection stack.
@ -214,10 +201,10 @@ namespace System.Reflection
{
public StackAllocatedArguments(object? obj1, object? obj2, object? obj3, object? obj4)
{
_args.Set(0, obj1);
_args.Set(1, obj2);
_args.Set(2, obj3);
_args.Set(3, obj4);
_args[0] = obj1;
_args[1] = obj2;
_args[2] = obj3;
_args[3] = obj4;
}
internal ArgumentData<object?> _args;

View file

@ -118,8 +118,8 @@ namespace System.Reflection
Debug.Assert(_argCount <= MaxStackAllocArgCount);
StackAllocatedArgumentsWithCopyBack stackArgStorage = default;
Span<object?> copyOfArgs = stackArgStorage._args.AsSpan(_argCount);
Span<bool> shouldCopyBack = stackArgStorage._shouldCopyBack.AsSpan(_argCount);
Span<object?> copyOfArgs = ((Span<object?>)stackArgStorage._args).Slice(0, _argCount);
Span<bool> shouldCopyBack = ((Span<bool>)stackArgStorage._shouldCopyBack).Slice(0, _argCount);
object? ret;
if ((_strategy & InvokerStrategy.StrategyDetermined_ObjSpanArgs) == 0)

View file

@ -298,8 +298,8 @@ namespace System.Reflection
Debug.Assert(_argCount <= MaxStackAllocArgCount);
StackAllocatedArgumentsWithCopyBack stackArgStorage = default;
Span<object?> copyOfArgs = stackArgStorage._args.AsSpan(_argCount);
scoped Span<bool> shouldCopyBack = stackArgStorage._shouldCopyBack.AsSpan(_argCount);
Span<object?> copyOfArgs = ((Span<object?>)stackArgStorage._args).Slice(0, _argCount);
scoped Span<bool> shouldCopyBack = ((Span<bool>)stackArgStorage._shouldCopyBack).Slice(0, _argCount);
for (int i = 0; i < _argCount; i++)
{
@ -332,7 +332,7 @@ namespace System.Reflection
internal object? InvokeDirectByRef(object? obj, object? arg1 = null, object? arg2 = null, object? arg3 = null, object? arg4 = null)
{
StackAllocatedArguments stackStorage = new(arg1, arg2, arg3, arg4);
return InvokeDirectByRefWithFewArgs(obj, stackStorage._args.AsSpan(_argCount));
return InvokeDirectByRefWithFewArgs(obj, ((Span<object?>)stackStorage._args).Slice(0, _argCount));
}
internal unsafe object? InvokeDirectByRefWithFewArgs(object? obj, Span<object?> copyOfArgs)

View file

@ -109,7 +109,7 @@ namespace System.Buffers
// We may have up to 8 buckets.
// If we have <= 8 strings, the buckets will be the strings themselves, and TBucketized.Value will be false.
// If we have more than 8, the buckets will be string[], and TBucketized.Value will be true.
private readonly EightPackedReferences _buckets;
private readonly EightObjects _buckets;
private readonly Vector512<byte>
_n0Low, _n0High,
@ -121,9 +121,7 @@ namespace System.Buffers
Debug.Assert(!TBucketized.Value);
Debug.Assert(n is 2 or 3);
_buckets = new EightPackedReferences(MemoryMarshal.CreateReadOnlySpan(
ref Unsafe.As<string, object>(ref MemoryMarshal.GetReference(values)),
values.Length));
ReadOnlySpan<object?>.CastUp(values).CopyTo(_buckets);
(_n0Low, _n0High) = TeddyBucketizer.GenerateNonBucketizedFingerprint(values, offset: 0);
(_n1Low, _n1High) = TeddyBucketizer.GenerateNonBucketizedFingerprint(values, offset: 1);
@ -139,7 +137,7 @@ namespace System.Buffers
Debug.Assert(TBucketized.Value);
Debug.Assert(n is 2 or 3);
_buckets = new EightPackedReferences(buckets);
((ReadOnlySpan<object?>)buckets).CopyTo(_buckets);
(_n0Low, _n0High) = TeddyBucketizer.GenerateBucketizedFingerprint(buckets, offset: 0);
(_n1Low, _n1High) = TeddyBucketizer.GenerateBucketizedFingerprint(buckets, offset: 1);

View file

@ -1,23 +0,0 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System.Diagnostics;
using System.Runtime.CompilerServices;
namespace System.Buffers
{
[InlineArray(8)]
internal struct EightPackedReferences
{
#pragma warning disable CA1823 // Unused field -- https://github.com/dotnet/roslyn-analyzers/issues/6788
private object? _ref0;
#pragma warning restore CA1823
public EightPackedReferences(ReadOnlySpan<object> values)
{
Debug.Assert(values.Length is > 0 and <= 8, $"Got {values.Length} values");
values.CopyTo(this!);
}
}
}

View file

@ -427,13 +427,13 @@ namespace System
public static string Format([StringSyntax(StringSyntaxAttribute.CompositeFormat)] string format, object? arg0, object? arg1)
{
TwoObjects two = new TwoObjects(arg0, arg1);
return FormatHelper(null, format, MemoryMarshal.CreateReadOnlySpan(ref two.Arg0, 2));
return FormatHelper(null, format, two);
}
public static string Format([StringSyntax(StringSyntaxAttribute.CompositeFormat)] string format, object? arg0, object? arg1, object? arg2)
{
ThreeObjects three = new ThreeObjects(arg0, arg1, arg2);
return FormatHelper(null, format, MemoryMarshal.CreateReadOnlySpan(ref three.Arg0, 3));
return FormatHelper(null, format, three);
}
public static string Format([StringSyntax(StringSyntaxAttribute.CompositeFormat)] string format, params object?[] args)
@ -456,13 +456,13 @@ namespace System
public static string Format(IFormatProvider? provider, [StringSyntax(StringSyntaxAttribute.CompositeFormat)] string format, object? arg0, object? arg1)
{
TwoObjects two = new TwoObjects(arg0, arg1);
return FormatHelper(provider, format, MemoryMarshal.CreateReadOnlySpan(ref two.Arg0, 2));
return FormatHelper(provider, format, two);
}
public static string Format(IFormatProvider? provider, [StringSyntax(StringSyntaxAttribute.CompositeFormat)] string format, object? arg0, object? arg1, object? arg2)
{
ThreeObjects three = new ThreeObjects(arg0, arg1, arg2);
return FormatHelper(provider, format, MemoryMarshal.CreateReadOnlySpan(ref three.Arg0, 3));
return FormatHelper(provider, format, three);
}
public static string Format(IFormatProvider? provider, [StringSyntax(StringSyntaxAttribute.CompositeFormat)] string format, params object?[] args)

View file

@ -1366,13 +1366,13 @@ namespace System.Text
public StringBuilder AppendFormat([StringSyntax(StringSyntaxAttribute.CompositeFormat)] string format, object? arg0, object? arg1)
{
TwoObjects two = new TwoObjects(arg0, arg1);
return AppendFormatHelper(null, format, MemoryMarshal.CreateReadOnlySpan(ref two.Arg0, 2));
return AppendFormatHelper(null, format, two);
}
public StringBuilder AppendFormat([StringSyntax(StringSyntaxAttribute.CompositeFormat)] string format, object? arg0, object? arg1, object? arg2)
{
ThreeObjects three = new ThreeObjects(arg0, arg1, arg2);
return AppendFormatHelper(null, format, MemoryMarshal.CreateReadOnlySpan(ref three.Arg0, 3));
return AppendFormatHelper(null, format, three);
}
public StringBuilder AppendFormat([StringSyntax(StringSyntaxAttribute.CompositeFormat)] string format, params object?[] args)
@ -1395,13 +1395,13 @@ namespace System.Text
public StringBuilder AppendFormat(IFormatProvider? provider, [StringSyntax(StringSyntaxAttribute.CompositeFormat)] string format, object? arg0, object? arg1)
{
TwoObjects two = new TwoObjects(arg0, arg1);
return AppendFormatHelper(provider, format, MemoryMarshal.CreateReadOnlySpan(ref two.Arg0, 2));
return AppendFormatHelper(provider, format, two);
}
public StringBuilder AppendFormat(IFormatProvider? provider, [StringSyntax(StringSyntaxAttribute.CompositeFormat)] string format, object? arg0, object? arg1, object? arg2)
{
ThreeObjects three = new ThreeObjects(arg0, arg1, arg2);
return AppendFormatHelper(provider, format, MemoryMarshal.CreateReadOnlySpan(ref three.Arg0, 3));
return AppendFormatHelper(provider, format, three);
}
public StringBuilder AppendFormat(IFormatProvider? provider, [StringSyntax(StringSyntaxAttribute.CompositeFormat)] string format, params object?[] args)