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