diff options
| author | Ralf Luther <luther.ralf@gmail.com> | 2019-03-27 20:23:17 +0000 |
|---|---|---|
| committer | Gerrit Code Review <gerrit2@aicp-server-3> | 2019-03-27 20:23:17 +0000 |
| commit | 1ce3a9d272e564b22a1333a1e36a3d3ab7cfab01 (patch) | |
| tree | 391382eadd4fec5bb480f2e8934fa352770221d1 /clang-r353983/include/llvm/Support/Recycler.h | |
| parent | d1d48b140bafaa8a50107292f5fce95562575765 (diff) | |
| parent | 4f56932d3416ac03f646bc1a611b3135fec2fe08 (diff) | |
Merge "Update prebuilt Clang to r353983." into p9.0HEADp9.0-backupp9.0
Diffstat (limited to 'clang-r353983/include/llvm/Support/Recycler.h')
| -rw-r--r-- | clang-r353983/include/llvm/Support/Recycler.h | 115 |
1 files changed, 115 insertions, 0 deletions
diff --git a/clang-r353983/include/llvm/Support/Recycler.h b/clang-r353983/include/llvm/Support/Recycler.h new file mode 100644 index 00000000..bbd9ae32 --- /dev/null +++ b/clang-r353983/include/llvm/Support/Recycler.h @@ -0,0 +1,115 @@ +//==- llvm/Support/Recycler.h - Recycling Allocator --------------*- C++ -*-==// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines the Recycler class template. See the doxygen comment for +// Recycler for more details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_RECYCLER_H +#define LLVM_SUPPORT_RECYCLER_H + +#include "llvm/ADT/ilist.h" +#include "llvm/Support/Allocator.h" +#include "llvm/Support/ErrorHandling.h" +#include <cassert> + +namespace llvm { + +/// PrintRecyclingAllocatorStats - Helper for RecyclingAllocator for +/// printing statistics. +/// +void PrintRecyclerStats(size_t Size, size_t Align, size_t FreeListSize); + +/// 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)> +class Recycler { + 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; + __asan_unpoison_memory_region(Val, Size); + FreeList = FreeList->Next; + __msan_allocated_memory(Val, Size); + return Val; + } + + void push(FreeNode *N) { + N->Next = FreeList; + FreeList = N; + __asan_poison_memory_region(N, Size); + } + +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 && "Non-empty recycler deleted!"); + } + + /// clear - Release all the tracked allocations to the allocator. The + /// recycler must be free of any tracked allocations before being + /// deleted; calling clear is one way to ensure this. + template<class AllocatorType> + void clear(AllocatorType &Allocator) { + while (FreeList) { + T *t = reinterpret_cast<T *>(pop_val()); + Allocator.Deallocate(t); + } + } + + /// Special case for BumpPtrAllocator which has an empty Deallocate() + /// function. + /// + /// There is no need to traverse the free list, pulling all the objects into + /// cache. + void clear(BumpPtrAllocator &) { FreeList = nullptr; } + + template<class SubClass, class AllocatorType> + SubClass *Allocate(AllocatorType &Allocator) { + static_assert(alignof(SubClass) <= Align, + "Recycler allocation alignment is less than object align!"); + static_assert(sizeof(SubClass) <= Size, + "Recycler allocation size is less than object size!"); + return FreeList ? reinterpret_cast<SubClass *>(pop_val()) + : static_cast<SubClass *>(Allocator.Allocate(Size, Align)); + } + + template<class AllocatorType> + T *Allocate(AllocatorType &Allocator) { + return Allocate<T>(Allocator); + } + + template<class SubClass, class AllocatorType> + void Deallocate(AllocatorType & /*Allocator*/, SubClass* Element) { + push(reinterpret_cast<FreeNode *>(Element)); + } + + 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 |
