X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=include%2Fllvm%2FSupport%2FRecycler.h;h=a38050d81903ac24b7b180a3c9d118f4e37a9d6d;hb=5c542537c1330e18cce3744b519849e2c0c11fff;hp=e97f36a735fdf64ece518c5afac4200565b19dd6;hpb=7c5042f86b4ad7d3fce819dbf9f6a215bef852c5;p=oota-llvm.git diff --git a/include/llvm/Support/Recycler.h b/include/llvm/Support/Recycler.h index e97f36a735f..a38050d8190 100644 --- a/include/llvm/Support/Recycler.h +++ b/include/llvm/Support/Recycler.h @@ -28,53 +28,36 @@ namespace llvm { /// void PrintRecyclerStats(size_t Size, size_t Align, size_t FreeListSize); -/// RecyclerStruct - Implementation detail for Recycler. This is a -/// class that the recycler imposes on free'd memory to carve out -/// next/prev pointers. -struct RecyclerStruct { - RecyclerStruct *Prev, *Next; -}; - -template<> -struct ilist_traits : - public ilist_default_traits { - static RecyclerStruct *getPrev(const RecyclerStruct *t) { return t->Prev; } - static RecyclerStruct *getNext(const RecyclerStruct *t) { return t->Next; } - static void setPrev(RecyclerStruct *t, RecyclerStruct *p) { t->Prev = p; } - static void setNext(RecyclerStruct *t, RecyclerStruct *n) { t->Next = n; } - - mutable RecyclerStruct Sentinel; - RecyclerStruct *createSentinel() const { - return &Sentinel; - } - static void destroySentinel(RecyclerStruct *) {} - - RecyclerStruct *provideInitialHead() const { return createSentinel(); } - RecyclerStruct *ensureHead(RecyclerStruct*) const { return createSentinel(); } - static void noteHead(RecyclerStruct*, RecyclerStruct*) {} - - static void deleteNode(RecyclerStruct *) { - llvm_unreachable("Recycler's ilist_traits shouldn't see a deleteNode call!"); - } -}; - /// Recycler - This class manages a linked-list of deallocated nodes /// and facilitates reusing deallocated memory in place of allocating /// new memory. /// template::Alignment> class Recycler { - /// FreeList - Doubly-linked list of nodes that have deleted contents and - /// are not in active use. - /// - iplist FreeList; + struct FreeNode { + FreeNode *Next; + }; + + /// List of nodes that have deleted contents and are not in active use. + FreeNode *FreeList = nullptr; + + FreeNode *pop_val() { + auto *Val = FreeList; + FreeList = FreeList->Next; + return Val; + } + + void push(FreeNode *N) { + N->Next = FreeList; + FreeList = N; + } public: ~Recycler() { // If this fails, either the callee has lost track of some allocation, // or the callee isn't tracking allocations and should just call // clear() before deleting the Recycler. - assert(FreeList.empty() && "Non-empty recycler deleted!"); + assert(!FreeList && "Non-empty recycler deleted!"); } /// clear - Release all the tracked allocations to the allocator. The @@ -82,8 +65,8 @@ public: /// deleted; calling clear is one way to ensure this. template void clear(AllocatorType &Allocator) { - while (!FreeList.empty()) { - T *t = reinterpret_cast(FreeList.remove(FreeList.begin())); + while (FreeList) { + T *t = reinterpret_cast(pop_val()); Allocator.Deallocate(t); } } @@ -93,9 +76,7 @@ public: /// /// There is no need to traverse the free list, pulling all the objects into /// cache. - void clear(BumpPtrAllocator&) { - FreeList.clearAndLeakNodesUnsafely(); - } + void clear(BumpPtrAllocator &) { FreeList = nullptr; } template SubClass *Allocate(AllocatorType &Allocator) { @@ -103,9 +84,8 @@ public: "Recycler allocation alignment is less than object align!"); static_assert(sizeof(SubClass) <= Size, "Recycler allocation size is less than object size!"); - return !FreeList.empty() ? - reinterpret_cast(FreeList.remove(FreeList.begin())) : - static_cast(Allocator.Allocate(Size, Align)); + return FreeList ? reinterpret_cast(pop_val()) + : static_cast(Allocator.Allocate(Size, Align)); } template @@ -115,14 +95,20 @@ public: template void Deallocate(AllocatorType & /*Allocator*/, SubClass* Element) { - FreeList.push_front(reinterpret_cast(Element)); + push(reinterpret_cast(Element)); } - void PrintStats() { - PrintRecyclerStats(Size, Align, FreeList.size()); - } + void PrintStats(); }; +template +void Recycler::PrintStats() { + size_t S = 0; + for (auto *I = FreeList; I; I = I->Next) + ++S; + PrintRecyclerStats(Size, Align, S); +} + } #endif