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.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "Test.h"
|
|
|
|
#include "SkFixedAlloc.h"
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
2016-11-15 17:58:33 +00:00
|
|
|
static int created, destroyed;
|
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;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct Big {
|
|
|
|
Big() {}
|
|
|
|
uint32_t array[128];
|
|
|
|
};
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
DEF_TEST(FixedAlloc, r) {
|
|
|
|
// Basic mechanics.
|
|
|
|
{
|
|
|
|
uint8_t buf[128];
|
|
|
|
SkFixedAlloc fa(buf, sizeof(buf));
|
|
|
|
|
|
|
|
Foo* foo = fa.make<Foo>(3, 4.0f);
|
|
|
|
REPORTER_ASSERT(r, foo);
|
|
|
|
REPORTER_ASSERT(r, foo->x == 3);
|
|
|
|
REPORTER_ASSERT(r, foo->y == 4.0f);
|
|
|
|
REPORTER_ASSERT(r, created == 1);
|
2016-11-15 17:58:33 +00:00
|
|
|
REPORTER_ASSERT(r, destroyed == 0);
|
2016-11-11 15:38:49 +00:00
|
|
|
|
|
|
|
Foo* bar = fa.make<Foo>(8, 1.0f);
|
|
|
|
REPORTER_ASSERT(r, bar);
|
|
|
|
REPORTER_ASSERT(r, bar->x == 8);
|
|
|
|
REPORTER_ASSERT(r, bar->y == 1.0f);
|
|
|
|
REPORTER_ASSERT(r, created == 2);
|
2016-11-15 17:58:33 +00:00
|
|
|
REPORTER_ASSERT(r, destroyed == 0);
|
2016-11-11 15:38:49 +00:00
|
|
|
|
|
|
|
fa.undo();
|
2016-11-15 17:58:33 +00:00
|
|
|
REPORTER_ASSERT(r, created == 2);
|
|
|
|
REPORTER_ASSERT(r, destroyed == 1);
|
2016-11-11 15:38:49 +00:00
|
|
|
}
|
2016-11-15 17:58:33 +00:00
|
|
|
REPORTER_ASSERT(r, created == 2);
|
|
|
|
REPORTER_ASSERT(r, destroyed == 2);
|
2016-11-11 15:38:49 +00:00
|
|
|
|
|
|
|
{
|
|
|
|
// Test alignment gurantees.
|
|
|
|
uint8_t buf[64];
|
|
|
|
SkFixedAlloc fa(buf+3, sizeof(buf)-3);
|
|
|
|
|
|
|
|
Foo* foo = fa.make<Foo>(3, 4.0f);
|
|
|
|
REPORTER_ASSERT(r, SkIsAlign4((uintptr_t)foo));
|
|
|
|
REPORTER_ASSERT(r, created == 3);
|
2016-11-15 17:58:33 +00:00
|
|
|
REPORTER_ASSERT(r, destroyed == 2);
|
2016-11-11 15:38:49 +00:00
|
|
|
|
|
|
|
// Might as well test reset() while we're at it.
|
|
|
|
fa.reset();
|
2016-11-15 17:58:33 +00:00
|
|
|
REPORTER_ASSERT(r, created == 3);
|
|
|
|
REPORTER_ASSERT(r, destroyed == 3);
|
2016-11-11 15:38:49 +00:00
|
|
|
}
|
2016-11-15 17:58:33 +00:00
|
|
|
REPORTER_ASSERT(r, created == 3);
|
|
|
|
REPORTER_ASSERT(r, destroyed == 3);
|
2016-11-11 15:38:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
DEF_TEST(FallbackAlloc, r) {
|
|
|
|
// SkFixedAlloc will eventually fail when it runs out of space in its buffer.
|
|
|
|
int buf[32];
|
|
|
|
SkFixedAlloc fixed(buf, sizeof(buf));
|
|
|
|
bool fixed_failed = false;
|
|
|
|
for (int i = 0; i < 32; i++) {
|
2016-11-15 17:58:33 +00:00
|
|
|
// (Remember, there is some overhead to each make() call.)
|
|
|
|
fixed_failed = fixed_failed || (fixed.make<int>(i) == nullptr);
|
2016-11-11 15:38:49 +00:00
|
|
|
}
|
|
|
|
REPORTER_ASSERT(r, fixed_failed);
|
|
|
|
|
|
|
|
|
|
|
|
// SkFallbackAlloc will always succeed, using the heap as required.
|
|
|
|
fixed.reset();
|
|
|
|
SkFallbackAlloc fallback(&fixed);
|
|
|
|
|
|
|
|
bool fallback_failed = false;
|
|
|
|
for (int i = 0; i < 32; i++) {
|
2016-11-15 17:58:33 +00:00
|
|
|
fallback_failed = fallback_failed || (fallback.make<int>(i) == nullptr);
|
2016-11-11 15:38:49 +00:00
|
|
|
}
|
|
|
|
REPORTER_ASSERT(r, !fallback_failed);
|
|
|
|
|
|
|
|
|
|
|
|
// Test small, big, small allocations to make sure once we go to the heap we stay there.
|
|
|
|
fallback.reset();
|
|
|
|
auto smallA = fallback.make<int>(2);
|
|
|
|
auto big = fallback.make<Big>();
|
|
|
|
auto smallB = fallback.make<int>(3);
|
|
|
|
|
|
|
|
auto in_buf = [&](void* ptr) {
|
|
|
|
return (uintptr_t)(buf+0 ) <= (uintptr_t)ptr
|
|
|
|
&& (uintptr_t)(buf+32) > (uintptr_t)ptr;
|
|
|
|
};
|
|
|
|
|
|
|
|
REPORTER_ASSERT(r, in_buf(smallA));
|
|
|
|
REPORTER_ASSERT(r, !in_buf(big));
|
|
|
|
REPORTER_ASSERT(r, !in_buf(smallB));
|
|
|
|
}
|
2017-01-13 16:30:44 +00:00
|
|
|
|
|
|
|
struct WithDtor {
|
|
|
|
~WithDtor() { }
|
|
|
|
};
|
|
|
|
|
|
|
|
DEF_TEST(ArenaAlloc, r) {
|
|
|
|
|
|
|
|
{
|
|
|
|
created = 0;
|
|
|
|
destroyed = 0;
|
|
|
|
|
|
|
|
SkArenaAlloc arena{nullptr, 0};
|
|
|
|
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);
|
|
|
|
arena.make<typename std::aligned_storage<10,8>::type>();
|
|
|
|
}
|
|
|
|
REPORTER_ASSERT(r, created == 11);
|
|
|
|
REPORTER_ASSERT(r, destroyed == 11);
|
|
|
|
|
|
|
|
{
|
|
|
|
created = 0;
|
|
|
|
destroyed = 0;
|
|
|
|
char block[1024];
|
|
|
|
SkArenaAlloc arena{block};
|
|
|
|
|
|
|
|
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);
|
|
|
|
arena.make<typename std::aligned_storage<10,8>::type>();
|
|
|
|
}
|
|
|
|
REPORTER_ASSERT(r, created == 11);
|
|
|
|
REPORTER_ASSERT(r, destroyed == 11);
|
|
|
|
|
|
|
|
{
|
|
|
|
created = 0;
|
|
|
|
destroyed = 0;
|
|
|
|
std::unique_ptr<char[]> block{new char[1024]};
|
|
|
|
SkArenaAlloc arena{block.get(), 1024};
|
|
|
|
|
|
|
|
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);
|
|
|
|
arena.make<typename std::aligned_storage<10,8>::type>();
|
|
|
|
}
|
|
|
|
REPORTER_ASSERT(r, created == 11);
|
|
|
|
REPORTER_ASSERT(r, destroyed == 11);
|
|
|
|
|
|
|
|
}
|