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