summaryrefslogtreecommitdiff
path: root/include/llvm/Support
diff options
context:
space:
mode:
authorChandler Carruth <chandlerc@gmail.com>2014-04-15 00:19:41 +0000
committerChandler Carruth <chandlerc@gmail.com>2014-04-15 00:19:41 +0000
commitebfe4d7fee96e635d2656fb664ee0b56c41d0fcc (patch)
tree1ad9360252a991628ca374b2436a8ec47d48d28e /include/llvm/Support
parent40352669ba5a42c22395abf03e289c4f2ee9ec47 (diff)
downloadllvm-ebfe4d7fee96e635d2656fb664ee0b56c41d0fcc.tar.gz
llvm-ebfe4d7fee96e635d2656fb664ee0b56c41d0fcc.tar.bz2
llvm-ebfe4d7fee96e635d2656fb664ee0b56c41d0fcc.tar.xz
[Allocator] Factor the Allocate template overloads into a base class
rather than defining them (differently!) in both allocators. This also serves as a basis for documenting and even enforcing some of the LLVM-style "allocator" concept methods which must exist with various signatures. I plan on extending and changing the signatures of these to further simplify our allocator model in subsequent commits, so I wanted to factor things as best as I could first. Notably, I'm working to add the 'Size' to the deallocation method of all allocators. This has several implications not the least of which are faster deallocation times on certain allocation libraries (tcmalloc). It also will allow the JIT allocator to fully model the existing allocation interfaces and allow sanitizer poisoning of deallocated regions. The list of advantages goes on. =] But by factoring things first I'll be able to make this easier by first introducing template helpers for the deallocation path. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@206225 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'include/llvm/Support')
-rw-r--r--include/llvm/Support/Allocator.h86
1 files changed, 57 insertions, 29 deletions
diff --git a/include/llvm/Support/Allocator.h b/include/llvm/Support/Allocator.h
index 19ef4e834a..a28080187b 100644
--- a/include/llvm/Support/Allocator.h
+++ b/include/llvm/Support/Allocator.h
@@ -6,9 +6,16 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file defines the MallocAllocator and BumpPtrAllocator interfaces.
-//
+/// \file
+///
+/// This file defines the MallocAllocator and BumpPtrAllocator interfaces. Both
+/// of these conform to an LLVM "Allocator" concept which consists of an
+/// Allocate method accepting a size and alignment, and a Deallocate accepting
+/// a pointer and size. Further, the LLVM "Allocator" concept has overloads of
+/// Allocate and Deallocate for setting size and alignment based on the final
+/// type. These overloads are typically provided by a base class template \c
+/// AllocatorBase.
+///
//===----------------------------------------------------------------------===//
#ifndef LLVM_SUPPORT_ALLOCATOR_H
@@ -32,7 +39,46 @@ template <typename T> struct ReferenceAdder<T &> {
typedef T result;
};
-class MallocAllocator {
+/// \brief CRTP base class providing obvious overloads for the core \c
+/// Allocate() methods of LLVM-style allocators.
+///
+/// This base class both documents the full public interface exposed by all
+/// LLVM-style allocators, and redirects all of the overloads to a single core
+/// set of methods which the derived class must define.
+template <typename DerivedT> class AllocatorBase {
+public:
+ /// \brief Allocate \a Size bytes of \a Alignment aligned memory. This method
+ /// must be implemented by \c DerivedT.
+ void *Allocate(size_t Size, size_t Alignment) {
+ static_assert(static_cast<void *(AllocatorBase::*)(size_t, size_t)>(
+ &AllocatorBase::Allocate) !=
+ static_cast<void *(DerivedT::*)(size_t, size_t)>(
+ &DerivedT::Allocate),
+ "Class derives from AllocatorBase without implementing the "
+ "core Allocate(size_t, size_t) overload!");
+ return static_cast<DerivedT *>(this)->Allocate(Size, Alignment);
+ }
+
+ /// \brief Allocate space for one object without constructing it.
+ template <typename T> T *Allocate() {
+ return static_cast<T *>(Allocate(sizeof(T), AlignOf<T>::Alignment));
+ }
+
+ /// \brief Allocate space for an array of objects without constructing them.
+ template <typename T> T *Allocate(size_t Num) {
+ return static_cast<T *>(Allocate(Num * sizeof(T), AlignOf<T>::Alignment));
+ }
+
+ /// \brief Allocate space for an array of objects with the specified alignment
+ /// and without constructing them.
+ template <typename T> T *Allocate(size_t Num, size_t Alignment) {
+ // Round EltSize up to the specified alignment.
+ size_t EltSize = (sizeof(T) + Alignment - 1) & (-Alignment);
+ return static_cast<T *>(Allocate(Num * EltSize, Alignment));
+ }
+};
+
+class MallocAllocator : public AllocatorBase<MallocAllocator> {
public:
MallocAllocator() {}
~MallocAllocator() {}
@@ -41,13 +87,8 @@ public:
void *Allocate(size_t Size, size_t /*Alignment*/) { return malloc(Size); }
- template <typename T> T *Allocate() {
- return static_cast<T *>(malloc(sizeof(T)));
- }
-
- template <typename T> T *Allocate(size_t Num) {
- return static_cast<T *>(malloc(sizeof(T) * Num));
- }
+ // Pull in base class overloads.
+ using AllocatorBase<MallocAllocator>::Allocate;
void Deallocate(const void *Ptr) { free(const_cast<void *>(Ptr)); }
@@ -91,7 +132,9 @@ void printBumpPtrAllocatorStats(unsigned NumSlabs, size_t BytesAllocated,
/// use a custom allocator.
template <typename AllocatorT = MallocSlabAllocator, size_t SlabSize = 4096,
size_t SizeThreshold = SlabSize>
-class BumpPtrAllocatorImpl {
+class BumpPtrAllocatorImpl
+ : public AllocatorBase<
+ BumpPtrAllocatorImpl<AllocatorT, SlabSize, SizeThreshold>> {
BumpPtrAllocatorImpl(const BumpPtrAllocatorImpl &) LLVM_DELETED_FUNCTION;
void operator=(const BumpPtrAllocatorImpl &) LLVM_DELETED_FUNCTION;
@@ -176,23 +219,8 @@ public:
return Ptr;
}
- /// \brief Allocate space for one object without constructing it.
- template <typename T> T *Allocate() {
- return static_cast<T *>(Allocate(sizeof(T), AlignOf<T>::Alignment));
- }
-
- /// \brief Allocate space for an array of objects without constructing them.
- template <typename T> T *Allocate(size_t Num) {
- return static_cast<T *>(Allocate(Num * sizeof(T), AlignOf<T>::Alignment));
- }
-
- /// \brief Allocate space for an array of objects with the specified alignment
- /// and without constructing them.
- template <typename T> T *Allocate(size_t Num, size_t Alignment) {
- // Round EltSize up to the specified alignment.
- size_t EltSize = (sizeof(T) + Alignment - 1) & (-Alignment);
- return static_cast<T *>(Allocate(Num * EltSize, Alignment));
- }
+ // Pull in base class overloads.
+ using AllocatorBase<BumpPtrAllocatorImpl>::Allocate;
void Deallocate(const void * /*Ptr*/) {}