Added a simple PtcFormatter library for deserialization/serialization, which does not require reflection, in use at PtcJumpTable and PtcProfiler; improves maintainability and simplicity/readability of affected code.
This commit is contained in:
parent
18f576f49d
commit
8b9c28ac7d
6 changed files with 171 additions and 203 deletions
|
@ -1,6 +1,6 @@
|
||||||
namespace ARMeilleure.State
|
namespace ARMeilleure.State
|
||||||
{
|
{
|
||||||
enum ExecutionMode
|
enum ExecutionMode : int
|
||||||
{
|
{
|
||||||
Aarch32Arm = 0,
|
Aarch32Arm = 0,
|
||||||
Aarch32Thumb = 1,
|
Aarch32Thumb = 1,
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
using ARMeilleure.Diagnostics;
|
using ARMeilleure.Diagnostics;
|
||||||
using ARMeilleure.IntermediateRepresentation;
|
using ARMeilleure.IntermediateRepresentation;
|
||||||
using ARMeilleure.State;
|
using ARMeilleure.State;
|
||||||
|
using ARMeilleure.Translation.PTC;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
@ -9,8 +10,6 @@ using static ARMeilleure.IntermediateRepresentation.OperandHelper;
|
||||||
|
|
||||||
namespace ARMeilleure.Translation
|
namespace ARMeilleure.Translation
|
||||||
{
|
{
|
||||||
using PTC;
|
|
||||||
|
|
||||||
class EmitterContext
|
class EmitterContext
|
||||||
{
|
{
|
||||||
private readonly Dictionary<Operand, BasicBlock> _irLabels;
|
private readonly Dictionary<Operand, BasicBlock> _irLabels;
|
||||||
|
|
|
@ -549,7 +549,7 @@ namespace ARMeilleure.Translation.PTC
|
||||||
SkipReloc(infoEntry.RelocEntriesCount);
|
SkipReloc(infoEntry.RelocEntriesCount);
|
||||||
SkipUnwindInfo(unwindInfosReader);
|
SkipUnwindInfo(unwindInfosReader);
|
||||||
}
|
}
|
||||||
else if (infoEntry.HighCq || !PtcProfiler.ProfiledFuncs.TryGetValue(infoEntry.Address, out var value) || !value.highCq)
|
else if (infoEntry.HighCq || !PtcProfiler.ProfiledFuncs.TryGetValue(infoEntry.Address, out var value) || !value.HighCq)
|
||||||
{
|
{
|
||||||
Span<byte> code = ReadCode(codesReader, infoEntry.CodeLen);
|
Span<byte> code = ReadCode(codesReader, infoEntry.CodeLen);
|
||||||
|
|
||||||
|
@ -808,7 +808,7 @@ namespace ARMeilleure.Translation.PTC
|
||||||
Translator.DisposePools();
|
Translator.DisposePools();
|
||||||
}
|
}
|
||||||
|
|
||||||
int maxDegreeOfParallelism = Environment.ProcessorCount;
|
int maxDegreeOfParallelism = (Environment.ProcessorCount * 3) / 4;
|
||||||
|
|
||||||
List<Thread> threads = new List<Thread>();
|
List<Thread> threads = new List<Thread>();
|
||||||
|
|
||||||
|
|
121
ARMeilleure/Translation/PTC/PtcFormatter.cs
Normal file
121
ARMeilleure/Translation/PTC/PtcFormatter.cs
Normal file
|
@ -0,0 +1,121 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
namespace ARMeilleure.Translation.PTC
|
||||||
|
{
|
||||||
|
public class PtcFormatter
|
||||||
|
{
|
||||||
|
#region "Deserialize"
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static Dictionary<TKey, TValue> DeserializeDictionary<TKey, TValue>(Stream stream, Func<Stream, TValue> valueFunc) where TKey : unmanaged
|
||||||
|
{
|
||||||
|
Dictionary<TKey, TValue> dictionary = new();
|
||||||
|
|
||||||
|
int count = DeserializeStructure<int>(stream);
|
||||||
|
|
||||||
|
for (int i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
TKey key = DeserializeStructure<TKey>(stream);
|
||||||
|
TValue value = valueFunc(stream);
|
||||||
|
|
||||||
|
dictionary.Add(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return dictionary;
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static List<T> DeserializeList<T>(Stream stream) where T : unmanaged
|
||||||
|
{
|
||||||
|
List<T> list = new();
|
||||||
|
|
||||||
|
int count = DeserializeStructure<int>(stream);
|
||||||
|
|
||||||
|
for (int i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
T item = DeserializeStructure<T>(stream);
|
||||||
|
|
||||||
|
list.Add(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static T DeserializeStructure<T>(Stream stream) where T : unmanaged
|
||||||
|
{
|
||||||
|
T structure = default(T);
|
||||||
|
|
||||||
|
Span<T> spanT = MemoryMarshal.CreateSpan(ref structure, 1);
|
||||||
|
stream.Read(MemoryMarshal.AsBytes(spanT));
|
||||||
|
|
||||||
|
return structure;
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region "GetSerializeSize"
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static int GetSerializeSizeDictionary<TKey, TValue>(Dictionary<TKey, TValue> dictionary, Func<TValue, int> valueFunc) where TKey : unmanaged
|
||||||
|
{
|
||||||
|
int size = 0;
|
||||||
|
|
||||||
|
size += Unsafe.SizeOf<int>();
|
||||||
|
|
||||||
|
foreach ((_, TValue value) in dictionary)
|
||||||
|
{
|
||||||
|
size += Unsafe.SizeOf<TKey>();
|
||||||
|
size += valueFunc(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static int GetSerializeSizeList<T>(List<T> list) where T : unmanaged
|
||||||
|
{
|
||||||
|
int size = 0;
|
||||||
|
|
||||||
|
size += Unsafe.SizeOf<int>();
|
||||||
|
|
||||||
|
size += list.Count * Unsafe.SizeOf<T>();
|
||||||
|
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region "Serialize"
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static void SerializeDictionary<TKey, TValue>(Stream stream, Dictionary<TKey, TValue> dictionary, Action<Stream, TValue> valueAction) where TKey : unmanaged
|
||||||
|
{
|
||||||
|
SerializeStructure<int>(stream, ref Unsafe.AsRef(dictionary.Count));
|
||||||
|
|
||||||
|
foreach ((TKey key, TValue value) in dictionary)
|
||||||
|
{
|
||||||
|
SerializeStructure<TKey>(stream, ref Unsafe.AsRef(key));
|
||||||
|
valueAction(stream, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static void SerializeList<T>(Stream stream, List<T> list) where T : unmanaged
|
||||||
|
{
|
||||||
|
SerializeStructure<int>(stream, ref Unsafe.AsRef(list.Count));
|
||||||
|
|
||||||
|
foreach (T item in list)
|
||||||
|
{
|
||||||
|
SerializeStructure<T>(stream, ref Unsafe.AsRef(item));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static void SerializeStructure<T>(Stream stream, ref T structure) where T : unmanaged
|
||||||
|
{
|
||||||
|
Span<T> spanT = MemoryMarshal.CreateSpan(ref structure, 1);
|
||||||
|
stream.Write(MemoryMarshal.AsBytes(spanT));
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,14 +6,15 @@ using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
using static ARMeilleure.Translation.PTC.PtcFormatter;
|
||||||
|
|
||||||
namespace ARMeilleure.Translation.PTC
|
namespace ARMeilleure.Translation.PTC
|
||||||
{
|
{
|
||||||
class PtcJumpTable
|
class PtcJumpTable
|
||||||
{
|
{
|
||||||
|
[StructLayout(LayoutKind.Sequential, Pack = 1/*, Size = 16*/)]
|
||||||
public struct TableEntry<TAddress>
|
public struct TableEntry<TAddress>
|
||||||
{
|
{
|
||||||
public const int Stride = 16; // Bytes.
|
|
||||||
|
|
||||||
public int EntryIndex;
|
public int EntryIndex;
|
||||||
public long GuestAddress;
|
public long GuestAddress;
|
||||||
public TAddress HostAddress; // int
|
public TAddress HostAddress; // int
|
||||||
|
@ -70,179 +71,38 @@ namespace ARMeilleure.Translation.PTC
|
||||||
|
|
||||||
public static PtcJumpTable Deserialize(Stream stream)
|
public static PtcJumpTable Deserialize(Stream stream)
|
||||||
{
|
{
|
||||||
using (BinaryReader reader = new BinaryReader(stream, EncodingCache.UTF8NoBOM, true))
|
var jumpTable = DeserializeList<TableEntry<DirectHostAddress>>(stream);
|
||||||
{
|
var dynamicTable = DeserializeList<TableEntry<IndirectHostAddress>>(stream);
|
||||||
var jumpTable = new List<TableEntry<DirectHostAddress>>();
|
|
||||||
|
|
||||||
int jumpTableCount = reader.ReadInt32();
|
var targets = DeserializeList<ulong>(stream);
|
||||||
|
var dependants = DeserializeDictionary<ulong, List<int>>(stream, (stream) => DeserializeList<int>(stream));
|
||||||
for (int i = 0; i < jumpTableCount; i++)
|
var owners = DeserializeDictionary<ulong, List<int>>(stream, (stream) => DeserializeList<int>(stream));
|
||||||
{
|
|
||||||
int entryIndex = reader.ReadInt32();
|
|
||||||
long guestAddress = reader.ReadInt64();
|
|
||||||
DirectHostAddress hostAddress = (DirectHostAddress)reader.ReadInt32();
|
|
||||||
|
|
||||||
jumpTable.Add(new TableEntry<DirectHostAddress>(entryIndex, guestAddress, hostAddress));
|
|
||||||
}
|
|
||||||
|
|
||||||
var dynamicTable = new List<TableEntry<IndirectHostAddress>>();
|
|
||||||
|
|
||||||
int dynamicTableCount = reader.ReadInt32();
|
|
||||||
|
|
||||||
for (int i = 0; i < dynamicTableCount; i++)
|
|
||||||
{
|
|
||||||
int entryIndex = reader.ReadInt32();
|
|
||||||
long guestAddress = reader.ReadInt64();
|
|
||||||
IndirectHostAddress hostAddress = (IndirectHostAddress)reader.ReadInt32();
|
|
||||||
|
|
||||||
dynamicTable.Add(new TableEntry<IndirectHostAddress>(entryIndex, guestAddress, hostAddress));
|
|
||||||
}
|
|
||||||
|
|
||||||
var targets = new List<ulong>();
|
|
||||||
|
|
||||||
int targetsCount = reader.ReadInt32();
|
|
||||||
|
|
||||||
for (int i = 0; i < targetsCount; i++)
|
|
||||||
{
|
|
||||||
ulong address = reader.ReadUInt64();
|
|
||||||
|
|
||||||
targets.Add(address);
|
|
||||||
}
|
|
||||||
|
|
||||||
var dependants = new Dictionary<ulong, List<int>>();
|
|
||||||
|
|
||||||
int dependantsCount = reader.ReadInt32();
|
|
||||||
|
|
||||||
for (int i = 0; i < dependantsCount; i++)
|
|
||||||
{
|
|
||||||
ulong address = reader.ReadUInt64();
|
|
||||||
|
|
||||||
var entries = new List<int>();
|
|
||||||
|
|
||||||
int entriesCount = reader.ReadInt32();
|
|
||||||
|
|
||||||
for (int j = 0; j < entriesCount; j++)
|
|
||||||
{
|
|
||||||
int entry = reader.ReadInt32();
|
|
||||||
|
|
||||||
entries.Add(entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
dependants.Add(address, entries);
|
|
||||||
}
|
|
||||||
|
|
||||||
var owners = new Dictionary<ulong, List<int>>();
|
|
||||||
|
|
||||||
int ownersCount = reader.ReadInt32();
|
|
||||||
|
|
||||||
for (int i = 0; i < ownersCount; i++)
|
|
||||||
{
|
|
||||||
ulong address = reader.ReadUInt64();
|
|
||||||
|
|
||||||
var entries = new List<int>();
|
|
||||||
|
|
||||||
int entriesCount = reader.ReadInt32();
|
|
||||||
|
|
||||||
for (int j = 0; j < entriesCount; j++)
|
|
||||||
{
|
|
||||||
int entry = reader.ReadInt32();
|
|
||||||
|
|
||||||
entries.Add(entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
owners.Add(address, entries);
|
|
||||||
}
|
|
||||||
|
|
||||||
return new PtcJumpTable(jumpTable, dynamicTable, targets, dependants, owners);
|
return new PtcJumpTable(jumpTable, dynamicTable, targets, dependants, owners);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public static int GetSerializeSize(PtcJumpTable ptcJumpTable)
|
public static int GetSerializeSize(PtcJumpTable ptcJumpTable)
|
||||||
{
|
{
|
||||||
const int CountSize = 4; // Bytes.
|
|
||||||
|
|
||||||
int size = 0;
|
int size = 0;
|
||||||
|
|
||||||
size += CountSize + ptcJumpTable._jumpTable.Count * TableEntry<DirectHostAddress>.Stride;
|
size += GetSerializeSizeList<TableEntry<DirectHostAddress>>(ptcJumpTable._jumpTable);
|
||||||
|
size += GetSerializeSizeList<TableEntry<IndirectHostAddress>>(ptcJumpTable._dynamicTable);
|
||||||
|
|
||||||
size += CountSize + ptcJumpTable._dynamicTable.Count * TableEntry<IndirectHostAddress>.Stride;
|
size += GetSerializeSizeList<ulong>(ptcJumpTable.Targets);
|
||||||
|
size += GetSerializeSizeDictionary<ulong, List<int>>(ptcJumpTable.Dependants, (list) => GetSerializeSizeList<int>(list));
|
||||||
size += CountSize + ptcJumpTable.Targets.Count * 8;
|
size += GetSerializeSizeDictionary<ulong, List<int>>(ptcJumpTable.Owners, (list) => GetSerializeSizeList<int>(list));
|
||||||
|
|
||||||
size += CountSize;
|
|
||||||
foreach (var kv in ptcJumpTable.Dependants)
|
|
||||||
{
|
|
||||||
size += 8; // kv.Key (address)
|
|
||||||
size += CountSize + kv.Value.Count * 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
size += CountSize;
|
|
||||||
foreach (var kv in ptcJumpTable.Owners)
|
|
||||||
{
|
|
||||||
size += 8; // kv.Key (address)
|
|
||||||
size += CountSize + kv.Value.Count * 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Serialize(Stream stream, PtcJumpTable ptcJumpTable)
|
public static void Serialize(Stream stream, PtcJumpTable ptcJumpTable)
|
||||||
{
|
{
|
||||||
using (BinaryWriter writer = new BinaryWriter(stream, EncodingCache.UTF8NoBOM, true))
|
SerializeList<TableEntry<DirectHostAddress>>(stream, ptcJumpTable._jumpTable);
|
||||||
{
|
SerializeList<TableEntry<IndirectHostAddress>>(stream, ptcJumpTable._dynamicTable);
|
||||||
writer.Write((int)ptcJumpTable._jumpTable.Count);
|
|
||||||
|
|
||||||
foreach (var tableEntry in ptcJumpTable._jumpTable)
|
SerializeList<ulong>(stream, ptcJumpTable.Targets);
|
||||||
{
|
SerializeDictionary<ulong, List<int>>(stream, ptcJumpTable.Dependants, (stream, list) => SerializeList<int>(stream, list));
|
||||||
writer.Write((int)tableEntry.EntryIndex);
|
SerializeDictionary<ulong, List<int>>(stream, ptcJumpTable.Owners, (stream, list) => SerializeList<int>(stream, list));
|
||||||
writer.Write((long)tableEntry.GuestAddress);
|
|
||||||
writer.Write((int)tableEntry.HostAddress);
|
|
||||||
}
|
|
||||||
|
|
||||||
writer.Write((int)ptcJumpTable._dynamicTable.Count);
|
|
||||||
|
|
||||||
foreach (var tableEntry in ptcJumpTable._dynamicTable)
|
|
||||||
{
|
|
||||||
writer.Write((int)tableEntry.EntryIndex);
|
|
||||||
writer.Write((long)tableEntry.GuestAddress);
|
|
||||||
writer.Write((int)tableEntry.HostAddress);
|
|
||||||
}
|
|
||||||
|
|
||||||
writer.Write((int)ptcJumpTable.Targets.Count);
|
|
||||||
|
|
||||||
foreach (ulong address in ptcJumpTable.Targets)
|
|
||||||
{
|
|
||||||
writer.Write((ulong)address);
|
|
||||||
}
|
|
||||||
|
|
||||||
writer.Write((int)ptcJumpTable.Dependants.Count);
|
|
||||||
|
|
||||||
foreach (var kv in ptcJumpTable.Dependants)
|
|
||||||
{
|
|
||||||
writer.Write((ulong)kv.Key); // address
|
|
||||||
|
|
||||||
writer.Write((int)kv.Value.Count);
|
|
||||||
|
|
||||||
foreach (int entry in kv.Value)
|
|
||||||
{
|
|
||||||
writer.Write((int)entry);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
writer.Write((int)ptcJumpTable.Owners.Count);
|
|
||||||
|
|
||||||
foreach (var kv in ptcJumpTable.Owners)
|
|
||||||
{
|
|
||||||
writer.Write((ulong)kv.Key); // address
|
|
||||||
|
|
||||||
writer.Write((int)kv.Value.Count);
|
|
||||||
|
|
||||||
foreach (int entry in kv.Value)
|
|
||||||
{
|
|
||||||
writer.Write((int)entry);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Initialize(JumpTable jumpTable)
|
public void Initialize(JumpTable jumpTable)
|
||||||
|
@ -349,7 +209,7 @@ namespace ARMeilleure.Translation.PTC
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!PtcProfiler.ProfiledFuncs.TryGetValue((ulong)guestAddress, out var value) || !value.highCq)
|
if (!PtcProfiler.ProfiledFuncs.TryGetValue((ulong)guestAddress, out var value) || !value.HighCq)
|
||||||
{
|
{
|
||||||
throw new KeyNotFoundException($"({nameof(guestAddress)} = 0x{(ulong)guestAddress:X16})");
|
throw new KeyNotFoundException($"({nameof(guestAddress)} = 0x{(ulong)guestAddress:X16})");
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,9 +6,12 @@ using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.IO.Compression;
|
using System.IO.Compression;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
using System.Security.Cryptography;
|
using System.Security.Cryptography;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
|
||||||
|
using static ARMeilleure.Translation.PTC.PtcFormatter;
|
||||||
|
|
||||||
namespace ARMeilleure.Translation.PTC
|
namespace ARMeilleure.Translation.PTC
|
||||||
{
|
{
|
||||||
public static class PtcProfiler
|
public static class PtcProfiler
|
||||||
|
@ -31,7 +34,7 @@ namespace ARMeilleure.Translation.PTC
|
||||||
|
|
||||||
private static byte[] _lastHash;
|
private static byte[] _lastHash;
|
||||||
|
|
||||||
internal static Dictionary<ulong, (ExecutionMode mode, bool highCq)> ProfiledFuncs { get; private set; }
|
internal static Dictionary<ulong, FuncProfile> ProfiledFuncs { get; private set; }
|
||||||
|
|
||||||
internal static bool Enabled { get; private set; }
|
internal static bool Enabled { get; private set; }
|
||||||
|
|
||||||
|
@ -49,7 +52,7 @@ namespace ARMeilleure.Translation.PTC
|
||||||
|
|
||||||
_disposed = false;
|
_disposed = false;
|
||||||
|
|
||||||
ProfiledFuncs = new Dictionary<ulong, (ExecutionMode, bool)>();
|
ProfiledFuncs = new Dictionary<ulong, FuncProfile>();
|
||||||
|
|
||||||
Enabled = false;
|
Enabled = false;
|
||||||
}
|
}
|
||||||
|
@ -62,7 +65,7 @@ namespace ARMeilleure.Translation.PTC
|
||||||
|
|
||||||
lock (_lock)
|
lock (_lock)
|
||||||
{
|
{
|
||||||
ProfiledFuncs.TryAdd(address, (mode, highCq: false));
|
ProfiledFuncs.TryAdd(address, new FuncProfile(mode, highCq: false));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -77,7 +80,7 @@ namespace ARMeilleure.Translation.PTC
|
||||||
{
|
{
|
||||||
Debug.Assert(ProfiledFuncs.ContainsKey(address));
|
Debug.Assert(ProfiledFuncs.ContainsKey(address));
|
||||||
|
|
||||||
ProfiledFuncs[address] = (mode, highCq: true);
|
ProfiledFuncs[address] = new FuncProfile(mode, highCq: true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -97,7 +100,7 @@ namespace ARMeilleure.Translation.PTC
|
||||||
|
|
||||||
if (!funcs.ContainsKey(address))
|
if (!funcs.ContainsKey(address))
|
||||||
{
|
{
|
||||||
profiledFuncsToTranslate.Enqueue((address, profiledFunc.Value.mode, profiledFunc.Value.highCq));
|
profiledFuncsToTranslate.Enqueue((address, profiledFunc.Value.Mode, profiledFunc.Value.HighCq));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -194,7 +197,7 @@ namespace ARMeilleure.Translation.PTC
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
ProfiledFuncs = new Dictionary<ulong, (ExecutionMode, bool)>();
|
ProfiledFuncs = new Dictionary<ulong, FuncProfile>();
|
||||||
|
|
||||||
InvalidateCompressedStream(compressedStream);
|
InvalidateCompressedStream(compressedStream);
|
||||||
|
|
||||||
|
@ -230,26 +233,9 @@ namespace ARMeilleure.Translation.PTC
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Dictionary<ulong, (ExecutionMode, bool)> Deserialize(Stream stream)
|
private static Dictionary<ulong, FuncProfile> Deserialize(Stream stream)
|
||||||
{
|
{
|
||||||
using (BinaryReader reader = new BinaryReader(stream, EncodingCache.UTF8NoBOM, true))
|
return DeserializeDictionary<ulong, FuncProfile>(stream, (stream) => DeserializeStructure<FuncProfile>(stream));
|
||||||
{
|
|
||||||
var profiledFuncs = new Dictionary<ulong, (ExecutionMode, bool)>();
|
|
||||||
|
|
||||||
int profiledFuncsCount = reader.ReadInt32();
|
|
||||||
|
|
||||||
for (int i = 0; i < profiledFuncsCount; i++)
|
|
||||||
{
|
|
||||||
ulong address = reader.ReadUInt64();
|
|
||||||
|
|
||||||
ExecutionMode mode = (ExecutionMode)reader.ReadInt32();
|
|
||||||
bool highCq = reader.ReadBoolean();
|
|
||||||
|
|
||||||
profiledFuncs.Add(address, (mode, highCq));
|
|
||||||
}
|
|
||||||
|
|
||||||
return profiledFuncs;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void InvalidateCompressedStream(FileStream compressedStream)
|
private static void InvalidateCompressedStream(FileStream compressedStream)
|
||||||
|
@ -348,20 +334,9 @@ namespace ARMeilleure.Translation.PTC
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void Serialize(Stream stream, Dictionary<ulong, (ExecutionMode mode, bool highCq)> profiledFuncs)
|
private static void Serialize(Stream stream, Dictionary<ulong, FuncProfile> profiledFuncs)
|
||||||
{
|
{
|
||||||
using (BinaryWriter writer = new BinaryWriter(stream, EncodingCache.UTF8NoBOM, true))
|
SerializeDictionary<ulong, FuncProfile>(stream, profiledFuncs, (stream, structure) => SerializeStructure<FuncProfile>(stream, ref structure));
|
||||||
{
|
|
||||||
writer.Write((int)profiledFuncs.Count);
|
|
||||||
|
|
||||||
foreach (var kv in profiledFuncs)
|
|
||||||
{
|
|
||||||
writer.Write((ulong)kv.Key); // address
|
|
||||||
|
|
||||||
writer.Write((int)kv.Value.mode);
|
|
||||||
writer.Write((bool)kv.Value.highCq);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private struct Header
|
private struct Header
|
||||||
|
@ -371,6 +346,19 @@ namespace ARMeilleure.Translation.PTC
|
||||||
public uint InfoFileVersion;
|
public uint InfoFileVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential, Pack = 1/*, Size = 5*/)]
|
||||||
|
internal struct FuncProfile
|
||||||
|
{
|
||||||
|
public ExecutionMode Mode;
|
||||||
|
public bool HighCq;
|
||||||
|
|
||||||
|
public FuncProfile(ExecutionMode mode, bool highCq)
|
||||||
|
{
|
||||||
|
Mode = mode;
|
||||||
|
HighCq = highCq;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
internal static void Start()
|
internal static void Start()
|
||||||
{
|
{
|
||||||
if (Ptc.State == PtcState.Enabled ||
|
if (Ptc.State == PtcState.Enabled ||
|
||||||
|
|
Loading…
Reference in a new issue