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 "SkArenaAlloc.h"
9 #include "SkRefCnt.h"
10 #include "SkTypes.h"
11 #include "Test.h"
12
13 #include <memory>
14 #include <new>
15 #include <type_traits>
16
17 namespace {
18
19 static int created, destroyed;
20
21 struct Foo {
Foo__anonf9215baa0111::Foo22 Foo() : x(-2), y(-3.0f) { created++; }
Foo__anonf9215baa0111::Foo23 Foo(int X, float Y) : x(X), y(Y) { created++; }
~Foo__anonf9215baa0111::Foo24 ~Foo() { destroyed++; }
25
26 int x;
27 float y;
28 };
29
30 struct Big {
Big__anonf9215baa0111::Big31 Big() {}
32 uint32_t array[128];
33 };
34
35 struct Node {
Node__anonf9215baa0111::Node36 Node(Node* n) : next(n) { created++; }
~Node__anonf9215baa0111::Node37 ~Node() {
38 destroyed++;
39 if (next) {
40 next->~Node();
41 }
42 }
43 Node *next;
44 };
45
46 struct Start {
~Start__anonf9215baa0111::Start47 ~Start() {
48 if (start) {
49 start->~Node();
50 }
51 }
52 Node* start;
53 };
54
55 struct FooRefCnt : public SkRefCnt {
FooRefCnt__anonf9215baa0111::FooRefCnt56 FooRefCnt() : x(-2), y(-3.0f) { created++; }
FooRefCnt__anonf9215baa0111::FooRefCnt57 FooRefCnt(int X, float Y) : x(X), y(Y) { created++; }
~FooRefCnt__anonf9215baa0111::FooRefCnt58 ~FooRefCnt() { destroyed++; }
59
60 int x;
61 float y;
62 };
63
64 }
65
66 struct WithDtor {
~WithDtorWithDtor67 ~WithDtor() { }
68 };
69
DEF_TEST(ArenaAlloc,r)70 DEF_TEST(ArenaAlloc, r) {
71
72 {
73 created = 0;
74 destroyed = 0;
75
76 SkArenaAlloc arena{0};
77 REPORTER_ASSERT(r, *arena.make<int>(3) == 3);
78 Foo* foo = arena.make<Foo>(3, 4.0f);
79 REPORTER_ASSERT(r, foo->x == 3);
80 REPORTER_ASSERT(r, foo->y == 4.0f);
81 REPORTER_ASSERT(r, created == 1);
82 REPORTER_ASSERT(r, destroyed == 0);
83 arena.makeArrayDefault<int>(10);
84 int* zeroed = arena.makeArray<int>(10);
85 for (int i = 0; i < 10; i++) {
86 REPORTER_ASSERT(r, zeroed[i] == 0);
87 }
88 Foo* fooArray = arena.makeArrayDefault<Foo>(10);
89 REPORTER_ASSERT(r, fooArray[3].x == -2);
90 REPORTER_ASSERT(r, fooArray[4].y == -3.0f);
91 REPORTER_ASSERT(r, created == 11);
92 REPORTER_ASSERT(r, destroyed == 0);
93 arena.make<typename std::aligned_storage<10,8>::type>();
94 }
95 REPORTER_ASSERT(r, created == 11);
96 REPORTER_ASSERT(r, destroyed == 11);
97
98 {
99 created = 0;
100 destroyed = 0;
101 SkSTArenaAlloc<64> arena;
102
103 REPORTER_ASSERT(r, *arena.make<int>(3) == 3);
104 Foo* foo = arena.make<Foo>(3, 4.0f);
105 REPORTER_ASSERT(r, foo->x == 3);
106 REPORTER_ASSERT(r, foo->y == 4.0f);
107 REPORTER_ASSERT(r, created == 1);
108 REPORTER_ASSERT(r, destroyed == 0);
109 arena.makeArrayDefault<int>(10);
110 int* zeroed = arena.makeArray<int>(10);
111 for (int i = 0; i < 10; i++) {
112 REPORTER_ASSERT(r, zeroed[i] == 0);
113 }
114 Foo* fooArray = arena.makeArrayDefault<Foo>(10);
115 REPORTER_ASSERT(r, fooArray[3].x == -2);
116 REPORTER_ASSERT(r, fooArray[4].y == -3.0f);
117 REPORTER_ASSERT(r, created == 11);
118 REPORTER_ASSERT(r, destroyed == 0);
119 arena.make<typename std::aligned_storage<10,8>::type>();
120 }
121 REPORTER_ASSERT(r, created == 11);
122 REPORTER_ASSERT(r, destroyed == 11);
123
124 {
125 created = 0;
126 destroyed = 0;
127 std::unique_ptr<char[]> block{new char[1024]};
128 SkArenaAlloc arena{block.get(), 1024, 0};
129
130 REPORTER_ASSERT(r, *arena.make<int>(3) == 3);
131 Foo* foo = arena.make<Foo>(3, 4.0f);
132 REPORTER_ASSERT(r, foo->x == 3);
133 REPORTER_ASSERT(r, foo->y == 4.0f);
134 REPORTER_ASSERT(r, created == 1);
135 REPORTER_ASSERT(r, destroyed == 0);
136 arena.makeArrayDefault<int>(10);
137 int* zeroed = arena.makeArray<int>(10);
138 for (int i = 0; i < 10; i++) {
139 REPORTER_ASSERT(r, zeroed[i] == 0);
140 }
141 Foo* fooArray = arena.makeArrayDefault<Foo>(10);
142 REPORTER_ASSERT(r, fooArray[3].x == -2);
143 REPORTER_ASSERT(r, fooArray[4].y == -3.0f);
144 REPORTER_ASSERT(r, created == 11);
145 REPORTER_ASSERT(r, destroyed == 0);
146 arena.make<typename std::aligned_storage<10,8>::type>();
147 }
148 REPORTER_ASSERT(r, created == 11);
149 REPORTER_ASSERT(r, destroyed == 11);
150
151 {
152 SkSTArenaAlloc<64> arena;
153 arena.makeArrayDefault<char>(256);
154 arena.reset();
155 arena.reset();
156 }
157
158 {
159 created = 0;
160 destroyed = 0;
161 SkSTArenaAlloc<64> arena;
162
163 Start start;
164 Node* current = nullptr;
165 for (int i = 0; i < 128; i++) {
166 uint64_t* temp = arena.makeArrayDefault<uint64_t>(sizeof(Node) / sizeof(Node*));
167 current = new (temp)Node(current);
168 }
169 start.start = current;
170 }
171
172 REPORTER_ASSERT(r, created == 128);
173 REPORTER_ASSERT(r, destroyed == 128);
174
175 {
176 created = 0;
177 destroyed = 0;
178 SkSTArenaAlloc<64> arena;
179
180 sk_sp<FooRefCnt> f = arena.makeSkSp<FooRefCnt>(4, 5.0f);
181 REPORTER_ASSERT(r, f->x == 4);
182 REPORTER_ASSERT(r, f->y == 5.0f);
183 REPORTER_ASSERT(r, created == 1);
184 REPORTER_ASSERT(r, destroyed == 0);
185 }
186 REPORTER_ASSERT(r, created == 1);
187 REPORTER_ASSERT(r, destroyed == 1);
188 }
189