Fix reset and deleting behavior.

* Reset the Arena state.
* Call all the dtors before deleting the blocks.

TBR=mtklein@google.com

Change-Id: Iac320fec16e572cc9a6184c1f580089ab720f036
Reviewed-on: https://skia-review.googlesource.com/7221
Reviewed-by: Herb Derby <herb@google.com>
Commit-Queue: Herb Derby <herb@google.com>
This commit is contained in:
Herb Derby 2017-01-18 17:07:48 -05:00 committed by Skia Commit-Bot
parent 95acbad4fe
commit 412a86d014
3 changed files with 86 additions and 28 deletions

View File

@ -12,15 +12,21 @@ struct Skipper {
char* operator()(char* objEnd, ptrdiff_t size) { return objEnd + size; }
};
struct NextBlock {
char* operator()(char* objEnd, ptrdiff_t size) { delete [] objEnd; return objEnd + size; }
struct SkArenaAlloc::NextBlock {
char* operator()(char* objEnd, ptrdiff_t size) {
ResetBlock(objEnd + size);
delete [] objEnd;
return nullptr;
}
};
SkArenaAlloc::SkArenaAlloc(char* block, size_t size, size_t extraSize)
: fDtorCursor{block}
, fCursor {block}
, fEnd {block + size}
, fExtraSize {extraSize}
: fDtorCursor {block}
, fCursor {block}
, fEnd {block + size}
, fFirstBlock {block}
, fFirstSize {size}
, fExtraSize {extraSize}
{
if (size < sizeof(Footer)) {
fEnd = fCursor = fDtorCursor = nullptr;
@ -32,16 +38,12 @@ SkArenaAlloc::SkArenaAlloc(char* block, size_t size, size_t extraSize)
}
SkArenaAlloc::~SkArenaAlloc() {
this->reset();
ResetBlock(fDtorCursor);
}
void SkArenaAlloc::reset() {
Footer f;
memmove(&f, fDtorCursor - sizeof(Footer), sizeof(Footer));
char* releaser = fDtorCursor;
while (releaser != nullptr) {
releaser = this->callFooterAction(releaser);
}
this->~SkArenaAlloc();
new (this) SkArenaAlloc{fFirstBlock, fFirstSize, fExtraSize};
}
void SkArenaAlloc::installFooter(FooterAction* releaser, ptrdiff_t padding) {
@ -54,8 +56,6 @@ void SkArenaAlloc::installFooter(FooterAction* releaser, ptrdiff_t padding) {
Footer footer = (Footer)(footerData);
memmove(fCursor, &footer, sizeof(Footer));
Footer check;
memmove(&check, fCursor, sizeof(Footer));
fCursor += sizeof(Footer);
fDtorCursor = fCursor;
}
@ -104,7 +104,7 @@ char* SkArenaAlloc::allocObject(size_t size, size_t alignment) {
char* SkArenaAlloc::allocObjectWithFooter(size_t sizeIncludingFooter, size_t alignment) {
size_t mask = alignment - 1;
restart:
restart:
size_t skipOverhead = 0;
bool needsSkipFooter = fCursor != fDtorCursor;
if (needsSkipFooter) {
@ -132,14 +132,20 @@ char* SkArenaAlloc::allocObjectWithFooter(size_t sizeIncludingFooter, size_t ali
return objStart;
}
char* SkArenaAlloc::callFooterAction(char* end) {
Footer footer;
memcpy(&footer, end - sizeof(Footer), sizeof(Footer));
void SkArenaAlloc::ResetBlock(char* footerEnd) {
while (footerEnd != nullptr) {
footerEnd = CallFooterAction(footerEnd);
}
}
FooterAction* releaser = (FooterAction*)((char*)EndChain + (footer >> 5));
char* SkArenaAlloc::CallFooterAction(char* footerEnd) {
Footer footer;
memcpy(&footer, footerEnd - sizeof(Footer), sizeof(Footer));
FooterAction* action = (FooterAction*)((char*)EndChain + (footer >> 5));
ptrdiff_t padding = footer & 31;
char* r = releaser(end) - padding;
char* r = action(footerEnd) - padding;
return r;
}

View File

@ -56,7 +56,7 @@ public:
SkArenaAlloc(char* block, size_t size, size_t extraSize = 0);
template <size_t kSize>
SkArenaAlloc(char (&block)[kSize], size_t extraSize = 0)
SkArenaAlloc(char (&block)[kSize], size_t extraSize = kSize)
: SkArenaAlloc(block, kSize, extraSize)
{}
@ -116,6 +116,8 @@ private:
using Footer = int32_t;
using FooterAction = char* (char*);
struct NextBlock;
void installFooter(FooterAction* releaser, ptrdiff_t padding);
// N.B. Action is different than FooterAction. FooterAction expects the end of the Footer,
@ -179,7 +181,9 @@ private:
return objStart;
}
char* callFooterAction(char* end);
static char* CallFooterAction(char* end);
static void ResetBlock(char* footerEnd);
static char* EndChain(char*);
@ -195,10 +199,12 @@ private:
}
};
char* fDtorCursor;
char* fCursor;
char* fEnd;
size_t fExtraSize;
char* fDtorCursor;
char* fCursor;
char* fEnd;
char* const fFirstBlock;
const size_t fFirstSize;
const size_t fExtraSize;
};
#endif//SkFixedAlloc_DEFINED

View File

@ -26,6 +26,26 @@ namespace {
uint32_t array[128];
};
struct Node {
Node(Node* n) : next(n) { created++; }
~Node() {
destroyed++;
if (next) {
next->~Node();
}
}
Node *next;
};
struct Start {
~Start() {
if (start) {
start->~Node();
}
}
Node* start;
};
}
struct WithDtor {
@ -63,7 +83,7 @@ DEF_TEST(ArenaAlloc, r) {
{
created = 0;
destroyed = 0;
char block[1024];
char block[64];
SkArenaAlloc arena{block};
REPORTER_ASSERT(r, *arena.make<int>(3) == 3);
@ -113,4 +133,30 @@ DEF_TEST(ArenaAlloc, r) {
}
REPORTER_ASSERT(r, created == 11);
REPORTER_ASSERT(r, destroyed == 11);
{
char storage[64];
SkArenaAlloc arena{storage};
arena.makeArrayDefault<char>(256);
arena.reset();
arena.reset();
}
{
created = 0;
destroyed = 0;
char storage[64];
SkArenaAlloc arena{storage};
Start start;
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);
}
start.start = current;
}
REPORTER_ASSERT(r, created == 128);
REPORTER_ASSERT(r, destroyed == 128);
}