58b130681d
Looking at SkSmallAlloc hasn't left me terribly impressed. I think we can replace it with something a lot simpler to work with. That simpler thing's core would be something like SkFixedAlloc, which allocates objects out of a fixed sized buffer, and cleans them up when done. If needed, we can wrap that with logic to try to allocate out of an SkFixedAlloc, falling back on mallc() when exhausted. BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=4658 Change-Id: I8d94156ddf98802e42ec0890cff0f06b21f073b0 Reviewed-on: https://skia-review.googlesource.com/4658 Commit-Queue: Mike Klein <mtklein@chromium.org> Reviewed-by: Mike Reed <reed@google.com>
114 lines
3.0 KiB
C++
114 lines
3.0 KiB
C++
/*
|
|
* 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 {
|
|
|
|
static int created, destroyed;
|
|
|
|
struct Foo {
|
|
Foo(int X, float Y) : x(X), y(Y) { created++; }
|
|
~Foo() { destroyed++; }
|
|
|
|
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);
|
|
REPORTER_ASSERT(r, destroyed == 0);
|
|
|
|
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);
|
|
REPORTER_ASSERT(r, destroyed == 0);
|
|
|
|
fa.undo();
|
|
REPORTER_ASSERT(r, created == 2);
|
|
REPORTER_ASSERT(r, destroyed == 1);
|
|
}
|
|
REPORTER_ASSERT(r, created == 2);
|
|
REPORTER_ASSERT(r, destroyed == 2);
|
|
|
|
{
|
|
// 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);
|
|
REPORTER_ASSERT(r, destroyed == 2);
|
|
|
|
// Might as well test reset() while we're at it.
|
|
fa.reset();
|
|
REPORTER_ASSERT(r, created == 3);
|
|
REPORTER_ASSERT(r, destroyed == 3);
|
|
}
|
|
REPORTER_ASSERT(r, created == 3);
|
|
REPORTER_ASSERT(r, destroyed == 3);
|
|
}
|
|
|
|
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++) {
|
|
// (Remember, there is some overhead to each make() call.)
|
|
fixed_failed = fixed_failed || (fixed.make<int>(i) == nullptr);
|
|
}
|
|
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++) {
|
|
fallback_failed = fallback_failed || (fallback.make<int>(i) == nullptr);
|
|
}
|
|
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));
|
|
}
|