|
@@ -39,6 +39,8 @@ public static partial class LuaVirtualMachine
|
|
|
|
|
|
|
|
readonly int BaseCallStackCount = thread.CallStack.Count;
|
|
readonly int BaseCallStackCount = thread.CallStack.Count;
|
|
|
|
|
|
|
|
|
|
+ public PostOperationType PostOperation;
|
|
|
|
|
+
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
|
public bool Pop(Instruction instruction, int frameBase)
|
|
public bool Pop(Instruction instruction, int frameBase)
|
|
|
{
|
|
{
|
|
@@ -186,49 +188,60 @@ public static partial class LuaVirtualMachine
|
|
|
ResultsBuffer.AsSpan(0, count).Clear();
|
|
ResultsBuffer.AsSpan(0, count).Clear();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ public int? ExecutePostOperation(PostOperationType postOperation)
|
|
|
|
|
+ {
|
|
|
|
|
+ switch (postOperation)
|
|
|
|
|
+ {
|
|
|
|
|
+ case PostOperationType.Nop: break;
|
|
|
|
|
+ case PostOperationType.SetResult:
|
|
|
|
|
+ var RA = Instruction.A + FrameBase;
|
|
|
|
|
+ Stack.Get(RA) = TaskResult == 0 ? LuaValue.Nil : ResultsBuffer[0];
|
|
|
|
|
+ Stack.NotifyTop(RA + 1);
|
|
|
|
|
+ ClearResultsBuffer();
|
|
|
|
|
+ break;
|
|
|
|
|
+ case PostOperationType.TForCall:
|
|
|
|
|
+ TForCallPostOperation(ref this);
|
|
|
|
|
+ break;
|
|
|
|
|
+ case PostOperationType.Call:
|
|
|
|
|
+ CallPostOperation(ref this);
|
|
|
|
|
+ break;
|
|
|
|
|
+ case PostOperationType.TailCall:
|
|
|
|
|
+ var resultsSpan = ResultsBuffer.AsSpan(0, TaskResult);
|
|
|
|
|
+ if (!PopFromBuffer(resultsSpan))
|
|
|
|
|
+ {
|
|
|
|
|
+ ResultCount = TaskResult;
|
|
|
|
|
+ resultsSpan.CopyTo(Buffer.Span);
|
|
|
|
|
+ resultsSpan.Clear();
|
|
|
|
|
+ LuaValueArrayPool.Return1024(ResultsBuffer);
|
|
|
|
|
+ return TaskResult;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ resultsSpan.Clear();
|
|
|
|
|
+ break;
|
|
|
|
|
+ case PostOperationType.Self:
|
|
|
|
|
+ SelfPostOperation(ref this);
|
|
|
|
|
+ break;
|
|
|
|
|
+ case PostOperationType.Compare:
|
|
|
|
|
+ ComparePostOperation(ref this);
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return null;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
public async ValueTask<int> ExecuteClosureAsyncImpl()
|
|
public async ValueTask<int> ExecuteClosureAsyncImpl()
|
|
|
{
|
|
{
|
|
|
- while (MoveNext(ref this, out var postOperation))
|
|
|
|
|
|
|
+ while (MoveNext(ref this))
|
|
|
{
|
|
{
|
|
|
TaskResult = await Task;
|
|
TaskResult = await Task;
|
|
|
Task = default;
|
|
Task = default;
|
|
|
-
|
|
|
|
|
- Thread.PopCallStackFrame();
|
|
|
|
|
- switch (postOperation)
|
|
|
|
|
|
|
+ if (PostOperation != PostOperationType.TailCall)
|
|
|
{
|
|
{
|
|
|
- case PostOperationType.Nop: break;
|
|
|
|
|
- case PostOperationType.SetResult:
|
|
|
|
|
- var RA = Instruction.A + FrameBase;
|
|
|
|
|
- Stack.Get(RA) = TaskResult == 0 ? LuaValue.Nil : ResultsBuffer[0];
|
|
|
|
|
- Stack.NotifyTop(RA + 1);
|
|
|
|
|
- ClearResultsBuffer();
|
|
|
|
|
- break;
|
|
|
|
|
- case PostOperationType.TForCall:
|
|
|
|
|
- TForCallPostOperation(ref this);
|
|
|
|
|
- break;
|
|
|
|
|
- case PostOperationType.Call:
|
|
|
|
|
- CallPostOperation(ref this);
|
|
|
|
|
- break;
|
|
|
|
|
- case PostOperationType.TailCall:
|
|
|
|
|
- var resultsSpan = ResultsBuffer.AsSpan(0, TaskResult);
|
|
|
|
|
- if (!PopFromBuffer(resultsSpan))
|
|
|
|
|
- {
|
|
|
|
|
- ResultCount = TaskResult;
|
|
|
|
|
- resultsSpan.CopyTo(Buffer.Span);
|
|
|
|
|
- resultsSpan.Clear();
|
|
|
|
|
- LuaValueArrayPool.Return1024(ResultsBuffer);
|
|
|
|
|
- return TaskResult;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- resultsSpan.Clear();
|
|
|
|
|
- break;
|
|
|
|
|
- case PostOperationType.Self:
|
|
|
|
|
- SelfPostOperation(ref this);
|
|
|
|
|
- break;
|
|
|
|
|
- case PostOperationType.Compare:
|
|
|
|
|
- ComparePostOperation(ref this);
|
|
|
|
|
- break;
|
|
|
|
|
|
|
+ Thread.PopCallStackFrame();
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+ var r = ExecutePostOperation(PostOperation);
|
|
|
|
|
+ if (r.HasValue) return r.Value;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
return ResultCount;
|
|
return ResultCount;
|
|
@@ -259,20 +272,17 @@ public static partial class LuaVirtualMachine
|
|
|
return context.ExecuteClosureAsyncImpl();
|
|
return context.ExecuteClosureAsyncImpl();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- static bool MoveNext(ref VirtualMachineExecutionContext context, out PostOperationType postOperation)
|
|
|
|
|
|
|
+ static bool MoveNext(ref VirtualMachineExecutionContext context)
|
|
|
{
|
|
{
|
|
|
- postOperation = PostOperationType.None;
|
|
|
|
|
-
|
|
|
|
|
try
|
|
try
|
|
|
{
|
|
{
|
|
|
- // This is a label to restart the execution when new function is called or restarted
|
|
|
|
|
|
|
+ // This is a label to restart the execution when new function is called or restarted
|
|
|
Restart:
|
|
Restart:
|
|
|
ref var instructionsHead = ref context.Chunk.Instructions[0];
|
|
ref var instructionsHead = ref context.Chunk.Instructions[0];
|
|
|
var frameBase = context.FrameBase;
|
|
var frameBase = context.FrameBase;
|
|
|
var stack = context.Stack;
|
|
var stack = context.Stack;
|
|
|
stack.EnsureCapacity(frameBase + context.Chunk.MaxStackPosition);
|
|
stack.EnsureCapacity(frameBase + context.Chunk.MaxStackPosition);
|
|
|
ref var constHead = ref MemoryMarshalEx.UnsafeElementAt(context.Chunk.Constants, 0);
|
|
ref var constHead = ref MemoryMarshalEx.UnsafeElementAt(context.Chunk.Constants, 0);
|
|
|
-
|
|
|
|
|
while (true)
|
|
while (true)
|
|
|
{
|
|
{
|
|
|
var instructionRef = Unsafe.Add(ref instructionsHead, ++context.Pc);
|
|
var instructionRef = Unsafe.Add(ref instructionsHead, ++context.Pc);
|
|
@@ -320,7 +330,6 @@ public static partial class LuaVirtualMachine
|
|
|
continue;
|
|
continue;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- postOperation = PostOperationType.SetResult;
|
|
|
|
|
return true;
|
|
return true;
|
|
|
case OpCode.SetTabUp:
|
|
case OpCode.SetTabUp:
|
|
|
instruction = instructionRef;
|
|
instruction = instructionRef;
|
|
@@ -354,7 +363,6 @@ public static partial class LuaVirtualMachine
|
|
|
continue;
|
|
continue;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- postOperation = PostOperationType.Nop;
|
|
|
|
|
return true;
|
|
return true;
|
|
|
|
|
|
|
|
case OpCode.SetUpVal:
|
|
case OpCode.SetUpVal:
|
|
@@ -394,7 +402,6 @@ public static partial class LuaVirtualMachine
|
|
|
continue;
|
|
continue;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- postOperation = PostOperationType.Nop;
|
|
|
|
|
return true;
|
|
return true;
|
|
|
case OpCode.NewTable:
|
|
case OpCode.NewTable:
|
|
|
instruction = instructionRef;
|
|
instruction = instructionRef;
|
|
@@ -417,7 +424,6 @@ public static partial class LuaVirtualMachine
|
|
|
continue;
|
|
continue;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- postOperation = PostOperationType.Self;
|
|
|
|
|
return true;
|
|
return true;
|
|
|
case OpCode.Add:
|
|
case OpCode.Add:
|
|
|
instruction = instructionRef;
|
|
instruction = instructionRef;
|
|
@@ -445,7 +451,6 @@ public static partial class LuaVirtualMachine
|
|
|
continue;
|
|
continue;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- postOperation = PostOperationType.SetResult;
|
|
|
|
|
return true;
|
|
return true;
|
|
|
case OpCode.Sub:
|
|
case OpCode.Sub:
|
|
|
instruction = instructionRef;
|
|
instruction = instructionRef;
|
|
@@ -476,7 +481,6 @@ public static partial class LuaVirtualMachine
|
|
|
continue;
|
|
continue;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- postOperation = PostOperationType.SetResult;
|
|
|
|
|
return true;
|
|
return true;
|
|
|
|
|
|
|
|
case OpCode.Mul:
|
|
case OpCode.Mul:
|
|
@@ -508,7 +512,6 @@ public static partial class LuaVirtualMachine
|
|
|
continue;
|
|
continue;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- postOperation = PostOperationType.SetResult;
|
|
|
|
|
return true;
|
|
return true;
|
|
|
|
|
|
|
|
case OpCode.Div:
|
|
case OpCode.Div:
|
|
@@ -540,7 +543,6 @@ public static partial class LuaVirtualMachine
|
|
|
continue;
|
|
continue;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- postOperation = PostOperationType.SetResult;
|
|
|
|
|
return true;
|
|
return true;
|
|
|
case OpCode.Mod:
|
|
case OpCode.Mod:
|
|
|
instruction = instructionRef;
|
|
instruction = instructionRef;
|
|
@@ -566,7 +568,6 @@ public static partial class LuaVirtualMachine
|
|
|
continue;
|
|
continue;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- postOperation = PostOperationType.SetResult;
|
|
|
|
|
return true;
|
|
return true;
|
|
|
case OpCode.Pow:
|
|
case OpCode.Pow:
|
|
|
instruction = instructionRef;
|
|
instruction = instructionRef;
|
|
@@ -588,7 +589,6 @@ public static partial class LuaVirtualMachine
|
|
|
continue;
|
|
continue;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- postOperation = PostOperationType.SetResult;
|
|
|
|
|
return true;
|
|
return true;
|
|
|
case OpCode.Unm:
|
|
case OpCode.Unm:
|
|
|
instruction = instructionRef;
|
|
instruction = instructionRef;
|
|
@@ -610,7 +610,6 @@ public static partial class LuaVirtualMachine
|
|
|
continue;
|
|
continue;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- postOperation = PostOperationType.SetResult;
|
|
|
|
|
return true;
|
|
return true;
|
|
|
case OpCode.Not:
|
|
case OpCode.Not:
|
|
|
instruction = instructionRef;
|
|
instruction = instructionRef;
|
|
@@ -642,7 +641,6 @@ public static partial class LuaVirtualMachine
|
|
|
continue;
|
|
continue;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- postOperation = PostOperationType.SetResult;
|
|
|
|
|
return true;
|
|
return true;
|
|
|
case OpCode.Concat:
|
|
case OpCode.Concat:
|
|
|
if (Concat(ref context, out doRestart))
|
|
if (Concat(ref context, out doRestart))
|
|
@@ -651,7 +649,6 @@ public static partial class LuaVirtualMachine
|
|
|
continue;
|
|
continue;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- postOperation = PostOperationType.SetResult;
|
|
|
|
|
return true;
|
|
return true;
|
|
|
case OpCode.Jmp:
|
|
case OpCode.Jmp:
|
|
|
instruction = instructionRef;
|
|
instruction = instructionRef;
|
|
@@ -685,7 +682,6 @@ public static partial class LuaVirtualMachine
|
|
|
continue;
|
|
continue;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- postOperation = PostOperationType.Compare;
|
|
|
|
|
return true;
|
|
return true;
|
|
|
case OpCode.Lt:
|
|
case OpCode.Lt:
|
|
|
instruction = instructionRef;
|
|
instruction = instructionRef;
|
|
@@ -723,7 +719,6 @@ public static partial class LuaVirtualMachine
|
|
|
continue;
|
|
continue;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- postOperation = PostOperationType.Compare;
|
|
|
|
|
return true;
|
|
return true;
|
|
|
case OpCode.Le:
|
|
case OpCode.Le:
|
|
|
instruction = instructionRef;
|
|
instruction = instructionRef;
|
|
@@ -760,7 +755,6 @@ public static partial class LuaVirtualMachine
|
|
|
continue;
|
|
continue;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- postOperation = PostOperationType.Compare;
|
|
|
|
|
return true;
|
|
return true;
|
|
|
case OpCode.Test:
|
|
case OpCode.Test:
|
|
|
instruction = instructionRef;
|
|
instruction = instructionRef;
|
|
@@ -791,7 +785,6 @@ public static partial class LuaVirtualMachine
|
|
|
continue;
|
|
continue;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- postOperation = PostOperationType.Call;
|
|
|
|
|
return true;
|
|
return true;
|
|
|
case OpCode.TailCall:
|
|
case OpCode.TailCall:
|
|
|
if (TailCall(ref context, out doRestart))
|
|
if (TailCall(ref context, out doRestart))
|
|
@@ -801,7 +794,6 @@ public static partial class LuaVirtualMachine
|
|
|
continue;
|
|
continue;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- postOperation = PostOperationType.TailCall;
|
|
|
|
|
return true;
|
|
return true;
|
|
|
case OpCode.Return:
|
|
case OpCode.Return:
|
|
|
instruction = instructionRef;
|
|
instruction = instructionRef;
|
|
@@ -872,7 +864,7 @@ public static partial class LuaVirtualMachine
|
|
|
continue;
|
|
continue;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- postOperation = PostOperationType.TForCall;
|
|
|
|
|
|
|
+
|
|
|
return true;
|
|
return true;
|
|
|
case OpCode.TForLoop:
|
|
case OpCode.TForLoop:
|
|
|
instruction = instructionRef;
|
|
instruction = instructionRef;
|
|
@@ -926,7 +918,7 @@ public static partial class LuaVirtualMachine
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
End:
|
|
End:
|
|
|
- postOperation = PostOperationType.None;
|
|
|
|
|
|
|
+ context.PostOperation = PostOperationType.None;
|
|
|
LuaValueArrayPool.Return1024(context.ResultsBuffer);
|
|
LuaValueArrayPool.Return1024(context.ResultsBuffer);
|
|
|
return false;
|
|
return false;
|
|
|
}
|
|
}
|
|
@@ -1032,6 +1024,7 @@ public static partial class LuaVirtualMachine
|
|
|
var newFrame = func.CreateNewFrame(ref context, newBase, variableArgumentCount);
|
|
var newFrame = func.CreateNewFrame(ref context, newBase, variableArgumentCount);
|
|
|
|
|
|
|
|
thread.PushCallStackFrame(newFrame);
|
|
thread.PushCallStackFrame(newFrame);
|
|
|
|
|
+
|
|
|
if (func is Closure)
|
|
if (func is Closure)
|
|
|
{
|
|
{
|
|
|
context.Push(newFrame);
|
|
context.Push(newFrame);
|
|
@@ -1048,6 +1041,7 @@ public static partial class LuaVirtualMachine
|
|
|
|
|
|
|
|
if (!task.IsCompleted)
|
|
if (!task.IsCompleted)
|
|
|
{
|
|
{
|
|
|
|
|
+ context.PostOperation = PostOperationType.Call;
|
|
|
context.Task = task;
|
|
context.Task = task;
|
|
|
return false;
|
|
return false;
|
|
|
}
|
|
}
|
|
@@ -1148,7 +1142,14 @@ public static partial class LuaVirtualMachine
|
|
|
|
|
|
|
|
var (newBase, argumentCount, variableArgumentCount) = PrepareForFunctionTailCall(thread, func, instruction, RA);
|
|
var (newBase, argumentCount, variableArgumentCount) = PrepareForFunctionTailCall(thread, func, instruction, RA);
|
|
|
|
|
|
|
|
|
|
+
|
|
|
|
|
+ var lastPc = thread.CallStack.AsSpan()[^1].CallerInstructionIndex;
|
|
|
|
|
+ context.Thread.PopCallStackFrameUnsafe();
|
|
|
|
|
+
|
|
|
var newFrame = func.CreateNewFrame(ref context, newBase, variableArgumentCount);
|
|
var newFrame = func.CreateNewFrame(ref context, newBase, variableArgumentCount);
|
|
|
|
|
+
|
|
|
|
|
+ newFrame.Flags |= CallStackFrameFlags.TailCall;
|
|
|
|
|
+ newFrame.CallerInstructionIndex = lastPc;
|
|
|
thread.PushCallStackFrame(newFrame);
|
|
thread.PushCallStackFrame(newFrame);
|
|
|
|
|
|
|
|
context.Push(newFrame);
|
|
context.Push(newFrame);
|
|
@@ -1163,12 +1164,11 @@ public static partial class LuaVirtualMachine
|
|
|
|
|
|
|
|
if (!task.IsCompleted)
|
|
if (!task.IsCompleted)
|
|
|
{
|
|
{
|
|
|
|
|
+ context.PostOperation = PostOperationType.TailCall;
|
|
|
context.Task = task;
|
|
context.Task = task;
|
|
|
return false;
|
|
return false;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- context.Thread.PopCallStackFrame();
|
|
|
|
|
-
|
|
|
|
|
doRestart = true;
|
|
doRestart = true;
|
|
|
var awaiter = task.GetAwaiter();
|
|
var awaiter = task.GetAwaiter();
|
|
|
var resultCount = awaiter.GetResult();
|
|
var resultCount = awaiter.GetResult();
|
|
@@ -1214,6 +1214,7 @@ public static partial class LuaVirtualMachine
|
|
|
|
|
|
|
|
if (!task.IsCompleted)
|
|
if (!task.IsCompleted)
|
|
|
{
|
|
{
|
|
|
|
|
+ context.PostOperation = PostOperationType.TForCall;
|
|
|
context.Task = task;
|
|
context.Task = task;
|
|
|
|
|
|
|
|
return false;
|
|
return false;
|
|
@@ -1264,6 +1265,7 @@ public static partial class LuaVirtualMachine
|
|
|
table.EnsureArrayCapacity((instruction.C - 1) * 50 + count);
|
|
table.EnsureArrayCapacity((instruction.C - 1) * 50 + count);
|
|
|
stack.GetBuffer().Slice(RA + 1, count)
|
|
stack.GetBuffer().Slice(RA + 1, count)
|
|
|
.CopyTo(table.GetArraySpan()[((instruction.C - 1) * 50)..]);
|
|
.CopyTo(table.GetArraySpan()[((instruction.C - 1) * 50)..]);
|
|
|
|
|
+ stack.PopUntil(RA + 1);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
static void ComparePostOperation(ref VirtualMachineExecutionContext context)
|
|
static void ComparePostOperation(ref VirtualMachineExecutionContext context)
|
|
@@ -1358,6 +1360,7 @@ public static partial class LuaVirtualMachine
|
|
|
|
|
|
|
|
if (!task.IsCompleted)
|
|
if (!task.IsCompleted)
|
|
|
{
|
|
{
|
|
|
|
|
+ context.PostOperation = context.Instruction.OpCode == OpCode.GetTable ? PostOperationType.SetResult : PostOperationType.Self;
|
|
|
context.Task = task;
|
|
context.Task = task;
|
|
|
result = default;
|
|
result = default;
|
|
|
return false;
|
|
return false;
|
|
@@ -1417,6 +1420,7 @@ public static partial class LuaVirtualMachine
|
|
|
Function:
|
|
Function:
|
|
|
if (table.TryReadFunction(out var function))
|
|
if (table.TryReadFunction(out var function))
|
|
|
{
|
|
{
|
|
|
|
|
+ context.PostOperation = PostOperationType.Nop;
|
|
|
return CallSetTableFunc(targetTable, function, key, value, ref context, out doRestart);
|
|
return CallSetTableFunc(targetTable, function, key, value, ref context, out doRestart);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
@@ -1495,6 +1499,7 @@ public static partial class LuaVirtualMachine
|
|
|
|
|
|
|
|
if (!task.IsCompleted)
|
|
if (!task.IsCompleted)
|
|
|
{
|
|
{
|
|
|
|
|
+ context.PostOperation = PostOperationType.SetResult;
|
|
|
context.Task = task;
|
|
context.Task = task;
|
|
|
return false;
|
|
return false;
|
|
|
}
|
|
}
|
|
@@ -1597,6 +1602,7 @@ public static partial class LuaVirtualMachine
|
|
|
|
|
|
|
|
if (!task.IsCompleted)
|
|
if (!task.IsCompleted)
|
|
|
{
|
|
{
|
|
|
|
|
+ context.PostOperation = PostOperationType.Compare;
|
|
|
context.Task = task;
|
|
context.Task = task;
|
|
|
return false;
|
|
return false;
|
|
|
}
|
|
}
|