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