ChiaHungDuan 8b65c9d1ed
[scudo] Make block storage in TransferBatch trailing objects (#144204)
This allows us to change the number of blocks stored according to the
size of BatchClass.

Also change the name `TransferBatch` to `Batch` given that it's never
the unit of transferring blocks.
2025-07-08 11:07:05 -07:00

92 lines
3.1 KiB
C++

//===-- allocator_common.h --------------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef SCUDO_ALLOCATOR_COMMON_H_
#define SCUDO_ALLOCATOR_COMMON_H_
#include "common.h"
#include "list.h"
namespace scudo {
template <class SizeClassAllocator> struct Batch {
typedef typename SizeClassAllocator::SizeClassMap SizeClassMap;
typedef typename SizeClassAllocator::CompactPtrT CompactPtrT;
void setFromArray(CompactPtrT *Array, u16 N) {
DCHECK_LE(N, SizeClassAllocator::MaxNumBlocksInBatch);
Count = N;
memcpy(Blocks, Array, sizeof(Blocks[0]) * Count);
}
void appendFromArray(CompactPtrT *Array, u16 N) {
DCHECK_LE(N, SizeClassAllocator::MaxNumBlocksInBatch - Count);
memcpy(Blocks + Count, Array, sizeof(Blocks[0]) * N);
// u16 will be promoted to int by arithmetic type conversion.
Count = static_cast<u16>(Count + N);
}
void appendFromBatch(Batch *B, u16 N) {
DCHECK_LE(N, SizeClassAllocator::MaxNumBlocksInBatch - Count);
DCHECK_GE(B->Count, N);
// Append from the back of `B`.
memcpy(Blocks + Count, B->Blocks + (B->Count - N), sizeof(Blocks[0]) * N);
// u16 will be promoted to int by arithmetic type conversion.
Count = static_cast<u16>(Count + N);
B->Count = static_cast<u16>(B->Count - N);
}
void clear() { Count = 0; }
bool empty() { return Count == 0; }
void add(CompactPtrT P) {
DCHECK_LT(Count, SizeClassAllocator::MaxNumBlocksInBatch);
Blocks[Count++] = P;
}
void moveToArray(CompactPtrT *Array) {
memcpy(Array, Blocks, sizeof(Blocks[0]) * Count);
clear();
}
void moveNToArray(CompactPtrT *Array, u16 N) {
DCHECK_LE(N, Count);
memcpy(Array, Blocks + Count - N, sizeof(Blocks[0]) * N);
Count = static_cast<u16>(Count - N);
}
u16 getCount() const { return Count; }
bool isEmpty() const { return Count == 0U; }
CompactPtrT get(u16 I) const {
DCHECK_LE(I, Count);
return Blocks[I];
}
Batch *Next;
private:
u16 Count;
CompactPtrT Blocks[];
};
// A BatchGroup is used to collect blocks. Each group has a group id to
// identify the group kind of contained blocks.
template <class SizeClassAllocator> struct BatchGroup {
// `Next` is used by IntrusiveList.
BatchGroup *Next;
// The compact base address of each group
uptr CompactPtrGroupBase;
// This is used to track how many bytes are not in-use since last time we
// tried to release pages.
uptr BytesInBGAtLastCheckpoint;
// Blocks are managed by Batch in a list.
SinglyLinkedList<Batch<SizeClassAllocator>> Batches;
// Cache value of SizeClassAllocatorLocalCache::getMaxCached()
// TODO(chiahungduan): Except BatchClass, every Batch stores the same number
// of blocks. As long as we make BatchClass follow this constraint, this
// field can be removed.
u16 MaxCachedPerBatch;
};
} // namespace scudo
#endif // SCUDO_ALLOCATOR_COMMON_H_