Optimizer.InlineMethod.cs 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using ILRuntime.Mono.Cecil;
  6. using ILRuntime.Mono.Cecil.Cil;
  7. using ILRuntime.CLR.TypeSystem;
  8. using ILRuntime.CLR.Method;
  9. using ILRuntime.Runtime.Intepreter.OpCodes;
  10. namespace ILRuntime.Runtime.Intepreter.RegisterVM
  11. {
  12. partial class Optimizer
  13. {
  14. public const int MaximalInlineInstructionCount = 20;
  15. public static void InlineMethod(CodeBasicBlock block, ILMethod method, RegisterVMSymbolLink symbolLink, ref Dictionary<int, int[]> jumpTables, short baseRegIdx, bool hasReturn)
  16. {
  17. var ins = block.FinalInstructions;
  18. var body = method.BodyRegister;
  19. OpCodeR start = new OpCodeR();
  20. start.Code = OpCodeREnum.InlineStart;
  21. ins.Add(start);
  22. int branchStart = ins.Count;
  23. int branchOffset = 0;
  24. List<int> reloc = new List<int>();
  25. if (body != null)
  26. {
  27. for (int i = 0; i < body.Length; i++)
  28. {
  29. var opcode = body[i];
  30. short r1 = 0;
  31. short r2 = 0;
  32. short r3 = 0;
  33. if (GetOpcodeSourceRegister(ref opcode, hasReturn, out r1, out r2, out r3))
  34. {
  35. if (r1 >= 0)
  36. {
  37. ReplaceOpcodeSource(ref opcode, 0, (short)(r1 + baseRegIdx));
  38. }
  39. if (r2 >= 0)
  40. {
  41. ReplaceOpcodeSource(ref opcode, 1, (short)(r2 + baseRegIdx));
  42. }
  43. if (r3 >= 0)
  44. {
  45. ReplaceOpcodeSource(ref opcode, 2, (short)(r3 + baseRegIdx));
  46. }
  47. }
  48. if (GetOpcodeDestRegister(ref opcode, out r1))
  49. {
  50. if (r1 >= 0)
  51. ReplaceOpcodeDest(ref opcode, (short)(r1 + baseRegIdx));
  52. }
  53. if (opcode.Code == OpCodeREnum.Ret)
  54. {
  55. bool needMove = hasReturn && opcode.Register1 != baseRegIdx;
  56. if (needMove)
  57. {
  58. opcode.Code = OpCodeREnum.Move;
  59. opcode.Register2 = opcode.Register1;
  60. opcode.Register1 = baseRegIdx;
  61. ins.Add(opcode);
  62. branchOffset++;
  63. }
  64. if (i < body.Length - 1)
  65. {
  66. if (needMove)
  67. {
  68. for (int j = branchStart; j < ins.Count; j++)
  69. {
  70. var op2 = ins[j];
  71. if (IsBranching(op2.Code))
  72. {
  73. if (op2.Operand > i)
  74. {
  75. op2.Operand++;
  76. ins[j] = op2;
  77. }
  78. }
  79. else if (IsIntermediateBranching(op2.Code))
  80. {
  81. if (op2.Operand4 > i)
  82. {
  83. op2.Operand4++;
  84. ins[j] = op2;
  85. }
  86. }
  87. else if(op2.Code == OpCodeREnum.Switch)
  88. {
  89. var targets = jumpTables[op2.Operand];
  90. for(int k = 0; k < targets.Length; k++)
  91. {
  92. if (targets[k] > i)
  93. targets[k]++;
  94. }
  95. }
  96. }
  97. }
  98. reloc.Add(ins.Count);
  99. opcode.Code = OpCodeREnum.Br;
  100. ins.Add(opcode);
  101. }
  102. continue;
  103. }
  104. if (IsBranching(opcode.Code))
  105. {
  106. opcode.Operand += branchOffset;
  107. }
  108. if (opcode.Code == OpCodeREnum.Switch)
  109. {
  110. int[] targets = method.JumpTablesRegister[opcode.Operand];
  111. int[] newTargets = new int[targets.Length];
  112. for (int j = 0; j < targets.Length; j++)
  113. {
  114. newTargets[j] = targets[j] + branchOffset;
  115. }
  116. if (jumpTables == null)
  117. jumpTables = new Dictionary<int, int[]>();
  118. opcode.Operand = newTargets.GetHashCode();
  119. jumpTables.Add(opcode.Operand, newTargets);
  120. }
  121. #if DEBUG && !DISABLE_ILRUNTIME_DEBUG
  122. RegisterVMSymbol oriIns;
  123. if (method.RegisterVMSymbols.TryGetValue(i, out oriIns))
  124. {
  125. oriIns.ParentSymbol = symbolLink;
  126. block.InstructionMapping.Add(ins.Count, oriIns);
  127. }
  128. #endif
  129. ins.Add(opcode);
  130. }
  131. }
  132. foreach (var i in reloc)
  133. {
  134. var opcode = ins[i];
  135. opcode.Operand = ins.Count - branchStart;
  136. ins[i] = opcode;
  137. }
  138. start.Code = OpCodeREnum.InlineEnd;
  139. ins.Add(start);
  140. }
  141. }
  142. }