OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2012 Google Inc. | 2 * Copyright 2012 Google Inc. |
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 "GrMemoryPool.h" | 8 #include "GrMemoryPool.h" |
9 | 9 |
10 #ifdef SK_DEBUG | 10 #ifdef SK_DEBUG |
11 #define VALIDATE this->validate() | 11 #define VALIDATE this->validate() |
12 #else | 12 #else |
13 #define VALIDATE | 13 #define VALIDATE |
14 #endif | 14 #endif |
15 | 15 |
| 16 constexpr size_t GrMemoryPool::kSmallestMinAllocSize; |
| 17 |
16 GrMemoryPool::GrMemoryPool(size_t preallocSize, size_t minAllocSize) { | 18 GrMemoryPool::GrMemoryPool(size_t preallocSize, size_t minAllocSize) { |
17 SkDEBUGCODE(fAllocationCnt = 0); | 19 SkDEBUGCODE(fAllocationCnt = 0); |
18 SkDEBUGCODE(fAllocBlockCnt = 0); | 20 SkDEBUGCODE(fAllocBlockCnt = 0); |
19 | 21 |
20 minAllocSize = SkTMax<size_t>(minAllocSize, 1 << 10); | 22 minAllocSize = SkTMax<size_t>(GrSizeAlignUp(minAllocSize, kAlignment), kSmal
lestMinAllocSize); |
21 fMinAllocSize = GrSizeAlignUp(minAllocSize + kPerAllocPad, kAlignment); | 23 preallocSize = SkTMax<size_t>(GrSizeAlignUp(preallocSize, kAlignment), minAl
locSize); |
22 fPreallocSize = GrSizeAlignUp(preallocSize + kPerAllocPad, kAlignment); | 24 |
23 fPreallocSize = SkTMax(fPreallocSize, fMinAllocSize); | 25 fMinAllocSize = minAllocSize; |
24 fSize = 0; | 26 fSize = 0; |
25 | 27 |
26 fHead = CreateBlock(fPreallocSize); | 28 fHead = CreateBlock(preallocSize); |
27 fTail = fHead; | 29 fTail = fHead; |
28 fHead->fNext = nullptr; | 30 fHead->fNext = nullptr; |
29 fHead->fPrev = nullptr; | 31 fHead->fPrev = nullptr; |
30 VALIDATE; | 32 VALIDATE; |
31 }; | 33 }; |
32 | 34 |
33 GrMemoryPool::~GrMemoryPool() { | 35 GrMemoryPool::~GrMemoryPool() { |
34 VALIDATE; | 36 VALIDATE; |
35 SkASSERT(0 == fAllocationCnt); | 37 SkASSERT(0 == fAllocationCnt); |
36 SkASSERT(fHead == fTail); | 38 SkASSERT(fHead == fTail); |
37 SkASSERT(0 == fHead->fLiveCount); | 39 SkASSERT(0 == fHead->fLiveCount); |
38 DeleteBlock(fHead); | 40 DeleteBlock(fHead); |
39 }; | 41 }; |
40 | 42 |
41 void* GrMemoryPool::allocate(size_t size) { | 43 void* GrMemoryPool::allocate(size_t size) { |
42 VALIDATE; | 44 VALIDATE; |
43 size += kPerAllocPad; | 45 size += kPerAllocPad; |
44 size = GrSizeAlignUp(size, kAlignment); | 46 size = GrSizeAlignUp(size, kAlignment); |
45 if (fTail->fFreeSize < size) { | 47 if (fTail->fFreeSize < size) { |
46 size_t blockSize = size; | 48 size_t blockSize = size + kHeaderSize; |
47 blockSize = SkTMax<size_t>(blockSize, fMinAllocSize); | 49 blockSize = SkTMax<size_t>(blockSize, fMinAllocSize); |
48 BlockHeader* block = CreateBlock(blockSize); | 50 BlockHeader* block = CreateBlock(blockSize); |
49 | 51 |
50 block->fPrev = fTail; | 52 block->fPrev = fTail; |
51 block->fNext = nullptr; | 53 block->fNext = nullptr; |
52 SkASSERT(nullptr == fTail->fNext); | 54 SkASSERT(nullptr == fTail->fNext); |
53 fTail->fNext = block; | 55 fTail->fNext = block; |
54 fTail = block; | 56 fTail = block; |
55 fSize += block->fSize; | 57 fSize += block->fSize; |
56 SkDEBUGCODE(++fAllocBlockCnt); | 58 SkDEBUGCODE(++fAllocBlockCnt); |
(...skipping 23 matching lines...) Expand all Loading... |
80 AllocHeader* allocData = reinterpret_cast<AllocHeader*>(ptr); | 82 AllocHeader* allocData = reinterpret_cast<AllocHeader*>(ptr); |
81 SkASSERT(kAssignedMarker == allocData->fSentinal); | 83 SkASSERT(kAssignedMarker == allocData->fSentinal); |
82 SkDEBUGCODE(allocData->fSentinal = kFreedMarker); | 84 SkDEBUGCODE(allocData->fSentinal = kFreedMarker); |
83 BlockHeader* block = allocData->fHeader; | 85 BlockHeader* block = allocData->fHeader; |
84 SkASSERT(kAssignedMarker == block->fBlockSentinal); | 86 SkASSERT(kAssignedMarker == block->fBlockSentinal); |
85 if (1 == block->fLiveCount) { | 87 if (1 == block->fLiveCount) { |
86 // the head block is special, it is reset rather than deleted | 88 // the head block is special, it is reset rather than deleted |
87 if (fHead == block) { | 89 if (fHead == block) { |
88 fHead->fCurrPtr = reinterpret_cast<intptr_t>(fHead) + kHeaderSize; | 90 fHead->fCurrPtr = reinterpret_cast<intptr_t>(fHead) + kHeaderSize; |
89 fHead->fLiveCount = 0; | 91 fHead->fLiveCount = 0; |
90 fHead->fFreeSize = fPreallocSize; | 92 fHead->fFreeSize = fHead->fSize - kHeaderSize; |
91 } else { | 93 } else { |
92 BlockHeader* prev = block->fPrev; | 94 BlockHeader* prev = block->fPrev; |
93 BlockHeader* next = block->fNext; | 95 BlockHeader* next = block->fNext; |
94 SkASSERT(prev); | 96 SkASSERT(prev); |
95 prev->fNext = next; | 97 prev->fNext = next; |
96 if (next) { | 98 if (next) { |
97 next->fPrev = prev; | 99 next->fPrev = prev; |
98 } else { | 100 } else { |
99 SkASSERT(fTail == block); | 101 SkASSERT(fTail == block); |
100 fTail = prev; | 102 fTail = prev; |
101 } | 103 } |
102 fSize -= block->fSize; | 104 fSize -= block->fSize; |
103 DeleteBlock(block); | 105 DeleteBlock(block); |
104 SkDEBUGCODE(fAllocBlockCnt--); | 106 SkDEBUGCODE(fAllocBlockCnt--); |
105 } | 107 } |
106 } else { | 108 } else { |
107 --block->fLiveCount; | 109 --block->fLiveCount; |
108 // Trivial reclaim: if we're releasing the most recent allocation, reuse
it | 110 // Trivial reclaim: if we're releasing the most recent allocation, reuse
it |
109 if (block->fPrevPtr == ptr) { | 111 if (block->fPrevPtr == ptr) { |
110 block->fFreeSize += (block->fCurrPtr - block->fPrevPtr); | 112 block->fFreeSize += (block->fCurrPtr - block->fPrevPtr); |
111 block->fCurrPtr = block->fPrevPtr; | 113 block->fCurrPtr = block->fPrevPtr; |
112 } | 114 } |
113 } | 115 } |
114 SkDEBUGCODE(--fAllocationCnt); | 116 SkDEBUGCODE(--fAllocationCnt); |
115 VALIDATE; | 117 VALIDATE; |
116 } | 118 } |
117 | 119 |
118 GrMemoryPool::BlockHeader* GrMemoryPool::CreateBlock(size_t size) { | 120 GrMemoryPool::BlockHeader* GrMemoryPool::CreateBlock(size_t blockSize) { |
119 size_t paddedSize = size + kHeaderSize; | 121 blockSize = SkTMax<size_t>(blockSize, kHeaderSize); |
120 BlockHeader* block = | 122 BlockHeader* block = |
121 reinterpret_cast<BlockHeader*>(sk_malloc_throw(paddedSize)); | 123 reinterpret_cast<BlockHeader*>(sk_malloc_throw(blockSize)); |
122 // we assume malloc gives us aligned memory | 124 // we assume malloc gives us aligned memory |
123 SkASSERT(!(reinterpret_cast<intptr_t>(block) % kAlignment)); | 125 SkASSERT(!(reinterpret_cast<intptr_t>(block) % kAlignment)); |
124 SkDEBUGCODE(block->fBlockSentinal = kAssignedMarker); | 126 SkDEBUGCODE(block->fBlockSentinal = kAssignedMarker); |
125 block->fLiveCount = 0; | 127 block->fLiveCount = 0; |
126 block->fFreeSize = size; | 128 block->fFreeSize = blockSize - kHeaderSize; |
127 block->fCurrPtr = reinterpret_cast<intptr_t>(block) + kHeaderSize; | 129 block->fCurrPtr = reinterpret_cast<intptr_t>(block) + kHeaderSize; |
128 block->fPrevPtr = 0; // gcc warns on assigning nullptr to an intptr_t. | 130 block->fPrevPtr = 0; // gcc warns on assigning nullptr to an intptr_t. |
129 block->fSize = paddedSize; | 131 block->fSize = blockSize; |
130 return block; | 132 return block; |
131 } | 133 } |
132 | 134 |
133 void GrMemoryPool::DeleteBlock(BlockHeader* block) { | 135 void GrMemoryPool::DeleteBlock(BlockHeader* block) { |
134 SkASSERT(kAssignedMarker == block->fBlockSentinal); | 136 SkASSERT(kAssignedMarker == block->fBlockSentinal); |
135 SkDEBUGCODE(block->fBlockSentinal = kFreedMarker); // FWIW | 137 SkDEBUGCODE(block->fBlockSentinal = kFreedMarker); // FWIW |
136 sk_free(block); | 138 sk_free(block); |
137 } | 139 } |
138 | 140 |
139 void GrMemoryPool::validate() { | 141 void GrMemoryPool::validate() { |
140 #ifdef SK_DEBUG | 142 #ifdef SK_DEBUG |
141 BlockHeader* block = fHead; | 143 BlockHeader* block = fHead; |
142 BlockHeader* prev = nullptr; | 144 BlockHeader* prev = nullptr; |
143 SkASSERT(block); | 145 SkASSERT(block); |
144 int allocCount = 0; | 146 int allocCount = 0; |
145 do { | 147 do { |
146 SkASSERT(kAssignedMarker == block->fBlockSentinal); | 148 SkASSERT(kAssignedMarker == block->fBlockSentinal); |
147 allocCount += block->fLiveCount; | 149 allocCount += block->fLiveCount; |
148 SkASSERT(prev == block->fPrev); | 150 SkASSERT(prev == block->fPrev); |
149 if (prev) { | 151 if (prev) { |
150 SkASSERT(prev->fNext == block); | 152 SkASSERT(prev->fNext == block); |
151 } | 153 } |
152 | 154 |
153 intptr_t b = reinterpret_cast<intptr_t>(block); | 155 intptr_t b = reinterpret_cast<intptr_t>(block); |
154 size_t ptrOffset = block->fCurrPtr - b; | 156 size_t ptrOffset = block->fCurrPtr - b; |
155 size_t totalSize = ptrOffset + block->fFreeSize; | 157 size_t totalSize = ptrOffset + block->fFreeSize; |
156 size_t userSize = totalSize - kHeaderSize; | |
157 intptr_t userStart = b + kHeaderSize; | 158 intptr_t userStart = b + kHeaderSize; |
158 | 159 |
159 SkASSERT(!(b % kAlignment)); | 160 SkASSERT(!(b % kAlignment)); |
160 SkASSERT(!(totalSize % kAlignment)); | 161 SkASSERT(!(totalSize % kAlignment)); |
161 SkASSERT(!(userSize % kAlignment)); | |
162 SkASSERT(!(block->fCurrPtr % kAlignment)); | 162 SkASSERT(!(block->fCurrPtr % kAlignment)); |
163 if (fHead != block) { | 163 if (fHead != block) { |
164 SkASSERT(block->fLiveCount); | 164 SkASSERT(block->fLiveCount); |
165 SkASSERT(userSize >= fMinAllocSize); | 165 SkASSERT(totalSize >= fMinAllocSize); |
166 } else { | 166 } else { |
167 SkASSERT(userSize == fPreallocSize); | 167 SkASSERT(totalSize == block->fSize); |
168 } | 168 } |
169 if (!block->fLiveCount) { | 169 if (!block->fLiveCount) { |
170 SkASSERT(ptrOffset == kHeaderSize); | 170 SkASSERT(ptrOffset == kHeaderSize); |
171 SkASSERT(userStart == block->fCurrPtr); | 171 SkASSERT(userStart == block->fCurrPtr); |
172 } else { | 172 } else { |
173 AllocHeader* allocData = reinterpret_cast<AllocHeader*>(userStart); | 173 AllocHeader* allocData = reinterpret_cast<AllocHeader*>(userStart); |
174 SkASSERT(allocData->fSentinal == kAssignedMarker || | 174 SkASSERT(allocData->fSentinal == kAssignedMarker || |
175 allocData->fSentinal == kFreedMarker); | 175 allocData->fSentinal == kFreedMarker); |
176 SkASSERT(block == allocData->fHeader); | 176 SkASSERT(block == allocData->fHeader); |
177 } | 177 } |
178 | 178 |
179 prev = block; | 179 prev = block; |
180 } while ((block = block->fNext)); | 180 } while ((block = block->fNext)); |
181 SkASSERT(allocCount == fAllocationCnt); | 181 SkASSERT(allocCount == fAllocationCnt); |
182 SkASSERT(prev == fTail); | 182 SkASSERT(prev == fTail); |
183 SkASSERT(fAllocBlockCnt != 0 || fSize == 0); | 183 SkASSERT(fAllocBlockCnt != 0 || fSize == 0); |
184 #endif | 184 #endif |
185 } | 185 } |
OLD | NEW |