19f617d64c5f3f2a0949f359f63b1cb3bff4b3a9bChris Lattner//===--- Allocator.h - Simple memory allocation abstraction -----*- C++ -*-===//
29f617d64c5f3f2a0949f359f63b1cb3bff4b3a9bChris Lattner//
39f617d64c5f3f2a0949f359f63b1cb3bff4b3a9bChris Lattner//                     The LLVM Compiler Infrastructure
49f617d64c5f3f2a0949f359f63b1cb3bff4b3a9bChris Lattner//
57ed47a13356daed2a34cd2209a31f92552e3bdd8Chris Lattner// This file is distributed under the University of Illinois Open Source
67ed47a13356daed2a34cd2209a31f92552e3bdd8Chris Lattner// License. See LICENSE.TXT for details.
79f617d64c5f3f2a0949f359f63b1cb3bff4b3a9bChris Lattner//
89f617d64c5f3f2a0949f359f63b1cb3bff4b3a9bChris Lattner//===----------------------------------------------------------------------===//
9dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines/// \file
10dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines///
11dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines/// This file defines the MallocAllocator and BumpPtrAllocator interfaces. Both
12dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines/// of these conform to an LLVM "Allocator" concept which consists of an
13dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines/// Allocate method accepting a size and alignment, and a Deallocate accepting
14dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines/// a pointer and size. Further, the LLVM "Allocator" concept has overloads of
15dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines/// Allocate and Deallocate for setting size and alignment based on the final
16dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines/// type. These overloads are typically provided by a base class template \c
17dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines/// AllocatorBase.
18dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines///
199f617d64c5f3f2a0949f359f63b1cb3bff4b3a9bChris Lattner//===----------------------------------------------------------------------===//
209f617d64c5f3f2a0949f359f63b1cb3bff4b3a9bChris Lattner
219f617d64c5f3f2a0949f359f63b1cb3bff4b3a9bChris Lattner#ifndef LLVM_SUPPORT_ALLOCATOR_H
229f617d64c5f3f2a0949f359f63b1cb3bff4b3a9bChris Lattner#define LLVM_SUPPORT_ALLOCATOR_H
239f617d64c5f3f2a0949f359f63b1cb3bff4b3a9bChris Lattner
24dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines#include "llvm/ADT/SmallVector.h"
25869a3344f17975f57a328dcc8bacf6775344c045Ted Kremenek#include "llvm/Support/AlignOf.h"
261f6efa3996dd1929fbc129203ce5009b620e6969Michael J. Spencer#include "llvm/Support/DataTypes.h"
27255f89faee13dc491cb64fbeae3c763e7e2ea4e6Chandler Carruth#include "llvm/Support/MathExtras.h"
2836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#include "llvm/Support/Memory.h"
299553188fccbf0ae9c5b6bef26d0d2bd5feff8b59Dan Gohman#include <algorithm>
308f51a62b41a425f7fe262ff20cee835129ecc072Reid Kleckner#include <cassert>
319553188fccbf0ae9c5b6bef26d0d2bd5feff8b59Dan Gohman#include <cstddef>
32255f89faee13dc491cb64fbeae3c763e7e2ea4e6Chandler Carruth#include <cstdlib>
339f617d64c5f3f2a0949f359f63b1cb3bff4b3a9bChris Lattner
349f617d64c5f3f2a0949f359f63b1cb3bff4b3a9bChris Lattnernamespace llvm {
35fe2cce63aa26d0916fa7be32c6bf7fa8fb059ee7Misha Brukman
36dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines/// \brief CRTP base class providing obvious overloads for the core \c
37dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines/// Allocate() methods of LLVM-style allocators.
38dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines///
39dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines/// This base class both documents the full public interface exposed by all
40dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines/// LLVM-style allocators, and redirects all of the overloads to a single core
41dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines/// set of methods which the derived class must define.
42dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hinestemplate <typename DerivedT> class AllocatorBase {
439f617d64c5f3f2a0949f359f63b1cb3bff4b3a9bChris Lattnerpublic:
44dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  /// \brief Allocate \a Size bytes of \a Alignment aligned memory. This method
45dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  /// must be implemented by \c DerivedT.
46dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  void *Allocate(size_t Size, size_t Alignment) {
47dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines#ifdef __clang__
48dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    static_assert(static_cast<void *(AllocatorBase::*)(size_t, size_t)>(
49dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                      &AllocatorBase::Allocate) !=
50dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                      static_cast<void *(DerivedT::*)(size_t, size_t)>(
51dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                          &DerivedT::Allocate),
52dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                  "Class derives from AllocatorBase without implementing the "
53dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                  "core Allocate(size_t, size_t) overload!");
54dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines#endif
55dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    return static_cast<DerivedT *>(this)->Allocate(Size, Alignment);
5636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  }
57fe2cce63aa26d0916fa7be32c6bf7fa8fb059ee7Misha Brukman
58dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  /// \brief Deallocate \a Ptr to \a Size bytes of memory allocated by this
59dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  /// allocator.
60dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  void Deallocate(const void *Ptr, size_t Size) {
61dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines#ifdef __clang__
62dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    static_assert(static_cast<void (AllocatorBase::*)(const void *, size_t)>(
63dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                      &AllocatorBase::Deallocate) !=
64dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                      static_cast<void (DerivedT::*)(const void *, size_t)>(
65dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                          &DerivedT::Deallocate),
66dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                  "Class derives from AllocatorBase without implementing the "
67dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                  "core Deallocate(void *) overload!");
68dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines#endif
69dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    return static_cast<DerivedT *>(this)->Deallocate(Ptr, Size);
7007c2a78c2b9bf2500ece856c2df2dc043db9acb6Ted Kremenek  }
71fe2cce63aa26d0916fa7be32c6bf7fa8fb059ee7Misha Brukman
72dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  // The rest of these methods are helpers that redirect to one of the above
73dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  // core methods.
74f4dc289cea5dbfa272b54a8436a6bda6b226cee2Dan Gohman
75dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  /// \brief Allocate space for a sequence of objects without constructing them.
76dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  template <typename T> T *Allocate(size_t Num = 1) {
77dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    return static_cast<T *>(Allocate(Num * sizeof(T), AlignOf<T>::Alignment));
78dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  }
799f617d64c5f3f2a0949f359f63b1cb3bff4b3a9bChris Lattner
80dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  /// \brief Deallocate space for a sequence of objects without constructing them.
81dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  template <typename T>
82dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  typename std::enable_if<
83dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines      !std::is_same<typename std::remove_cv<T>::type, void>::value, void>::type
84dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  Deallocate(T *Ptr, size_t Num = 1) {
85dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    Deallocate(static_cast<const void *>(Ptr), Num * sizeof(T));
86dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  }
878f51a62b41a425f7fe262ff20cee835129ecc072Reid Kleckner};
888f51a62b41a425f7fe262ff20cee835129ecc072Reid Kleckner
89dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hinesclass MallocAllocator : public AllocatorBase<MallocAllocator> {
908f51a62b41a425f7fe262ff20cee835129ecc072Reid Klecknerpublic:
91dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  void Reset() {}
928f51a62b41a425f7fe262ff20cee835129ecc072Reid Kleckner
9337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  LLVM_ATTRIBUTE_RETURNS_NONNULL void *Allocate(size_t Size,
9437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines                                                size_t /*Alignment*/) {
9537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    return malloc(Size);
9637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  }
978f51a62b41a425f7fe262ff20cee835129ecc072Reid Kleckner
98dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  // Pull in base class overloads.
99dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  using AllocatorBase<MallocAllocator>::Allocate;
1008f51a62b41a425f7fe262ff20cee835129ecc072Reid Kleckner
101dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  void Deallocate(const void *Ptr, size_t /*Size*/) {
102dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    free(const_cast<void *>(Ptr));
103dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  }
1047f9a887d3f64d1227b911c9180767d95dbba4c10Argyrios Kyrtzidis
105dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  // Pull in base class overloads.
106dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  using AllocatorBase<MallocAllocator>::Deallocate;
1078f51a62b41a425f7fe262ff20cee835129ecc072Reid Kleckner
108dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  void PrintStats() const {}
109dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines};
1108f51a62b41a425f7fe262ff20cee835129ecc072Reid Kleckner
111dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hinesnamespace detail {
1128f51a62b41a425f7fe262ff20cee835129ecc072Reid Kleckner
113dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines// We call out to an external function to actually print the message as the
114dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines// printing code uses Allocator.h in its implementation.
115dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hinesvoid printBumpPtrAllocatorStats(unsigned NumSlabs, size_t BytesAllocated,
116dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                                size_t TotalMemory);
117dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines} // End namespace detail.
1188f51a62b41a425f7fe262ff20cee835129ecc072Reid Kleckner
11936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines/// \brief Allocate memory in an ever growing pool, as if by bump-pointer.
12036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines///
12136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines/// This isn't strictly a bump-pointer allocator as it uses backing slabs of
12237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines/// memory rather than relying on a boundless contiguous heap. However, it has
12337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines/// bump-pointer semantics in that it is a monotonically growing pool of memory
12436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines/// where every allocation is found by merely allocating the next N bytes in
12536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines/// the slab, or the next N bytes in the next slab.
12636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines///
12736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines/// Note that this also has a threshold for forcing allocations above a certain
12836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines/// size into their own slab.
129dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines///
130dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines/// The BumpPtrAllocatorImpl template defaults to using a MallocAllocator
131dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines/// object, which wraps malloc, to allocate memory, but it can be changed to
132dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines/// use a custom allocator.
133dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hinestemplate <typename AllocatorT = MallocAllocator, size_t SlabSize = 4096,
134dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines          size_t SizeThreshold = SlabSize>
135dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hinesclass BumpPtrAllocatorImpl
136dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    : public AllocatorBase<
137dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines          BumpPtrAllocatorImpl<AllocatorT, SlabSize, SizeThreshold>> {
1389f617d64c5f3f2a0949f359f63b1cb3bff4b3a9bChris Lattnerpublic:
13936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  static_assert(SizeThreshold <= SlabSize,
14036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines                "The SizeThreshold must be at most the SlabSize to ensure "
14136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines                "that objects larger than a slab go into their own memory "
14236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines                "allocation.");
14336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
14436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  BumpPtrAllocatorImpl()
145dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines      : CurPtr(nullptr), End(nullptr), BytesAllocated(0), Allocator() {}
146dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  template <typename T>
147dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  BumpPtrAllocatorImpl(T &&Allocator)
148dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines      : CurPtr(nullptr), End(nullptr), BytesAllocated(0),
149dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        Allocator(std::forward<T &&>(Allocator)) {}
150dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
1516948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar  // Manually implement a move constructor as we must clear the old allocator's
152dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  // slabs as a matter of correctness.
153dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  BumpPtrAllocatorImpl(BumpPtrAllocatorImpl &&Old)
154dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines      : CurPtr(Old.CurPtr), End(Old.End), Slabs(std::move(Old.Slabs)),
155dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        CustomSizedSlabs(std::move(Old.CustomSizedSlabs)),
156dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        BytesAllocated(Old.BytesAllocated),
157dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        Allocator(std::move(Old.Allocator)) {
158dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    Old.CurPtr = Old.End = nullptr;
159dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    Old.BytesAllocated = 0;
160dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    Old.Slabs.clear();
161dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    Old.CustomSizedSlabs.clear();
162dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  }
163dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
164dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  ~BumpPtrAllocatorImpl() {
165dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    DeallocateSlabs(Slabs.begin(), Slabs.end());
166dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    DeallocateCustomSizedSlabs();
167dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  }
168dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
169dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  BumpPtrAllocatorImpl &operator=(BumpPtrAllocatorImpl &&RHS) {
170dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    DeallocateSlabs(Slabs.begin(), Slabs.end());
171dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    DeallocateCustomSizedSlabs();
172dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
173dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    CurPtr = RHS.CurPtr;
174dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    End = RHS.End;
175dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    BytesAllocated = RHS.BytesAllocated;
176dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    Slabs = std::move(RHS.Slabs);
177dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    CustomSizedSlabs = std::move(RHS.CustomSizedSlabs);
178dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    Allocator = std::move(RHS.Allocator);
179dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
180dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    RHS.CurPtr = RHS.End = nullptr;
181dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    RHS.BytesAllocated = 0;
182dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    RHS.Slabs.clear();
183dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    RHS.CustomSizedSlabs.clear();
184dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    return *this;
185dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  }
18636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
18736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  /// \brief Deallocate all but the current slab and reset the current pointer
1888f51a62b41a425f7fe262ff20cee835129ecc072Reid Kleckner  /// to the beginning of it, freeing all memory allocated so far.
18936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  void Reset() {
1906948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar    DeallocateCustomSizedSlabs();
1916948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar    CustomSizedSlabs.clear();
1926948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar
193dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    if (Slabs.empty())
19436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      return;
195dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
196dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    // Reset the state.
19736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    BytesAllocated = 0;
198dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    CurPtr = (char *)Slabs.front();
199dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    End = CurPtr + SlabSize;
200dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
2016948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar    // Deallocate all but the first slab, and deallocate all custom-sized slabs.
202dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    DeallocateSlabs(std::next(Slabs.begin()), Slabs.end());
203dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    Slabs.erase(std::next(Slabs.begin()), Slabs.end());
20436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  }
205f4dc289cea5dbfa272b54a8436a6bda6b226cee2Dan Gohman
20636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  /// \brief Allocate space at the specified alignment.
2070c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar  LLVM_ATTRIBUTE_RETURNS_NONNULL LLVM_ATTRIBUTE_RETURNS_NOALIAS void *
2080c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar  Allocate(size_t Size, size_t Alignment) {
20937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    assert(Alignment > 0 && "0-byte alignnment is not allowed. Use 1 instead.");
21036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
21136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    // Keep track of how many bytes we've allocated.
21236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    BytesAllocated += Size;
21336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
21437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    size_t Adjustment = alignmentAdjustment(CurPtr, Alignment);
21537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    assert(Adjustment + Size >= Size && "Adjustment + Size must not overflow");
21636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
21737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    // Check if we have enough space.
21837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    if (Adjustment + Size <= size_t(End - CurPtr)) {
21937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines      char *AlignedPtr = CurPtr + Adjustment;
22037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines      CurPtr = AlignedPtr + Size;
22136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      // Update the allocation point of this memory block in MemorySanitizer.
22236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      // Without this, MemorySanitizer messages for values originated from here
22336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      // will point to the allocation of the entire slab.
22437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines      __msan_allocated_memory(AlignedPtr, Size);
225cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      // Similarly, tell ASan about this space.
226cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      __asan_unpoison_memory_region(AlignedPtr, Size);
22737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines      return AlignedPtr;
22836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    }
229869a3344f17975f57a328dcc8bacf6775344c045Ted Kremenek
23036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    // If Size is really big, allocate a separate slab for it.
231dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    size_t PaddedSize = Size + Alignment - 1;
23236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    if (PaddedSize > SizeThreshold) {
233dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines      void *NewSlab = Allocator.Allocate(PaddedSize, 0);
234cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      // We own the new slab and don't want anyone reading anyting other than
235cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      // pieces returned from this method.  So poison the whole slab.
236cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      __asan_poison_memory_region(NewSlab, PaddedSize);
237dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines      CustomSizedSlabs.push_back(std::make_pair(NewSlab, PaddedSize));
23836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
23937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines      uintptr_t AlignedAddr = alignAddr(NewSlab, Alignment);
24037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines      assert(AlignedAddr + Size <= (uintptr_t)NewSlab + PaddedSize);
24137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines      char *AlignedPtr = (char*)AlignedAddr;
24237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines      __msan_allocated_memory(AlignedPtr, Size);
243cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      __asan_unpoison_memory_region(AlignedPtr, Size);
24437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines      return AlignedPtr;
24536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    }
24636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
24736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    // Otherwise, start a new slab and try again.
24836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    StartNewSlab();
24937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    uintptr_t AlignedAddr = alignAddr(CurPtr, Alignment);
25037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    assert(AlignedAddr + Size <= (uintptr_t)End &&
25137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines           "Unable to allocate memory!");
25237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    char *AlignedPtr = (char*)AlignedAddr;
25337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    CurPtr = AlignedPtr + Size;
25437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    __msan_allocated_memory(AlignedPtr, Size);
255cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    __asan_unpoison_memory_region(AlignedPtr, Size);
25637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    return AlignedPtr;
257869a3344f17975f57a328dcc8bacf6775344c045Ted Kremenek  }
258fe2cce63aa26d0916fa7be32c6bf7fa8fb059ee7Misha Brukman
259dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  // Pull in base class overloads.
260dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  using AllocatorBase<BumpPtrAllocatorImpl>::Allocate;
261fe2cce63aa26d0916fa7be32c6bf7fa8fb059ee7Misha Brukman
262cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  void Deallocate(const void *Ptr, size_t Size) {
263cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    __asan_poison_memory_region(Ptr, Size);
264cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  }
26536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
266dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  // Pull in base class overloads.
267dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  using AllocatorBase<BumpPtrAllocatorImpl>::Deallocate;
2683f4c81de0ac7ff75e538dd68ef4ecfa204760bc9Ted Kremenek
269dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  size_t GetNumSlabs() const { return Slabs.size() + CustomSizedSlabs.size(); }
270f4dc289cea5dbfa272b54a8436a6bda6b226cee2Dan Gohman
271dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  size_t getTotalMemory() const {
272dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    size_t TotalMemory = 0;
273dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    for (auto I = Slabs.begin(), E = Slabs.end(); I != E; ++I)
274dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines      TotalMemory += computeSlabSize(std::distance(Slabs.begin(), I));
275dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    for (auto &PtrAndSize : CustomSizedSlabs)
276dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines      TotalMemory += PtrAndSize.second;
277dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    return TotalMemory;
278dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  }
2798f51a62b41a425f7fe262ff20cee835129ecc072Reid Kleckner
280dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  void PrintStats() const {
281dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    detail::printBumpPtrAllocatorStats(Slabs.size(), BytesAllocated,
282dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                                       getTotalMemory());
283dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  }
28436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
285dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hinesprivate:
28636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  /// \brief The current pointer into the current slab.
28736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  ///
28836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  /// This points to the next free byte in the slab.
28936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  char *CurPtr;
29036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
29136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  /// \brief The end of the current slab.
29236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  char *End;
29336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
294dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  /// \brief The slabs allocated so far.
295dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  SmallVector<void *, 4> Slabs;
296dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
297dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  /// \brief Custom-sized slabs allocated for too-large allocation requests.
298dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  SmallVector<std::pair<void *, size_t>, 0> CustomSizedSlabs;
299dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
300dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  /// \brief How many bytes we've allocated.
30136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  ///
302dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  /// Used so that we can compute how much space was wasted.
303dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  size_t BytesAllocated;
30436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
305dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  /// \brief The allocator instance we use to get slabs of memory.
306dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  AllocatorT Allocator;
307dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
308dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  static size_t computeSlabSize(unsigned SlabIdx) {
30936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    // Scale the actual allocated slab size based on the number of slabs
31036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    // allocated. Every 128 slabs allocated, we double the allocated size to
31136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    // reduce allocation frequency, but saturate at multiplying the slab size by
31236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    // 2^30.
313dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    return SlabSize * ((size_t)1 << std::min<size_t>(30, SlabIdx / 128));
31436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  }
31536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
316dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  /// \brief Allocate a new slab and move the bump pointers over into the new
317dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  /// slab, modifying CurPtr and End.
318dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  void StartNewSlab() {
319dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    size_t AllocatedSlabSize = computeSlabSize(Slabs.size());
320dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
321dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    void *NewSlab = Allocator.Allocate(AllocatedSlabSize, 0);
322cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    // We own the new slab and don't want anyone reading anything other than
323cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    // pieces returned from this method.  So poison the whole slab.
324cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    __asan_poison_memory_region(NewSlab, AllocatedSlabSize);
325cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar
326dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    Slabs.push_back(NewSlab);
327dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    CurPtr = (char *)(NewSlab);
328dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    End = ((char *)NewSlab) + AllocatedSlabSize;
329dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  }
330dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
331dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  /// \brief Deallocate a sequence of slabs.
332dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  void DeallocateSlabs(SmallVectorImpl<void *>::iterator I,
333dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                       SmallVectorImpl<void *>::iterator E) {
334dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    for (; I != E; ++I) {
335dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines      size_t AllocatedSlabSize =
336dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines          computeSlabSize(std::distance(Slabs.begin(), I));
337dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines      Allocator.Deallocate(*I, AllocatedSlabSize);
338dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    }
339dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  }
340dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
341dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  /// \brief Deallocate all memory for custom sized slabs.
342dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  void DeallocateCustomSizedSlabs() {
343dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    for (auto &PtrAndSize : CustomSizedSlabs) {
344dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines      void *Ptr = PtrAndSize.first;
345dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines      size_t Size = PtrAndSize.second;
346dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines      Allocator.Deallocate(Ptr, Size);
34736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    }
34836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  }
34936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
35036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  template <typename T> friend class SpecificBumpPtrAllocator;
3519f617d64c5f3f2a0949f359f63b1cb3bff4b3a9bChris Lattner};
3529f617d64c5f3f2a0949f359f63b1cb3bff4b3a9bChris Lattner
35336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines/// \brief The standard BumpPtrAllocator which just uses the default template
35436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines/// paramaters.
35536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinestypedef BumpPtrAllocatorImpl<> BumpPtrAllocator;
35636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
35736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines/// \brief A BumpPtrAllocator that allows only elements of a specific type to be
35836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines/// allocated.
35936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines///
36036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines/// This allows calling the destructor in DestroyAll() and when the allocator is
36136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines/// destroyed.
36236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinestemplate <typename T> class SpecificBumpPtrAllocator {
363991de14dd62dcbab4b31357ae22dc5b053ba50a0Benjamin Kramer  BumpPtrAllocator Allocator;
36436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
365991de14dd62dcbab4b31357ae22dc5b053ba50a0Benjamin Kramerpublic:
36636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  SpecificBumpPtrAllocator() : Allocator() {}
367dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  SpecificBumpPtrAllocator(SpecificBumpPtrAllocator &&Old)
368dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines      : Allocator(std::move(Old.Allocator)) {}
36936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  ~SpecificBumpPtrAllocator() { DestroyAll(); }
370991de14dd62dcbab4b31357ae22dc5b053ba50a0Benjamin Kramer
371dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  SpecificBumpPtrAllocator &operator=(SpecificBumpPtrAllocator &&RHS) {
372dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    Allocator = std::move(RHS.Allocator);
373dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    return *this;
374dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  }
375dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
376991de14dd62dcbab4b31357ae22dc5b053ba50a0Benjamin Kramer  /// Call the destructor of each allocated object and deallocate all but the
377991de14dd62dcbab4b31357ae22dc5b053ba50a0Benjamin Kramer  /// current slab and reset the current pointer to the beginning of it, freeing
378991de14dd62dcbab4b31357ae22dc5b053ba50a0Benjamin Kramer  /// all memory allocated so far.
379991de14dd62dcbab4b31357ae22dc5b053ba50a0Benjamin Kramer  void DestroyAll() {
380dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    auto DestroyElements = [](char *Begin, char *End) {
38137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines      assert(Begin == (char*)alignAddr(Begin, alignOf<T>()));
382dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines      for (char *Ptr = Begin; Ptr + sizeof(T) <= End; Ptr += sizeof(T))
383dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        reinterpret_cast<T *>(Ptr)->~T();
384dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    };
385dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
386dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    for (auto I = Allocator.Slabs.begin(), E = Allocator.Slabs.end(); I != E;
387dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines         ++I) {
388dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines      size_t AllocatedSlabSize = BumpPtrAllocator::computeSlabSize(
389dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines          std::distance(Allocator.Slabs.begin(), I));
39037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines      char *Begin = (char*)alignAddr(*I, alignOf<T>());
391dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines      char *End = *I == Allocator.Slabs.back() ? Allocator.CurPtr
392dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                                               : (char *)*I + AllocatedSlabSize;
393dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
394dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines      DestroyElements(Begin, End);
395dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    }
396dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
397dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    for (auto &PtrAndSize : Allocator.CustomSizedSlabs) {
398dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines      void *Ptr = PtrAndSize.first;
399dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines      size_t Size = PtrAndSize.second;
40037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines      DestroyElements((char*)alignAddr(Ptr, alignOf<T>()), (char *)Ptr + Size);
401991de14dd62dcbab4b31357ae22dc5b053ba50a0Benjamin Kramer    }
402dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
403991de14dd62dcbab4b31357ae22dc5b053ba50a0Benjamin Kramer    Allocator.Reset();
404991de14dd62dcbab4b31357ae22dc5b053ba50a0Benjamin Kramer  }
405991de14dd62dcbab4b31357ae22dc5b053ba50a0Benjamin Kramer
40636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  /// \brief Allocate space for an array of objects without constructing them.
40736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  T *Allocate(size_t num = 1) { return Allocator.Allocate<T>(num); }
408991de14dd62dcbab4b31357ae22dc5b053ba50a0Benjamin Kramer};
409991de14dd62dcbab4b31357ae22dc5b053ba50a0Benjamin Kramer
410abb8bf131c8542ff25964b69797558d425ed93c8Dan Gohman}  // end namespace llvm
4119f617d64c5f3f2a0949f359f63b1cb3bff4b3a9bChris Lattner
412dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hinestemplate <typename AllocatorT, size_t SlabSize, size_t SizeThreshold>
413dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hinesvoid *operator new(size_t Size,
414dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                   llvm::BumpPtrAllocatorImpl<AllocatorT, SlabSize,
415dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                                              SizeThreshold> &Allocator) {
4169553188fccbf0ae9c5b6bef26d0d2bd5feff8b59Dan Gohman  struct S {
4179553188fccbf0ae9c5b6bef26d0d2bd5feff8b59Dan Gohman    char c;
4189553188fccbf0ae9c5b6bef26d0d2bd5feff8b59Dan Gohman    union {
4199553188fccbf0ae9c5b6bef26d0d2bd5feff8b59Dan Gohman      double D;
4209553188fccbf0ae9c5b6bef26d0d2bd5feff8b59Dan Gohman      long double LD;
4219553188fccbf0ae9c5b6bef26d0d2bd5feff8b59Dan Gohman      long long L;
4229553188fccbf0ae9c5b6bef26d0d2bd5feff8b59Dan Gohman      void *P;
4239553188fccbf0ae9c5b6bef26d0d2bd5feff8b59Dan Gohman    } x;
4249553188fccbf0ae9c5b6bef26d0d2bd5feff8b59Dan Gohman  };
42536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  return Allocator.Allocate(
42636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      Size, std::min((size_t)llvm::NextPowerOf2(Size), offsetof(S, x)));
4279553188fccbf0ae9c5b6bef26d0d2bd5feff8b59Dan Gohman}
4289553188fccbf0ae9c5b6bef26d0d2bd5feff8b59Dan Gohman
429dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hinestemplate <typename AllocatorT, size_t SlabSize, size_t SizeThreshold>
430dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hinesvoid operator delete(
431dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    void *, llvm::BumpPtrAllocatorImpl<AllocatorT, SlabSize, SizeThreshold> &) {
432dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines}
433180c3d4edd1219832be8f2cf91f5f73f9757c36fBenjamin Kramer
4348f51a62b41a425f7fe262ff20cee835129ecc072Reid Kleckner#endif // LLVM_SUPPORT_ALLOCATOR_H
435