RuntimeStack.cs 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633
  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. StackObjectAllocator allocator;
  18. IntPtr nativePointer;
  19. #if DEBUG && !DISABLE_ILRUNTIME_DEBUG
  20. IList<object> managedStack = new List<object>(32);
  21. #else
  22. IList<object> managedStack = new UncheckedList<object>(32);
  23. #endif
  24. UncheckedStack<StackFrame> frames = new UncheckedStack<StackFrame>();
  25. public const int MAXIMAL_STACK_OBJECTS = 1024 * 16;
  26. public UncheckedStack<StackFrame> Frames { get { return frames; } }
  27. public RuntimeStack(ILIntepreter intepreter)
  28. {
  29. this.intepreter = intepreter;
  30. nativePointer = System.Runtime.InteropServices.Marshal.AllocHGlobal(sizeof(StackObject) * MAXIMAL_STACK_OBJECTS);
  31. pointer = (StackObject*)nativePointer.ToPointer();
  32. endOfMemory = Add(pointer, MAXIMAL_STACK_OBJECTS);
  33. valueTypePtr = endOfMemory - 1;
  34. }
  35. ~RuntimeStack()
  36. {
  37. Dispose();
  38. }
  39. public StackObject* StackBase
  40. {
  41. get
  42. {
  43. return pointer;
  44. }
  45. }
  46. public StackObject* ValueTypeStackPointer
  47. {
  48. get
  49. {
  50. return valueTypePtr;
  51. }
  52. internal set
  53. {
  54. if (value > ValueTypeStackBase)
  55. throw new StackOverflowException();
  56. valueTypePtr = value;
  57. }
  58. }
  59. public StackObject* ValueTypeStackBase
  60. {
  61. get
  62. {
  63. return endOfMemory - 1;
  64. }
  65. }
  66. public IList<object> ManagedStack { get { return managedStack; } }
  67. public void ResetValueTypePointer()
  68. {
  69. valueTypePtr = endOfMemory - 1;
  70. }
  71. public void InitializeFrame(ILMethod method, StackObject* esp, out StackFrame res)
  72. {
  73. #if DEBUG
  74. if (esp < pointer || esp >= endOfMemory)
  75. throw new StackOverflowException();
  76. if (frames.Count > 0 && frames.Peek().BasePointer > esp)
  77. throw new StackOverflowException();
  78. #endif
  79. res = new StackFrame();
  80. res.LocalVarPointer = esp;
  81. res.Method = method;
  82. #if DEBUG && !DISABLE_ILRUNTIME_DEBUG
  83. res.Address = new IntegerReference();
  84. for (int i = 0; i < method.LocalVariableCount; i++)
  85. {
  86. var p = Add(esp, i);
  87. p->ObjectType = ObjectTypes.Null;
  88. }
  89. #endif
  90. res.BasePointer = method.LocalVariableCount > 0 ? Add(esp, method.LocalVariableCount) : esp;
  91. res.ManagedStackBase = managedStack.Count;
  92. res.ValueTypeBasePointer = valueTypePtr;
  93. //frames.Push(res);
  94. }
  95. public void PushFrame(ref StackFrame frame)
  96. {
  97. frames.Push(ref frame);
  98. }
  99. public StackObject* PopFrame(ref StackFrame frame, StackObject* esp)
  100. {
  101. #if DEBUG
  102. if (frames.Count > 0 && frames.Peek().BasePointer == frame.BasePointer)
  103. #endif
  104. frames.Pop();
  105. #if DEBUG
  106. else
  107. throw new NotSupportedException();
  108. #endif
  109. StackObject* returnVal = esp - 1;
  110. var method = frame.Method;
  111. StackObject* ret = ILIntepreter.Minus(frame.LocalVarPointer, method.ParameterCount);
  112. int mStackBase = frame.ManagedStackBase;
  113. if (method.HasThis)
  114. ret--;
  115. if (allocator != null)
  116. allocator.FreeBefore(frame.ValueTypeBasePointer);
  117. for (StackObject* ptr = ret; ptr < frame.LocalVarPointer; ptr++)
  118. {
  119. if (ptr->ObjectType == ObjectTypes.ValueTypeObjectReference)
  120. {
  121. var addr = ILIntepreter.ResolveReference(ptr);
  122. int start = int.MaxValue;
  123. int end = int.MaxValue;
  124. var tmp = addr;
  125. CountValueTypeManaged(ptr, ref start, ref end, &tmp);
  126. if (addr > frame.ValueTypeBasePointer)
  127. {
  128. frame.ValueTypeBasePointer = addr;
  129. }
  130. if (start < mStackBase)
  131. mStackBase = start;
  132. }
  133. }
  134. if(method.ReturnType != intepreter.AppDomain.VoidType)
  135. {
  136. *ret = *returnVal;
  137. if(ret->ObjectType == ObjectTypes.Object)
  138. {
  139. ret->Value = mStackBase;
  140. managedStack[mStackBase] = managedStack[returnVal->Value];
  141. mStackBase++;
  142. }
  143. else if(ret->ObjectType == ObjectTypes.ValueTypeObjectReference)
  144. {
  145. StackObject* oriAddr = frame.ValueTypeBasePointer;
  146. RelocateValueType(ret, ref frame.ValueTypeBasePointer, ref mStackBase);
  147. *(long*)&ret->Value = (long)oriAddr;
  148. }
  149. ret++;
  150. }
  151. #if DEBUG && !DISABLE_ILRUNTIME_DEBUG
  152. ((List<object>)managedStack).RemoveRange(mStackBase, managedStack.Count - mStackBase);
  153. #else
  154. ((UncheckedList<object>)managedStack).RemoveRange(mStackBase, managedStack.Count - mStackBase);
  155. #endif
  156. valueTypePtr = frame.ValueTypeBasePointer;
  157. return ret;
  158. }
  159. public void RelocateValueTypeAndFreeAfterDst(StackObject* src, StackObject* dst)
  160. {
  161. var objRef2 = dst;
  162. dst = ILIntepreter.ResolveReference(dst);
  163. int start = int.MaxValue;
  164. int end = int.MaxValue;
  165. CountValueTypeManaged(objRef2, ref start, ref end, &objRef2);
  166. RelocateValueType(src, ref dst, ref start);
  167. ValueTypeStackPointer = dst;
  168. if (start <= end)
  169. RemoveManagedStackRange(start, end);
  170. }
  171. void RelocateValueType(StackObject* src, ref StackObject* dst, ref int mStackBase)
  172. {
  173. StackObject* descriptor = ILIntepreter.ResolveReference(src);
  174. if (descriptor > dst)
  175. throw new StackOverflowException();
  176. *dst = *descriptor;
  177. int cnt = descriptor->ValueLow;
  178. StackObject* endAddr = ILIntepreter.Minus(dst, cnt + 1);
  179. for(int i = 0; i < cnt; i++)
  180. {
  181. StackObject* addr = ILIntepreter.Minus(descriptor, i + 1);
  182. StackObject* tarVal = ILIntepreter.Minus(dst, i + 1);
  183. *tarVal = *addr;
  184. switch (addr->ObjectType)
  185. {
  186. case ObjectTypes.Object:
  187. case ObjectTypes.ArrayReference:
  188. case ObjectTypes.FieldReference:
  189. if (tarVal->Value >= mStackBase)
  190. {
  191. int oldIdx = addr->Value;
  192. tarVal->Value = mStackBase;
  193. managedStack[mStackBase] = managedStack[oldIdx];
  194. mStackBase++;
  195. }
  196. break;
  197. case ObjectTypes.ValueTypeObjectReference:
  198. var newAddr = endAddr;
  199. RelocateValueType(addr, ref endAddr, ref mStackBase);
  200. *(long*)&tarVal->Value = (long)newAddr;
  201. break;
  202. }
  203. }
  204. dst = endAddr;
  205. }
  206. int CountValueTypeManaged(IType type)
  207. {
  208. int res = 0;
  209. if (type is ILType)
  210. {
  211. ILType t = (ILType)type;
  212. for (int i = 0; i < t.FieldTypes.Length; i++)
  213. {
  214. var ft = t.FieldTypes[i];
  215. if (!ft.IsPrimitive && !ft.IsEnum)
  216. {
  217. if (ft.IsValueType)
  218. {
  219. if (!(ft is ILType) && ((CLRType)ft).ValueTypeBinder == null)
  220. {
  221. res++;
  222. }
  223. }
  224. else
  225. {
  226. res++;
  227. }
  228. }
  229. }
  230. if (type.BaseType != null && type.BaseType is ILType)
  231. res += CountValueTypeManaged((ILType)type.BaseType);
  232. }
  233. else
  234. {
  235. CLRType t = (CLRType)type;
  236. var cnt = t.TotalFieldCount;
  237. for (int i = 0; i < cnt; i++)
  238. {
  239. var it = t.OrderedFieldTypes[i] as CLRType;
  240. if (!it.IsPrimitive && it.IsEnum)
  241. {
  242. if (it.IsValueType)
  243. {
  244. if (it.ValueTypeBinder == null)
  245. {
  246. res++;
  247. }
  248. }
  249. else
  250. {
  251. res++;
  252. }
  253. }
  254. }
  255. }
  256. return res;
  257. }
  258. void AllocBlock(int size, out StackObject* dst, out int managedIdx)
  259. {
  260. dst = valueTypePtr;
  261. valueTypePtr = ILIntepreter.Minus(valueTypePtr, size);
  262. if (valueTypePtr <= StackBase)
  263. throw new StackOverflowException();
  264. managedIdx = managedStack.Count;
  265. }
  266. public void ClearAllocator()
  267. {
  268. if (allocator != null)
  269. allocator.Clear();
  270. }
  271. public void AllocValueTypeAndCopy(StackObject* ptr, StackObject* src)
  272. {
  273. var dst = ILIntepreter.ResolveReference(src);
  274. var type = intepreter.AppDomain.GetTypeByIndex(dst->Value);
  275. int size, managedCount;
  276. type.GetValueTypeSize(out size, out managedCount);
  277. if (allocator == null)
  278. allocator = new StackObjectAllocator(AllocBlock);
  279. StackObjectAllocation alloc;
  280. if(allocator.AllocExisting(ptr, size, managedCount, out alloc))
  281. {
  282. if (dst != alloc.Address)
  283. {
  284. dst = alloc.Address;
  285. ptr->ObjectType = ObjectTypes.ValueTypeObjectReference;
  286. *(long*)&ptr->Value = (long)dst;
  287. int managedIdx = alloc.ManagedIndex;
  288. InitializeValueTypeObject(type, dst, true, ref managedIdx, false);
  289. intepreter.CopyStackValueType(src, ptr, managedStack);
  290. FreeValueTypeObject(src);
  291. }
  292. else
  293. {
  294. ptr->ObjectType = ObjectTypes.ValueTypeObjectReference;
  295. *(long*)&ptr->Value = (long)dst;
  296. }
  297. }
  298. else
  299. {
  300. int start = int.MaxValue;
  301. int end = int.MinValue;
  302. StackObject* endAddr;
  303. CountValueTypeManaged(src, ref start, ref end, &endAddr);
  304. if (endAddr == valueTypePtr)
  305. valueTypePtr = dst;
  306. allocator.RegisterAllocation(ptr, dst, size, start, managedCount);
  307. ptr->ObjectType = ObjectTypes.ValueTypeObjectReference;
  308. *(long*)&ptr->Value = (long)dst;
  309. }
  310. }
  311. public void AllocValueType(StackObject* ptr, IType type, bool register = false, bool noInitialize = false)
  312. {
  313. if (type.IsValueType)
  314. {
  315. StackObject* dst;
  316. int size, managedCount;
  317. type.GetValueTypeSize(out size, out managedCount);
  318. int managedIdx = -1;
  319. if (register)
  320. {
  321. if (allocator == null)
  322. allocator = new StackObjectAllocator(AllocBlock);
  323. var allocation = allocator.Alloc(ptr, size, managedCount);
  324. dst = allocation.Address;
  325. managedIdx = allocation.ManagedIndex;
  326. }
  327. else
  328. {
  329. dst = valueTypePtr;
  330. managedIdx = managedStack.Count;
  331. valueTypePtr = ILIntepreter.Minus(valueTypePtr, size);
  332. if (valueTypePtr <= StackBase)
  333. throw new StackOverflowException();
  334. }
  335. ptr->ObjectType = ObjectTypes.ValueTypeObjectReference;
  336. *(long*)&ptr->Value = (long)dst;
  337. InitializeValueTypeObject(type, dst, register, ref managedIdx, noInitialize);
  338. }
  339. else
  340. throw new ArgumentException(type.FullName + " is not a value type.", "type");
  341. }
  342. internal void InitializeValueTypeObject(IType type, StackObject* ptr, bool register, ref int managedIdx, bool noInitialize)
  343. {
  344. ptr->ObjectType = ObjectTypes.ValueTypeDescriptor;
  345. ptr->Value = type.TypeIndex;
  346. ptr->ValueLow = type.TotalFieldCount;
  347. StackObject* endPtr = ptr - (type.TotalFieldCount + 1);
  348. if (noInitialize)
  349. return;
  350. if (type is ILType)
  351. {
  352. ILType t = (ILType)type;
  353. for (int i = 0; i < t.FieldTypes.Length; i++)
  354. {
  355. var ft = t.FieldTypes[i];
  356. StackObject* val = ILIntepreter.Minus(ptr, t.FieldStartIndex + i + 1);
  357. if (ft.IsPrimitive)
  358. *val = ft.DefaultObject;
  359. else if (ft.IsEnum)
  360. StackObject.Initialized(val, ft);
  361. else
  362. {
  363. if (ft.IsValueType)
  364. {
  365. if (ft is ILType || ((CLRType)ft).ValueTypeBinder != null)
  366. {
  367. val->ObjectType = ObjectTypes.ValueTypeObjectReference;
  368. *(long*)&val->Value = (long)endPtr;
  369. InitializeValueTypeObject(ft, endPtr, register, ref managedIdx, noInitialize);
  370. int size, mCnt;
  371. ft.GetValueTypeSize(out size, out mCnt);
  372. endPtr -= size;
  373. }
  374. else
  375. {
  376. val->ObjectType = ObjectTypes.Object;
  377. val->Value = managedIdx;
  378. if (managedIdx < managedStack.Count)
  379. managedStack[managedIdx] = ((CLRType)ft).CreateDefaultInstance();
  380. else
  381. managedStack.Add(((CLRType)ft).CreateDefaultInstance());
  382. managedIdx++;
  383. }
  384. }
  385. else
  386. {
  387. val->ObjectType = ObjectTypes.Object;
  388. val->Value = managedIdx;
  389. if (managedIdx < managedStack.Count)
  390. managedStack[managedIdx] = null;
  391. else
  392. managedStack.Add(null);
  393. managedIdx++;
  394. }
  395. }
  396. }
  397. if (type.BaseType != null && type.BaseType is ILType)
  398. InitializeValueTypeObject((ILType)type.BaseType, ptr, register, ref managedIdx, noInitialize);
  399. }
  400. else
  401. {
  402. CLRType t = (CLRType)type;
  403. var cnt = t.TotalFieldCount;
  404. for (int i = 0; i < cnt; i++)
  405. {
  406. var it = t.OrderedFieldTypes[i] as CLRType;
  407. StackObject* val = ILIntepreter.Minus(ptr, i + 1);
  408. if (it.IsPrimitive)
  409. *val = it.DefaultObject;
  410. else if (it.IsEnum)
  411. StackObject.Initialized(val, it);
  412. else
  413. {
  414. if (it.IsValueType)
  415. {
  416. if (it.ValueTypeBinder != null)
  417. {
  418. val->ObjectType = ObjectTypes.ValueTypeObjectReference;
  419. *(long*)&val->Value = (long)endPtr;
  420. InitializeValueTypeObject(it, endPtr, register, ref managedIdx, noInitialize);
  421. int size, mCnt;
  422. it.GetValueTypeSize(out size, out mCnt);
  423. endPtr -= size;
  424. }
  425. else
  426. {
  427. val->ObjectType = ObjectTypes.Object;
  428. val->Value = managedIdx;
  429. if (managedIdx < managedStack.Count)
  430. managedStack[managedIdx] = it.CreateDefaultInstance();
  431. else
  432. managedStack.Add(it.CreateDefaultInstance());
  433. managedIdx++;
  434. }
  435. }
  436. else
  437. {
  438. val->ObjectType = ObjectTypes.Object;
  439. val->Value = managedIdx;
  440. if (managedIdx < managedStack.Count)
  441. managedStack[managedIdx] = null;
  442. else
  443. managedStack.Add(null);
  444. managedIdx++;
  445. }
  446. }
  447. }
  448. }
  449. }
  450. public void ClearValueTypeObject(IType type, StackObject* ptr)
  451. {
  452. if (type is ILType)
  453. {
  454. ILType t = (ILType)type;
  455. for (int i = 0; i < t.FieldTypes.Length; i++)
  456. {
  457. var ft = t.FieldTypes[i];
  458. StackObject* val = ILIntepreter.Minus(ptr, t.FieldStartIndex + i + 1);
  459. if (ft.IsPrimitive || ft.IsEnum)
  460. StackObject.Initialized(val, ft);
  461. else
  462. {
  463. switch (val->ObjectType)
  464. {
  465. case ObjectTypes.ValueTypeObjectReference:
  466. ClearValueTypeObject(ft, ILIntepreter.ResolveReference(val));
  467. break;
  468. default:
  469. if (ft.IsValueType)
  470. {
  471. if(ft is ILType)
  472. {
  473. throw new NotImplementedException();
  474. }
  475. else
  476. {
  477. managedStack[val->Value] = ((CLRType)ft).CreateDefaultInstance();
  478. }
  479. }
  480. else
  481. managedStack[val->Value] = null;
  482. break;
  483. }
  484. }
  485. }
  486. if (type.BaseType != null && type.BaseType is ILType)
  487. ClearValueTypeObject((ILType)type.BaseType, ptr);
  488. }
  489. else
  490. {
  491. CLRType t = (CLRType)type;
  492. var cnt = t.TotalFieldCount;
  493. for (int i = 0; i < cnt; i++)
  494. {
  495. var vt = t.OrderedFieldTypes[i] as CLRType;
  496. StackObject* val = ILIntepreter.Minus(ptr, i + 1);
  497. if (vt.IsPrimitive)
  498. StackObject.Initialized(val, vt);
  499. else
  500. {
  501. switch (val->ObjectType)
  502. {
  503. case ObjectTypes.ValueTypeObjectReference:
  504. {
  505. var dst = ILIntepreter.ResolveReference(val);
  506. ClearValueTypeObject(vt, dst);
  507. }
  508. break;
  509. default:
  510. if (vt.IsValueType)
  511. {
  512. managedStack[val->Value] = vt.CreateDefaultInstance();
  513. }
  514. else
  515. managedStack[val->Value] = null;
  516. break;
  517. }
  518. }
  519. }
  520. }
  521. }
  522. internal void RemoveManagedStackRange(int start, int end)
  523. {
  524. if (start != int.MaxValue)
  525. {
  526. if (end == managedStack.Count - 1)
  527. {
  528. #if DEBUG && !DISABLE_ILRUNTIME_DEBUG
  529. ((List<object>)managedStack).RemoveRange(start, managedStack.Count - start);
  530. #else
  531. ((UncheckedList<object>)managedStack).RemoveRange(start, managedStack.Count - start);
  532. #endif
  533. }
  534. else
  535. throw new NotSupportedException();
  536. }
  537. }
  538. public void FreeRegisterValueType(StackObject* esp)
  539. {
  540. if (esp->ObjectType != ObjectTypes.ValueTypeObjectReference)
  541. return;
  542. allocator.Free(esp);
  543. }
  544. public void FreeValueTypeObject(StackObject* esp)
  545. {
  546. if (esp->ObjectType != ObjectTypes.ValueTypeObjectReference)
  547. return;
  548. int start = int.MaxValue;
  549. int end = int.MinValue;
  550. StackObject* endAddr;
  551. CountValueTypeManaged(esp, ref start, ref end, &endAddr);
  552. if (endAddr == valueTypePtr)
  553. valueTypePtr = ILIntepreter.ResolveReference(esp);
  554. else
  555. throw new NotSupportedException();
  556. RemoveManagedStackRange(start, end);
  557. }
  558. public void CountValueTypeManaged(StackObject* esp, ref int start, ref int end, StackObject** endAddr)
  559. {
  560. StackObject* descriptor = ILIntepreter.ResolveReference(esp);
  561. int cnt = descriptor->ValueLow;
  562. *endAddr = ILIntepreter.Minus(descriptor, cnt + 1);
  563. for (int i = 0; i < cnt; i++)
  564. {
  565. StackObject* addr = ILIntepreter.Minus(descriptor, i + 1);
  566. switch (addr->ObjectType)
  567. {
  568. case ObjectTypes.Object:
  569. case ObjectTypes.ArrayReference:
  570. case ObjectTypes.FieldReference:
  571. {
  572. if (start == int.MaxValue)
  573. {
  574. start = addr->Value;
  575. end = start;
  576. }
  577. else if (addr->Value == end + 1)
  578. end++;
  579. else
  580. throw new NotSupportedException();
  581. }
  582. break;
  583. case ObjectTypes.ValueTypeObjectReference:
  584. CountValueTypeManaged(addr, ref start, ref end, endAddr);
  585. break;
  586. }
  587. }
  588. }
  589. public void Dispose()
  590. {
  591. if (nativePointer != IntPtr.Zero)
  592. {
  593. System.Runtime.InteropServices.Marshal.FreeHGlobal(nativePointer);
  594. nativePointer = IntPtr.Zero;
  595. }
  596. }
  597. StackObject* Add(StackObject* a, int b)
  598. {
  599. return (StackObject*)((long)a + sizeof(StackObject) * b);
  600. }
  601. }
  602. }