Browse Source

Revert "Optimize: pooling context"

This reverts commit 3f35b1c68a74f824d65b7e266b63ac059c45b5ca.
AnnulusGames 1 year ago
parent
commit
5ff2c53656

+ 8 - 38
src/Lua/LuaFunctionExecutionContext.cs

@@ -1,47 +1,17 @@
-using System.Collections.Concurrent;
 using System.Runtime.CompilerServices;
 using Lua.CodeAnalysis;
 
 namespace Lua;
 
-public static class LuaFunctionExecutionContextPool
+public readonly record struct LuaFunctionExecutionContext
 {
-    static readonly ConcurrentStack<LuaFunctionExecutionContext> stack = new();
-
-    [MethodImpl(MethodImplOptions.AggressiveInlining)]
-    public static LuaFunctionExecutionContext Rent()
-    {
-        if (!stack.TryPop(out var context))
-        {
-            context = new();
-        }
-
-        return context;
-    }
-
-    [MethodImpl(MethodImplOptions.AggressiveInlining)]
-    public static void Return(LuaFunctionExecutionContext context)
-    {
-        context.State = default!;
-        context.Thread = default!;
-        context.ArgumentCount = default;
-        context.FrameBase = default;
-        context.SourcePosition = default;
-        context.RootChunkName = default;
-        context.ChunkName = default;
-        stack.Push(context);
-    }
-}
-
-public record LuaFunctionExecutionContext
-{
-    public LuaState State { get; set; } = default!;
-    public LuaThread Thread { get; set; } = default!;
-    public int ArgumentCount { get; set; }
-    public int FrameBase { get; set; }
-    public SourcePosition? SourcePosition { get; set; }
-    public string? RootChunkName { get; set; }
-    public string? ChunkName { get; set; }
+    public required LuaState State { get; init; }
+    public required LuaThread Thread { get; init; }
+    public required int ArgumentCount { get; init; }
+    public required int FrameBase { get; init; }
+    public SourcePosition? SourcePosition { get; init; }
+    public string? RootChunkName { get; init; }
+    public string? ChunkName { get; init; }
 
     public ReadOnlySpan<LuaValue> Arguments
     {

+ 7 - 16
src/Lua/LuaFunctionExtensions.cs

@@ -4,6 +4,7 @@ namespace Lua;
 
 public static class LuaFunctionExtensions
 {
+
     public static async ValueTask<LuaValue[]> InvokeAsync(this LuaFunction function, LuaState state, LuaValue[] arguments, CancellationToken cancellationToken = default)
     {
         using var buffer = new PooledArray<LuaValue>(1024);
@@ -16,23 +17,13 @@ public static class LuaFunctionExtensions
             thread.Stack.Push(arguments[i]);
         }
 
-        var funcContext = LuaFunctionExecutionContextPool.Rent();
-        funcContext.State = state;
-        funcContext.Thread = thread;
-        funcContext.ArgumentCount = arguments.Length;
-        funcContext.FrameBase = frameBase;
-        funcContext.ChunkName = function.Name;
-        funcContext.RootChunkName = function.Name;
-
-        int resultCount;
-        try
+        var resultCount = await function.InvokeAsync(new()
         {
-            resultCount = await function.InvokeAsync(funcContext, buffer.AsMemory(), cancellationToken);
-        }
-        finally
-        {
-            LuaFunctionExecutionContextPool.Return(funcContext);
-        }
+            State = state,
+            Thread = thread,
+            ArgumentCount = arguments.Length,
+            FrameBase = frameBase,
+        }, buffer.AsMemory(), cancellationToken);
 
         return buffer.AsSpan()[0..resultCount].ToArray();
     }

+ 10 - 12
src/Lua/LuaState.cs

@@ -61,25 +61,23 @@ public sealed class LuaState
         ThrowIfRunning();
 
         Volatile.Write(ref isRunning, true);
-        var funcContext = LuaFunctionExecutionContextPool.Rent();
         try
         {
             var closure = new Closure(this, chunk);
-
-            funcContext.State = this;
-            funcContext.Thread = CurrentThread;
-            funcContext.ArgumentCount = 0;
-            funcContext.FrameBase = 0;
-            funcContext.SourcePosition = null;
-            funcContext.RootChunkName = chunk.Name;
-            funcContext.ChunkName = chunk.Name;
-
-            return await closure.InvokeAsync(funcContext, buffer, cancellationToken);
+            return await closure.InvokeAsync(new()
+            {
+                State = this,
+                Thread = CurrentThread,
+                ArgumentCount = 0,
+                FrameBase = 0,
+                SourcePosition = null,
+                RootChunkName = chunk.Name,
+                ChunkName = chunk.Name,
+            }, buffer, cancellationToken);
         }
         finally
         {
             Volatile.Write(ref isRunning, false);
-            LuaFunctionExecutionContextPool.Return(funcContext);
         }
     }
 

+ 177 - 325
src/Lua/Runtime/LuaVirtualMachine.cs

@@ -63,21 +63,10 @@ public static partial class LuaVirtualMachine
                             var vc = RK(stack, chunk, instruction.C, frame.Base);
                             var upValue = closure.UpValues[instruction.B];
                             var table = upValue.GetValue();
-
-                            (var task, var funcContext) = GetTableValue(state, thread, chunk, rootChunk, pc, table, vc, resultBuffer.AsMemory(), cancellationToken);
-                            try
-                            {
-                                await task;
-                                stack.UnsafeGet(RA) = resultBuffer[0];
-                                stack.NotifyTop(RA + 1);
-                            }
-                            finally
-                            {
-                                if (funcContext != null)
-                                {
-                                    LuaFunctionExecutionContextPool.Return(funcContext);
-                                }
-                            }
+                            await GetTableValue(state, thread, chunk, rootChunk, pc, table, vc, resultBuffer.AsMemory(), cancellationToken);
+                            var value = resultBuffer[0];
+                            stack.UnsafeGet(RA) = value;
+                            stack.NotifyTop(RA + 1);
                             break;
                         }
                     case OpCode.GetTable:
@@ -85,20 +74,10 @@ public static partial class LuaVirtualMachine
                             stack.EnsureCapacity(RA + 1);
                             var table = stack.UnsafeGet(RB);
                             var vc = RK(stack, chunk, instruction.C, frame.Base);
-                            (var task, var funcContext) = GetTableValue(state, thread, chunk, rootChunk, pc, table, vc, resultBuffer.AsMemory(), cancellationToken);
-                            try
-                            {
-                                await task;
-                                stack.UnsafeGet(RA) = resultBuffer[0];
-                                stack.NotifyTop(RA + 1);
-                            }
-                            finally
-                            {
-                                if (funcContext != null)
-                                {
-                                    LuaFunctionExecutionContextPool.Return(funcContext);
-                                }
-                            }
+                            await GetTableValue(state, thread, chunk, rootChunk, pc, table, vc, resultBuffer.AsMemory(), cancellationToken);
+                            var value = resultBuffer[0];
+                            stack.UnsafeGet(RA) = value;
+                            stack.NotifyTop(RA + 1);
                         }
                         break;
                     case OpCode.SetTabUp:
@@ -108,21 +87,9 @@ public static partial class LuaVirtualMachine
 
                             var upValue = closure.UpValues[instruction.A];
                             var table = upValue.GetValue();
-
-                            (var task, var funcContext) = SetTableValue(state, thread, chunk, rootChunk, pc, table, vb, vc, resultBuffer.AsMemory(), cancellationToken);
-                            try
-                            {
-                                await task;
-                            }
-                            finally
-                            {
-                                if (funcContext != null)
-                                {
-                                    LuaFunctionExecutionContextPool.Return(funcContext);
-                                }
-                            }
+                            await SetTableValue(state, thread, chunk, rootChunk, pc, table, vb, vc, resultBuffer.AsMemory(), cancellationToken);
+                            break;
                         }
-                        break;
                     case OpCode.SetUpVal:
                         {
                             var upValue = closure.UpValues[instruction.B];
@@ -134,19 +101,7 @@ public static partial class LuaVirtualMachine
                             var table = stack.UnsafeGet(RA);
                             var vb = RK(stack, chunk, instruction.B, frame.Base);
                             var vc = RK(stack, chunk, instruction.C, frame.Base);
-
-                            (var task, var funcContext) = SetTableValue(state, thread, chunk, rootChunk, pc, table, vb, vc, resultBuffer.AsMemory(), cancellationToken);
-                            try
-                            {
-                                await task;
-                            }
-                            finally
-                            {
-                                if (funcContext != null)
-                                {
-                                    LuaFunctionExecutionContextPool.Return(funcContext);
-                                }
-                            }
+                            await SetTableValue(state, thread, chunk, rootChunk, pc, table, vb, vc, resultBuffer.AsMemory(), cancellationToken);
                         }
                         break;
                     case OpCode.NewTable:
@@ -160,22 +115,12 @@ public static partial class LuaVirtualMachine
                             var table = stack.UnsafeGet(RB);
                             var vc = RK(stack, chunk, instruction.C, frame.Base);
 
-                            (var task, var funcContext) = GetTableValue(state, thread, chunk, rootChunk, pc, table, vc, resultBuffer.AsMemory(), cancellationToken);
-                            try
-                            {
-                                await task; 
-                                var value = resultBuffer[0];
-                                stack.UnsafeGet(RA + 1) = table;
-                                stack.UnsafeGet(RA) = value;
-                                stack.NotifyTop(RA + 2);
-                            }
-                            finally
-                            {
-                                if (funcContext != null)
-                                {
-                                    LuaFunctionExecutionContextPool.Return(funcContext);
-                                }
-                            }
+                            await GetTableValue(state, thread, chunk, rootChunk, pc, table, vc, resultBuffer.AsMemory(), cancellationToken);
+                            var value = resultBuffer[0];
+
+                            stack.UnsafeGet(RA + 1) = table;
+                            stack.UnsafeGet(RA) = value;
+                            stack.NotifyTop(RA + 2);
                         }
                         break;
                     case OpCode.Add:
@@ -199,22 +144,16 @@ public static partial class LuaVirtualMachine
                                 stack.Push(vb);
                                 stack.Push(vc);
 
-                                var funcContext = LuaFunctionExecutionContextPool.Rent();
-                                funcContext.State = state;
-                                funcContext.Thread = thread;
-                                funcContext.ArgumentCount = 2;
-                                funcContext.FrameBase = stack.Count - 2;
-                                funcContext.SourcePosition = MemoryMarshalEx.UnsafeElementAt(chunk.SourcePositions, pc);
-                                funcContext.ChunkName = chunk.Name;
-                                funcContext.RootChunkName = rootChunk.Name;
-                                try
-                                {
-                                    await func.InvokeAsync(funcContext, resultBuffer.AsMemory(), cancellationToken);
-                                }
-                                finally
+                                await func.InvokeAsync(new()
                                 {
-                                    LuaFunctionExecutionContextPool.Return(funcContext);
-                                }
+                                    State = state,
+                                    Thread = thread,
+                                    ArgumentCount = 2,
+                                    FrameBase = stack.Count - 2,
+                                    SourcePosition = MemoryMarshalEx.UnsafeElementAt(chunk.SourcePositions, pc),
+                                    ChunkName = chunk.Name,
+                                    RootChunkName = rootChunk.Name,
+                                }, resultBuffer.AsMemory(), cancellationToken);
 
                                 stack.UnsafeGet(RA) = resultBuffer[0];
                             }
@@ -247,22 +186,16 @@ public static partial class LuaVirtualMachine
                                 stack.Push(vb);
                                 stack.Push(vc);
 
-                                var funcContext = LuaFunctionExecutionContextPool.Rent();
-                                funcContext.State = state;
-                                funcContext.Thread = thread;
-                                funcContext.ArgumentCount = 2;
-                                funcContext.FrameBase = stack.Count - 2;
-                                funcContext.SourcePosition = MemoryMarshalEx.UnsafeElementAt(chunk.SourcePositions, pc);
-                                funcContext.ChunkName = chunk.Name;
-                                funcContext.RootChunkName = rootChunk.Name;
-                                try
-                                {
-                                    await func.InvokeAsync(funcContext, resultBuffer.AsMemory(), cancellationToken);
-                                }
-                                finally
+                                await func.InvokeAsync(new()
                                 {
-                                    LuaFunctionExecutionContextPool.Return(funcContext);
-                                }
+                                    State = state,
+                                    Thread = thread,
+                                    ArgumentCount = 2,
+                                    FrameBase = stack.Count - 2,
+                                    SourcePosition = MemoryMarshalEx.UnsafeElementAt(chunk.SourcePositions, pc),
+                                    ChunkName = chunk.Name,
+                                    RootChunkName = rootChunk.Name,
+                                }, resultBuffer.AsMemory(), cancellationToken);
 
                                 stack.UnsafeGet(RA) = resultBuffer[0];
                             }
@@ -295,22 +228,16 @@ public static partial class LuaVirtualMachine
                                 stack.Push(vb);
                                 stack.Push(vc);
 
-                                var funcContext = LuaFunctionExecutionContextPool.Rent();
-                                funcContext.State = state;
-                                funcContext.Thread = thread;
-                                funcContext.ArgumentCount = 2;
-                                funcContext.FrameBase = stack.Count - 2;
-                                funcContext.SourcePosition = MemoryMarshalEx.UnsafeElementAt(chunk.SourcePositions, pc);
-                                funcContext.ChunkName = chunk.Name;
-                                funcContext.RootChunkName = rootChunk.Name;
-                                try
+                                await func.InvokeAsync(new()
                                 {
-                                    await func.InvokeAsync(funcContext, resultBuffer.AsMemory(), cancellationToken);
-                                }
-                                finally
-                                {
-                                    LuaFunctionExecutionContextPool.Return(funcContext);
-                                }
+                                    State = state,
+                                    Thread = thread,
+                                    ArgumentCount = 2,
+                                    FrameBase = stack.Count - 2,
+                                    SourcePosition = MemoryMarshalEx.UnsafeElementAt(chunk.SourcePositions, pc),
+                                    ChunkName = chunk.Name,
+                                    RootChunkName = rootChunk.Name,
+                                }, resultBuffer.AsMemory(), cancellationToken);
 
                                 stack.UnsafeGet(RA) = resultBuffer[0];
                             }
@@ -343,22 +270,16 @@ public static partial class LuaVirtualMachine
                                 stack.Push(vb);
                                 stack.Push(vc);
 
-                                var funcContext = LuaFunctionExecutionContextPool.Rent();
-                                funcContext.State = state;
-                                funcContext.Thread = thread;
-                                funcContext.ArgumentCount = 2;
-                                funcContext.FrameBase = stack.Count - 2;
-                                funcContext.SourcePosition = MemoryMarshalEx.UnsafeElementAt(chunk.SourcePositions, pc);
-                                funcContext.ChunkName = chunk.Name;
-                                funcContext.RootChunkName = rootChunk.Name;
-                                try
+                                await func.InvokeAsync(new()
                                 {
-                                    await func.InvokeAsync(funcContext, resultBuffer.AsMemory(), cancellationToken);
-                                }
-                                finally
-                                {
-                                    LuaFunctionExecutionContextPool.Return(funcContext);
-                                }
+                                    State = state,
+                                    Thread = thread,
+                                    ArgumentCount = 2,
+                                    FrameBase = stack.Count - 2,
+                                    SourcePosition = MemoryMarshalEx.UnsafeElementAt(chunk.SourcePositions, pc),
+                                    ChunkName = chunk.Name,
+                                    RootChunkName = rootChunk.Name,
+                                }, resultBuffer.AsMemory(), cancellationToken);
 
                                 stack.UnsafeGet(RA) = resultBuffer[0];
                             }
@@ -396,22 +317,16 @@ public static partial class LuaVirtualMachine
                                 stack.Push(vb);
                                 stack.Push(vc);
 
-                                var funcContext = LuaFunctionExecutionContextPool.Rent();
-                                funcContext.State = state;
-                                funcContext.Thread = thread;
-                                funcContext.ArgumentCount = 2;
-                                funcContext.FrameBase = stack.Count - 2;
-                                funcContext.SourcePosition = MemoryMarshalEx.UnsafeElementAt(chunk.SourcePositions, pc);
-                                funcContext.ChunkName = chunk.Name;
-                                funcContext.RootChunkName = rootChunk.Name;
-                                try
+                                await func.InvokeAsync(new()
                                 {
-                                    await func.InvokeAsync(funcContext, resultBuffer.AsMemory(), cancellationToken);
-                                }
-                                finally
-                                {
-                                    LuaFunctionExecutionContextPool.Return(funcContext);
-                                }
+                                    State = state,
+                                    Thread = thread,
+                                    ArgumentCount = 2,
+                                    FrameBase = stack.Count - 2,
+                                    SourcePosition = MemoryMarshalEx.UnsafeElementAt(chunk.SourcePositions, pc),
+                                    ChunkName = chunk.Name,
+                                    RootChunkName = rootChunk.Name,
+                                }, resultBuffer.AsMemory(), cancellationToken);
 
                                 stack.UnsafeGet(RA) = resultBuffer[0];
                             }
@@ -444,22 +359,16 @@ public static partial class LuaVirtualMachine
                                 stack.Push(vb);
                                 stack.Push(vc);
 
-                                var funcContext = LuaFunctionExecutionContextPool.Rent();
-                                funcContext.State = state;
-                                funcContext.Thread = thread;
-                                funcContext.ArgumentCount = 2;
-                                funcContext.FrameBase = stack.Count - 2;
-                                funcContext.SourcePosition = MemoryMarshalEx.UnsafeElementAt(chunk.SourcePositions, pc);
-                                funcContext.ChunkName = chunk.Name;
-                                funcContext.RootChunkName = rootChunk.Name;
-                                try
+                                await func.InvokeAsync(new()
                                 {
-                                    await func.InvokeAsync(funcContext, resultBuffer.AsMemory(), cancellationToken);
-                                }
-                                finally
-                                {
-                                    LuaFunctionExecutionContextPool.Return(funcContext);
-                                }
+                                    State = state,
+                                    Thread = thread,
+                                    ArgumentCount = 2,
+                                    FrameBase = stack.Count - 2,
+                                    SourcePosition = MemoryMarshalEx.UnsafeElementAt(chunk.SourcePositions, pc),
+                                    ChunkName = chunk.Name,
+                                    RootChunkName = rootChunk.Name,
+                                }, resultBuffer.AsMemory(), cancellationToken);
 
                                 stack.UnsafeGet(RA) = resultBuffer[0];
                             }
@@ -490,22 +399,16 @@ public static partial class LuaVirtualMachine
 
                                 stack.Push(vb);
 
-                                var funcContext = LuaFunctionExecutionContextPool.Rent();
-                                funcContext.State = state;
-                                funcContext.Thread = thread;
-                                funcContext.ArgumentCount = 1;
-                                funcContext.FrameBase = stack.Count - 1;
-                                funcContext.SourcePosition = MemoryMarshalEx.UnsafeElementAt(chunk.SourcePositions, pc);
-                                funcContext.ChunkName = chunk.Name;
-                                funcContext.RootChunkName = rootChunk.Name;
-                                try
-                                {
-                                    await func.InvokeAsync(funcContext, resultBuffer.AsMemory(), cancellationToken);
-                                }
-                                finally
+                                await func.InvokeAsync(new()
                                 {
-                                    LuaFunctionExecutionContextPool.Return(funcContext);
-                                }
+                                    State = state,
+                                    Thread = thread,
+                                    ArgumentCount = 1,
+                                    FrameBase = stack.Count - 1,
+                                    SourcePosition = MemoryMarshalEx.UnsafeElementAt(chunk.SourcePositions, pc),
+                                    ChunkName = chunk.Name,
+                                    RootChunkName = rootChunk.Name,
+                                }, resultBuffer.AsMemory(), cancellationToken);
 
                                 stack.UnsafeGet(RA) = resultBuffer[0];
                             }
@@ -543,22 +446,16 @@ public static partial class LuaVirtualMachine
 
                                 stack.Push(vb);
 
-                                var funcContext = LuaFunctionExecutionContextPool.Rent();
-                                funcContext.State = state;
-                                funcContext.Thread = thread;
-                                funcContext.ArgumentCount = 1;
-                                funcContext.FrameBase = stack.Count - 1;
-                                funcContext.SourcePosition = MemoryMarshalEx.UnsafeElementAt(chunk.SourcePositions, pc);
-                                funcContext.ChunkName = chunk.Name;
-                                funcContext.RootChunkName = rootChunk.Name;
-                                try
-                                {
-                                    await func.InvokeAsync(funcContext, resultBuffer.AsMemory(), cancellationToken);
-                                }
-                                finally
+                                await func.InvokeAsync(new()
                                 {
-                                    LuaFunctionExecutionContextPool.Return(funcContext);
-                                }
+                                    State = state,
+                                    Thread = thread,
+                                    ArgumentCount = 1,
+                                    FrameBase = stack.Count - 1,
+                                    SourcePosition = MemoryMarshalEx.UnsafeElementAt(chunk.SourcePositions, pc),
+                                    ChunkName = chunk.Name,
+                                    RootChunkName = rootChunk.Name,
+                                }, resultBuffer.AsMemory(), cancellationToken);
 
                                 stack.UnsafeGet(RA) = resultBuffer[0];
                             }
@@ -609,22 +506,16 @@ public static partial class LuaVirtualMachine
                                 stack.Push(vb);
                                 stack.Push(vc);
 
-                                var funcContext = LuaFunctionExecutionContextPool.Rent();
-                                funcContext.State = state;
-                                funcContext.Thread = thread;
-                                funcContext.ArgumentCount = 2;
-                                funcContext.FrameBase = stack.Count - 2;
-                                funcContext.SourcePosition = MemoryMarshalEx.UnsafeElementAt(chunk.SourcePositions, pc);
-                                funcContext.ChunkName = chunk.Name;
-                                funcContext.RootChunkName = rootChunk.Name;
-                                try
-                                {
-                                    await func.InvokeAsync(funcContext, resultBuffer.AsMemory(), cancellationToken);
-                                }
-                                finally
+                                await func.InvokeAsync(new()
                                 {
-                                    LuaFunctionExecutionContextPool.Return(funcContext);
-                                }
+                                    State = state,
+                                    Thread = thread,
+                                    ArgumentCount = 2,
+                                    FrameBase = stack.Count - 2,
+                                    SourcePosition = MemoryMarshalEx.UnsafeElementAt(chunk.SourcePositions, pc),
+                                    ChunkName = chunk.Name,
+                                    RootChunkName = rootChunk.Name,
+                                }, resultBuffer.AsMemory(), cancellationToken);
 
                                 stack.UnsafeGet(RA) = resultBuffer[0];
                             }
@@ -659,22 +550,16 @@ public static partial class LuaVirtualMachine
                                 stack.Push(vb);
                                 stack.Push(vc);
 
-                                var funcContext = LuaFunctionExecutionContextPool.Rent();
-                                funcContext.State = state;
-                                funcContext.Thread = thread;
-                                funcContext.ArgumentCount = 2;
-                                funcContext.FrameBase = stack.Count - 2;
-                                funcContext.SourcePosition = MemoryMarshalEx.UnsafeElementAt(chunk.SourcePositions, pc);
-                                funcContext.ChunkName = chunk.Name;
-                                funcContext.RootChunkName = rootChunk.Name;
-                                try
-                                {
-                                    await func.InvokeAsync(funcContext, resultBuffer.AsMemory(), cancellationToken);
-                                }
-                                finally
+                                await func.InvokeAsync(new()
                                 {
-                                    LuaFunctionExecutionContextPool.Return(funcContext);
-                                }
+                                    State = state,
+                                    Thread = thread,
+                                    ArgumentCount = 2,
+                                    FrameBase = stack.Count - 2,
+                                    SourcePosition = MemoryMarshalEx.UnsafeElementAt(chunk.SourcePositions, pc),
+                                    ChunkName = chunk.Name,
+                                    RootChunkName = rootChunk.Name,
+                                }, resultBuffer.AsMemory(), cancellationToken);
 
                                 compareResult = resultBuffer[0].ToBoolean();
                             }
@@ -709,22 +594,16 @@ public static partial class LuaVirtualMachine
                                 stack.Push(vb);
                                 stack.Push(vc);
 
-                                var funcContext = LuaFunctionExecutionContextPool.Rent();
-                                funcContext.State = state;
-                                funcContext.Thread = thread;
-                                funcContext.ArgumentCount = 2;
-                                funcContext.FrameBase = stack.Count - 2;
-                                funcContext.SourcePosition = MemoryMarshalEx.UnsafeElementAt(chunk.SourcePositions, pc);
-                                funcContext.ChunkName = chunk.Name;
-                                funcContext.RootChunkName = rootChunk.Name;
-                                try
-                                {
-                                    await func.InvokeAsync(funcContext, resultBuffer.AsMemory(), cancellationToken);
-                                }
-                                finally
+                                await func.InvokeAsync(new()
                                 {
-                                    LuaFunctionExecutionContextPool.Return(funcContext);
-                                }
+                                    State = state,
+                                    Thread = thread,
+                                    ArgumentCount = 2,
+                                    FrameBase = stack.Count - 2,
+                                    SourcePosition = MemoryMarshalEx.UnsafeElementAt(chunk.SourcePositions, pc),
+                                    ChunkName = chunk.Name,
+                                    RootChunkName = rootChunk.Name,
+                                }, resultBuffer.AsMemory(), cancellationToken);
 
                                 compareResult = resultBuffer[0].ToBoolean();
                             }
@@ -763,22 +642,16 @@ public static partial class LuaVirtualMachine
                                 stack.Push(vb);
                                 stack.Push(vc);
 
-                                var funcContext = LuaFunctionExecutionContextPool.Rent();
-                                funcContext.State = state;
-                                funcContext.Thread = thread;
-                                funcContext.ArgumentCount = 2;
-                                funcContext.FrameBase = stack.Count - 2;
-                                funcContext.SourcePosition = MemoryMarshalEx.UnsafeElementAt(chunk.SourcePositions, pc);
-                                funcContext.ChunkName = chunk.Name;
-                                funcContext.RootChunkName = rootChunk.Name;
-                                try
+                                await func.InvokeAsync(new()
                                 {
-                                    await func.InvokeAsync(funcContext, resultBuffer.AsMemory(), cancellationToken);
-                                }
-                                finally
-                                {
-                                    LuaFunctionExecutionContextPool.Return(funcContext);
-                                }
+                                    State = state,
+                                    Thread = thread,
+                                    ArgumentCount = 2,
+                                    FrameBase = stack.Count - 2,
+                                    SourcePosition = MemoryMarshalEx.UnsafeElementAt(chunk.SourcePositions, pc),
+                                    ChunkName = chunk.Name,
+                                    RootChunkName = rootChunk.Name,
+                                }, resultBuffer.AsMemory(), cancellationToken);
 
                                 compareResult = resultBuffer[0].ToBoolean();
                             }
@@ -845,25 +718,18 @@ public static partial class LuaVirtualMachine
                             });
 
                             int rawResultCount;
-
                             try
                             {
-                                var funcContext = LuaFunctionExecutionContextPool.Rent();
-                                funcContext.State = state;
-                                funcContext.Thread = thread;
-                                funcContext.ArgumentCount = argumentCount;
-                                funcContext.FrameBase = newBase;
-                                funcContext.SourcePosition = callPosition;
-                                funcContext.ChunkName = chunkName;
-                                funcContext.RootChunkName = rootChunkName;
-                                try
-                                {
-                                    rawResultCount = await func.InternalInvokeAsyncCore(funcContext, resultBuffer.AsMemory(), cancellationToken);
-                                }
-                                finally
+                                rawResultCount = await func.InternalInvokeAsyncCore(new()
                                 {
-                                    LuaFunctionExecutionContextPool.Return(funcContext);
-                                }
+                                    State = state,
+                                    Thread = thread,
+                                    ArgumentCount = argumentCount,
+                                    FrameBase = newBase,
+                                    SourcePosition = callPosition,
+                                    ChunkName = chunkName,
+                                    RootChunkName = rootChunkName,
+                                }, resultBuffer.AsMemory(), cancellationToken);
                             }
                             finally
                             {
@@ -909,22 +775,16 @@ public static partial class LuaVirtualMachine
 
                             (var newBase, var argumentCount) = PrepareForFunctionCall(thread, func, instruction, RA, resultBuffer.AsSpan(), true);
 
-                            var funcContext = LuaFunctionExecutionContextPool.Rent();
-                            funcContext.State = state;
-                            funcContext.Thread = thread;
-                            funcContext.ArgumentCount = argumentCount;
-                            funcContext.FrameBase = newBase;
-                            funcContext.SourcePosition = MemoryMarshalEx.UnsafeElementAt(chunk.SourcePositions, pc);
-                            funcContext.ChunkName = chunk.Name;
-                            funcContext.RootChunkName = rootChunk.Name;
-                            try
-                            {
-                                return await func.InvokeAsync(funcContext, buffer, cancellationToken);
-                            }
-                            finally
+                            return await func.InvokeAsync(new()
                             {
-                                LuaFunctionExecutionContextPool.Return(funcContext);
-                            }
+                                State = state,
+                                Thread = thread,
+                                ArgumentCount = argumentCount,
+                                FrameBase = newBase,
+                                SourcePosition = MemoryMarshalEx.UnsafeElementAt(chunk.SourcePositions, pc),
+                                ChunkName = chunk.Name,
+                                RootChunkName = rootChunk.Name,
+                            }, buffer, cancellationToken);
                         }
                     case OpCode.Return:
                         {
@@ -1008,24 +868,16 @@ public static partial class LuaVirtualMachine
                             stack.UnsafeGet(nextBase + 1) = stack.UnsafeGet(RA + 2);
                             stack.NotifyTop(nextBase + 2);
 
-                            var funcContext = LuaFunctionExecutionContextPool.Rent();
-                            funcContext.State = state;
-                            funcContext.Thread = thread;
-                            funcContext.ArgumentCount = 2;
-                            funcContext.FrameBase = nextBase;
-                            funcContext.SourcePosition = MemoryMarshalEx.UnsafeElementAt(chunk.SourcePositions, pc);
-                            funcContext.ChunkName = chunk.Name;
-                            funcContext.RootChunkName = rootChunk.Name;
-
-                            int resultCount;
-                            try
+                            var resultCount = await iterator.InvokeAsync(new()
                             {
-                                resultCount = await iterator.InvokeAsync(funcContext, resultBuffer.AsMemory(), cancellationToken);
-                            }
-                            finally
-                            {
-                                LuaFunctionExecutionContextPool.Return(funcContext);
-                            }
+                                State = state,
+                                Thread = thread,
+                                ArgumentCount = 2,
+                                FrameBase = nextBase,
+                                SourcePosition = MemoryMarshalEx.UnsafeElementAt(chunk.SourcePositions, pc),
+                                ChunkName = chunk.Name,
+                                RootChunkName = rootChunk.Name,
+                            }, resultBuffer.AsMemory(), cancellationToken);
 
                             stack.EnsureCapacity(RA + instruction.C + 3);
                             for (int i = 1; i <= instruction.C; i++)
@@ -1118,7 +970,7 @@ public static partial class LuaVirtualMachine
         }
     }
 
-    static (ValueTask<int> Task, LuaFunctionExecutionContext? Context) GetTableValue(LuaState state, LuaThread thread, Chunk chunk, Chunk rootChunk, int pc, LuaValue table, LuaValue key, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    static ValueTask<int> GetTableValue(LuaState state, LuaThread thread, Chunk chunk, Chunk rootChunk, int pc, LuaValue table, LuaValue key, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
         var stack = thread.Stack;
         var isTable = table.TryRead<LuaTable>(out var t);
@@ -1126,7 +978,7 @@ public static partial class LuaVirtualMachine
         if (isTable && t.TryGetValue(key, out var result))
         {
             buffer.Span[0] = result;
-            return (new(1), null);
+            return new(1);
         }
         else if (table.TryGetMetamethod(state, Metamethods.Index, out var metamethod))
         {
@@ -1138,21 +990,21 @@ public static partial class LuaVirtualMachine
             stack.Push(table);
             stack.Push(key);
 
-            var funcContext = LuaFunctionExecutionContextPool.Rent();
-            funcContext.State = state;
-            funcContext.Thread = thread;
-            funcContext.ArgumentCount = 2;
-            funcContext.FrameBase = stack.Count - 2;
-            funcContext.SourcePosition = MemoryMarshalEx.UnsafeElementAt(chunk.SourcePositions, pc);
-            funcContext.ChunkName = chunk.Name;
-            funcContext.RootChunkName = rootChunk.Name;
-
-            return (indexTable.InvokeAsync(funcContext, buffer, cancellationToken), funcContext);
+            return indexTable.InvokeAsync(new()
+            {
+                State = state,
+                Thread = thread,
+                ArgumentCount = 2,
+                SourcePosition = MemoryMarshalEx.UnsafeElementAt(chunk.SourcePositions, pc),
+                FrameBase = stack.Count - 2,
+                ChunkName = chunk.Name,
+                RootChunkName = rootChunk.Name,
+            }, buffer, cancellationToken);
         }
         else if (isTable)
         {
             buffer.Span[0] = LuaValue.Nil;
-            return (new(1), null);
+            return new(1);
         }
         else
         {
@@ -1161,7 +1013,7 @@ public static partial class LuaVirtualMachine
         }
     }
 
-    static (ValueTask<int> Task, LuaFunctionExecutionContext? Context) SetTableValue(LuaState state, LuaThread thread, Chunk chunk, Chunk rootChunk, int pc, LuaValue table, LuaValue key, LuaValue value, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    static ValueTask<int> SetTableValue(LuaState state, LuaThread thread, Chunk chunk, Chunk rootChunk, int pc, LuaValue table, LuaValue key, LuaValue value, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
         var stack = thread.Stack;
         var isTable = table.TryRead<LuaTable>(out var t);
@@ -1178,7 +1030,7 @@ public static partial class LuaVirtualMachine
         if (isTable)
         {
             t[key] = value;
-            return (new(1), null);
+            return new(1);
         }
         else if (table.TryGetMetamethod(state, Metamethods.NewIndex, out var metamethod))
         {
@@ -1191,16 +1043,16 @@ public static partial class LuaVirtualMachine
             stack.Push(key);
             stack.Push(value);
 
-            var funcContext = LuaFunctionExecutionContextPool.Rent();
-            funcContext.State = state;
-            funcContext.Thread = thread;
-            funcContext.ArgumentCount = 3;
-            funcContext.FrameBase = stack.Count - 3;
-            funcContext.SourcePosition = MemoryMarshalEx.UnsafeElementAt(chunk.SourcePositions, pc);
-            funcContext.ChunkName = chunk.Name;
-            funcContext.RootChunkName = rootChunk.Name;
-
-            return (indexTable.InvokeAsync(funcContext, buffer, cancellationToken), funcContext);
+            return indexTable.InvokeAsync(new()
+            {
+                State = state,
+                Thread = thread,
+                ArgumentCount = 3,
+                FrameBase = stack.Count - 3,
+                SourcePosition = MemoryMarshalEx.UnsafeElementAt(chunk.SourcePositions, pc),
+                ChunkName = chunk.Name,
+                RootChunkName = rootChunk.Name,
+            }, buffer, cancellationToken);
         }
         else
         {