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

Chris Lattner lattner at cs.uiuc.edu
Wed Mar 2 20:49:48 PST 2005



Changes in directory llvm-poolalloc/runtime/FL2Allocator:

FreeListAllocator.cpp updated: 1.36 -> 1.37
PoolAllocator.h updated: 1.19 -> 1.20
---
Log message:

Now that we have templates, we can actually use them for something interesting.

In particular, we make the following changes for pointer compressed pools 
(because we know they are contiguous and max 2^32 bytes):

1. The loop in poolalloc to allocate new chunks of memory is now no longer a  
   loop.
2. NodeHeader is now a 4 byte object size instead of 8 bytes.
3. FreedNodeHeader now consists of two 4 byte indexes, instead of two pointers.
   On a 64-bit system, this shrinks the minimum object size from 16 bytes to 8 
   bytes.

The code to manage the differences between normal pools (which use real pointers
not indexes), and pointer compressed pools is all isolated to two small traits
classes.



---
Diffs of the changes:  (+123 -32)

 FreeListAllocator.cpp |   95 +++++++++++++++++++++++++++++++++++++-------------
 PoolAllocator.h       |   60 ++++++++++++++++++++++++++-----
 2 files changed, 123 insertions(+), 32 deletions(-)


Index: llvm-poolalloc/runtime/FL2Allocator/FreeListAllocator.cpp
diff -u llvm-poolalloc/runtime/FL2Allocator/FreeListAllocator.cpp:1.36 llvm-poolalloc/runtime/FL2Allocator/FreeListAllocator.cpp:1.37
--- llvm-poolalloc/runtime/FL2Allocator/FreeListAllocator.cpp:1.36	Wed Mar  2 21:36:16 2005
+++ llvm-poolalloc/runtime/FL2Allocator/FreeListAllocator.cpp	Wed Mar  2 22:49:32 2005
@@ -13,7 +13,6 @@
 //===----------------------------------------------------------------------===//
 
 #include "PoolAllocator.h"
-#include <assert.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
@@ -149,24 +148,47 @@
 template<typename PoolTraits>
 static void AddNodeToFreeList(PoolTy<PoolTraits> *Pool,
                               FreedNodeHeader<PoolTraits> *FreeNode) {
-  FreedNodeHeader<PoolTraits> **FreeList;
+  typename PoolTraits::FreeNodeHeaderPtrTy *FreeList;
   if (FreeNode->Header.Size == Pool->DeclaredSize)
     FreeList = &Pool->ObjFreeList;
   else
     FreeList = &Pool->OtherFreeList;
 
-  FreeNode->PrevP = FreeList;
+  void *PoolBase = Pool->Slabs;
+
+  typename PoolTraits::FreeNodeHeaderPtrTy FreeNodeIdx = 
+    PoolTraits::FNHPtrToIndex(FreeNode, PoolBase);
+
+  FreeNode->Prev = 0;   // First on the list.
   FreeNode->Next = *FreeList;
-  *FreeList = FreeNode;
+  *FreeList = FreeNodeIdx;
   if (FreeNode->Next)
-    FreeNode->Next->PrevP = &FreeNode->Next;
+    PoolTraits::IndexToFNHPtr(FreeNode->Next, PoolBase)->Prev = FreeNodeIdx;
 }
 
 template<typename PoolTraits>
-static void UnlinkFreeNode(FreedNodeHeader<PoolTraits> *FNH) {
-  *FNH->PrevP = FNH->Next;
+static void UnlinkFreeNode(PoolTy<PoolTraits> *Pool,
+                           FreedNodeHeader<PoolTraits> *FNH) {
+  void *PoolBase = Pool->Slabs;
+
+  // Make the predecessor point to our next node.
+  if (FNH->Prev)
+    PoolTraits::IndexToFNHPtr(FNH->Prev, PoolBase)->Next = FNH->Next;
+  else {
+    typename PoolTraits::FreeNodeHeaderPtrTy NodeIdx = 
+      PoolTraits::FNHPtrToIndex(FNH, PoolBase);
+
+    if (Pool->ObjFreeList == NodeIdx)
+      Pool->ObjFreeList = FNH->Next;
+    else {
+      assert(Pool->OtherFreeList == NodeIdx &&
+             "Prev Ptr is null but not at head of free list?");
+      Pool->OtherFreeList = FNH->Next;
+    }
+  }
+
   if (FNH->Next)
-    FNH->Next->PrevP = FNH->PrevP;
+    PoolTraits::IndexToFNHPtr(FNH->Next, PoolBase)->Prev = FNH->Prev;
 }
 
 
@@ -502,8 +524,11 @@
 
   // Fast path - allocate objects off the object list.
   if (NumBytes == Pool->DeclaredSize && Pool->ObjFreeList != 0) {
-    FreedNodeHeader<PoolTraits> *Node = Pool->ObjFreeList;
-    UnlinkFreeNode(Node);
+    typename PoolTraits::FreeNodeHeaderPtrTy NodeIdx = Pool->ObjFreeList;
+    void *PoolBase = Pool->Slabs;
+    FreedNodeHeader<PoolTraits> *Node =
+      PoolTraits::IndexToFNHPtr(NodeIdx, PoolBase);
+    UnlinkFreeNode(Pool, Node);
     assert(NumBytes == Node->Header.Size);
 
     Node->Header.Size = NumBytes|1;   // Mark as allocated
@@ -519,7 +544,9 @@
   // Fast path.  In the common case, we can allocate a portion of the node at
   // the front of the free list.
   do {
-    FreedNodeHeader<PoolTraits> *FirstNode = Pool->OtherFreeList;
+    void *PoolBase = Pool->Slabs;
+    FreedNodeHeader<PoolTraits> *FirstNode =
+      PoolTraits::IndexToFNHPtr(Pool->OtherFreeList, PoolBase);
     if (FirstNode) {
       unsigned FirstNodeSize = FirstNode->Header.Size;
       if (FirstNodeSize >= NumBytes) {
@@ -530,14 +557,14 @@
                                    sizeof(NodeHeader<PoolTraits>) +NumBytes);
           
           // Remove from list
-          UnlinkFreeNode(FirstNode);
+          UnlinkFreeNode(Pool, FirstNode);
           
           NextNodes->Header.Size = FirstNodeSize-NumBytes -
                                    sizeof(NodeHeader<PoolTraits>);
           AddNodeToFreeList(Pool, NextNodes);
           
         } else {
-          UnlinkFreeNode(FirstNode);
+          UnlinkFreeNode(Pool, FirstNode);
           NumBytes = FirstNodeSize;
         }
         FirstNode->Header.Size = NumBytes|1;   // Mark as allocated
@@ -547,19 +574,25 @@
 
       // Perform a search of the free list, taking the front of the first free
       // chunk that is big enough.
-      FreedNodeHeader<PoolTraits> **FN = &Pool->OtherFreeList;
+      typename PoolTraits::FreeNodeHeaderPtrTy *FN = &Pool->OtherFreeList;
       FreedNodeHeader<PoolTraits> *FNN = FirstNode;
       
       // Search the list for the first-fit.
-      while (FNN && FNN->Header.Size < NumBytes)
-        FN = &FNN->Next, FNN = *FN;
+      while (FNN && FNN->Header.Size < NumBytes) {
+        // Advance FN to point to the Next field of FNN.
+        FN = &FNN->Next;
+
+        // Advance FNN to point to whatever the next node points to (null or the
+        // next node in the free list).
+        FNN = PoolTraits::IndexToFNHPtr(*FN, PoolBase);
+      }
       
       if (FNN) {
         // We found a slab big enough.  If it's a perfect fit, just unlink
         // from the free list, otherwise, slice a little bit off and adjust
         // the free list.
         if (FNN->Header.Size > 2*NumBytes+sizeof(NodeHeader<PoolTraits>)) {
-          UnlinkFreeNode(FNN);
+          UnlinkFreeNode(Pool, FNN);
           
           // Put the remainder back on the list...
           FreedNodeHeader<PoolTraits> *NextNodes =
@@ -570,7 +603,7 @@
             sizeof(NodeHeader<PoolTraits>);
           AddNodeToFreeList(Pool, NextNodes);
         } else {
-          UnlinkFreeNode(FNN);
+          UnlinkFreeNode(Pool, FNN);
           NumBytes = FNN->Header.Size;
         }
         FNN->Header.Size = NumBytes|1;   // Mark as allocated
@@ -579,6 +612,12 @@
       }
     }
 
+    // If we are not allowed to grow this pool, don't.
+    if (!PoolTraits::CanGrowPool) {
+      abort();
+      return 0;
+    }
+
     // Oops, we didn't find anything on the free list big enough!  Allocate
     // another slab and try again.
     PoolSlab<PoolTraits>::create(Pool, NumBytes);
@@ -624,7 +663,7 @@
   NextFNH = (FreedNodeHeader<PoolTraits>*)((char*)Node+Size);
   while ((NextFNH->Header.Size & 1) == 0) {
     // Unlink NextFNH from the freelist that it is in.
-    UnlinkFreeNode(NextFNH);
+    UnlinkFreeNode(Pool, NextFNH);
     Size += sizeof(NodeHeader<PoolTraits>)+NextFNH->Header.Size;
     NextFNH = (FreedNodeHeader<PoolTraits>*)((char*)Node+Size);
   }
@@ -634,25 +673,35 @@
   // a simple check that prevents many horrible forms of fragmentation,
   // particularly when freeing objects in allocation order.
   //
-  if (FreedNodeHeader<PoolTraits> *ObjFNH = Pool->ObjFreeList)
+  if (Pool->ObjFreeList) {
+    void *PoolBase = Pool->Slabs;
+    FreedNodeHeader<PoolTraits> *ObjFNH = 
+      PoolTraits::IndexToFNHPtr(Pool->ObjFreeList, PoolBase);
+
     if ((char*)ObjFNH + sizeof(NodeHeader<PoolTraits>) +
-        ObjFNH->Header.Size == (char*)FNH){
+        ObjFNH->Header.Size == (char*)FNH) {
       // Merge this with a node that is already on the object size free list.
       // Because the object is growing, we will never be able to find it if we
       // leave it on the object freelist.
-      UnlinkFreeNode(ObjFNH);
+      UnlinkFreeNode(Pool, ObjFNH);
       ObjFNH->Header.Size += Size+sizeof(NodeHeader<PoolTraits>);
       AddNodeToFreeList(Pool, ObjFNH);
       return;
     }
+  }
+
+  if (Pool->OtherFreeList) {
+    void *PoolBase = Pool->Slabs;
+    FreedNodeHeader<PoolTraits> *OFNH = 
+      PoolTraits::IndexToFNHPtr(Pool->OtherFreeList, PoolBase);
 
-  if (FreedNodeHeader<PoolTraits> *OFNH = Pool->OtherFreeList)
     if ((char*)OFNH + sizeof(NodeHeader<PoolTraits>) +
         OFNH->Header.Size == (char*)FNH) {
       // Merge this with a node that is already on the object size free list.
       OFNH->Header.Size += Size+sizeof(NodeHeader<PoolTraits>);
       return;
     }
+  }
 
   FNH->Header.Size = Size;
   AddNodeToFreeList(Pool, FNH);


Index: llvm-poolalloc/runtime/FL2Allocator/PoolAllocator.h
diff -u llvm-poolalloc/runtime/FL2Allocator/PoolAllocator.h:1.19 llvm-poolalloc/runtime/FL2Allocator/PoolAllocator.h:1.20
--- llvm-poolalloc/runtime/FL2Allocator/PoolAllocator.h:1.19	Wed Mar  2 21:36:16 2005
+++ llvm-poolalloc/runtime/FL2Allocator/PoolAllocator.h	Wed Mar  2 22:49:32 2005
@@ -22,8 +22,12 @@
 #ifndef POOLALLOCATOR_RUNTIME_H
 #define POOLALLOCATOR_RUNTIME_H
 
+#include <assert.h>
+
 template<typename PoolTraits>
 struct PoolSlab;
+template<typename PoolTraits>
+struct FreedNodeHeader;
 
 // NormalPoolTraits - This describes normal pool allocation pools, which can
 // address the entire heap, and are made out of multiple chunks of memory.  The
@@ -31,7 +35,26 @@
 // pointers.
 struct NormalPoolTraits {
   typedef unsigned long NodeHeaderType;
-  enum { UseLargeArrayObjects = 1 };
+  enum {
+    UseLargeArrayObjects = 1,
+    CanGrowPool = 1,
+  };
+
+  // Pointers are just pointers.
+  typedef FreedNodeHeader<NormalPoolTraits>* FreeNodeHeaderPtrTy;
+
+
+  /// DerefFNHPtr - Given an index into the pool, return a pointer to the
+  /// FreeNodeHeader object.
+  static FreedNodeHeader<NormalPoolTraits>*
+  IndexToFNHPtr(FreeNodeHeaderPtrTy P, void *PoolBase) {
+    return P;
+  }
+
+  static FreeNodeHeaderPtrTy
+  FNHPtrToIndex(FreedNodeHeader<NormalPoolTraits>* FNHP, void *PoolBase) {
+    return FNHP;
+  }
 };
 
 
@@ -41,10 +64,28 @@
 // uses 32-bit indexes from the start of the pool instead of full pointers to
 // decrease the minimum object size.
 struct CompressedPoolTraits {
-  typedef unsigned long NodeHeaderType;
+  typedef unsigned NodeHeaderType;
 
-  enum { UseLargeArrayObjects = 0 };
-  
+  enum {
+    UseLargeArrayObjects = 0,
+    CanGrowPool = 0,
+  };
+
+  // Represent pointers with indexes from the pool base.
+  typedef unsigned FreeNodeHeaderPtrTy;
+
+  /// DerefFNHPtr - Given an index into the pool, return a pointer to the
+  /// FreeNodeHeader object.
+  static FreedNodeHeader<CompressedPoolTraits>*
+  IndexToFNHPtr(FreeNodeHeaderPtrTy P, void *PoolBase) {
+    return (FreedNodeHeader<CompressedPoolTraits>*)((char*)PoolBase + P);
+  }
+
+  static FreeNodeHeaderPtrTy
+  FNHPtrToIndex(FreedNodeHeader<CompressedPoolTraits>* FNHP, void *PoolBase) {
+    assert(FNHP && PoolBase && "Can't handle null FHNP!");
+    return (char*)FNHP - (char*)PoolBase;
+  }
 };
 
 
@@ -64,10 +105,11 @@
   NodeHeader<PoolTraits> Header;
 
   // Next - The next object in the free list.
-  FreedNodeHeader *Next;
+  typename PoolTraits::FreeNodeHeaderPtrTy Next;
 
-  // PrevP - The pointer that points to this node on the free list.
-  FreedNodeHeader **PrevP;
+  // Prev - The node that points to this node on the free list.  This is null
+  // if it is the first node in one of the two free lists.
+  typename PoolTraits::FreeNodeHeaderPtrTy Prev;
 };
 
 
@@ -107,8 +149,8 @@
   PoolSlab<PoolTraits> *Slabs;
 
   // The free node lists for objects of various sizes.  
-  FreedNodeHeader<PoolTraits> *ObjFreeList;
-  FreedNodeHeader<PoolTraits> *OtherFreeList;
+  typename PoolTraits::FreeNodeHeaderPtrTy ObjFreeList;
+  typename PoolTraits::FreeNodeHeaderPtrTy OtherFreeList;
 
   // Alignment - The required alignment of allocations the pool in bytes.
   unsigned Alignment;






More information about the llvm-commits mailing list