Explorar o código

Misc fixes on the arena allocator (#364)

gdkchan %!s(int64=7) %!d(string=hai) anos
pai
achega
d6fba62f8a
Modificáronse 1 ficheiros con 43 adicións e 5 borrados
  1. 43 5
      Ryujinx.HLE/Memory/ArenaAllocator.cs

+ 43 - 5
Ryujinx.HLE/Memory/ArenaAllocator.cs

@@ -45,6 +45,33 @@ namespace Ryujinx.HLE.Memory
                     Rg.Position += Size;
                     Rg.Size     -= Size;
 
+                    if (Rg.Size == 0)
+                    {
+                        //Region is empty, just remove it.
+                        FreeRegions.Remove(Node);
+                    }
+                    else if (Node.Previous != null)
+                    {
+                        //Re-sort based on size (smaller first).
+                        Node = Node.Previous;
+
+                        FreeRegions.Remove(Node.Next);
+
+                        while (Node != null && (ulong)Node.Value.Size > (ulong)Rg.Size)
+                        {
+                            Node = Node.Previous;
+                        }
+
+                        if (Node != null)
+                        {
+                            FreeRegions.AddAfter(Node, Rg);
+                        }
+                        else
+                        {
+                            FreeRegions.AddFirst(Rg);
+                        }
+                    }
+
                     TotalUsedSize += Size;
 
                     return true;
@@ -65,7 +92,7 @@ namespace Ryujinx.HLE.Memory
             Region NewRg = new Region(Position, Size);
 
             LinkedListNode<Region> Node   = FreeRegions.First;
-            LinkedListNode<Region> PrevSz = Node;
+            LinkedListNode<Region> PrevSz = null;
 
             while (Node != null)
             {
@@ -77,27 +104,38 @@ namespace Ryujinx.HLE.Memory
 
                 if (Rg.Position == End)
                 {
+                    //Current region position matches the end of the freed region,
+                    //just merge the two and remove the current region from the list.
                     NewRg.Size += Rg.Size;
 
                     FreeRegions.Remove(Node);
                 }
                 else if (RgEnd == Position)
                 {
+                    //End of the current region matches the position of the freed region,
+                    //just merge the two and remove the current region from the list.
                     NewRg.Position  = Rg.Position;
                     NewRg.Size     += Rg.Size;
 
                     FreeRegions.Remove(Node);
                 }
-                else if ((ulong)Rg.Size < (ulong)NewRg.Size &&
-                         (ulong)Rg.Size > (ulong)PrevSz.Value.Size)
+                else
                 {
-                    PrevSz = Node;
+                    if (PrevSz == null)
+                    {
+                        PrevSz = Node;
+                    }
+                    else if ((ulong)Rg.Size < (ulong)NewRg.Size &&
+                             (ulong)Rg.Size > (ulong)PrevSz.Value.Size)
+                    {
+                        PrevSz = Node;
+                    }
                 }
 
                 Node = NextNode;
             }
 
-            if ((ulong)PrevSz.Value.Size < (ulong)Size)
+            if (PrevSz != null && (ulong)PrevSz.Value.Size < (ulong)Size)
             {
                 FreeRegions.AddAfter(PrevSz, NewRg);
             }