Some cleanup

This commit is contained in:
riperiperi 2024-06-24 21:18:01 +01:00
parent aa3b1e8996
commit a37f65e87d
5 changed files with 39 additions and 14 deletions

View file

@ -5,12 +5,18 @@ namespace ARMeilleure.Common
public interface IAddressTable<TEntry> : IDisposable where TEntry : unmanaged public interface IAddressTable<TEntry> : IDisposable where TEntry : unmanaged
{ {
/// <summary> /// <summary>
/// Gets the bits used by the <see cref="Levels"/> of the <see cref="AddressTable{TEntry}"/> instance. /// True if the address table's bottom level is sparsely mapped.
/// This also ensures the second bottom level is filled with a dummy page rather than 0.
/// </summary>
bool Sparse { get; }
/// <summary>
/// Gets the bits used by the <see cref="Levels"/> of the <see cref="IAddressTable{TEntry}"/> instance.
/// </summary> /// </summary>
ulong Mask { get; } ulong Mask { get; }
/// <summary> /// <summary>
/// Gets the <see cref="Level"/>s used by the <see cref="AddressTable{TEntry}"/> instance. /// Gets the <see cref="AddressTableLevel"/>s used by the <see cref="IAddressTable{TEntry}"/> instance.
/// </summary> /// </summary>
AddressTableLevel[] Levels { get; } AddressTableLevel[] Levels { get; }
@ -27,7 +33,7 @@ namespace ARMeilleure.Common
/// <summary> /// <summary>
/// Determines if the specified <paramref name="address"/> is in the range of the /// Determines if the specified <paramref name="address"/> is in the range of the
/// <see cref="AddressTable{TEntry}"/>. /// <see cref="IAddressTable{TEntry}"/>.
/// </summary> /// </summary>
/// <param name="address">Guest address</param> /// <param name="address">Guest address</param>
/// <returns><see langword="true"/> if is valid; otherwise <see langword="false"/></returns> /// <returns><see langword="true"/> if is valid; otherwise <see langword="false"/></returns>

View file

@ -205,7 +205,7 @@ namespace ARMeilleure.Instructions
hostAddress = context.Load(OperandType.I64, hostAddressAddr); hostAddress = context.Load(OperandType.I64, hostAddressAddr);
} }
else if (table.Levels.Length == 2) else if (table.Sparse && table.Levels.Length == 2)
{ {
// Inline table lookup. Only enabled when the sparse function table is enabled with 2 levels. // Inline table lookup. Only enabled when the sparse function table is enabled with 2 levels.
// Deliberately attempts to avoid branches. // Deliberately attempts to avoid branches.

View file

@ -18,9 +18,19 @@ namespace ARMeilleure.Common
/// <typeparam name="TEntry">Type of the value</typeparam> /// <typeparam name="TEntry">Type of the value</typeparam>
public unsafe class AddressTable<TEntry> : IAddressTable<TEntry> where TEntry : unmanaged public unsafe class AddressTable<TEntry> : IAddressTable<TEntry> where TEntry : unmanaged
{ {
/// <summary>
/// Represents a page of the address table.
/// </summary>
private readonly struct AddressTablePage private readonly struct AddressTablePage
{ {
/// <summary>
/// True if the allocation belongs to a sparse block, false otherwise.
/// </summary>
public readonly bool IsSparse; public readonly bool IsSparse;
/// <summary>
/// Base address for the page.
/// </summary>
public readonly IntPtr Address; public readonly IntPtr Address;
public AddressTablePage(bool isSparse, IntPtr address) public AddressTablePage(bool isSparse, IntPtr address)
@ -36,13 +46,13 @@ namespace ARMeilleure.Common
private readonly struct TableSparseBlock : IDisposable private readonly struct TableSparseBlock : IDisposable
{ {
public readonly SparseMemoryBlock Block; public readonly SparseMemoryBlock Block;
public readonly TrackingEventDelegate TrackingEvent; private readonly TrackingEventDelegate _trackingEvent;
public TableSparseBlock(ulong size, Action<IntPtr> ensureMapped, PageInitDelegate pageInit) public TableSparseBlock(ulong size, Action<IntPtr> ensureMapped, PageInitDelegate pageInit)
{ {
var block = new SparseMemoryBlock(size, pageInit, null); var block = new SparseMemoryBlock(size, pageInit, null);
TrackingEvent = (ulong address, ulong size, bool write) => _trackingEvent = (ulong address, ulong size, bool write) =>
{ {
Logger.Error?.PrintMsg(LogClass.Cpu, $"Triggered from exception"); Logger.Error?.PrintMsg(LogClass.Cpu, $"Triggered from exception");
@ -56,7 +66,7 @@ namespace ARMeilleure.Common
bool added = NativeSignalHandler.AddTrackedRegion( bool added = NativeSignalHandler.AddTrackedRegion(
(nuint)block.Block.Pointer, (nuint)block.Block.Pointer,
(nuint)(block.Block.Pointer + (IntPtr)block.Block.Size), (nuint)(block.Block.Pointer + (IntPtr)block.Block.Size),
Marshal.GetFunctionPointerForDelegate(TrackingEvent)); Marshal.GetFunctionPointerForDelegate(_trackingEvent));
if (!added) if (!added)
{ {
@ -79,7 +89,6 @@ namespace ARMeilleure.Common
private readonly List<AddressTablePage> _pages; private readonly List<AddressTablePage> _pages;
private TEntry _fill; private TEntry _fill;
private readonly bool _sparse;
private readonly MemoryBlock _sparseFill; private readonly MemoryBlock _sparseFill;
private readonly SparseMemoryBlock _fillBottomLevel; private readonly SparseMemoryBlock _fillBottomLevel;
private readonly TEntry* _fillBottomLevelPtr; private readonly TEntry* _fillBottomLevelPtr;
@ -90,6 +99,8 @@ namespace ARMeilleure.Common
private ulong _sparseBlockSize; private ulong _sparseBlockSize;
private ulong _sparseReservedOffset; private ulong _sparseReservedOffset;
public bool Sparse { get; }
/// <inheritdoc/> /// <inheritdoc/>
public ulong Mask { get; } public ulong Mask { get; }
@ -150,7 +161,7 @@ namespace ARMeilleure.Common
Mask |= level.Mask; Mask |= level.Mask;
} }
_sparse = sparse; Sparse = sparse;
if (sparse) if (sparse)
{ {
@ -279,9 +290,13 @@ namespace ARMeilleure.Common
return (TEntry*)page; return (TEntry*)page;
} }
/// <summary>
/// Ensure the given pointer is mapped in any overlapping sparse reservations.
/// </summary>
/// <param name="ptr">Pointer to be mapped</param>
private void EnsureMapped(IntPtr ptr) private void EnsureMapped(IntPtr ptr)
{ {
if (_sparse) if (Sparse)
{ {
// Check sparse allocations to see if the pointer is in any of them. // Check sparse allocations to see if the pointer is in any of them.
// Ensure the page is committed if there's a match. // Ensure the page is committed if there's a match.
@ -356,6 +371,10 @@ namespace ARMeilleure.Common
Ryujinx.Common.Logging.Logger.Info?.PrintMsg(LogClass.Cpu, $"Using memory {initedSize}/{reservedSize} bytes"); Ryujinx.Common.Logging.Logger.Info?.PrintMsg(LogClass.Cpu, $"Using memory {initedSize}/{reservedSize} bytes");
} }
/// <summary>
/// Reserve a new sparse block, and add it to the list.
/// </summary>
/// <returns>The new sparse block that was added</returns>
private TableSparseBlock ReserveNewSparseBlock() private TableSparseBlock ReserveNewSparseBlock()
{ {
var block = new TableSparseBlock(_sparseBlockSize, EnsureMapped, InitLeafPage); var block = new TableSparseBlock(_sparseBlockSize, EnsureMapped, InitLeafPage);
@ -382,7 +401,7 @@ namespace ARMeilleure.Common
AddressTablePage page; AddressTablePage page;
if (_sparse && leaf) if (Sparse && leaf)
{ {
_sparseLock.EnterWriteLock(); _sparseLock.EnterWriteLock();
@ -450,7 +469,7 @@ namespace ARMeilleure.Common
} }
} }
if (_sparse) if (Sparse)
{ {
foreach (TableSparseBlock block in _sparseReserved) foreach (TableSparseBlock block in _sparseReserved)
{ {

View file

@ -142,7 +142,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
int tempRegister; int tempRegister;
int tempGuestAddress = -1; int tempGuestAddress = -1;
bool inlineLookup = guestAddress.Kind != OperandKind.Constant && funcTable != null && funcTable.Levels.Length == 2; bool inlineLookup = guestAddress.Kind != OperandKind.Constant && funcTable != null && funcTable.Sparse && funcTable.Levels.Length == 2;
if (guestAddress.Kind == OperandKind.Constant) if (guestAddress.Kind == OperandKind.Constant)
{ {

View file

@ -307,7 +307,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm64.Target.Arm64
int tempRegister; int tempRegister;
int tempGuestAddress = -1; int tempGuestAddress = -1;
bool inlineLookup = guestAddress.Kind != OperandKind.Constant && funcTable != null && funcTable.Levels.Length == 2; bool inlineLookup = guestAddress.Kind != OperandKind.Constant && funcTable != null && funcTable.Sparse && funcTable.Levels.Length == 2;
if (guestAddress.Kind == OperandKind.Constant) if (guestAddress.Kind == OperandKind.Constant)
{ {