ILMethod.cs 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Reflection;
  6. using ILRuntime.Mono.Cecil;
  7. using ILRuntime.Runtime.Intepreter.OpCodes;
  8. using ILRuntime.Runtime.Intepreter;
  9. using ILRuntime.Runtime.Debugger;
  10. using ILRuntime.CLR.TypeSystem;
  11. using ILRuntime.Reflection;
  12. namespace ILRuntime.CLR.Method
  13. {
  14. public class ILMethod : IMethod
  15. {
  16. OpCode[] body;
  17. MethodDefinition def;
  18. List<IType> parameters;
  19. ILRuntime.Runtime.Enviorment.AppDomain appdomain;
  20. ILType declaringType;
  21. ExceptionHandler[] exceptionHandler;
  22. KeyValuePair<string, IType>[] genericParameters;
  23. IType[] genericArguments;
  24. Dictionary<int, int[]> jumptables;
  25. bool isDelegateInvoke;
  26. ILRuntimeMethodInfo refletionMethodInfo;
  27. ILRuntimeConstructorInfo reflectionCtorInfo;
  28. int paramCnt, localVarCnt;
  29. Mono.Collections.Generic.Collection<Mono.Cecil.Cil.VariableDefinition> variables;
  30. int hashCode = -1;
  31. static int instance_id = 0x10000000;
  32. public MethodDefinition Definition { get { return def; } }
  33. public Dictionary<int, int[]> JumpTables { get { return jumptables; } }
  34. internal IDelegateAdapter DelegateAdapter { get; set; }
  35. internal int StartLine { get; set; }
  36. internal int EndLine { get; set; }
  37. public MethodInfo ReflectionMethodInfo
  38. {
  39. get
  40. {
  41. if (IsConstructor)
  42. throw new NotSupportedException();
  43. if (refletionMethodInfo == null)
  44. refletionMethodInfo = new ILRuntimeMethodInfo(this);
  45. return refletionMethodInfo;
  46. }
  47. }
  48. public ConstructorInfo ReflectionConstructorInfo
  49. {
  50. get
  51. {
  52. if (!IsConstructor)
  53. throw new NotSupportedException();
  54. if (reflectionCtorInfo == null)
  55. reflectionCtorInfo = new ILRuntimeConstructorInfo(this);
  56. return reflectionCtorInfo;
  57. }
  58. }
  59. internal ExceptionHandler[] ExceptionHandler
  60. {
  61. get
  62. {
  63. if (body == null)
  64. InitCodeBody();
  65. return exceptionHandler;
  66. }
  67. }
  68. public string Name
  69. {
  70. get
  71. {
  72. return def.Name;
  73. }
  74. }
  75. public IType DeclearingType
  76. {
  77. get
  78. {
  79. return declaringType;
  80. }
  81. }
  82. public bool HasThis
  83. {
  84. get
  85. {
  86. return def.HasThis;
  87. }
  88. }
  89. public int GenericParameterCount
  90. {
  91. get
  92. {
  93. if (IsGenericInstance)
  94. return 0;
  95. return def.GenericParameters.Count;
  96. }
  97. }
  98. public bool IsGenericInstance
  99. {
  100. get
  101. {
  102. return genericParameters != null;
  103. }
  104. }
  105. public Mono.Collections.Generic.Collection<Mono.Cecil.Cil.VariableDefinition> Variables
  106. {
  107. get
  108. {
  109. return variables;
  110. }
  111. }
  112. public KeyValuePair<string, IType>[] GenericArguments { get { return genericParameters; } }
  113. public IType[] GenericArugmentsArray { get { return genericArguments; } }
  114. public ILMethod(MethodDefinition def, ILType type, ILRuntime.Runtime.Enviorment.AppDomain domain)
  115. {
  116. this.def = def;
  117. declaringType = type;
  118. if (def.ReturnType.IsGenericParameter)
  119. {
  120. ReturnType = FindGenericArgument(def.ReturnType.Name);
  121. }
  122. else
  123. ReturnType = domain.GetType(def.ReturnType, type, this);
  124. if (type.IsDelegate && def.Name == "Invoke")
  125. isDelegateInvoke = true;
  126. this.appdomain = domain;
  127. paramCnt = def.HasParameters ? def.Parameters.Count : 0;
  128. #if DEBUG && !DISABLE_ILRUNTIME_DEBUG
  129. if (def.HasBody)
  130. {
  131. var sp = GetValidSequence(0, 1);
  132. if (sp != null)
  133. {
  134. StartLine = sp.StartLine;
  135. sp = GetValidSequence(def.Body.Instructions.Count - 1, -1);
  136. if (sp != null)
  137. {
  138. EndLine = sp.EndLine;
  139. }
  140. }
  141. }
  142. #endif
  143. }
  144. Mono.Cecil.Cil.SequencePoint GetValidSequence(int startIdx, int dir)
  145. {
  146. var seqMapping = def.DebugInformation.GetSequencePointMapping();
  147. var cur = DebugService.FindSequencePoint(def.Body.Instructions[startIdx], seqMapping);
  148. while (cur != null && cur.StartLine == 0x0feefee)
  149. {
  150. startIdx += dir;
  151. if (startIdx >= 0 && startIdx < def.Body.Instructions.Count)
  152. {
  153. cur = DebugService.FindSequencePoint(def.Body.Instructions[startIdx], seqMapping);
  154. }
  155. else
  156. break;
  157. }
  158. return cur;
  159. }
  160. public IType FindGenericArgument(string name)
  161. {
  162. IType res = declaringType.FindGenericArgument(name);
  163. if (res == null && genericParameters != null)
  164. {
  165. foreach (var i in genericParameters)
  166. {
  167. if (i.Key == name)
  168. return i.Value;
  169. }
  170. }
  171. else
  172. return res;
  173. return null;
  174. }
  175. internal OpCode[] Body
  176. {
  177. get
  178. {
  179. if (body == null)
  180. InitCodeBody();
  181. return body;
  182. }
  183. }
  184. public bool HasBody
  185. {
  186. get
  187. {
  188. return body != null;
  189. }
  190. }
  191. public int LocalVariableCount
  192. {
  193. get
  194. {
  195. return localVarCnt;
  196. }
  197. }
  198. public bool IsConstructor
  199. {
  200. get
  201. {
  202. return def.IsConstructor;
  203. }
  204. }
  205. public bool IsDelegateInvoke
  206. {
  207. get
  208. {
  209. return isDelegateInvoke;
  210. }
  211. }
  212. public bool IsStatic
  213. {
  214. get { return def.IsStatic; }
  215. }
  216. public int ParameterCount
  217. {
  218. get
  219. {
  220. return paramCnt;
  221. }
  222. }
  223. public List<IType> Parameters
  224. {
  225. get
  226. {
  227. if (def.HasParameters && parameters == null)
  228. {
  229. InitParameters();
  230. }
  231. return parameters;
  232. }
  233. }
  234. public IType ReturnType
  235. {
  236. get;
  237. private set;
  238. }
  239. public void Prewarm(bool recursive)
  240. {
  241. HashSet<ILMethod> alreadyPrewarmed = null;
  242. if (recursive)
  243. {
  244. alreadyPrewarmed = new HashSet<ILMethod>();
  245. }
  246. Prewarm(alreadyPrewarmed);
  247. }
  248. private void Prewarm(HashSet<ILMethod> alreadyPrewarmed)
  249. {
  250. if (alreadyPrewarmed != null && alreadyPrewarmed.Add(this) == false)
  251. return;
  252. if (GenericParameterCount > 0 && !IsGenericInstance)
  253. return;
  254. //当前方法用到的IType,提前InitializeMethods()。各个子调用,提前InitParameters()
  255. var body = Body;
  256. //当前方法用到的CLR局部变量,提前InitializeFields()、GetTypeFlags()
  257. for (int i = 0; i < LocalVariableCount; i++)
  258. {
  259. var v = Variables[i];
  260. var vt = v.VariableType;
  261. IType t;
  262. if (vt.IsGenericParameter)
  263. {
  264. t = FindGenericArgument(vt.Name);
  265. }
  266. else
  267. {
  268. t = appdomain.GetType(v.VariableType, DeclearingType, this);
  269. }
  270. if (t is CLRType ct)
  271. {
  272. var fields = ct.Fields;
  273. ILRuntime.CLR.Utils.Extensions.GetTypeFlags(ct.TypeForCLR);
  274. }
  275. }
  276. foreach (var ins in body)
  277. {
  278. switch (ins.Code)
  279. {
  280. case OpCodeEnum.Call:
  281. case OpCodeEnum.Newobj:
  282. case OpCodeEnum.Ldftn:
  283. case OpCodeEnum.Ldvirtftn:
  284. case OpCodeEnum.Callvirt:
  285. {
  286. var m = appdomain.GetMethod(ins.TokenInteger);
  287. if (m is ILMethod ilm)
  288. {
  289. //如果参数alreadyPrewarmed不为空,则不仅prewarm当前方法,还会递归prewarm所有子调用
  290. //如果参数alreadyPrewarmed为空,则只prewarm当前方法
  291. if (alreadyPrewarmed != null)
  292. {
  293. ilm.Prewarm(alreadyPrewarmed);
  294. }
  295. }
  296. else if (m is CLRMethod clrm)
  297. {
  298. ILRuntime.CLR.Utils.Extensions.GetTypeFlags(clrm.DeclearingType.TypeForCLR);
  299. }
  300. }
  301. break;
  302. case OpCodeEnum.Ldfld:
  303. case OpCodeEnum.Stfld:
  304. case OpCodeEnum.Ldflda:
  305. case OpCodeEnum.Ldsfld:
  306. case OpCodeEnum.Ldsflda:
  307. case OpCodeEnum.Stsfld:
  308. case OpCodeEnum.Ldtoken:
  309. {
  310. //提前InitializeBaseType()
  311. var t = appdomain.GetType((int)(ins.TokenLong >> 32));
  312. if (t != null)
  313. {
  314. var baseType = t.BaseType;
  315. }
  316. }
  317. break;
  318. }
  319. }
  320. }
  321. void InitCodeBody()
  322. {
  323. if (def.HasBody)
  324. {
  325. localVarCnt = def.Body.Variables.Count;
  326. body = new OpCode[def.Body.Instructions.Count];
  327. Dictionary<Mono.Cecil.Cil.Instruction, int> addr = new Dictionary<Mono.Cecil.Cil.Instruction, int>();
  328. for (int i = 0; i < body.Length; i++)
  329. {
  330. var c = def.Body.Instructions[i];
  331. OpCode code = new OpCode();
  332. code.Code = (OpCodeEnum)c.OpCode.Code;
  333. addr[c] = i;
  334. body[i] = code;
  335. }
  336. for (int i = 0; i < body.Length; i++)
  337. {
  338. var c = def.Body.Instructions[i];
  339. InitToken(ref body[i], c.Operand, addr);
  340. if (i > 0 && c.OpCode.Code == Mono.Cecil.Cil.Code.Callvirt && def.Body.Instructions[i - 1].OpCode.Code == Mono.Cecil.Cil.Code.Constrained)
  341. {
  342. body[i - 1].TokenLong = body[i].TokenInteger;
  343. }
  344. }
  345. for (int i = 0; i < def.Body.ExceptionHandlers.Count; i++)
  346. {
  347. var eh = def.Body.ExceptionHandlers[i];
  348. if (exceptionHandler == null)
  349. exceptionHandler = new Method.ExceptionHandler[def.Body.ExceptionHandlers.Count];
  350. ExceptionHandler e = new ExceptionHandler();
  351. e.HandlerStart = addr[eh.HandlerStart];
  352. e.HandlerEnd = addr[eh.HandlerEnd] - 1;
  353. e.TryStart = addr[eh.TryStart];
  354. e.TryEnd = addr[eh.TryEnd] - 1;
  355. switch (eh.HandlerType)
  356. {
  357. case Mono.Cecil.Cil.ExceptionHandlerType.Catch:
  358. e.CatchType = appdomain.GetType(eh.CatchType, declaringType, this);
  359. e.HandlerType = ExceptionHandlerType.Catch;
  360. break;
  361. case Mono.Cecil.Cil.ExceptionHandlerType.Finally:
  362. e.HandlerType = ExceptionHandlerType.Finally;
  363. break;
  364. case Mono.Cecil.Cil.ExceptionHandlerType.Fault:
  365. e.HandlerType = ExceptionHandlerType.Fault;
  366. break;
  367. default:
  368. throw new NotImplementedException();
  369. }
  370. exceptionHandler[i] = e;
  371. //Mono.Cecil.Cil.ExceptionHandlerType.
  372. }
  373. //Release Method body to save memory
  374. variables = def.Body.Variables;
  375. def.Body = null;
  376. }
  377. else
  378. body = new OpCode[0];
  379. }
  380. unsafe void InitToken(ref OpCode code, object token, Dictionary<Mono.Cecil.Cil.Instruction, int> addr)
  381. {
  382. switch (code.Code)
  383. {
  384. case OpCodeEnum.Leave:
  385. case OpCodeEnum.Leave_S:
  386. case OpCodeEnum.Br:
  387. case OpCodeEnum.Br_S:
  388. case OpCodeEnum.Brtrue:
  389. case OpCodeEnum.Brtrue_S:
  390. case OpCodeEnum.Brfalse:
  391. case OpCodeEnum.Brfalse_S:
  392. //比较流程控制
  393. case OpCodeEnum.Beq:
  394. case OpCodeEnum.Beq_S:
  395. case OpCodeEnum.Bne_Un:
  396. case OpCodeEnum.Bne_Un_S:
  397. case OpCodeEnum.Bge:
  398. case OpCodeEnum.Bge_S:
  399. case OpCodeEnum.Bge_Un:
  400. case OpCodeEnum.Bge_Un_S:
  401. case OpCodeEnum.Bgt:
  402. case OpCodeEnum.Bgt_S:
  403. case OpCodeEnum.Bgt_Un:
  404. case OpCodeEnum.Bgt_Un_S:
  405. case OpCodeEnum.Ble:
  406. case OpCodeEnum.Ble_S:
  407. case OpCodeEnum.Ble_Un:
  408. case OpCodeEnum.Ble_Un_S:
  409. case OpCodeEnum.Blt:
  410. case OpCodeEnum.Blt_S:
  411. case OpCodeEnum.Blt_Un:
  412. case OpCodeEnum.Blt_Un_S:
  413. code.TokenInteger = addr[(Mono.Cecil.Cil.Instruction)token];
  414. break;
  415. case OpCodeEnum.Ldc_I4:
  416. code.TokenInteger = (int)token;
  417. break;
  418. case OpCodeEnum.Ldc_I4_S:
  419. code.TokenInteger = (sbyte)token;
  420. break;
  421. case OpCodeEnum.Ldc_I8:
  422. code.TokenLong = (long)token;
  423. break;
  424. case OpCodeEnum.Ldc_R4:
  425. {
  426. float val = (float)token;
  427. code.TokenInteger = *(int*)&val;
  428. }
  429. break;
  430. case OpCodeEnum.Ldc_R8:
  431. {
  432. double val = (double)token;
  433. code.TokenLong = *(long*)&val;
  434. }
  435. break;
  436. case OpCodeEnum.Stloc:
  437. case OpCodeEnum.Stloc_S:
  438. case OpCodeEnum.Ldloc:
  439. case OpCodeEnum.Ldloc_S:
  440. case OpCodeEnum.Ldloca:
  441. case OpCodeEnum.Ldloca_S:
  442. {
  443. Mono.Cecil.Cil.VariableDefinition vd = (Mono.Cecil.Cil.VariableDefinition)token;
  444. code.TokenInteger = vd.Index;
  445. }
  446. break;
  447. case OpCodeEnum.Ldarg_S:
  448. case OpCodeEnum.Ldarg:
  449. case OpCodeEnum.Ldarga:
  450. case OpCodeEnum.Ldarga_S:
  451. case OpCodeEnum.Starg:
  452. case OpCodeEnum.Starg_S:
  453. {
  454. Mono.Cecil.ParameterDefinition vd = (Mono.Cecil.ParameterDefinition)token;
  455. code.TokenInteger = vd.Index;
  456. if (HasThis)
  457. code.TokenInteger++;
  458. }
  459. break;
  460. case OpCodeEnum.Call:
  461. case OpCodeEnum.Newobj:
  462. case OpCodeEnum.Ldftn:
  463. case OpCodeEnum.Ldvirtftn:
  464. case OpCodeEnum.Callvirt:
  465. {
  466. bool invalidToken;
  467. var m = appdomain.GetMethod(token, declaringType, this, out invalidToken);
  468. if (m != null)
  469. {
  470. if(code.Code == OpCodeEnum.Callvirt && m is ILMethod)
  471. {
  472. ILMethod ilm = (ILMethod)m;
  473. if (!ilm.def.IsAbstract && !ilm.def.IsVirtual && !ilm.DeclearingType.IsInterface)
  474. code.Code = OpCodeEnum.Call;
  475. }
  476. if (invalidToken)
  477. code.TokenInteger = m.GetHashCode();
  478. else
  479. code.TokenInteger = token.GetHashCode();
  480. }
  481. else
  482. {
  483. //Cannot find method or the method is dummy
  484. MethodReference _ref = (MethodReference)token;
  485. int paramCnt = _ref.HasParameters ? _ref.Parameters.Count : 0;
  486. if (_ref.HasThis)
  487. paramCnt++;
  488. code.TokenLong = paramCnt;
  489. }
  490. }
  491. break;
  492. case OpCodeEnum.Constrained:
  493. case OpCodeEnum.Box:
  494. case OpCodeEnum.Unbox_Any:
  495. case OpCodeEnum.Unbox:
  496. case OpCodeEnum.Initobj:
  497. case OpCodeEnum.Isinst:
  498. case OpCodeEnum.Newarr:
  499. case OpCodeEnum.Stobj:
  500. case OpCodeEnum.Ldobj:
  501. {
  502. code.TokenInteger = GetTypeTokenHashCode(token);
  503. }
  504. break;
  505. case OpCodeEnum.Stfld:
  506. case OpCodeEnum.Ldfld:
  507. case OpCodeEnum.Ldflda:
  508. {
  509. code.TokenLong = appdomain.GetStaticFieldIndex(token, declaringType, this);
  510. }
  511. break;
  512. case OpCodeEnum.Stsfld:
  513. case OpCodeEnum.Ldsfld:
  514. case OpCodeEnum.Ldsflda:
  515. {
  516. code.TokenLong = appdomain.GetStaticFieldIndex(token, declaringType, this);
  517. }
  518. break;
  519. case OpCodeEnum.Ldstr:
  520. {
  521. long hashCode = appdomain.CacheString(token);
  522. code.TokenLong = hashCode;
  523. }
  524. break;
  525. case OpCodeEnum.Ldtoken:
  526. {
  527. if (token is FieldReference)
  528. {
  529. code.TokenInteger = 0;
  530. code.TokenLong = appdomain.GetStaticFieldIndex(token, declaringType, this);
  531. }
  532. else if (token is TypeReference)
  533. {
  534. code.TokenInteger = 1;
  535. code.TokenLong = GetTypeTokenHashCode(token);
  536. }
  537. else
  538. throw new NotImplementedException();
  539. }
  540. break;
  541. case OpCodeEnum.Switch:
  542. {
  543. PrepareJumpTable(token, addr);
  544. code.TokenInteger = token.GetHashCode();
  545. }
  546. break;
  547. }
  548. }
  549. int GetTypeTokenHashCode(object token)
  550. {
  551. var t = appdomain.GetType(token, declaringType, this);
  552. bool isGenericParameter = CheckHasGenericParamter(token);
  553. if (t == null && isGenericParameter)
  554. {
  555. t = FindGenericArgument(((TypeReference)token).Name);
  556. }
  557. if (t != null)
  558. {
  559. if (t is ILType || isGenericParameter)
  560. {
  561. return t.GetHashCode();
  562. }
  563. else
  564. return token.GetHashCode();
  565. }
  566. return 0;
  567. }
  568. bool CheckHasGenericParamter(object token)
  569. {
  570. if (token is TypeReference)
  571. {
  572. TypeReference _ref = ((TypeReference)token);
  573. if (_ref.IsArray)
  574. return CheckHasGenericParamter(((ArrayType)_ref).ElementType);
  575. if (_ref.IsGenericParameter)
  576. return true;
  577. if (_ref.IsGenericInstance)
  578. {
  579. GenericInstanceType gi = (GenericInstanceType)_ref;
  580. foreach(var i in gi.GenericArguments)
  581. {
  582. if (CheckHasGenericParamter(i))
  583. return true;
  584. }
  585. return false;
  586. }
  587. else
  588. return false;
  589. }
  590. else
  591. return false;
  592. }
  593. void PrepareJumpTable(object token, Dictionary<Mono.Cecil.Cil.Instruction, int> addr)
  594. {
  595. int hashCode = token.GetHashCode();
  596. if (jumptables == null)
  597. jumptables = new Dictionary<int, int[]>();
  598. if (jumptables.ContainsKey(hashCode))
  599. return;
  600. Mono.Cecil.Cil.Instruction[] e = token as Mono.Cecil.Cil.Instruction[];
  601. int[] addrs = new int[e.Length];
  602. for (int i = 0; i < e.Length; i++)
  603. {
  604. addrs[i] = addr[e[i]];
  605. }
  606. jumptables[hashCode] = addrs;
  607. }
  608. void InitParameters()
  609. {
  610. parameters = new List<IType>();
  611. foreach (var i in def.Parameters)
  612. {
  613. IType type = null;
  614. bool isByRef = false;
  615. bool isArray = false;
  616. int rank = 1;
  617. TypeReference pt = i.ParameterType;
  618. if (pt.IsByReference)
  619. {
  620. isByRef = true;
  621. pt = ((ByReferenceType)pt).ElementType;
  622. }
  623. if (pt.IsArray)
  624. {
  625. isArray = true;
  626. rank = ((ArrayType)pt).Rank;
  627. pt = ((ArrayType)pt).ElementType;
  628. }
  629. if (pt.IsGenericParameter)
  630. {
  631. type = FindGenericArgument(pt.Name);
  632. if (type == null && def.HasGenericParameters)
  633. {
  634. bool found = false;
  635. foreach (var j in def.GenericParameters)
  636. {
  637. if (j.Name == pt.Name)
  638. {
  639. found = true;
  640. break;
  641. }
  642. }
  643. if (found)
  644. {
  645. type = new ILGenericParameterType(pt.Name);
  646. }
  647. else
  648. throw new NotSupportedException("Cannot find Generic Parameter " + pt.Name + " in " + def.FullName);
  649. }
  650. }
  651. else
  652. type = appdomain.GetType(pt, declaringType, this);
  653. if (isArray)
  654. type = type.MakeArrayType(rank);
  655. if (isByRef)
  656. type = type.MakeByRefType();
  657. parameters.Add(type);
  658. }
  659. }
  660. public IMethod MakeGenericMethod(IType[] genericArguments)
  661. {
  662. KeyValuePair<string, IType>[] genericParameters = new KeyValuePair<string, IType>[genericArguments.Length];
  663. for (int i = 0; i < genericArguments.Length; i++)
  664. {
  665. string name = def.GenericParameters[i].Name;
  666. IType val = genericArguments[i];
  667. genericParameters[i] = new KeyValuePair<string, IType>(name, val);
  668. }
  669. ILMethod m = new ILMethod(def, declaringType, appdomain);
  670. m.genericParameters = genericParameters;
  671. m.genericArguments = genericArguments;
  672. if (m.def.ReturnType.IsGenericParameter)
  673. {
  674. m.ReturnType = m.FindGenericArgument(m.def.ReturnType.Name);
  675. }
  676. return m;
  677. }
  678. string cachedName;
  679. public override string ToString()
  680. {
  681. if (cachedName == null)
  682. {
  683. StringBuilder sb = new StringBuilder();
  684. sb.Append(declaringType.FullName);
  685. sb.Append('.');
  686. sb.Append(Name);
  687. sb.Append('(');
  688. bool isFirst = true;
  689. if (parameters == null)
  690. InitParameters();
  691. for (int i = 0; i < parameters.Count; i++)
  692. {
  693. if (isFirst)
  694. isFirst = false;
  695. else
  696. sb.Append(", ");
  697. sb.Append(parameters[i].Name);
  698. sb.Append(' ');
  699. sb.Append(def.Parameters[i].Name);
  700. }
  701. sb.Append(')');
  702. cachedName = sb.ToString();
  703. }
  704. return cachedName;
  705. }
  706. public override int GetHashCode()
  707. {
  708. if (hashCode == -1)
  709. hashCode = System.Threading.Interlocked.Add(ref instance_id, 1);
  710. return hashCode;
  711. }
  712. }
  713. }