See merge request ryubing/ryujinx!202
This commit is contained in:
LotP
2025-10-30 20:55:58 -05:00
parent ab7aeee67b
commit 92b61f9d73
43 changed files with 686 additions and 315 deletions

View File

@@ -1,4 +1,5 @@
using System;
using System.Buffers;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.CompilerServices;
@@ -38,7 +39,7 @@ namespace Ryujinx.Memory.Range
index = ~index;
}
RangeItem<T> rangeItem = new(item);
RangeItem<T> rangeItem = _rangeItemPool.Allocate().Set(item);
Insert(index, rangeItem);
}
@@ -144,6 +145,8 @@ namespace Ryujinx.Memory.Range
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void RemoveAt(int index)
{
_rangeItemPool.Release(Items[index]);
if (index < Count - 1)
{
Items[index + 1].Previous = index > 0 ? Items[index - 1] : null;
@@ -433,7 +436,7 @@ namespace Ryujinx.Memory.Range
return (Items[index], Items[endIndex - 1]);
}
public RangeItem<T>[] FindOverlapsAsArray(ulong address, ulong size)
public RangeItem<T>[] FindOverlapsAsArray(ulong address, ulong size, out int length)
{
(int index, int endIndex) = BinarySearchEdges(address, address + size);
@@ -441,11 +444,13 @@ namespace Ryujinx.Memory.Range
if (index < 0)
{
result = [];
result = null;
length = 0;
}
else
{
result = new RangeItem<T>[endIndex - index];
result = ArrayPool<RangeItem<T>>.Shared.Rent(endIndex - index);
length = endIndex - index;
Array.Copy(Items, index, result, 0, endIndex - index);
}

View File

@@ -36,8 +36,6 @@ namespace Ryujinx.Memory.Range
public class RangeList<T> : RangeListBase<T> where T : IRange
{
public readonly ReaderWriterLockSlim Lock = new();
private readonly Dictionary<ulong, RangeItem<T>> _quickAccess = new(AddressEqualityComparer.Comparer);
/// <summary>
/// Creates a new range list.
@@ -93,11 +91,6 @@ namespace Ryujinx.Memory.Range
Items[index + 1].Previous = rangeItem;
}
foreach (ulong address in Items[index].QuickAccessAddresses)
{
_quickAccess.Remove(address);
}
Items[index] = rangeItem;
return true;
@@ -142,11 +135,6 @@ namespace Ryujinx.Memory.Range
Items[index + 1].Previous = rangeItem;
}
foreach (ulong address in item.QuickAccessAddresses)
{
_quickAccess.Remove(address);
}
Items[index] = rangeItem;
return true;
@@ -210,11 +198,6 @@ namespace Ryujinx.Memory.Range
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void RemoveAt(int index)
{
foreach (ulong address in Items[index].QuickAccessAddresses)
{
_quickAccess.Remove(address);
}
if (index < Count - 1)
{
Items[index + 1].Previous = index > 0 ? Items[index - 1] : null;
@@ -253,15 +236,6 @@ namespace Ryujinx.Memory.Range
int startIndex = BinarySearch(startItem.Address);
int endIndex = BinarySearch(endItem.Address);
for (int i = startIndex; i <= endIndex; i++)
{
_quickAccess.Remove(Items[i].Address);
foreach (ulong addr in Items[i].QuickAccessAddresses)
{
_quickAccess.Remove(addr);
}
}
if (endIndex < Count - 1)
{
Items[endIndex + 1].Previous = startIndex > 0 ? Items[startIndex - 1] : null;
@@ -349,11 +323,6 @@ namespace Ryujinx.Memory.Range
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public override RangeItem<T> FindOverlapFast(ulong address, ulong size)
{
if (_quickAccess.TryGetValue(address, out RangeItem<T> quickResult))
{
return quickResult;
}
int index = BinarySearch(address, address + size);
if (index < 0)
@@ -361,12 +330,6 @@ namespace Ryujinx.Memory.Range
return null;
}
if (Items[index].OverlapsWith(address, address + 1))
{
_quickAccess.Add(address, Items[index]);
Items[index].QuickAccessAddresses.Add(address);
}
return Items[index];
}

View File

@@ -1,20 +1,42 @@
using System.Collections;
using Ryujinx.Common;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
namespace Ryujinx.Memory.Range
{
public class RangeItem<TValue>(TValue value) where TValue : IRange
public class RangeItem<TValue> where TValue : IRange
{
public RangeItem<TValue> Next;
public RangeItem<TValue> Previous;
public readonly ulong Address = value.Address;
public readonly ulong EndAddress = value.Address + value.Size;
public ulong Address;
public ulong EndAddress;
public readonly TValue Value = value;
public TValue Value;
public RangeItem()
{
}
public RangeItem(TValue value)
{
Address = value.Address;
EndAddress = value.Address + value.Size;
Value = value;
}
public readonly List<ulong> QuickAccessAddresses = [];
public RangeItem<TValue> Set(TValue value)
{
Next = null;
Previous = null;
Address = value.Address;
EndAddress = value.Address + value.Size;
Value = value;
return this;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool OverlapsWith(ulong address, ulong endAddress)
@@ -23,20 +45,9 @@ namespace Ryujinx.Memory.Range
}
}
class AddressEqualityComparer : IEqualityComparer<ulong>
{
public bool Equals(ulong u1, ulong u2)
{
return u1 == u2;
}
public int GetHashCode(ulong value) => (int)(value << 5);
public static readonly AddressEqualityComparer Comparer = new();
}
public unsafe abstract class RangeListBase<T> : IEnumerable<T> where T : IRange
{
protected static readonly ObjectPool<RangeItem<T>> _rangeItemPool = new(() => new RangeItem<T>());
private const int BackingInitialSize = 1024;
protected RangeItem<T>[] Items;

View File

@@ -1,5 +1,6 @@
using Ryujinx.Memory.Range;
using System;
using System.Buffers;
using System.Collections.Generic;
namespace Ryujinx.Memory.Tracking
@@ -300,10 +301,10 @@ namespace Ryujinx.Memory.Tracking
// We use the non-span method here because keeping the lock will cause a deadlock.
regions.Lock.EnterReadLock();
RangeItem<VirtualRegion>[] overlaps = regions.FindOverlapsAsArray(address, size);
RangeItem<VirtualRegion>[] overlaps = regions.FindOverlapsAsArray(address, size, out int length);
regions.Lock.ExitReadLock();
if (overlaps.Length == 0 && !precise)
if (length == 0 && !precise)
{
if (_memoryManager.IsRangeMapped(address, size))
{
@@ -323,8 +324,8 @@ namespace Ryujinx.Memory.Tracking
// Increase the access size to trigger handles with misaligned accesses.
size += (ulong)_pageSize;
}
for (int i = 0; i < overlaps.Length; i++)
for (int i = 0; i < length; i++)
{
VirtualRegion region = overlaps[i].Value;
@@ -337,6 +338,11 @@ namespace Ryujinx.Memory.Tracking
region.Signal(address, size, write, exemptId);
}
}
if (length != 0)
{
ArrayPool<RangeItem<VirtualRegion>>.Shared.Return(overlaps);
}
}
}