aboutsummaryrefslogtreecommitdiff
path: root/ChocolArm64/ATranslatedSub.cs
diff options
context:
space:
mode:
authorgdkchan <gab.dark.100@gmail.com>2018-03-04 14:09:59 -0300
committerGitHub <noreply@github.com>2018-03-04 14:09:59 -0300
commit3edb66f389ac279bdcde26c5682aa39b9bf5f853 (patch)
treeb3082b45648417a289ba10c2b40f6c134b93fa98 /ChocolArm64/ATranslatedSub.cs
parentee9df32e3e13fe982c8154a6454566c8edfa13d3 (diff)
Improve CPU initial translation speeds (#50)
* Add background translation to the CPU * Do not use a separate thread for translation, implement 2 tiers translation * Remove unnecessary usings * Lower MinCallCountForReJit * Remove unused variable
Diffstat (limited to 'ChocolArm64/ATranslatedSub.cs')
-rw-r--r--ChocolArm64/ATranslatedSub.cs92
1 files changed, 61 insertions, 31 deletions
diff --git a/ChocolArm64/ATranslatedSub.cs b/ChocolArm64/ATranslatedSub.cs
index 71a6793a..414038ab 100644
--- a/ChocolArm64/ATranslatedSub.cs
+++ b/ChocolArm64/ATranslatedSub.cs
@@ -2,6 +2,7 @@ using ChocolArm64.Memory;
using ChocolArm64.State;
using System;
using System.Collections.Generic;
+using System.Collections.ObjectModel;
using System.Reflection;
using System.Reflection.Emit;
@@ -13,35 +14,47 @@ namespace ChocolArm64
private AA64Subroutine ExecDelegate;
- private bool HasDelegate;
-
- public static Type[] FixedArgTypes { get; private set; }
-
public static int StateArgIdx { get; private set; }
public static int MemoryArgIdx { get; private set; }
+ public static Type[] FixedArgTypes { get; private set; }
+
public DynamicMethod Method { get; private set; }
- public HashSet<long> SubCalls { get; private set; }
+ public ReadOnlyCollection<ARegister> Params { get; private set; }
- public List<ARegister> Params { get; private set; }
+ private HashSet<long> Callees;
- public bool NeedsReJit { get; private set; }
+ private ATranslatedSubType Type;
- public ATranslatedSub()
- {
- SubCalls = new HashSet<long>();
- }
+ private int CallCount;
+
+ private bool NeedsReJit;
+
+ private int MinCallCountForReJit = 250;
- public ATranslatedSub(DynamicMethod Method, List<ARegister> Params) : this()
+ public ATranslatedSub(DynamicMethod Method, List<ARegister> Params, HashSet<long> Callees)
{
+ if (Method == null)
+ {
+ throw new ArgumentNullException(nameof(Method));
+ }
+
if (Params == null)
{
throw new ArgumentNullException(nameof(Params));
}
- this.Method = Method;
- this.Params = Params;
+ if (Callees == null)
+ {
+ throw new ArgumentNullException(nameof(Callees));
+ }
+
+ this.Method = Method;
+ this.Params = Params.AsReadOnly();
+ this.Callees = Callees;
+
+ PrepareDelegate();
}
static ATranslatedSub()
@@ -69,36 +82,53 @@ namespace ChocolArm64
}
}
- public long Execute(AThreadState ThreadState, AMemory Memory)
+ private void PrepareDelegate()
{
- if (!HasDelegate)
- {
- string Name = $"{Method.Name}_Dispatch";
+ string Name = $"{Method.Name}_Dispatch";
- DynamicMethod Mthd = new DynamicMethod(Name, typeof(long), FixedArgTypes);
+ DynamicMethod Mthd = new DynamicMethod(Name, typeof(long), FixedArgTypes);
- ILGenerator Generator = Mthd.GetILGenerator();
+ ILGenerator Generator = Mthd.GetILGenerator();
- Generator.EmitLdargSeq(FixedArgTypes.Length);
+ Generator.EmitLdargSeq(FixedArgTypes.Length);
- foreach (ARegister Reg in Params)
- {
- Generator.EmitLdarg(StateArgIdx);
+ foreach (ARegister Reg in Params)
+ {
+ Generator.EmitLdarg(StateArgIdx);
- Generator.Emit(OpCodes.Ldfld, Reg.GetField());
- }
+ Generator.Emit(OpCodes.Ldfld, Reg.GetField());
+ }
- Generator.Emit(OpCodes.Call, Method);
- Generator.Emit(OpCodes.Ret);
+ Generator.Emit(OpCodes.Call, Method);
+ Generator.Emit(OpCodes.Ret);
- ExecDelegate = (AA64Subroutine)Mthd.CreateDelegate(typeof(AA64Subroutine));
+ ExecDelegate = (AA64Subroutine)Mthd.CreateDelegate(typeof(AA64Subroutine));
+ }
- HasDelegate = true;
+ public bool ShouldReJit()
+ {
+ if (Type == ATranslatedSubType.SubTier0)
+ {
+ if (CallCount < MinCallCountForReJit)
+ {
+ CallCount++;
+ }
+
+ return CallCount == MinCallCountForReJit;
}
+ return Type == ATranslatedSubType.SubTier1 && NeedsReJit;
+ }
+
+ public long Execute(AThreadState ThreadState, AMemory Memory)
+ {
return ExecDelegate(ThreadState, Memory);
}
- public void MarkForReJit() => NeedsReJit = true;
+ public void SetType(ATranslatedSubType Type) => this.Type = Type;
+
+ public bool HasCallee(long Position) => Callees.Contains(Position);
+
+ public void MarkForReJit() => NeedsReJit = true;
}
} \ No newline at end of file