1 /*
2 * Copyright 2016 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8 #include "include/core/SkTypes.h"
9 #include "src/base/SkArenaAlloc.h"
10 #include "tests/Test.h"
11
12 #include <cstddef>
13 #include <cstdint>
14 #include <initializer_list>
15 #include <limits>
16 #include <memory>
17 #include <new>
18
DEF_TEST(ArenaAlloc,r)19 DEF_TEST(ArenaAlloc, r) {
20 static int created = 0,
21 destroyed = 0;
22
23 struct Foo {
24 Foo() : x(-2), y(-3.0f) { created++; }
25 Foo(int X, float Y) : x(X), y(Y) { created++; }
26 ~Foo() { destroyed++; }
27 int x;
28 float y;
29 };
30
31 struct alignas(8) OddAlignment {
32 char buf[10];
33 };
34
35 // Check construction/destruction counts from SkArenaAlloc.
36 created = 0;
37 destroyed = 0;
38 {
39 SkArenaAlloc arena{0};
40 REPORTER_ASSERT(r, *arena.make<int>(3) == 3);
41 Foo* foo = arena.make<Foo>(3, 4.0f);
42 REPORTER_ASSERT(r, foo->x == 3);
43 REPORTER_ASSERT(r, foo->y == 4.0f);
44 REPORTER_ASSERT(r, created == 1);
45 REPORTER_ASSERT(r, destroyed == 0);
46 arena.makeArrayDefault<int>(10);
47 int* zeroed = arena.makeArray<int>(10);
48 for (int i = 0; i < 10; i++) {
49 REPORTER_ASSERT(r, zeroed[i] == 0);
50 }
51 Foo* fooArray = arena.makeArrayDefault<Foo>(10);
52 REPORTER_ASSERT(r, fooArray[3].x == -2);
53 REPORTER_ASSERT(r, fooArray[4].y == -3.0f);
54 REPORTER_ASSERT(r, created == 11);
55 REPORTER_ASSERT(r, destroyed == 0);
56 arena.make<OddAlignment>();
57 }
58 REPORTER_ASSERT(r, created == 11);
59 REPORTER_ASSERT(r, destroyed == 11);
60
61 // Check construction/destruction counts from SkSTArenaAlloc.
62 created = 0;
63 destroyed = 0;
64 {
65 SkSTArenaAlloc<64> arena;
66 REPORTER_ASSERT(r, *arena.make<int>(3) == 3);
67 Foo* foo = arena.make<Foo>(3, 4.0f);
68 REPORTER_ASSERT(r, foo->x == 3);
69 REPORTER_ASSERT(r, foo->y == 4.0f);
70 REPORTER_ASSERT(r, created == 1);
71 REPORTER_ASSERT(r, destroyed == 0);
72 arena.makeArrayDefault<int>(10);
73 int* zeroed = arena.makeArray<int>(10);
74 for (int i = 0; i < 10; i++) {
75 REPORTER_ASSERT(r, zeroed[i] == 0);
76 }
77 Foo* fooArray = arena.makeArrayDefault<Foo>(10);
78 REPORTER_ASSERT(r, fooArray[3].x == -2);
79 REPORTER_ASSERT(r, fooArray[4].y == -3.0f);
80 REPORTER_ASSERT(r, created == 11);
81 REPORTER_ASSERT(r, destroyed == 0);
82 arena.make<OddAlignment>();
83 }
84 REPORTER_ASSERT(r, created == 11);
85 REPORTER_ASSERT(r, destroyed == 11);
86
87 // Check construction/destruction counts from SkArenaAlloc when passed an initial block.
88 created = 0;
89 destroyed = 0;
90 {
91 std::unique_ptr<char[]> block{new char[1024]};
92 SkArenaAlloc arena{block.get(), 1024, 0};
93 REPORTER_ASSERT(r, *arena.make<int>(3) == 3);
94 Foo* foo = arena.make<Foo>(3, 4.0f);
95 REPORTER_ASSERT(r, foo->x == 3);
96 REPORTER_ASSERT(r, foo->y == 4.0f);
97 REPORTER_ASSERT(r, created == 1);
98 REPORTER_ASSERT(r, destroyed == 0);
99 arena.makeArrayDefault<int>(10);
100 int* zeroed = arena.makeArray<int>(10);
101 for (int i = 0; i < 10; i++) {
102 REPORTER_ASSERT(r, zeroed[i] == 0);
103 }
104 Foo* fooArray = arena.makeArrayDefault<Foo>(10);
105 REPORTER_ASSERT(r, fooArray[3].x == -2);
106 REPORTER_ASSERT(r, fooArray[4].y == -3.0f);
107 REPORTER_ASSERT(r, created == 11);
108 REPORTER_ASSERT(r, destroyed == 0);
109 arena.make<OddAlignment>();
110 }
111 REPORTER_ASSERT(r, created == 11);
112 REPORTER_ASSERT(r, destroyed == 11);
113 }
114
DEF_TEST(ArenaAllocReset,r)115 DEF_TEST(ArenaAllocReset, r) {
116 SkSTArenaAllocWithReset<64> arena;
117 arena.makeArrayDefault<char>(256);
118 arena.reset();
119 arena.reset();
120 }
121
DEF_TEST(ArenaAllocIsEmpty,r)122 DEF_TEST(ArenaAllocIsEmpty, r) {
123 char storage[1000];
124 for (int arenaSize : {1, 2, 3, 10, 100, 1000}) {
125 for (int alloc1Size : {1, 10, 100, 1000}) {
126 for (int alloc2Size : {1, 10, 100, 1000}) {
127 SkArenaAllocWithReset arena(storage, arenaSize, 1000);
128 REPORTER_ASSERT(r, arena.isEmpty());
129
130 [[maybe_unused]] char* alloc1 = arena.makeArray<char>(alloc1Size);
131 REPORTER_ASSERT(r, !arena.isEmpty());
132
133 [[maybe_unused]] char* alloc2 = arena.makeArray<char>(alloc2Size);
134 REPORTER_ASSERT(r, !arena.isEmpty());
135
136 arena.reset();
137 REPORTER_ASSERT(r, arena.isEmpty());
138 }
139 }
140 }
141 }
142
DEF_TEST(ArenaAllocWithMultipleBlocks,r)143 DEF_TEST(ArenaAllocWithMultipleBlocks, r) {
144 // Make sure that multiple blocks are handled correctly.
145 static int created = 0,
146 destroyed = 0;
147 {
148 struct Node {
149 Node(Node* n) : next(n) { created++; }
150 ~Node() { destroyed++; }
151 Node *next;
152 char filler[64];
153 };
154
155 SkSTArenaAlloc<64> arena;
156 Node* current = nullptr;
157 for (int i = 0; i < 128; i++) {
158 current = arena.make<Node>(current);
159 }
160 }
161 REPORTER_ASSERT(r, created == 128);
162 REPORTER_ASSERT(r, destroyed == 128);
163 }
164
DEF_TEST(ArenaAllocDestructionOrder,r)165 DEF_TEST(ArenaAllocDestructionOrder, r) {
166 // Make sure that objects and blocks are destroyed in the correct order. If they are not,
167 // then there will be a use after free error in asan.
168 static int created = 0,
169 destroyed = 0;
170 {
171 struct Node {
172 Node(Node* n) : next(n) { created++; }
173 ~Node() {
174 destroyed++;
175 if (next) {
176 next->~Node();
177 }
178 }
179 Node *next;
180 };
181
182 SkSTArenaAlloc<64> arena;
183 Node* current = nullptr;
184 for (int i = 0; i < 128; i++) {
185 uint64_t* temp = arena.makeArrayDefault<uint64_t>(sizeof(Node) / sizeof(Node*));
186 current = new (temp)Node(current);
187 }
188 current->~Node();
189 }
190 REPORTER_ASSERT(r, created == 128);
191 REPORTER_ASSERT(r, destroyed == 128);
192
193 {
194 SkSTArenaAlloc<64> arena;
195 auto a = arena.makeInitializedArray<int>(8, [](size_t i ) { return i; });
196 for (size_t i = 0; i < 8; i++) {
197 REPORTER_ASSERT(r, a[i] == (int)i);
198 }
199 }
200 }
201
DEF_TEST(ArenaAllocUnusualAlignment,r)202 DEF_TEST(ArenaAllocUnusualAlignment, r) {
203 SkArenaAlloc arena(4096);
204 // Move to a 1 character boundary.
205 arena.make<char>();
206 // Allocate something with interesting alignment.
207 void* ptr = arena.makeBytesAlignedTo(4081, 8);
208 REPORTER_ASSERT(r, ((intptr_t)ptr & 7) == 0);
209 }
210
DEF_TEST(SkFibBlockSizes,r)211 DEF_TEST(SkFibBlockSizes, r) {
212 {
213 SkFibBlockSizes<std::numeric_limits<uint32_t>::max()> fibs{1, 1};
214 uint32_t lastSize = 1;
215 for (int i = 0; i < 64; i++) {
216 uint32_t size = fibs.nextBlockSize();
217 REPORTER_ASSERT(r, lastSize <= size);
218 lastSize = size;
219 }
220 REPORTER_ASSERT(r, lastSize == 2971215073u);
221 }
222 {
223 SkFibBlockSizes<std::numeric_limits<uint32_t>::max()> fibs{0, 1024};
224 uint32_t lastSize = 1;
225 for (int i = 0; i < 64; i++) {
226 uint32_t size = fibs.nextBlockSize();
227 REPORTER_ASSERT(r, lastSize <= size);
228 lastSize = size;
229 REPORTER_ASSERT(r, lastSize <= std::numeric_limits<uint32_t>::max());
230 }
231 REPORTER_ASSERT(r, lastSize == 3524578u * 1024);
232 }
233
234 {
235 SkFibBlockSizes<std::numeric_limits<uint32_t>::max() / 2> fibs{1024, 0};
236 uint32_t lastSize = 1;
237 for (int i = 0; i < 64; i++) {
238 uint32_t size = fibs.nextBlockSize();
239 REPORTER_ASSERT(r, lastSize <= size);
240 lastSize = size;
241 REPORTER_ASSERT(r, lastSize <= std::numeric_limits<uint32_t>::max() / 2);
242 }
243 REPORTER_ASSERT(r, lastSize == 1346269u * 1024);
244 }
245 }
246