2016-11-11 15:38:49 +00:00
|
|
|
/*
|
|
|
|
* Copyright 2016 Google Inc.
|
|
|
|
*
|
|
|
|
* Use of this source code is governed by a BSD-style license that can be
|
|
|
|
* found in the LICENSE file.
|
|
|
|
*/
|
|
|
|
|
2019-04-23 17:05:21 +00:00
|
|
|
#include "include/core/SkRefCnt.h"
|
|
|
|
#include "include/core/SkTypes.h"
|
2019-05-17 20:29:34 +00:00
|
|
|
#include "src/core/SkArenaAlloc.h"
|
2019-04-23 17:05:21 +00:00
|
|
|
#include "tests/Test.h"
|
2018-03-02 21:59:53 +00:00
|
|
|
|
|
|
|
#include <memory>
|
|
|
|
#include <new>
|
|
|
|
#include <type_traits>
|
2016-11-11 15:38:49 +00:00
|
|
|
|
2020-12-16 16:17:27 +00:00
|
|
|
DEF_TEST(ArenaAlloc, r) {
|
|
|
|
static int created = 0,
|
|
|
|
destroyed = 0;
|
2016-11-11 15:38:49 +00:00
|
|
|
|
|
|
|
struct Foo {
|
2017-01-13 16:30:44 +00:00
|
|
|
Foo() : x(-2), y(-3.0f) { created++; }
|
|
|
|
Foo(int X, float Y) : x(X), y(Y) { created++; }
|
2016-11-15 17:58:33 +00:00
|
|
|
~Foo() { destroyed++; }
|
2016-11-11 15:38:49 +00:00
|
|
|
int x;
|
|
|
|
float y;
|
|
|
|
};
|
|
|
|
|
2020-12-16 16:17:27 +00:00
|
|
|
struct alignas(8) OddAlignment {
|
|
|
|
char buf[10];
|
2017-02-06 18:03:49 +00:00
|
|
|
};
|
|
|
|
|
2020-12-16 16:17:27 +00:00
|
|
|
created = 0;
|
|
|
|
destroyed = 0;
|
2017-01-13 16:30:44 +00:00
|
|
|
{
|
2017-04-14 18:51:27 +00:00
|
|
|
SkArenaAlloc arena{0};
|
2017-01-13 16:30:44 +00:00
|
|
|
REPORTER_ASSERT(r, *arena.make<int>(3) == 3);
|
|
|
|
Foo* foo = arena.make<Foo>(3, 4.0f);
|
|
|
|
REPORTER_ASSERT(r, foo->x == 3);
|
|
|
|
REPORTER_ASSERT(r, foo->y == 4.0f);
|
|
|
|
REPORTER_ASSERT(r, created == 1);
|
|
|
|
REPORTER_ASSERT(r, destroyed == 0);
|
|
|
|
arena.makeArrayDefault<int>(10);
|
|
|
|
int* zeroed = arena.makeArray<int>(10);
|
|
|
|
for (int i = 0; i < 10; i++) {
|
|
|
|
REPORTER_ASSERT(r, zeroed[i] == 0);
|
|
|
|
}
|
|
|
|
Foo* fooArray = arena.makeArrayDefault<Foo>(10);
|
|
|
|
REPORTER_ASSERT(r, fooArray[3].x == -2);
|
|
|
|
REPORTER_ASSERT(r, fooArray[4].y == -3.0f);
|
|
|
|
REPORTER_ASSERT(r, created == 11);
|
|
|
|
REPORTER_ASSERT(r, destroyed == 0);
|
2020-11-09 21:50:37 +00:00
|
|
|
arena.make<OddAlignment>();
|
2017-01-13 16:30:44 +00:00
|
|
|
}
|
|
|
|
REPORTER_ASSERT(r, created == 11);
|
|
|
|
REPORTER_ASSERT(r, destroyed == 11);
|
|
|
|
|
2020-12-16 16:17:27 +00:00
|
|
|
created = 0;
|
|
|
|
destroyed = 0;
|
2017-01-13 16:30:44 +00:00
|
|
|
{
|
2017-05-24 18:53:44 +00:00
|
|
|
SkSTArenaAlloc<64> arena;
|
2017-01-13 16:30:44 +00:00
|
|
|
REPORTER_ASSERT(r, *arena.make<int>(3) == 3);
|
|
|
|
Foo* foo = arena.make<Foo>(3, 4.0f);
|
|
|
|
REPORTER_ASSERT(r, foo->x == 3);
|
|
|
|
REPORTER_ASSERT(r, foo->y == 4.0f);
|
|
|
|
REPORTER_ASSERT(r, created == 1);
|
|
|
|
REPORTER_ASSERT(r, destroyed == 0);
|
|
|
|
arena.makeArrayDefault<int>(10);
|
|
|
|
int* zeroed = arena.makeArray<int>(10);
|
|
|
|
for (int i = 0; i < 10; i++) {
|
|
|
|
REPORTER_ASSERT(r, zeroed[i] == 0);
|
|
|
|
}
|
|
|
|
Foo* fooArray = arena.makeArrayDefault<Foo>(10);
|
|
|
|
REPORTER_ASSERT(r, fooArray[3].x == -2);
|
|
|
|
REPORTER_ASSERT(r, fooArray[4].y == -3.0f);
|
|
|
|
REPORTER_ASSERT(r, created == 11);
|
|
|
|
REPORTER_ASSERT(r, destroyed == 0);
|
2020-11-09 21:50:37 +00:00
|
|
|
arena.make<OddAlignment>();
|
2017-01-13 16:30:44 +00:00
|
|
|
}
|
|
|
|
REPORTER_ASSERT(r, created == 11);
|
|
|
|
REPORTER_ASSERT(r, destroyed == 11);
|
|
|
|
|
2020-12-16 16:17:27 +00:00
|
|
|
created = 0;
|
|
|
|
destroyed = 0;
|
2017-01-13 16:30:44 +00:00
|
|
|
{
|
|
|
|
std::unique_ptr<char[]> block{new char[1024]};
|
2017-04-14 18:51:27 +00:00
|
|
|
SkArenaAlloc arena{block.get(), 1024, 0};
|
2017-01-13 16:30:44 +00:00
|
|
|
REPORTER_ASSERT(r, *arena.make<int>(3) == 3);
|
|
|
|
Foo* foo = arena.make<Foo>(3, 4.0f);
|
|
|
|
REPORTER_ASSERT(r, foo->x == 3);
|
|
|
|
REPORTER_ASSERT(r, foo->y == 4.0f);
|
|
|
|
REPORTER_ASSERT(r, created == 1);
|
|
|
|
REPORTER_ASSERT(r, destroyed == 0);
|
|
|
|
arena.makeArrayDefault<int>(10);
|
|
|
|
int* zeroed = arena.makeArray<int>(10);
|
|
|
|
for (int i = 0; i < 10; i++) {
|
|
|
|
REPORTER_ASSERT(r, zeroed[i] == 0);
|
|
|
|
}
|
|
|
|
Foo* fooArray = arena.makeArrayDefault<Foo>(10);
|
|
|
|
REPORTER_ASSERT(r, fooArray[3].x == -2);
|
|
|
|
REPORTER_ASSERT(r, fooArray[4].y == -3.0f);
|
|
|
|
REPORTER_ASSERT(r, created == 11);
|
|
|
|
REPORTER_ASSERT(r, destroyed == 0);
|
2020-11-09 21:50:37 +00:00
|
|
|
arena.make<OddAlignment>();
|
2017-01-13 16:30:44 +00:00
|
|
|
}
|
|
|
|
REPORTER_ASSERT(r, created == 11);
|
|
|
|
REPORTER_ASSERT(r, destroyed == 11);
|
2017-01-19 19:28:49 +00:00
|
|
|
|
|
|
|
{
|
2020-08-01 20:26:04 +00:00
|
|
|
SkSTArenaAllocWithReset<64> arena;
|
2017-01-19 19:28:49 +00:00
|
|
|
arena.makeArrayDefault<char>(256);
|
|
|
|
arena.reset();
|
|
|
|
arena.reset();
|
|
|
|
}
|
|
|
|
|
2020-12-16 16:17:27 +00:00
|
|
|
// Make sure that multiple blocks are handled correctly.
|
|
|
|
created = 0;
|
|
|
|
destroyed = 0;
|
2017-01-19 19:28:49 +00:00
|
|
|
{
|
2020-12-16 16:17:27 +00:00
|
|
|
struct Node {
|
|
|
|
Node(Node* n) : next(n) { created++; }
|
|
|
|
~Node() { destroyed++; }
|
|
|
|
Node *next;
|
|
|
|
char filler[64];
|
|
|
|
};
|
|
|
|
|
2017-05-24 18:53:44 +00:00
|
|
|
SkSTArenaAlloc<64> arena;
|
2020-12-16 16:17:27 +00:00
|
|
|
Node* current = nullptr;
|
|
|
|
for (int i = 0; i < 128; i++) {
|
|
|
|
current = arena.make<Node>(current);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
REPORTER_ASSERT(r, created == 128);
|
|
|
|
REPORTER_ASSERT(r, destroyed == 128);
|
2017-01-19 19:28:49 +00:00
|
|
|
|
2020-12-16 16:17:27 +00:00
|
|
|
// Make sure that objects and blocks are destroyed in the correct order. If they are not,
|
|
|
|
// then there will be a use after free error in asan.
|
|
|
|
created = 0;
|
|
|
|
destroyed = 0;
|
|
|
|
{
|
|
|
|
struct Node {
|
|
|
|
Node(Node* n) : next(n) { created++; }
|
|
|
|
~Node() {
|
|
|
|
destroyed++;
|
|
|
|
if (next) {
|
|
|
|
next->~Node();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Node *next;
|
|
|
|
};
|
|
|
|
|
|
|
|
SkSTArenaAlloc<64> arena;
|
2017-01-19 19:28:49 +00:00
|
|
|
Node* current = nullptr;
|
|
|
|
for (int i = 0; i < 128; i++) {
|
|
|
|
uint64_t* temp = arena.makeArrayDefault<uint64_t>(sizeof(Node) / sizeof(Node*));
|
|
|
|
current = new (temp)Node(current);
|
|
|
|
}
|
2020-12-16 16:17:27 +00:00
|
|
|
current->~Node();
|
2017-01-19 19:28:49 +00:00
|
|
|
}
|
2020-12-16 16:17:27 +00:00
|
|
|
REPORTER_ASSERT(r, created == 128);
|
|
|
|
REPORTER_ASSERT(r, destroyed == 128);
|
2017-01-19 19:28:49 +00:00
|
|
|
|
2020-05-13 18:53:40 +00:00
|
|
|
{
|
|
|
|
SkSTArenaAlloc<64> arena;
|
|
|
|
auto a = arena.makeInitializedArray<int>(8, [](size_t i ) { return i; });
|
|
|
|
for (size_t i = 0; i < 8; i++) {
|
|
|
|
REPORTER_ASSERT(r, a[i] == (int)i);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-09-08 18:59:16 +00:00
|
|
|
{
|
|
|
|
SkArenaAlloc arena(4096);
|
2020-12-16 16:17:27 +00:00
|
|
|
// Move to a 1 character boundary.
|
|
|
|
arena.make<char>();
|
|
|
|
// Allocate something with interesting alignment.
|
|
|
|
void* ptr = arena.makeBytesAlignedTo(4081, 8);
|
|
|
|
REPORTER_ASSERT(r, ((intptr_t)ptr & 7) == 0);
|
2020-09-08 18:59:16 +00:00
|
|
|
}
|
2017-01-13 16:30:44 +00:00
|
|
|
}
|