| Index: src/core/SkChunkAlloc.cpp
|
| diff --git a/src/core/SkChunkAlloc.cpp b/src/core/SkChunkAlloc.cpp
|
| index 62cdf1532f75b15738c296cf786d24b23ed1dfa0..4a71c2d2c43576263d00b2aeeac16aef90d50e61 100644
|
| --- a/src/core/SkChunkAlloc.cpp
|
| +++ b/src/core/SkChunkAlloc.cpp
|
| @@ -23,6 +23,18 @@ struct SkChunkAlloc::Block {
|
| char* fFreePtr;
|
| // data[] follows
|
|
|
| + size_t blockSize() {
|
| + char* start = this->startOfData();
|
| + size_t bytes = fFreePtr - start;
|
| + return fFreeSize + bytes;
|
| + }
|
| +
|
| + void reset() {
|
| + fNext = NULL;
|
| + fFreeSize = this->blockSize();
|
| + fFreePtr = this->startOfData();
|
| + }
|
| +
|
| char* startOfData() {
|
| return reinterpret_cast<char*>(this + 1);
|
| }
|
| @@ -53,7 +65,8 @@ SkChunkAlloc::SkChunkAlloc(size_t minSize) {
|
| fChunkSize = fMinSize;
|
| fTotalCapacity = 0;
|
| fTotalUsed = 0;
|
| - fBlockCount = 0;
|
| + SkDEBUGCODE(fTotalLost = 0;)
|
| + SkDEBUGCODE(fBlockCount = 0;)
|
| }
|
|
|
| SkChunkAlloc::~SkChunkAlloc() {
|
| @@ -66,7 +79,40 @@ void SkChunkAlloc::reset() {
|
| fChunkSize = fMinSize; // reset to our initial minSize
|
| fTotalCapacity = 0;
|
| fTotalUsed = 0;
|
| - fBlockCount = 0;
|
| + SkDEBUGCODE(fTotalLost = 0;)
|
| + SkDEBUGCODE(fBlockCount = 0;)
|
| +}
|
| +
|
| +void SkChunkAlloc::rewind() {
|
| + SkDEBUGCODE(this->validate();)
|
| +
|
| + Block* largest = fBlock;
|
| +
|
| + if (largest) {
|
| + Block* next;
|
| + for (Block* cur = largest->fNext; cur; cur = next) {
|
| + next = cur->fNext;
|
| + if (cur->blockSize() > largest->blockSize()) {
|
| + sk_free(largest);
|
| + largest = cur;
|
| + } else {
|
| + sk_free(cur);
|
| + }
|
| + }
|
| +
|
| + largest->reset();
|
| + fTotalCapacity = largest->blockSize();
|
| + SkDEBUGCODE(fBlockCount = 1;)
|
| + } else {
|
| + fTotalCapacity = 0;
|
| + SkDEBUGCODE(fBlockCount = 0;)
|
| + }
|
| +
|
| + fBlock = largest;
|
| + fChunkSize = fMinSize; // reset to our initial minSize
|
| + fTotalUsed = 0;
|
| + SkDEBUGCODE(fTotalLost = 0;)
|
| + SkDEBUGCODE(this->validate();)
|
| }
|
|
|
| SkChunkAlloc::Block* SkChunkAlloc::newBlock(size_t bytes, AllocFailType ftype) {
|
| @@ -79,43 +125,60 @@ SkChunkAlloc::Block* SkChunkAlloc::newBlock(size_t bytes, AllocFailType ftype) {
|
| ftype == kThrow_AllocFailType ? SK_MALLOC_THROW : 0);
|
|
|
| if (block) {
|
| - // block->fNext = fBlock;
|
| block->fFreeSize = size;
|
| block->fFreePtr = block->startOfData();
|
|
|
| fTotalCapacity += size;
|
| - fBlockCount += 1;
|
| + SkDEBUGCODE(fBlockCount += 1;)
|
|
|
| fChunkSize = increase_next_size(fChunkSize);
|
| }
|
| return block;
|
| }
|
|
|
| -void* SkChunkAlloc::alloc(size_t bytes, AllocFailType ftype) {
|
| - fTotalUsed += bytes;
|
| -
|
| - bytes = SkAlign4(bytes);
|
| -
|
| - Block* block = fBlock;
|
| +SkChunkAlloc::Block* SkChunkAlloc::addBlockIfNecessary(size_t bytes, AllocFailType ftype) {
|
| + SkASSERT(SkIsAlign4(bytes));
|
|
|
| - if (block == NULL || bytes > block->fFreeSize) {
|
| - block = this->newBlock(bytes, ftype);
|
| - if (NULL == block) {
|
| + if (!fBlock || bytes > fBlock->fFreeSize) {
|
| + Block* block = this->newBlock(bytes, ftype);
|
| + if (!block) {
|
| return NULL;
|
| }
|
| +#ifdef SK_DEBUG
|
| + if (fBlock) {
|
| + fTotalLost += fBlock->fFreeSize;
|
| + }
|
| +#endif
|
| block->fNext = fBlock;
|
| fBlock = block;
|
| }
|
|
|
| - SkASSERT(block && bytes <= block->fFreeSize);
|
| + SkASSERT(fBlock && bytes <= fBlock->fFreeSize);
|
| + return fBlock;
|
| +}
|
| +
|
| +void* SkChunkAlloc::alloc(size_t bytes, AllocFailType ftype) {
|
| + SkDEBUGCODE(this->validate();)
|
| +
|
| + bytes = SkAlign4(bytes);
|
| +
|
| + Block* block = this->addBlockIfNecessary(bytes, ftype);
|
| + if (!block) {
|
| + return NULL;
|
| + }
|
| +
|
| char* ptr = block->fFreePtr;
|
|
|
| + fTotalUsed += bytes;
|
| block->fFreeSize -= bytes;
|
| block->fFreePtr = ptr + bytes;
|
| + SkDEBUGCODE(this->validate();)
|
| return ptr;
|
| }
|
|
|
| size_t SkChunkAlloc::unalloc(void* ptr) {
|
| + SkDEBUGCODE(this->validate();)
|
| +
|
| size_t bytes = 0;
|
| Block* block = fBlock;
|
| if (block) {
|
| @@ -123,10 +186,12 @@ size_t SkChunkAlloc::unalloc(void* ptr) {
|
| char* start = block->startOfData();
|
| if (start <= cPtr && cPtr < block->fFreePtr) {
|
| bytes = block->fFreePtr - cPtr;
|
| + fTotalUsed -= bytes;
|
| block->fFreeSize += bytes;
|
| block->fFreePtr = cPtr;
|
| }
|
| }
|
| + SkDEBUGCODE(this->validate();)
|
| return bytes;
|
| }
|
|
|
| @@ -140,3 +205,31 @@ bool SkChunkAlloc::contains(const void* addr) const {
|
| }
|
| return false;
|
| }
|
| +
|
| +#ifdef SK_DEBUG
|
| +void SkChunkAlloc::validate() {
|
| + int numBlocks = 0;
|
| + size_t totCapacity = 0;
|
| + size_t totUsed = 0;
|
| + size_t totLost = 0;
|
| + size_t totAvailable = 0;
|
| +
|
| + for (Block* temp = fBlock; temp; temp = temp->fNext) {
|
| + ++numBlocks;
|
| + totCapacity += temp->blockSize();
|
| + totUsed += temp->fFreePtr - temp->startOfData();
|
| + if (temp == fBlock) {
|
| + totAvailable += temp->fFreeSize;
|
| + } else {
|
| + totLost += temp->fFreeSize;
|
| + }
|
| + }
|
| +
|
| + SkASSERT(fBlockCount == numBlocks);
|
| + SkASSERT(fTotalCapacity == totCapacity);
|
| + SkASSERT(fTotalUsed == totUsed);
|
| + SkASSERT(fTotalLost == totLost);
|
| + SkASSERT(totCapacity == totUsed + totLost + totAvailable);
|
| +}
|
| +#endif
|
| +
|
|
|