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

Dinakar Dhurjati dhurjati at cs.uiuc.edu
Thu Dec 22 08:50:36 PST 2005



Changes in directory llvm-poolalloc/runtime/SafePoolAllocator:

PoolAllocatorBitMask.cpp added (r1.1)
---
Log message:

*** empty log message ***

---
Diffs of the changes:  (+1220 -0)

 PoolAllocatorBitMask.cpp | 1220 +++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 1220 insertions(+)


Index: llvm-poolalloc/runtime/SafePoolAllocator/PoolAllocatorBitMask.cpp
diff -c /dev/null llvm-poolalloc/runtime/SafePoolAllocator/PoolAllocatorBitMask.cpp:1.1
*** /dev/null	Thu Dec 22 10:50:34 2005
--- llvm-poolalloc/runtime/SafePoolAllocator/PoolAllocatorBitMask.cpp	Thu Dec 22 10:50:24 2005
***************
*** 0 ****
--- 1,1220 ----
+ //===- PoolAllocatorBitMask.cpp - Implementation of poolallocator runtime -===//
+ // 
+ //                       The LLVM Compiler Infrastructure
+ //
+ // This file was developed by the LLVM research group and is distributed under
+ // the University of Illinois Open Source License. See LICENSE.TXT for details.
+ // 
+ //===----------------------------------------------------------------------===//
+ //
+ // This file is one possible implementation of the LLVM pool allocator runtime
+ // library.
+ //
+ // This uses the 'Ptr1' field to maintain a linked list of slabs that are either
+ // empty or are partially allocated from.  The 'Ptr2' field of the PoolTy is
+ // used to track a linked list of slabs which are full, ie, all elements have
+ // been allocated from them.
+ //
+ //===----------------------------------------------------------------------===//
+ 
+ #include "PoolAllocator.h"
+ #include "PageManager.h"
+ #include <assert.h>
+ #include <stdlib.h>
+ #include <stdio.h>
+ #include <unistd.h>
+ #define DEBUG(x) 
+ //===----------------------------------------------------------------------===//
+ //
+ //  PoolSlab implementation
+ //
+ //===----------------------------------------------------------------------===//
+ 
+ 
+ // PoolSlab Structure - Hold multiple objects of the current node type.
+ // Invariants: FirstUnused <= UsedEnd
+ //
+ struct PoolSlab {
+   PoolSlab **PrevPtr, *Next;
+   bool isSingleArray;   // If this slab is used for exactly one array
+ 
+ private:
+   // 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;
+ 
+   // NumNodesInSlab - This contains the number of nodes in this slab, which
+   // effects the size of the NodeFlags vector, and indicates the number of nodes
+   // which are in the slab.
+   unsigned int NumNodesInSlab;
+ 
+   // NodeFlagsVector - This array contains two bits for each node in this pool
+   // slab.  The first (low address) bit indicates whether this node has been
+   // allocated, and the second (next higher) bit indicates whether this is the
+   // start of an allocation.
+   //
+   // This is a variable sized array, which has 2*NumNodesInSlab bits (rounded up
+   // to 4 bytes).
+   unsigned NodeFlagsVector[];
+   
+   bool isNodeAllocated(unsigned NodeNum) {
+     return NodeFlagsVector[NodeNum/16] & (1 << (NodeNum & 15));
+   }
+ 
+   void markNodeAllocated(unsigned NodeNum) {
+     NodeFlagsVector[NodeNum/16] |= 1 << (NodeNum & 15);
+   }
+ 
+   void markNodeFree(unsigned NodeNum) {
+     NodeFlagsVector[NodeNum/16] &= ~(1 << (NodeNum & 15));
+   }
+ 
+   void setStartBit(unsigned NodeNum) {
+     NodeFlagsVector[NodeNum/16] |= 1 << ((NodeNum & 15)+16);
+   }
+ 
+   bool isStartOfAllocation(unsigned NodeNum) {
+     return NodeFlagsVector[NodeNum/16] & (1 << ((NodeNum & 15)+16));
+   }
+   
+   void clearStartBit(unsigned NodeNum) {
+     NodeFlagsVector[NodeNum/16] &= ~(1 << ((NodeNum & 15)+16));
+   }
+ 
+ public:
+   // 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);
+ 
+   // getSlabSize - Return the number of nodes that each slab should contain.
+   static unsigned getSlabSize(PoolTy *Pool) {
+     // We need space for the header...
+     unsigned NumNodes = PageSize-sizeof(PoolSlab);
+     
+     // We need space for the NodeFlags...
+     unsigned NodeFlagsBytes = NumNodes/Pool->NodeSize * 2 / 8;
+     NumNodes -= (NodeFlagsBytes+3) & ~3;  // Round up to int boundaries.
+ 
+     // Divide the remainder among the nodes!
+     return NumNodes / Pool->NodeSize;
+   }
+ 
+   void addToList(PoolSlab **PrevPtrPtr) {
+     PoolSlab *InsertBefore = *PrevPtrPtr;
+     *PrevPtrPtr = this;
+     PrevPtr = PrevPtrPtr;
+     Next = InsertBefore;
+     if (InsertBefore) InsertBefore->PrevPtr = &Next;
+   }
+ 
+   void unlinkFromList() {
+     *PrevPtr = Next;
+     if (Next) Next->PrevPtr = PrevPtr;
+   }
+ 
+   unsigned getSlabSize() const {
+     return NumNodesInSlab;
+   }
+ 
+   // destroy - Release the memory for the current object.
+   void destroy();
+ 
+   // isEmpty - This is a quick check to see if this slab is completely empty or
+   // not.
+   bool isEmpty() const { return UsedEnd == 0; }
+ 
+   // isFull - This is a quick check to see if the slab is completely allocated.
+   //
+   bool isFull() const { return isSingleArray || FirstUnused == getSlabSize(); }
+ 
+   // allocateSingle - Allocate a single element from this pool, returning -1 if
+   // 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) {
+     char *Data = (char*)&NodeFlagsVector[((unsigned)NumNodesInSlab+15)/16];
+     return &Data[ElementNum*ElementSize];
+   }
+   const void *getElementAddress(unsigned ElementNum, unsigned ElementSize)const{
+     const char *Data =
+       (const char *)&NodeFlagsVector[(unsigned)(NumNodesInSlab+15)/16];
+     return &Data[ElementNum*ElementSize];
+   }
+ 
+   // containsElement - Return the element number of the specified address in
+   // this slab.  If the address is not in slab, return -1.
+   int containsElement(void *Ptr, unsigned ElementSize) const;
+ 
+   // freeElement - Free the single node, small array, or entire array indicated.
+   void freeElement(unsigned short ElementIdx);
+   
+   // lastNodeAllocated - Return one past the last node in the pool which is
+   // before ScanIdx, that is allocated.  If there are no allocated nodes in this
+   // slab before ScanIdx, return 0.
+   unsigned lastNodeAllocated(unsigned ScanIdx);
+ };
+ 
+ // create - Create a new (empty) slab and add it to the end of the Pools list.
+ PoolSlab *PoolSlab::create(PoolTy *Pool) {
+   unsigned NodesPerSlab = getSlabSize(Pool);
+ 
+   unsigned Size = sizeof(PoolSlab) + 4*((NodesPerSlab+15)/16) +
+     Pool->NodeSize*getSlabSize(Pool);
+   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...
+   PS->addToList((PoolSlab**)&Pool->Ptr1);
+   //  printf(" creating a slab %x\n", PS);
+   return PS;
+ }
+ 
+ void *PoolSlab::createSingleArray(PoolTy *Pool, unsigned NumNodes) {
+   // FIXME: This wastes memory by allocating space for the NodeFlagsVector
+   unsigned NodesPerSlab = getSlabSize(Pool);
+   assert(NumNodes > NodesPerSlab && "No need to create a single array!");
+ 
+   unsigned NumPages = (NumNodes+NodesPerSlab-1)/NodesPerSlab;
+   PoolSlab *PS = (PoolSlab*)AllocateNPages(NumPages);
+ 
+   assert(PS && "poolalloc: Could not allocate memory!");
+ 
+   if (Pool->NumSlabs > AddrArrSize)
+     Pool->Slabs->insert((void*)PS);
+   else if (Pool->NumSlabs == AddrArrSize) {
+     // Create the hash_set
+     Pool->Slabs = new hash_set<void *>;
+     Pool->Slabs->insert((void *)PS);
+     for (unsigned i = 0; i < AddrArrSize; ++i)
+       Pool->Slabs->insert((void *) Pool->SlabAddressArray[i]);
+   } else {
+     // Insert it in the array
+     Pool->SlabAddressArray[Pool->NumSlabs] = (unsigned) PS;
+   }
+   Pool->NumSlabs++;
+   
+   PS->addToList((PoolSlab**)&Pool->LargeArrays);
+ 
+   PS->isSingleArray = 1;
+   PS->NumNodesInSlab = NumPages * PageSize;
+   *(unsigned*)&PS->FirstUnused = NumPages;
+   return PS->getElementAddress(0, 0);
+ }
+ 
+ void PoolSlab::destroy() {
+   if (isSingleArray)
+     for (unsigned NumPages = *(unsigned*)&FirstUnused; NumPages != 1;--NumPages)
+       FreePage((char*)this + (NumPages-1)*PageSize);
+ 
+   FreePage(this);
+ }
+ 
+ // allocateSingle - Allocate a single element from this pool, returning -1 if
+ // there is no space.
+ int PoolSlab::allocateSingle() {
+   // If the slab is a single array, go on to the next slab.  Don't allocate
+   // single nodes in a SingleArray slab.
+   if (isSingleArray) return -1;
+ 
+   unsigned SlabSize = getSlabSize();
+ 
+   // Check to see if there are empty entries at the end of the slab...
+   if (UsedEnd < SlabSize) {
+     // Mark the returned entry used
+     unsigned short UE = UsedEnd;
+     markNodeAllocated(UE);
+     setStartBit(UE);
+     
+     // If we are allocating out the first unused field, bump its index also
+     if (FirstUnused == UE)
+       FirstUnused++;
+     
+     // Return the entry, increment UsedEnd field.
+     return UsedEnd++;
+   }
+   
+   // If not, check to see if this node has a declared "FirstUnused" value that
+   // is less than the number of nodes allocated...
+   //
+   if (FirstUnused < SlabSize) {
+     // Successfully allocate out the first unused node
+     unsigned Idx = FirstUnused;
+     markNodeAllocated(Idx);
+     setStartBit(Idx);
+     
+     // Increment FirstUnused to point to the new first unused value...
+     // FIXME: this should be optimized
+     unsigned short FU = FirstUnused;
+     do {
+       ++FU;
+     } while (FU != SlabSize && isNodeAllocated(FU));
+     FirstUnused = FU;
+     
+     return Idx;
+   }
+   
+   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 <= getSlabSize()) {
+     // Mark the returned entry used and set the start bit
+     unsigned UE = UsedEnd;
+     setStartBit(UE);
+     for (unsigned i = UE; i != UE+Size; ++i)
+       markNodeAllocated(i);
+     
+     // If we are allocating out the first unused field, bump its index also
+     if (FirstUnused == UE)
+       FirstUnused += Size;
+ 
+     // Increment UsedEnd
+     UsedEnd += Size;
+ 
+     // Return the entry
+     return UE;
+   }
+ 
+   // 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 <= getSlabSize()) {
+     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 <= getSlabSize() && 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 {
+   const void *FirstElement = getElementAddress(0, 0);
+   if (FirstElement <= Ptr) {
+     unsigned Delta = (char*)Ptr-(char*)FirstElement;
+     if (isSingleArray) 
+       if (Delta < NumNodesInSlab) return Delta/ElementSize;
+     unsigned Index = Delta/ElementSize;
+     if (Index < getSlabSize()) {
+       if (Delta % ElementSize != 0) {
+ 	printf("Freeing pointer into the middle of an element!");
+ 	abort();
+       }
+       
+       return Index;
+     }
+   }
+   return -1;
+ }
+ 
+ 
+ // freeElement - Free the single node, small array, or entire array indicated.
+ void PoolSlab::freeElement(unsigned short ElementIdx) {
+   if (!isNodeAllocated(ElementIdx)) return;
+   //  assert(isNodeAllocated(ElementIdx) &&
+   //         "poolfree: Attempt to free node that is already freed\n");
+   assert(!isSingleArray && "Cannot free an element from a single array!");
+ 
+   // Mark this element as being free!
+   markNodeFree(ElementIdx);
+ 
+   // If this slab is not a SingleArray
+   assert(isStartOfAllocation(ElementIdx) &&
+          "poolfree: Attempt to free middle of allocated array\n");
+   
+   // Free the first cell
+   clearStartBit(ElementIdx);
+   markNodeFree(ElementIdx);
+   
+   // Free all nodes if this was a small array allocation.
+   unsigned short ElementEndIdx = ElementIdx + 1;
+ 
+   // FIXME: This should use manual strength reduction to produce decent code.
+   unsigned short UE = UsedEnd;
+   while (ElementEndIdx != UE &&
+          !isStartOfAllocation(ElementEndIdx) && 
+          isNodeAllocated(ElementEndIdx)) {
+     markNodeFree(ElementEndIdx);
+     ++ElementEndIdx;
+   }
+   
+   // 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) {
+ #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+1 &&
+              "FirstUnused field was out of date!");
+     }
+   }
+ }
+ 
+ unsigned PoolSlab::lastNodeAllocated(unsigned ScanIdx) {
+   // Check the last few nodes in the current word of flags...
+   unsigned CurWord = ScanIdx/16;
+   unsigned short Flags = NodeFlagsVector[CurWord] & 0xFFFF;
+   if (Flags) {
+     // Mask off nodes above this one
+     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.
+   --CurWord;
+   while (CurWord != ~0U) {
+     Flags = NodeFlagsVector[CurWord] & 0xFFFF;
+     if (Flags) {
+       // There must be a node allocated in this word!
+       //printf("B: ");
+       goto ContainsAllocatedNode;
+     }
+     CurWord--;
+   }
+   return 0;
+ 
+ ContainsAllocatedNode:
+   // 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;
+ }
+ 
+ 
+ //===----------------------------------------------------------------------===//
+ //
+ //  Pool allocator library implementation
+ //
+ //===----------------------------------------------------------------------===//
+ 
+ // poolinit - Initialize a pool descriptor to empty
+ //
+ void poolinit(PoolTy *Pool, unsigned NodeSize) {
+   assert(Pool && "Null pool pointer passed into poolinit!\n");
+   DEBUG(printf("pool init %x, %d\n", Pool, NodeSize);)
+ 
+   // Ensure the page manager is initialized
+   InitializePageManager();
+ 
+   // We must alway return unique pointers, even if they asked for 0 bytes
+   Pool->NodeSize = NodeSize ? NodeSize : 1;
+   Pool->Ptr1 = Pool->Ptr2 = 0;
+   Pool->LargeArrays = 0;
+   // For SAFECode, we set FreeablePool to 0 always
+   //  Pool->FreeablePool = 0;
+   Pool->AllocadPool = -1;
+   Pool->lastUsed = 0;
+   Pool->prevPage[0] = 0;
+   Pool->prevPage[1] = 0;
+   // Initialize the SlabAddressArray to zero
+   for (int i = 0; i < AddrArrSize; ++i) {
+     Pool->SlabAddressArray[i] = 0;
+   }
+ 
+   Pool->NumSlabs = 0;
+ 
+   ///  Pool->Slabs = new hash_set<void*>;
+   // Call hash_set constructor explicitly
+   //   void *SlabPtr = &Pool->Slabs;
+   //   new (SlabPtr) hash_set<void*>;
+ }
+ 
+ void poolmakeunfreeable(PoolTy *Pool) {
+   assert(Pool && "Null pool pointer passed in to poolmakeunfreeable!\n");
+   //  Pool->FreeablePool = 0;
+ }
+ 
+ // pooldestroy - Release all memory allocated for a pool
+ //
+ void pooldestroy(PoolTy *Pool) {
+   assert(Pool && "Null pool pointer passed in to pooldestroy!\n");
+   if (Pool->AllocadPool) return;
+   
+   if (Pool->NumSlabs > AddrArrSize) {
+     Pool->Slabs->clear();
+     delete Pool->Slabs;
+   }
+ 
+   // Free any partially allocated slabs
+   PoolSlab *PS = (PoolSlab*)Pool->Ptr1;
+   while (PS) {
+     PoolSlab *Next = PS->Next;
+     PS->destroy();
+     PS = Next;
+   }
+ 
+   // Free the completely allocated slabs
+   PS = (PoolSlab*)Pool->Ptr2;
+   while (PS) {
+     PoolSlab *Next = PS->Next;
+     PS->destroy();
+     PS = Next;
+   }
+ 
+   // Free the large arrays
+   PS = (PoolSlab*)Pool->LargeArrays;
+   while (PS) {
+     PoolSlab *Next = PS->Next;
+     PS->destroy();
+     PS = Next;
+   }
+ 
+ }
+ 
+ 
+ // poolallocarray - a helper function used to implement poolalloc, when the
+ // number of nodes to allocate is not 1.
+ static void *poolallocarray(PoolTy* Pool, unsigned Size) {
+   assert(Pool && "Null pool pointer passed into poolallocarray!\n");
+   if (Size > PoolSlab::getSlabSize(Pool))
+     return PoolSlab::createSingleArray(Pool, Size);
+  
+   PoolSlab *PS = (PoolSlab*)Pool->Ptr1;
+ 
+   // Loop through all of the slabs looking for one with an opening
+   for (; PS; PS = PS->Next) {
+     int Element = PS->allocateMultiple(Size);
+     if (Element != -1) {
+       // We allocated an element.  Check to see if this slab has been completely
+       // filled up.  If so, move it to the Ptr2 list.
+       if (PS->isFull()) {
+         PS->unlinkFromList();
+         PS->addToList((PoolSlab**)&Pool->Ptr2);
+       }
+       return PS->getElementAddress(Element, Pool->NodeSize);
+     }
+   }
+   
+   PoolSlab *New = PoolSlab::create(Pool);
+   //  printf("new slab created %x \n", New);
+   if (Pool->NumSlabs > AddrArrSize)
+     Pool->Slabs->insert((void *)New);
+   else if (Pool->NumSlabs == AddrArrSize) {
+     // Create the hash_set
+     Pool->Slabs = new hash_set<void *>;
+     Pool->Slabs->insert((void *)New);
+     for (unsigned i = 0; i < AddrArrSize; ++i)
+       Pool->Slabs->insert((void *)Pool->SlabAddressArray[i]);
+   } else {
+     // Insert it in the array
+     Pool->SlabAddressArray[Pool->NumSlabs] = (unsigned) New;
+   }
+   Pool->NumSlabs++;
+   
+   int Idx = New->allocateMultiple(Size);
+   assert(Idx == 0 && "New allocation didn't return zero'th node?");
+   return New->getElementAddress(0, 0);
+ }
+ 
+ void poolregister(PoolTy *Pool, unsigned NumBytes, void * allocaptr) {
+   if (!Pool) {
+     abort();
+     printf("Null pool pointer passed in to poolalloc!\n");
+     exit(-1);
+   } 
+   if (Pool->AllocadPool != -1) {
+     if (Pool->AllocadPool == 0) {
+       printf(" Handle this case later\n");
+       exit(-1);
+     } else {
+       printf(" An allocad pool, you can only allocate once \n");
+       exit(-1);
+     }
+   } else {
+     Pool->AllocadPool = NumBytes;
+     Pool->allocaptr = allocaptr;
+   }
+ }
+ 
+ //Pool->AllocadPool -1 : unused so far
+ //Pool->AllocadPool 0 : used only for mallocs
+ //Pool->AllocadPool >0 : used for only allocas indicating the size 
+ void *poolalloc(PoolTy *Pool, unsigned NumBytes) {
+   void *retAddress = NULL;
+   if (!Pool) {
+     printf("Null pool pointer passed in to poolalloc!, FAILING\n");
+     exit(-1);
+   } 
+   if (Pool->AllocadPool != -1) {
+     if (Pool->AllocadPool != 0) {
+       printf(" Did not Handle this case, an alloa and malloc point to");
+       printf("same DSNode, Will happen in stack safety \n");
+       exit(-1);
+     }
+   } else {
+     Pool->AllocadPool = 0;
+   }
+ 
+   unsigned NodeSize = Pool->NodeSize;
+   unsigned NodesToAllocate = (NumBytes+NodeSize-1)/NodeSize;
+   if (NodesToAllocate > 1) {
+     retAddress = poolallocarray(Pool, NodesToAllocate);
+     return retAddress;
+   }
+ 
+   // Special case the most common situation, where a single node is being
+   // allocated.
+   PoolSlab *PS = (PoolSlab*)Pool->Ptr1;
+ 
+   if (__builtin_expect(PS != 0, 1)) {
+     int Element = PS->allocateSingle();
+     if (__builtin_expect(Element != -1, 1)) {
+       // We allocated an element.  Check to see if this slab has been
+       // completely filled up.  If so, move it to the Ptr2 list.
+       if (__builtin_expect(PS->isFull(), false)) {
+         PS->unlinkFromList();
+         PS->addToList((PoolSlab**)&Pool->Ptr2);
+       }
+       retAddress = PS->getElementAddress(Element, NodeSize);
+       // printf(" returning the address %x",retAddress);
+       return retAddress;
+     }
+ 
+     // Loop through all of the slabs looking for one with an opening
+     for (PS = PS->Next; PS; PS = PS->Next) {
+       int Element = PS->allocateSingle();
+       if (Element != -1) {
+         // We allocated an element.  Check to see if this slab has been
+         // completely filled up.  If so, move it to the Ptr2 list.
+         if (PS->isFull()) {
+           PS->unlinkFromList();
+           PS->addToList((PoolSlab**)&Pool->Ptr2);
+         }
+         
+ 	retAddress = PS->getElementAddress(Element, NodeSize);
+ 	//	printf(" returning the address %x",retAddress);
+ 	return retAddress;
+       }
+     }
+   }
+ 
+   // Otherwise we must allocate a new slab and add it to the list
+   PoolSlab *New = PoolSlab::create(Pool);
+   
+   if (Pool->NumSlabs > AddrArrSize)
+     Pool->Slabs->insert((void *)New);
+   else if (Pool->NumSlabs == AddrArrSize) {
+     // Create the hash_set
+     Pool->Slabs = new hash_set<void *>;
+     Pool->Slabs->insert((void *)New);
+     for (unsigned i = 0; i < AddrArrSize; ++i)
+       Pool->Slabs->insert((void *)Pool->SlabAddressArray[i]);
+   } else {
+     // Insert it in the array
+     Pool->SlabAddressArray[Pool->NumSlabs] = (unsigned) New;
+   }
+   Pool->NumSlabs++;
+ 
+   int Idx = New->allocateSingle();
+   assert(Idx == 0 && "New allocation didn't return zero'th node?");
+   retAddress = New->getElementAddress(0, 0);
+   //  printf(" returning the address %x",retAddress);
+   return retAddress;
+ }
+ 
+ /*
+ // SearchForContainingSlab - This implementation uses the hash_set as well
+ // as the array to search the list of allocated slabs for the node in question
+ static PoolSlab *SearchForContainingSlab(PoolTy *Pool, void *Node,
+                                          unsigned &TheIndex) {
+   //  printf("in pool check for pool %x, node %x\n",Pool,Node);
+   unsigned NodeSize = Pool->NodeSize;
+   void *PS;
+   if (!Pool) {
+     printf("Empty Pool in pool check FAILING \n");
+     exit(-1);
+   } 
+   assert (Pool->AllocadPool <= 0 && "SearchForContainingSlab not to be called"
+           " for alloca'ed pools");
+   
+   PS = (void*)((long)Node & ~(PageSize-1));
+   if (Pool->NumSlabs > AddrArrSize) {
+     hash_set<void*> &theSlabs = *Pool->Slabs;
+     if (theSlabs.find(PS) == theSlabs.end()) {
+       // Check the LargeArrays
+       if (Pool->LargeArrays) {
+ 	PoolSlab *PSlab = (PoolSlab*) Pool->LargeArrays;
+ 	unsigned Idx = -1;
+ 	while (PSlab) {
+ 	  assert(PSlab && "poolcheck: node being free'd not found in "
+ 		 "allocation pool specified!\n");
+ 	  Idx = PSlab->containsElement(Node, NodeSize);
+ 	  if (Idx != -1) break;
+ 	  PSlab = PSlab->Next;
+ 	}
+ 	if (Idx == -1) {
+ 	  printf("poolcheck: node being checked not found in pool \n");
+ 	  abort();
+ 	}
+ 	TheIndex = Idx;
+ 	return PSlab;
+       } else {
+ 	printf("poolcheck: node being checked not found in pool \n");
+ 	abort();
+       }
+     } else {
+       // Check that Node does not point to PoolSlab meta-data
+       if ((PoolSlab *)PS->getElementAddress(0,0) > (long) Node) {
+ 	printf("poolcheck: node being checked points to meta-data \n");
+ 	abort();
+       }	
+       TheIndex = PS->containsElement(Node, NodeSize);
+       return (PoolSlab *)PS;
+     }
+   } else {
+     bool found;
+     for (unsigned i = 0; i < AddrArrSize && !found; ++i) {
+       if (Pool->SlabAddressArray[i] == (unsigned) PS)
+ 	found = true;
+     } 
+ 
+     if (found) {
+       // Check that Node does not point to PoolSlab meta-data
+       if ((PoolSlab *)PS->getElementAddress(0,0) > (long) Node) {
+ 	printf("poolcheck: node being checked points to meta-data \n");
+ 	abort();
+       }	
+       TheIndex = PS->containsElement(Node, NodeSize);
+       return (PoolSlab *)PS;
+     } else {
+       // Check the LargeArrays
+       if (Pool->LargeArrays) {
+ 	PoolSlab *PSlab = (PoolSlab*) Pool->LargeArrays;
+ 	unsigned Idx = -1;
+ 	while (PSlab) {
+ 	  assert(PSlab && "poolcheck: node being free'd not found in "
+ 		 "allocation pool specified!\n");
+ 	  Idx = PSlab->containsElement(Node, NodeSize);
+ 	  if (Idx != -1) break;
+ 	  PSlab = PSlab->Next;
+ 	}
+ 	if (Idx == -1) {
+ 	  printf("poolcheck: node being checked not found in pool \n");
+ 	  abort();
+ 	}
+ 	TheIndex = Idx;
+ 	return PSlab;	
+       }
+       printf("poolcheck: node being checked not found in pool \n");
+       abort();
+     }
+   }
+ }
+ */
+ 
+ // SearchForContainingSlab - Do a brute force search through the list of
+ // allocated slabs for the node in question.
+ //
+ static PoolSlab *SearchForContainingSlab(PoolTy *Pool, void *Node,
+                                          unsigned &TheIndex) {
+   PoolSlab *PS = (PoolSlab*)Pool->Ptr1;
+   unsigned NodeSize = Pool->NodeSize;
+ 
+   // Search the partially allocated slab list for the slab that contains this
+   // node.
+   int Idx = -1;
+   if (PS) {               // Pool->Ptr1 could be null if Ptr2 isn't
+     for (; PS; PS = PS->Next) {
+       Idx = PS->containsElement(Node, NodeSize);
+       if (Idx != -1) break;
+     }
+   }
+ 
+   // If the partially allocated slab list doesn't contain it, maybe the
+   // completely allocated list does.
+   if (PS == 0) {
+     PS = (PoolSlab*)Pool->Ptr2;
+     assert(Idx == -1 && "Found node but don't have PS?");
+     
+     while (PS) {
+       assert(PS && "poolfree: node being free'd not found in allocation "
+              " pool specified!\n");
+       Idx = PS->containsElement(Node, NodeSize);
+       if (Idx != -1) break;
+       PS = PS->Next;
+     }
+   }
+   
+   // Otherwise, maybe its a block within LargeArrays
+   if(PS == 0) {
+     PS = (PoolSlab*)Pool->LargeArrays;
+     assert(Idx == -1  && "Found node but don't have PS?");
+     
+     while (PS) {
+       assert(PS && "poolfree: node being free'd not found in allocation "
+              " pool specified!\n");
+       Idx = PS->containsElement(Node, NodeSize);
+       if (Idx != -1) break;
+       PS = PS->Next;
+     }
+   }
+ 
+   TheIndex = Idx;
+   return PS;
+ }
+ 
+ void poolcheckoptim(PoolTy *Pool, void *Node) {
+   if (Pool->AllocadPool > 0) {
+     if (Pool->allocaptr <= Node) {
+      unsigned diffPtr = (unsigned)Node - (unsigned)Pool->allocaptr;
+      unsigned offset = diffPtr % Pool->NodeSize;
+      if ((diffPtr  < Pool->AllocadPool ) && (offset >= 0))
+        return;
+     }
+     PCheckPassed = 0;
+     abort();
+   }
+   
+   PoolSlab *PS = (PoolSlab*)((long)Node & ~(PageSize-1));
+ 
+   if (Pool->NumSlabs > AddrArrSize) {
+     hash_set<void*> &theSlabs = *Pool->Slabs;
+     if (theSlabs.find((void*)PS) == theSlabs.end()) {
+       // Check the LargeArrays
+       if (Pool->LargeArrays) {
+ 	PoolSlab *PSlab = (PoolSlab*) Pool->LargeArrays;
+ 	int Idx = -1;
+ 	while (PSlab) {
+ 	  assert(PSlab && "poolcheck: node being free'd not found in "
+ 		 "allocation pool specified!\n");
+ 	  Idx = PSlab->containsElement(Node, Pool->NodeSize);
+ 	  if (Idx != -1) {
+ 	    Pool->prevPage[Pool->lastUsed] = PS;
+ 	    Pool->lastUsed = (Pool->lastUsed + 1) % 4;
+ 	    break;
+ 	  }
+ 	  PSlab = PSlab->Next;
+ 	}
+ 	
+ 	if (Idx == -1) {
+ 	  printf("poolcheck1: node being checked not found in pool with right"
+ 		 " alignment\n");
+ 	  PCheckPassed = 0;
+ 	  abort();
+ 	  exit(-1);
+ 	} else {
+ 	  //exit(-1);
+ 	}
+       } else {
+ 	printf("poolcheck2: node being checked not found in pool with right"
+ 	       " alignment\n");
+ 	abort();
+ 	exit(-1);
+       }
+     } else {
+       unsigned long startaddr = (unsigned long)PS->getElementAddress(0,0);
+       if (startaddr > (unsigned long) Node) {
+ 	printf("poolcheck: node being checked points to meta-data \n");
+ 	abort();
+       }
+       unsigned long offset = ((unsigned long) Node - (unsigned long) startaddr) % Pool->NodeSize;
+       if (offset != 0) {
+ 	printf("poolcheck3: node being checked does not have right alignment\n");
+ 	abort();
+       }
+       Pool->prevPage[Pool->lastUsed] = PS;
+       Pool->lastUsed = (Pool->lastUsed + 1) % 4;
+     }
+   } else {
+     bool found = false;
+     for (unsigned i = 0; i < AddrArrSize && !found; ++i) {
+       if ((unsigned)Pool->SlabAddressArray[i] == (unsigned) PS) {
+ 	found = true;
+ 	Pool->prevPage[Pool->lastUsed] = PS;
+ 	Pool->lastUsed = (Pool->lastUsed + 1) % 4;
+       }
+     } 
+ 
+     if (found) {
+       // Check that Node does not point to PoolSlab meta-data
+       unsigned long startaddr = (unsigned long)PS->getElementAddress(0,0);
+       if (startaddr > (unsigned long) Node) {
+ 	printf("poolcheck: node being checked points to meta-data \n");
+ 	exit(-1);
+       }
+       unsigned long offset = ((unsigned long) Node - (unsigned long) startaddr) % Pool->NodeSize;
+       if (offset != 0) {
+ 	printf("poolcheck4: node being checked does not have right alignment\n");
+ 	abort();
+       }	
+     } else {
+       // Check the LargeArrays
+       if (Pool->LargeArrays) {
+ 	PoolSlab *PSlab = (PoolSlab*) Pool->LargeArrays;
+ 	int Idx = -1;
+ 	while (PSlab) {
+ 	  assert(PSlab && "poolcheck: node being free'd not found in "
+ 		 "allocation pool specified!\n");
+ 	  Idx = PSlab->containsElement(Node, Pool->NodeSize);
+ 	  if (Idx != -1) {
+ 	    Pool->prevPage[Pool->lastUsed] = PS;
+ 	    Pool->lastUsed = (Pool->lastUsed + 1) % 4;
+ 	    break;
+ 	  }
+ 	  PSlab = PSlab->Next;
+ 	}
+ 	if (Idx == -1) {
+ 	  printf("poolcheck6: node being checked not found in pool with right"
+ 		 " alignment\n");
+ 	  abort();
+ 	}	  
+       } else {
+ 	printf("poolcheck5: node being checked not found in pool with right"
+ 	       " alignment %x %x\n",Pool,Node);
+ 	abort();
+       }
+     }
+   }
+ }
+ 
+ void poolcheck(PoolTy *Pool, void *Node) {
+   PoolSlab *PS;
+   PS = (PoolSlab*)((long)Node & ~(PageSize-1));
+   if (Pool->prevPage[0] == PS) {
+     return;
+   }
+   if (Pool->prevPage[1] == PS) {
+     return;
+   }    
+   if (Pool->prevPage[2] == PS) {
+     return;
+   }    
+   if (Pool->prevPage[3] == PS) {
+     return;
+   }    
+   poolcheckoptim(Pool, Node);
+ }
+ 
+ 
+ 
+ // Check that Node falls within the pool and within start and (including)
+ // end offset
+ void poolcheckalign(PoolTy *Pool, void *Node, unsigned StartOffset, 
+ 		    unsigned EndOffset) {
+   PoolSlab *PS;
+   if (StartOffset >= Pool->NodeSize || EndOffset >= Pool->NodeSize) {
+     printf("Error: Offset specified exceeded node size");
+     exit(-1);
+   }
+ 
+   if (Pool->AllocadPool > 0) {
+     if (Pool->allocaptr <= Node) {
+      unsigned diffPtr = (unsigned)Node - (unsigned)Pool->allocaptr;
+      unsigned offset = diffPtr % Pool->NodeSize;
+      if ((diffPtr  < Pool->AllocadPool ) && (offset >= StartOffset) &&
+ 	 (offset <= EndOffset))
+        return;
+     }
+     assert(0 && "poolcheckalign failure FAILING \n");
+     exit(-1);    
+   }
+   
+   PS = (PoolSlab*)((long)Node & ~(PageSize-1));
+ 
+   if (Pool->NumSlabs > AddrArrSize) {
+     hash_set<void*> &theSlabs = *Pool->Slabs;
+     if (theSlabs.find((void*)PS) == theSlabs.end()) {
+       // Check the LargeArrays
+       if (Pool->LargeArrays) {
+ 	PoolSlab *PSlab = (PoolSlab*) Pool->LargeArrays;
+ 	int Idx = -1;
+ 	while (PSlab) {
+ 	  assert(PSlab && "poolcheck: node being free'd not found in "
+ 		 "allocation pool specified!\n");
+ 	  Idx = PSlab->containsElement(Node, Pool->NodeSize);
+ 	  if (Idx != -1) {
+ 	    Pool->prevPage[Pool->lastUsed] = PS;
+ 	    Pool->lastUsed = (Pool->lastUsed + 1) % 4;
+ 	    break;
+ 	  }
+ 	  PSlab = PSlab->Next;
+ 	}
+ 	
+ 	if (Idx == -1) {
+ 	  printf("poolcheck1: node being checked not found in pool with right"
+ 		 " alignment\n");
+ 	  abort();
+ 	  exit(-1);
+ 	} else {
+ 	  //exit(-1);
+ 	}
+       } else {
+ 	printf("poolcheck2: node being checked not found in pool with right"
+ 	       " alignment\n");
+ 	abort();
+ 	exit(-1);
+       }
+     } else {
+       unsigned long startaddr = (unsigned long)PS->getElementAddress(0,0);
+       if (startaddr > (unsigned long) Node) {
+ 	printf("poolcheck: node being checked points to meta-data \n");
+ 	abort();
+ 	exit(-1);
+       }
+       unsigned long offset = ((unsigned long) Node - (unsigned long) startaddr) % Pool->NodeSize;
+       if ((offset < StartOffset) || (offset > EndOffset)) {
+ 	printf("poolcheck3: node being checked does not have right alignment\n");
+ 	abort();
+ 	exit(-1);
+       }
+       Pool->prevPage[Pool->lastUsed] = PS;
+       Pool->lastUsed = (Pool->lastUsed + 1) % 4;
+     }
+   } else {
+     bool found = false;
+     for (unsigned i = 0; i < AddrArrSize && !found; ++i) {
+       if ((unsigned)Pool->SlabAddressArray[i] == (unsigned) PS) {
+ 	found = true;
+ 	Pool->prevPage[Pool->lastUsed] = PS;
+ 	Pool->lastUsed = (Pool->lastUsed + 1) % 4;
+       }
+     } 
+ 
+     if (found) {
+       // Check that Node does not point to PoolSlab meta-data
+       unsigned long startaddr = (unsigned long)PS->getElementAddress(0,0);
+       if (startaddr > (unsigned long) Node) {
+ 	printf("poolcheck: node being checked points to meta-data \n");
+ 	exit(-1);
+       }
+       unsigned long offset = ((unsigned long) Node - (unsigned long) startaddr) % Pool->NodeSize;
+       if ((offset < StartOffset) || (offset > EndOffset)) {
+ 	printf("poolcheck4: node being checked does not have right alignment\n");
+ 	abort();
+ 	exit(-1);
+       }	
+     } else {
+       // Check the LargeArrays
+       if (Pool->LargeArrays) {
+ 	PoolSlab *PSlab = (PoolSlab*) Pool->LargeArrays;
+ 	int Idx = -1;
+ 	while (PSlab) {
+ 	  assert(PSlab && "poolcheck: node being free'd not found in "
+ 		 "allocation pool specified!\n");
+ 	  Idx = PSlab->containsElement(Node, Pool->NodeSize);
+ 	  if (Idx != -1) {
+ 	    Pool->prevPage[Pool->lastUsed] = PS;
+ 	    Pool->lastUsed = (Pool->lastUsed + 1) % 4;
+ 	    break;
+ 	  }
+ 	  PSlab = PSlab->Next;
+ 	}
+ 	if (Idx == -1) {
+ 	  printf("poolcheck6: node being checked not found in pool with right"
+ 		 " alignment\n");
+ 	  abort();
+ 	  exit(-1);
+ 	}	  
+       } else {
+ 	printf("poolcheck5: node being checked not found in pool with right"
+ 	       " alignment %x %x\n",Pool,Node);
+ 	abort();
+       }
+     }
+   }
+ 
+ }
+ 
+ 
+ /*
+ void poolcheck(PoolTy *Pool, void *Node) {
+   PoolSlab *PS = (PoolSlab*)Pool->Ptr1;
+   unsigned NodeSize = Pool->NodeSize;
+ 
+   // Search the partially allocated slab list for the slab that contains this
+   // node.
+   int Idx = -1;
+   if (PS) {               // Pool->Ptr1 could be null if Ptr2 isn't
+     for (; PS; PS = PS->Next) {
+       Idx = PS->containsElement(Node, NodeSize);
+       if (Idx != -1) break;
+     }
+   }
+ 
+   // If the partially allocated slab list doesn't contain it, maybe the
+   // completely allocated list does.
+   if (PS == 0) {
+     PS = (PoolSlab*)Pool->Ptr2;
+     while (1) {
+       assert(PS && "poolcheck: node being checked not found in pool "
+              " specified!\n");
+       Idx = PS->containsElement(Node, NodeSize);
+       if (Idx != -1) break;
+       PS = PS->Next;
+     }
+   }
+ }
+ */
+ 
+ void poolfree(PoolTy *Pool, void *Node) {
+   assert(Pool && "Null pool pointer passed in to poolfree!\n");
+   DEBUG(printf("poolfree  %x %x \n",Pool,Node);)
+   PoolSlab *PS;
+   int Idx;
+   if (1) {                  // THIS SHOULD BE SET FOR SAFECODE!
+     unsigned TheIndex;
+     PS = SearchForContainingSlab(Pool, Node, TheIndex);
+     Idx = TheIndex;
+   } else {
+     // Since it is undefined behavior to free a node which has not been
+     // allocated, we know that the pointer coming in has to be a valid node
+     // pointer in the pool.  Mask off some bits of the address to find the base
+     // of the pool.
+     assert((PageSize & PageSize-1) == 0 && "Page size is not a power of 2??");
+     PS = (PoolSlab*)((long)Node & ~(PageSize-1));
+ 
+     if (PS->isSingleArray) {
+       PS->unlinkFromList();
+       PS->destroy();
+       return;
+     }
+ 
+     Idx = PS->containsElement(Node, Pool->NodeSize);
+     assert((int)Idx != -1 && "Node not contained in slab??");
+   }
+ 
+   // If PS was full, it must have been in list #2.  Unlink it and move it to
+   // list #1.
+   if (PS->isFull()) {
+     // Now that we found the node, we are about to free an element from it.
+     // This will make the slab no longer completely full, so we must move it to
+     // the other list!
+     PS->unlinkFromList(); // Remove it from the Ptr2 list.
+ 
+     PoolSlab **InsertPosPtr = (PoolSlab**)&Pool->Ptr1;
+ 
+     // If the partially full list has an empty node sitting at the front of the
+     // list, insert right after it.
+     if ((*InsertPosPtr)->isEmpty())
+       InsertPosPtr = &(*InsertPosPtr)->Next;
+ 
+     PS->addToList(InsertPosPtr);     // Insert it now in the Ptr1 list.
+   }
+ 
+   // Free the actual element now!
+   PS->freeElement(Idx);
+ 
+   // Ok, if this slab is empty, we unlink it from the of slabs and either move
+   // it to the head of the list, or free it, depending on whether or not there
+   // is already an empty slab at the head of the list.
+   //
+   if (PS->isEmpty()) {
+     PS->unlinkFromList();   // Unlink from the list of slabs...
+     
+     // If we can free this pool, check to see if there are any empty slabs at
+     // the start of this list.  If so, delete the FirstSlab!
+     PoolSlab *FirstSlab = (PoolSlab*)Pool->Ptr1;
+     if (0 && FirstSlab && FirstSlab->isEmpty()) {
+       // Here we choose to delete FirstSlab instead of the pool we just freed
+       // from because the pool we just freed from is more likely to be in the
+       // processor cache.
+       FirstSlab->unlinkFromList();
+       FirstSlab->destroy();
+       //      Pool->Slabs.erase((void *)FirstSlab);
+     }
+  
+     // Link our slab onto the head of the list so that allocations will find it
+     // efficiently.    
+     PS->addToList((PoolSlab**)&Pool->Ptr1);
+   }
+ }






More information about the llvm-commits mailing list