diff --git a/ARMeilleure/CodeGen/RegisterAllocators/LinearScanAllocator.cs b/ARMeilleure/CodeGen/RegisterAllocators/LinearScanAllocator.cs index 71739d436e..99400a39c5 100644 --- a/ARMeilleure/CodeGen/RegisterAllocators/LinearScanAllocator.cs +++ b/ARMeilleure/CodeGen/RegisterAllocators/LinearScanAllocator.cs @@ -50,6 +50,8 @@ namespace ARMeilleure.CodeGen.RegisterAllocators StackAlloc = stackAlloc; Masks = masks; + BitMapPool.PrepareBitMapPool(); + Active = BitMapPool.Allocate(intervalsCount); Inactive = BitMapPool.Allocate(intervalsCount); } @@ -73,7 +75,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators public void Dispose() { - BitMapPool.Release(); + BitMapPool.ResetBitMapPool(); } } @@ -84,57 +86,51 @@ namespace ARMeilleure.CodeGen.RegisterAllocators { NumberLocals(cfg); - AllocationContext context = new AllocationContext(stackAlloc, regMasks, _intervals.Count); - - BuildIntervals(cfg, context); - - for (int index = 0; index < _intervals.Count; index++) + using (AllocationContext context = new AllocationContext(stackAlloc, regMasks, _intervals.Count)) { - LiveInterval current = _intervals[index]; + BuildIntervals(cfg, context); - if (current.IsEmpty) + for (int index = 0; index < _intervals.Count; index++) { - continue; - } + LiveInterval current = _intervals[index]; - if (current.IsFixed) - { - context.Active.Set(index); - - if (current.Register.Type == RegisterType.Integer) + if (current.IsEmpty) { - context.IntUsedRegisters |= 1 << current.Register.Index; - } - else /* if (interval.Register.Type == RegisterType.Vector) */ - { - context.VecUsedRegisters |= 1 << current.Register.Index; + continue; } - continue; + if (current.IsFixed) + { + context.Active.Set(index); + + if (current.Register.Type == RegisterType.Integer) + { + context.IntUsedRegisters |= 1 << current.Register.Index; + } + else /* if (interval.Register.Type == RegisterType.Vector) */ + { + context.VecUsedRegisters |= 1 << current.Register.Index; + } + + continue; + } + + AllocateInterval(context, current, index); } - AllocateInterval(context, current, index); - } - - for (int index = RegistersCount * 2; index < _intervals.Count; index++) - { - if (!_intervals[index].IsSpilled) + for (int index = RegistersCount * 2; index < _intervals.Count; index++) { - ReplaceLocalWithRegister(_intervals[index]); + if (!_intervals[index].IsSpilled) + { + ReplaceLocalWithRegister(_intervals[index]); + } } + + InsertSplitCopies(); + InsertSplitCopiesAtEdges(cfg); + + return new AllocationResult(context.IntUsedRegisters, context.VecUsedRegisters, context.StackAlloc.TotalSize); } - - InsertSplitCopies(); - InsertSplitCopiesAtEdges(cfg); - - AllocationResult result = new AllocationResult( - context.IntUsedRegisters, - context.VecUsedRegisters, - context.StackAlloc.TotalSize); - - context.Dispose(); - - return result; } private void AllocateInterval(AllocationContext context, LiveInterval current, int cIndex) diff --git a/ARMeilleure/CodeGen/X86/CodeGenContext.cs b/ARMeilleure/CodeGen/X86/CodeGenContext.cs index da147cca29..67ee0afea7 100644 --- a/ARMeilleure/CodeGen/X86/CodeGenContext.cs +++ b/ARMeilleure/CodeGen/X86/CodeGenContext.cs @@ -2,6 +2,7 @@ using ARMeilleure.CodeGen.RegisterAllocators; using ARMeilleure.Common; using ARMeilleure.IntermediateRepresentation; using ARMeilleure.Translation.PTC; +using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; @@ -301,7 +302,7 @@ namespace ARMeilleure.CodeGen.X86 { Assembler assembler = new Assembler(codeStream, _ptcInfo); - byte[] buffer; + Span buffer; for (int index = 0; index < _jumps.Count; index++) { @@ -309,7 +310,7 @@ namespace ARMeilleure.CodeGen.X86 buffer = new byte[jump.JumpPosition - _stream.Position]; - _stream.Read(buffer, 0, buffer.Length); + _stream.Read(buffer); _stream.Seek(_ptcDisabled ? ReservedBytesForJump : jump.InstSize, SeekOrigin.Current); codeStream.Write(buffer); @@ -326,7 +327,7 @@ namespace ARMeilleure.CodeGen.X86 buffer = new byte[_stream.Length - _stream.Position]; - _stream.Read(buffer, 0, buffer.Length); + _stream.Read(buffer); codeStream.Write(buffer); diff --git a/ARMeilleure/Common/BitMap.cs b/ARMeilleure/Common/BitMap.cs index b1c9a6735d..f782ac8b97 100644 --- a/ARMeilleure/Common/BitMap.cs +++ b/ARMeilleure/Common/BitMap.cs @@ -35,7 +35,7 @@ namespace ARMeilleure.Common } } - public void Reset(int initialCapacity) + public BitMap Reset(int initialCapacity) { int count = (initialCapacity + IntMask) / IntSize; @@ -50,6 +50,8 @@ namespace ARMeilleure.Common { _masks.Add(0); } + + return this; } public bool Set(int bit) diff --git a/ARMeilleure/Common/BitMapPool.cs b/ARMeilleure/Common/BitMapPool.cs index aac32d55fb..d8d297faf0 100644 --- a/ARMeilleure/Common/BitMapPool.cs +++ b/ARMeilleure/Common/BitMapPool.cs @@ -4,15 +4,29 @@ { public static BitMap Allocate(int initialCapacity) { - BitMap result = ThreadStaticPool.Instance.Allocate(); - result.Reset(initialCapacity); - - return result; + return BitMap().Reset(initialCapacity); } - public static void Release() + #region "ThreadStaticPool" + public static void PrepareBitMapPool(int groupId = 0) { - ThreadStaticPool.Instance.Clear(); + ThreadStaticPool.PreparePool(groupId, ChunkSizeLimit.Small); } + + private static BitMap BitMap() + { + return ThreadStaticPool.Instance.Allocate(); + } + + public static void ResetBitMapPool(int groupId = 0) + { + ThreadStaticPool.ResetPool(groupId); + } + + public static void DisposeBitMapPools() + { + ThreadStaticPool.DisposePools(); + } + #endregion } } diff --git a/ARMeilleure/Common/ThreadStaticPool.cs b/ARMeilleure/Common/ThreadStaticPool.cs index e23bf1dce5..bbe662f827 100644 --- a/ARMeilleure/Common/ThreadStaticPool.cs +++ b/ARMeilleure/Common/ThreadStaticPool.cs @@ -1,4 +1,5 @@ -using System; +using ARMeilleure.Translation.PTC; +using System; using System.Collections.Concurrent; using System.Collections.Generic; @@ -6,9 +7,6 @@ namespace ARMeilleure.Common { class ThreadStaticPool where T : class, new() { - private const int ChunkSizeLimit = 1000; // even - private const int PoolSizeIncrement = 200; // > 0 - [ThreadStatic] private static ThreadStaticPool _instance; @@ -18,21 +16,36 @@ namespace ARMeilleure.Common { if (_instance == null) { - PreparePool(0); // So that we can still use a pool when blindly initializing one. + PreparePool(); // So that we can still use a pool when blindly initializing one. } return _instance; } } - private static ConcurrentDictionary>> _pools = new(); + private static readonly ConcurrentDictionary>> _pools = new(); private static Stack> GetPools(int groupId) { return _pools.GetOrAdd(groupId, (groupId) => new()); } - public static void PreparePool(int groupId) + public static void PreparePool( + int groupId = 0, + ChunkSizeLimit chunkSizeLimit = ChunkSizeLimit.Large, + PoolSizeIncrement poolSizeIncrement = PoolSizeIncrement.Default) + { + if (Ptc.State == PtcState.Disabled) + { + PreparePoolDefault(groupId, (int)chunkSizeLimit, (int)poolSizeIncrement); + } + else + { + PreparePoolSlim((int)chunkSizeLimit, (int)poolSizeIncrement); + } + } + + private static void PreparePoolDefault(int groupId, int chunkSizeLimit, int poolSizeIncrement) { // Prepare the pool for this thread, ideally using an existing one from the specified group. @@ -41,27 +54,75 @@ namespace ARMeilleure.Common var pools = GetPools(groupId); lock (pools) { - _instance = (pools.Count != 0) ? pools.Pop() : new(); + _instance = (pools.Count != 0) ? pools.Pop() : new(chunkSizeLimit, poolSizeIncrement); } } } - public static void ReturnPool(int groupId) + private static void PreparePoolSlim(int chunkSizeLimit, int poolSizeIncrement) { - // Reset, limit if necessary, and return the pool for this thread to the specified group. + // Prepare the pool for this thread. - var pools = GetPools(groupId); - lock (pools) + if (_instance == null) { - _instance.Clear(); - _instance.ChunkSizeLimiter(); - pools.Push(_instance); - - _instance = null; + _instance = new(chunkSizeLimit, poolSizeIncrement); } } - public static void ResetPools() + public static void ResetPool(int groupId = 0) + { + if (Ptc.State == PtcState.Disabled) + { + ResetPoolDefault(groupId); + } + else + { + ResetPoolSlim(); + } + } + + private static void ResetPoolDefault(int groupId) + { + // Reset, limit if necessary, and return the pool for this thread to the specified group. + + if (_instance != null) + { + var pools = GetPools(groupId); + lock (pools) + { + _instance.Clear(); + _instance.ChunkSizeLimiter(); + pools.Push(_instance); + + _instance = null; + } + } + } + + private static void ResetPoolSlim() + { + // Reset, limit if necessary, the pool for this thread. + + if (_instance != null) + { + _instance.Clear(); + _instance.ChunkSizeLimiter(); + } + } + + public static void DisposePools() + { + if (Ptc.State == PtcState.Disabled) + { + DisposePoolsDefault(); + } + else + { + DisposePoolSlim(); + } + } + + private static void DisposePoolsDefault() { // Resets any static references to the pools used by threads for each group, allowing them to be garbage collected. @@ -78,20 +139,37 @@ namespace ARMeilleure.Common _pools.Clear(); } + private static void DisposePoolSlim() + { + // Dispose the pool for this thread. + + if (_instance != null) + { + _instance.Dispose(); + + _instance = null; + } + } + private List _pool; private int _chunkIndex = -1; private int _poolIndex = -1; + private int _chunkSizeLimit; + private int _poolSizeIncrement; - private ThreadStaticPool() + private ThreadStaticPool(int chunkSizeLimit, int poolSizeIncrement) { - _pool = new(ChunkSizeLimit * 2); + _chunkSizeLimit = chunkSizeLimit; + _poolSizeIncrement = poolSizeIncrement; + + _pool = new(chunkSizeLimit * 2); AddChunkIfNeeded(); } public T Allocate() { - if (++_poolIndex >= PoolSizeIncrement) + if (++_poolIndex >= _poolSizeIncrement) { AddChunkIfNeeded(); @@ -105,9 +183,9 @@ namespace ARMeilleure.Common { if (++_chunkIndex >= _pool.Count) { - T[] pool = new T[PoolSizeIncrement]; + T[] pool = new T[_poolSizeIncrement]; - for (int i = 0; i < PoolSizeIncrement; i++) + for (int i = 0; i < _poolSizeIncrement; i++) { pool[i] = new T(); } @@ -124,18 +202,18 @@ namespace ARMeilleure.Common private void ChunkSizeLimiter() { - if (_pool.Count >= ChunkSizeLimit) + if (_pool.Count >= _chunkSizeLimit) { - int newChunkSize = ChunkSizeLimit / 2; + int newChunkSize = _chunkSizeLimit / 2; _pool.RemoveRange(newChunkSize, _pool.Count - newChunkSize); - _pool.Capacity = ChunkSizeLimit * 2; + _pool.Capacity = _chunkSizeLimit * 2; } } private void Dispose() { - _pool.Clear(); + _pool = null; } } } diff --git a/ARMeilleure/Common/ThreadStaticPoolEnums.cs b/ARMeilleure/Common/ThreadStaticPoolEnums.cs new file mode 100644 index 0000000000..0d1d98d3cb --- /dev/null +++ b/ARMeilleure/Common/ThreadStaticPoolEnums.cs @@ -0,0 +1,14 @@ +namespace ARMeilleure.Common +{ + public enum PoolSizeIncrement + { + Default = 200 + } + + public enum ChunkSizeLimit + { + Large = 200000 / PoolSizeIncrement.Default, + Medium = 100000 / PoolSizeIncrement.Default, + Small = 50000 / PoolSizeIncrement.Default + } +} \ No newline at end of file diff --git a/ARMeilleure/IntermediateRepresentation/OperandHelper.cs b/ARMeilleure/IntermediateRepresentation/OperandHelper.cs index f7381d869f..26d6647835 100644 --- a/ARMeilleure/IntermediateRepresentation/OperandHelper.cs +++ b/ARMeilleure/IntermediateRepresentation/OperandHelper.cs @@ -4,16 +4,6 @@ namespace ARMeilleure.IntermediateRepresentation { static class OperandHelper { - private static MemoryOperand MemoryOperand() - { - return ThreadStaticPool.Instance.Allocate(); - } - - private static Operand Operand() - { - return ThreadStaticPool.Instance.Allocate(); - } - public static Operand Const(OperandType type, long value) { return type == OperandType.I32 ? Operand().With((int)value) : Operand().With(value); @@ -84,22 +74,34 @@ namespace ARMeilleure.IntermediateRepresentation return MemoryOperand().With(type, baseAddress, index, scale, displacement); } - public static void PrepareOperandPool(bool highCq) + #region "ThreadStaticPool" + public static void PrepareOperandPool(int groupId = 0) { - ThreadStaticPool.PreparePool(highCq ? 1 : 0); - ThreadStaticPool.PreparePool(highCq ? 1 : 0); + ThreadStaticPool.PreparePool(groupId, ChunkSizeLimit.Large); + ThreadStaticPool.PreparePool(groupId, ChunkSizeLimit.Small); } - public static void ReturnOperandPool(bool highCq) + private static Operand Operand() { - ThreadStaticPool.ReturnPool(highCq ? 1 : 0); - ThreadStaticPool.ReturnPool(highCq ? 1 : 0); + return ThreadStaticPool.Instance.Allocate(); } - public static void ResetOperandPools() + private static MemoryOperand MemoryOperand() { - ThreadStaticPool.ResetPools(); - ThreadStaticPool.ResetPools(); + return ThreadStaticPool.Instance.Allocate(); } + + public static void ResetOperandPool(int groupId = 0) + { + ThreadStaticPool.ResetPool(groupId); + ThreadStaticPool.ResetPool(groupId); + } + + public static void DisposeOperandPools() + { + ThreadStaticPool.DisposePools(); + ThreadStaticPool.DisposePools(); + } + #endregion } } diff --git a/ARMeilleure/IntermediateRepresentation/OperationHelper.cs b/ARMeilleure/IntermediateRepresentation/OperationHelper.cs index 538bdac485..0e560ee0a2 100644 --- a/ARMeilleure/IntermediateRepresentation/OperationHelper.cs +++ b/ARMeilleure/IntermediateRepresentation/OperationHelper.cs @@ -4,11 +4,6 @@ namespace ARMeilleure.IntermediateRepresentation { static class OperationHelper { - public static Operation Operation() - { - return ThreadStaticPool.Instance.Allocate(); - } - public static Operation Operation(Instruction instruction, Operand destination) { return Operation().With(instruction, destination); @@ -46,19 +41,26 @@ namespace ARMeilleure.IntermediateRepresentation return Operation().With(instruction, destinations, sources); } - public static void PrepareOperationPool(bool highCq) + #region "ThreadStaticPool" + public static void PrepareOperationPool(int groupId = 0) { - ThreadStaticPool.PreparePool(highCq ? 1 : 0); + ThreadStaticPool.PreparePool(groupId, ChunkSizeLimit.Medium); } - public static void ReturnOperationPool(bool highCq) + private static Operation Operation() { - ThreadStaticPool.ReturnPool(highCq ? 1 : 0); + return ThreadStaticPool.Instance.Allocate(); } - public static void ResetOperationPools() + public static void ResetOperationPool(int groupId = 0) { - ThreadStaticPool.ResetPools(); + ThreadStaticPool.ResetPool(groupId); } + + public static void DisposeOperationPools() + { + ThreadStaticPool.DisposePools(); + } + #endregion } } diff --git a/ARMeilleure/Translation/DirectCallStubs.cs b/ARMeilleure/Translation/DirectCallStubs.cs index df7ca16e7f..85af690187 100644 --- a/ARMeilleure/Translation/DirectCallStubs.cs +++ b/ARMeilleure/Translation/DirectCallStubs.cs @@ -29,11 +29,17 @@ namespace ARMeilleure.Translation { if (_initialized) return; + Translator.PreparePool(); + _directCallStubPtr = Marshal.GetFunctionPointerForDelegate(GenerateDirectCallStub(false)); _directTailCallStubPtr = Marshal.GetFunctionPointerForDelegate(GenerateDirectCallStub(true)); _indirectCallStubPtr = Marshal.GetFunctionPointerForDelegate(GenerateIndirectCallStub(false)); _indirectTailCallStubPtr = Marshal.GetFunctionPointerForDelegate(GenerateIndirectCallStub(true)); + Translator.ResetPool(); + + Translator.DisposePools(); + _initialized = true; } } diff --git a/ARMeilleure/Translation/JumpTableEntryAllocator.cs b/ARMeilleure/Translation/JumpTableEntryAllocator.cs deleted file mode 100644 index 3b918628ff..0000000000 --- a/ARMeilleure/Translation/JumpTableEntryAllocator.cs +++ /dev/null @@ -1,72 +0,0 @@ -using ARMeilleure.Common; -using System.Collections.Generic; -using System.Diagnostics; - -namespace ARMeilleure.Translation -{ - class JumpTableEntryAllocator - { - private readonly BitMap _bitmap; - private int _freeHint; - - public JumpTableEntryAllocator() - { - _bitmap = new BitMap(); - } - - public bool EntryIsValid(int entryIndex) - { - lock (_bitmap) - { - return _bitmap.IsSet(entryIndex); - } - } - - public void SetEntry(int entryIndex) - { - lock (_bitmap) - { - _bitmap.Set(entryIndex); - } - } - - public int AllocateEntry() - { - lock (_bitmap) - { - int entryIndex; - - if (!_bitmap.IsSet(_freeHint)) - { - entryIndex = _freeHint; - } - else - { - entryIndex = _bitmap.FindFirstUnset(); - } - - _freeHint = entryIndex + 1; - - bool wasSet = _bitmap.Set(entryIndex); - Debug.Assert(wasSet); - - return entryIndex; - } - } - - public void FreeEntry(int entryIndex) - { - lock (_bitmap) - { - _bitmap.Clear(entryIndex); - - _freeHint = entryIndex; - } - } - - public IEnumerable GetEntries() - { - return _bitmap; - } - } -} diff --git a/ARMeilleure/Translation/PTC/Ptc.cs b/ARMeilleure/Translation/PTC/Ptc.cs index 8f250a5528..2ca39bfb80 100644 --- a/ARMeilleure/Translation/PTC/Ptc.cs +++ b/ARMeilleure/Translation/PTC/Ptc.cs @@ -12,6 +12,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.IO.Compression; +using System.Runtime; using System.Runtime.InteropServices; using System.Security.Cryptography; using System.Threading; @@ -20,9 +21,9 @@ namespace ARMeilleure.Translation.PTC { public static class Ptc { - private const string HeaderMagic = "PTChd"; + private const string HeaderMagicString = "PTChd\0\0\0"; - private const int InternalVersion = 1817; //! To be incremented manually for each change to the ARMeilleure project. + private const uint InternalVersion = 1817; //! To be incremented manually for each change to the ARMeilleure project. private const string ActualDir = "0"; private const string BackupDir = "1"; @@ -37,12 +38,14 @@ namespace ARMeilleure.Translation.PTC private const byte FillingByte = 0x00; private const CompressionLevel SaveCompressionLevel = CompressionLevel.Fastest; - private static readonly MemoryStream _infosStream; - private static readonly MemoryStream _codesStream; - private static readonly MemoryStream _relocsStream; - private static readonly MemoryStream _unwindInfosStream; + private static MemoryStream _infosStream; + private static MemoryStream _codesStream; + private static MemoryStream _relocsStream; + private static MemoryStream _unwindInfosStream; - private static readonly BinaryWriter _infosWriter; + private static BinaryWriter _infosWriter; + + private static readonly ulong _headerMagic; private static readonly ManualResetEvent _waitEvent; @@ -73,6 +76,8 @@ namespace ARMeilleure.Translation.PTC _infosWriter = new BinaryWriter(_infosStream, EncodingCache.UTF8NoBOM, true); + _headerMagic = BitConverter.ToUInt64(EncodingCache.UTF8NoBOM.GetBytes(HeaderMagicString), 0); + _waitEvent = new ManualResetEvent(true); _loggerEvent = new AutoResetEvent(false); @@ -95,13 +100,13 @@ namespace ARMeilleure.Translation.PTC public static void Initialize(string titleIdText, string displayVersion, bool enabled) { Wait(); - ClearMemoryStreams(); - PtcJumpTable.Clear(); PtcProfiler.Wait(); PtcProfiler.ClearEntries(); - if (String.IsNullOrEmpty(titleIdText) || titleIdText == TitleIdTextDefault) + Logger.Info?.Print(LogClass.Ptc, $"Initializing Profiled Persistent Translation Cache (enabled: {enabled})."); + + if (!enabled || String.IsNullOrEmpty(titleIdText) || titleIdText == TitleIdTextDefault) { TitleIdText = TitleIdTextDefault; DisplayVersion = DisplayVersionDefault; @@ -114,49 +119,54 @@ namespace ARMeilleure.Translation.PTC return; } - Logger.Info?.Print(LogClass.Ptc, $"Initializing Profiled Persistent Translation Cache (enabled: {enabled})."); - TitleIdText = titleIdText; DisplayVersion = !String.IsNullOrEmpty(displayVersion) ? displayVersion : DisplayVersionDefault; - if (enabled) + string workPathActual = Path.Combine(AppDataManager.GamesDirPath, TitleIdText, "cache", "cpu", ActualDir); + string workPathBackup = Path.Combine(AppDataManager.GamesDirPath, TitleIdText, "cache", "cpu", BackupDir); + + if (!Directory.Exists(workPathActual)) { - 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); - - Enable(); - - PreLoad(); - PtcProfiler.PreLoad(); + Directory.CreateDirectory(workPathActual); } - else + + if (!Directory.Exists(workPathBackup)) { - CachePathActual = string.Empty; - CachePathBackup = string.Empty; - - Disable(); + Directory.CreateDirectory(workPathBackup); } + + CachePathActual = Path.Combine(workPathActual, DisplayVersion); + CachePathBackup = Path.Combine(workPathBackup, DisplayVersion); + + PreLoad(); + PtcProfiler.PreLoad(); + + Enable(); } - internal static void ClearMemoryStreams() + private static void ResetMemoryStreamsIfNeeded() { - _infosStream.SetLength(0L); - _codesStream.SetLength(0L); - _relocsStream.SetLength(0L); - _unwindInfosStream.SetLength(0L); + if (_infosStream.Length == 0L && + _codesStream.Length == 0L && + _relocsStream.Length == 0L && + _unwindInfosStream.Length == 0L) + { + return; + } + + _infosWriter.Dispose(); + + _infosStream.Dispose(); + _codesStream.Dispose(); + _relocsStream.Dispose(); + _unwindInfosStream.Dispose(); + + _infosStream = new MemoryStream(); + _codesStream = new MemoryStream(); + _relocsStream = new MemoryStream(); + _unwindInfosStream = new MemoryStream(); + + _infosWriter = new BinaryWriter(_infosStream, EncodingCache.UTF8NoBOM, true); } private static void PreLoad() @@ -183,106 +193,153 @@ namespace ARMeilleure.Translation.PTC } } - private static bool Load(string fileName, bool isBackup) + private static unsafe bool Load(string fileName, bool isBackup) { using (FileStream compressedStream = new FileStream(fileName, FileMode.Open)) using (DeflateStream deflateStream = new DeflateStream(compressedStream, CompressionMode.Decompress, true)) - using (MemoryStream stream = new MemoryStream()) - using (MD5 md5 = MD5.Create()) { - int hashSize = md5.HashSize / 8; + IntPtr intPtr = IntPtr.Zero; try { - deflateStream.CopyTo(stream); + MD5 md5 = MD5.Create(); + + int hashSize = md5.HashSize / 8; + + byte[] currentSizeHash = new byte[hashSize]; + compressedStream.Read(currentSizeHash, 0, hashSize); + + byte[] sizeBytes = new byte[sizeof(int)]; + compressedStream.Read(sizeBytes, 0, sizeBytes.Length); + + byte[] expectedSizeHash = md5.ComputeHash(sizeBytes); + + if (!CompareHash(currentSizeHash, expectedSizeHash)) + { + InvalidateCompressedStream(compressedStream); + + return false; + } + + int size = BitConverter.ToInt32(sizeBytes, 0); + + intPtr = Marshal.AllocHGlobal(size); + + using (UnmanagedMemoryStream stream = new UnmanagedMemoryStream((byte*)intPtr.ToPointer(), size, size, FileAccess.ReadWrite)) + { + try + { + deflateStream.CopyTo(stream); + } + catch + { + InvalidateCompressedStream(compressedStream); + + return false; + } + + stream.Seek(0L, SeekOrigin.Begin); + + byte[] currentHash = new byte[hashSize]; + stream.Read(currentHash, 0, hashSize); + + byte[] expectedHash = md5.ComputeHash(stream); + + md5.Dispose(); + + if (!CompareHash(currentHash, expectedHash)) + { + InvalidateCompressedStream(compressedStream); + + return false; + } + + stream.Seek((long)hashSize, SeekOrigin.Begin); + + Header header = ReadHeader(stream); + + if (header.Magic != _headerMagic) + { + InvalidateCompressedStream(compressedStream); + + return false; + } + + if (header.CacheFileVersion != InternalVersion) + { + InvalidateCompressedStream(compressedStream); + + return false; + } + + if (header.FeatureInfo != GetFeatureInfo()) + { + InvalidateCompressedStream(compressedStream); + + return false; + } + + if (header.OSPlatform != GetOSPlatform()) + { + InvalidateCompressedStream(compressedStream); + + return false; + } + + if (header.InfosLen % InfoEntry.Stride != 0) + { + InvalidateCompressedStream(compressedStream); + + return false; + } + + long here = stream.Position; + + stream.Seek(header.InfosLen + header.CodesLen + header.RelocsLen + header.UnwindInfosLen, SeekOrigin.Current); + + try + { + PtcJumpTable = PtcJumpTable.Deserialize(stream); + } + catch + { + PtcJumpTable = new PtcJumpTable(); + + InvalidateCompressedStream(compressedStream); + + return false; + } + + stream.Seek(here, SeekOrigin.Begin); + + int maxLength = Math.Max(Math.Max(header.InfosLen, header.CodesLen), Math.Max(header.RelocsLen, header.UnwindInfosLen)); + + Span buffer = new byte[maxLength]; + + Span infosBuf = buffer.Slice(0, header.InfosLen); + stream.Read(infosBuf); + _infosStream.Write(infosBuf); + + Span codesBuf = buffer.Slice(0, header.CodesLen); + stream.Read(codesBuf); + _codesStream.Write(codesBuf); + + Span relocsBuf = buffer.Slice(0, header.RelocsLen); + stream.Read(relocsBuf); + _relocsStream.Write(relocsBuf); + + Span unwindInfosBuf = buffer.Slice(0, header.UnwindInfosLen); + stream.Read(unwindInfosBuf); + _unwindInfosStream.Write(unwindInfosBuf); + } } - catch + finally { - InvalidateCompressedStream(compressedStream); - - return false; + if (intPtr != IntPtr.Zero) + { + Marshal.FreeHGlobal(intPtr); + } } - - stream.Seek(0L, SeekOrigin.Begin); - - byte[] currentHash = new byte[hashSize]; - stream.Read(currentHash, 0, hashSize); - - byte[] expectedHash = md5.ComputeHash(stream); - - if (!CompareHash(currentHash, expectedHash)) - { - InvalidateCompressedStream(compressedStream); - - return false; - } - - stream.Seek((long)hashSize, SeekOrigin.Begin); - - Header header = ReadHeader(stream); - - if (header.Magic != HeaderMagic) - { - InvalidateCompressedStream(compressedStream); - - return false; - } - - if (header.CacheFileVersion != InternalVersion) - { - InvalidateCompressedStream(compressedStream); - - return false; - } - - if (header.FeatureInfo != GetFeatureInfo()) - { - InvalidateCompressedStream(compressedStream); - - return false; - } - - if (header.OSPlatform != GetOSPlatform()) - { - InvalidateCompressedStream(compressedStream); - - return false; - } - - if (header.InfosLen % InfoEntry.Stride != 0) - { - InvalidateCompressedStream(compressedStream); - - return false; - } - - byte[] infosBuf = new byte[header.InfosLen]; - byte[] codesBuf = new byte[header.CodesLen]; - byte[] relocsBuf = new byte[header.RelocsLen]; - byte[] unwindInfosBuf = new byte[header.UnwindInfosLen]; - - stream.Read(infosBuf, 0, header.InfosLen); - stream.Read(codesBuf, 0, header.CodesLen); - stream.Read(relocsBuf, 0, header.RelocsLen); - stream.Read(unwindInfosBuf, 0, header.UnwindInfosLen); - - try - { - PtcJumpTable = PtcJumpTable.Deserialize(stream); - } - catch - { - PtcJumpTable = new PtcJumpTable(); - - InvalidateCompressedStream(compressedStream); - - return false; - } - - _infosStream.Write(infosBuf, 0, header.InfosLen); - _codesStream.Write(codesBuf, 0, header.CodesLen); - _relocsStream.Write(relocsBuf, 0, header.RelocsLen); - _unwindInfosStream.Write(unwindInfosBuf, 0, header.UnwindInfosLen); } long fileSize = new FileInfo(fileName).Length; @@ -297,13 +354,13 @@ namespace ARMeilleure.Translation.PTC return currentHash.SequenceEqual(expectedHash); } - private static Header ReadHeader(MemoryStream stream) + private static Header ReadHeader(Stream stream) { using (BinaryReader headerReader = new BinaryReader(stream, EncodingCache.UTF8NoBOM, true)) { Header header = new Header(); - header.Magic = headerReader.ReadString(); + header.Magic = headerReader.ReadUInt64(); header.CacheFileVersion = headerReader.ReadUInt32(); header.FeatureInfo = headerReader.ReadUInt64(); @@ -323,85 +380,130 @@ namespace ARMeilleure.Translation.PTC compressedStream.SetLength(0L); } - private static void PreSave(object state) + private static void PreSave() { _waitEvent.Reset(); - string fileNameActual = String.Concat(CachePathActual, ".cache"); - string fileNameBackup = String.Concat(CachePathBackup, ".cache"); - - FileInfo fileInfoActual = new FileInfo(fileNameActual); - - if (fileInfoActual.Exists && fileInfoActual.Length != 0L) + try { - File.Copy(fileNameActual, fileNameBackup, true); - } + string fileNameActual = String.Concat(CachePathActual, ".cache"); + string fileNameBackup = String.Concat(CachePathBackup, ".cache"); - Save(fileNameActual); + FileInfo fileInfoActual = new FileInfo(fileNameActual); + + if (fileInfoActual.Exists && fileInfoActual.Length != 0L) + { + File.Copy(fileNameActual, fileNameBackup, true); + } + + Save(fileNameActual); + } + finally + { + ResetMemoryStreamsIfNeeded(); + PtcJumpTable.ClearIfNeeded(); + + GCSettings.LargeObjectHeapCompactionMode = GCLargeObjectHeapCompactionMode.CompactOnce; + } _waitEvent.Set(); } - private static void Save(string fileName) + private static unsafe void Save(string fileName) { int translatedFuncsCount; - using (MemoryStream stream = new MemoryStream()) - using (MD5 md5 = MD5.Create()) + IntPtr intPtr = IntPtr.Zero; + + try { + MD5 md5 = MD5.Create(); + int hashSize = md5.HashSize / 8; - stream.Seek((long)hashSize, SeekOrigin.Begin); + int size = hashSize + Header.Size + GetMemoryStreamsLength() + PtcJumpTable.GetSerializeSize(PtcJumpTable); - WriteHeader(stream); + byte[] sizeBytes = BitConverter.GetBytes(size); + Debug.Assert(sizeBytes.Length == sizeof(int)); + byte[] sizeHash = md5.ComputeHash(sizeBytes); - _infosStream.WriteTo(stream); - _codesStream.WriteTo(stream); - _relocsStream.WriteTo(stream); - _unwindInfosStream.WriteTo(stream); + intPtr = Marshal.AllocHGlobal(size); - PtcJumpTable.Serialize(stream, PtcJumpTable); - - translatedFuncsCount = GetInfosEntriesCount(); - - ClearMemoryStreams(); - PtcJumpTable.Clear(); - - stream.Seek((long)hashSize, SeekOrigin.Begin); - byte[] hash = md5.ComputeHash(stream); - - stream.Seek(0L, SeekOrigin.Begin); - stream.Write(hash, 0, hashSize); - - using (FileStream compressedStream = new FileStream(fileName, FileMode.OpenOrCreate)) - using (DeflateStream deflateStream = new DeflateStream(compressedStream, SaveCompressionLevel, true)) + using (UnmanagedMemoryStream stream = new UnmanagedMemoryStream((byte*)intPtr.ToPointer(), size, size, FileAccess.ReadWrite)) { - try - { - stream.WriteTo(deflateStream); - } - catch - { - compressedStream.Position = 0L; - } + stream.Seek((long)hashSize, SeekOrigin.Begin); - if (compressedStream.Position < compressedStream.Length) + WriteHeader(stream); + + _infosStream.WriteTo(stream); + _codesStream.WriteTo(stream); + _relocsStream.WriteTo(stream); + _unwindInfosStream.WriteTo(stream); + + PtcJumpTable.Serialize(stream, PtcJumpTable); + + stream.Seek((long)hashSize, SeekOrigin.Begin); + byte[] hash = md5.ComputeHash(stream); + + md5.Dispose(); + + stream.Seek(0L, SeekOrigin.Begin); + stream.Write(hash, 0, hashSize); + + translatedFuncsCount = GetInfosEntriesCount(); + + ResetMemoryStreamsIfNeeded(); + PtcJumpTable.ClearIfNeeded(); + + using (FileStream compressedStream = new FileStream(fileName, FileMode.OpenOrCreate)) + using (DeflateStream deflateStream = new DeflateStream(compressedStream, SaveCompressionLevel, true)) { - compressedStream.SetLength(compressedStream.Position); + compressedStream.Write(sizeHash, 0, hashSize); + compressedStream.Write(sizeBytes, 0, sizeBytes.Length); + + try + { + 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; - Logger.Info?.Print(LogClass.Ptc, $"Saved Translation Cache (size: {fileSize} bytes, translated functions: {translatedFuncsCount})."); + if (fileSize != 0L) + { + Logger.Info?.Print(LogClass.Ptc, $"Saved Translation Cache (size: {fileSize} bytes, translated functions: {translatedFuncsCount})."); + } } - private static void WriteHeader(MemoryStream stream) + private static int GetMemoryStreamsLength() + { + return (int)_infosStream.Length + (int)_codesStream.Length + (int)_relocsStream.Length + (int)_unwindInfosStream.Length; + } + + private static void WriteHeader(Stream stream) { using (BinaryWriter headerWriter = new BinaryWriter(stream, EncodingCache.UTF8NoBOM, true)) { - headerWriter.Write((string)HeaderMagic); // Header.Magic + headerWriter.Write((ulong)_headerMagic); // Header.Magic headerWriter.Write((uint)InternalVersion); // Header.CacheFileVersion headerWriter.Write((ulong)GetFeatureInfo()); // Header.FeatureInfo @@ -416,10 +518,10 @@ namespace ARMeilleure.Translation.PTC internal static void LoadTranslations(ConcurrentDictionary funcs, IMemoryManager memory, JumpTable jumpTable) { - if ((int)_infosStream.Length == 0 || - (int)_codesStream.Length == 0 || - (int)_relocsStream.Length == 0 || - (int)_unwindInfosStream.Length == 0) + if (_infosStream.Length == 0L && + _codesStream.Length == 0L && + _relocsStream.Length == 0L && + _unwindInfosStream.Length == 0L) { return; } @@ -448,7 +550,7 @@ namespace ARMeilleure.Translation.PTC } else if (infoEntry.HighCq || !PtcProfiler.ProfiledFuncs.TryGetValue(infoEntry.Address, out var value) || !value.highCq) { - byte[] code = ReadCode(codesReader, infoEntry.CodeLen); + Span code = ReadCode(codesReader, infoEntry.CodeLen); if (infoEntry.RelocEntriesCount != 0) { @@ -529,11 +631,11 @@ namespace ARMeilleure.Translation.PTC _unwindInfosStream.Seek(pushEntriesLength * UnwindPushEntry.Stride + UnwindInfo.Stride, SeekOrigin.Current); } - private static byte[] ReadCode(BinaryReader codesReader, int codeLen) + private static Span ReadCode(BinaryReader codesReader, int codeLen) { - byte[] codeBuf = new byte[codeLen]; + Span codeBuf = new byte[codeLen]; - codesReader.Read(codeBuf, 0, codeLen); + codesReader.Read(codeBuf); return codeBuf; } @@ -605,9 +707,9 @@ namespace ARMeilleure.Translation.PTC return new UnwindInfo(pushEntries, prologueSize); } - private static TranslatedFunction FastTranslate(byte[] code, ulong guestSize, UnwindInfo unwindInfo, bool highCq) + private static TranslatedFunction FastTranslate(ReadOnlySpan code, ulong guestSize, UnwindInfo unwindInfo, bool highCq) { - CompiledFunction cFunc = new CompiledFunction(code, unwindInfo); + CompiledFunction cFunc = new CompiledFunction(code.ToArray(), unwindInfo); IntPtr codePtr = JitCache.Map(cFunc); @@ -663,6 +765,11 @@ namespace ARMeilleure.Translation.PTC if (profiledFuncsToTranslate.Count == 0) { + ResetMemoryStreamsIfNeeded(); + PtcJumpTable.ClearIfNeeded(); + + GCSettings.LargeObjectHeapCompactionMode = GCLargeObjectHeapCompactionMode.CompactOnce; + return; } @@ -696,9 +803,11 @@ namespace ARMeilleure.Translation.PTC break; } } + + Translator.DisposePools(); } - int maxDegreeOfParallelism = (Environment.ProcessorCount * 3) / 4; + int maxDegreeOfParallelism = Environment.ProcessorCount; List threads = new List(); @@ -715,8 +824,6 @@ namespace ARMeilleure.Translation.PTC threads.Clear(); - Translator.ResetPools(); - _loggerEvent.Set(); PtcJumpTable.Initialize(jumpTable); @@ -724,7 +831,9 @@ namespace ARMeilleure.Translation.PTC PtcJumpTable.ReadJumpTable(jumpTable); PtcJumpTable.ReadDynamicTable(jumpTable); - ThreadPool.QueueUserWorkItem(PreSave); + Thread preSaveThread = new Thread(PreSave); + preSaveThread.IsBackground = true; + preSaveThread.Start(); } private static void TranslationLogger(object state) @@ -784,7 +893,9 @@ namespace ARMeilleure.Translation.PTC private struct Header { - public string Magic; + public const int Size = 40; // Bytes. + + public ulong Magic; public uint CacheFileVersion; public ulong FeatureInfo; @@ -849,6 +960,8 @@ namespace ARMeilleure.Translation.PTC Wait(); _waitEvent.Dispose(); + _loggerEvent.Dispose(); + _infosWriter.Dispose(); _infosStream.Dispose(); diff --git a/ARMeilleure/Translation/PTC/PtcJumpTable.cs b/ARMeilleure/Translation/PTC/PtcJumpTable.cs index d52d08743d..43d64f19d1 100644 --- a/ARMeilleure/Translation/PTC/PtcJumpTable.cs +++ b/ARMeilleure/Translation/PTC/PtcJumpTable.cs @@ -12,9 +12,11 @@ namespace ARMeilleure.Translation.PTC { public struct TableEntry { + public const int Stride = 16; // Bytes. + public int EntryIndex; public long GuestAddress; - public TAddress HostAddress; + public TAddress HostAddress; // int public TableEntry(int entryIndex, long guestAddress, TAddress hostAddress) { @@ -24,14 +26,14 @@ namespace ARMeilleure.Translation.PTC } } - public enum DirectHostAddress + public enum DirectHostAddress : int { CallStub = 0, TailCallStub = 1, Host = 2 } - public enum IndirectHostAddress + public enum IndirectHostAddress : int { CallStub = 0, TailCallStub = 1 @@ -66,7 +68,7 @@ namespace ARMeilleure.Translation.PTC Owners = owners; } - public static PtcJumpTable Deserialize(MemoryStream stream) + public static PtcJumpTable Deserialize(Stream stream) { using (BinaryReader reader = new BinaryReader(stream, EncodingCache.UTF8NoBOM, true)) { @@ -155,7 +157,36 @@ namespace ARMeilleure.Translation.PTC } } - public static void Serialize(MemoryStream stream, PtcJumpTable ptcJumpTable) + public static int GetSerializeSize(PtcJumpTable ptcJumpTable) + { + const int CountSize = 4; // Bytes. + + int size = 0; + + size += CountSize + ptcJumpTable._jumpTable.Count * TableEntry.Stride; + + size += CountSize + ptcJumpTable._dynamicTable.Count * TableEntry.Stride; + + size += CountSize + ptcJumpTable.Targets.Count * 8; + + 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; + } + + public static void Serialize(Stream stream, PtcJumpTable ptcJumpTable) { using (BinaryWriter writer = new BinaryWriter(stream, EncodingCache.UTF8NoBOM, true)) { @@ -270,14 +301,25 @@ namespace ARMeilleure.Translation.PTC Owners.Remove(guestAddress); } - public void Clear() + public void ClearIfNeeded() { + if (_jumpTable.Count == 0 && _dynamicTable.Count == 0 && + Targets.Count == 0 && Dependants.Count == 0 && Owners.Count == 0) + { + return; + } + _jumpTable.Clear(); + _jumpTable.TrimExcess(); _dynamicTable.Clear(); + _dynamicTable.TrimExcess(); Targets.Clear(); + Targets.TrimExcess(); Dependants.Clear(); + Dependants.TrimExcess(); Owners.Clear(); + Owners.TrimExcess(); } public void WriteJumpTable(JumpTable jumpTable, ConcurrentDictionary funcs) diff --git a/ARMeilleure/Translation/PTC/PtcProfiler.cs b/ARMeilleure/Translation/PTC/PtcProfiler.cs index 0def32c328..ddab4db2a3 100644 --- a/ARMeilleure/Translation/PTC/PtcProfiler.cs +++ b/ARMeilleure/Translation/PTC/PtcProfiler.cs @@ -29,6 +29,8 @@ namespace ARMeilleure.Translation.PTC private static bool _disposed; + private static byte[] _lastHash; + internal static Dictionary ProfiledFuncs { get; private set; } internal static bool Enabled { get; private set; } @@ -105,10 +107,13 @@ namespace ARMeilleure.Translation.PTC internal static void ClearEntries() { ProfiledFuncs.Clear(); + ProfiledFuncs.TrimExcess(); } internal static void PreLoad() { + _lastHash = Array.Empty(); + string fileNameActual = String.Concat(Ptc.CachePathActual, ".info"); string fileNameBackup = String.Concat(Ptc.CachePathBackup, ".info"); @@ -138,8 +143,6 @@ namespace ARMeilleure.Translation.PTC using (MemoryStream stream = new MemoryStream()) using (MD5 md5 = MD5.Create()) { - int hashSize = md5.HashSize / 8; - try { deflateStream.CopyTo(stream); @@ -151,6 +154,8 @@ namespace ARMeilleure.Translation.PTC return false; } + int hashSize = md5.HashSize / 8; + stream.Seek(0L, SeekOrigin.Begin); byte[] currentHash = new byte[hashSize]; @@ -195,6 +200,8 @@ namespace ARMeilleure.Translation.PTC return false; } + + _lastHash = expectedHash; } long fileSize = new FileInfo(fileName).Length; @@ -209,7 +216,7 @@ namespace ARMeilleure.Translation.PTC return currentHash.SequenceEqual(expectedHash); } - private static Header ReadHeader(MemoryStream stream) + private static Header ReadHeader(Stream stream) { using (BinaryReader headerReader = new BinaryReader(stream, EncodingCache.UTF8NoBOM, true)) { @@ -223,7 +230,7 @@ namespace ARMeilleure.Translation.PTC } } - private static Dictionary Deserialize(MemoryStream stream) + private static Dictionary Deserialize(Stream stream) { using (BinaryReader reader = new BinaryReader(stream, EncodingCache.UTF8NoBOM, true)) { @@ -295,16 +302,25 @@ namespace ARMeilleure.Translation.PTC stream.Seek(0L, SeekOrigin.Begin); stream.Write(hash, 0, hashSize); + if (CompareHash(hash, _lastHash)) + { + return; + } + using (FileStream compressedStream = new FileStream(fileName, FileMode.OpenOrCreate)) using (DeflateStream deflateStream = new DeflateStream(compressedStream, SaveCompressionLevel, true)) { try { stream.WriteTo(deflateStream); + + _lastHash = hash; } catch { compressedStream.Position = 0L; + + _lastHash = Array.Empty(); } if (compressedStream.Position < compressedStream.Length) @@ -316,10 +332,13 @@ namespace ARMeilleure.Translation.PTC long fileSize = new FileInfo(fileName).Length; - Logger.Info?.Print(LogClass.Ptc, $"Saved Profiling Info (size: {fileSize} bytes, profiled functions: {profiledFuncsCount})."); + if (fileSize != 0L) + { + Logger.Info?.Print(LogClass.Ptc, $"Saved Profiling Info (size: {fileSize} bytes, profiled functions: {profiledFuncsCount})."); + } } - private static void WriteHeader(MemoryStream stream) + private static void WriteHeader(Stream stream) { using (BinaryWriter headerWriter = new BinaryWriter(stream, EncodingCache.UTF8NoBOM, true)) { @@ -329,7 +348,7 @@ namespace ARMeilleure.Translation.PTC } } - private static void Serialize(MemoryStream stream, Dictionary profiledFuncs) + private static void Serialize(Stream stream, Dictionary profiledFuncs) { using (BinaryWriter writer = new BinaryWriter(stream, EncodingCache.UTF8NoBOM, true)) { diff --git a/ARMeilleure/Translation/Translator.cs b/ARMeilleure/Translation/Translator.cs index 2c32e9f00c..30b448c1c6 100644 --- a/ARMeilleure/Translation/Translator.cs +++ b/ARMeilleure/Translation/Translator.cs @@ -11,8 +11,10 @@ using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; using System.Linq; +using System.Runtime; using System.Threading; +using static ARMeilleure.Common.BitMapPool; using static ARMeilleure.IntermediateRepresentation.OperandHelper; using static ARMeilleure.IntermediateRepresentation.OperationHelper; @@ -148,10 +150,12 @@ namespace ARMeilleure.Translation ClearJitCache(); - ResetPools(); + DisposePools(); _jumpTable.Dispose(); _jumpTable = null; + + GCSettings.LargeObjectHeapCompactionMode = GCLargeObjectHeapCompactionMode.CompactOnce; } } @@ -207,7 +211,7 @@ namespace ARMeilleure.Translation Logger.EndPass(PassName.Decoding); - PreparePool(highCq); + PreparePool(highCq ? 1 : 0); Logger.StartPass(PassName.Translation); @@ -240,13 +244,13 @@ namespace ARMeilleure.Translation { func = Compiler.Compile(cfg, argTypes, OperandType.I64, options); - ReturnPool(highCq); + ResetPool(highCq ? 1 : 0); } else using (PtcInfo ptcInfo = new PtcInfo()) { func = Compiler.Compile(cfg, argTypes, OperandType.I64, options, ptcInfo); - ReturnPool(highCq); + ResetPool(highCq ? 1 : 0); Ptc.WriteInfoCodeRelocUnwindInfo(address, funcSize, highCq, ptcInfo); } @@ -254,22 +258,23 @@ namespace ARMeilleure.Translation return new TranslatedFunction(func, funcSize, highCq); } - internal static void PreparePool(bool highCq) + internal static void PreparePool(int groupId = 0) { - PrepareOperandPool(highCq); - PrepareOperationPool(highCq); + PrepareOperandPool(groupId); + PrepareOperationPool(groupId); } - internal static void ReturnPool(bool highCq) + internal static void ResetPool(int groupId = 0) { - ReturnOperandPool(highCq); - ReturnOperationPool(highCq); + ResetOperationPool(groupId); + ResetOperandPool(groupId); } - internal static void ResetPools() + internal static void DisposePools() { - ResetOperandPools(); - ResetOperationPools(); + DisposeOperandPools(); + DisposeOperationPools(); + DisposeBitMapPools(); } private struct Range diff --git a/Ryujinx.Memory/MemoryBlock.cs b/Ryujinx.Memory/MemoryBlock.cs index fadd50d44d..198e275b4f 100644 --- a/Ryujinx.Memory/MemoryBlock.cs +++ b/Ryujinx.Memory/MemoryBlock.cs @@ -40,8 +40,6 @@ namespace Ryujinx.Memory } Size = size; - - GC.AddMemoryPressure((long)Size); } /// @@ -283,8 +281,6 @@ namespace Ryujinx.Memory if (ptr != IntPtr.Zero) { MemoryManagement.Free(ptr); - - GC.RemoveMemoryPressure((long)Size); } }