LuaThread.cs 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. using System.Runtime.CompilerServices;
  2. using Lua.Internal;
  3. using Lua.Runtime;
  4. namespace Lua;
  5. public abstract class LuaThread
  6. {
  7. internal LuaThread() { }
  8. public virtual LuaThreadStatus GetStatus()
  9. {
  10. return LuaThreadStatus.Running;
  11. }
  12. public virtual void UnsafeSetStatus(LuaThreadStatus status) { }
  13. public virtual ValueTask<int> ResumeAsync(LuaFunctionExecutionContext context, CancellationToken cancellationToken = default)
  14. {
  15. return new(context.Return(false, "cannot resume non-suspended coroutine"));
  16. }
  17. public virtual ValueTask<int> YieldAsync(LuaFunctionExecutionContext context, CancellationToken cancellationToken = default)
  18. {
  19. throw new LuaRuntimeException(context.Thread.GetTraceback(), "attempt to yield from outside a coroutine");
  20. }
  21. internal class ThreadCoreData: IPoolNode<ThreadCoreData>
  22. {
  23. //internal LuaCoroutineData? coroutineData;
  24. internal LuaStack Stack = new();
  25. internal FastStackCore<CallStackFrame> CallStack;
  26. public void Clear()
  27. {
  28. Stack.Clear();
  29. CallStack.Clear();
  30. }
  31. static LinkedPool<ThreadCoreData> pool;
  32. ThreadCoreData? nextNode;
  33. public ref ThreadCoreData? NextNode => ref nextNode;
  34. public static ThreadCoreData Create()
  35. {
  36. if (!pool.TryPop(out ThreadCoreData result))
  37. {
  38. result = new ThreadCoreData();
  39. }
  40. return result;
  41. }
  42. public void Release()
  43. {
  44. Clear();
  45. pool.TryPush(this);
  46. }
  47. }
  48. public LuaState State { get;protected set; }
  49. internal ThreadCoreData? CoreData = new();
  50. internal BitFlags2 LineAndCountHookMask;
  51. internal BitFlags2 CallOrReturnHookMask;
  52. internal bool IsInHook;
  53. internal int HookCount;
  54. internal int BaseHookCount;
  55. internal int LastPc;
  56. internal LuaFunction? Hook { get; set; }
  57. internal LuaStack Stack => CoreData!.Stack;
  58. internal ref FastStackCore<CallStackFrame> CallStack => ref CoreData!.CallStack;
  59. internal bool IsLineHookEnabled
  60. {
  61. get => LineAndCountHookMask.Flag0;
  62. set => LineAndCountHookMask.Flag0 = value;
  63. }
  64. internal bool IsCountHookEnabled
  65. {
  66. get => LineAndCountHookMask.Flag1;
  67. set => LineAndCountHookMask.Flag1 = value;
  68. }
  69. internal bool IsCallHookEnabled
  70. {
  71. get => CallOrReturnHookMask.Flag0;
  72. set => CallOrReturnHookMask.Flag0 = value;
  73. }
  74. internal bool IsReturnHookEnabled
  75. {
  76. get => CallOrReturnHookMask.Flag1;
  77. set => CallOrReturnHookMask.Flag1 = value;
  78. }
  79. public void Push(LuaValue value)
  80. {
  81. CoreData.Stack.Push(value);
  82. }
  83. public void Push(params ReadOnlySpan<LuaValue> span)
  84. {
  85. CoreData.Stack.PushRange(span);
  86. }
  87. public void Pop(int count)
  88. {
  89. CoreData.Stack.Pop(count);
  90. }
  91. public LuaValue Pop()
  92. {
  93. return CoreData.Stack.Pop();
  94. }
  95. public ref readonly CallStackFrame GetCurrentFrame()
  96. {
  97. return ref CoreData.CallStack.PeekRef();
  98. }
  99. public ReadOnlySpan<LuaValue> GetStackValues()
  100. {
  101. return CoreData.Stack.AsSpan();
  102. }
  103. public ReadOnlySpan<CallStackFrame> GetCallStackFrames()
  104. {
  105. return CoreData.CallStack.AsSpan();
  106. }
  107. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  108. internal void PushCallStackFrame(in CallStackFrame frame)
  109. {
  110. CoreData.CallStack.Push(frame);
  111. }
  112. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  113. internal void PopCallStackFrameWithStackPop()
  114. {
  115. if (CoreData.CallStack.TryPop(out var frame))
  116. {
  117. CoreData.Stack.PopUntil(frame.Base);
  118. }
  119. else
  120. {
  121. ThrowForEmptyStack();
  122. }
  123. }
  124. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  125. internal void PopCallStackFrameWithStackPop(int frameBase)
  126. {
  127. if (CoreData.CallStack.TryPop())
  128. {
  129. CoreData.Stack.PopUntil(frameBase);
  130. }
  131. else
  132. {
  133. ThrowForEmptyStack();
  134. }
  135. }
  136. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  137. internal void PopCallStackFrame()
  138. {
  139. if (!CoreData.CallStack.TryPop())
  140. {
  141. ThrowForEmptyStack();
  142. }
  143. }
  144. internal void DumpStackValues()
  145. {
  146. var span = GetStackValues();
  147. for (int i = 0; i < span.Length; i++)
  148. {
  149. Console.WriteLine($"LuaStack [{i}]\t{span[i]}");
  150. }
  151. }
  152. public Traceback GetTraceback()
  153. {
  154. var frames = GetCallStackFrames();
  155. return new(State) { RootFunc = frames[0].Function, StackFrames = GetCallStackFrames()[1..].ToArray() };
  156. }
  157. static void ThrowForEmptyStack() => throw new InvalidOperationException("Empty stack");
  158. }