[llvm-commits] CVS: poolalloc/runtime/FL2Allocator/FreeListAllocator.cpp

Chris Lattner lattner at cs.uiuc.edu
Fri Mar 5 04:57:22 PST 2004


Changes in directory poolalloc/runtime/FL2Allocator:

FreeListAllocator.cpp updated: 1.9 -> 1.10

---
Log message:

Make freed nodes exist in a doubly linked list.  This allows us to coallesce
consequtive freed nodes into larger nodes


---
Diffs of the changes:  (+63 -58)

Index: poolalloc/runtime/FL2Allocator/FreeListAllocator.cpp
diff -u poolalloc/runtime/FL2Allocator/FreeListAllocator.cpp:1.9 poolalloc/runtime/FL2Allocator/FreeListAllocator.cpp:1.10
--- poolalloc/runtime/FL2Allocator/FreeListAllocator.cpp:1.9	Fri Mar  5 03:33:13 2004
+++ poolalloc/runtime/FL2Allocator/FreeListAllocator.cpp	Fri Mar  5 04:53:26 2004
@@ -10,7 +10,6 @@
 // This file is one possible implementation of the LLVM pool allocator runtime
 // library.
 //
-//
 //===----------------------------------------------------------------------===//
 
 #include "PoolAllocator.h"
@@ -33,6 +32,29 @@
 #define DEBUG(X)
 #endif
 
+static inline unsigned getSizeClass(unsigned NumBytes) {
+  if (NumBytes <= FreeListOneSize)
+    return NumBytes > FreeListZeroSize;
+  else
+    return 2 + (NumBytes > FreeListTwoSize);
+}
+
+static void AddNodeToFreeList(PoolTy *Pool, FreedNodeHeader *FreeNode) {
+  unsigned SizeClass = getSizeClass(FreeNode->Header.Size);
+  FreeNode->PrevP = &Pool->FreeNodeLists[SizeClass];
+  FreeNode->Next = Pool->FreeNodeLists[SizeClass];
+  Pool->FreeNodeLists[SizeClass] = FreeNode;
+  if (FreeNode->Next)
+    FreeNode->Next->PrevP = &FreeNode->Next;
+}
+
+static void UnlinkFreeNode(FreedNodeHeader *FNH) {
+  *FNH->PrevP = FNH->Next;
+  if (FNH->Next)
+    FNH->Next->PrevP = FNH->PrevP;
+}
+
+
 // PoolSlab Structure - Hold multiple objects of the current node type.
 // Invariants: FirstUnused <= UsedEnd
 //
@@ -53,13 +75,18 @@
   unsigned Size = Pool->AllocSize;
   Pool->AllocSize <<= 1;
   Size = Size / SizeHint * SizeHint;
-  PoolSlab *PS = (PoolSlab*)malloc(Size);
+  PoolSlab *PS = (PoolSlab*)malloc(Size+sizeof(PoolSlab)+ 2*sizeof(NodeHeader));
 
   // Add the body of the slab to the free list...
   FreedNodeHeader *SlabBody = (FreedNodeHeader*)(PS+1);
-  SlabBody->Header.Size = Size-sizeof(PoolSlab)-sizeof(FreedNodeHeader);
-  SlabBody->Next = Pool->FreeNodeLists[LargeFreeList];
-  Pool->FreeNodeLists[LargeFreeList] = SlabBody;
+  SlabBody->Header.Size = Size;
+  AddNodeToFreeList(Pool, SlabBody);
+
+  // Make sure to add a marker at the end of the slab to prevent the coallescer
+  // from trying to merge off the end of the page.
+  FreedNodeHeader *End =
+    (FreedNodeHeader*)((char*)SlabBody + sizeof(NodeHeader) + Size);
+  End->Header.Size = ~0; // Looks like an allocated chunk
 
   // Add the slab to the list...
   PS->Next = Pool->Slabs;
@@ -113,26 +140,15 @@
   }
 }
 
-static inline unsigned getSizeClass(unsigned NumBytes) {
-  if (NumBytes <= FreeListOneSize)
-    return NumBytes > FreeListZeroSize;
-  else
-    return 2 + (NumBytes > FreeListTwoSize);
-}
-
-static void AddNodeToFreeList(PoolTy *Pool, FreedNodeHeader *FreeNode) {
-  unsigned SizeClass = getSizeClass(FreeNode->Header.Size);
-  FreeNode->Next = Pool->FreeNodeLists[SizeClass];
-  Pool->FreeNodeLists[SizeClass] = FreeNode;
-}
-
-
 void *poolalloc(PoolTy *Pool, unsigned NumBytes) {
   // If a null pool descriptor is passed in, this is not a pool allocated data
   // structure.  Hand off to the system malloc.
   if (Pool == 0) return malloc(NumBytes);
   if (NumBytes == 0) return 0;
   NumBytes = (NumBytes+3) & ~3;  // Round up to 4 bytes...
+
+  // Objects must be at least 8 bytes to hold the FreedNodeHeader object when
+  // they are freed.
   if (NumBytes < 8) NumBytes = 8;
 
   ++Pool->NumObjects;
@@ -145,11 +161,9 @@
   while (SizeClass < 3 && Pool->FreeNodeLists[SizeClass] == 0)
     ++SizeClass;
 
-  FreedNodeHeader *SizeClassFreeNodeList = Pool->FreeNodeLists[SizeClass];
-
   // Fast path.  In the common case, we can allocate a portion of the node at
   // the front of the free list.
-  if (FreedNodeHeader *FirstNode = SizeClassFreeNodeList) {
+  if (FreedNodeHeader *FirstNode = Pool->FreeNodeLists[SizeClass]) {
     unsigned FirstNodeSize = FirstNode->Header.Size;
     if (FirstNodeSize > NumBytes) {
       if (FirstNodeSize >= 2*NumBytes+sizeof(NodeHeader)) {
@@ -158,19 +172,16 @@
           (FreedNodeHeader*)((char*)FirstNode + sizeof(NodeHeader) + NumBytes);
 
         // Remove from list
-        Pool->FreeNodeLists[SizeClass] = FirstNode->Next;
+        UnlinkFreeNode(FirstNode);
 
         NextNodes->Header.Size = FirstNodeSize-NumBytes-sizeof(NodeHeader);
         AddNodeToFreeList(Pool, NextNodes);
 
-        FirstNode->Header.Size = NumBytes;
-        DEBUG(printf("alloc Pool:0x%X Bytes:%d -> 0x%X\n", Pool, NumBytes, 
-                     &FirstNode->Header+1));
-        return &FirstNode->Header+1;
+      } else {
+        UnlinkFreeNode(FirstNode);
+        NumBytes = FirstNodeSize;
       }
-
-      Pool->FreeNodeLists[SizeClass] = FirstNode->Next; // Unlink
-      FirstNode->Header.Size = FirstNodeSize;
+      FirstNode->Header.Size = NumBytes|1;   // Mark as allocated
       DEBUG(printf("alloc Pool:0x%X Bytes:%d -> 0x%X\n", Pool, NumBytes, 
                    &FirstNode->Header+1));
       return &FirstNode->Header+1;
@@ -193,25 +204,21 @@
         // the free list, otherwise, slice a little bit off and adjust the free
         // list.
         if (FNN->Header.Size > 2*NumBytes+sizeof(NodeHeader)) {
-          *FN = FNN->Next;   // Unlink
+          UnlinkFreeNode(FNN);
 
           // Put the remainder back on the list...
           FreedNodeHeader *NextNodes =
             (FreedNodeHeader*)((char*)FNN + sizeof(NodeHeader) + NumBytes);
           NextNodes->Header.Size = FNN->Header.Size-NumBytes-sizeof(NodeHeader);
           AddNodeToFreeList(Pool, NextNodes);
-
-          FNN->Header.Size = NumBytes;
-          DEBUG(printf("alloc Pool:0x%X Bytes:%d -> 0x%X\n", Pool, NumBytes, 
-                       &FNN->Header+1));
-          return &FNN->Header+1;
         } else {
-          *FN = FNN->Next;   // Unlink
-          FNN->Header.Size = FNN->Header.Size;
-          DEBUG(printf("alloc Pool:0x%X Bytes:%d -> 0x%X\n", Pool, NumBytes,
-                       &FNN->Header+1));
-          return &FNN->Header+1;
+          UnlinkFreeNode(FNN);
+          NumBytes = FNN->Header.Size;
         }
+        FNN->Header.Size = NumBytes|1;   // Mark as allocated
+        DEBUG(printf("alloc Pool:0x%X Bytes:%d -> 0x%X\n", Pool, NumBytes, 
+                     &FNN->Header+1));
+        return &FNN->Header+1;
       }
 
       if (SizeClass < LargeFreeList) {
@@ -239,7 +246,6 @@
   return LAH+1;
 }
 
-
 void poolfree(PoolTy *Pool, void *Node) {
   // If a null pool descriptor is passed in, this is not a pool allocated data
   // structure.  Hand off to the system free.
@@ -248,36 +254,35 @@
 
   // Check to see how many elements were allocated to this node...
   FreedNodeHeader *FNH = (FreedNodeHeader*)((char*)Node-sizeof(NodeHeader));
-  unsigned Size = FNH->Header.Size;
-
+  assert((FNH->Header.Size & 1) && "Node not allocated!");
+  unsigned Size = FNH->Header.Size & ~1;
   DEBUG(printf("free  Pool:0x%X <- 0x%X  Size:%d\n", Pool, Node, Size));
 
-  if (Size == ~0U) goto LargeArrayCase;
+  if (Size == ~1U) goto LargeArrayCase;
   
+  // If the node immediately after this one is also free, merge it into node.
+  FreedNodeHeader *NextFNH;
+  NextFNH = (FreedNodeHeader*)((char*)Node+Size);
+  while ((NextFNH->Header.Size & 1) == 0) {
+    // Unlink NextFNH from the freelist that it is in.
+    UnlinkFreeNode(NextFNH);
+    Size += sizeof(NodeHeader)+NextFNH->Header.Size;
+    NextFNH = (FreedNodeHeader*)((char*)Node+Size);
+  }
+
   // If there are already nodes on the freelist, see if these blocks can be
   // coallesced into one of the early blocks on the front of the list.  This is
   // a simple check that prevents many horrible forms of fragmentation.
   //
   for (unsigned SizeClass = 0; SizeClass <= LargeFreeList; ++SizeClass)
-    if (FreedNodeHeader *CurFrontNode = Pool->FreeNodeLists[SizeClass]) {
-      if ((char*)FNH + sizeof(NodeHeader) + Size == (char*)CurFrontNode) {
-        // This node immediately preceeds the node on the front of the
-        // free-list.  Remove the current front of the free list, replacing it
-        // with the current block.
-        FNH->Header.Size = Size + CurFrontNode->Header.Size+sizeof(NodeHeader);
-        FNH->Next = CurFrontNode->Next;
-        Pool->FreeNodeLists[SizeClass] = FNH;
-        return;
-      }
-      
-      if ((char*)CurFrontNode + sizeof(NodeHeader) + CurFrontNode->Header.Size ==
+    if (FreedNodeHeader *CurFrontNode = Pool->FreeNodeLists[SizeClass])
+      if ((char*)CurFrontNode + sizeof(NodeHeader) + CurFrontNode->Header.Size==
           (char*)FNH) {
         // This node immediately follows the node on the front of the free-list.
         // No list manipulation is required.
         CurFrontNode->Header.Size += Size+sizeof(NodeHeader);
         return;
       }
-    }
 
   FNH->Header.Size = Size;
   AddNodeToFreeList(Pool, FNH);





More information about the llvm-commits mailing list