GrMemoryPool always standard_layout for offsetof
GrMemoryPool in debug has extra fields and so wants to make use of offsetof. The offsetof can only be taken on standard layout objects. However, in debug std::unique_ptr may not be standard layout, which makes SkAutoTArray not standard layout, which makes SkTHashTable not standard layout, which makes SkTHashSet not standard layout, which makes GrMemoryPool not standard layout, producing a compile error. Since this is debug only, move the debug only fields behind a pointer (which unfortunately cannot be a std::unique_ptr, since it may not be standard layout). This allows building with recent libc++ headers and clang. Change-Id: Id9d312d7939808399d0796428de218d30263c26f Reviewed-on: https://skia-review.googlesource.com/c/skia/+/482004 Reviewed-by: Michael Ludwig <michaelludwig@google.com> Commit-Queue: Ben Wagner <bungeman@google.com>
This commit is contained in:
parent
b05732e102
commit
15f186d277
@ -32,20 +32,24 @@ std::unique_ptr<GrMemoryPool> GrMemoryPool::Make(size_t preallocSize, size_t min
|
||||
GrMemoryPool::GrMemoryPool(size_t preallocSize, size_t minAllocSize)
|
||||
: fAllocator(SkBlockAllocator::GrowthPolicy::kFixed, minAllocSize,
|
||||
preallocSize - offsetof(GrMemoryPool, fAllocator) - sizeof(SkBlockAllocator)) {
|
||||
SkDEBUGCODE(fAllocationCount = 0;)
|
||||
SkDEBUGCODE(
|
||||
fDebug = new Debug;
|
||||
fDebug->fAllocationCount = 0;
|
||||
)
|
||||
}
|
||||
|
||||
GrMemoryPool::~GrMemoryPool() {
|
||||
this->reportLeaks();
|
||||
SkASSERT(0 == fAllocationCount);
|
||||
SkASSERT(0 == fDebug->fAllocationCount);
|
||||
SkASSERT(this->isEmpty());
|
||||
SkDEBUGCODE(delete fDebug;)
|
||||
}
|
||||
|
||||
void GrMemoryPool::reportLeaks() const {
|
||||
#ifdef SK_DEBUG
|
||||
int i = 0;
|
||||
int n = fAllocatedIDs.count();
|
||||
for (int id : fAllocatedIDs) {
|
||||
int n = fDebug->fAllocatedIDs.count();
|
||||
for (int id : fDebug->fAllocatedIDs) {
|
||||
if (++i == 1) {
|
||||
SkDebugf("Leaked %d IDs (in no particular order): %d%s", n, id, (n == i) ? "\n" : "");
|
||||
} else if (i < 11) {
|
||||
@ -85,8 +89,8 @@ void* GrMemoryPool::allocate(size_t size) {
|
||||
}();
|
||||
|
||||
// You can set a breakpoint here when a leaked ID is allocated to see the stack frame.
|
||||
fAllocatedIDs.add(header->fID);
|
||||
fAllocationCount++;
|
||||
fDebug->fAllocatedIDs.add(header->fID);
|
||||
fDebug->fAllocationCount++;
|
||||
#endif
|
||||
|
||||
// User-facing pointer is after the header padding
|
||||
@ -104,8 +108,8 @@ void GrMemoryPool::release(void* p) {
|
||||
#endif
|
||||
|
||||
#if defined(SK_DEBUG)
|
||||
fAllocatedIDs.remove(header->fID);
|
||||
fAllocationCount--;
|
||||
fDebug->fAllocatedIDs.remove(header->fID);
|
||||
fDebug->fAllocationCount--;
|
||||
#endif
|
||||
|
||||
SkBlockAllocator::Block* block = fAllocator.owningBlock<kAlignment>(header, header->fStart);
|
||||
@ -138,8 +142,8 @@ void GrMemoryPool::validate() const {
|
||||
for (const auto* b : fAllocator.blocks()) {
|
||||
allocCount += b->metadata();
|
||||
}
|
||||
SkASSERT(allocCount == fAllocationCount);
|
||||
SkASSERT(fAllocationCount == fAllocatedIDs.count());
|
||||
SkASSERT(allocCount == fDebug->fAllocationCount);
|
||||
SkASSERT(fDebug->fAllocationCount == fDebug->fAllocatedIDs.count());
|
||||
SkASSERT(allocCount > 0 || this->isEmpty());
|
||||
}
|
||||
#endif
|
||||
|
@ -88,6 +88,7 @@ public:
|
||||
*/
|
||||
size_t preallocSize() const {
|
||||
// Account for the debug-only fields in this count, the offset is 0 for release builds
|
||||
static_assert(std::is_standard_layout<GrMemoryPool>::value, "");
|
||||
return offsetof(GrMemoryPool, fAllocator) + fAllocator.preallocSize();
|
||||
}
|
||||
|
||||
@ -119,8 +120,14 @@ private:
|
||||
GrMemoryPool(size_t preallocSize, size_t minAllocSize);
|
||||
|
||||
#ifdef SK_DEBUG
|
||||
SkTHashSet<int> fAllocatedIDs;
|
||||
int fAllocationCount;
|
||||
// Because this exists preallocSize wants to use offsetof, so keep GrMemoryPool standard layout
|
||||
// without depending on SkTHashSet being standard layout. Note that std::unique_ptr may not be
|
||||
// standard layout.
|
||||
struct Debug{
|
||||
SkTHashSet<int> fAllocatedIDs;
|
||||
int fAllocationCount;
|
||||
};
|
||||
Debug* fDebug{nullptr};
|
||||
#endif
|
||||
|
||||
SkBlockAllocator fAllocator; // Must be the last field, in order to use extra allocated space
|
||||
|
Loading…
Reference in New Issue
Block a user