1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2012 Google Inc. 3cb93a386Sopenharmony_ci * 4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be 5cb93a386Sopenharmony_ci * found in the LICENSE file. 6cb93a386Sopenharmony_ci */ 7cb93a386Sopenharmony_ci 8cb93a386Sopenharmony_ci#ifndef GrMemoryPool_DEFINED 9cb93a386Sopenharmony_ci#define GrMemoryPool_DEFINED 10cb93a386Sopenharmony_ci 11cb93a386Sopenharmony_ci#include "src/core/SkBlockAllocator.h" 12cb93a386Sopenharmony_ci 13cb93a386Sopenharmony_ci#ifdef SK_DEBUG 14cb93a386Sopenharmony_ci#include "include/private/SkTHash.h" 15cb93a386Sopenharmony_ci#endif 16cb93a386Sopenharmony_ci 17cb93a386Sopenharmony_ci/** 18cb93a386Sopenharmony_ci * Allocates memory in blocks and parcels out space in the blocks for allocation requests. It is 19cb93a386Sopenharmony_ci * optimized for allocate / release speed over memory efficiency. The interface is designed to be 20cb93a386Sopenharmony_ci * used to implement operator new and delete overrides. All allocations are expected to be released 21cb93a386Sopenharmony_ci * before the pool's destructor is called. Allocations will be aligned to sizeof(std::max_align_t). 22cb93a386Sopenharmony_ci * 23cb93a386Sopenharmony_ci * All allocated objects must be released back to the memory pool before it can be destroyed. 24cb93a386Sopenharmony_ci */ 25cb93a386Sopenharmony_ciclass GrMemoryPool { 26cb93a386Sopenharmony_cipublic: 27cb93a386Sopenharmony_ci#ifdef SK_FORCE_8_BYTE_ALIGNMENT 28cb93a386Sopenharmony_ci // https://github.com/emscripten-core/emscripten/issues/10072 29cb93a386Sopenharmony_ci // Since Skia does not use "long double" (16 bytes), we should be ok to force it back to 8 bytes 30cb93a386Sopenharmony_ci // until emscripten is fixed. 31cb93a386Sopenharmony_ci inline static constexpr size_t kAlignment = 8; 32cb93a386Sopenharmony_ci#else 33cb93a386Sopenharmony_ci // Guaranteed alignment of pointer returned by allocate(). 34cb93a386Sopenharmony_ci inline static constexpr size_t kAlignment = alignof(std::max_align_t); 35cb93a386Sopenharmony_ci#endif 36cb93a386Sopenharmony_ci 37cb93a386Sopenharmony_ci // Smallest block size allocated on the heap (not the smallest reservation via allocate()). 38cb93a386Sopenharmony_ci inline static constexpr size_t kMinAllocationSize = 1 << 10; 39cb93a386Sopenharmony_ci 40cb93a386Sopenharmony_ci /** 41cb93a386Sopenharmony_ci * Prealloc size is the amount of space to allocate at pool creation 42cb93a386Sopenharmony_ci * time and keep around until pool destruction. The min alloc size is 43cb93a386Sopenharmony_ci * the smallest allowed size of additional allocations. Both sizes are 44cb93a386Sopenharmony_ci * adjusted to ensure that they are at least as large as kMinAllocationSize 45cb93a386Sopenharmony_ci * and less than SkBlockAllocator::kMaxAllocationSize. 46cb93a386Sopenharmony_ci * 47cb93a386Sopenharmony_ci * Both sizes are what the pool will end up allocating from the system, and 48cb93a386Sopenharmony_ci * portions of the allocated memory is used for internal bookkeeping. 49cb93a386Sopenharmony_ci */ 50cb93a386Sopenharmony_ci static std::unique_ptr<GrMemoryPool> Make(size_t preallocSize, size_t minAllocSize); 51cb93a386Sopenharmony_ci 52cb93a386Sopenharmony_ci ~GrMemoryPool(); 53cb93a386Sopenharmony_ci void operator delete(void* p) { ::operator delete(p); } 54cb93a386Sopenharmony_ci 55cb93a386Sopenharmony_ci /** 56cb93a386Sopenharmony_ci * Allocates memory. The memory must be freed with release() before the GrMemoryPool is deleted. 57cb93a386Sopenharmony_ci */ 58cb93a386Sopenharmony_ci void* allocate(size_t size); 59cb93a386Sopenharmony_ci /** 60cb93a386Sopenharmony_ci * p must have been returned by allocate(). 61cb93a386Sopenharmony_ci */ 62cb93a386Sopenharmony_ci void release(void* p); 63cb93a386Sopenharmony_ci 64cb93a386Sopenharmony_ci /** 65cb93a386Sopenharmony_ci * Returns true if there are no unreleased allocations. 66cb93a386Sopenharmony_ci */ 67cb93a386Sopenharmony_ci bool isEmpty() const { 68cb93a386Sopenharmony_ci // If size is the same as preallocSize, there aren't any heap blocks, so currentBlock() 69cb93a386Sopenharmony_ci // is the inline head block. 70cb93a386Sopenharmony_ci return fAllocator.currentBlock() == fAllocator.headBlock() && 71cb93a386Sopenharmony_ci fAllocator.currentBlock()->metadata() == 0; 72cb93a386Sopenharmony_ci } 73cb93a386Sopenharmony_ci 74cb93a386Sopenharmony_ci /** 75cb93a386Sopenharmony_ci * In debug mode, this reports the IDs of unfreed nodes via `SkDebugf`. This reporting is also 76cb93a386Sopenharmony_ci * performed automatically whenever a GrMemoryPool is destroyed. 77cb93a386Sopenharmony_ci * In release mode, this method is a no-op. 78cb93a386Sopenharmony_ci */ 79cb93a386Sopenharmony_ci void reportLeaks() const; 80cb93a386Sopenharmony_ci 81cb93a386Sopenharmony_ci /** 82cb93a386Sopenharmony_ci * Returns the total allocated size of the GrMemoryPool minus any preallocated amount 83cb93a386Sopenharmony_ci */ 84cb93a386Sopenharmony_ci size_t size() const { return fAllocator.totalSize() - fAllocator.preallocSize(); } 85cb93a386Sopenharmony_ci 86cb93a386Sopenharmony_ci /** 87cb93a386Sopenharmony_ci * Returns the preallocated size of the GrMemoryPool 88cb93a386Sopenharmony_ci */ 89cb93a386Sopenharmony_ci size_t preallocSize() const { 90cb93a386Sopenharmony_ci // Account for the debug-only fields in this count, the offset is 0 for release builds 91cb93a386Sopenharmony_ci return offsetof(GrMemoryPool, fAllocator) + fAllocator.preallocSize(); 92cb93a386Sopenharmony_ci } 93cb93a386Sopenharmony_ci 94cb93a386Sopenharmony_ci /** 95cb93a386Sopenharmony_ci * Frees any scratch blocks that are no longer being used. 96cb93a386Sopenharmony_ci */ 97cb93a386Sopenharmony_ci void resetScratchSpace() { 98cb93a386Sopenharmony_ci fAllocator.resetScratchSpace(); 99cb93a386Sopenharmony_ci } 100cb93a386Sopenharmony_ci 101cb93a386Sopenharmony_ci#ifdef SK_DEBUG 102cb93a386Sopenharmony_ci void validate() const; 103cb93a386Sopenharmony_ci#endif 104cb93a386Sopenharmony_ci 105cb93a386Sopenharmony_ciprivate: 106cb93a386Sopenharmony_ci // Per-allocation overhead so that GrMemoryPool can always identify the block owning each and 107cb93a386Sopenharmony_ci // release all occupied bytes, including any resulting from alignment padding. 108cb93a386Sopenharmony_ci struct Header { 109cb93a386Sopenharmony_ci int fStart; 110cb93a386Sopenharmony_ci int fEnd; 111cb93a386Sopenharmony_ci#if defined(SK_DEBUG) 112cb93a386Sopenharmony_ci int fID; // ID that can be used to track down leaks by clients. 113cb93a386Sopenharmony_ci#endif 114cb93a386Sopenharmony_ci#if defined(SK_DEBUG) || defined(SK_SANITIZE_ADDRESS) 115cb93a386Sopenharmony_ci int fSentinel; // set to a known value to check for memory stomping; poisoned in ASAN mode 116cb93a386Sopenharmony_ci#endif 117cb93a386Sopenharmony_ci }; 118cb93a386Sopenharmony_ci 119cb93a386Sopenharmony_ci GrMemoryPool(size_t preallocSize, size_t minAllocSize); 120cb93a386Sopenharmony_ci 121cb93a386Sopenharmony_ci#ifdef SK_DEBUG 122cb93a386Sopenharmony_ci SkTHashSet<int> fAllocatedIDs; 123cb93a386Sopenharmony_ci int fAllocationCount; 124cb93a386Sopenharmony_ci#endif 125cb93a386Sopenharmony_ci 126cb93a386Sopenharmony_ci SkBlockAllocator fAllocator; // Must be the last field, in order to use extra allocated space 127cb93a386Sopenharmony_ci}; 128cb93a386Sopenharmony_ci#endif 129