Browse Source

Optimize: LuaVirtualMachine

Akeit0 1 year ago
parent
commit
c941f69a44

+ 70 - 0
src/Lua/Internal/LuaValueArrayPool.cs

@@ -0,0 +1,70 @@
+namespace Lua.Internal;
+
+internal static class LuaValueArrayPool
+{
+    static FastStackCore<LuaValue[]> poolOf1024;
+    static FastStackCore<LuaValue[]> poolOf1;
+
+    static readonly object lockObject = new();
+
+
+    public static LuaValue[] Rent1024()
+    {
+        lock (lockObject)
+        {
+            if (poolOf1024.Count > 0)
+            {
+                return poolOf1024.Pop();
+            }
+
+            return new LuaValue[1024];
+        }
+    }
+
+    public static LuaValue[] Rent1()
+    {
+        lock (lockObject)
+        {
+            if (poolOf1.Count > 0)
+            {
+                return poolOf1.Pop();
+            }
+
+            return new LuaValue[1];
+        }
+    }
+
+    public static void Return1024(LuaValue[] array)
+    {
+        if (array.Length != 1024)
+        {
+            ThrowInvalidArraySize(array.Length, 1024);
+        }
+
+        array.AsSpan().Clear();
+        lock (lockObject)
+        {
+            poolOf1024.Push(array);
+        }
+    }
+
+
+    public static void Return1(LuaValue[] array)
+    {
+        if (array.Length != 1)
+        {
+            ThrowInvalidArraySize(array.Length, 1);
+        }
+
+        array[0] = LuaValue.Nil;
+        lock (lockObject)
+        {
+            poolOf1.Push(array);
+        }
+    }
+
+    static void ThrowInvalidArraySize(int size, int expectedSize)
+    {
+        throw new InvalidOperationException($"Invalid array size: {size}, expected: {expectedSize}");
+    }
+}

+ 7 - 0
src/Lua/LuaFunction.cs

@@ -1,3 +1,4 @@
+using System.Runtime.CompilerServices;
 using Lua.Runtime;
 
 namespace Lua;
@@ -7,6 +8,12 @@ public class LuaFunction(string name, Func<LuaFunctionExecutionContext, Memory<L
     public string Name { get; } = name;
     internal Func<LuaFunctionExecutionContext, Memory<LuaValue>, CancellationToken, ValueTask<int>> Func { get; } = func;
 
+    internal bool IsClosure
+    {
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        get; private protected init;
+    } = false;
+
     public LuaFunction(Func<LuaFunctionExecutionContext, Memory<LuaValue>, CancellationToken, ValueTask<int>> func) : this("anonymous", func)
     {
     }

+ 1 - 0
src/Lua/LuaFunctionExecutionContext.cs

@@ -14,6 +14,7 @@ public readonly record struct LuaFunctionExecutionContext
     public SourcePosition? SourcePosition { get; init; }
     public string? RootChunkName { get; init; }
     public string? ChunkName { get; init; }
+    public  int? CallerInstructionIndex { get; init; }
     public object? AdditionalContext { get; init; }
 
     public ReadOnlySpan<LuaValue> Arguments

+ 37 - 3
src/Lua/LuaThread.cs

@@ -1,3 +1,4 @@
+using System.Runtime.CompilerServices;
 using Lua.Internal;
 using Lua.Runtime;
 
@@ -31,15 +32,46 @@ public abstract class LuaThread
         return callStack.AsSpan();
     }
 
-    internal void PushCallStackFrame(CallStackFrame frame)
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    internal void PushCallStackFrame(in CallStackFrame frame)
     {
         callStack.Push(frame);
     }
 
+
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
     internal void PopCallStackFrame()
     {
-        var frame = callStack.Pop();
-        stack.PopUntil(frame.Base);
+        if (callStack.TryPop(out var frame))
+        {
+            stack.PopUntil(frame.Base);
+        }
+        else
+        {
+            ThrowForEmptyStack();
+        }
+    }
+
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    internal void PopCallStackFrameUnsafe(int frameBase)
+    {
+        if (callStack.TryPop())
+        {
+            stack.PopUntil(frameBase);
+        }
+        else
+        {
+            ThrowForEmptyStack();
+        }
+    }
+
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    internal void PopCallStackFrameUnsafe()
+    {
+        if (!callStack.TryPop())
+        {
+            ThrowForEmptyStack();
+        }
     }
 
     internal void DumpStackValues()
@@ -50,4 +82,6 @@ public abstract class LuaThread
             Console.WriteLine($"LuaStack [{i}]\t{span[i]}");
         }
     }
+    
+    static void ThrowForEmptyStack() => throw new InvalidOperationException("Empty stack");
 }

+ 1 - 0
src/Lua/Runtime/CallStackFrame.cs

@@ -12,4 +12,5 @@ public record struct CallStackFrame
     public required LuaFunction Function;
     public required SourcePosition? CallPosition;
     public required int VariableArgumentCount;
+    public  int? CallerInstructionIndex;
 }

+ 17 - 1
src/Lua/Runtime/Closure.cs

@@ -1,3 +1,4 @@
+using System.Runtime.CompilerServices;
 using Lua.Internal;
 
 namespace Lua.Runtime;
@@ -8,7 +9,7 @@ public sealed class Closure : LuaFunction
     FastListCore<UpValue> upValues;
 
     public Closure(LuaState state, Chunk proto, LuaTable? environment = null)
-        : base(proto.Name, (context, buffer, ct) => LuaVirtualMachine.ExecuteClosureAsync(context.State, context.Thread.GetCurrentFrame(), buffer, ct))
+        : base(proto.Name, (context, buffer, ct) => LuaVirtualMachine.ExecuteClosureAsync(context.State, buffer, ct))
     {
         this.proto = proto;
 
@@ -19,11 +20,26 @@ public sealed class Closure : LuaFunction
             var upValue = GetUpValueFromDescription(state, environment == null ? state.EnvUpValue : UpValue.Closed(environment), proto, description, 1);
             upValues.Add(upValue);
         }
+
+        IsClosure = true;
     }
 
     public Chunk Proto => proto;
     public ReadOnlySpan<UpValue> UpValues => upValues.AsSpan();
 
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    internal LuaValue GetUpValue(int index)
+    {
+        return upValues[index].GetValue();
+    }
+
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    internal void SetUpValue(int index, LuaValue value)
+    {
+        upValues[index].SetValue(value);
+    }
+
+
     static UpValue GetUpValueFromDescription(LuaState state, UpValue envUpValue, Chunk proto, UpValueInfo description, int depth)
     {
         if (description.IsInRegister)

File diff suppressed because it is too large
+ 1355 - 819
src/Lua/Runtime/LuaVirtualMachine.cs


Some files were not shown because too many files changed in this diff