From 86f7b09b64c66533870b01ecf0792a52830fa9e6 Mon Sep 17 00:00:00 2001 From: riperiperi Date: Mon, 24 Jun 2024 19:43:22 +0100 Subject: [PATCH] Automatically size sparse blocks to minimize tracking ranges --- src/Ryujinx.Cpu/AddressTable.cs | 45 +++++++++++++++---- src/Ryujinx.Cpu/Jit/JitCpuContext.cs | 1 + .../LightningJit/LightningJitCpuContext.cs | 1 + 3 files changed, 39 insertions(+), 8 deletions(-) diff --git a/src/Ryujinx.Cpu/AddressTable.cs b/src/Ryujinx.Cpu/AddressTable.cs index e8a0c423b..306a6f4d7 100644 --- a/src/Ryujinx.Cpu/AddressTable.cs +++ b/src/Ryujinx.Cpu/AddressTable.cs @@ -1,3 +1,4 @@ +using Ryujinx.Common; using Ryujinx.Common.Logging; using Ryujinx.Cpu.Signal; using Ryujinx.Memory; @@ -89,9 +90,9 @@ namespace ARMeilleure.Common private readonly TEntry* _fillBottomLevelPtr; private readonly List _sparseReserved; - private readonly ulong _sparseBlockSize; private readonly ReaderWriterLockSlim _sparseLock; + private ulong _sparseBlockSize; private ulong _sparseReservedOffset; /// @@ -170,7 +171,7 @@ namespace ARMeilleure.Common _sparseReserved = new List(); _sparseLock = new ReaderWriterLockSlim(); - _sparseBlockSize = bottomLevelSize << 3; + _sparseBlockSize = bottomLevelSize; } } @@ -202,6 +203,23 @@ namespace ARMeilleure.Common _fill = fillValue; } + /// + /// Signal that the given code range exists. + /// + /// + /// + public void SignalCodeRange(ulong address, ulong size) + { + AddressTableLevel bottom = Levels.Last(); + ulong bottomLevelEntries = 1ul << bottom.Length; + + ulong entryIndex = address >> bottom.Index; + ulong entries = size >> bottom.Index; + entries += entryIndex - BitUtils.AlignDown(entryIndex, bottomLevelEntries); + + _sparseBlockSize = Math.Max(_sparseBlockSize, BitUtils.AlignUp(entries, bottomLevelEntries) * (ulong)sizeof(TEntry)); + } + /// public bool IsValid(ulong address) { @@ -341,12 +359,14 @@ namespace ARMeilleure.Common Ryujinx.Common.Logging.Logger.Info?.PrintMsg(LogClass.Cpu, $"Using memory {initedSize}/{reservedSize} bytes"); } - private void ReserveNewSparseBlock() + private TableSparseBlock ReserveNewSparseBlock() { var block = new TableSparseBlock(_sparseBlockSize, EnsureMapped, InitLeafPage); _sparseReserved.Add(block); _sparseReservedOffset = 0; + + return block; } /// @@ -369,12 +389,21 @@ namespace ARMeilleure.Common { _sparseLock.EnterWriteLock(); - if (_sparseReserved.Count == 0 || _sparseReservedOffset == _sparseBlockSize) - { - ReserveNewSparseBlock(); - } + SparseMemoryBlock block; - SparseMemoryBlock block = _sparseReserved.Last().Block; + if (_sparseReserved.Count == 0) + { + block = ReserveNewSparseBlock().Block; + } + else + { + block = _sparseReserved.Last().Block; + + if (_sparseReservedOffset == block.Block.Size) + { + block = ReserveNewSparseBlock().Block; + } + } page = new AddressTablePage(true, block.Block.Pointer + (IntPtr)_sparseReservedOffset); diff --git a/src/Ryujinx.Cpu/Jit/JitCpuContext.cs b/src/Ryujinx.Cpu/Jit/JitCpuContext.cs index 2b70b0239..5a9c9dcfe 100644 --- a/src/Ryujinx.Cpu/Jit/JitCpuContext.cs +++ b/src/Ryujinx.Cpu/Jit/JitCpuContext.cs @@ -59,6 +59,7 @@ namespace Ryujinx.Cpu.Jit /// public void PrepareCodeRange(ulong address, ulong size) { + _functionTable.SignalCodeRange(address, size); _translator.PrepareCodeRange(address, size); } diff --git a/src/Ryujinx.Cpu/LightningJit/LightningJitCpuContext.cs b/src/Ryujinx.Cpu/LightningJit/LightningJitCpuContext.cs index 2d4ca0fca..b0b5ad72f 100644 --- a/src/Ryujinx.Cpu/LightningJit/LightningJitCpuContext.cs +++ b/src/Ryujinx.Cpu/LightningJit/LightningJitCpuContext.cs @@ -53,6 +53,7 @@ namespace Ryujinx.Cpu.LightningJit /// public void PrepareCodeRange(ulong address, ulong size) { + _functionTable.SignalCodeRange(address, size); } public void Dispose()