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:
parent
95acbad4fe
commit
412a86d014
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user