CLRMethod.cs 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457
  1. using ILRuntime.CLR.TypeSystem;
  2. using ILRuntime.CLR.Utils;
  3. using ILRuntime.Runtime.Enviorment;
  4. using ILRuntime.Runtime.Intepreter;
  5. using ILRuntime.Runtime.Stack;
  6. using System;
  7. using System.Collections.Generic;
  8. using System.Reflection;
  9. namespace ILRuntime.CLR.Method
  10. {
  11. public class CLRMethod : IMethod
  12. {
  13. MethodInfo def;
  14. ConstructorInfo cDef;
  15. List<IType> parameters;
  16. ParameterInfo[] parametersCLR;
  17. ILRuntime.Runtime.Enviorment.AppDomain appdomain;
  18. CLRType declaringType;
  19. bool isConstructor;
  20. CLRRedirectionDelegate redirect;
  21. IType[] genericArguments;
  22. Type[] genericArgumentsCLR;
  23. object[] invocationParam;
  24. bool isDelegateInvoke;
  25. int hashCode = -1;
  26. static int instance_id = 0x20000000;
  27. public IType DeclearingType
  28. {
  29. get
  30. {
  31. return declaringType;
  32. }
  33. }
  34. public string Name
  35. {
  36. get
  37. {
  38. return def.Name;
  39. }
  40. }
  41. public bool HasThis
  42. {
  43. get
  44. {
  45. return isConstructor ? !cDef.IsStatic : !def.IsStatic;
  46. }
  47. }
  48. int _genericParameterCount = -1;
  49. public int GenericParameterCount
  50. {
  51. get
  52. {
  53. if (_genericParameterCount == -1)
  54. {
  55. if (def.ContainsGenericParameters && def.IsGenericMethodDefinition)
  56. _genericParameterCount = def.GetGenericArguments().Length;
  57. else
  58. _genericParameterCount = 0;
  59. }
  60. return _genericParameterCount;
  61. }
  62. }
  63. public bool IsGenericInstance
  64. {
  65. get
  66. {
  67. return genericArguments != null;
  68. }
  69. }
  70. public bool IsDelegateInvoke
  71. {
  72. get
  73. {
  74. return isDelegateInvoke;
  75. }
  76. }
  77. public bool IsStatic
  78. {
  79. get
  80. {
  81. if (cDef != null)
  82. return cDef.IsStatic;
  83. else
  84. return def.IsStatic;
  85. }
  86. }
  87. public CLRRedirectionDelegate Redirection
  88. {
  89. get
  90. {
  91. if (redirect == null)
  92. {
  93. if (def != null)
  94. {
  95. if (def.IsGenericMethod && !def.IsGenericMethodDefinition)
  96. {
  97. //Redirection of Generic method Definition will be prioritized
  98. if (!appdomain.RedirectMap.TryGetValue(def.GetGenericMethodDefinition(), out redirect))
  99. appdomain.RedirectMap.TryGetValue(def, out redirect);
  100. }
  101. else
  102. appdomain.RedirectMap.TryGetValue(def, out redirect);
  103. }
  104. else if (cDef != null)
  105. {
  106. appdomain.RedirectMap.TryGetValue(cDef, out redirect);
  107. }
  108. }
  109. return redirect;
  110. }
  111. }
  112. public MethodInfo MethodInfo { get { return def; } }
  113. public ConstructorInfo ConstructorInfo { get { return cDef; } }
  114. public IType[] GenericArguments { get { return genericArguments; } }
  115. public Type[] GenericArgumentsCLR
  116. {
  117. get
  118. {
  119. if (genericArgumentsCLR == null)
  120. {
  121. if (cDef != null)
  122. genericArgumentsCLR = cDef.GetGenericArguments();
  123. else
  124. genericArgumentsCLR = def.GetGenericArguments();
  125. }
  126. return genericArgumentsCLR;
  127. }
  128. }
  129. internal CLRMethod(MethodInfo def, CLRType type, ILRuntime.Runtime.Enviorment.AppDomain domain)
  130. {
  131. this.def = def;
  132. declaringType = type;
  133. this.appdomain = domain;
  134. if (!def.ContainsGenericParameters)
  135. {
  136. ReturnType = domain.GetType(def.ReturnType.FullName);
  137. if (ReturnType == null)
  138. {
  139. ReturnType = domain.GetType(def.ReturnType.AssemblyQualifiedName);
  140. }
  141. }
  142. if (type.IsDelegate && def.Name == "Invoke")
  143. isDelegateInvoke = true;
  144. isConstructor = false;
  145. }
  146. internal CLRMethod(ConstructorInfo def, CLRType type, ILRuntime.Runtime.Enviorment.AppDomain domain)
  147. {
  148. this.cDef = def;
  149. declaringType = type;
  150. this.appdomain = domain;
  151. if (!def.ContainsGenericParameters)
  152. {
  153. ReturnType = type;
  154. }
  155. isConstructor = true;
  156. }
  157. public int ParameterCount
  158. {
  159. get
  160. {
  161. return Parameters.Count;
  162. }
  163. }
  164. public List<IType> Parameters
  165. {
  166. get
  167. {
  168. if (parameters == null)
  169. {
  170. InitParameters();
  171. }
  172. return parameters;
  173. }
  174. }
  175. public ParameterInfo[] ParametersCLR
  176. {
  177. get
  178. {
  179. if (parametersCLR == null)
  180. {
  181. if (cDef != null)
  182. parametersCLR = cDef.GetParameters();
  183. else
  184. parametersCLR = def.GetParameters();
  185. }
  186. return parametersCLR;
  187. }
  188. }
  189. public IType ReturnType
  190. {
  191. get;
  192. private set;
  193. }
  194. public bool IsConstructor
  195. {
  196. get
  197. {
  198. return cDef != null;
  199. }
  200. }
  201. void InitParameters()
  202. {
  203. parameters = new List<IType>();
  204. foreach (var i in ParametersCLR)
  205. {
  206. IType type = appdomain.GetType(i.ParameterType.FullName);
  207. if (type == null)
  208. type = appdomain.GetType(i.ParameterType.AssemblyQualifiedName);
  209. if (i.ParameterType.IsGenericTypeDefinition)
  210. {
  211. if (type == null)
  212. type = appdomain.GetType(i.ParameterType.GetGenericTypeDefinition().FullName);
  213. if (type == null)
  214. type = appdomain.GetType(i.ParameterType.GetGenericTypeDefinition().AssemblyQualifiedName);
  215. }
  216. if (i.ParameterType.ContainsGenericParameters)
  217. {
  218. var t = i.ParameterType;
  219. if (t.HasElementType)
  220. t = i.ParameterType.GetElementType();
  221. else if (t.GetGenericArguments().Length > 0)
  222. {
  223. t = t.GetGenericArguments()[0];
  224. }
  225. type = new ILGenericParameterType(t.Name);
  226. }
  227. if (type == null)
  228. throw new TypeLoadException();
  229. parameters.Add(type);
  230. }
  231. }
  232. unsafe StackObject* Minus(StackObject* a, int b)
  233. {
  234. return (StackObject*)((long)a - sizeof(StackObject) * b);
  235. }
  236. public unsafe object Invoke(Runtime.Intepreter.ILIntepreter intepreter, StackObject* esp, IList<object> mStack, bool isNewObj = false)
  237. {
  238. if (parameters == null)
  239. {
  240. InitParameters();
  241. }
  242. int paramCount = ParameterCount;
  243. if (invocationParam == null)
  244. invocationParam = new object[paramCount];
  245. object[] param = invocationParam;
  246. for (int i = paramCount; i >= 1; i--)
  247. {
  248. var p = Minus(esp, i);
  249. var pt = this.ParametersCLR[paramCount - i].ParameterType;
  250. var obj = pt.CheckCLRTypes(StackObject.ToObject(p, appdomain, mStack));
  251. obj = ILIntepreter.CheckAndCloneValueType(obj, appdomain);
  252. param[paramCount - i] = obj;
  253. }
  254. if (isConstructor)
  255. {
  256. if (!isNewObj)
  257. {
  258. if (!cDef.IsStatic)
  259. {
  260. object instance = declaringType.TypeForCLR.CheckCLRTypes(StackObject.ToObject((Minus(esp, paramCount + 1)), appdomain, mStack));
  261. if (instance == null)
  262. throw new NullReferenceException();
  263. if (instance is CrossBindingAdaptorType && paramCount == 0)//It makes no sense to call the Adaptor's default constructor
  264. return null;
  265. cDef.Invoke(instance, param);
  266. Array.Clear(invocationParam, 0, invocationParam.Length);
  267. return null;
  268. }
  269. else
  270. {
  271. throw new NotImplementedException();
  272. }
  273. }
  274. else
  275. {
  276. var res = cDef.Invoke(param);
  277. FixReference(paramCount, esp, param, mStack, null, false);
  278. Array.Clear(invocationParam, 0, invocationParam.Length);
  279. return res;
  280. }
  281. }
  282. else
  283. {
  284. object instance = null;
  285. if (!def.IsStatic)
  286. {
  287. instance = StackObject.ToObject((Minus(esp, paramCount + 1)), appdomain, mStack);
  288. if (!(instance is Reflection.ILRuntimeWrapperType))
  289. instance = declaringType.TypeForCLR.CheckCLRTypes(instance);
  290. if (declaringType.IsValueType)
  291. instance = ILIntepreter.CheckAndCloneValueType(instance, appdomain);
  292. if (instance == null)
  293. throw new NullReferenceException();
  294. }
  295. object res = null;
  296. /*if (redirect != null)
  297. res = redirect(new ILContext(appdomain, intepreter, esp, mStack, this), instance, param, genericArguments);
  298. else*/
  299. {
  300. res = def.Invoke(instance, param);
  301. }
  302. FixReference(paramCount, esp, param, mStack, instance, !def.IsStatic);
  303. Array.Clear(invocationParam, 0, invocationParam.Length);
  304. return res;
  305. }
  306. }
  307. unsafe void FixReference(int paramCount, StackObject* esp, object[] param, IList<object> mStack, object instance, bool hasThis)
  308. {
  309. var cnt = hasThis ? paramCount + 1 : paramCount;
  310. for (int i = cnt; i >= 1; i--)
  311. {
  312. var p = Minus(esp, i);
  313. var val = i <= paramCount ? param[paramCount - i] : instance;
  314. switch (p->ObjectType)
  315. {
  316. case ObjectTypes.StackObjectReference:
  317. {
  318. var addr = *(long*)&p->Value;
  319. var dst = (StackObject*)addr;
  320. if (dst->ObjectType >= ObjectTypes.Object)
  321. {
  322. var obj = val;
  323. if (obj is CrossBindingAdaptorType)
  324. obj = ((CrossBindingAdaptorType)obj).ILInstance;
  325. mStack[dst->Value] = obj;
  326. }
  327. else
  328. {
  329. ILIntepreter.UnboxObject(dst, val, mStack, appdomain);
  330. }
  331. }
  332. break;
  333. case ObjectTypes.FieldReference:
  334. {
  335. var obj = mStack[p->Value];
  336. if (obj is ILTypeInstance)
  337. {
  338. ((ILTypeInstance)obj)[p->ValueLow] = val;
  339. }
  340. else
  341. {
  342. var t = appdomain.GetType(obj.GetType()) as CLRType;
  343. t.GetField(p->ValueLow).SetValue(obj, val);
  344. }
  345. }
  346. break;
  347. case ObjectTypes.StaticFieldReference:
  348. {
  349. var t = appdomain.GetType(p->Value);
  350. if (t is ILType)
  351. {
  352. ((ILType)t).StaticInstance[p->ValueLow] = val;
  353. }
  354. else
  355. {
  356. ((CLRType)t).SetStaticFieldValue(p->ValueLow, val);
  357. }
  358. }
  359. break;
  360. case ObjectTypes.ArrayReference:
  361. {
  362. var arr = mStack[p->Value] as Array;
  363. arr.SetValue(val, p->ValueLow);
  364. }
  365. break;
  366. }
  367. }
  368. }
  369. public IMethod MakeGenericMethod(IType[] genericArguments)
  370. {
  371. Type[] p = new Type[genericArguments.Length];
  372. for (int i = 0; i < genericArguments.Length; i++)
  373. {
  374. p[i] = genericArguments[i].TypeForCLR;
  375. }
  376. MethodInfo t = null;
  377. #if UNITY_EDITOR || (DEBUG && !DISABLE_ILRUNTIME_DEBUG)
  378. try
  379. {
  380. #endif
  381. t = def.MakeGenericMethod(p);
  382. #if UNITY_EDITOR || (DEBUG && !DISABLE_ILRUNTIME_DEBUG)
  383. }
  384. catch (Exception e)
  385. {
  386. string argString = "";
  387. for (int i = 0; i < genericArguments.Length; i++)
  388. {
  389. argString += genericArguments[i].TypeForCLR.FullName + ", ";
  390. }
  391. argString = argString.Substring(0, argString.Length - 2);
  392. throw new Exception(string.Format("MakeGenericMethod failed : {0}.{1}<{2}>", def.DeclaringType.FullName, def.Name, argString));
  393. }
  394. #endif
  395. var res = new CLRMethod(t, declaringType, appdomain);
  396. res.genericArguments = genericArguments;
  397. return res;
  398. }
  399. public override string ToString()
  400. {
  401. if (def != null)
  402. return def.ToString();
  403. else
  404. return cDef.ToString();
  405. }
  406. public override int GetHashCode()
  407. {
  408. if (hashCode == -1)
  409. hashCode = System.Threading.Interlocked.Add(ref instance_id, 1);
  410. return hashCode;
  411. }
  412. bool? isExtend;
  413. public bool IsExtend
  414. {
  415. get
  416. {
  417. if (isExtend == null)
  418. {
  419. isExtend = this.IsExtendMethod();
  420. }
  421. return isExtend.Value;
  422. }
  423. }
  424. }
  425. }