BumpPtrAllocatorImpl(BumpPtrAllocatorImpl &&Old)
: CurPtr(Old.CurPtr), End(Old.End), Slabs(std::move(Old.Slabs)),
CustomSizedSlabs(std::move(Old.CustomSizedSlabs)),
- BytesAllocated(Old.BytesAllocated),
+ BytesAllocated(Old.BytesAllocated), RedZoneSize(Old.RedZoneSize),
Allocator(std::move(Old.Allocator)) {
Old.CurPtr = Old.End = nullptr;
Old.BytesAllocated = 0;
CurPtr = RHS.CurPtr;
End = RHS.End;
BytesAllocated = RHS.BytesAllocated;
+ RedZoneSize = RHS.RedZoneSize;
Slabs = std::move(RHS.Slabs);
CustomSizedSlabs = std::move(RHS.CustomSizedSlabs);
Allocator = std::move(RHS.Allocator);
size_t Adjustment = alignmentAdjustment(CurPtr, Alignment);
assert(Adjustment + Size >= Size && "Adjustment + Size must not overflow");
+ size_t SizeToAllocate = Size;
+#if LLVM_ADDRESS_SANITIZER_BUILD
+ // Add trailing bytes as a "red zone" under ASan.
+ SizeToAllocate += RedZoneSize;
+#endif
+
// Check if we have enough space.
- if (Adjustment + Size <= size_t(End - CurPtr)) {
+ if (Adjustment + SizeToAllocate <= size_t(End - CurPtr)) {
char *AlignedPtr = CurPtr + Adjustment;
- CurPtr = AlignedPtr + Size;
+ CurPtr = AlignedPtr + SizeToAllocate;
// 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.
}
// If Size is really big, allocate a separate slab for it.
- size_t PaddedSize = Size + Alignment - 1;
+ size_t PaddedSize = SizeToAllocate + Alignment - 1;
if (PaddedSize > SizeThreshold) {
void *NewSlab = Allocator.Allocate(PaddedSize, 0);
// We own the new slab and don't want anyone reading anyting other than
// Otherwise, start a new slab and try again.
StartNewSlab();
uintptr_t AlignedAddr = alignAddr(CurPtr, Alignment);
- assert(AlignedAddr + Size <= (uintptr_t)End &&
+ assert(AlignedAddr + SizeToAllocate <= (uintptr_t)End &&
"Unable to allocate memory!");
char *AlignedPtr = (char*)AlignedAddr;
- CurPtr = AlignedPtr + Size;
+ CurPtr = AlignedPtr + SizeToAllocate;
__msan_allocated_memory(AlignedPtr, Size);
__asan_unpoison_memory_region(AlignedPtr, Size);
return AlignedPtr;
size_t getBytesAllocated() const { return BytesAllocated; }
+ void setRedZoneSize(size_t NewSize) {
+ RedZoneSize = NewSize;
+ }
+
void PrintStats() const {
detail::printBumpPtrAllocatorStats(Slabs.size(), BytesAllocated,
getTotalMemory());
/// Used so that we can compute how much space was wasted.
size_t BytesAllocated = 0;
+ /// \brief The number of bytes to put between allocations when running under
+ /// a sanitizer.
+ size_t RedZoneSize = 1;
+
/// \brief The allocator instance we use to get slabs of memory.
AllocatorT Allocator;
BumpPtrAllocator Allocator;
public:
- SpecificBumpPtrAllocator() = default;
+ SpecificBumpPtrAllocator() {
+ // Because SpecificBumpPtrAllocator walks the memory to call destructors,
+ // it can't have red zones between allocations.
+ Allocator.setRedZoneSize(0);
+ }
SpecificBumpPtrAllocator(SpecificBumpPtrAllocator &&Old)
: Allocator(std::move(Old.Allocator)) {}
~SpecificBumpPtrAllocator() { DestroyAll(); }