diff options
-rw-r--r-- | src/core/SkArenaAlloc.cpp | 46 | ||||
-rw-r--r-- | src/core/SkArenaAlloc.h | 18 | ||||
-rw-r--r-- | tests/ArenaAllocTest.cpp | 48 |
3 files changed, 85 insertions, 27 deletions
diff --git a/src/core/SkArenaAlloc.cpp b/src/core/SkArenaAlloc.cpp index d6c249b573..03ab9fad4f 100644 --- a/src/core/SkArenaAlloc.cpp +++ b/src/core/SkArenaAlloc.cpp @@ -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) { +void SkArenaAlloc::ResetBlock(char* footerEnd) { + while (footerEnd != nullptr) { + footerEnd = CallFooterAction(footerEnd); + } +} + +char* SkArenaAlloc::CallFooterAction(char* footerEnd) { Footer footer; - memcpy(&footer, end - sizeof(Footer), sizeof(Footer)); + memcpy(&footer, footerEnd - sizeof(Footer), sizeof(Footer)); - FooterAction* releaser = (FooterAction*)((char*)EndChain + (footer >> 5)); + FooterAction* action = (FooterAction*)((char*)EndChain + (footer >> 5)); ptrdiff_t padding = footer & 31; - char* r = releaser(end) - padding; + char* r = action(footerEnd) - padding; return r; } diff --git a/src/core/SkArenaAlloc.h b/src/core/SkArenaAlloc.h index 8152c94cbd..56006c30b2 100644 --- a/src/core/SkArenaAlloc.h +++ b/src/core/SkArenaAlloc.h @@ -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 diff --git a/tests/ArenaAllocTest.cpp b/tests/ArenaAllocTest.cpp index 647ea25283..0836b0c49f 100644 --- a/tests/ArenaAllocTest.cpp +++ b/tests/ArenaAllocTest.cpp @@ -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); } |