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

Chris Lattner lattner at cs.uiuc.edu
Sun Oct 26 17:10:02 PST 2003


Changes in directory poolalloc/runtime/PoolAllocator:

PoolAllocator.h updated: 1.2 -> 1.3
PoolAllocatorChained.cpp updated: 1.14 -> 1.15

---
Log message:

Continue refactoring code.  Now it is more object oriented, and actually
understandable!


---
Diffs of the changes:  (+111 -103)

Index: poolalloc/runtime/PoolAllocator/PoolAllocator.h
diff -u poolalloc/runtime/PoolAllocator/PoolAllocator.h:1.2 poolalloc/runtime/PoolAllocator/PoolAllocator.h:1.3
--- poolalloc/runtime/PoolAllocator/PoolAllocator.h:1.2	Fri Oct 24 14:56:44 2003
+++ poolalloc/runtime/PoolAllocator/PoolAllocator.h	Sun Oct 26 17:09:40 2003
@@ -33,7 +33,7 @@
   void poolmakeunfreeable(PoolTy *Pool);
   void pooldestroy(PoolTy *Pool);
   void *poolalloc(PoolTy *Pool);
-  void poolfree(PoolTy *Pool, char *Node);
+  void poolfree(PoolTy *Pool, void *Node);
   void* poolallocarray(PoolTy* Pool, unsigned Size);
 }
 


Index: poolalloc/runtime/PoolAllocator/PoolAllocatorChained.cpp
diff -u poolalloc/runtime/PoolAllocator/PoolAllocatorChained.cpp:1.14 poolalloc/runtime/PoolAllocator/PoolAllocatorChained.cpp:1.15
--- poolalloc/runtime/PoolAllocator/PoolAllocatorChained.cpp:1.14	Sun Oct 26 16:32:58 2003
+++ poolalloc/runtime/PoolAllocator/PoolAllocatorChained.cpp	Sun Oct 26 17:09:40 2003
@@ -40,7 +40,9 @@
   PoolSlab *Next;
   unsigned isSingleArray;   // If this slab is used for exactly one array
 
-  unsigned short FirstUnused;     // First empty node in slab
+private:
+  // FirstUnused - First empty node in slab
+  unsigned short FirstUnused;
 
   // UsedEnd - 1 past the last allocated node in slab. 0 if slab is empty
   unsigned short UsedEnd;
@@ -67,7 +69,6 @@
     StartOfAllocation[NodeNum >> 3] |= 1 << (NodeNum & 7);
   }
 
-private:
   bool isStartOfAllocation(unsigned NodeNum) {
     return StartOfAllocation[NodeNum >> 3] & (1 << (NodeNum & 7));
   }
@@ -84,6 +85,10 @@
   // create - Create a new (empty) slab and add it to the end of the Pools list.
   static PoolSlab *create(PoolTy *Pool);
 
+  // createSingleArray - Create a slab for a large singlearray with NumNodes
+  // entries in it, returning the pointer into the pool directly.
+  static void *createSingleArray(PoolTy *Pool, unsigned NumNodes);
+
   // destroy - Release the memory for the current object.
   void destroy() {
     free(this);
@@ -97,6 +102,10 @@
   // there is no space.
   int allocateSingle();
 
+  // allocateMultiple - Allocate multiple contiguous elements from this pool,
+  // returning -1 if there is no space.
+  int allocateMultiple(unsigned Num);
+
   // getElementAddress - Return the address of the specified element.
   void *getElementAddress(unsigned ElementNum, unsigned ElementSize) {
     return &Data[ElementNum*ElementSize];
@@ -127,6 +136,21 @@
   return PS;
 }
 
+void *PoolSlab::createSingleArray(PoolTy *Pool, unsigned NumNodes) {
+  PoolSlab *PS = (PoolSlab*)malloc(sizeof(PoolSlab) +
+                                   Pool->NodeSize*NumNodes-1);
+  assert(PS && "poolalloc: Could not allocate memory!");
+
+  PS->isSingleArray = 1;  // Not a single array!
+  PS->markNodeAllocated(0);
+
+  // Add the slab to the list...
+  PS->Next = (PoolSlab*)Pool->Slabs;
+  Pool->Slabs = PS;
+  return &PS->Data[0];
+}
+
+
 // allocateSingle - Allocate a single element from this pool, returning -1 if
 // there is no space.
 int PoolSlab::allocateSingle() {
@@ -159,9 +183,10 @@
     setStartBit(Idx);
     
     // Increment FirstUnused to point to the new first unused value...
+    // FIXME: this should be optimized
     do {
       ++FirstUnused;
-    } while (FirstUnused < NodesPerSlab && isNodeAllocated(FirstUnused));
+    } while (FirstUnused != NodesPerSlab && isNodeAllocated(FirstUnused));
     
     return Idx;
   }
@@ -169,6 +194,72 @@
   return -1;
 }
 
+// allocateMultiple - Allocate multiple contiguous elements from this pool,
+// returning -1 if there is no space.
+int PoolSlab::allocateMultiple(unsigned Size) {
+  // Do not allocate small arrays in SingleArray slabs
+  if (isSingleArray) return -1;
+
+  // For small array allocation, check to see if there are empty entries at the
+  // end of the slab...
+  if (UsedEnd+Size <= NodesPerSlab) {
+    // Mark the returned entry used and set the start bit
+    setStartBit(UsedEnd);
+    for (unsigned i = UsedEnd; i != UsedEnd + Size; ++i)
+      markNodeAllocated(i);
+    
+    // If we are allocating out the first unused field, bump its index also
+    if (FirstUnused == UsedEnd)
+      FirstUnused += Size;
+
+    // Increment UsedEnd
+    UsedEnd += Size;
+
+    // Return the entry
+    return UsedEnd - Size;
+  }
+
+  // If not, check to see if this node has a declared "FirstUnused" value
+  // starting which Size nodes can be allocated
+  //
+  unsigned Idx = FirstUnused;
+  while (Idx+Size <= NodesPerSlab) {
+    assert(!isNodeAllocated(Idx) && "FirstUsed is not accurate!");
+
+    // Check if there is a continuous array of Size nodes starting FirstUnused
+    unsigned LastUnused = Idx+1;
+    for (; LastUnused != Idx+Size && !isNodeAllocated(LastUnused); ++LastUnused)
+      /*empty*/;
+
+    // If we found an unused section of this pool which is large enough, USE IT!
+    if (LastUnused == Idx+Size) {
+      setStartBit(Idx);
+      // FIXME: this loop can be made more efficient!
+      for (unsigned i = Idx; i != Idx + Size; ++i)
+        markNodeAllocated(i);
+
+      // This should not be allocating on the end of the pool, so we don't need
+      // to bump the UsedEnd pointer.
+      assert(Idx != UsedEnd && "Shouldn't allocate at end of pool!");
+
+      // If we are allocating out the first unused field, bump its index also.
+      if (Idx == FirstUnused)
+        FirstUnused += Size;
+      
+      // Return the entry
+      return Idx;
+    }
+
+    // Otherwise, try later in the pool.  Find the next unused entry.
+    Idx = LastUnused;
+    while (Idx+Size <= NodesPerSlab && isNodeAllocated(Idx))
+      ++Idx;
+  }
+
+  return -1;
+}
+
+
 // containsElement - Return the element number of the specified address in
 // this slab.  If the address is not in slab, return -1.
 int PoolSlab::containsElement(void *Ptr, unsigned ElementSize) const {
@@ -194,7 +285,7 @@
 
   // If this slab is a SingleArray, there is nothing else to do.
   if (isSingleArray) {
-    UsedEnd = 0;               // This slab is now empty
+    FirstUnused = UsedEnd = 0;               // This slab is now empty
     assert(ElementIdx == 0 &&
            "poolfree: Attempt to free middle of allocated array\n");
     return;
@@ -213,7 +304,7 @@
 
   // FIXME: This should use manual strength reduction if GCC isn't producing
   // decent code (which is almost certainly isn't).
-  while (ElementEndIdx < UsedEnd && !isStartOfAllocation(ElementEndIdx) && 
+  while (ElementEndIdx != UsedEnd && !isStartOfAllocation(ElementEndIdx) && 
          isNodeAllocated(ElementEndIdx)) {
     markNodeFree(ElementEndIdx);
     ++ElementEndIdx;
@@ -360,106 +451,23 @@
   }
 }
 
-// The poolallocarray version of FindSlabEntry
-static void *FindSlabEntryArray(PoolSlab *PS, unsigned NodeSize, unsigned Size){
-  if (Size > PoolSlab::NodesPerSlab) return 0;
-
-  // Loop through all of the slabs looking for one with an opening
-  for (; PS; PS = PS->Next) {
-    if (PS->isSingleArray)
-      continue; // Do not allocate small arrays in SingleArray slabs
-
-    // For small array allocation, check to see if there are empty entries at
-    // the end of the slab...
-    if (PS->UsedEnd-1 < PoolSlab::NodesPerSlab-Size) {
-      // Mark the returned entry used and set the start bit
-      PS->setStartBit(PS->UsedEnd);
-      for (unsigned i = PS->UsedEnd; i < PS->UsedEnd + Size; ++i)
-	PS->markNodeAllocated(i);
-
-      // If we are allocating out the first unused field, bump its index also
-      if (PS->FirstUnused == PS->UsedEnd)
-        PS->FirstUnused += Size;
-
-      // Increment UsedEnd
-      PS->UsedEnd += Size;
-
-      // Return the entry
-      return &PS->Data[0] + (PS->UsedEnd - Size) * NodeSize;
-    }
-
-    // If not, check to see if this node has a declared "FirstUnused" value
-    // starting which Size nodes can be allocated
-    //
-    if (PS->FirstUnused < PoolSlab::NodesPerSlab - Size + 1 &&
-	(PS->UsedEnd < PS->FirstUnused+1 || 
-	 PS->UsedEnd - PS->FirstUnused >= Size+1)) {
-      unsigned Idx = PS->FirstUnused, foundArray;
-      
-      // Check if there is a continuous array of Size nodes starting FirstUnused
-      foundArray = 1;
-      for (unsigned i = Idx; (i < Idx + Size) && foundArray; ++i)
-	if (PS->isNodeAllocated(i))
-	  foundArray = 0;
-
-      if (foundArray) {
-	// Successfully allocate starting from the first unused node
-	PS->setStartBit(Idx);
-	for (unsigned i = Idx; i < Idx + Size; ++i)
-	  PS->markNodeAllocated(i);
-	
-	PS->FirstUnused += Size;
-	while (PS->FirstUnused < PoolSlab::NodesPerSlab &&
-               PS->isNodeAllocated(PS->FirstUnused)) {
-	  ++PS->FirstUnused;
-	}
-	return &PS->Data[0] + Idx*NodeSize;
-      }
-      
-    }
-  }
-
-  // No empty nodes available, must grow # slabs!
-  return 0;
-}
-
-void* poolallocarray(PoolTy* Pool, unsigned Size) {
+void *poolallocarray(PoolTy* Pool, unsigned Size) {
   assert(Pool && "Null pool pointer passed into poolallocarray!\n");
 
-  unsigned NodeSize = Pool->NodeSize;
-
-  // Return if this pool has size 0
-  if (NodeSize == 0)
-    return 0;
+  if (Size > PoolSlab::NodesPerSlab)
+    return PoolSlab::createSingleArray(Pool, Size);    
 
+  // Loop through all of the slabs looking for one with an opening
   PoolSlab *PS = (PoolSlab*)Pool->Slabs;
-  if (void *Result = FindSlabEntryArray(PS, NodeSize,Size))
-    return Result;
-
-  // Otherwise we must allocate a new slab and add it to the list
-  if (Size > PoolSlab::NodesPerSlab) {
-    // Allocate a new slab of size Size
-    PS = (PoolSlab*)malloc(sizeof(PoolSlab)+NodeSize*Size-1);
-    assert(PS && "poolallocarray: Could not allocate memory!\n");
-    PS->isSingleArray = 1;
-    PS->markNodeAllocated(0);
-  } else {
-    PS = (PoolSlab*)malloc(sizeof(PoolSlab)+NodeSize*PoolSlab::NodesPerSlab-1);
-    assert(PS && "poolallocarray: Could not allocate memory!\n");
-
-    // Initialize the slab to indicate that the first element is allocated
-    PS->FirstUnused = Size;
-    PS->UsedEnd = Size;
-    
-    PS->isSingleArray = 0;
-
-    PS->setStartBit(0);
-    for (unsigned i = 0; i != Size; ++i)
-      PS->markNodeAllocated(i);
+  for (; PS; PS = PS->Next) {
+    int Element = PS->allocateMultiple(Size);
+    if (Element != -1)
+      return PS->getElementAddress(Element, Pool->NodeSize);
+    PS = PS->Next;
   }
-
-  // Add the slab to the list...
-  PS->Next = (PoolSlab*)Pool->Slabs;
-  Pool->Slabs = PS;
-  return &PS->Data[0];
+  
+  PoolSlab *New = PoolSlab::create(Pool);
+  int Idx = New->allocateMultiple(Size);
+  assert(Idx == 0 && "New allocation didn't return zero'th node?");
+  return New->getElementAddress(0, 0);
 }





More information about the llvm-commits mailing list