summaryrefslogtreecommitdiffstats
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
commit761af74802ee320d38430925eb9e30c4b1b0832c (patch)
tree5b51037b0501d95dfb2b2ff537c0038a8ad69e89
parentf80abc060cb1277b719031acee38300227b16898 (diff)
downloadbcm5719-llvm-761af74802ee320d38430925eb9e30c4b1b0832c.tar.gz
bcm5719-llvm-761af74802ee320d38430925eb9e30c4b1b0832c.zip
[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. llvm-svn: 206225
-rw-r--r--llvm/include/llvm/Support/Allocator.h86
1 files changed, 57 insertions, 29 deletions
diff --git a/llvm/include/llvm/Support/Allocator.h b/llvm/include/llvm/Support/Allocator.h
index 19ef4e834a5..a28080187b6 100644
--- a/llvm/include/llvm/Support/Allocator.h
+++ b/llvm/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*/) {}
OpenPOWER on IntegriCloud