RuntimeStack.cs 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using ILRuntime.CLR.Method;
  6. using ILRuntime.Runtime.Intepreter;
  7. namespace ILRuntime.Runtime.Stack
  8. {
  9. unsafe class RuntimeStack : IDisposable
  10. {
  11. ILIntepreter intepreter;
  12. StackObject* pointer;
  13. StackObject* endOfMemory;
  14. IntPtr nativePointer;
  15. List<object> managedStack = new List<object>(32);
  16. Stack<StackFrame> frames = new Stack<StackFrame>();
  17. const int MAXIMAL_STACK_OBJECTS = 1024 * 16;
  18. public Stack<StackFrame> Frames { get { return frames; } }
  19. public RuntimeStack(ILIntepreter intepreter)
  20. {
  21. this.intepreter = intepreter;
  22. nativePointer = System.Runtime.InteropServices.Marshal.AllocHGlobal(sizeof(StackObject) * MAXIMAL_STACK_OBJECTS);
  23. pointer = (StackObject*)nativePointer.ToPointer();
  24. endOfMemory = Add(pointer, MAXIMAL_STACK_OBJECTS);
  25. }
  26. ~RuntimeStack()
  27. {
  28. Dispose();
  29. }
  30. public StackObject* StackBase
  31. {
  32. get
  33. {
  34. return pointer;
  35. }
  36. }
  37. public List<object> ManagedStack { get { return managedStack; } }
  38. public void InitializeFrame(ILMethod method, StackObject* esp, out StackFrame res)
  39. {
  40. if (esp < pointer || esp >= endOfMemory)
  41. throw new StackOverflowException();
  42. if (frames.Count > 0 && frames.Peek().BasePointer > esp)
  43. throw new StackOverflowException();
  44. res = new StackFrame();
  45. res.LocalVarPointer = esp;
  46. res.Method = method;
  47. #if DEBUG
  48. res.Address = new IntegerReference();
  49. for (int i = 0; i < method.LocalVariableCount; i++)
  50. {
  51. var p = Add(esp, i);
  52. p->ObjectType = ObjectTypes.Null;
  53. }
  54. #endif
  55. res.BasePointer = method.LocalVariableCount > 0 ? Add(esp, method.LocalVariableCount + 1) : esp;
  56. res.ManagedStackBase = managedStack.Count;
  57. //frames.Push(res);
  58. }
  59. public void PushFrame(ref StackFrame frame)
  60. {
  61. frames.Push(frame);
  62. }
  63. public StackObject* PopFrame(ref StackFrame frame, StackObject* esp, List<object> mStack)
  64. {
  65. if (frames.Count > 0 && frames.Peek().BasePointer == frame.BasePointer)
  66. frames.Pop();
  67. else
  68. throw new NotSupportedException();
  69. StackObject* returnVal = esp - 1;
  70. StackObject* ret = frame.LocalVarPointer - frame.Method.ParameterCount;
  71. int mStackBase = frame.ManagedStackBase;
  72. if (frame.Method.HasThis)
  73. ret--;
  74. if(frame.Method.ReturnType != intepreter.AppDomain.VoidType)
  75. {
  76. *ret = *returnVal;
  77. if(ret->ObjectType == ObjectTypes.Object)
  78. {
  79. ret->Value = mStackBase;
  80. mStack[mStackBase] = mStack[returnVal->Value];
  81. mStackBase++;
  82. }
  83. ret++;
  84. }
  85. mStack.RemoveRange(mStackBase, mStack.Count - mStackBase);
  86. return ret;
  87. }
  88. public void Dispose()
  89. {
  90. if (nativePointer != IntPtr.Zero)
  91. {
  92. System.Runtime.InteropServices.Marshal.FreeHGlobal(nativePointer);
  93. nativePointer = IntPtr.Zero;
  94. }
  95. }
  96. StackObject* Add(StackObject* a, int b)
  97. {
  98. return (StackObject*)((long)a + sizeof(StackObject) * b);
  99. }
  100. }
  101. }