11<#@ output extension=".tt.cs" #>
2+ <#@ import namespace="System.Linq" #>
23using System;
3- using System.Buffers;
4- namespace Pchp.Core;
5- using System.Runtime.CompilerServices;
64using System.Runtime.InteropServices;
5+ namespace Pchp.Core;
6+
7+
78
89partial interface IPhpCallable
910{
@@ -22,6 +23,8 @@ partial interface IPhpCallable
2223 for(int arity = 2; arity <= 16; arity++)
2324 {
2425#>
26+
27+
2528 /// <summary>
2629 /// Invokes the callback with given arguments.
2730 /// Uses ArrayPool to avoid allocation.
@@ -33,21 +36,26 @@ partial interface IPhpCallable
3336<# } #>
3437 PhpValue p<#= arity - 1 #>)
3538 {
36- var phpArgs = ArrayPool<PhpValue>.Shared.Rent(<#= arity #>);
37- try
38- {
39- <# for(int p = 0; p < arity; p++) { #>
40- phpArgs[<#= p #>] = p<#= p #>;
41- <# } #>
42- return Invoke(ctx, new ReadOnlySpan<PhpValue>(phpArgs, 0, <#= arity #>));
43- }
44- finally
45- {
46- ArrayPool<PhpValue>.Shared.Return(phpArgs, true);
47- }
39+
40+ var tuple = new PhpArgTuple<#= arity #>(<#= string.Join(", ", Enumerable.Range(0, arity).Select(index => $"p{index}")) #>);
41+ var span = MemoryMarshal.CreateReadOnlySpan(ref tuple, 1);
42+ var phpArgs = MemoryMarshal.Cast<PhpArgTuple<#= arity #>, PhpValue>(span);
43+ return Invoke(ctx, phpArgs);
4844 }
4945
5046<#
5147 }
48+
49+ for (int arity = 2; arity <= 16; arity++)
50+ {#>
51+ [StructLayout(LayoutKind.Sequential)]
52+ private record struct PhpArgTuple<#= arity #>(
53+ <# for(int p = 0; p < arity - 1; p++) { #>
54+ PhpValue Argument<#= p #>,
55+ <# } #>
56+ PhpValue Argument<#= arity - 1 #>);
57+
58+ <#
59+ }
5260#>
5361}
0 commit comments