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

Chris Lattner lattner at cs.uiuc.edu
Mon Nov 8 22:41:32 PST 2004



Changes in directory poolalloc/runtime/FL2Allocator:

FreeListAllocator.cpp updated: 1.23 -> 1.24
PoolAllocator.h updated: 1.11 -> 1.12

---
Log message:

More improvements to trace output, allowing us to trace mallocrepl.

Two bugfixes:
1. On X86, make sure to align all returned pointers to 8 byte boundaries.  In
   particular, things with doubles in them REALLY want memory to be aligned,
   though we don't get bus errors on X86.  In the future, an argument to
   pool init can be used to relax this.
2. Do not allocate "large" objects out of the pool slab even if we have 
   enough space to do so in a slab.



---
Diffs of the changes:  (+80 -52)

Index: poolalloc/runtime/FL2Allocator/FreeListAllocator.cpp
diff -u poolalloc/runtime/FL2Allocator/FreeListAllocator.cpp:1.23 poolalloc/runtime/FL2Allocator/FreeListAllocator.cpp:1.24
--- poolalloc/runtime/FL2Allocator/FreeListAllocator.cpp:1.23	Sun Nov  7 19:45:55 2004
+++ poolalloc/runtime/FL2Allocator/FreeListAllocator.cpp	Tue Nov  9 00:41:22 2004
@@ -22,12 +22,12 @@
 #define INITIAL_SLAB_SIZE 4096
 #define LARGE_SLAB_SIZE   4096
 
-
+#ifndef NDEBUG
 // Configuration macros.  Define up to one of these.
 //#define PRINT_NUM_POOLS          // Print use dynamic # pools info
 //#define PRINT_POOLDESTROY_STATS  // When pools are destroyed, print stats
-//#define PRINT_POOL_TRACE         // Print a full trace
-
+#define PRINT_POOL_TRACE         // Print a full trace
+#endif
 
 //===----------------------------------------------------------------------===//
 // Pool Debugging stuff.
@@ -175,16 +175,26 @@
   Size = (Size+SizeHint-1) / SizeHint * SizeHint;
   PoolSlab *PS = (PoolSlab*)malloc(Size+sizeof(PoolSlab) + sizeof(NodeHeader) +
                                    sizeof(FreedNodeHeader));
+  char *PoolBody = (char*)(PS+1);
 
-  // Add the body of the slab to the free list...
-  FreedNodeHeader *SlabBody = (FreedNodeHeader*)(PS+1);
+  // If the Alignment is greater than the size of the FreedNodeHeader, skip over
+  // some space so that the a "free pointer + sizeof(FreedNodeHeader)" is always
+  // aligned.
+  unsigned Alignment = Pool->Alignment;
+  if (Alignment > sizeof(FreedNodeHeader)) {
+    PoolBody += Alignment-sizeof(FreedNodeHeader);
+    Size -= Alignment-sizeof(FreedNodeHeader);
+  }
+      
+  // Add the body of the slab to the free list.
+  FreedNodeHeader *SlabBody = (FreedNodeHeader*)PoolBody;
   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);
+      (FreedNodeHeader*)(PoolBody + sizeof(NodeHeader) + Size);
   End->Header.Size = ~0; // Looks like an allocated chunk
 
   // Add the slab to the list...
@@ -210,6 +220,7 @@
   memset(Pool, 0, sizeof(PoolTy));
   Pool->AllocSize = INITIAL_SLAB_SIZE;
   Pool->DeclaredSize = DeclaredSize;
+  Pool->Alignment = __alignof(double);
 
   DO_IF_TRACE(fprintf(stderr, "[%d] poolinit(0x%X, %d)\n", addPoolNumber(Pool),
                       Pool, DeclaredSize));
@@ -255,23 +266,33 @@
 
   // 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) NumBytes = 1;
-  unsigned PtrSize = sizeof(int*);
-  NumBytes = (NumBytes+(PtrSize-1)) & ~(PtrSize-1);  // Round up to 4/8 bytes...
+  if (Pool == 0) {
+    void *Result = malloc(NumBytes);
+    DO_IF_TRACE(fprintf(stderr, "0x%X [malloc]\n", Result));
+                return Result;
+  }
+  DO_IF_PNP(if (Pool->NumObjects == 0) ++PoolCounter);  // Track # pools.
 
   // Objects must be at least 8 bytes to hold the FreedNodeHeader object when
-  // they are freed.
+  // they are freed.  This also handles allocations of 0 bytes.
   if (NumBytes < (sizeof(FreedNodeHeader)-sizeof(NodeHeader)))
     NumBytes = sizeof(FreedNodeHeader)-sizeof(NodeHeader);
 
-  DO_IF_PNP(if (Pool->NumObjects == 0) ++PoolCounter);  // Track # pools.
+  // Adjust the size so that memory allocated from the pool is always on the
+  // proper alignment boundary.
+  unsigned Alignment = Pool->Alignment;
+  NumBytes = NumBytes+sizeof(FreedNodeHeader)+(Alignment-1);      // Round up
+  NumBytes = (NumBytes & ~(Alignment-1))-sizeof(FreedNodeHeader); // Truncate
 
   ++Pool->NumObjects;
   Pool->BytesAllocated += NumBytes;
 
+  if (NumBytes >= LARGE_SLAB_SIZE-sizeof(PoolSlab)-sizeof(NodeHeader))
+    goto LargeObject;
+
   // Figure out which size class to start scanning from.
-  unsigned SizeClass = getSizeClass(NumBytes);
+  unsigned SizeClass;
+  SizeClass = getSizeClass(NumBytes);
 
   // Scan for a class that has entries!
   while (SizeClass < 3 && Pool->FreeNodeLists[SizeClass] == 0)
@@ -305,46 +326,45 @@
 
   // Perform a search of the free list, taking the front of the first free chunk
   // that is big enough.
-  if (NumBytes <= LARGE_SLAB_SIZE-sizeof(PoolSlab)-sizeof(NodeHeader)) {
-    do {
-      FreedNodeHeader **FN = &Pool->FreeNodeLists[SizeClass];
-      FreedNodeHeader *FNN = *FN;
-
-      // Search the list for the first-fit
-      while (FNN && FNN->Header.Size < NumBytes)
-        FN = &FNN->Next, FNN = *FN;
-
-      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)) {
-          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);
-        } else {
-          UnlinkFreeNode(FNN);
-          NumBytes = FNN->Header.Size;
-        }
-        FNN->Header.Size = NumBytes|1;   // Mark as allocated
-        DO_IF_TRACE(fprintf(stderr, "0x%X\n", &FNN->Header+1));
-        return &FNN->Header+1;
-      }
+  do {
+    FreedNodeHeader **FN = &Pool->FreeNodeLists[SizeClass];
+    FreedNodeHeader *FNN = *FN;
+
+    // Search the list for the first-fit
+    while (FNN && FNN->Header.Size < NumBytes)
+      FN = &FNN->Next, FNN = *FN;
+
+    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)) {
+        UnlinkFreeNode(FNN);
 
-      if (SizeClass < LargeFreeList) {
-        ++SizeClass;
+        // 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);
       } else {
-        // Oops, we didn't find anything on the free list big enough!  Allocate
-        // another slab and try again.
-        PoolSlab::create(Pool, NumBytes);
+        UnlinkFreeNode(FNN);
+        NumBytes = FNN->Header.Size;
       }
-    } while (1);
-  }
+      FNN->Header.Size = NumBytes|1;   // Mark as allocated
+      DO_IF_TRACE(fprintf(stderr, "0x%X\n", &FNN->Header+1));
+      return &FNN->Header+1;
+    }
+
+    if (SizeClass < LargeFreeList) {
+      ++SizeClass;
+    } else {
+      // Oops, we didn't find anything on the free list big enough!  Allocate
+      // another slab and try again.
+      PoolSlab::create(Pool, NumBytes);
+    }
+  } while (1);
 
+LargeObject:
   // Otherwise, the allocation is a large array.  Since we're not going to be
   // able to help much for this allocation, simply pass it on to malloc.
   LargeArrayHeader *LAH = (LargeArrayHeader*)malloc(sizeof(LargeArrayHeader) + 
@@ -357,13 +377,17 @@
 }
 
 void poolfree(PoolTy *Pool, void *Node) {
+  if (Node == 0) return;
   DO_IF_TRACE(fprintf(stderr, "[%d] poolfree(0x%X) ",
                       getPoolNumber(Pool), Node));
 
   // If a null pool descriptor is passed in, this is not a pool allocated data
   // structure.  Hand off to the system free.
-  if (Pool == 0) { free(Node); return; }
-  if (Node == 0) return;
+  if (Pool == 0) {
+    free(Node);
+    DO_IF_TRACE(fprintf(stderr, "[free]\n"));
+    return;
+  }
 
   // Check to see how many elements were allocated to this node...
   FreedNodeHeader *FNH = (FreedNodeHeader*)((char*)Node-sizeof(NodeHeader));
@@ -385,7 +409,8 @@
 
   // 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.
+  // a simple check that prevents many horrible forms of fragmentation,
+  // particularly when freeing objects in allocation order.
   //
   for (unsigned SizeClass = 0; SizeClass <= LargeFreeList; ++SizeClass)
     if (FreedNodeHeader *CurFrontNode = Pool->FreeNodeLists[SizeClass])


Index: poolalloc/runtime/FL2Allocator/PoolAllocator.h
diff -u poolalloc/runtime/FL2Allocator/PoolAllocator.h:1.11 poolalloc/runtime/FL2Allocator/PoolAllocator.h:1.12
--- poolalloc/runtime/FL2Allocator/PoolAllocator.h:1.11	Sun Nov  7 19:44:13 2004
+++ poolalloc/runtime/FL2Allocator/PoolAllocator.h	Tue Nov  9 00:41:22 2004
@@ -86,6 +86,9 @@
   // The free node lists for objects of various sizes.  
   FreedNodeHeader *FreeNodeLists[4];
 
+  // Alignment - The required alignment of allocations the pool in bytes.
+  unsigned Alignment;
+
   // NumObjects - the number of poolallocs for this pool.
   unsigned NumObjects;
 





More information about the llvm-commits mailing list