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

Chris Lattner lattner at cs.uiuc.edu
Sat Nov 8 01:23:02 PST 2003


Changes in directory poolalloc/runtime/PoolAllocator:

PoolAllocatorBitMask.cpp updated: 1.26 -> 1.27

---
Log message:

Make deletes much more efficient through the use of an extra data member, which
speeds up FIFO usage patterns, and by optimizing the scanning case.


---
Diffs of the changes:  (+56 -13)

Index: poolalloc/runtime/PoolAllocator/PoolAllocatorBitMask.cpp
diff -u poolalloc/runtime/PoolAllocator/PoolAllocatorBitMask.cpp:1.26 poolalloc/runtime/PoolAllocator/PoolAllocatorBitMask.cpp:1.27
--- poolalloc/runtime/PoolAllocator/PoolAllocatorBitMask.cpp:1.26	Fri Nov  7 23:24:56 2003
+++ poolalloc/runtime/PoolAllocator/PoolAllocatorBitMask.cpp	Sat Nov  8 01:22:19 2003
@@ -44,6 +44,9 @@
   // FirstUnused - First empty node in slab
   unsigned short FirstUnused;
 
+  // UsedBegin - The first node in the slab that is used.
+  unsigned short UsedBegin;
+
   // UsedEnd - 1 past the last allocated node in slab. 0 if slab is empty
   unsigned short UsedEnd;
 
@@ -172,12 +175,13 @@
 
   unsigned Size = sizeof(PoolSlab) + 4*((NodesPerSlab+15)/16) +
                   Pool->NodeSize*getSlabSize(Pool);
-  assert(Size < PageSize && "Trying to allocate a slab larger than a page!");
+  assert(Size <= PageSize && "Trying to allocate a slab larger than a page!");
   PoolSlab *PS = (PoolSlab*)AllocatePage();
 
   PS->NumNodesInSlab = NodesPerSlab;
   PS->isSingleArray = 0;  // Not a single array!
   PS->FirstUnused = 0;    // Nothing allocated.
+  PS->UsedBegin   = 0;    // Nothing allocated.
   PS->UsedEnd     = 0;    // Nothing allocated.
 
   // Add the slab to the list...
@@ -378,13 +382,35 @@
   
   // Update the first free field if this node is below the free node line
   if (ElementIdx < FirstUnused) FirstUnused = ElementIdx;
+
+  // Update the first used field if this node was the first used.
+  if (ElementIdx == UsedBegin) UsedBegin = ElementEndIdx;
   
   // If we are freeing the last element in a slab, shrink the UsedEnd marker
   // down to the last used node.
   if (ElementEndIdx == UE) {
-    UsedEnd = lastNodeAllocated(ElementIdx);
-    assert(FirstUnused <= UsedEnd &&
-           "FirstUnused field was out of date!");
+#if 0
+      printf("FU: %d, UB: %d, UE: %d  FREED: [%d-%d)",
+           FirstUnused, UsedBegin, UsedEnd, ElementIdx, ElementEndIdx);
+#endif
+
+    // If the user is freeing the slab entirely in-order, it's quite possible
+    // that all nodes are free in the slab.  If this is the case, simply reset
+    // our pointers.
+    if (UsedBegin == UE) {
+      //printf(": SLAB EMPTY\n");
+      FirstUnused = 0;
+      UsedBegin = 0;
+      UsedEnd = 0;
+    } else if (FirstUnused == ElementIdx) {
+      // Freed the last node(s) in this slab.
+      FirstUnused = ElementIdx;
+      UsedEnd = ElementIdx;
+    } else {
+      UsedEnd = lastNodeAllocated(ElementIdx);
+      assert(FirstUnused <= UsedEnd &&
+             "FirstUnused field was out of date!");
+    }
   }
 }
 
@@ -394,32 +420,49 @@
   unsigned short Flags = NodeFlagsVector[CurWord] & 0xFFFF;
   if (Flags) {
     // Mask off nodes above this one
-    Flags &= (1 << (ScanIdx & 15))-1;
+    Flags &= (1 << ((ScanIdx & 15)+1))-1;
     if (Flags) {
       // If there is still something in the flags vector, then there is a node
       // allocated in this part.  The goto is a hack to get the uncommonly
       // executed code away from the common code path.
+      //printf("A: ");
       goto ContainsAllocatedNode;
     }
   }
 
   // Ok, the top word doesn't contain anything, scan the whole flag words now.
-  ScanIdx &= ~15;
   --CurWord;
   while (CurWord != ~0U) {
-    if (NodeFlagsVector[CurWord] & 0xFFFF)
+    Flags = NodeFlagsVector[CurWord] & 0xFFFF;
+    if (Flags) {
+      // There must be a node allocated in this word!
+      //printf("B: ");
       goto ContainsAllocatedNode;
+    }
     CurWord--;
-    ScanIdx -= 16;
   }
   return 0;
 
 ContainsAllocatedNode:
-  // Figure out exactly which node is allocated in this word now.
-  // FIXME: this could be made to be more efficient!
-  do {
-    --ScanIdx;
-  } while (ScanIdx && !isNodeAllocated(ScanIdx-1));
+  // Figure out exactly which node is allocated in this word now.  The node
+  // allocated is the one with the highest bit set in 'Flags'.
+  //
+  // This should use __builtin_clz to get the value, but this builtin is only
+  // available with GCC 3.4 and above.  :(
+  assert(Flags && "Should have allocated node!");
+  
+  unsigned short MSB;
+#if GCC3_4_EVENTUALLY
+  MSB = 16 - ::__builtin_clz(Flags);
+#else
+  for (MSB = 15; (Flags & (1U << MSB)) == 0; --MSB)
+    /*empty*/;
+#endif
+
+  assert((1U << MSB) & Flags);   // The bit should be set
+  assert((~(1U << MSB) & Flags) < Flags);// Removing it should make flag smaller
+  ScanIdx = CurWord*16 + MSB;
+  assert(isNodeAllocated(ScanIdx));
   return ScanIdx;
 }
 





More information about the llvm-commits mailing list