瀏覽代碼

Update several methods to use GetNode directly and avoid array allocations

gdk 3 年之前
父節點
當前提交
c646638680
共有 1 個文件被更改,包括 74 次插入51 次删除
  1. 74 51
      Ryujinx.Memory/WindowsShared/PlaceholderManager.cs

+ 74 - 51
Ryujinx.Memory/WindowsShared/PlaceholderManager.cs

@@ -89,9 +89,12 @@ namespace Ryujinx.Memory.WindowsShared
             lock (_mappings)
             {
                 RangeNode<ulong> node = _mappings.GetNode(new RangeNode<ulong>(address, address + 1UL, default));
+                RangeNode<ulong> successorNode;
 
-                for (; node != null; node = node.Successor)
+                for (; node != null; node = successorNode)
                 {
+                    successorNode = node.Successor;
+
                     if (IsMapped(node.Value))
                     {
                         if (!WindowsApi.UnmapViewOfFile2(WindowsApi.CurrentProcessHandle, (IntPtr)node.Start, 2))
@@ -372,25 +375,25 @@ namespace Ryujinx.Memory.WindowsShared
             ulong endAddress = address + size;
             ulong blockAddress = (ulong)owner.Pointer;
             ulong blockEnd = blockAddress + owner.Size;
-            var overlaps = new RangeNode<ulong>[InitialOverlapsSize];
             int unmappedCount = 0;
 
             lock (_mappings)
             {
-                int count = _mappings.GetNodes(address, endAddress, ref overlaps);
+                RangeNode<ulong> node = _mappings.GetNode(new RangeNode<ulong>(address, address + 1UL, default));
 
-                if (count == 0)
+                if (node == null)
                 {
-                    // Nothing to coalesce if we no overlaps.
+                    // Nothing to coalesce if we have no overlaps.
                     return;
                 }
 
-                RangeNode<ulong> predecessor = overlaps[0].Predecessor;
-                RangeNode<ulong> successor = overlaps[count - 1].Successor;
+                RangeNode<ulong> predecessor = node.Predecessor;
+                RangeNode<ulong> successor = null;
 
-                for (int index = 0; index < count; index++)
+                for (; node != null; node = successor)
                 {
-                    var overlap = overlaps[index];
+                    successor = node.Successor;
+                    var overlap = node;
 
                     if (!IsMapped(overlap.Value))
                     {
@@ -400,6 +403,11 @@ namespace Ryujinx.Memory.WindowsShared
                         _mappings.Remove(overlap);
                         unmappedCount++;
                     }
+
+                    if (node.End >= endAddress)
+                    {
+                        break;
+                    }
                 }
 
                 if (predecessor != null && !IsMapped(predecessor.Value) && predecessor.Start >= blockAddress)
@@ -469,46 +477,50 @@ namespace Ryujinx.Memory.WindowsShared
             ulong reprotectSize = (ulong)size;
             ulong endAddress = reprotectAddress + reprotectSize;
 
-            var overlaps = new RangeNode<ulong>[InitialOverlapsSize];
-            int count;
+            bool success = true;
 
             lock (_mappings)
             {
-                count = _mappings.GetNodes(reprotectAddress, endAddress, ref overlaps);
-            }
+                RangeNode<ulong> node = _mappings.GetNode(new RangeNode<ulong>(reprotectAddress, reprotectAddress + 1UL, default));
+                RangeNode<ulong> successorNode;
 
-            bool success = true;
-
-            for (int index = 0; index < count; index++)
-            {
-                var overlap = overlaps[index];
+                for (; node != null; node = successorNode)
+                {
+                    successorNode = node.Successor;
+                    var overlap = node;
 
-                ulong mappedAddress = overlap.Start;
-                ulong mappedSize = overlap.End - overlap.Start;
+                    ulong mappedAddress = overlap.Start;
+                    ulong mappedSize = overlap.End - overlap.Start;
 
-                if (mappedAddress < reprotectAddress)
-                {
-                    ulong delta = reprotectAddress - mappedAddress;
-                    mappedAddress = reprotectAddress;
-                    mappedSize -= delta;
-                }
+                    if (mappedAddress < reprotectAddress)
+                    {
+                        ulong delta = reprotectAddress - mappedAddress;
+                        mappedAddress = reprotectAddress;
+                        mappedSize -= delta;
+                    }
 
-                ulong mappedEndAddress = mappedAddress + mappedSize;
+                    ulong mappedEndAddress = mappedAddress + mappedSize;
 
-                if (mappedEndAddress > endAddress)
-                {
-                    ulong delta = mappedEndAddress - endAddress;
-                    mappedSize -= delta;
-                }
+                    if (mappedEndAddress > endAddress)
+                    {
+                        ulong delta = mappedEndAddress - endAddress;
+                        mappedSize -= delta;
+                    }
 
-                if (!WindowsApi.VirtualProtect((IntPtr)mappedAddress, (IntPtr)mappedSize, WindowsApi.GetProtection(permission), out _))
-                {
-                    if (throwOnError)
+                    if (!WindowsApi.VirtualProtect((IntPtr)mappedAddress, (IntPtr)mappedSize, WindowsApi.GetProtection(permission), out _))
                     {
-                        throw new WindowsApiException("VirtualProtect");
+                        if (throwOnError)
+                        {
+                            throw new WindowsApiException("VirtualProtect");
+                        }
+
+                        success = false;
                     }
 
-                    success = false;
+                    if (node.End >= endAddress)
+                    {
+                        break;
+                    }
                 }
             }
 
@@ -565,26 +577,27 @@ namespace Ryujinx.Memory.WindowsShared
         private void UpdateProtection(ulong address, ulong size, MemoryPermission permission)
         {
             ulong endAddress = address + size;
-            var overlaps = new RangeNode<MemoryPermission>[InitialOverlapsSize];
-            int count;
 
             lock (_protections)
             {
-                count = _protections.GetNodes(address, endAddress, ref overlaps);
+                RangeNode<MemoryPermission> node = _protections.GetNode(new RangeNode<MemoryPermission>(address, address + 1UL, default));
 
-                if (count == 1 &&
-                    overlaps[0].Start <= address &&
-                    overlaps[0].End >= endAddress &&
-                    overlaps[0].Value == permission)
+                if (node != null &&
+                    node.Start <= address &&
+                    node.End >= endAddress &&
+                    node.Value == permission)
                 {
                     return;
                 }
 
+                RangeNode<MemoryPermission> successorNode;
+
                 ulong startAddress = address;
 
-                for (int index = 0; index < count; index++)
+                for (; node != null; node = successorNode)
                 {
-                    var protection = overlaps[index];
+                    successorNode = node.Successor;
+                    var protection = node;
 
                     ulong protAddress = protection.Start;
                     ulong protEndAddress = protection.End;
@@ -616,6 +629,11 @@ namespace Ryujinx.Memory.WindowsShared
                             _protections.Add(new RangeNode<MemoryPermission>(endAddress, protEndAddress, protPermission));
                         }
                     }
+
+                    if (node.End >= endAddress)
+                    {
+                        break;
+                    }
                 }
 
                 _protections.Add(new RangeNode<MemoryPermission>(startAddress, endAddress, permission));
@@ -630,16 +648,16 @@ namespace Ryujinx.Memory.WindowsShared
         private void RemoveProtection(ulong address, ulong size)
         {
             ulong endAddress = address + size;
-            var overlaps = new RangeNode<MemoryPermission>[InitialOverlapsSize];
-            int count;
 
             lock (_protections)
             {
-                count = _protections.GetNodes(address, endAddress, ref overlaps);
+                RangeNode<MemoryPermission> node = _protections.GetNode(new RangeNode<MemoryPermission>(address, address + 1UL, default));
+                RangeNode<MemoryPermission> successorNode;
 
-                for (int index = 0; index < count; index++)
+                for (; node != null; node = successorNode)
                 {
-                    var protection = overlaps[index];
+                    successorNode = node.Successor;
+                    var protection = node;
 
                     ulong protAddress = protection.Start;
                     ulong protEndAddress = protection.End;
@@ -656,6 +674,11 @@ namespace Ryujinx.Memory.WindowsShared
                     {
                         _protections.Add(new RangeNode<MemoryPermission>(endAddress, protEndAddress, protPermission));
                     }
+
+                    if (node.End >= endAddress)
+                    {
+                        break;
+                    }
                 }
             }
         }