diff options
| author | TSR Berry <20988865+TSRBerry@users.noreply.github.com> | 2023-04-08 01:22:00 +0200 |
|---|---|---|
| committer | Mary <thog@protonmail.com> | 2023-04-27 23:51:14 +0200 |
| commit | cee712105850ac3385cd0091a923438167433f9f (patch) | |
| tree | 4a5274b21d8b7f938c0d0ce18736d3f2993b11b1 /ARMeilleure/Translation/PTC | |
| parent | cd124bda587ef09668a971fa1cac1c3f0cfc9f21 (diff) | |
Move solution and projects to src
Diffstat (limited to 'ARMeilleure/Translation/PTC')
| -rw-r--r-- | ARMeilleure/Translation/PTC/EncodingCache.cs | 9 | ||||
| -rw-r--r-- | ARMeilleure/Translation/PTC/IPtcLoadState.cs | 10 | ||||
| -rw-r--r-- | ARMeilleure/Translation/PTC/Ptc.cs | 1131 | ||||
| -rw-r--r-- | ARMeilleure/Translation/PTC/PtcFormatter.cs | 179 | ||||
| -rw-r--r-- | ARMeilleure/Translation/PTC/PtcLoadingState.cs | 9 | ||||
| -rw-r--r-- | ARMeilleure/Translation/PTC/PtcProfiler.cs | 421 | ||||
| -rw-r--r-- | ARMeilleure/Translation/PTC/PtcState.cs | 10 |
7 files changed, 0 insertions, 1769 deletions
diff --git a/ARMeilleure/Translation/PTC/EncodingCache.cs b/ARMeilleure/Translation/PTC/EncodingCache.cs deleted file mode 100644 index 90d40c47..00000000 --- a/ARMeilleure/Translation/PTC/EncodingCache.cs +++ /dev/null @@ -1,9 +0,0 @@ -using System.Text; - -namespace ARMeilleure.Translation.PTC -{ - static class EncodingCache - { - public static readonly Encoding UTF8NoBOM = new UTF8Encoding(encoderShouldEmitUTF8Identifier: false, throwOnInvalidBytes: true); - } -}
\ No newline at end of file diff --git a/ARMeilleure/Translation/PTC/IPtcLoadState.cs b/ARMeilleure/Translation/PTC/IPtcLoadState.cs deleted file mode 100644 index 1b11ac0b..00000000 --- a/ARMeilleure/Translation/PTC/IPtcLoadState.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System; - -namespace ARMeilleure.Translation.PTC -{ - public interface IPtcLoadState - { - event Action<PtcLoadingState, int, int> PtcStateChanged; - void Continue(); - } -}
\ No newline at end of file diff --git a/ARMeilleure/Translation/PTC/Ptc.cs b/ARMeilleure/Translation/PTC/Ptc.cs deleted file mode 100644 index ea4e715b..00000000 --- a/ARMeilleure/Translation/PTC/Ptc.cs +++ /dev/null @@ -1,1131 +0,0 @@ -using ARMeilleure.CodeGen; -using ARMeilleure.CodeGen.Linking; -using ARMeilleure.CodeGen.Unwinding; -using ARMeilleure.Common; -using ARMeilleure.Memory; -using Ryujinx.Common; -using Ryujinx.Common.Configuration; -using Ryujinx.Common.Logging; -using Ryujinx.Common.Memory; -using System; -using System.Buffers.Binary; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.IO.Compression; -using System.Runtime; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; -using System.Threading; - -using static ARMeilleure.Translation.PTC.PtcFormatter; - -namespace ARMeilleure.Translation.PTC -{ - using Arm64HardwareCapabilities = ARMeilleure.CodeGen.Arm64.HardwareCapabilities; - using X86HardwareCapabilities = ARMeilleure.CodeGen.X86.HardwareCapabilities; - - class Ptc : IPtcLoadState - { - private const string OuterHeaderMagicString = "PTCohd\0\0"; - private const string InnerHeaderMagicString = "PTCihd\0\0"; - - private const uint InternalVersion = 4661; //! To be incremented manually for each change to the ARMeilleure project. - - private const string ActualDir = "0"; - private const string BackupDir = "1"; - - private const string TitleIdTextDefault = "0000000000000000"; - private const string DisplayVersionDefault = "0"; - - public static readonly Symbol PageTableSymbol = new(SymbolType.Special, 1); - public static readonly Symbol CountTableSymbol = new(SymbolType.Special, 2); - public static readonly Symbol DispatchStubSymbol = new(SymbolType.Special, 3); - - private const byte FillingByte = 0x00; - private const CompressionLevel SaveCompressionLevel = CompressionLevel.Fastest; - - public PtcProfiler Profiler { get; } - - // Carriers. - private MemoryStream _infosStream; - private List<byte[]> _codesList; - private MemoryStream _relocsStream; - private MemoryStream _unwindInfosStream; - - private readonly ulong _outerHeaderMagic; - private readonly ulong _innerHeaderMagic; - - private readonly ManualResetEvent _waitEvent; - - private readonly object _lock; - - private bool _disposed; - - public string TitleIdText { get; private set; } - public string DisplayVersion { get; private set; } - - private MemoryManagerType _memoryMode; - - public string CachePathActual { get; private set; } - public string CachePathBackup { get; private set; } - - public PtcState State { get; private set; } - - // Progress reporting helpers. - private volatile int _translateCount; - private volatile int _translateTotalCount; - public event Action<PtcLoadingState, int, int> PtcStateChanged; - - public Ptc() - { - Profiler = new PtcProfiler(this); - - InitializeCarriers(); - - _outerHeaderMagic = BinaryPrimitives.ReadUInt64LittleEndian(EncodingCache.UTF8NoBOM.GetBytes(OuterHeaderMagicString).AsSpan()); - _innerHeaderMagic = BinaryPrimitives.ReadUInt64LittleEndian(EncodingCache.UTF8NoBOM.GetBytes(InnerHeaderMagicString).AsSpan()); - - _waitEvent = new ManualResetEvent(true); - - _lock = new object(); - - _disposed = false; - - TitleIdText = TitleIdTextDefault; - DisplayVersion = DisplayVersionDefault; - - CachePathActual = string.Empty; - CachePathBackup = string.Empty; - - Disable(); - } - - public void Initialize(string titleIdText, string displayVersion, bool enabled, MemoryManagerType memoryMode) - { - Wait(); - - Profiler.Wait(); - Profiler.ClearEntries(); - - Logger.Info?.Print(LogClass.Ptc, $"Initializing Profiled Persistent Translation Cache (enabled: {enabled})."); - - if (!enabled || string.IsNullOrEmpty(titleIdText) || titleIdText == TitleIdTextDefault) - { - TitleIdText = TitleIdTextDefault; - DisplayVersion = DisplayVersionDefault; - - CachePathActual = string.Empty; - CachePathBackup = string.Empty; - - Disable(); - - return; - } - - TitleIdText = titleIdText; - DisplayVersion = !string.IsNullOrEmpty(displayVersion) ? displayVersion : DisplayVersionDefault; - _memoryMode = memoryMode; - - string workPathActual = Path.Combine(AppDataManager.GamesDirPath, TitleIdText, "cache", "cpu", ActualDir); - string workPathBackup = Path.Combine(AppDataManager.GamesDirPath, TitleIdText, "cache", "cpu", BackupDir); - - if (!Directory.Exists(workPathActual)) - { - Directory.CreateDirectory(workPathActual); - } - - if (!Directory.Exists(workPathBackup)) - { - Directory.CreateDirectory(workPathBackup); - } - - CachePathActual = Path.Combine(workPathActual, DisplayVersion); - CachePathBackup = Path.Combine(workPathBackup, DisplayVersion); - - PreLoad(); - Profiler.PreLoad(); - - Enable(); - } - - private void InitializeCarriers() - { - _infosStream = MemoryStreamManager.Shared.GetStream(); - _codesList = new List<byte[]>(); - _relocsStream = MemoryStreamManager.Shared.GetStream(); - _unwindInfosStream = MemoryStreamManager.Shared.GetStream(); - } - - private void DisposeCarriers() - { - _infosStream.Dispose(); - _codesList.Clear(); - _relocsStream.Dispose(); - _unwindInfosStream.Dispose(); - } - - private bool AreCarriersEmpty() - { - return _infosStream.Length == 0L && _codesList.Count == 0 && _relocsStream.Length == 0L && _unwindInfosStream.Length == 0L; - } - - private void ResetCarriersIfNeeded() - { - if (AreCarriersEmpty()) - { - return; - } - - DisposeCarriers(); - - InitializeCarriers(); - } - - private void PreLoad() - { - string fileNameActual = $"{CachePathActual}.cache"; - string fileNameBackup = $"{CachePathBackup}.cache"; - - FileInfo fileInfoActual = new FileInfo(fileNameActual); - FileInfo fileInfoBackup = new FileInfo(fileNameBackup); - - if (fileInfoActual.Exists && fileInfoActual.Length != 0L) - { - if (!Load(fileNameActual, false)) - { - if (fileInfoBackup.Exists && fileInfoBackup.Length != 0L) - { - Load(fileNameBackup, true); - } - } - } - else if (fileInfoBackup.Exists && fileInfoBackup.Length != 0L) - { - Load(fileNameBackup, true); - } - } - - private unsafe bool Load(string fileName, bool isBackup) - { - using (FileStream compressedStream = new(fileName, FileMode.Open)) - using (DeflateStream deflateStream = new(compressedStream, CompressionMode.Decompress, true)) - { - OuterHeader outerHeader = DeserializeStructure<OuterHeader>(compressedStream); - - if (!outerHeader.IsHeaderValid()) - { - InvalidateCompressedStream(compressedStream); - - return false; - } - - if (outerHeader.Magic != _outerHeaderMagic) - { - InvalidateCompressedStream(compressedStream); - - return false; - } - - if (outerHeader.CacheFileVersion != InternalVersion) - { - InvalidateCompressedStream(compressedStream); - - return false; - } - - if (outerHeader.Endianness != GetEndianness()) - { - InvalidateCompressedStream(compressedStream); - - return false; - } - - if (outerHeader.FeatureInfo != GetFeatureInfo()) - { - InvalidateCompressedStream(compressedStream); - - return false; - } - - if (outerHeader.MemoryManagerMode != GetMemoryManagerMode()) - { - InvalidateCompressedStream(compressedStream); - - return false; - } - - if (outerHeader.OSPlatform != GetOSPlatform()) - { - InvalidateCompressedStream(compressedStream); - - return false; - } - - if (outerHeader.Architecture != (uint)RuntimeInformation.ProcessArchitecture) - { - InvalidateCompressedStream(compressedStream); - - return false; - } - - IntPtr intPtr = IntPtr.Zero; - - try - { - intPtr = Marshal.AllocHGlobal(new IntPtr(outerHeader.UncompressedStreamSize)); - - using (UnmanagedMemoryStream stream = new((byte*)intPtr.ToPointer(), outerHeader.UncompressedStreamSize, outerHeader.UncompressedStreamSize, FileAccess.ReadWrite)) - { - try - { - deflateStream.CopyTo(stream); - } - catch - { - InvalidateCompressedStream(compressedStream); - - return false; - } - - Debug.Assert(stream.Position == stream.Length); - - stream.Seek(0L, SeekOrigin.Begin); - - InnerHeader innerHeader = DeserializeStructure<InnerHeader>(stream); - - if (!innerHeader.IsHeaderValid()) - { - InvalidateCompressedStream(compressedStream); - - return false; - } - - if (innerHeader.Magic != _innerHeaderMagic) - { - InvalidateCompressedStream(compressedStream); - - return false; - } - - ReadOnlySpan<byte> infosBytes = new(stream.PositionPointer, innerHeader.InfosLength); - stream.Seek(innerHeader.InfosLength, SeekOrigin.Current); - - Hash128 infosHash = XXHash128.ComputeHash(infosBytes); - - if (innerHeader.InfosHash != infosHash) - { - InvalidateCompressedStream(compressedStream); - - return false; - } - - ReadOnlySpan<byte> codesBytes = (int)innerHeader.CodesLength > 0 ? new(stream.PositionPointer, (int)innerHeader.CodesLength) : ReadOnlySpan<byte>.Empty; - stream.Seek(innerHeader.CodesLength, SeekOrigin.Current); - - Hash128 codesHash = XXHash128.ComputeHash(codesBytes); - - if (innerHeader.CodesHash != codesHash) - { - InvalidateCompressedStream(compressedStream); - - return false; - } - - ReadOnlySpan<byte> relocsBytes = new(stream.PositionPointer, innerHeader.RelocsLength); - stream.Seek(innerHeader.RelocsLength, SeekOrigin.Current); - - Hash128 relocsHash = XXHash128.ComputeHash(relocsBytes); - - if (innerHeader.RelocsHash != relocsHash) - { - InvalidateCompressedStream(compressedStream); - - return false; - } - - ReadOnlySpan<byte> unwindInfosBytes = new(stream.PositionPointer, innerHeader.UnwindInfosLength); - stream.Seek(innerHeader.UnwindInfosLength, SeekOrigin.Current); - - Hash128 unwindInfosHash = XXHash128.ComputeHash(unwindInfosBytes); - - if (innerHeader.UnwindInfosHash != unwindInfosHash) - { - InvalidateCompressedStream(compressedStream); - - return false; - } - - Debug.Assert(stream.Position == stream.Length); - - stream.Seek((long)Unsafe.SizeOf<InnerHeader>(), SeekOrigin.Begin); - - _infosStream.Write(infosBytes); - stream.Seek(innerHeader.InfosLength, SeekOrigin.Current); - - _codesList.ReadFrom(stream); - - _relocsStream.Write(relocsBytes); - stream.Seek(innerHeader.RelocsLength, SeekOrigin.Current); - - _unwindInfosStream.Write(unwindInfosBytes); - stream.Seek(innerHeader.UnwindInfosLength, SeekOrigin.Current); - - Debug.Assert(stream.Position == stream.Length); - } - } - finally - { - if (intPtr != IntPtr.Zero) - { - Marshal.FreeHGlobal(intPtr); - } - } - } - - long fileSize = new FileInfo(fileName).Length; - - Logger.Info?.Print(LogClass.Ptc, $"{(isBackup ? "Loaded Backup Translation Cache" : "Loaded Translation Cache")} (size: {fileSize} bytes, translated functions: {GetEntriesCount()})."); - - return true; - } - - private void InvalidateCompressedStream(FileStream compressedStream) - { - compressedStream.SetLength(0L); - } - - private void PreSave() - { - _waitEvent.Reset(); - - try - { - string fileNameActual = $"{CachePathActual}.cache"; - string fileNameBackup = $"{CachePathBackup}.cache"; - - FileInfo fileInfoActual = new FileInfo(fileNameActual); - - if (fileInfoActual.Exists && fileInfoActual.Length != 0L) - { - File.Copy(fileNameActual, fileNameBackup, true); - } - - Save(fileNameActual); - } - finally - { - ResetCarriersIfNeeded(); - - GCSettings.LargeObjectHeapCompactionMode = GCLargeObjectHeapCompactionMode.CompactOnce; - } - - _waitEvent.Set(); - } - - private unsafe void Save(string fileName) - { - int translatedFuncsCount; - - InnerHeader innerHeader = new InnerHeader(); - - innerHeader.Magic = _innerHeaderMagic; - - innerHeader.InfosLength = (int)_infosStream.Length; - innerHeader.CodesLength = _codesList.Length(); - innerHeader.RelocsLength = (int)_relocsStream.Length; - innerHeader.UnwindInfosLength = (int)_unwindInfosStream.Length; - - OuterHeader outerHeader = new OuterHeader(); - - outerHeader.Magic = _outerHeaderMagic; - - outerHeader.CacheFileVersion = InternalVersion; - outerHeader.Endianness = GetEndianness(); - outerHeader.FeatureInfo = GetFeatureInfo(); - outerHeader.MemoryManagerMode = GetMemoryManagerMode(); - outerHeader.OSPlatform = GetOSPlatform(); - outerHeader.Architecture = (uint)RuntimeInformation.ProcessArchitecture; - - outerHeader.UncompressedStreamSize = - (long)Unsafe.SizeOf<InnerHeader>() + - innerHeader.InfosLength + - innerHeader.CodesLength + - innerHeader.RelocsLength + - innerHeader.UnwindInfosLength; - - outerHeader.SetHeaderHash(); - - IntPtr intPtr = IntPtr.Zero; - - try - { - intPtr = Marshal.AllocHGlobal(new IntPtr(outerHeader.UncompressedStreamSize)); - - using (UnmanagedMemoryStream stream = new((byte*)intPtr.ToPointer(), outerHeader.UncompressedStreamSize, outerHeader.UncompressedStreamSize, FileAccess.ReadWrite)) - { - stream.Seek((long)Unsafe.SizeOf<InnerHeader>(), SeekOrigin.Begin); - - ReadOnlySpan<byte> infosBytes = new(stream.PositionPointer, innerHeader.InfosLength); - _infosStream.WriteTo(stream); - - ReadOnlySpan<byte> codesBytes = (int)innerHeader.CodesLength > 0 ? new(stream.PositionPointer, (int)innerHeader.CodesLength) : ReadOnlySpan<byte>.Empty; - _codesList.WriteTo(stream); - - ReadOnlySpan<byte> relocsBytes = new(stream.PositionPointer, innerHeader.RelocsLength); - _relocsStream.WriteTo(stream); - - ReadOnlySpan<byte> unwindInfosBytes = new(stream.PositionPointer, innerHeader.UnwindInfosLength); - _unwindInfosStream.WriteTo(stream); - - Debug.Assert(stream.Position == stream.Length); - - innerHeader.InfosHash = XXHash128.ComputeHash(infosBytes); - innerHeader.CodesHash = XXHash128.ComputeHash(codesBytes); - innerHeader.RelocsHash = XXHash128.ComputeHash(relocsBytes); - innerHeader.UnwindInfosHash = XXHash128.ComputeHash(unwindInfosBytes); - - innerHeader.SetHeaderHash(); - - stream.Seek(0L, SeekOrigin.Begin); - SerializeStructure(stream, innerHeader); - - translatedFuncsCount = GetEntriesCount(); - - ResetCarriersIfNeeded(); - - using (FileStream compressedStream = new(fileName, FileMode.OpenOrCreate)) - using (DeflateStream deflateStream = new(compressedStream, SaveCompressionLevel, true)) - { - try - { - SerializeStructure(compressedStream, outerHeader); - - stream.Seek(0L, SeekOrigin.Begin); - stream.CopyTo(deflateStream); - } - catch - { - compressedStream.Position = 0L; - } - - if (compressedStream.Position < compressedStream.Length) - { - compressedStream.SetLength(compressedStream.Position); - } - } - } - } - finally - { - if (intPtr != IntPtr.Zero) - { - Marshal.FreeHGlobal(intPtr); - } - } - - long fileSize = new FileInfo(fileName).Length; - - if (fileSize != 0L) - { - Logger.Info?.Print(LogClass.Ptc, $"Saved Translation Cache (size: {fileSize} bytes, translated functions: {translatedFuncsCount})."); - } - } - - public void LoadTranslations(Translator translator) - { - if (AreCarriersEmpty()) - { - return; - } - - long infosStreamLength = _infosStream.Length; - long relocsStreamLength = _relocsStream.Length; - long unwindInfosStreamLength = _unwindInfosStream.Length; - - _infosStream.Seek(0L, SeekOrigin.Begin); - _relocsStream.Seek(0L, SeekOrigin.Begin); - _unwindInfosStream.Seek(0L, SeekOrigin.Begin); - - using (BinaryReader relocsReader = new(_relocsStream, EncodingCache.UTF8NoBOM, true)) - using (BinaryReader unwindInfosReader = new(_unwindInfosStream, EncodingCache.UTF8NoBOM, true)) - { - for (int index = 0; index < GetEntriesCount(); index++) - { - InfoEntry infoEntry = DeserializeStructure<InfoEntry>(_infosStream); - - if (infoEntry.Stubbed) - { - SkipCode(index, infoEntry.CodeLength); - SkipReloc(infoEntry.RelocEntriesCount); - SkipUnwindInfo(unwindInfosReader); - - continue; - } - - bool isEntryChanged = infoEntry.Hash != ComputeHash(translator.Memory, infoEntry.Address, infoEntry.GuestSize); - - if (isEntryChanged || (!infoEntry.HighCq && Profiler.ProfiledFuncs.TryGetValue(infoEntry.Address, out var value) && value.HighCq)) - { - infoEntry.Stubbed = true; - infoEntry.CodeLength = 0; - UpdateInfo(infoEntry); - - StubCode(index); - StubReloc(infoEntry.RelocEntriesCount); - StubUnwindInfo(unwindInfosReader); - - if (isEntryChanged) - { - Logger.Info?.Print(LogClass.Ptc, $"Invalidated translated function (address: 0x{infoEntry.Address:X16})"); - } - - continue; - } - - byte[] code = ReadCode(index, infoEntry.CodeLength); - - Counter<uint> callCounter = null; - - if (infoEntry.RelocEntriesCount != 0) - { - RelocEntry[] relocEntries = GetRelocEntries(relocsReader, infoEntry.RelocEntriesCount); - - PatchCode(translator, code, relocEntries, out callCounter); - } - - UnwindInfo unwindInfo = ReadUnwindInfo(unwindInfosReader); - - TranslatedFunction func = FastTranslate(code, callCounter, infoEntry.GuestSize, unwindInfo, infoEntry.HighCq); - - translator.RegisterFunction(infoEntry.Address, func); - - bool isAddressUnique = translator.Functions.TryAdd(infoEntry.Address, infoEntry.GuestSize, func); - - Debug.Assert(isAddressUnique, $"The address 0x{infoEntry.Address:X16} is not unique."); - } - } - - if (_infosStream.Length != infosStreamLength || _infosStream.Position != infosStreamLength || - _relocsStream.Length != relocsStreamLength || _relocsStream.Position != relocsStreamLength || - _unwindInfosStream.Length != unwindInfosStreamLength || _unwindInfosStream.Position != unwindInfosStreamLength) - { - throw new Exception("The length of a memory stream has changed, or its position has not reached or has exceeded its end."); - } - - Logger.Info?.Print(LogClass.Ptc, $"{translator.Functions.Count} translated functions loaded"); - } - - private int GetEntriesCount() - { - return _codesList.Count; - } - - [Conditional("DEBUG")] - private void SkipCode(int index, int codeLength) - { - Debug.Assert(_codesList[index].Length == 0); - Debug.Assert(codeLength == 0); - } - - private void SkipReloc(int relocEntriesCount) - { - _relocsStream.Seek(relocEntriesCount * RelocEntry.Stride, SeekOrigin.Current); - } - - private void SkipUnwindInfo(BinaryReader unwindInfosReader) - { - int pushEntriesLength = unwindInfosReader.ReadInt32(); - - _unwindInfosStream.Seek(pushEntriesLength * UnwindPushEntry.Stride + UnwindInfo.Stride, SeekOrigin.Current); - } - - private byte[] ReadCode(int index, int codeLength) - { - Debug.Assert(_codesList[index].Length == codeLength); - - return _codesList[index]; - } - - private RelocEntry[] GetRelocEntries(BinaryReader relocsReader, int relocEntriesCount) - { - RelocEntry[] relocEntries = new RelocEntry[relocEntriesCount]; - - for (int i = 0; i < relocEntriesCount; i++) - { - int position = relocsReader.ReadInt32(); - SymbolType type = (SymbolType)relocsReader.ReadByte(); - ulong value = relocsReader.ReadUInt64(); - - relocEntries[i] = new RelocEntry(position, new Symbol(type, value)); - } - - return relocEntries; - } - - private void PatchCode(Translator translator, Span<byte> code, RelocEntry[] relocEntries, out Counter<uint> callCounter) - { - callCounter = null; - - foreach (RelocEntry relocEntry in relocEntries) - { - IntPtr? imm = null; - Symbol symbol = relocEntry.Symbol; - - if (symbol.Type == SymbolType.FunctionTable) - { - ulong guestAddress = symbol.Value; - - if (translator.FunctionTable.IsValid(guestAddress)) - { - unsafe { imm = (IntPtr)Unsafe.AsPointer(ref translator.FunctionTable.GetValue(guestAddress)); } - } - } - else if (symbol.Type == SymbolType.DelegateTable) - { - int index = (int)symbol.Value; - - if (Delegates.TryGetDelegateFuncPtrByIndex(index, out IntPtr funcPtr)) - { - imm = funcPtr; - } - } - else if (symbol == PageTableSymbol) - { - imm = translator.Memory.PageTablePointer; - } - else if (symbol == CountTableSymbol) - { - if (callCounter == null) - { - callCounter = new Counter<uint>(translator.CountTable); - } - - unsafe { imm = (IntPtr)Unsafe.AsPointer(ref callCounter.Value); } - } - else if (symbol == DispatchStubSymbol) - { - imm = translator.Stubs.DispatchStub; - } - - if (imm == null) - { - throw new Exception($"Unexpected reloc entry {relocEntry}."); - } - - BinaryPrimitives.WriteUInt64LittleEndian(code.Slice(relocEntry.Position, 8), (ulong)imm.Value); - } - } - - private UnwindInfo ReadUnwindInfo(BinaryReader unwindInfosReader) - { - int pushEntriesLength = unwindInfosReader.ReadInt32(); - - UnwindPushEntry[] pushEntries = new UnwindPushEntry[pushEntriesLength]; - - for (int i = 0; i < pushEntriesLength; i++) - { - int pseudoOp = unwindInfosReader.ReadInt32(); - int prologOffset = unwindInfosReader.ReadInt32(); - int regIndex = unwindInfosReader.ReadInt32(); - int stackOffsetOrAllocSize = unwindInfosReader.ReadInt32(); - - pushEntries[i] = new UnwindPushEntry((UnwindPseudoOp)pseudoOp, prologOffset, regIndex, stackOffsetOrAllocSize); - } - - int prologueSize = unwindInfosReader.ReadInt32(); - - return new UnwindInfo(pushEntries, prologueSize); - } - - private TranslatedFunction FastTranslate( - byte[] code, - Counter<uint> callCounter, - ulong guestSize, - UnwindInfo unwindInfo, - bool highCq) - { - var cFunc = new CompiledFunction(code, unwindInfo, RelocInfo.Empty); - var gFunc = cFunc.MapWithPointer<GuestFunction>(out IntPtr gFuncPointer); - - return new TranslatedFunction(gFunc, gFuncPointer, callCounter, guestSize, highCq); - } - - private void UpdateInfo(InfoEntry infoEntry) - { - _infosStream.Seek(-Unsafe.SizeOf<InfoEntry>(), SeekOrigin.Current); - - SerializeStructure(_infosStream, infoEntry); - } - - private void StubCode(int index) - { - _codesList[index] = Array.Empty<byte>(); - } - - private void StubReloc(int relocEntriesCount) - { - for (int i = 0; i < relocEntriesCount * RelocEntry.Stride; i++) - { - _relocsStream.WriteByte(FillingByte); - } - } - - private void StubUnwindInfo(BinaryReader unwindInfosReader) - { - int pushEntriesLength = unwindInfosReader.ReadInt32(); - - for (int i = 0; i < pushEntriesLength * UnwindPushEntry.Stride + UnwindInfo.Stride; i++) - { - _unwindInfosStream.WriteByte(FillingByte); - } - } - - public void MakeAndSaveTranslations(Translator translator) - { - var profiledFuncsToTranslate = Profiler.GetProfiledFuncsToTranslate(translator.Functions); - - _translateCount = 0; - _translateTotalCount = profiledFuncsToTranslate.Count; - - if (_translateTotalCount == 0) - { - ResetCarriersIfNeeded(); - - GCSettings.LargeObjectHeapCompactionMode = GCLargeObjectHeapCompactionMode.CompactOnce; - - return; - } - - int degreeOfParallelism = Environment.ProcessorCount; - - // If there are enough cores lying around, we leave one alone for other tasks. - if (degreeOfParallelism > 4) - { - degreeOfParallelism--; - } - - Logger.Info?.Print(LogClass.Ptc, $"{_translateCount} of {_translateTotalCount} functions translated | Thread count: {degreeOfParallelism}"); - - PtcStateChanged?.Invoke(PtcLoadingState.Start, _translateCount, _translateTotalCount); - - using AutoResetEvent progressReportEvent = new AutoResetEvent(false); - - Thread progressReportThread = new Thread(ReportProgress) - { - Name = "Ptc.ProgressReporter", - Priority = ThreadPriority.Lowest, - IsBackground = true - }; - - progressReportThread.Start(progressReportEvent); - - void TranslateFuncs() - { - while (profiledFuncsToTranslate.TryDequeue(out var item)) - { - ulong address = item.address; - - Debug.Assert(Profiler.IsAddressInStaticCodeRange(address)); - - TranslatedFunction func = translator.Translate(address, item.funcProfile.Mode, item.funcProfile.HighCq); - - bool isAddressUnique = translator.Functions.TryAdd(address, func.GuestSize, func); - - Debug.Assert(isAddressUnique, $"The address 0x{address:X16} is not unique."); - - Interlocked.Increment(ref _translateCount); - - translator.RegisterFunction(address, func); - - if (State != PtcState.Enabled) - { - break; - } - } - } - - List<Thread> threads = new List<Thread>(); - - for (int i = 0; i < degreeOfParallelism; i++) - { - Thread thread = new Thread(TranslateFuncs); - thread.IsBackground = true; - - threads.Add(thread); - } - - Stopwatch sw = Stopwatch.StartNew(); - - threads.ForEach((thread) => thread.Start()); - threads.ForEach((thread) => thread.Join()); - - threads.Clear(); - - progressReportEvent.Set(); - progressReportThread.Join(); - - sw.Stop(); - - PtcStateChanged?.Invoke(PtcLoadingState.Loaded, _translateCount, _translateTotalCount); - - Logger.Info?.Print(LogClass.Ptc, $"{_translateCount} of {_translateTotalCount} functions translated | Thread count: {degreeOfParallelism} in {sw.Elapsed.TotalSeconds} s"); - - Thread preSaveThread = new Thread(PreSave); - preSaveThread.IsBackground = true; - preSaveThread.Start(); - } - - private void ReportProgress(object state) - { - const int refreshRate = 50; // ms. - - AutoResetEvent endEvent = (AutoResetEvent)state; - - int count = 0; - - do - { - int newCount = _translateCount; - - if (count != newCount) - { - PtcStateChanged?.Invoke(PtcLoadingState.Loading, newCount, _translateTotalCount); - count = newCount; - } - } - while (!endEvent.WaitOne(refreshRate)); - } - - public static Hash128 ComputeHash(IMemoryManager memory, ulong address, ulong guestSize) - { - return XXHash128.ComputeHash(memory.GetSpan(address, checked((int)(guestSize)))); - } - - public void WriteCompiledFunction(ulong address, ulong guestSize, Hash128 hash, bool highCq, CompiledFunction compiledFunc) - { - lock (_lock) - { - byte[] code = compiledFunc.Code; - RelocInfo relocInfo = compiledFunc.RelocInfo; - UnwindInfo unwindInfo = compiledFunc.UnwindInfo; - - InfoEntry infoEntry = new InfoEntry(); - - infoEntry.Address = address; - infoEntry.GuestSize = guestSize; - infoEntry.Hash = hash; - infoEntry.HighCq = highCq; - infoEntry.Stubbed = false; - infoEntry.CodeLength = code.Length; - infoEntry.RelocEntriesCount = relocInfo.Entries.Length; - - SerializeStructure(_infosStream, infoEntry); - - WriteCode(code.AsSpan()); - - // WriteReloc. - using var relocInfoWriter = new BinaryWriter(_relocsStream, EncodingCache.UTF8NoBOM, true); - - foreach (RelocEntry entry in relocInfo.Entries) - { - relocInfoWriter.Write(entry.Position); - relocInfoWriter.Write((byte)entry.Symbol.Type); - relocInfoWriter.Write(entry.Symbol.Value); - } - - // WriteUnwindInfo. - using var unwindInfoWriter = new BinaryWriter(_unwindInfosStream, EncodingCache.UTF8NoBOM, true); - - unwindInfoWriter.Write(unwindInfo.PushEntries.Length); - - foreach (UnwindPushEntry unwindPushEntry in unwindInfo.PushEntries) - { - unwindInfoWriter.Write((int)unwindPushEntry.PseudoOp); - unwindInfoWriter.Write(unwindPushEntry.PrologOffset); - unwindInfoWriter.Write(unwindPushEntry.RegIndex); - unwindInfoWriter.Write(unwindPushEntry.StackOffsetOrAllocSize); - } - - unwindInfoWriter.Write(unwindInfo.PrologSize); - } - } - - private void WriteCode(ReadOnlySpan<byte> code) - { - _codesList.Add(code.ToArray()); - } - - public static bool GetEndianness() - { - return BitConverter.IsLittleEndian; - } - - private static FeatureInfo GetFeatureInfo() - { - if (RuntimeInformation.ProcessArchitecture == Architecture.Arm64) - { - return new FeatureInfo( - (ulong)Arm64HardwareCapabilities.LinuxFeatureInfoHwCap, - (ulong)Arm64HardwareCapabilities.LinuxFeatureInfoHwCap2, - (ulong)Arm64HardwareCapabilities.MacOsFeatureInfo, - 0, - 0); - } - else if (RuntimeInformation.ProcessArchitecture == Architecture.X64) - { - return new FeatureInfo( - (ulong)X86HardwareCapabilities.FeatureInfo1Ecx, - (ulong)X86HardwareCapabilities.FeatureInfo1Edx, - (ulong)X86HardwareCapabilities.FeatureInfo7Ebx, - (ulong)X86HardwareCapabilities.FeatureInfo7Ecx, - (ulong)X86HardwareCapabilities.Xcr0InfoEax); - } - else - { - return new FeatureInfo(0, 0, 0, 0, 0); - } - } - - private byte GetMemoryManagerMode() - { - return (byte)_memoryMode; - } - - private static uint GetOSPlatform() - { - uint osPlatform = 0u; - - osPlatform |= (OperatingSystem.IsFreeBSD() ? 1u : 0u) << 0; - osPlatform |= (OperatingSystem.IsLinux() ? 1u : 0u) << 1; - osPlatform |= (OperatingSystem.IsMacOS() ? 1u : 0u) << 2; - osPlatform |= (OperatingSystem.IsWindows() ? 1u : 0u) << 3; - - return osPlatform; - } - - [StructLayout(LayoutKind.Sequential, Pack = 1/*, Size = 86*/)] - private struct OuterHeader - { - public ulong Magic; - - public uint CacheFileVersion; - - public bool Endianness; - public FeatureInfo FeatureInfo; - public byte MemoryManagerMode; - public uint OSPlatform; - public uint Architecture; - - public long UncompressedStreamSize; - - public Hash128 HeaderHash; - - public void SetHeaderHash() - { - Span<OuterHeader> spanHeader = MemoryMarshal.CreateSpan(ref this, 1); - - HeaderHash = XXHash128.ComputeHash(MemoryMarshal.AsBytes(spanHeader).Slice(0, Unsafe.SizeOf<OuterHeader>() - Unsafe.SizeOf<Hash128>())); - } - - public bool IsHeaderValid() - { - Span<OuterHeader> spanHeader = MemoryMarshal.CreateSpan(ref this, 1); - - return XXHash128.ComputeHash(MemoryMarshal.AsBytes(spanHeader).Slice(0, Unsafe.SizeOf<OuterHeader>() - Unsafe.SizeOf<Hash128>())) == HeaderHash; - } - } - - [StructLayout(LayoutKind.Sequential, Pack = 1/*, Size = 40*/)] - private record struct FeatureInfo(ulong FeatureInfo0, ulong FeatureInfo1, ulong FeatureInfo2, ulong FeatureInfo3, ulong FeatureInfo4); - - [StructLayout(LayoutKind.Sequential, Pack = 1/*, Size = 128*/)] - private struct InnerHeader - { - public ulong Magic; - - public int InfosLength; - public long CodesLength; - public int RelocsLength; - public int UnwindInfosLength; - - public Hash128 InfosHash; - public Hash128 CodesHash; - public Hash128 RelocsHash; - public Hash128 UnwindInfosHash; - - public Hash128 HeaderHash; - - public void SetHeaderHash() - { - Span<InnerHeader> spanHeader = MemoryMarshal.CreateSpan(ref this, 1); - - HeaderHash = XXHash128.ComputeHash(MemoryMarshal.AsBytes(spanHeader).Slice(0, Unsafe.SizeOf<InnerHeader>() - Unsafe.SizeOf<Hash128>())); - } - - public bool IsHeaderValid() - { - Span<InnerHeader> spanHeader = MemoryMarshal.CreateSpan(ref this, 1); - - return XXHash128.ComputeHash(MemoryMarshal.AsBytes(spanHeader).Slice(0, Unsafe.SizeOf<InnerHeader>() - Unsafe.SizeOf<Hash128>())) == HeaderHash; - } - } - - [StructLayout(LayoutKind.Sequential, Pack = 1/*, Size = 42*/)] - private struct InfoEntry - { - public ulong Address; - public ulong GuestSize; - public Hash128 Hash; - public bool HighCq; - public bool Stubbed; - public int CodeLength; - public int RelocEntriesCount; - } - - private void Enable() - { - State = PtcState.Enabled; - } - - public void Continue() - { - if (State == PtcState.Enabled) - { - State = PtcState.Continuing; - } - } - - public void Close() - { - if (State == PtcState.Enabled || - State == PtcState.Continuing) - { - State = PtcState.Closing; - } - } - - public void Disable() - { - State = PtcState.Disabled; - } - - private void Wait() - { - _waitEvent.WaitOne(); - } - - public void Dispose() - { - if (!_disposed) - { - _disposed = true; - - Wait(); - _waitEvent.Dispose(); - - DisposeCarriers(); - } - } - } -} diff --git a/ARMeilleure/Translation/PTC/PtcFormatter.cs b/ARMeilleure/Translation/PTC/PtcFormatter.cs deleted file mode 100644 index 2f7a9c21..00000000 --- a/ARMeilleure/Translation/PTC/PtcFormatter.cs +++ /dev/null @@ -1,179 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -namespace ARMeilleure.Translation.PTC -{ - static class PtcFormatter - { - #region "Deserialize" - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Dictionary<TKey, TValue> DeserializeDictionary<TKey, TValue>(Stream stream, Func<Stream, TValue> valueFunc) where TKey : struct - { - 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 : struct - { - 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 : struct - { - T structure = default(T); - - Span<T> spanT = MemoryMarshal.CreateSpan(ref structure, 1); - int bytesCount = stream.Read(MemoryMarshal.AsBytes(spanT)); - - if (bytesCount != Unsafe.SizeOf<T>()) - { - throw new EndOfStreamException(); - } - - return structure; - } - #endregion - - #region "GetSerializeSize" - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int GetSerializeSizeDictionary<TKey, TValue>(Dictionary<TKey, TValue> dictionary, Func<TValue, int> valueFunc) where TKey : struct - { - 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 : struct - { - 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 : struct - { - SerializeStructure<int>(stream, dictionary.Count); - - foreach ((TKey key, TValue value) in dictionary) - { - SerializeStructure<TKey>(stream, key); - valueAction(stream, value); - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void SerializeList<T>(Stream stream, List<T> list) where T : struct - { - SerializeStructure<int>(stream, list.Count); - - foreach (T item in list) - { - SerializeStructure<T>(stream, item); - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void SerializeStructure<T>(Stream stream, T structure) where T : struct - { - Span<T> spanT = MemoryMarshal.CreateSpan(ref structure, 1); - stream.Write(MemoryMarshal.AsBytes(spanT)); - } - #endregion - - #region "Extension methods" - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void ReadFrom<T>(this List<T[]> list, Stream stream) where T : struct - { - int count = DeserializeStructure<int>(stream); - - for (int i = 0; i < count; i++) - { - int itemLength = DeserializeStructure<int>(stream); - - T[] item = new T[itemLength]; - - int bytesCount = stream.Read(MemoryMarshal.AsBytes(item.AsSpan())); - - if (bytesCount != itemLength) - { - throw new EndOfStreamException(); - } - - list.Add(item); - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static long Length<T>(this List<T[]> list) where T : struct - { - long size = 0L; - - size += Unsafe.SizeOf<int>(); - - foreach (T[] item in list) - { - size += Unsafe.SizeOf<int>(); - size += item.Length; - } - - return size; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void WriteTo<T>(this List<T[]> list, Stream stream) where T : struct - { - SerializeStructure<int>(stream, list.Count); - - foreach (T[] item in list) - { - SerializeStructure<int>(stream, item.Length); - - stream.Write(MemoryMarshal.AsBytes(item.AsSpan())); - } - } - #endregion - } -}
\ No newline at end of file diff --git a/ARMeilleure/Translation/PTC/PtcLoadingState.cs b/ARMeilleure/Translation/PTC/PtcLoadingState.cs deleted file mode 100644 index 526cf91f..00000000 --- a/ARMeilleure/Translation/PTC/PtcLoadingState.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace ARMeilleure.Translation.PTC -{ - public enum PtcLoadingState - { - Start, - Loading, - Loaded - } -}
\ No newline at end of file diff --git a/ARMeilleure/Translation/PTC/PtcProfiler.cs b/ARMeilleure/Translation/PTC/PtcProfiler.cs deleted file mode 100644 index 391e29c7..00000000 --- a/ARMeilleure/Translation/PTC/PtcProfiler.cs +++ /dev/null @@ -1,421 +0,0 @@ -using ARMeilleure.State; -using Ryujinx.Common; -using Ryujinx.Common.Logging; -using Ryujinx.Common.Memory; -using System; -using System.Buffers.Binary; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.IO.Compression; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; -using System.Threading; - -using static ARMeilleure.Translation.PTC.PtcFormatter; - -namespace ARMeilleure.Translation.PTC -{ - class PtcProfiler - { - private const string OuterHeaderMagicString = "Pohd\0\0\0\0"; - - private const uint InternalVersion = 1866; //! Not to be incremented manually for each change to the ARMeilleure project. - - private const int SaveInterval = 30; // Seconds. - - private const CompressionLevel SaveCompressionLevel = CompressionLevel.Fastest; - - private readonly Ptc _ptc; - - private readonly System.Timers.Timer _timer; - - private readonly ulong _outerHeaderMagic; - - private readonly ManualResetEvent _waitEvent; - - private readonly object _lock; - - private bool _disposed; - - private Hash128 _lastHash; - - public Dictionary<ulong, FuncProfile> ProfiledFuncs { get; private set; } - - public bool Enabled { get; private set; } - - public ulong StaticCodeStart { get; set; } - public ulong StaticCodeSize { get; set; } - - public PtcProfiler(Ptc ptc) - { - _ptc = ptc; - - _timer = new System.Timers.Timer((double)SaveInterval * 1000d); - _timer.Elapsed += PreSave; - - _outerHeaderMagic = BinaryPrimitives.ReadUInt64LittleEndian(EncodingCache.UTF8NoBOM.GetBytes(OuterHeaderMagicString).AsSpan()); - - _waitEvent = new ManualResetEvent(true); - - _lock = new object(); - - _disposed = false; - - ProfiledFuncs = new Dictionary<ulong, FuncProfile>(); - - Enabled = false; - } - - public void AddEntry(ulong address, ExecutionMode mode, bool highCq) - { - if (IsAddressInStaticCodeRange(address)) - { - Debug.Assert(!highCq); - - lock (_lock) - { - ProfiledFuncs.TryAdd(address, new FuncProfile(mode, highCq: false)); - } - } - } - - public void UpdateEntry(ulong address, ExecutionMode mode, bool highCq) - { - if (IsAddressInStaticCodeRange(address)) - { - Debug.Assert(highCq); - - lock (_lock) - { - Debug.Assert(ProfiledFuncs.ContainsKey(address)); - - ProfiledFuncs[address] = new FuncProfile(mode, highCq: true); - } - } - } - - public bool IsAddressInStaticCodeRange(ulong address) - { - return address >= StaticCodeStart && address < StaticCodeStart + StaticCodeSize; - } - - public ConcurrentQueue<(ulong address, FuncProfile funcProfile)> GetProfiledFuncsToTranslate(TranslatorCache<TranslatedFunction> funcs) - { - var profiledFuncsToTranslate = new ConcurrentQueue<(ulong address, FuncProfile funcProfile)>(); - - foreach (var profiledFunc in ProfiledFuncs) - { - if (!funcs.ContainsKey(profiledFunc.Key)) - { - profiledFuncsToTranslate.Enqueue((profiledFunc.Key, profiledFunc.Value)); - } - } - - return profiledFuncsToTranslate; - } - - public void ClearEntries() - { - ProfiledFuncs.Clear(); - ProfiledFuncs.TrimExcess(); - } - - public void PreLoad() - { - _lastHash = default; - - string fileNameActual = $"{_ptc.CachePathActual}.info"; - string fileNameBackup = $"{_ptc.CachePathBackup}.info"; - - FileInfo fileInfoActual = new FileInfo(fileNameActual); - FileInfo fileInfoBackup = new FileInfo(fileNameBackup); - - if (fileInfoActual.Exists && fileInfoActual.Length != 0L) - { - if (!Load(fileNameActual, false)) - { - if (fileInfoBackup.Exists && fileInfoBackup.Length != 0L) - { - Load(fileNameBackup, true); - } - } - } - else if (fileInfoBackup.Exists && fileInfoBackup.Length != 0L) - { - Load(fileNameBackup, true); - } - } - - private bool Load(string fileName, bool isBackup) - { - using (FileStream compressedStream = new(fileName, FileMode.Open)) - using (DeflateStream deflateStream = new(compressedStream, CompressionMode.Decompress, true)) - { - OuterHeader outerHeader = DeserializeStructure<OuterHeader>(compressedStream); - - if (!outerHeader.IsHeaderValid()) - { - InvalidateCompressedStream(compressedStream); - - return false; - } - - if (outerHeader.Magic != _outerHeaderMagic) - { - InvalidateCompressedStream(compressedStream); - - return false; - } - - if (outerHeader.InfoFileVersion != InternalVersion) - { - InvalidateCompressedStream(compressedStream); - - return false; - } - - if (outerHeader.Endianness != Ptc.GetEndianness()) - { - InvalidateCompressedStream(compressedStream); - - return false; - } - - using (MemoryStream stream = MemoryStreamManager.Shared.GetStream()) - { - Debug.Assert(stream.Seek(0L, SeekOrigin.Begin) == 0L && stream.Length == 0L); - - try - { - deflateStream.CopyTo(stream); - } - catch - { - InvalidateCompressedStream(compressedStream); - - return false; - } - - Debug.Assert(stream.Position == stream.Length); - - stream.Seek(0L, SeekOrigin.Begin); - - Hash128 expectedHash = DeserializeStructure<Hash128>(stream); - - Hash128 actualHash = XXHash128.ComputeHash(GetReadOnlySpan(stream)); - - if (actualHash != expectedHash) - { - InvalidateCompressedStream(compressedStream); - - return false; - } - - ProfiledFuncs = Deserialize(stream); - - Debug.Assert(stream.Position == stream.Length); - - _lastHash = actualHash; - } - } - - long fileSize = new FileInfo(fileName).Length; - - Logger.Info?.Print(LogClass.Ptc, $"{(isBackup ? "Loaded Backup Profiling Info" : "Loaded Profiling Info")} (size: {fileSize} bytes, profiled functions: {ProfiledFuncs.Count})."); - - return true; - } - - private static Dictionary<ulong, FuncProfile> Deserialize(Stream stream) - { - return DeserializeDictionary<ulong, FuncProfile>(stream, (stream) => DeserializeStructure<FuncProfile>(stream)); - } - - private ReadOnlySpan<byte> GetReadOnlySpan(MemoryStream memoryStream) - { - return new(memoryStream.GetBuffer(), (int)memoryStream.Position, (int)memoryStream.Length - (int)memoryStream.Position); - } - - private void InvalidateCompressedStream(FileStream compressedStream) - { - compressedStream.SetLength(0L); - } - - private void PreSave(object source, System.Timers.ElapsedEventArgs e) - { - _waitEvent.Reset(); - - string fileNameActual = $"{_ptc.CachePathActual}.info"; - string fileNameBackup = $"{_ptc.CachePathBackup}.info"; - - FileInfo fileInfoActual = new FileInfo(fileNameActual); - - if (fileInfoActual.Exists && fileInfoActual.Length != 0L) - { - File.Copy(fileNameActual, fileNameBackup, true); - } - - Save(fileNameActual); - - _waitEvent.Set(); - } - - private void Save(string fileName) - { - int profiledFuncsCount; - - OuterHeader outerHeader = new OuterHeader(); - - outerHeader.Magic = _outerHeaderMagic; - - outerHeader.InfoFileVersion = InternalVersion; - outerHeader.Endianness = Ptc.GetEndianness(); - - outerHeader.SetHeaderHash(); - - using (MemoryStream stream = MemoryStreamManager.Shared.GetStream()) - { - Debug.Assert(stream.Seek(0L, SeekOrigin.Begin) == 0L && stream.Length == 0L); - - stream.Seek((long)Unsafe.SizeOf<Hash128>(), SeekOrigin.Begin); - - lock (_lock) - { - Serialize(stream, ProfiledFuncs); - - profiledFuncsCount = ProfiledFuncs.Count; - } - - Debug.Assert(stream.Position == stream.Length); - - stream.Seek((long)Unsafe.SizeOf<Hash128>(), SeekOrigin.Begin); - Hash128 hash = XXHash128.ComputeHash(GetReadOnlySpan(stream)); - - stream.Seek(0L, SeekOrigin.Begin); - SerializeStructure(stream, hash); - - if (hash == _lastHash) - { - return; - } - - using (FileStream compressedStream = new(fileName, FileMode.OpenOrCreate)) - using (DeflateStream deflateStream = new(compressedStream, SaveCompressionLevel, true)) - { - try - { - SerializeStructure(compressedStream, outerHeader); - - stream.WriteTo(deflateStream); - - _lastHash = hash; - } - catch - { - compressedStream.Position = 0L; - - _lastHash = default; - } - - if (compressedStream.Position < compressedStream.Length) - { - compressedStream.SetLength(compressedStream.Position); - } - } - } - - long fileSize = new FileInfo(fileName).Length; - - if (fileSize != 0L) - { - Logger.Info?.Print(LogClass.Ptc, $"Saved Profiling Info (size: {fileSize} bytes, profiled functions: {profiledFuncsCount})."); - } - } - - private void Serialize(Stream stream, Dictionary<ulong, FuncProfile> profiledFuncs) - { - SerializeDictionary(stream, profiledFuncs, (stream, structure) => SerializeStructure(stream, structure)); - } - - [StructLayout(LayoutKind.Sequential, Pack = 1/*, Size = 29*/)] - private struct OuterHeader - { - public ulong Magic; - - public uint InfoFileVersion; - - public bool Endianness; - - public Hash128 HeaderHash; - - public void SetHeaderHash() - { - Span<OuterHeader> spanHeader = MemoryMarshal.CreateSpan(ref this, 1); - - HeaderHash = XXHash128.ComputeHash(MemoryMarshal.AsBytes(spanHeader).Slice(0, Unsafe.SizeOf<OuterHeader>() - Unsafe.SizeOf<Hash128>())); - } - - public bool IsHeaderValid() - { - Span<OuterHeader> spanHeader = MemoryMarshal.CreateSpan(ref this, 1); - - return XXHash128.ComputeHash(MemoryMarshal.AsBytes(spanHeader).Slice(0, Unsafe.SizeOf<OuterHeader>() - Unsafe.SizeOf<Hash128>())) == HeaderHash; - } - } - - [StructLayout(LayoutKind.Sequential, Pack = 1/*, Size = 5*/)] - public struct FuncProfile - { - public ExecutionMode Mode; - public bool HighCq; - - public FuncProfile(ExecutionMode mode, bool highCq) - { - Mode = mode; - HighCq = highCq; - } - } - - public void Start() - { - if (_ptc.State == PtcState.Enabled || - _ptc.State == PtcState.Continuing) - { - Enabled = true; - - _timer.Enabled = true; - } - } - - public void Stop() - { - Enabled = false; - - if (!_disposed) - { - _timer.Enabled = false; - } - } - - public void Wait() - { - _waitEvent.WaitOne(); - } - - public void Dispose() - { - if (!_disposed) - { - _disposed = true; - - _timer.Elapsed -= PreSave; - _timer.Dispose(); - - Wait(); - _waitEvent.Dispose(); - } - } - } -}
\ No newline at end of file diff --git a/ARMeilleure/Translation/PTC/PtcState.cs b/ARMeilleure/Translation/PTC/PtcState.cs deleted file mode 100644 index ca4f4108..00000000 --- a/ARMeilleure/Translation/PTC/PtcState.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace ARMeilleure.Translation.PTC -{ - enum PtcState - { - Enabled, - Continuing, - Closing, - Disabled - } -}
\ No newline at end of file |
