mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-22 02:33:06 +01:00
ae65e281f3
to reflect the new license. We understand that people may be surprised that we're moving the header entirely to discuss the new license. We checked this carefully with the Foundation's lawyer and we believe this is the correct approach. Essentially, all code in the project is now made available by the LLVM project under our new license, so you will see that the license headers include that license only. Some of our contributors have contributed code under our old license, and accordingly, we have retained a copy of our old license notice in the top-level files in each project and repository. llvm-svn: 351636
116 lines
3.5 KiB
C++
116 lines
3.5 KiB
C++
//==- 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
|