1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/skia/trunk/src/core/SkChunkAlloc.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,142 @@ 1.4 +/* 1.5 + * Copyright 2006 The Android Open Source Project 1.6 + * 1.7 + * Use of this source code is governed by a BSD-style license that can be 1.8 + * found in the LICENSE file. 1.9 + */ 1.10 + 1.11 +#include "SkChunkAlloc.h" 1.12 + 1.13 +// Don't malloc any chunks smaller than this 1.14 +#define MIN_CHUNKALLOC_BLOCK_SIZE 1024 1.15 + 1.16 +// Return the new min blocksize given the current value 1.17 +static size_t increase_next_size(size_t size) { 1.18 + return size + (size >> 1); 1.19 +} 1.20 + 1.21 +/////////////////////////////////////////////////////////////////////////////// 1.22 + 1.23 +struct SkChunkAlloc::Block { 1.24 + Block* fNext; 1.25 + size_t fFreeSize; 1.26 + char* fFreePtr; 1.27 + // data[] follows 1.28 + 1.29 + char* startOfData() { 1.30 + return reinterpret_cast<char*>(this + 1); 1.31 + } 1.32 + 1.33 + static void FreeChain(Block* block) { 1.34 + while (block) { 1.35 + Block* next = block->fNext; 1.36 + sk_free(block); 1.37 + block = next; 1.38 + } 1.39 + }; 1.40 + 1.41 + bool contains(const void* addr) const { 1.42 + const char* ptr = reinterpret_cast<const char*>(addr); 1.43 + return ptr >= (const char*)(this + 1) && ptr < fFreePtr; 1.44 + } 1.45 +}; 1.46 + 1.47 +/////////////////////////////////////////////////////////////////////////////// 1.48 + 1.49 +SkChunkAlloc::SkChunkAlloc(size_t minSize) { 1.50 + if (minSize < MIN_CHUNKALLOC_BLOCK_SIZE) { 1.51 + minSize = MIN_CHUNKALLOC_BLOCK_SIZE; 1.52 + } 1.53 + 1.54 + fBlock = NULL; 1.55 + fMinSize = minSize; 1.56 + fChunkSize = fMinSize; 1.57 + fTotalCapacity = 0; 1.58 + fTotalUsed = 0; 1.59 + fBlockCount = 0; 1.60 +} 1.61 + 1.62 +SkChunkAlloc::~SkChunkAlloc() { 1.63 + this->reset(); 1.64 +} 1.65 + 1.66 +void SkChunkAlloc::reset() { 1.67 + Block::FreeChain(fBlock); 1.68 + fBlock = NULL; 1.69 + fChunkSize = fMinSize; // reset to our initial minSize 1.70 + fTotalCapacity = 0; 1.71 + fTotalUsed = 0; 1.72 + fBlockCount = 0; 1.73 +} 1.74 + 1.75 +SkChunkAlloc::Block* SkChunkAlloc::newBlock(size_t bytes, AllocFailType ftype) { 1.76 + size_t size = bytes; 1.77 + if (size < fChunkSize) { 1.78 + size = fChunkSize; 1.79 + } 1.80 + 1.81 + Block* block = (Block*)sk_malloc_flags(sizeof(Block) + size, 1.82 + ftype == kThrow_AllocFailType ? SK_MALLOC_THROW : 0); 1.83 + 1.84 + if (block) { 1.85 + // block->fNext = fBlock; 1.86 + block->fFreeSize = size; 1.87 + block->fFreePtr = block->startOfData(); 1.88 + 1.89 + fTotalCapacity += size; 1.90 + fBlockCount += 1; 1.91 + 1.92 + fChunkSize = increase_next_size(fChunkSize); 1.93 + } 1.94 + return block; 1.95 +} 1.96 + 1.97 +void* SkChunkAlloc::alloc(size_t bytes, AllocFailType ftype) { 1.98 + fTotalUsed += bytes; 1.99 + 1.100 + bytes = SkAlign4(bytes); 1.101 + 1.102 + Block* block = fBlock; 1.103 + 1.104 + if (block == NULL || bytes > block->fFreeSize) { 1.105 + block = this->newBlock(bytes, ftype); 1.106 + if (NULL == block) { 1.107 + return NULL; 1.108 + } 1.109 + block->fNext = fBlock; 1.110 + fBlock = block; 1.111 + } 1.112 + 1.113 + SkASSERT(block && bytes <= block->fFreeSize); 1.114 + char* ptr = block->fFreePtr; 1.115 + 1.116 + block->fFreeSize -= bytes; 1.117 + block->fFreePtr = ptr + bytes; 1.118 + return ptr; 1.119 +} 1.120 + 1.121 +size_t SkChunkAlloc::unalloc(void* ptr) { 1.122 + size_t bytes = 0; 1.123 + Block* block = fBlock; 1.124 + if (block) { 1.125 + char* cPtr = reinterpret_cast<char*>(ptr); 1.126 + char* start = block->startOfData(); 1.127 + if (start <= cPtr && cPtr < block->fFreePtr) { 1.128 + bytes = block->fFreePtr - cPtr; 1.129 + block->fFreeSize += bytes; 1.130 + block->fFreePtr = cPtr; 1.131 + } 1.132 + } 1.133 + return bytes; 1.134 +} 1.135 + 1.136 +bool SkChunkAlloc::contains(const void* addr) const { 1.137 + const Block* block = fBlock; 1.138 + while (block) { 1.139 + if (block->contains(addr)) { 1.140 + return true; 1.141 + } 1.142 + block = block->fNext; 1.143 + } 1.144 + return false; 1.145 +}