OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2006 The Android Open Source Project | 2 * Copyright 2006 The Android Open Source Project |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "SkChunkAlloc.h" | 8 #include "SkChunkAlloc.h" |
9 | 9 |
10 // Don't malloc any chunks smaller than this | 10 // Don't malloc any chunks smaller than this |
11 #define MIN_CHUNKALLOC_BLOCK_SIZE 1024 | 11 #define MIN_CHUNKALLOC_BLOCK_SIZE 1024 |
12 | 12 |
13 // Return the new min blocksize given the current value | 13 // Return the new min blocksize given the current value |
14 static size_t increase_next_size(size_t size) { | 14 static size_t increase_next_size(size_t size) { |
15 return size + (size >> 1); | 15 return size + (size >> 1); |
16 } | 16 } |
17 | 17 |
18 /////////////////////////////////////////////////////////////////////////////// | 18 /////////////////////////////////////////////////////////////////////////////// |
19 | 19 |
20 struct SkChunkAlloc::Block { | 20 struct SkChunkAlloc::Block { |
21 Block* fNext; | 21 Block* fNext; |
22 size_t fFreeSize; | 22 size_t fFreeSize; |
23 char* fFreePtr; | 23 char* fFreePtr; |
24 // data[] follows | 24 // data[] follows |
25 | 25 |
26 size_t blockSize() { | 26 size_t blockSize() const { |
27 char* start = this->startOfData(); | 27 char* start = this->startOfData(); |
28 size_t bytes = fFreePtr - start; | 28 size_t bytes = fFreePtr - start; |
29 return fFreeSize + bytes; | 29 return fFreeSize + bytes; |
30 } | 30 } |
31 | 31 |
32 void reset() { | 32 void reset() { |
33 fNext = nullptr; | 33 fNext = nullptr; |
34 fFreeSize = this->blockSize(); | 34 fFreeSize = this->blockSize(); |
35 fFreePtr = this->startOfData(); | 35 fFreePtr = this->startOfData(); |
36 } | 36 } |
37 | 37 |
38 char* startOfData() { | 38 char* startOfData() const { |
39 return reinterpret_cast<char*>(this + 1); | 39 return reinterpret_cast<char*>(SkAlign8(reinterpret_cast<size_t>(this +
1))); |
40 } | 40 } |
41 | 41 |
42 static void FreeChain(Block* block) { | 42 static void FreeChain(Block* block) { |
43 while (block) { | 43 while (block) { |
44 Block* next = block->fNext; | 44 Block* next = block->fNext; |
45 sk_free(block); | 45 sk_free(block); |
46 block = next; | 46 block = next; |
47 } | 47 } |
48 }; | 48 }; |
49 | 49 |
50 bool contains(const void* addr) const { | 50 bool contains(const void* addr) const { |
51 const char* ptr = reinterpret_cast<const char*>(addr); | 51 const char* ptr = reinterpret_cast<const char*>(addr); |
52 return ptr >= (const char*)(this + 1) && ptr < fFreePtr; | 52 return ptr >= this->startOfData() && ptr < fFreePtr; |
53 } | 53 } |
54 }; | 54 }; |
55 | 55 |
56 /////////////////////////////////////////////////////////////////////////////// | 56 /////////////////////////////////////////////////////////////////////////////// |
57 | 57 |
58 SkChunkAlloc::SkChunkAlloc(size_t minSize) { | 58 SkChunkAlloc::SkChunkAlloc(size_t minSize) { |
59 if (minSize < MIN_CHUNKALLOC_BLOCK_SIZE) { | 59 if (minSize < MIN_CHUNKALLOC_BLOCK_SIZE) { |
60 minSize = MIN_CHUNKALLOC_BLOCK_SIZE; | 60 minSize = MIN_CHUNKALLOC_BLOCK_SIZE; |
61 } | 61 } |
62 | 62 |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
114 SkDEBUGCODE(fTotalLost = 0;) | 114 SkDEBUGCODE(fTotalLost = 0;) |
115 SkDEBUGCODE(this->validate();) | 115 SkDEBUGCODE(this->validate();) |
116 } | 116 } |
117 | 117 |
118 SkChunkAlloc::Block* SkChunkAlloc::newBlock(size_t bytes, AllocFailType ftype) { | 118 SkChunkAlloc::Block* SkChunkAlloc::newBlock(size_t bytes, AllocFailType ftype) { |
119 size_t size = bytes; | 119 size_t size = bytes; |
120 if (size < fChunkSize) { | 120 if (size < fChunkSize) { |
121 size = fChunkSize; | 121 size = fChunkSize; |
122 } | 122 } |
123 | 123 |
124 Block* block = (Block*)sk_malloc_flags(sizeof(Block) + size, | 124 Block* block = (Block*)sk_malloc_flags(SkAlign8(sizeof(Block)) + size, |
125 ftype == kThrow_AllocFailType ? SK_MALLOC_THROW : 0); | 125 ftype == kThrow_AllocFailType ? SK_MALLOC_THROW : 0); |
126 | 126 |
127 if (block) { | 127 if (block) { |
128 block->fFreeSize = size; | 128 block->fFreeSize = size; |
129 block->fFreePtr = block->startOfData(); | 129 block->fFreePtr = block->startOfData(); |
130 | 130 |
131 fTotalCapacity += size; | 131 fTotalCapacity += size; |
132 SkDEBUGCODE(fBlockCount += 1;) | 132 SkDEBUGCODE(fBlockCount += 1;) |
133 | 133 |
134 fChunkSize = increase_next_size(fChunkSize); | 134 fChunkSize = increase_next_size(fChunkSize); |
135 } | 135 } |
136 return block; | 136 return block; |
137 } | 137 } |
138 | 138 |
139 SkChunkAlloc::Block* SkChunkAlloc::addBlockIfNecessary(size_t bytes, AllocFailTy
pe ftype) { | 139 SkChunkAlloc::Block* SkChunkAlloc::addBlockIfNecessary(size_t bytes, AllocFailTy
pe ftype) { |
140 SkASSERT(SkIsAlign4(bytes)); | 140 SkASSERT(SkIsAlign8(bytes)); |
141 | 141 |
142 if (!fBlock || bytes > fBlock->fFreeSize) { | 142 if (!fBlock || bytes > fBlock->fFreeSize) { |
143 Block* block = this->newBlock(bytes, ftype); | 143 Block* block = this->newBlock(bytes, ftype); |
144 if (!block) { | 144 if (!block) { |
145 return nullptr; | 145 return nullptr; |
146 } | 146 } |
147 #ifdef SK_DEBUG | 147 #ifdef SK_DEBUG |
148 if (fBlock) { | 148 if (fBlock) { |
149 fTotalLost += fBlock->fFreeSize; | 149 fTotalLost += fBlock->fFreeSize; |
150 } | 150 } |
151 #endif | 151 #endif |
152 block->fNext = fBlock; | 152 block->fNext = fBlock; |
153 fBlock = block; | 153 fBlock = block; |
154 } | 154 } |
155 | 155 |
156 SkASSERT(fBlock && bytes <= fBlock->fFreeSize); | 156 SkASSERT(fBlock && bytes <= fBlock->fFreeSize); |
157 return fBlock; | 157 return fBlock; |
158 } | 158 } |
159 | 159 |
160 void* SkChunkAlloc::alloc(size_t bytes, AllocFailType ftype) { | 160 void* SkChunkAlloc::alloc(size_t bytes, AllocFailType ftype) { |
161 SkDEBUGCODE(this->validate();) | 161 SkDEBUGCODE(this->validate();) |
162 | 162 |
163 bytes = SkAlign4(bytes); | 163 bytes = SkAlign8(bytes); |
164 | 164 |
165 Block* block = this->addBlockIfNecessary(bytes, ftype); | 165 Block* block = this->addBlockIfNecessary(bytes, ftype); |
166 if (!block) { | 166 if (!block) { |
167 return nullptr; | 167 return nullptr; |
168 } | 168 } |
169 | 169 |
170 char* ptr = block->fFreePtr; | 170 char* ptr = block->fFreePtr; |
171 | 171 |
172 fTotalUsed += bytes; | 172 fTotalUsed += bytes; |
173 block->fFreeSize -= bytes; | 173 block->fFreeSize -= bytes; |
174 block->fFreePtr = ptr + bytes; | 174 block->fFreePtr = ptr + bytes; |
175 SkDEBUGCODE(this->validate();) | 175 SkDEBUGCODE(this->validate();) |
| 176 SkASSERT(SkIsAlign8((size_t)ptr)); |
176 return ptr; | 177 return ptr; |
177 } | 178 } |
178 | 179 |
179 size_t SkChunkAlloc::unalloc(void* ptr) { | 180 size_t SkChunkAlloc::unalloc(void* ptr) { |
180 SkDEBUGCODE(this->validate();) | 181 SkDEBUGCODE(this->validate();) |
181 | 182 |
182 size_t bytes = 0; | 183 size_t bytes = 0; |
183 Block* block = fBlock; | 184 Block* block = fBlock; |
184 if (block) { | 185 if (block) { |
185 char* cPtr = reinterpret_cast<char*>(ptr); | 186 char* cPtr = reinterpret_cast<char*>(ptr); |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
225 } | 226 } |
226 } | 227 } |
227 | 228 |
228 SkASSERT(fBlockCount == numBlocks); | 229 SkASSERT(fBlockCount == numBlocks); |
229 SkASSERT(fTotalCapacity == totCapacity); | 230 SkASSERT(fTotalCapacity == totCapacity); |
230 SkASSERT(fTotalUsed == totUsed); | 231 SkASSERT(fTotalUsed == totUsed); |
231 SkASSERT(fTotalLost == totLost); | 232 SkASSERT(fTotalLost == totLost); |
232 SkASSERT(totCapacity == totUsed + totLost + totAvailable); | 233 SkASSERT(totCapacity == totUsed + totLost + totAvailable); |
233 } | 234 } |
234 #endif | 235 #endif |
OLD | NEW |