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__anonb3a063240111::Foo22         Foo() : x(-2), y(-3.0f) { created++; }
Foo__anonb3a063240111::Foo23         Foo(int X, float Y) : x(X), y(Y) { created++; }
~Foo__anonb3a063240111::Foo24         ~Foo() { destroyed++; }
25 
26         int x;
27         float y;
28     };
29 
30     struct Big {
Big__anonb3a063240111::Big31         Big() {}
32         uint32_t array[128];
33     };
34 
35     struct Node {
Node__anonb3a063240111::Node36         Node(Node* n) : next(n) { created++; }
~Node__anonb3a063240111::Node37         ~Node() {
38             destroyed++;
39             if (next) {
40                 next->~Node();
41             }
42         }
43         Node *next;
44     };
45 
46     struct Start {
~Start__anonb3a063240111::Start47         ~Start() {
48             if (start) {
49                 start->~Node();
50             }
51         }
52         Node* start;
53     };
54 
55     struct FooRefCnt : public SkRefCnt {
FooRefCnt__anonb3a063240111::FooRefCnt56         FooRefCnt() : x(-2), y(-3.0f) { created++; }
FooRefCnt__anonb3a063240111::FooRefCnt57         FooRefCnt(int X, float Y) : x(X), y(Y) { created++; }
~FooRefCnt__anonb3a063240111::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