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,30 @@ partial interface IPhpCallable
3336<# } #>
3437 PhpValue p<#= arity - 1 #>)
3538 {
36- var phpArgs = ArrayPool<PhpValue>.Shared.Rent(<#= arity #>);
37- try
39+
40+ var tuple = new PhpArgTuple<#= arity #>
3841 {
3942<# for(int p = 0; p < arity; p++) { #>
40- phpArgs[ <#= p #>] = p<#= p #>;
43+ Argument <#= p #> = p<#= p #>,
4144<# } #>
42- return Invoke(ctx, new ReadOnlySpan<PhpValue>(phpArgs, 0, <#= arity #>));
43- }
44- finally
45- {
46- ArrayPool<PhpValue>.Shared.Return(phpArgs, true);
47- }
45+ };
46+ var phpArgs = MemoryMarshal.CreateSpan(ref tuple.Argument0, <#= arity #>);
47+ return Invoke(ctx, phpArgs);
4848 }
4949
5050<#
5151 }
52+
53+ for (int arity = 2; arity <= 16; arity++)
54+ {#>
55+ [StructLayout(LayoutKind.Sequential)]
56+ private struct PhpArgTuple<#= arity #>
57+ {
58+ <# for(int p = 0; p < arity; p++) { #>
59+ public PhpValue Argument<#= p #>;
60+ <# } #>
61+ }
62+ <#
63+ }
5264#>
5365}
0 commit comments