mirror of
https://git.ryujinx.app/ryubing/ryujinx.git
synced 2026-07-02 00:59:04 +00:00
Memory Changes part 2 (ryubing/ryujinx!123)
See merge request ryubing/ryujinx!123
This commit is contained in:
@@ -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++;
|
||||
}
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user