+ // Deallocate all but the first slab, and deallocate all custom-sized slabs.
+ DeallocateSlabs(std::next(Slabs.begin()), Slabs.end());
+ Slabs.erase(std::next(Slabs.begin()), Slabs.end());
+ }
+
+ /// \brief Allocate space at the specified alignment.
+ LLVM_ATTRIBUTE_RETURNS_NONNULL LLVM_ATTRIBUTE_RETURNS_NOALIAS void *
+ Allocate(size_t Size, size_t Alignment) {
+ assert(Alignment > 0 && "0-byte alignnment is not allowed. Use 1 instead.");
+
+ // Keep track of how many bytes we've allocated.
+ BytesAllocated += Size;
+
+ size_t Adjustment = alignmentAdjustment(CurPtr, Alignment);
+ assert(Adjustment + Size >= Size && "Adjustment + Size must not overflow");
+
+ // Check if we have enough space.
+ if (Adjustment + Size <= size_t(End - CurPtr)) {
+ char *AlignedPtr = CurPtr + Adjustment;
+ CurPtr = AlignedPtr + Size;
+ // Update the allocation point of this memory block in MemorySanitizer.
+ // Without this, MemorySanitizer messages for values originated from here
+ // will point to the allocation of the entire slab.
+ __msan_allocated_memory(AlignedPtr, Size);
+ return AlignedPtr;
+ }
+
+ // If Size is really big, allocate a separate slab for it.
+ size_t PaddedSize = Size + Alignment - 1;
+ if (PaddedSize > SizeThreshold) {
+ void *NewSlab = Allocator.Allocate(PaddedSize, 0);
+ CustomSizedSlabs.push_back(std::make_pair(NewSlab, PaddedSize));
+
+ uintptr_t AlignedAddr = alignAddr(NewSlab, Alignment);
+ assert(AlignedAddr + Size <= (uintptr_t)NewSlab + PaddedSize);
+ char *AlignedPtr = (char*)AlignedAddr;
+ __msan_allocated_memory(AlignedPtr, Size);
+ return AlignedPtr;
+ }
+
+ // Otherwise, start a new slab and try again.
+ StartNewSlab();
+ uintptr_t AlignedAddr = alignAddr(CurPtr, Alignment);
+ assert(AlignedAddr + Size <= (uintptr_t)End &&
+ "Unable to allocate memory!");
+ char *AlignedPtr = (char*)AlignedAddr;
+ CurPtr = AlignedPtr + Size;
+ __msan_allocated_memory(AlignedPtr, Size);
+ return AlignedPtr;
+ }
+
+ // Pull in base class overloads.
+ using AllocatorBase<BumpPtrAllocatorImpl>::Allocate;
+
+ void Deallocate(const void * /*Ptr*/, size_t /*Size*/) {}
+
+ // Pull in base class overloads.
+ using AllocatorBase<BumpPtrAllocatorImpl>::Deallocate;
+
+ size_t GetNumSlabs() const { return Slabs.size() + CustomSizedSlabs.size(); }
+
+ size_t getTotalMemory() const {
+ size_t TotalMemory = 0;
+ for (auto I = Slabs.begin(), E = Slabs.end(); I != E; ++I)
+ TotalMemory += computeSlabSize(std::distance(Slabs.begin(), I));
+ for (auto &PtrAndSize : CustomSizedSlabs)
+ TotalMemory += PtrAndSize.second;
+ return TotalMemory;
+ }
+
+ void PrintStats() const {
+ detail::printBumpPtrAllocatorStats(Slabs.size(), BytesAllocated,
+ getTotalMemory());
+ }
+
+private:
+ /// \brief The current pointer into the current slab.