diff options
author | Duncan P. N. Exon Smith <dexonsmith@apple.com> | 2015-10-07 20:49:09 +0000 |
---|---|---|
committer | Duncan P. N. Exon Smith <dexonsmith@apple.com> | 2015-10-07 20:49:09 +0000 |
commit | 4462c6190e7164009bce6d6f0d2f37f14a41eabd (patch) | |
tree | 5e5e6bf6c2421424edc2a21414099af9c4e9ebd9 | |
parent | c06b7d67cd1ebb1f81df9a0d04253d0d5f832b04 (diff) | |
download | bcm5719-llvm-4462c6190e7164009bce6d6f0d2f37f14a41eabd.tar.gz bcm5719-llvm-4462c6190e7164009bce6d6f0d2f37f14a41eabd.zip |
Support: Stop using iplist in Recycler
Recycler just needs a singly-linked list, and it takes less (and
simpler) code to hand-roll one of those than to build up the equivalent
`iplist_traits`. In theory, this should speed things up a bit too, but
this is really just a drive-by cleanup so I haven't measured.
llvm-svn: 249615
-rw-r--r-- | llvm/include/llvm/Support/Recycler.h | 80 |
1 files changed, 33 insertions, 47 deletions
diff --git a/llvm/include/llvm/Support/Recycler.h b/llvm/include/llvm/Support/Recycler.h index e97f36a735f..a38050d8190 100644 --- a/llvm/include/llvm/Support/Recycler.h +++ b/llvm/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<RecyclerStruct> : - public ilist_default_traits<RecyclerStruct> { - 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<class T, size_t Size = sizeof(T), size_t Align = AlignOf<T>::Alignment> class Recycler { - /// FreeList - Doubly-linked list of nodes that have deleted contents and - /// are not in active use. - /// - iplist<RecyclerStruct> 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<class AllocatorType> void clear(AllocatorType &Allocator) { - while (!FreeList.empty()) { - T *t = reinterpret_cast<T *>(FreeList.remove(FreeList.begin())); + while (FreeList) { + T *t = reinterpret_cast<T *>(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<class SubClass, class AllocatorType> 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<SubClass *>(FreeList.remove(FreeList.begin())) : - static_cast<SubClass *>(Allocator.Allocate(Size, Align)); + return FreeList ? reinterpret_cast<SubClass *>(pop_val()) + : static_cast<SubClass *>(Allocator.Allocate(Size, Align)); } template<class AllocatorType> @@ -115,14 +95,20 @@ public: template<class SubClass, class AllocatorType> void Deallocate(AllocatorType & /*Allocator*/, SubClass* Element) { - FreeList.push_front(reinterpret_cast<RecyclerStruct *>(Element)); + push(reinterpret_cast<FreeNode *>(Element)); } - void PrintStats() { - PrintRecyclerStats(Size, Align, FreeList.size()); - } + void PrintStats(); }; +template <class T, size_t Size, size_t Align> +void Recycler<T, Size, Align>::PrintStats() { + size_t S = 0; + for (auto *I = FreeList; I; I = I->Next) + ++S; + PrintRecyclerStats(Size, Align, S); +} + } #endif |