|
@@ -215,10 +215,11 @@ public static partial class LuaVirtualMachine
|
|
|
State.PopCallStackFrameUntil(BaseCallStackCount);
|
|
State.PopCallStackFrameUntil(BaseCallStackCount);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- bool ExecutePostOperation(PostOperationType postOperation)
|
|
|
|
|
|
|
+ bool ExecutePostOperation(int varArgs, PostOperationType postOperation)
|
|
|
{
|
|
{
|
|
|
var stackCount = Stack.Count;
|
|
var stackCount = Stack.Count;
|
|
|
var resultsSpan = Stack.GetBuffer()[CurrentReturnFrameBase..];
|
|
var resultsSpan = Stack.GetBuffer()[CurrentReturnFrameBase..];
|
|
|
|
|
+ var lastTop = CurrentReturnFrameBase - varArgs;
|
|
|
switch (postOperation)
|
|
switch (postOperation)
|
|
|
{
|
|
{
|
|
|
case PostOperationType.Nop: break;
|
|
case PostOperationType.Nop: break;
|
|
@@ -226,7 +227,7 @@ public static partial class LuaVirtualMachine
|
|
|
var RA = Instruction.A + FrameBase;
|
|
var RA = Instruction.A + FrameBase;
|
|
|
Stack.Get(RA) = stackCount > CurrentReturnFrameBase ? Stack.Get(CurrentReturnFrameBase) : LuaValue.Nil;
|
|
Stack.Get(RA) = stackCount > CurrentReturnFrameBase ? Stack.Get(CurrentReturnFrameBase) : LuaValue.Nil;
|
|
|
Stack.NotifyTop(RA + 1);
|
|
Stack.NotifyTop(RA + 1);
|
|
|
- Stack.PopUntil(RA + 1);
|
|
|
|
|
|
|
+ Stack.PopUntil(Math.Max(RA + 1, lastTop));
|
|
|
break;
|
|
break;
|
|
|
case PostOperationType.TForCall:
|
|
case PostOperationType.TForCall:
|
|
|
TForCallPostOperation(this);
|
|
TForCallPostOperation(this);
|
|
@@ -242,10 +243,10 @@ public static partial class LuaVirtualMachine
|
|
|
|
|
|
|
|
break;
|
|
break;
|
|
|
case PostOperationType.Self:
|
|
case PostOperationType.Self:
|
|
|
- SelfPostOperation(this, resultsSpan);
|
|
|
|
|
|
|
+ SelfPostOperation(this, lastTop, resultsSpan);
|
|
|
break;
|
|
break;
|
|
|
case PostOperationType.Compare:
|
|
case PostOperationType.Compare:
|
|
|
- ComparePostOperation(this, resultsSpan);
|
|
|
|
|
|
|
+ ComparePostOperation(this, lastTop, resultsSpan);
|
|
|
break;
|
|
break;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -263,13 +264,15 @@ public static partial class LuaVirtualMachine
|
|
|
toCatchFlag = true;
|
|
toCatchFlag = true;
|
|
|
await Task;
|
|
await Task;
|
|
|
Task = default;
|
|
Task = default;
|
|
|
- CurrentReturnFrameBase = State.GetCurrentFrame().ReturnBase;
|
|
|
|
|
|
|
+ ref readonly var frame = ref State.GetCurrentFrame();
|
|
|
|
|
+ CurrentReturnFrameBase = frame.ReturnBase;
|
|
|
|
|
+ var variableArgumentCount = frame.VariableArgumentCount;
|
|
|
if (PostOperation is not (PostOperationType.TailCall or PostOperationType.DontPop))
|
|
if (PostOperation is not (PostOperationType.TailCall or PostOperationType.DontPop))
|
|
|
{
|
|
{
|
|
|
State.PopCallStackFrame();
|
|
State.PopCallStackFrame();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- if (!ExecutePostOperation(PostOperation))
|
|
|
|
|
|
|
+ if (!ExecutePostOperation(variableArgumentCount, PostOperation))
|
|
|
{
|
|
{
|
|
|
break;
|
|
break;
|
|
|
}
|
|
}
|
|
@@ -351,7 +354,7 @@ public static partial class LuaVirtualMachine
|
|
|
{
|
|
{
|
|
|
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 Unsafe.AsRef(in context.Prototype.Code[0]);
|
|
ref var instructionsHead = ref Unsafe.AsRef(in context.Prototype.Code[0]);
|
|
|
var frameBase = context.FrameBase;
|
|
var frameBase = context.FrameBase;
|
|
@@ -412,6 +415,7 @@ public static partial class LuaVirtualMachine
|
|
|
{
|
|
{
|
|
|
context.Pc++;
|
|
context.Pc++;
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
continue;
|
|
continue;
|
|
|
case OpCode.LoadNil:
|
|
case OpCode.LoadNil:
|
|
|
Markers.LoadNil();
|
|
Markers.LoadNil();
|
|
@@ -958,7 +962,7 @@ public static partial class LuaVirtualMachine
|
|
|
return mod;
|
|
return mod;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- static void SelfPostOperation(VirtualMachineExecutionContext context, Span<LuaValue> results)
|
|
|
|
|
|
|
+ static void SelfPostOperation(VirtualMachineExecutionContext context, int lastTop, Span<LuaValue> results)
|
|
|
{
|
|
{
|
|
|
var stack = context.Stack;
|
|
var stack = context.Stack;
|
|
|
var instruction = context.Instruction;
|
|
var instruction = context.Instruction;
|
|
@@ -968,6 +972,7 @@ public static partial class LuaVirtualMachine
|
|
|
var table = Unsafe.Add(ref stackHead, RB);
|
|
var table = Unsafe.Add(ref stackHead, RB);
|
|
|
Unsafe.Add(ref stackHead, RA + 1) = table;
|
|
Unsafe.Add(ref stackHead, RA + 1) = table;
|
|
|
Unsafe.Add(ref stackHead, RA) = results.Length == 0 ? LuaValue.Nil : results[0];
|
|
Unsafe.Add(ref stackHead, RA) = results.Length == 0 ? LuaValue.Nil : results[0];
|
|
|
|
|
+ stack.PopUntil(Math.Max(RA + 2, lastTop));
|
|
|
stack.NotifyTop(RA + 2);
|
|
stack.NotifyTop(RA + 2);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -1558,7 +1563,7 @@ public static partial class LuaVirtualMachine
|
|
|
stack.PopUntil(RA + 1);
|
|
stack.PopUntil(RA + 1);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- static void ComparePostOperation(VirtualMachineExecutionContext context, Span<LuaValue> results)
|
|
|
|
|
|
|
+ static void ComparePostOperation(VirtualMachineExecutionContext context, int lastTop, Span<LuaValue> results)
|
|
|
{
|
|
{
|
|
|
var compareResult = results.Length != 0 && results[0].ToBoolean();
|
|
var compareResult = results.Length != 0 && results[0].ToBoolean();
|
|
|
if (compareResult != (context.Instruction.A == 1))
|
|
if (compareResult != (context.Instruction.A == 1))
|
|
@@ -1567,6 +1572,7 @@ public static partial class LuaVirtualMachine
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
results.Clear();
|
|
results.Clear();
|
|
|
|
|
+ context.Stack.PopUntil(lastTop);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
@@ -1979,7 +1985,7 @@ public static partial class LuaVirtualMachine
|
|
|
stack.Push(vc);
|
|
stack.Push(vc);
|
|
|
var (argCount, variableArgumentCount) = PrepareForFunctionCall(context.State, func, newBase);
|
|
var (argCount, variableArgumentCount) = PrepareForFunctionCall(context.State, func, newBase);
|
|
|
newBase += variableArgumentCount;
|
|
newBase += variableArgumentCount;
|
|
|
- var newFrame = func.CreateNewFrame(context, newBase, context.Instruction.A + context.FrameBase, variableArgumentCount);
|
|
|
|
|
|
|
+ var newFrame = func.CreateNewFrame(context, newBase, newBase, variableArgumentCount);
|
|
|
|
|
|
|
|
context.State.PushCallStackFrame(newFrame);
|
|
context.State.PushCallStackFrame(newFrame);
|
|
|
if (context.State.CallOrReturnHookMask.Value != 0 && !context.State.IsInHook)
|
|
if (context.State.CallOrReturnHookMask.Value != 0 && !context.State.IsInHook)
|
|
@@ -2007,12 +2013,16 @@ public static partial class LuaVirtualMachine
|
|
|
return false;
|
|
return false;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- if (task.GetAwaiter().GetResult() == 0)
|
|
|
|
|
|
|
+ var destIndex = context.Instruction.A + context.FrameBase;
|
|
|
|
|
+ if (newFrame.ReturnBase != destIndex)
|
|
|
{
|
|
{
|
|
|
- stack.Get(newFrame.ReturnBase) = default;
|
|
|
|
|
|
|
+ stack.Get(destIndex)
|
|
|
|
|
+ = task.GetAwaiter().GetResult() != 0
|
|
|
|
|
+ ? stack.FastGet(newFrame.ReturnBase)
|
|
|
|
|
+ : default;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- stack.PopUntil(newFrame.ReturnBase + 1);
|
|
|
|
|
|
|
+ stack.PopUntil(Math.Max(destIndex + 1, newFrame.Base - newFrame.VariableArgumentCount));
|
|
|
context.State.PopCallStackFrame();
|
|
context.State.PopCallStackFrame();
|
|
|
return true;
|
|
return true;
|
|
|
}
|
|
}
|
|
@@ -2107,7 +2117,7 @@ public static partial class LuaVirtualMachine
|
|
|
var (argCount, variableArgumentCount) = PrepareForFunctionCall(context.State, func, newBase);
|
|
var (argCount, variableArgumentCount) = PrepareForFunctionCall(context.State, func, newBase);
|
|
|
newBase += variableArgumentCount;
|
|
newBase += variableArgumentCount;
|
|
|
|
|
|
|
|
- var newFrame = func.CreateNewFrame(context, newBase, context.Instruction.A + context.FrameBase, variableArgumentCount);
|
|
|
|
|
|
|
+ var newFrame = func.CreateNewFrame(context, newBase, newBase, variableArgumentCount);
|
|
|
|
|
|
|
|
context.State.PushCallStackFrame(newFrame);
|
|
context.State.PushCallStackFrame(newFrame);
|
|
|
if (context.State.CallOrReturnHookMask.Value != 0 && !context.State.IsInHook)
|
|
if (context.State.CallOrReturnHookMask.Value != 0 && !context.State.IsInHook)
|
|
@@ -2135,12 +2145,16 @@ public static partial class LuaVirtualMachine
|
|
|
return false;
|
|
return false;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- if (task.GetAwaiter().GetResult() == 0)
|
|
|
|
|
|
|
+ var destIndex = context.Instruction.A + context.FrameBase;
|
|
|
|
|
+ if (newFrame.ReturnBase != destIndex)
|
|
|
{
|
|
{
|
|
|
- stack.Get(newFrame.ReturnBase) = default;
|
|
|
|
|
|
|
+ stack.Get(destIndex)
|
|
|
|
|
+ = task.GetAwaiter().GetResult() != 0
|
|
|
|
|
+ ? stack.FastGet(newFrame.ReturnBase)
|
|
|
|
|
+ : default;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- stack.PopUntil(newFrame.ReturnBase + 1);
|
|
|
|
|
|
|
+ stack.PopUntil(Math.Max(destIndex + 1, newFrame.Base - newFrame.VariableArgumentCount));
|
|
|
context.State.PopCallStackFrame();
|
|
context.State.PopCallStackFrame();
|
|
|
return true;
|
|
return true;
|
|
|
}
|
|
}
|
|
@@ -2286,7 +2300,7 @@ public static partial class LuaVirtualMachine
|
|
|
context.Pc++;
|
|
context.Pc++;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- stack.PopUntil(newFrame.ReturnBase + 1);
|
|
|
|
|
|
|
+ stack.PopUntil(newFrame.Base - newFrame.VariableArgumentCount + 1);
|
|
|
context.State.PopCallStackFrame();
|
|
context.State.PopCallStackFrame();
|
|
|
|
|
|
|
|
return true;
|
|
return true;
|