X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=include%2Fllvm%2FSupport%2FAllocator.h;h=a2ad24ffead93bd995f50101e9c37063e30e9960;hb=a00b80b04c5edb08639c1c6b32e9231fd8b066f7;hp=9ca02efb1f6e557c893ce76991cff44ac34c4253;hpb=fe2cce63aa26d0916fa7be32c6bf7fa8fb059ee7;p=oota-llvm.git diff --git a/include/llvm/Support/Allocator.h b/include/llvm/Support/Allocator.h index 9ca02efb1f6..a2ad24ffead 100644 --- a/include/llvm/Support/Allocator.h +++ b/include/llvm/Support/Allocator.h @@ -15,9 +15,16 @@ #define LLVM_SUPPORT_ALLOCATOR_H #include "llvm/Support/AlignOf.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Support/DataTypes.h" +#include +#include #include +#include namespace llvm { +template struct ReferenceAdder { typedef T& result; }; +template struct ReferenceAdder { typedef T result; }; class MallocAllocator { public: @@ -41,21 +48,105 @@ public: void PrintStats() const {} }; -/// BumpPtrAllocator - This allocator is useful for containers that need very -/// simple memory allocation strategies. In particular, this just keeps +/// MemSlab - This structure lives at the beginning of every slab allocated by +/// the bump allocator. +class MemSlab { +public: + size_t Size; + MemSlab *NextPtr; +}; + +/// SlabAllocator - This class can be used to parameterize the underlying +/// allocation strategy for the bump allocator. In particular, this is used +/// by the JIT to allocate contiguous swathes of executable memory. The +/// interface uses MemSlab's instead of void *'s so that the allocator +/// doesn't have to remember the size of the pointer it allocated. +class SlabAllocator { +public: + virtual ~SlabAllocator(); + virtual MemSlab *Allocate(size_t Size) = 0; + virtual void Deallocate(MemSlab *Slab) = 0; +}; + +/// MallocSlabAllocator - The default slab allocator for the bump allocator +/// is an adapter class for MallocAllocator that just forwards the method +/// calls and translates the arguments. +class MallocSlabAllocator : public SlabAllocator { + /// Allocator - The underlying allocator that we forward to. + /// + MallocAllocator Allocator; + +public: + MallocSlabAllocator() : Allocator() { } + virtual ~MallocSlabAllocator(); + virtual MemSlab *Allocate(size_t Size); + virtual void Deallocate(MemSlab *Slab); +}; + +/// BumpPtrAllocator - This allocator is useful for containers that need +/// very simple memory allocation strategies. In particular, this just keeps /// allocating memory, and never deletes it until the entire block is dead. This /// makes allocation speedy, but must only be used when the trade-off is ok. class BumpPtrAllocator { BumpPtrAllocator(const BumpPtrAllocator &); // do not implement void operator=(const BumpPtrAllocator &); // do not implement - void *TheMemory; + /// SlabSize - Allocate data into slabs of this size unless we get an + /// allocation above SizeThreshold. + size_t SlabSize; + + /// SizeThreshold - For any allocation larger than this threshold, we should + /// allocate a separate slab. + size_t SizeThreshold; + + /// Allocator - The underlying allocator we use to get slabs of memory. This + /// defaults to MallocSlabAllocator, which wraps malloc, but it could be + /// changed to use a custom allocator. + SlabAllocator &Allocator; + + /// CurSlab - The slab that we are currently allocating into. + /// + MemSlab *CurSlab; + + /// CurPtr - The current pointer into the current slab. This points to the + /// next free byte in the slab. + char *CurPtr; + + /// End - The end of the current slab. + /// + char *End; + + /// BytesAllocated - This field tracks how many bytes we've allocated, so + /// that we can compute how much space was wasted. + size_t BytesAllocated; + + /// AlignPtr - Align Ptr to Alignment bytes, rounding up. Alignment should + /// be a power of two. This method rounds up, so AlignPtr(7, 4) == 8 and + /// AlignPtr(8, 4) == 8. + static char *AlignPtr(char *Ptr, size_t Alignment); + + /// StartNewSlab - Allocate a new slab and move the bump pointers over into + /// the new slab. Modifies CurPtr and End. + void StartNewSlab(); + + /// DeallocateSlabs - Deallocate all memory slabs after and including this + /// one. + void DeallocateSlabs(MemSlab *Slab); + + static MallocSlabAllocator DefaultSlabAllocator; + + template friend class SpecificBumpPtrAllocator; public: - BumpPtrAllocator(); + BumpPtrAllocator(size_t size = 4096, size_t threshold = 4096, + SlabAllocator &allocator = DefaultSlabAllocator); ~BumpPtrAllocator(); + /// Reset - Deallocate all but the current slab and reset the current pointer + /// to the beginning of it, freeing all memory allocated so far. void Reset(); + /// Allocate - Allocate space at the specified alignment. + /// void *Allocate(size_t Size, size_t Alignment); /// Allocate space, but do not construct, one object. @@ -75,17 +166,77 @@ public: /// Allocate space for a specific count of elements and with a specified /// alignment. template - T *Allocate(size_t Num, unsigned Alignment) { + T *Allocate(size_t Num, size_t Alignment) { // Round EltSize up to the specified alignment. - unsigned EltSize = (sizeof(T)+Alignment-1)&~Alignment; + size_t EltSize = (sizeof(T)+Alignment-1)&(-Alignment); return static_cast(Allocate(Num * EltSize, Alignment)); } void Deallocate(const void * /*Ptr*/) {} + unsigned GetNumSlabs() const; + void PrintStats() const; + + /// Compute the total physical memory allocated by this allocator. + size_t getTotalMemory() const; +}; + +/// SpecificBumpPtrAllocator - Same as BumpPtrAllocator but allows only +/// elements of one type to be allocated. This allows calling the destructor +/// in DestroyAll() and when the allocator is destroyed. +template +class SpecificBumpPtrAllocator { + BumpPtrAllocator Allocator; +public: + SpecificBumpPtrAllocator(size_t size = 4096, size_t threshold = 4096, + SlabAllocator &allocator = BumpPtrAllocator::DefaultSlabAllocator) + : Allocator(size, threshold, allocator) {} + + ~SpecificBumpPtrAllocator() { + DestroyAll(); + } + + /// Call the destructor of each allocated object and deallocate all but the + /// current slab and reset the current pointer to the beginning of it, freeing + /// all memory allocated so far. + void DestroyAll() { + MemSlab *Slab = Allocator.CurSlab; + while (Slab) { + char *End = Slab == Allocator.CurSlab ? Allocator.CurPtr : + (char *)Slab + Slab->Size; + for (char *Ptr = (char*)(Slab+1); Ptr < End; Ptr += sizeof(T)) { + Ptr = Allocator.AlignPtr(Ptr, alignOf()); + if (Ptr + sizeof(T) <= End) + reinterpret_cast(Ptr)->~T(); + } + Slab = Slab->NextPtr; + } + Allocator.Reset(); + } + + /// Allocate space for a specific count of elements. + T *Allocate(size_t num = 1) { + return Allocator.Allocate(num); + } }; } // end namespace llvm -#endif +inline void *operator new(size_t Size, llvm::BumpPtrAllocator &Allocator) { + struct S { + char c; + union { + double D; + long double LD; + long long L; + void *P; + } x; + }; + return Allocator.Allocate(Size, std::min((size_t)llvm::NextPowerOf2(Size), + offsetof(S, x))); +} + +inline void operator delete(void *, llvm::BumpPtrAllocator &) {} + +#endif // LLVM_SUPPORT_ALLOCATOR_H