InvocationContext.cs 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555
  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.CLR.Utils;
  8. using ILRuntime.Runtime.Intepreter;
  9. using ILRuntime.Runtime.Stack;
  10. namespace ILRuntime.Runtime.Enviorment
  11. {
  12. public static class PrimitiveConverter<T>
  13. {
  14. public static Func<T, int> ToInteger;
  15. public static Func<int, T> FromInteger;
  16. public static Func<T, long> ToLong;
  17. public static Func<long, T> FromLong;
  18. public static Func<T, float> ToFloat;
  19. public static Func<float, T> FromFloat;
  20. public static Func<T, double> ToDouble;
  21. public static Func<double, T> FromDouble;
  22. public static int CheckAndInvokeToInteger(T val)
  23. {
  24. if (ToInteger != null)
  25. return ToInteger(val);
  26. else
  27. throw new InvalidCastException(string.Format("Cannot cast {0} to System.Int32", typeof(T).FullName));
  28. }
  29. public static T CheckAndInvokeFromInteger(int val)
  30. {
  31. if (FromInteger != null)
  32. return FromInteger(val);
  33. else
  34. throw new InvalidCastException(string.Format("Cannot cast System.Int32 to {0}", typeof(T).FullName));
  35. }
  36. public static long CheckAndInvokeToLong(T val)
  37. {
  38. if (ToLong != null)
  39. return ToLong(val);
  40. else
  41. throw new InvalidCastException(string.Format("Cannot cast {0} to System.Int64", typeof(T).FullName));
  42. }
  43. public static T CheckAndInvokeFromLong(long val)
  44. {
  45. if (FromLong != null)
  46. return FromLong(val);
  47. else
  48. throw new InvalidCastException(string.Format("Cannot cast System.Int64 to {0}", typeof(T).FullName));
  49. }
  50. public static float CheckAndInvokeToFloat(T val)
  51. {
  52. if (ToFloat != null)
  53. return ToFloat(val);
  54. else
  55. throw new InvalidCastException(string.Format("Cannot cast {0} to System.Single", typeof(T).FullName));
  56. }
  57. public static T CheckAndInvokeFromFloat(float val)
  58. {
  59. if (FromFloat != null)
  60. return FromFloat(val);
  61. else
  62. throw new InvalidCastException(string.Format("Cannot cast System.Single to {0}", typeof(T).FullName));
  63. }
  64. public static double CheckAndInvokeToDouble(T val)
  65. {
  66. if (ToDouble != null)
  67. return ToDouble(val);
  68. else
  69. throw new InvalidCastException(string.Format("Cannot cast {0} to System.Double", typeof(T).FullName));
  70. }
  71. public static T CheckAndInvokeFromDouble(double val)
  72. {
  73. if (FromDouble != null)
  74. return FromDouble(val);
  75. else
  76. throw new InvalidCastException(string.Format("Cannot cast System.Double to {0}", typeof(T).FullName));
  77. }
  78. }
  79. enum InvocationTypes
  80. {
  81. Integer,
  82. Long,
  83. Float,
  84. Double,
  85. Enum,
  86. ValueType,
  87. Object,
  88. }
  89. public unsafe struct InvocationContext : IDisposable
  90. {
  91. StackObject* ebp;
  92. StackObject* esp;
  93. AppDomain domain;
  94. ILIntepreter intp;
  95. ILMethod method;
  96. IList<object> mStack;
  97. bool invocated;
  98. int paramCnt;
  99. bool hasReturn;
  100. bool useRegister;
  101. static bool defaultConverterIntialized = false;
  102. internal static void InitializeDefaultConverters()
  103. {
  104. if (!defaultConverterIntialized)
  105. {
  106. PrimitiveConverter<int>.ToInteger = (a) => a;
  107. PrimitiveConverter<int>.FromInteger = (a) => a;
  108. PrimitiveConverter<short>.ToInteger = (a) => a;
  109. PrimitiveConverter<short>.FromInteger = (a) => (short)a;
  110. PrimitiveConverter<byte>.ToInteger = (a) => a;
  111. PrimitiveConverter<byte>.FromInteger = (a) => (byte)a;
  112. PrimitiveConverter<sbyte>.ToInteger = (a) => a;
  113. PrimitiveConverter<sbyte>.FromInteger = (a) => (sbyte)a;
  114. PrimitiveConverter<ushort>.ToInteger = (a) => a;
  115. PrimitiveConverter<ushort>.FromInteger = (a) => (ushort)a;
  116. PrimitiveConverter<char>.ToInteger = (a) => a;
  117. PrimitiveConverter<char>.FromInteger = (a) => (char)a;
  118. PrimitiveConverter<uint>.ToInteger = (a) => (int)a;
  119. PrimitiveConverter<uint>.FromInteger = (a) => (uint)a;
  120. PrimitiveConverter<bool>.ToInteger = (a) => a ? 1 : 0;
  121. PrimitiveConverter<bool>.FromInteger = (a) => a == 1;
  122. PrimitiveConverter<long>.ToLong = (a) => a;
  123. PrimitiveConverter<long>.FromLong = (a) => a;
  124. PrimitiveConverter<ulong>.ToLong = (a) => (long)a;
  125. PrimitiveConverter<ulong>.FromLong = (a) => (ulong)a;
  126. PrimitiveConverter<float>.ToFloat = (a) => a;
  127. PrimitiveConverter<float>.FromFloat = (a) => a;
  128. PrimitiveConverter<double>.ToDouble = (a) => a;
  129. PrimitiveConverter<double>.FromDouble = (a) => a;
  130. defaultConverterIntialized = true;
  131. }
  132. }
  133. internal static InvocationTypes GetInvocationType<T>()
  134. {
  135. var type = typeof(T);
  136. if (type.IsPrimitive)
  137. {
  138. if (type == typeof(int))
  139. return InvocationTypes.Integer;
  140. if (type == typeof(short))
  141. return InvocationTypes.Integer;
  142. if (type == typeof(bool))
  143. return InvocationTypes.Integer;
  144. if (type == typeof(long))
  145. return InvocationTypes.Long;
  146. if (type == typeof(float))
  147. return InvocationTypes.Float;
  148. if (type == typeof(double))
  149. return InvocationTypes.Double;
  150. if (type == typeof(char))
  151. return InvocationTypes.Integer;
  152. if (type == typeof(ushort))
  153. return InvocationTypes.Integer;
  154. if (type == typeof(uint))
  155. return InvocationTypes.Integer;
  156. if (type == typeof(ulong))
  157. return InvocationTypes.Long;
  158. if (type == typeof(byte))
  159. return InvocationTypes.Integer;
  160. if (type == typeof(sbyte))
  161. return InvocationTypes.Integer;
  162. else
  163. throw new NotImplementedException(string.Format("Not supported type:{0}", type.FullName));
  164. }
  165. else if (type.IsEnum)
  166. {
  167. if (PrimitiveConverter<T>.ToInteger != null && PrimitiveConverter<T>.FromInteger != null)
  168. return InvocationTypes.Integer;
  169. if (PrimitiveConverter<T>.ToLong != null && PrimitiveConverter<T>.FromLong != null)
  170. return InvocationTypes.Long;
  171. return InvocationTypes.Enum;
  172. }
  173. else if (type.IsValueType)
  174. return InvocationTypes.ValueType;
  175. else
  176. return InvocationTypes.Object;
  177. }
  178. internal InvocationContext(ILIntepreter intp, ILMethod method)
  179. {
  180. var stack = intp.Stack;
  181. mStack = stack.ManagedStack;
  182. esp = stack.StackBase;
  183. ebp = esp;
  184. stack.ResetValueTypePointer();
  185. this.domain = intp.AppDomain;
  186. this.intp = intp;
  187. this.method = method;
  188. invocated = false;
  189. paramCnt = 0;
  190. hasReturn = method.ReturnType != domain.VoidType;
  191. useRegister = method.ShouldUseRegisterVM;
  192. }
  193. internal void SetInvoked(StackObject* esp)
  194. {
  195. this.esp = esp - 1;
  196. invocated = true;
  197. }
  198. internal StackObject* ESP
  199. {
  200. get
  201. {
  202. return esp;
  203. }
  204. set
  205. {
  206. esp = value;
  207. }
  208. }
  209. internal ILIntepreter Intepreter
  210. {
  211. get
  212. {
  213. return intp;
  214. }
  215. }
  216. internal IList<object> ManagedStack
  217. {
  218. get
  219. {
  220. return mStack;
  221. }
  222. }
  223. public void PushBool(bool val)
  224. {
  225. PushInteger(val ? 1 : 0);
  226. }
  227. public void PushInteger<T>(T val)
  228. {
  229. PushInteger(PrimitiveConverter<T>.CheckAndInvokeToInteger(val));
  230. }
  231. public void PushLong<T>(T val)
  232. {
  233. PushInteger(PrimitiveConverter<T>.CheckAndInvokeToLong(val));
  234. }
  235. public void PushInteger(int val)
  236. {
  237. esp->ObjectType = ObjectTypes.Integer;
  238. esp->Value = val;
  239. esp->ValueLow = 0;
  240. if (useRegister)
  241. mStack.Add(null);
  242. esp++;
  243. paramCnt++;
  244. }
  245. public void PushInteger(long val)
  246. {
  247. esp->ObjectType = ObjectTypes.Long;
  248. *(long*)&esp->Value = val;
  249. if (useRegister)
  250. mStack.Add(null);
  251. esp++;
  252. paramCnt++;
  253. }
  254. public void PushFloat<T>(T val)
  255. {
  256. PushFloat(PrimitiveConverter<T>.CheckAndInvokeToFloat(val));
  257. }
  258. public void PushFloat(float val)
  259. {
  260. esp->ObjectType = ObjectTypes.Float;
  261. *(float*)&esp->Value = val;
  262. if (useRegister)
  263. mStack.Add(null);
  264. esp++;
  265. paramCnt++;
  266. }
  267. public void PushDouble<T>(T val)
  268. {
  269. PushDouble(PrimitiveConverter<T>.CheckAndInvokeToDouble(val));
  270. }
  271. public void PushDouble(double val)
  272. {
  273. esp->ObjectType = ObjectTypes.Double;
  274. *(double*)&esp->Value = val;
  275. if (useRegister)
  276. mStack.Add(null);
  277. esp++;
  278. paramCnt++;
  279. }
  280. public void PushValueType<T>(ref T obj)
  281. {
  282. Type t = typeof(T);
  283. bool needPush = false;
  284. StackObject* res = default(StackObject*);
  285. ValueTypeBinder binder;
  286. if (domain.ValueTypeBinders.TryGetValue(t, out binder))
  287. {
  288. var binderT = binder as ValueTypeBinder<T>;
  289. if (binderT != null)
  290. {
  291. binderT.PushValue(ref obj, intp, esp, mStack);
  292. if (useRegister)
  293. mStack.Add(null);
  294. res = esp + 1;
  295. }
  296. else
  297. needPush = true;
  298. }
  299. else
  300. needPush = true;
  301. if (needPush)
  302. {
  303. res = ILIntepreter.PushObject(esp, mStack, obj, true);
  304. }
  305. esp = res;
  306. paramCnt++;
  307. }
  308. public void PushObject(object obj, bool isBox = true)
  309. {
  310. if (obj is CrossBindingAdaptorType)
  311. obj = ((CrossBindingAdaptorType)obj).ILInstance;
  312. var res = ILIntepreter.PushObject(esp, mStack, obj, isBox);
  313. if (esp->ObjectType < ObjectTypes.Object && useRegister)
  314. mStack.Add(null);
  315. esp = res;
  316. paramCnt++;
  317. }
  318. public void PushReference(int index)
  319. {
  320. var dst = ILIntepreter.Add(ebp, index);
  321. esp->ObjectType = ObjectTypes.StackObjectReference;
  322. *(long*)&esp->Value = (long)dst;
  323. if (useRegister)
  324. mStack.Add(null);
  325. esp++;
  326. }
  327. internal void PushParameter<T>(InvocationTypes type, T val)
  328. {
  329. switch (type)
  330. {
  331. case InvocationTypes.Integer:
  332. PushInteger(val);
  333. break;
  334. case InvocationTypes.Long:
  335. PushLong(val);
  336. break;
  337. case InvocationTypes.Float:
  338. PushFloat(val);
  339. break;
  340. case InvocationTypes.Double:
  341. PushDouble(val);
  342. break;
  343. case InvocationTypes.Enum:
  344. PushObject(val, false);
  345. break;
  346. case InvocationTypes.ValueType:
  347. PushValueType(ref val);
  348. break;
  349. default:
  350. PushObject(val);
  351. break;
  352. }
  353. }
  354. internal T ReadResult<T>(InvocationTypes type)
  355. {
  356. switch (type)
  357. {
  358. case InvocationTypes.Integer:
  359. return ReadInteger<T>();
  360. case InvocationTypes.Long:
  361. return ReadLong<T>();
  362. case InvocationTypes.Float:
  363. return ReadFloat<T>();
  364. case InvocationTypes.Double:
  365. return ReadDouble<T>();
  366. case InvocationTypes.ValueType:
  367. return ReadValueType<T>();
  368. default:
  369. return ReadObject<T>();
  370. }
  371. }
  372. public void Invoke()
  373. {
  374. if (invocated)
  375. throw new NotSupportedException("A invocation context can only be used once");
  376. invocated = true;
  377. var cnt = method.HasThis ? method.ParameterCount + 1 : method.ParameterCount;
  378. if (cnt != paramCnt)
  379. throw new ArgumentException("Argument count mismatch");
  380. bool unhandledException;
  381. if (useRegister)
  382. esp = intp.ExecuteR(method, esp, out unhandledException);
  383. else
  384. esp = intp.Execute(method, esp, out unhandledException);
  385. esp--;
  386. }
  387. void CheckReturnValue()
  388. {
  389. if (!invocated)
  390. throw new NotSupportedException("You have to invocate first before you try to read the return value");
  391. if (!hasReturn)
  392. throw new NotSupportedException("The target method does not have a return value");
  393. }
  394. public int ReadInteger()
  395. {
  396. CheckReturnValue();
  397. return esp->Value;
  398. }
  399. public int ReadInteger(int index)
  400. {
  401. var esp = ILIntepreter.Add(ebp, index);
  402. return esp->Value;
  403. }
  404. public T ReadInteger<T>()
  405. {
  406. return PrimitiveConverter<T>.CheckAndInvokeFromInteger(ReadInteger());
  407. }
  408. public long ReadLong()
  409. {
  410. CheckReturnValue();
  411. return *(long*)&esp->Value;
  412. }
  413. public long ReadLong(int index)
  414. {
  415. var esp = ILIntepreter.Add(ebp, index);
  416. return *(long*)&esp->Value;
  417. }
  418. public T ReadLong<T>()
  419. {
  420. return PrimitiveConverter<T>.CheckAndInvokeFromLong(ReadLong());
  421. }
  422. public float ReadFloat()
  423. {
  424. CheckReturnValue();
  425. return *(float*)&esp->Value;
  426. }
  427. public float ReadFloat(int index)
  428. {
  429. var esp = ILIntepreter.Add(ebp, index);
  430. return *(float*)&esp->Value;
  431. }
  432. public T ReadFloat<T>()
  433. {
  434. return PrimitiveConverter<T>.CheckAndInvokeFromFloat(ReadFloat());
  435. }
  436. public double ReadDouble()
  437. {
  438. CheckReturnValue();
  439. return *(double*)&esp->Value;
  440. }
  441. public double ReaDouble(int index)
  442. {
  443. var esp = ILIntepreter.Add(ebp, index);
  444. return *(double*)&esp->Value;
  445. }
  446. public T ReadDouble<T>()
  447. {
  448. return PrimitiveConverter<T>.CheckAndInvokeFromDouble(ReadDouble());
  449. }
  450. public bool ReadBool()
  451. {
  452. CheckReturnValue();
  453. return esp->Value == 1;
  454. }
  455. public bool ReadBool(int index)
  456. {
  457. var esp = ILIntepreter.Add(ebp, index);
  458. return esp->Value == 1;
  459. }
  460. public T ReadValueType<T>()
  461. {
  462. CheckReturnValue();
  463. Type t = typeof(T);
  464. T res = default(T);
  465. ValueTypeBinder binder;
  466. if (domain.ValueTypeBinders.TryGetValue(t, out binder))
  467. {
  468. var binderT = binder as ValueTypeBinder<T>;
  469. if (binderT != null)
  470. {
  471. binderT.ParseValue(ref res, intp, esp, mStack);
  472. }
  473. else
  474. res = (T)t.CheckCLRTypes(StackObject.ToObject(esp, domain, mStack));
  475. }
  476. else
  477. res = (T)t.CheckCLRTypes(StackObject.ToObject(esp, domain, mStack));
  478. return res;
  479. }
  480. public T ReadObject<T>()
  481. {
  482. CheckReturnValue();
  483. return (T)typeof(T).CheckCLRTypes(StackObject.ToObject(esp, domain, mStack));
  484. }
  485. public object ReadObject(Type type)
  486. {
  487. CheckReturnValue();
  488. return type.CheckCLRTypes(StackObject.ToObject(esp, domain, mStack));
  489. }
  490. public T ReadObject<T>(int index)
  491. {
  492. var esp = ILIntepreter.Add(ebp, index);
  493. return (T)typeof(T).CheckCLRTypes(StackObject.ToObject(esp, domain, mStack));
  494. }
  495. public void Dispose()
  496. {
  497. domain.FreeILIntepreter(intp);
  498. esp = null;
  499. intp = null;
  500. domain = null;
  501. method = null;
  502. mStack = null;
  503. }
  504. }
  505. }