See merge request ryubing/ryujinx!234
This commit is contained in:
LotP
2025-12-06 17:19:19 -06:00
committed by GreemDev
parent fd7554425a
commit c3155fcadb
37 changed files with 563 additions and 677 deletions

View File

@@ -3,7 +3,7 @@ namespace Ryujinx.Memory.Range
/// <summary>
/// Range of memory that can be split in two.
/// </summary>
public interface INonOverlappingRange : IRange
public interface INonOverlappingRange<T> : IRangeListRange<T> where T : class, IRangeListRange<T>
{
/// <summary>
/// Split this region into two, around the specified address.
@@ -11,6 +11,6 @@ namespace Ryujinx.Memory.Range
/// </summary>
/// <param name="splitAddress">Address to split the region around</param>
/// <returns>The second part of the split region, with start address at the given split.</returns>
public INonOverlappingRange Split(ulong splitAddress);
public INonOverlappingRange<T> Split(ulong splitAddress);
}
}

View File

@@ -24,8 +24,8 @@ namespace Ryujinx.Memory.Range
/// Check if this range overlaps with another.
/// </summary>
/// <param name="address">Base address</param>
/// <param name="size">Size of the range</param>
/// <param name="endAddress">EndAddress of the range</param>
/// <returns>True if overlapping, false otherwise</returns>
bool OverlapsWith(ulong address, ulong size);
bool OverlapsWith(ulong address, ulong endAddress);
}
}

View File

@@ -11,7 +11,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 unsafe class NonOverlappingRangeList<T> : RangeListBase<T> where T : class, INonOverlappingRange
public class NonOverlappingRangeList<T> : RangeListBase<T> where T : class, INonOverlappingRange<T>
{
public readonly ReaderWriterLockSlim Lock = new();
@@ -32,83 +32,18 @@ namespace Ryujinx.Memory.Range
/// <param name="item">The item to be added</param>
public override void Add(T item)
{
Debug.Assert(item.Address != item.EndAddress);
int index = BinarySearch(item.Address);
if (index < 0)
{
index = ~index;
}
RangeItem<T> rangeItem = _rangeItemPool.Allocate().Set(item);
Insert(index, rangeItem);
}
/// <summary>
/// Updates an item's end address on the list. Address must be the same.
/// </summary>
/// <param name="item">The item to be updated</param>
/// <returns>True if the item was located and updated, false otherwise</returns>
protected override bool Update(T item)
{
int index = BinarySearch(item.Address);
if (index >= 0 && Items[index].Value.Equals(item))
{
RangeItem<T> rangeItem = new(item) { Previous = Items[index].Previous, Next = Items[index].Next };
if (index > 0)
{
Items[index - 1].Next = rangeItem;
}
if (index < Count - 1)
{
Items[index + 1].Previous = rangeItem;
}
Items[index] = rangeItem;
return true;
}
return false;
}
/// <summary>
/// Updates an item's end address on the list. Address must be the same.
/// </summary>
/// <param name="item">The RangeItem to be updated</param>
/// <returns>True if the item was located and updated, false otherwise</returns>
protected override bool Update(RangeItem<T> item)
{
int index = BinarySearch(item.Address);
RangeItem<T> rangeItem = new(item.Value) { Previous = item.Previous, Next = item.Next };
if (index > 0)
{
Items[index - 1].Next = rangeItem;
}
if (index < Count - 1)
{
Items[index + 1].Previous = rangeItem;
}
Items[index] = rangeItem;
return true;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void Insert(int index, RangeItem<T> item)
{
Debug.Assert(item.Address != item.EndAddress);
if (Count + 1 > Items.Length)
{
Array.Resize(ref Items, Items.Length + BackingGrowthSize);
Array.Resize(ref Items, (int)(Items.Length * 1.5));
}
if (index >= Count)
@@ -145,8 +80,6 @@ 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;
@@ -173,7 +106,7 @@ namespace Ryujinx.Memory.Range
{
int index = BinarySearch(item.Address);
if (index >= 0 && Items[index].Value.Equals(item))
if (index >= 0 && Items[index] == item)
{
RemoveAt(index);
@@ -188,7 +121,7 @@ namespace Ryujinx.Memory.Range
/// </summary>
/// <param name="startItem">The first item in the range of items to be removed</param>
/// <param name="endItem">The last item in the range of items to be removed</param>
public override void RemoveRange(RangeItem<T> startItem, RangeItem<T> endItem)
public override void RemoveRange(T startItem, T endItem)
{
if (startItem is null)
{
@@ -197,7 +130,7 @@ namespace Ryujinx.Memory.Range
if (startItem == endItem)
{
Remove(startItem.Value);
Remove(startItem);
return;
}
@@ -229,42 +162,45 @@ namespace Ryujinx.Memory.Range
/// <param name="size">Size of the range</param>
public void RemoveRange(ulong address, ulong size)
{
int startIndex = BinarySearchLeftEdge(address, address + size);
(int startIndex, int endIndex) = BinarySearchEdges(address, address + size);
if (startIndex < 0)
{
return;
}
int endIndex = startIndex;
while (Items[endIndex] is not null && Items[endIndex].Address < address + size)
if (startIndex == endIndex - 1)
{
if (endIndex == Count - 1)
{
break;
}
endIndex++;
RemoveAt(startIndex);
return;
}
if (endIndex < Count - 1)
RemoveRangeInternal(startIndex, endIndex);
}
/// <summary>
/// Removes a range of items from the item list
/// </summary>
/// <param name="index">Start index of the range</param>
/// <param name="endIndex">End index of the range (exclusive)</param>
private void RemoveRangeInternal(int index, int endIndex)
{
if (endIndex < Count)
{
Items[endIndex + 1].Previous = startIndex > 0 ? Items[startIndex - 1] : null;
Items[endIndex].Previous = index > 0 ? Items[index - 1] : null;
}
if (startIndex > 0)
if (index > 0)
{
Items[startIndex - 1].Next = endIndex < Count - 1 ? Items[endIndex + 1] : null;
Items[index - 1].Next = endIndex < Count ? Items[endIndex] : null;
}
if (endIndex < Count - 1)
if (endIndex < Count)
{
Array.Copy(Items, endIndex + 1, Items, startIndex, Count - endIndex - 1);
Array.Copy(Items, endIndex, Items, index, Count - endIndex);
}
Count -= endIndex - startIndex + 1;
Count -= endIndex - index;
}
/// <summary>
@@ -296,8 +232,8 @@ namespace Ryujinx.Memory.Range
// So we need to return both the split 0-1 and 1-2 ranges.
Lock.EnterWriteLock();
(RangeItem<T> first, RangeItem<T> last) = FindOverlapsAsNodes(address, size);
list = new List<T>();
(T first, T last) = FindOverlapsAsNodes(address, size);
list = [];
if (first is null)
{
@@ -311,42 +247,41 @@ namespace Ryujinx.Memory.Range
ulong lastAddress = address;
ulong endAddress = address + size;
RangeItem<T> current = first;
T current = first;
while (last is not null && current is not null && current.Address < endAddress)
{
T region = current.Value;
if (first == last && region.Address == address && region.Size == size)
if (first == last && current.Address == address && current.Size == size)
{
// Exact match, no splitting required.
list.Add(region);
list.Add(current);
Lock.ExitWriteLock();
return;
}
if (lastAddress < region.Address)
if (lastAddress < current.Address)
{
// There is a gap between this region and the last. We need to fill it.
T fillRegion = factory(lastAddress, region.Address - lastAddress);
T fillRegion = factory(lastAddress, current.Address - lastAddress);
list.Add(fillRegion);
Add(fillRegion);
}
if (region.Address < address)
if (current.Address < address)
{
// Split the region around our base address and take the high half.
region = Split(region, address);
current = Split(current, address);
}
if (region.EndAddress > address + size)
if (current.EndAddress > address + size)
{
// Split the region around our end address and take the low half.
Split(region, address + size);
Split(current, address + size);
}
list.Add(region);
lastAddress = region.EndAddress;
list.Add(current);
lastAddress = current.EndAddress;
current = current.Next;
}
@@ -374,7 +309,6 @@ namespace Ryujinx.Memory.Range
private T Split(T region, ulong splitAddress)
{
T newRegion = (T)region.Split(splitAddress);
Update(region);
Add(newRegion);
return newRegion;
}
@@ -386,16 +320,11 @@ namespace Ryujinx.Memory.Range
/// <param name="size">Size in bytes of the range</param>
/// <returns>The leftmost overlapping item, or null if none is found</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public override RangeItem<T> FindOverlap(ulong address, ulong size)
public override T FindOverlap(ulong address, ulong size)
{
int index = BinarySearchLeftEdge(address, address + size);
if (index < 0)
{
return null;
}
return Items[index];
return index < 0 ? null : Items[index];
}
/// <summary>
@@ -405,16 +334,11 @@ namespace Ryujinx.Memory.Range
/// <param name="size">Size in bytes of the range</param>
/// <returns>The overlapping item, or null if none is found</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public override RangeItem<T> FindOverlapFast(ulong address, ulong size)
public override T FindOverlapFast(ulong address, ulong size)
{
int index = BinarySearch(address, address + size);
if (index < 0)
{
return null;
}
return Items[index];
return index < 0 ? null : Items[index];
}
/// <summary>
@@ -424,23 +348,18 @@ namespace Ryujinx.Memory.Range
/// <param name="size">Size in bytes of the range</param>
/// <returns>The first and last overlapping items, or null if none are found</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public (RangeItem<T>, RangeItem<T>) FindOverlapsAsNodes(ulong address, ulong size)
public (T, T) FindOverlapsAsNodes(ulong address, ulong size)
{
(int index, int endIndex) = BinarySearchEdges(address, address + size);
if (index < 0)
{
return (null, null);
}
return (Items[index], Items[endIndex - 1]);
return index < 0 ? (null, null) : (Items[index], Items[endIndex - 1]);
}
public RangeItem<T>[] FindOverlapsAsArray(ulong address, ulong size, out int length)
public T[] FindOverlapsAsArray(ulong address, ulong size, out int length)
{
(int index, int endIndex) = BinarySearchEdges(address, address + size);
RangeItem<T>[] result;
T[] result;
if (index < 0)
{
@@ -449,29 +368,20 @@ namespace Ryujinx.Memory.Range
}
else
{
result = ArrayPool<RangeItem<T>>.Shared.Rent(endIndex - index);
result = ArrayPool<T>.Shared.Rent(endIndex - index);
length = endIndex - index;
Array.Copy(Items, index, result, 0, endIndex - index);
Items.AsSpan(index, endIndex - index).CopyTo(result);
}
return result;
}
public Span<RangeItem<T>> FindOverlapsAsSpan(ulong address, ulong size)
public ReadOnlySpan<T> FindOverlapsAsSpan(ulong address, ulong size)
{
(int index, int endIndex) = BinarySearchEdges(address, address + size);
Span<RangeItem<T>> result;
if (index < 0)
{
result = [];
}
else
{
result = Items.AsSpan().Slice(index, endIndex - index);
}
ReadOnlySpan<T> result = index < 0 ? [] : Items.AsSpan(index, endIndex - index);
return result;
}
@@ -480,7 +390,7 @@ namespace Ryujinx.Memory.Range
{
for (int i = 0; i < Count; i++)
{
yield return Items[i].Value;
yield return Items[i];
}
}
}

View File

@@ -14,14 +14,14 @@ namespace Ryujinx.Memory.Range
/// startIndex is inclusive.
/// endIndex is exclusive.
/// </remarks>
public readonly struct OverlapResult<T> where T : IRange
public readonly struct OverlapResult<T> where T : class, IRangeListRange<T>
{
public readonly int StartIndex = -1;
public readonly int EndIndex = -1;
public readonly RangeItem<T> QuickResult;
public readonly T QuickResult;
public int Count => EndIndex - StartIndex;
public OverlapResult(int startIndex, int endIndex, RangeItem<T> quickResult = null)
public OverlapResult(int startIndex, int endIndex, T quickResult = null)
{
this.StartIndex = startIndex;
this.EndIndex = endIndex;
@@ -33,7 +33,7 @@ namespace Ryujinx.Memory.Range
/// Sorted list of ranges that supports binary search.
/// </summary>
/// <typeparam name="T">Type of the range.</typeparam>
public class RangeList<T> : RangeListBase<T> where T : IRange
public class RangeList<T> : RangeListBase<T> where T : class, IRangeListRange<T>
{
public readonly ReaderWriterLockSlim Lock = new();
@@ -61,104 +61,6 @@ namespace Ryujinx.Memory.Range
index = ~index;
}
Insert(index, new RangeItem<T>(item));
}
/// <summary>
/// Updates an item's end address on the list. Address must be the same.
/// </summary>
/// <param name="item">The item to be updated</param>
/// <returns>True if the item was located and updated, false otherwise</returns>
protected override bool Update(T item)
{
int index = BinarySearch(item.Address);
if (index >= 0)
{
while (index < Count)
{
if (Items[index].Value.Equals(item))
{
RangeItem<T> rangeItem = new(item) { Previous = Items[index].Previous, Next = Items[index].Next };
if (index > 0)
{
Items[index - 1].Next = rangeItem;
}
if (index < Count - 1)
{
Items[index + 1].Previous = rangeItem;
}
Items[index] = rangeItem;
return true;
}
if (Items[index].Address > item.Address)
{
break;
}
index++;
}
}
return false;
}
/// <summary>
/// Updates an item's end address on the list. Address must be the same.
/// </summary>
/// <param name="item">The RangeItem to be updated</param>
/// <returns>True if the item was located and updated, false otherwise</returns>
protected override bool Update(RangeItem<T> item)
{
int index = BinarySearch(item.Address);
if (index >= 0)
{
while (index < Count)
{
if (Items[index].Equals(item))
{
RangeItem<T> rangeItem = new(item.Value) { Previous = item.Previous, Next = item.Next };
if (index > 0)
{
Items[index - 1].Next = rangeItem;
}
if (index < Count - 1)
{
Items[index + 1].Previous = rangeItem;
}
Items[index] = rangeItem;
return true;
}
if (Items[index].Address > item.Address)
{
break;
}
index++;
}
}
return false;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void Insert(int index, RangeItem<T> item)
{
Debug.Assert(item.Address != item.EndAddress);
Debug.Assert(item.Address % 32 == 0);
if (Count + 1 > Items.Length)
{
Array.Resize(ref Items, Items.Length + BackingGrowthSize);
@@ -220,7 +122,7 @@ namespace Ryujinx.Memory.Range
/// <param name="startItem">The first item in the range of items to be removed</param>
/// <param name="endItem">The last item in the range of items to be removed</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public override void RemoveRange(RangeItem<T> startItem, RangeItem<T> endItem)
public override void RemoveRange(T startItem, T endItem)
{
if (startItem is null)
{
@@ -229,30 +131,29 @@ namespace Ryujinx.Memory.Range
if (startItem == endItem)
{
Remove(startItem.Value);
Remove(startItem);
return;
}
int startIndex = BinarySearch(startItem.Address);
int endIndex = BinarySearch(endItem.Address);
(int index, int endIndex) = BinarySearchEdges(startItem.Address, endItem.EndAddress);
if (endIndex < Count - 1)
if (endIndex < Count)
{
Items[endIndex + 1].Previous = startIndex > 0 ? Items[startIndex - 1] : null;
Items[endIndex].Previous = index > 0 ? Items[index - 1] : null;
}
if (startIndex > 0)
if (index > 0)
{
Items[startIndex - 1].Next = endIndex < Count - 1 ? Items[endIndex + 1] : null;
Items[index - 1].Next = endIndex < Count ? Items[endIndex] : null;
}
if (endIndex < Count - 1)
if (endIndex < Count)
{
Array.Copy(Items, endIndex + 1, Items, startIndex, Count - endIndex - 1);
Array.Copy(Items, endIndex, Items, index, Count - endIndex);
}
Count -= endIndex - startIndex + 1;
Count -= endIndex - index;
}
/// <summary>
@@ -268,7 +169,7 @@ namespace Ryujinx.Memory.Range
{
while (index < Count)
{
if (Items[index].Value.Equals(item))
if (Items[index] == item)
{
RemoveAt(index);
@@ -298,7 +199,7 @@ namespace Ryujinx.Memory.Range
/// <param name="size">Size in bytes of the range</param>
/// <returns>The overlapping item, or the default value for the type if none found</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public override RangeItem<T> FindOverlap(ulong address, ulong size)
public override T FindOverlap(ulong address, ulong size)
{
int index = BinarySearchLeftEdge(address, address + size);
@@ -321,7 +222,7 @@ namespace Ryujinx.Memory.Range
/// <param name="size">Size in bytes of the range</param>
/// <returns>The overlapping item, or the default value for the type if none found</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public override RangeItem<T> FindOverlapFast(ulong address, ulong size)
public override T FindOverlapFast(ulong address, ulong size)
{
int index = BinarySearch(address, address + size);
@@ -340,7 +241,7 @@ namespace Ryujinx.Memory.Range
/// <param name="size">Size in bytes of the range</param>
/// <param name="output">Output array where matches will be written. It is automatically resized to fit the results</param>
/// <returns>Range information of overlapping items found</returns>
private OverlapResult<T> FindOverlaps(ulong address, ulong size, ref RangeItem<T>[] output)
private OverlapResult<T> FindOverlaps(ulong address, ulong size, ref T[] output)
{
int outputCount = 0;
@@ -353,7 +254,7 @@ namespace Ryujinx.Memory.Range
for (int i = startIndex; i < Count; i++)
{
ref RangeItem<T> item = ref Items[i];
T item = Items[i];
if (item.Address >= endAddress)
{
@@ -398,7 +299,7 @@ namespace Ryujinx.Memory.Range
{
for (int i = 0; i < Count; i++)
{
yield return Items[i].Value;
yield return Items[i];
}
}
}

View File

@@ -1,56 +1,22 @@
using Ryujinx.Common;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
namespace Ryujinx.Memory.Range
{
public class RangeItem<TValue> where TValue : IRange
public interface IRangeListRange<TValue> : IRange where TValue : class, IRangeListRange<TValue>
{
public RangeItem<TValue> Next;
public RangeItem<TValue> Previous;
public ulong Address;
public ulong EndAddress;
public TValue Value;
public RangeItem()
{
}
public RangeItem(TValue value)
{
Address = value.Address;
EndAddress = value.Address + value.Size;
Value = value;
}
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)
{
return Address < endAddress && address < EndAddress;
}
public TValue Next { get; set; }
public TValue Previous { get; set; }
}
public unsafe abstract class RangeListBase<T> : IEnumerable<T> where T : IRange
public unsafe abstract class RangeListBase<T> : IEnumerable<T> where T : class, IRangeListRange<T>
{
protected static readonly ObjectPool<RangeItem<T>> _rangeItemPool = new(() => new RangeItem<T>());
private const int BackingInitialSize = 1024;
protected RangeItem<T>[] Items;
protected T[] Items;
protected readonly int BackingGrowthSize;
public int Count { get; protected set; }
@@ -62,32 +28,18 @@ namespace Ryujinx.Memory.Range
protected RangeListBase(int backingInitialSize = BackingInitialSize)
{
BackingGrowthSize = backingInitialSize;
Items = new RangeItem<T>[backingInitialSize];
Items = new T[backingInitialSize];
}
public abstract void Add(T item);
/// <summary>
/// Updates an item's end address on the list. Address must be the same.
/// </summary>
/// <param name="item">The item to be updated</param>
/// <returns>True if the item was located and updated, false otherwise</returns>
protected abstract bool Update(T item);
/// <summary>
/// Updates an item's end address on the list. Address must be the same.
/// </summary>
/// <param name="item">The RangeItem to be updated</param>
/// <returns>True if the item was located and updated, false otherwise</returns>
protected abstract bool Update(RangeItem<T> item);
public abstract bool Remove(T item);
public abstract void RemoveRange(RangeItem<T> startItem, RangeItem<T> endItem);
public abstract void RemoveRange(T startItem, T endItem);
public abstract RangeItem<T> FindOverlap(ulong address, ulong size);
public abstract T FindOverlap(ulong address, ulong size);
public abstract RangeItem<T> FindOverlapFast(ulong address, ulong size);
public abstract T FindOverlapFast(ulong address, ulong size);
/// <summary>
/// Performs binary search on the internal list of items.
@@ -106,7 +58,7 @@ namespace Ryujinx.Memory.Range
int middle = left + (range >> 1);
ref RangeItem<T> item = ref Items[middle];
T item = Items[middle];
if (item.Address == address)
{
@@ -144,7 +96,7 @@ namespace Ryujinx.Memory.Range
int middle = left + (range >> 1);
ref RangeItem<T> item = ref Items[middle];
T item = Items[middle];
if (item.OverlapsWith(address, endAddress))
{
@@ -185,7 +137,7 @@ namespace Ryujinx.Memory.Range
int middle = left + (range >> 1);
ref RangeItem<T> item = ref Items[middle];
T item = Items[middle];
bool match = item.OverlapsWith(address, endAddress);
@@ -237,7 +189,7 @@ namespace Ryujinx.Memory.Range
int middle = right - (range >> 1);
ref RangeItem<T> item = ref Items[middle];
T item = Items[middle];
bool match = item.OverlapsWith(address, endAddress);
@@ -282,7 +234,7 @@ namespace Ryujinx.Memory.Range
if (Count == 1)
{
ref RangeItem<T> item = ref Items[0];
T item = Items[0];
if (item.OverlapsWith(address, endAddress))
{
@@ -312,7 +264,7 @@ namespace Ryujinx.Memory.Range
int middle = left + (range >> 1);
ref RangeItem<T> item = ref Items[middle];
T item = Items[middle];
bool match = item.OverlapsWith(address, endAddress);
@@ -369,7 +321,7 @@ namespace Ryujinx.Memory.Range
int middle = right - (range >> 1);
ref RangeItem<T> item = ref Items[middle];
T item = Items[middle];
bool match = item.OverlapsWith(address, endAddress);

View File

@@ -5,7 +5,7 @@ namespace Ryujinx.Memory.Tracking
/// <summary>
/// A region of memory.
/// </summary>
abstract class AbstractRegion : INonOverlappingRange
abstract class AbstractRegion<T> : INonOverlappingRange<T> where T : class, INonOverlappingRange<T>
{
/// <summary>
/// Base address.
@@ -21,6 +21,9 @@ namespace Ryujinx.Memory.Tracking
/// End address.
/// </summary>
public ulong EndAddress => Address + Size;
public T Next { get; set; }
public T Previous { get; set; }
/// <summary>
/// Create a new region.
@@ -37,11 +40,11 @@ namespace Ryujinx.Memory.Tracking
/// Check if this range overlaps with another.
/// </summary>
/// <param name="address">Base address</param>
/// <param name="size">Size of the range</param>
/// <param name="endAddress">End address</param>
/// <returns>True if overlapping, false otherwise</returns>
public bool OverlapsWith(ulong address, ulong size)
public bool OverlapsWith(ulong address, ulong endAddress)
{
return Address < address + size && address < EndAddress;
return Address < endAddress && address < EndAddress;
}
/// <summary>
@@ -68,6 +71,6 @@ namespace Ryujinx.Memory.Tracking
/// </summary>
/// <param name="splitAddress">Address to split the region around</param>
/// <returns>The second part of the split region, with start address at the given split.</returns>
public abstract INonOverlappingRange Split(ulong splitAddress);
public abstract INonOverlappingRange<T> Split(ulong splitAddress);
}
}

View File

@@ -81,10 +81,10 @@ namespace Ryujinx.Memory.Tracking
{
NonOverlappingRangeList<VirtualRegion> regions = type == 0 ? _virtualRegions : _guestVirtualRegions;
regions.Lock.EnterReadLock();
Span<RangeItem<VirtualRegion>> overlaps = regions.FindOverlapsAsSpan(va, size);
ReadOnlySpan<VirtualRegion> overlaps = regions.FindOverlapsAsSpan(va, size);
for (int i = 0; i < overlaps.Length; i++)
{
VirtualRegion region = overlaps[i].Value;
VirtualRegion region = overlaps[i];
// If the region has been fully remapped, signal that it has been mapped again.
bool remapped = _memoryManager.IsRangeMapped(region.Address, region.Size);
@@ -117,11 +117,11 @@ namespace Ryujinx.Memory.Tracking
{
NonOverlappingRangeList<VirtualRegion> regions = type == 0 ? _virtualRegions : _guestVirtualRegions;
regions.Lock.EnterReadLock();
Span<RangeItem<VirtualRegion>> overlaps = regions.FindOverlapsAsSpan(va, size);
ReadOnlySpan<VirtualRegion> overlaps = regions.FindOverlapsAsSpan(va, size);
for (int i = 0; i < overlaps.Length; i++)
{
overlaps[i].Value.SignalMappingChanged(false);
overlaps[i].SignalMappingChanged(false);
}
regions.Lock.ExitReadLock();
}
@@ -301,7 +301,7 @@ 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, out int length);
VirtualRegion[] overlaps = regions.FindOverlapsAsArray(address, size, out int length);
regions.Lock.ExitReadLock();
if (length == 0 && !precise)
@@ -327,7 +327,7 @@ namespace Ryujinx.Memory.Tracking
for (int i = 0; i < length; i++)
{
VirtualRegion region = overlaps[i].Value;
VirtualRegion region = overlaps[i];
if (precise)
{
@@ -341,7 +341,7 @@ namespace Ryujinx.Memory.Tracking
if (length != 0)
{
ArrayPool<RangeItem<VirtualRegion>>.Shared.Return(overlaps);
ArrayPool<VirtualRegion>.Shared.Return(overlaps);
}
}
}

View File

@@ -6,7 +6,7 @@ namespace Ryujinx.Memory.Tracking
/// <summary>
/// A region of virtual memory.
/// </summary>
class VirtualRegion : AbstractRegion
class VirtualRegion : AbstractRegion<VirtualRegion>
{
public List<RegionHandle> Handles = [];
@@ -137,7 +137,7 @@ namespace Ryujinx.Memory.Tracking
}
}
public override INonOverlappingRange Split(ulong splitAddress)
public override INonOverlappingRange<VirtualRegion> Split(ulong splitAddress)
{
VirtualRegion newRegion = new(_tracking, splitAddress, EndAddress - splitAddress, Guest, _lastPermission);
Size = splitAddress - Address;