Processor.cs 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using System.Linq;
  5. using System.Text;
  6. using System.Threading;
  7. using MoonSharp.Interpreter.DataStructs;
  8. using MoonSharp.Interpreter.Debugging;
  9. namespace MoonSharp.Interpreter.Execution.VM
  10. {
  11. sealed partial class Processor
  12. {
  13. ByteCode m_RootChunk;
  14. FastStack<DynValue> m_ValueStack = new FastStack<DynValue>(131072);
  15. FastStack<CallStackItem> m_ExecutionStack = new FastStack<CallStackItem>(131072);
  16. List<Processor> m_CoroutinesStack;
  17. Table m_GlobalTable;
  18. Script m_Script;
  19. Processor m_Parent = null;
  20. CoroutineState m_State;
  21. bool m_CanYield = true;
  22. int m_SavedInstructionPtr = -1;
  23. DebugContext m_Debug;
  24. public Processor(Script script, Table globalContext, ByteCode byteCode)
  25. {
  26. m_CoroutinesStack = new List<Processor>();
  27. m_Debug = new DebugContext();
  28. m_RootChunk = byteCode;
  29. m_GlobalTable = globalContext;
  30. m_Script = script;
  31. m_State = CoroutineState.Main;
  32. DynValue.NewCoroutine(new Coroutine(this)); // creates an associated coroutine for the main processor
  33. }
  34. private Processor(Processor parentProcessor)
  35. {
  36. m_Debug = parentProcessor.m_Debug;
  37. m_RootChunk = parentProcessor.m_RootChunk;
  38. m_GlobalTable = parentProcessor.m_GlobalTable;
  39. m_Script = parentProcessor.m_Script;
  40. m_Parent = parentProcessor;
  41. m_State = CoroutineState.NotStarted;
  42. }
  43. public DynValue Call(DynValue function, DynValue[] args)
  44. {
  45. List<Processor> coroutinesStack = m_Parent != null ? m_Parent.m_CoroutinesStack : this.m_CoroutinesStack;
  46. if (coroutinesStack.Count > 0 && coroutinesStack[coroutinesStack.Count - 1] != this)
  47. return coroutinesStack[coroutinesStack.Count - 1].Call(function, args);
  48. EnterProcessor();
  49. try
  50. {
  51. var stopwatch = this.m_Script.PerformanceStats.StartStopwatch(Diagnostics.PerformanceCounter.Execution);
  52. m_CanYield = false;
  53. try
  54. {
  55. int entrypoint = PushClrToScriptStackFrame(CallStackItemFlags.CallEntryPoint, function, args);
  56. return Processing_Loop(entrypoint);
  57. }
  58. finally
  59. {
  60. m_CanYield = true;
  61. if (stopwatch != null)
  62. stopwatch.Dispose();
  63. }
  64. }
  65. finally
  66. {
  67. LeaveProcessor();
  68. }
  69. }
  70. // pushes all what's required to perform a clr-to-script function call. function can be null if it's already
  71. // at vstack top.
  72. private int PushClrToScriptStackFrame(CallStackItemFlags flags, DynValue function, DynValue[] args)
  73. {
  74. if (function == null)
  75. function = m_ValueStack.Peek();
  76. else
  77. m_ValueStack.Push(function); // func val
  78. args = Internal_AdjustTuple(args);
  79. for (int i = 0; i < args.Length; i++)
  80. m_ValueStack.Push(args[i]);
  81. m_ValueStack.Push(DynValue.NewNumber(args.Length)); // func args count
  82. m_ExecutionStack.Push(new CallStackItem()
  83. {
  84. BasePointer = m_ValueStack.Count,
  85. Debug_EntryPoint = function.Function.EntryPointByteCodeLocation,
  86. ReturnAddress = -1,
  87. ClosureScope = function.Function.ClosureContext,
  88. CallingSourceRef = SourceRef.GetClrLocation(),
  89. Flags = flags
  90. });
  91. return function.Function.EntryPointByteCodeLocation;
  92. }
  93. int m_OwningThreadID = -1;
  94. int m_ExecutionNesting = 0;
  95. private void LeaveProcessor()
  96. {
  97. m_ExecutionNesting -= 1;
  98. m_OwningThreadID = -1;
  99. if (m_Parent != null)
  100. {
  101. m_Parent.m_CoroutinesStack.RemoveAt(m_Parent.m_CoroutinesStack.Count - 1);
  102. }
  103. if (m_ExecutionNesting == 0 && m_Debug != null && m_Debug.DebuggerAttached != null)
  104. {
  105. m_Debug.DebuggerAttached.SignalExecutionEnded();
  106. }
  107. }
  108. private void EnterProcessor()
  109. {
  110. int threadID = Thread.CurrentThread.ManagedThreadId;
  111. if (m_OwningThreadID >= 0 && m_OwningThreadID != threadID && m_Script.Options.CheckThreadAccess)
  112. {
  113. string msg = string.Format("Cannot enter the same MoonSharp processor from two different threads : {0} and {1}", m_OwningThreadID, threadID);
  114. throw new InvalidOperationException(msg);
  115. }
  116. m_OwningThreadID = threadID;
  117. m_ExecutionNesting += 1;
  118. if (m_Parent != null)
  119. {
  120. m_Parent.m_CoroutinesStack.Add(this);
  121. }
  122. }
  123. internal SourceRef GetCoroutineSuspendedLocation()
  124. {
  125. return GetCurrentSourceRef(m_SavedInstructionPtr);
  126. }
  127. }
  128. }