RuntimeStack.cs 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using ILRuntime.CLR.Method;
  6. using ILRuntime.CLR.TypeSystem;
  7. using ILRuntime.Other;
  8. using ILRuntime.Runtime.Intepreter;
  9. namespace ILRuntime.Runtime.Stack
  10. {
  11. unsafe class RuntimeStack : IDisposable
  12. {
  13. ILIntepreter intepreter;
  14. StackObject* pointer;
  15. StackObject* endOfMemory;
  16. StackObject* valueTypePtr;
  17. IntPtr nativePointer;
  18. #if DEBUG && !DISABLE_ILRUNTIME_DEBUG
  19. IList<object> managedStack = new List<object>(32);
  20. #else
  21. IList<object> managedStack = new UncheckedList<object>(32);
  22. #endif
  23. UncheckedStack<StackFrame> frames = new UncheckedStack<StackFrame>();
  24. public const int MAXIMAL_STACK_OBJECTS = 1024 * 16;
  25. public UncheckedStack<StackFrame> Frames { get { return frames; } }
  26. public RuntimeStack(ILIntepreter intepreter)
  27. {
  28. this.intepreter = intepreter;
  29. nativePointer = System.Runtime.InteropServices.Marshal.AllocHGlobal(sizeof(StackObject) * MAXIMAL_STACK_OBJECTS);
  30. pointer = (StackObject*)nativePointer.ToPointer();
  31. endOfMemory = Add(pointer, MAXIMAL_STACK_OBJECTS);
  32. valueTypePtr = endOfMemory - 1;
  33. }
  34. ~RuntimeStack()
  35. {
  36. Dispose();
  37. }
  38. public StackObject* StackBase
  39. {
  40. get
  41. {
  42. return pointer;
  43. }
  44. }
  45. public StackObject* ValueTypeStackPointer
  46. {
  47. get
  48. {
  49. return valueTypePtr;
  50. }
  51. private set
  52. {
  53. if (value > ValueTypeStackBase)
  54. throw new StackOverflowException();
  55. valueTypePtr = value;
  56. }
  57. }
  58. public StackObject* ValueTypeStackBase
  59. {
  60. get
  61. {
  62. return endOfMemory - 1;
  63. }
  64. }
  65. public IList<object> ManagedStack { get { return managedStack; } }
  66. public void ResetValueTypePointer()
  67. {
  68. valueTypePtr = endOfMemory - 1;
  69. }
  70. public void InitializeFrame(ILMethod method, StackObject* esp, out StackFrame res)
  71. {
  72. #if DEBUG
  73. if (esp < pointer || esp >= endOfMemory)
  74. throw new StackOverflowException();
  75. if (frames.Count > 0 && frames.Peek().BasePointer > esp)
  76. throw new StackOverflowException();
  77. #endif
  78. res = new StackFrame();
  79. res.LocalVarPointer = esp;
  80. res.Method = method;
  81. #if DEBUG && !DISABLE_ILRUNTIME_DEBUG
  82. res.Address = new IntegerReference();
  83. for (int i = 0; i < method.LocalVariableCount; i++)
  84. {
  85. var p = Add(esp, i);
  86. p->ObjectType = ObjectTypes.Null;
  87. }
  88. #endif
  89. res.BasePointer = method.LocalVariableCount > 0 ? Add(esp, method.LocalVariableCount) : esp;
  90. res.ManagedStackBase = managedStack.Count;
  91. res.ValueTypeBasePointer = valueTypePtr;
  92. //frames.Push(res);
  93. }
  94. public void PushFrame(ref StackFrame frame)
  95. {
  96. frames.Push(ref frame);
  97. }
  98. public StackObject* PopFrame(ref StackFrame frame, StackObject* esp)
  99. {
  100. #if DEBUG
  101. if (frames.Count > 0 && frames.Peek().BasePointer == frame.BasePointer)
  102. #endif
  103. frames.Pop();
  104. #if DEBUG
  105. else
  106. throw new NotSupportedException();
  107. #endif
  108. StackObject* returnVal = esp - 1;
  109. var method = frame.Method;
  110. StackObject* ret = ILIntepreter.Minus(frame.LocalVarPointer, method.ParameterCount);
  111. int mStackBase = frame.ManagedStackBase;
  112. if (method.HasThis)
  113. ret--;
  114. for (StackObject* ptr = ret; ptr < frame.LocalVarPointer; ptr++)
  115. {
  116. if (ptr->ObjectType == ObjectTypes.ValueTypeObjectReference)
  117. {
  118. var addr = ILIntepreter.ResolveReference(ptr);
  119. int start = int.MaxValue;
  120. int end = int.MaxValue;
  121. var tmp = addr;
  122. CountValueTypeManaged(ptr, ref start, ref end, &tmp);
  123. if (addr > frame.ValueTypeBasePointer)
  124. {
  125. frame.ValueTypeBasePointer = addr;
  126. }
  127. if (start < mStackBase)
  128. mStackBase = start;
  129. }
  130. }
  131. if(method.ReturnType != intepreter.AppDomain.VoidType)
  132. {
  133. *ret = *returnVal;
  134. if(ret->ObjectType == ObjectTypes.Object)
  135. {
  136. ret->Value = mStackBase;
  137. managedStack[mStackBase] = managedStack[returnVal->Value];
  138. mStackBase++;
  139. }
  140. else if(ret->ObjectType == ObjectTypes.ValueTypeObjectReference)
  141. {
  142. StackObject* oriAddr = frame.ValueTypeBasePointer;
  143. RelocateValueType(ret, ref frame.ValueTypeBasePointer, ref mStackBase);
  144. *(long*)&ret->Value = (long)oriAddr;
  145. }
  146. ret++;
  147. }
  148. #if DEBUG && !DISABLE_ILRUNTIME_DEBUG
  149. ((List<object>)managedStack).RemoveRange(mStackBase, managedStack.Count - mStackBase);
  150. #else
  151. ((UncheckedList<object>)managedStack).RemoveRange(mStackBase, managedStack.Count - mStackBase);
  152. #endif
  153. valueTypePtr = frame.ValueTypeBasePointer;
  154. return ret;
  155. }
  156. public void RelocateValueTypeAndFreeAfterDst(StackObject* src, StackObject* dst)
  157. {
  158. var objRef2 = dst;
  159. dst = ILIntepreter.ResolveReference(dst);
  160. int start = int.MaxValue;
  161. int end = int.MaxValue;
  162. CountValueTypeManaged(objRef2, ref start, ref end, &objRef2);
  163. RelocateValueType(src, ref dst, ref start);
  164. ValueTypeStackPointer = dst;
  165. if (start <= end)
  166. RemoveManagedStackRange(start, end);
  167. }
  168. void RelocateValueType(StackObject* src, ref StackObject* dst, ref int mStackBase)
  169. {
  170. StackObject* descriptor = ILIntepreter.ResolveReference(src);
  171. if (descriptor > dst)
  172. throw new StackOverflowException();
  173. *dst = *descriptor;
  174. int cnt = descriptor->ValueLow;
  175. StackObject* endAddr = ILIntepreter.Minus(dst, cnt + 1);
  176. for(int i = 0; i < cnt; i++)
  177. {
  178. StackObject* addr = ILIntepreter.Minus(descriptor, i + 1);
  179. StackObject* tarVal = ILIntepreter.Minus(dst, i + 1);
  180. *tarVal = *addr;
  181. switch (addr->ObjectType)
  182. {
  183. case ObjectTypes.Object:
  184. case ObjectTypes.ArrayReference:
  185. case ObjectTypes.FieldReference:
  186. if (tarVal->Value >= mStackBase)
  187. {
  188. int oldIdx = addr->Value;
  189. tarVal->Value = mStackBase;
  190. managedStack[mStackBase] = managedStack[oldIdx];
  191. mStackBase++;
  192. }
  193. break;
  194. case ObjectTypes.ValueTypeObjectReference:
  195. var newAddr = endAddr;
  196. RelocateValueType(addr, ref endAddr, ref mStackBase);
  197. *(long*)&tarVal->Value = (long)newAddr;
  198. break;
  199. }
  200. }
  201. dst = endAddr;
  202. }
  203. public void AllocValueType(StackObject* ptr, IType type)
  204. {
  205. if (type.IsValueType)
  206. {
  207. int fieldCount = 0;
  208. if(type is ILType)
  209. {
  210. fieldCount = ((ILType)type).TotalFieldCount;
  211. }
  212. else
  213. {
  214. fieldCount = ((CLRType)type).TotalFieldCount;
  215. }
  216. ptr->ObjectType = ObjectTypes.ValueTypeObjectReference;
  217. var dst = valueTypePtr;
  218. *(long*)&ptr->Value = (long)dst;
  219. dst->ObjectType = ObjectTypes.ValueTypeDescriptor;
  220. dst->Value = type.GetHashCode();
  221. dst->ValueLow = fieldCount;
  222. valueTypePtr = ILIntepreter.Minus(valueTypePtr, fieldCount + 1);
  223. if (valueTypePtr <= StackBase)
  224. throw new StackOverflowException();
  225. InitializeValueTypeObject(type, dst);
  226. }
  227. else
  228. throw new ArgumentException(type.FullName + " is not a value type.", "type");
  229. }
  230. void InitializeValueTypeObject(IType type, StackObject* ptr)
  231. {
  232. if (type is ILType)
  233. {
  234. ILType t = (ILType)type;
  235. for (int i = 0; i < t.FieldTypes.Length; i++)
  236. {
  237. var ft = t.FieldTypes[i];
  238. StackObject* val = ILIntepreter.Minus(ptr, t.FieldStartIndex + i + 1);
  239. if (ft.IsPrimitive || ft.IsEnum)
  240. StackObject.Initialized(val, ft);
  241. else
  242. {
  243. if (ft.IsValueType)
  244. {
  245. if (ft is ILType || ((CLRType)ft).ValueTypeBinder != null)
  246. AllocValueType(val, ft);
  247. else
  248. {
  249. val->ObjectType = ObjectTypes.Object;
  250. val->Value = managedStack.Count;
  251. managedStack.Add(((CLRType)ft).CreateDefaultInstance());
  252. }
  253. }
  254. else
  255. {
  256. val->ObjectType = ObjectTypes.Object;
  257. val->Value = managedStack.Count;
  258. managedStack.Add(null);
  259. }
  260. }
  261. }
  262. if (type.BaseType != null && type.BaseType is ILType)
  263. InitializeValueTypeObject((ILType)type.BaseType, ptr);
  264. }
  265. else
  266. {
  267. CLRType t = (CLRType)type;
  268. var cnt = t.TotalFieldCount;
  269. for(int i = 0; i < cnt; i++)
  270. {
  271. var it = t.OrderedFieldTypes[i] as CLRType;
  272. StackObject* val = ILIntepreter.Minus(ptr, i + 1);
  273. if (it.IsPrimitive || it.IsEnum)
  274. StackObject.Initialized(val, it);
  275. else
  276. {
  277. if (it.IsValueType)
  278. {
  279. if (it.ValueTypeBinder != null)
  280. AllocValueType(val, it);
  281. else
  282. {
  283. val->ObjectType = ObjectTypes.Object;
  284. val->Value = managedStack.Count;
  285. managedStack.Add(it.CreateDefaultInstance());
  286. }
  287. }
  288. else
  289. {
  290. val->ObjectType = ObjectTypes.Object;
  291. val->Value = managedStack.Count;
  292. managedStack.Add(null);
  293. }
  294. }
  295. }
  296. }
  297. }
  298. public void ClearValueTypeObject(IType type, StackObject* ptr)
  299. {
  300. if (type is ILType)
  301. {
  302. ILType t = (ILType)type;
  303. for (int i = 0; i < t.FieldTypes.Length; i++)
  304. {
  305. var ft = t.FieldTypes[i];
  306. StackObject* val = ILIntepreter.Minus(ptr, t.FieldStartIndex + i + 1);
  307. if (ft.IsPrimitive || ft.IsEnum)
  308. StackObject.Initialized(val, ft);
  309. else
  310. {
  311. switch (val->ObjectType)
  312. {
  313. case ObjectTypes.ValueTypeObjectReference:
  314. ClearValueTypeObject(ft, ILIntepreter.ResolveReference(val));
  315. break;
  316. default:
  317. if (ft.IsValueType)
  318. {
  319. if(ft is ILType)
  320. {
  321. throw new NotImplementedException();
  322. }
  323. else
  324. {
  325. managedStack[val->Value] = ((CLRType)ft).CreateDefaultInstance();
  326. }
  327. }
  328. else
  329. managedStack[val->Value] = null;
  330. break;
  331. }
  332. }
  333. }
  334. if (type.BaseType != null && type.BaseType is ILType)
  335. ClearValueTypeObject((ILType)type.BaseType, ptr);
  336. }
  337. else
  338. {
  339. CLRType t = (CLRType)type;
  340. var cnt = t.TotalFieldCount;
  341. for (int i = 0; i < cnt; i++)
  342. {
  343. var vt = t.OrderedFieldTypes[i] as CLRType;
  344. StackObject* val = ILIntepreter.Minus(ptr, i + 1);
  345. if (vt.IsPrimitive)
  346. StackObject.Initialized(val, vt);
  347. else
  348. {
  349. switch (val->ObjectType)
  350. {
  351. case ObjectTypes.ValueTypeObjectReference:
  352. {
  353. var dst = ILIntepreter.ResolveReference(val);
  354. ClearValueTypeObject(vt, dst);
  355. }
  356. break;
  357. default:
  358. if (vt.IsValueType)
  359. {
  360. managedStack[val->Value] = vt.CreateDefaultInstance();
  361. }
  362. else
  363. managedStack[val->Value] = null;
  364. break;
  365. }
  366. }
  367. }
  368. }
  369. }
  370. void RemoveManagedStackRange(int start, int end)
  371. {
  372. if (start != int.MaxValue)
  373. {
  374. if (end == managedStack.Count - 1)
  375. {
  376. #if DEBUG && !DISABLE_ILRUNTIME_DEBUG
  377. ((List<object>)managedStack).RemoveRange(start, managedStack.Count - start);
  378. #else
  379. ((UncheckedList<object>)managedStack).RemoveRange(start, managedStack.Count - start);
  380. #endif
  381. }
  382. else
  383. throw new NotSupportedException();
  384. }
  385. }
  386. public void FreeValueTypeObject(StackObject* esp)
  387. {
  388. if (esp->ObjectType != ObjectTypes.ValueTypeObjectReference)
  389. return;
  390. int start = int.MaxValue;
  391. int end = int.MinValue;
  392. StackObject* endAddr;
  393. CountValueTypeManaged(esp, ref start, ref end, &endAddr);
  394. if (endAddr == valueTypePtr)
  395. valueTypePtr = ILIntepreter.ResolveReference(esp);
  396. else
  397. throw new NotSupportedException();
  398. RemoveManagedStackRange(start, end);
  399. }
  400. void CountValueTypeManaged(StackObject* esp, ref int start, ref int end, StackObject** endAddr)
  401. {
  402. StackObject* descriptor = ILIntepreter.ResolveReference(esp);
  403. int cnt = descriptor->ValueLow;
  404. *endAddr = ILIntepreter.Minus(descriptor, cnt + 1);
  405. for (int i = 0; i < cnt; i++)
  406. {
  407. StackObject* addr = ILIntepreter.Minus(descriptor, i + 1);
  408. switch (addr->ObjectType)
  409. {
  410. case ObjectTypes.Object:
  411. case ObjectTypes.ArrayReference:
  412. case ObjectTypes.FieldReference:
  413. {
  414. if (start == int.MaxValue)
  415. {
  416. start = addr->Value;
  417. end = start;
  418. }
  419. else if (addr->Value == end + 1)
  420. end++;
  421. else
  422. throw new NotSupportedException();
  423. }
  424. break;
  425. case ObjectTypes.ValueTypeObjectReference:
  426. CountValueTypeManaged(addr, ref start, ref end, endAddr);
  427. break;
  428. }
  429. }
  430. }
  431. public void Dispose()
  432. {
  433. if (nativePointer != IntPtr.Zero)
  434. {
  435. System.Runtime.InteropServices.Marshal.FreeHGlobal(nativePointer);
  436. nativePointer = IntPtr.Zero;
  437. }
  438. }
  439. StackObject* Add(StackObject* a, int b)
  440. {
  441. return (StackObject*)((long)a + sizeof(StackObject) * b);
  442. }
  443. }
  444. }