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