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