Memory Changes part 2 (ryubing/ryujinx!123)

See merge request ryubing/ryujinx!123
This commit is contained in:
LotP
2025-08-25 17:44:15 -05:00
parent d499449f57
commit 50ab108ee1
90 changed files with 2133 additions and 1159 deletions

View File

@@ -10,7 +10,7 @@ namespace Ryujinx.Memory.Range
/// A range list that assumes ranges are non-overlapping, with list items that can be split in two to avoid overlaps.
/// </summary>
/// <typeparam name="T">Type of the range.</typeparam>
public class NonOverlappingRangeList<T> : RangeListBase<T> where T : INonOverlappingRange
public unsafe class NonOverlappingRangeList<T> : RangeListBase<T> where T : class, INonOverlappingRange
{
private readonly Dictionary<ulong, RangeItem<T>> _quickAccess = new(AddressEqualityComparer.Comparer);
private readonly Dictionary<ulong, RangeItem<T>> _fastQuickAccess = new(AddressEqualityComparer.Comparer);
@@ -196,6 +196,16 @@ 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);
_fastQuickAccess.Remove(addr);
}
}
if (endIndex < Count - 1)
{
Items[endIndex + 1].Previous = startIndex > 0 ? Items[startIndex - 1] : null;
@@ -213,17 +223,6 @@ namespace Ryujinx.Memory.Range
}
Count -= endIndex - startIndex + 1;
while (startItem != endItem.Next)
{
_quickAccess.Remove(startItem.Address);
foreach (ulong addr in startItem.QuickAccessAddresses)
{
_quickAccess.Remove(addr);
_fastQuickAccess.Remove(addr);
}
startItem = startItem.Next;
}
}
/// <summary>
@@ -240,19 +239,22 @@ namespace Ryujinx.Memory.Range
return;
}
RangeItem<T> startItem = Items[startIndex];
int endIndex = startIndex;
while (startItem is not null && startItem.Address < address + size)
while (Items[endIndex] is not null && Items[endIndex].Address < address + size)
{
_quickAccess.Remove(startItem.Address);
foreach (ulong addr in startItem.QuickAccessAddresses)
_quickAccess.Remove(Items[endIndex].Address);
foreach (ulong addr in Items[endIndex].QuickAccessAddresses)
{
_quickAccess.Remove(addr);
_fastQuickAccess.Remove(addr);
}
startItem = startItem.Next;
if (endIndex == Count - 1)
{
break;
}
endIndex++;
}

View File

@@ -6,37 +6,6 @@ using System.Threading;
namespace Ryujinx.Memory.Range
{
public class RangeItem<TValue>(TValue value) 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 readonly TValue Value = value;
public readonly List<ulong> QuickAccessAddresses = [];
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool OverlapsWith(ulong address, ulong endAddress)
{
return Address < endAddress && address < EndAddress;
}
}
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();
}
/// <summary>
/// Result of an Overlaps Finder function. WARNING: if the result is from the optimized
/// Overlaps Finder, the StartIndex will be -1 even when the result isn't empty
@@ -209,43 +178,46 @@ namespace Ryujinx.Memory.Range
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public override void RemoveRange(RangeItem<T> startItem, RangeItem<T> endItem)
{
if (endItem.Next is not null)
if (startItem is null)
{
endItem.Next.Previous = startItem.Previous;
return;
}
if (startItem == endItem)
{
Remove(startItem.Value);
return;
}
if (startItem.Previous is not null)
{
startItem.Previous.Next = endItem.Next;
}
int startIndex = BinarySearch(startItem.Address);
int endIndex = BinarySearch(endItem.Address);
RangeItem<T> current = startItem;
while (current != endItem.Next)
for (int i = startIndex; i <= endIndex; i++)
{
foreach (ulong address in current.QuickAccessAddresses)
_quickAccess.Remove(Items[i].Address);
foreach (ulong addr in Items[i].QuickAccessAddresses)
{
_quickAccess.Remove(address);
_quickAccess.Remove(addr);
}
current = current.Next;
}
RangeItem<T>[] array = [];
OverlapResult<T> overlapResult = FindOverlaps(startItem.Address, endItem.EndAddress, ref array);
if (endIndex < Count - 1)
{
Items[endIndex + 1].Previous = startIndex > 0 ? Items[startIndex - 1] : null;
}
if (startIndex > 0)
{
Items[startIndex - 1].Next = endIndex < Count - 1 ? Items[endIndex + 1] : null;
}
if (overlapResult.EndIndex < Count)
if (endIndex < Count - 1)
{
Array.Copy(Items, overlapResult.EndIndex, Items, overlapResult.StartIndex, Count - overlapResult.EndIndex);
Count -= overlapResult.Count;
}
else if (overlapResult.EndIndex == Count)
{
Count = overlapResult.StartIndex;
}
else
{
Debug.Assert(false);
Array.Copy(Items, endIndex + 1, Items, startIndex, Count - endIndex - 1);
}
Count -= endIndex - startIndex + 1;
}
/// <summary>

View File

@@ -4,9 +4,40 @@ using System.Runtime.CompilerServices;
namespace Ryujinx.Memory.Range
{
public abstract class RangeListBase<T> : IEnumerable<T> where T : IRange
public class RangeItem<TValue>(TValue value) where TValue : IRange
{
protected const int BackingInitialSize = 1024;
public RangeItem<TValue> Next;
public RangeItem<TValue> Previous;
public readonly ulong Address = value.Address;
public readonly ulong EndAddress = value.Address + value.Size;
public readonly TValue Value = value;
public readonly List<ulong> QuickAccessAddresses = [];
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool OverlapsWith(ulong address, ulong endAddress)
{
return Address < endAddress && address < EndAddress;
}
}
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
{
private const int BackingInitialSize = 1024;
protected RangeItem<T>[] Items;
protected readonly int BackingGrowthSize;