|
|
@@ -24,11 +24,12 @@ namespace ARMeilleure.Translation.PTC
|
|
|
{
|
|
|
private const string OuterHeaderMagicString = "Pohd\0\0\0\0";
|
|
|
|
|
|
- private const uint InternalVersion = 5518; //! Not to be incremented manually for each change to the ARMeilleure project.
|
|
|
+ private const uint InternalVersion = 7007; //! Not to be incremented manually for each change to the ARMeilleure project.
|
|
|
|
|
|
- private static readonly uint[] _migrateInternalVersions =
|
|
|
+ private static readonly uint[] _migrateInternalVersions =
|
|
|
[
|
|
|
- 1866
|
|
|
+ 1866,
|
|
|
+ 5518,
|
|
|
];
|
|
|
|
|
|
private const int SaveInterval = 30; // Seconds.
|
|
|
@@ -77,20 +78,30 @@ namespace ARMeilleure.Translation.PTC
|
|
|
private void TimerElapsed(object _, ElapsedEventArgs __)
|
|
|
=> new Thread(PreSave) { Name = "Ptc.DiskWriter" }.Start();
|
|
|
|
|
|
- public void AddEntry(ulong address, ExecutionMode mode, bool highCq)
|
|
|
+ public void AddEntry(ulong address, ExecutionMode mode, bool highCq, bool blacklist = false)
|
|
|
{
|
|
|
if (IsAddressInStaticCodeRange(address))
|
|
|
{
|
|
|
Debug.Assert(!highCq);
|
|
|
|
|
|
- lock (_lock)
|
|
|
+ if (blacklist)
|
|
|
{
|
|
|
- ProfiledFuncs.TryAdd(address, new FuncProfile(mode, highCq: false));
|
|
|
+ lock (_lock)
|
|
|
+ {
|
|
|
+ ProfiledFuncs[address] = new FuncProfile(mode, highCq: false, true);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ lock (_lock)
|
|
|
+ {
|
|
|
+ ProfiledFuncs.TryAdd(address, new FuncProfile(mode, highCq: false, false));
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- public void UpdateEntry(ulong address, ExecutionMode mode, bool highCq)
|
|
|
+ public void UpdateEntry(ulong address, ExecutionMode mode, bool highCq, bool? blacklist = null)
|
|
|
{
|
|
|
if (IsAddressInStaticCodeRange(address))
|
|
|
{
|
|
|
@@ -100,7 +111,7 @@ namespace ARMeilleure.Translation.PTC
|
|
|
{
|
|
|
Debug.Assert(ProfiledFuncs.ContainsKey(address));
|
|
|
|
|
|
- ProfiledFuncs[address] = new FuncProfile(mode, highCq: true);
|
|
|
+ ProfiledFuncs[address] = new FuncProfile(mode, highCq: true, blacklist ?? ProfiledFuncs[address].Blacklist);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
@@ -116,7 +127,7 @@ namespace ARMeilleure.Translation.PTC
|
|
|
|
|
|
foreach (KeyValuePair<ulong, FuncProfile> profiledFunc in ProfiledFuncs)
|
|
|
{
|
|
|
- if (!funcs.ContainsKey(profiledFunc.Key))
|
|
|
+ if (!funcs.ContainsKey(profiledFunc.Key) && !profiledFunc.Value.Blacklist)
|
|
|
{
|
|
|
profiledFuncsToTranslate.Enqueue((profiledFunc.Key, profiledFunc.Value));
|
|
|
}
|
|
|
@@ -131,6 +142,24 @@ namespace ARMeilleure.Translation.PTC
|
|
|
ProfiledFuncs.TrimExcess();
|
|
|
}
|
|
|
|
|
|
+ public List<ulong> GetBlacklistedFunctions()
|
|
|
+ {
|
|
|
+ List<ulong> funcs = new List<ulong>();
|
|
|
+
|
|
|
+ foreach (var profiledFunc in ProfiledFuncs)
|
|
|
+ {
|
|
|
+ if (profiledFunc.Value.Blacklist)
|
|
|
+ {
|
|
|
+ if (!funcs.Contains(profiledFunc.Key))
|
|
|
+ {
|
|
|
+ funcs.Add(profiledFunc.Key);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return funcs;
|
|
|
+ }
|
|
|
+
|
|
|
public void PreLoad()
|
|
|
{
|
|
|
_lastHash = default;
|
|
|
@@ -221,13 +250,18 @@ namespace ARMeilleure.Translation.PTC
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
+ Func<ulong, FuncProfile, (ulong, FuncProfile)> migrateEntryFunc = null;
|
|
|
+
|
|
|
switch (outerHeader.InfoFileVersion)
|
|
|
{
|
|
|
case InternalVersion:
|
|
|
ProfiledFuncs = Deserialize(stream);
|
|
|
break;
|
|
|
case 1866:
|
|
|
- ProfiledFuncs = Deserialize(stream, (address, profile) => (address + 0x500000UL, profile));
|
|
|
+ migrateEntryFunc = (address, profile) => (address + 0x500000UL, profile);
|
|
|
+ goto case 5518;
|
|
|
+ case 5518:
|
|
|
+ ProfiledFuncs = DeserializeAddBlacklist(stream, migrateEntryFunc);
|
|
|
break;
|
|
|
default:
|
|
|
Logger.Error?.Print(LogClass.Ptc, $"No migration path for {nameof(outerHeader.InfoFileVersion)} '{outerHeader.InfoFileVersion}'. Discarding cache.");
|
|
|
@@ -257,6 +291,16 @@ namespace ARMeilleure.Translation.PTC
|
|
|
return DeserializeDictionary<ulong, FuncProfile>(stream, DeserializeStructure<FuncProfile>);
|
|
|
}
|
|
|
|
|
|
+ private static Dictionary<ulong, FuncProfile> DeserializeAddBlacklist(Stream stream, Func<ulong, FuncProfile, (ulong, FuncProfile)> migrateEntryFunc = null)
|
|
|
+ {
|
|
|
+ if (migrateEntryFunc != null)
|
|
|
+ {
|
|
|
+ return DeserializeAndUpdateDictionary(stream, (Stream stream) => { return new FuncProfile(DeserializeStructure<FuncProfilePreBlacklist>(stream)); }, migrateEntryFunc);
|
|
|
+ }
|
|
|
+
|
|
|
+ return DeserializeDictionary<ulong, FuncProfile>(stream, (Stream stream) => { return new FuncProfile(DeserializeStructure<FuncProfilePreBlacklist>(stream)); });
|
|
|
+ }
|
|
|
+
|
|
|
private static ReadOnlySpan<byte> GetReadOnlySpan(MemoryStream memoryStream)
|
|
|
{
|
|
|
return new(memoryStream.GetBuffer(), (int)memoryStream.Position, (int)memoryStream.Length - (int)memoryStream.Position);
|
|
|
@@ -388,13 +432,35 @@ namespace ARMeilleure.Translation.PTC
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- [StructLayout(LayoutKind.Sequential, Pack = 1/*, Size = 5*/)]
|
|
|
+ [StructLayout(LayoutKind.Sequential, Pack = 1/*, Size = 6*/)]
|
|
|
public struct FuncProfile
|
|
|
+ {
|
|
|
+ public ExecutionMode Mode;
|
|
|
+ public bool HighCq;
|
|
|
+ public bool Blacklist;
|
|
|
+
|
|
|
+ public FuncProfile(ExecutionMode mode, bool highCq, bool blacklist)
|
|
|
+ {
|
|
|
+ Mode = mode;
|
|
|
+ HighCq = highCq;
|
|
|
+ Blacklist = blacklist;
|
|
|
+ }
|
|
|
+
|
|
|
+ public FuncProfile(FuncProfilePreBlacklist fp)
|
|
|
+ {
|
|
|
+ Mode = fp.Mode;
|
|
|
+ HighCq = fp.HighCq;
|
|
|
+ Blacklist = false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ [StructLayout(LayoutKind.Sequential, Pack = 1/*, Size = 5*/)]
|
|
|
+ public struct FuncProfilePreBlacklist
|
|
|
{
|
|
|
public ExecutionMode Mode;
|
|
|
public bool HighCq;
|
|
|
|
|
|
- public FuncProfile(ExecutionMode mode, bool highCq)
|
|
|
+ public FuncProfilePreBlacklist(ExecutionMode mode, bool highCq)
|
|
|
{
|
|
|
Mode = mode;
|
|
|
HighCq = highCq;
|