Parcourir la source

implement `MemoryManagerHostTracked.GetReadOnlySequence()` (#6695)

* implement `MemoryManagerHostTracked.GetReadOnlySequence()`, fixes crashes on game starts on MacOS

* whitespace fixes

* whitespace fixes

* add missing call to `SignalMemoryTracking()`

* adjust call to `SignalMemoryTracking()``

* don't use GetPhysicalAddressMemory()

* add newline for consistency
jhorv il y a 2 ans
Parent
commit
9b94662b4b

+ 64 - 0
src/Ryujinx.Cpu/Jit/MemoryManagerHostTracked.cs

@@ -85,6 +85,70 @@ namespace Ryujinx.Cpu.Jit
             _addressSpace = new(Tracking, backingMemory, _nativePageTable, useProtectionMirrors);
         }
 
+        public override ReadOnlySequence<byte> GetReadOnlySequence(ulong va, int size, bool tracked = false)
+        {
+            if (size == 0)
+            {
+                return ReadOnlySequence<byte>.Empty;
+            }
+
+            try
+            {
+                if (tracked)
+                {
+                    SignalMemoryTracking(va, (ulong)size, false);
+                }
+                else
+                {
+                    AssertValidAddressAndSize(va, (ulong)size);
+                }
+
+                ulong endVa = va + (ulong)size;
+                int offset = 0;
+
+                BytesReadOnlySequenceSegment first = null, last = null;
+
+                while (va < endVa)
+                {
+                    (MemoryBlock memory, ulong rangeOffset, ulong copySize) = GetMemoryOffsetAndSize(va, (ulong)(size - offset));
+
+                    Memory<byte> physicalMemory = memory.GetMemory(rangeOffset, (int)copySize);
+
+                    if (first is null)
+                    {
+                        first = last = new BytesReadOnlySequenceSegment(physicalMemory);
+                    }
+                    else
+                    {
+                        if (last.IsContiguousWith(physicalMemory, out nuint contiguousStart, out int contiguousSize))
+                        {
+                            Memory<byte> contiguousPhysicalMemory = new NativeMemoryManager<byte>(contiguousStart, contiguousSize).Memory;
+
+                            last.Replace(contiguousPhysicalMemory);
+                        }
+                        else
+                        {
+                            last = last.Append(physicalMemory);
+                        }
+                    }
+
+                    va += copySize;
+                    offset += (int)copySize;
+                }
+
+                return new ReadOnlySequence<byte>(first, 0, last, (int)(size - last.RunningIndex));
+            }
+            catch (InvalidMemoryRegionException)
+            {
+                if (_invalidAccessHandler == null || !_invalidAccessHandler(va))
+                {
+                    throw;
+                }
+
+                return ReadOnlySequence<byte>.Empty;
+            }
+        }
+
         /// <inheritdoc/>
         public void Map(ulong va, ulong pa, ulong size, MemoryMapFlags flags)
         {

+ 5 - 0
src/Ryujinx.Memory/NativeMemoryManager.cs

@@ -8,6 +8,11 @@ namespace Ryujinx.Memory
         private readonly T* _pointer;
         private readonly int _length;
 
+        public NativeMemoryManager(nuint pointer, int length)
+            : this((T*)pointer, length)
+        {
+        }
+
         public NativeMemoryManager(T* pointer, int length)
         {
             _pointer = pointer;