1fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/* 2fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Copyright 2016 Google Inc. 3fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * 4fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Use of this source code is governed by a BSD-style license that can be 5fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * found in the LICENSE file. 6fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot */ 7fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 8fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#ifndef SkArenaAlloc_DEFINED 9fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#define SkArenaAlloc_DEFINED 10fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 11fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkRefCnt.h" 12fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkTFitsIn.h" 13fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkTypes.h" 14fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include <cstddef> 15fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include <new> 16fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include <type_traits> 17fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include <utility> 18fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include <vector> 19fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 20fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// SkArenaAlloc allocates object and destroys the allocated objects when destroyed. It's designed 21fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// to minimize the number of underlying block allocations. SkArenaAlloc allocates first out of an 22fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// (optional) user-provided block of memory, and when that's exhausted it allocates on the heap, 23fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// starting with an allocation of extraSize bytes. If your data (plus a small overhead) fits in 24fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// the user-provided block, SkArenaAlloc never uses the heap, and if it fits in extraSize bytes, 25fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// it'll use the heap only once. If you pass extraSize = 0, it allocates blocks for each call to 26fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// make<T>. 27fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// 28fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// Examples: 29fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// 30fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// char block[mostCasesSize]; 31fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// SkArenaAlloc arena(block, almostAllCasesSize); 32fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// 33fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// If mostCasesSize is too large for the stack, you can use the following pattern. 34fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// 35fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// std::unique_ptr<char[]> block{new char[mostCasesSize]}; 36fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// SkArenaAlloc arena(block.get(), mostCasesSize, almostAllCasesSize); 37fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// 38fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// If the program only sometimes allocates memory, use the following. 39fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// 40fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// SkArenaAlloc arena(nullptr, 0, almostAllCasesSize); 41fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// 42fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// The storage does not necessarily need to be on the stack. Embedding the storage in a class also 43fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// works. 44fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// 45fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// class Foo { 46fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// char storage[mostCasesSize]; 47fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// SkArenaAlloc arena (storage, almostAllCasesSize); 48fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// }; 49fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// 50fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// In addition, the system is optimized to handle POD data including arrays of PODs (where 51fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// POD is really data with no destructors). For POD data it has zero overhead per item, and a 52fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// typical block overhead of 8 bytes. For non-POD objects there is a per item overhead of 4 bytes. 53fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// For arrays of non-POD objects there is a per array overhead of typically 8 bytes. There is an 54fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// addition overhead when switching from POD data to non-POD data of typically 8 bytes. 55fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// 56fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// You can track memory use by adding SkArenaAlloc::kTrack as the last parameter to any constructor. 57fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// 58fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// char storage[someNumber]; 59fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// SkArenaAlloc alloc{storage, SkArenaAlloc::kTrack}; 60fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// 61fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// This will print out a line for every destructor or reset call that has the total memory 62fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// allocated, the total slop (the unused portion of a block), and the slop of the last block. 63fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// 64fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// If additional blocks are needed they are increased exponentially. This strategy bounds the 65fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// recursion of the RunDtorsOnBlock to be limited to O(log size-of-memory). Block size grow using 66fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// the Fibonacci sequence which means that for 2^32 memory there are 48 allocations, and for 2^48 67fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// there are 71 allocations. 68fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotclass SkArenaAlloc { 69fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotpublic: 70fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot enum Tracking {kDontTrack, kTrack}; 71fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkArenaAlloc(char* block, size_t size, size_t, Tracking tracking = kDontTrack); 72fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 73fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkArenaAlloc(size_t extraSize, Tracking tracking = kDontTrack) 74fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot : SkArenaAlloc(nullptr, 0, extraSize, tracking) 75fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot {} 76fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 77fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ~SkArenaAlloc(); 78fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 79fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot template <typename T, typename... Args> 80fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot T* make(Args&&... args) { 81fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot uint32_t size = SkTo<uint32_t>(sizeof(T)); 82fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot uint32_t alignment = SkTo<uint32_t>(alignof(T)); 83fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot char* objStart; 84fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (skstd::is_trivially_destructible<T>::value) { 85fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot objStart = this->allocObject(size, alignment); 86fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fCursor = objStart + size; 87fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 88fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot objStart = this->allocObjectWithFooter(size + sizeof(Footer), alignment); 89fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Can never be UB because max value is alignof(T). 90fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot uint32_t padding = SkTo<uint32_t>(objStart - fCursor); 91fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 92fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Advance to end of object to install footer. 93fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fCursor = objStart + size; 94fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FooterAction* releaser = [](char* objEnd) { 95fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot char* objStart = objEnd - (sizeof(T) + sizeof(Footer)); 96fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ((T*)objStart)->~T(); 97fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return objStart; 98fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot }; 99fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->installFooter(releaser, padding); 100fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 101fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 102fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // This must be last to make objects with nested use of this allocator work. 103fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return new(objStart) T(std::forward<Args>(args)...); 104fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 105fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 106fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot template <typename T, typename... Args> 107fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot sk_sp<T> makeSkSp(Args&&... args) { 108fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(SkTFitsIn<uint32_t>(sizeof(T))); 109fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 110fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // The arena takes a ref for itself to account for the destructor. The sk_sp count can't 111fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // become zero or the sk_sp will try to call free on the pointer. 112fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return sk_sp<T>(SkRef(this->make<T>(std::forward<Args>(args)...))); 113fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 114fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 115fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot template <typename T> 116fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot T* makeArrayDefault(size_t count) { 117fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot uint32_t safeCount = SkTo<uint32_t>(count); 118fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot T* array = (T*)this->commonArrayAlloc<T>(safeCount); 119fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 120fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // If T is primitive then no initialization takes place. 121fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (size_t i = 0; i < safeCount; i++) { 122fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot new (&array[i]) T; 123fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 124fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return array; 125fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 126fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 127fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot template <typename T> 128fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot T* makeArray(size_t count) { 129fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot uint32_t safeCount = SkTo<uint32_t>(count); 130fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot T* array = (T*)this->commonArrayAlloc<T>(safeCount); 131fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 132fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // If T is primitive then the memory is initialized. For example, an array of chars will 133fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // be zeroed. 134fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (size_t i = 0; i < safeCount; i++) { 135fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot new (&array[i]) T(); 136fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 137fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return array; 138fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 139fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 140fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Destroy all allocated objects, free any heap allocations. 141fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void reset(); 142fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 143fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotprivate: 144fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot using Footer = int64_t; 145fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot using FooterAction = char* (char*); 146fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 147fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot static char* SkipPod(char* footerEnd); 148fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot static void RunDtorsOnBlock(char* footerEnd); 149fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot static char* NextBlock(char* footerEnd); 150fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 151fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void installFooter(FooterAction* releaser, uint32_t padding); 152fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void installUint32Footer(FooterAction* action, uint32_t value, uint32_t padding); 153fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void installPtrFooter(FooterAction* action, char* ptr, uint32_t padding); 154fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 155fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void ensureSpace(uint32_t size, uint32_t alignment); 156fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 157fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot char* allocObject(uint32_t size, uint32_t alignment) { 158fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot uintptr_t mask = alignment - 1; 159fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot uintptr_t alignedOffset = (~reinterpret_cast<uintptr_t>(fCursor) + 1) & mask; 160fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot uintptr_t totalSize = size + alignedOffset; 161fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (totalSize < size) { 162fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SK_ABORT("The total size of allocation overflowed uintptr_t."); 163fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 164fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (totalSize > static_cast<uintptr_t>(fEnd - fCursor)) { 165fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->ensureSpace(size, alignment); 166fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot alignedOffset = (~reinterpret_cast<uintptr_t>(fCursor) + 1) & mask; 167fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 168fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return fCursor + alignedOffset; 169fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 170fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 171fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot char* allocObjectWithFooter(uint32_t sizeIncludingFooter, uint32_t alignment); 172fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 173fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot template <typename T> 174fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot char* commonArrayAlloc(uint32_t count) { 175fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot char* objStart; 176fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT_RELEASE(count <= std::numeric_limits<uint32_t>::max() / sizeof(T)); 177fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot uint32_t arraySize = SkTo<uint32_t>(count * sizeof(T)); 178fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot uint32_t alignment = SkTo<uint32_t>(alignof(T)); 179fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 180fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (skstd::is_trivially_destructible<T>::value) { 181fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot objStart = this->allocObject(arraySize, alignment); 182fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fCursor = objStart + arraySize; 183fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 184fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot constexpr uint32_t overhead = sizeof(Footer) + sizeof(uint32_t); 185fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT_RELEASE(arraySize <= std::numeric_limits<uint32_t>::max() - overhead); 186fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot uint32_t totalSize = arraySize + overhead; 187fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot objStart = this->allocObjectWithFooter(totalSize, alignment); 188fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 189fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Can never be UB because max value is alignof(T). 190fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot uint32_t padding = SkTo<uint32_t>(objStart - fCursor); 191fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 192fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Advance to end of array to install footer.? 193fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fCursor = objStart + arraySize; 194fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->installUint32Footer( 195fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot [](char* footerEnd) { 196fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot char* objEnd = footerEnd - (sizeof(Footer) + sizeof(uint32_t)); 197fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot uint32_t count; 198fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot memmove(&count, objEnd, sizeof(uint32_t)); 199fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot char* objStart = objEnd - count * sizeof(T); 200fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot T* array = (T*) objStart; 201fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (uint32_t i = 0; i < count; i++) { 202fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot array[i].~T(); 203fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 204fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return objStart; 205fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot }, 206fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkTo<uint32_t>(count), 207fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot padding); 208fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 209fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 210fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return objStart; 211fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 212fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 213fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot char* fDtorCursor; 214fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot char* fCursor; 215fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot char* fEnd; 216fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot char* const fFirstBlock; 217fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const uint32_t fFirstSize; 218fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const uint32_t fExtraSize; 219fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 220fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Track some useful stats. Track stats if fTotalSlop is >= 0; 221fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot uint32_t fTotalAlloc { 0}; 222fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int32_t fTotalSlop {-1}; 223fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 224fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Use the Fibonacci sequence as the growth factor for block size. The size of the block 225fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // allocated is fFib0 * fExtraSize. Using 2 ^ n * fExtraSize had too much slop for Android. 226fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot uint32_t fFib0 {1}, fFib1 {1}; 227fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}; 228fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 229fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// Helper for defining allocators with inline/reserved storage. 230fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// For argument declarations, stick to the base type (SkArenaAlloc). 231fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robottemplate <size_t InlineStorageSize> 232fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotclass SkSTArenaAlloc : public SkArenaAlloc { 233fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotpublic: 234fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot explicit SkSTArenaAlloc(size_t extraSize = InlineStorageSize, Tracking tracking = kDontTrack) 235fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot : INHERITED(fInlineStorage, InlineStorageSize, extraSize, tracking) {} 236fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 237fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotprivate: 238fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot char fInlineStorage[InlineStorageSize]; 239fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 240fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot using INHERITED = SkArenaAlloc; 241fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}; 242fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 243fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif // SkArenaAlloc_DEFINED 244