18 size_t additionalPreallocBytes)
22 , fBlockIncrement(
SkTo<uint16_t>(
24 (size_t)
std::numeric_limits<uint16_t>::
max())))
25 , fGrowthPolicy(static_cast<uint64_t>(policy))
30 , fHead(nullptr, additionalPreallocBytes + BaseHeadBlockSize()) {
35SkBlockAllocator::Block::Block(
Block*
prev,
int allocationSize)
38 , fSize(allocationSize)
41 , fAllocatorMetadata(0) {
45 this->poisonRange(kDataStart, fSize);
49 this->unpoisonRange(kDataStart, fSize);
51 SkASSERT(fSentinel == kAssignedMarker);
66 size_t size = this->scratchBlockSize();
71 size += (
b->fSize - kDataStart);
80 size += (
b->fCursor - kDataStart);
88 uintptr_t ptr =
reinterpret_cast<uintptr_t
>(p);
90 uintptr_t lowerBound =
reinterpret_cast<uintptr_t
>(
b) + kDataStart;
91 uintptr_t upperBound =
reinterpret_cast<uintptr_t
>(
b) +
b->fSize;
92 if (lowerBound <= ptr && ptr < upperBound) {
93 SkASSERT(
b->fSentinel == kAssignedMarker);
101 if (block == &fHead) {
103 block->fCursor = kDataStart;
104 block->fMetadata = 0;
105 block->poisonRange(kDataStart, block->fSize);
110 block->fPrev->fNext = block->fNext;
113 block->fNext->fPrev = block->fPrev;
116 fTail = block->fPrev;
120 if (this->scratchBlockSize() < block->fSize) {
125 block->markAsScratch();
134 if (fN0 > 0 && (fN1 > 1 || gp == GrowthPolicy::kFibonacci)) {
135 SkASSERT(gp != GrowthPolicy::kFixed);
136 if (gp == GrowthPolicy::kLinear) {
138 }
else if (gp == GrowthPolicy::kFibonacci) {
140 int temp = fN1 - fN0;
144 SkASSERT(gp == GrowthPolicy::kExponential);
155 Block* toSteal = other->fHead.fNext;
159 SkASSERT(other->fTail != &other->fHead);
160 toSteal->fPrev = fTail;
161 fTail->fNext = toSteal;
162 fTail = other->fTail;
164 other->fTail = &other->fHead;
165 other->fHead.fNext =
nullptr;
175 b->fCursor = kDataStart;
179 b->fAllocatorMetadata = 0;
180 b->poisonRange(kDataStart,
b->fSize);
186 SkASSERT(fTail == &fHead && fHead.fNext ==
nullptr && fHead.fPrev ==
nullptr &&
187 fHead.
metadata() == 0 && fHead.fCursor == kDataStart);
190 fN0 = (gp == GrowthPolicy::kLinear || gp == GrowthPolicy::kExponential) ? 1 : 0;
197 fHead.fPrev =
nullptr;
201void SkBlockAllocator::addBlock(
int minSize,
int maxSize) {
202 SkASSERT(minSize > (
int)
sizeof(
Block) && minSize <= maxSize);
205 static constexpr int kMaxN = (1 << 23) - 1;
206 static_assert(2 * kMaxN <= std::numeric_limits<int32_t>::max());
208 auto alignAllocSize = [](
int size) {
212 int mask = size > (1 << 15) ? ((1 << 12) - 1) : (kAddressAlign - 1);
213 return (size + mask) & ~mask;
218 if (this->scratchBlockSize() >= minSize) {
221 allocSize = fHead.fPrev->fSize;
223 fHead.fPrev =
nullptr;
224 }
else if (minSize < maxSize) {
227 int nextN1 = fN0 + fN1;
229 if (gp == GrowthPolicy::kFixed || gp == GrowthPolicy::kLinear) {
231 }
else if (gp == GrowthPolicy::kFibonacci) {
234 SkASSERT(gp == GrowthPolicy::kExponential);
237 fN0 = std::min(kMaxN, nextN0);
238 fN1 = std::min(kMaxN, nextN1);
242 int sizeIncrement = fBlockIncrement * kAddressAlign;
243 if (maxSize / sizeIncrement < nextN1) {
248 allocSize = std::min(alignAllocSize(std::max(minSize, sizeIncrement * nextN1)),
254 allocSize = alignAllocSize(minSize);
259 mem =
operator new(allocSize);
261 fTail->fNext =
new (mem)
Block(fTail, allocSize);
262 fTail = fTail->fNext;
266void SkBlockAllocator::validate()
const {
267 std::vector<const Block*>
blocks;
272 SkASSERT(kAssignedMarker == block->fSentinel);
273 if (block == &fHead) {
276 SkASSERT(!
prev && (!fHead.fPrev || fHead.fPrev->isScratch()));
285 SkASSERT(block->fCursor >= kDataStart);
286 SkASSERT(block->fCursor <= block->fSize);
static float prev(float f)
static constexpr size_t SkAlignTo(size_t x, size_t alignment)
size_t totalSpaceInUse() const
size_t preallocUsableSpace() const
void releaseBlock(Block *block)
void stealHeapBlocks(SkBlockAllocator *other)
size_t preallocSize() const
size_t totalUsableSpace() const
SkBlockAllocator(GrowthPolicy policy, size_t blockIncrementBytes, size_t additionalPreallocBytes=0)
Block * findOwningBlock(const void *ptr)
static constexpr int kMaxAllocationSize
BlockIter< false, false > rblocks()
BlockIter< true, false > blocks()
static float max(float r, float g, float b)
static float min(float r, float g, float b)