TranslatedSub.cs 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. using ChocolArm64.Memory;
  2. using ChocolArm64.State;
  3. using System;
  4. using System.Reflection;
  5. using System.Reflection.Emit;
  6. namespace ChocolArm64.Translation
  7. {
  8. delegate long ArmSubroutine(CpuThreadState state, MemoryManager memory);
  9. class TranslatedSub
  10. {
  11. //This is the minimum amount of calls needed for the method
  12. //to be retranslated with higher quality code. It's only worth
  13. //doing that for hot code.
  14. private const int MinCallCountForOpt = 30;
  15. public ArmSubroutine Delegate { get; private set; }
  16. public static int StateArgIdx { get; }
  17. public static int MemoryArgIdx { get; }
  18. public static Type[] FixedArgTypes { get; }
  19. public DynamicMethod Method { get; }
  20. public TranslationTier Tier { get; }
  21. public long IntNiRegsMask { get; }
  22. public long VecNiRegsMask { get; }
  23. private bool _isWorthOptimizing;
  24. private int _callCount;
  25. public TranslatedSub(
  26. DynamicMethod method,
  27. long intNiRegsMask,
  28. long vecNiRegsMask,
  29. TranslationTier tier,
  30. bool isWorthOptimizing)
  31. {
  32. Method = method ?? throw new ArgumentNullException(nameof(method));;
  33. IntNiRegsMask = intNiRegsMask;
  34. VecNiRegsMask = vecNiRegsMask;
  35. _isWorthOptimizing = isWorthOptimizing;
  36. Tier = tier;
  37. }
  38. static TranslatedSub()
  39. {
  40. MethodInfo mthdInfo = typeof(ArmSubroutine).GetMethod("Invoke");
  41. ParameterInfo[] Params = mthdInfo.GetParameters();
  42. FixedArgTypes = new Type[Params.Length];
  43. for (int index = 0; index < Params.Length; index++)
  44. {
  45. Type argType = Params[index].ParameterType;
  46. FixedArgTypes[index] = argType;
  47. if (argType == typeof(CpuThreadState))
  48. {
  49. StateArgIdx = index;
  50. }
  51. else if (argType == typeof(MemoryManager))
  52. {
  53. MemoryArgIdx = index;
  54. }
  55. }
  56. }
  57. public void PrepareMethod()
  58. {
  59. Delegate = (ArmSubroutine)Method.CreateDelegate(typeof(ArmSubroutine));
  60. }
  61. public long Execute(CpuThreadState threadState, MemoryManager memory)
  62. {
  63. return Delegate(threadState, memory);
  64. }
  65. public bool IsWorthOptimizing()
  66. {
  67. if (!_isWorthOptimizing)
  68. {
  69. return false;
  70. }
  71. if (_callCount++ < MinCallCountForOpt)
  72. {
  73. return false;
  74. }
  75. //Only return true once, so that it is
  76. //added to the queue only once.
  77. _isWorthOptimizing = false;
  78. return true;
  79. }
  80. }
  81. }