aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core
diff options
context:
space:
mode:
authorGravatar Mike Klein <mtklein@chromium.org>2016-11-15 17:58:33 +0000
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2016-11-15 18:01:21 +0000
commit526525a37c2550ab4292a02a179ed5d5fe291919 (patch)
treeb76aad519850163a816032d41d37d654035b736d /src/core
parent02806f4dd5d388ec47efd414732857ecb2ff2b62 (diff)
Revert "While we can, restrict SkFixedAlloc/SkFallbackAlloc to POD."
This reverts commit 1ee70359a199f161ce38451989a706d727954cc1. Reason for revert: breaking my various rolls. Original change's description: > While we can, restrict SkFixedAlloc/SkFallbackAlloc to POD. > > This trims the overhead down to a uniform 4 bytes. > > BUG=skia: > > GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=4786 > > Change-Id: I92127a0c2d6c23a4a372eca39842e22195d2dc99 > Reviewed-on: https://skia-review.googlesource.com/4786 > Reviewed-by: Herb Derby <herb@google.com> > Commit-Queue: Mike Klein <mtklein@chromium.org> > TBR=mtklein@chromium.org,herb@google.com,reviews@skia.org NOPRESUBMIT=true NOTREECHECKS=true NOTRY=true Change-Id: Iae9ef553422352a1abf95b709fccd014d468da86 Reviewed-on: https://skia-review.googlesource.com/4829 Commit-Queue: Mike Klein <mtklein@chromium.org> Reviewed-by: Mike Klein <mtklein@chromium.org>
Diffstat (limited to 'src/core')
-rw-r--r--src/core/SkColorShader.cpp4
-rw-r--r--src/core/SkFixedAlloc.cpp43
-rw-r--r--src/core/SkFixedAlloc.h89
-rw-r--r--src/core/SkModeColorFilter.cpp2
4 files changed, 64 insertions, 74 deletions
diff --git a/src/core/SkColorShader.cpp b/src/core/SkColorShader.cpp
index 5551f1e630..69d9e46b27 100644
--- a/src/core/SkColorShader.cpp
+++ b/src/core/SkColorShader.cpp
@@ -317,7 +317,7 @@ bool SkColor4Shader::Color4Context::onChooseBlitProcs(const SkImageInfo& info, B
bool SkColorShader::onAppendStages(SkRasterPipeline* p,
SkColorSpace* dst,
SkFallbackAlloc* scratch) const {
- auto color = scratch->copy(SkPM4f_from_SkColor(fColor, dst));
+ auto color = scratch->make<SkPM4f>(SkPM4f_from_SkColor(fColor, dst));
p->append(SkRasterPipeline::move_src_dst);
p->append(SkRasterPipeline::constant_color, color);
if (!append_gamut_transform(p, scratch,
@@ -331,7 +331,7 @@ bool SkColorShader::onAppendStages(SkRasterPipeline* p,
bool SkColor4Shader::onAppendStages(SkRasterPipeline* p,
SkColorSpace* dst,
SkFallbackAlloc* scratch) const {
- auto color = scratch->copy(fColor4.premul());
+ auto color = scratch->make<SkPM4f>(fColor4.premul());
p->append(SkRasterPipeline::move_src_dst);
p->append(SkRasterPipeline::constant_color, color);
if (!append_gamut_transform(p, scratch, fColorSpace.get(), dst)) {
diff --git a/src/core/SkFixedAlloc.cpp b/src/core/SkFixedAlloc.cpp
index 420cdb24cd..133245a9cb 100644
--- a/src/core/SkFixedAlloc.cpp
+++ b/src/core/SkFixedAlloc.cpp
@@ -11,37 +11,23 @@ SkFixedAlloc::SkFixedAlloc(void* ptr, size_t len)
: fBuffer((char*)ptr), fUsed(0), fLimit(len) {}
void SkFixedAlloc::undo() {
- uint32_t skip_and_size;
- memcpy(&skip_and_size, fBuffer + fUsed - 4, 4);
- fUsed -= skip_and_size + 4;
-}
-
-void SkFixedAlloc::reset() {
- fUsed = 0;
-}
-
-void* SkFixedAlloc::alloc(size_t size, size_t align) {
- auto aligned = ((uintptr_t)(fBuffer+fUsed) + align-1) & ~(align-1);
- size_t skip = aligned - (uintptr_t)(fBuffer+fUsed);
+ // This function is essentially make() in reverse.
- if (!SkTFitsIn<uint32_t>(skip + size) ||
- fUsed + skip + size + 4 > fLimit) {
- return nullptr;
- }
+ // First, read the Footer we stamped at the end.
+ Footer footer;
+ memcpy(&footer, fBuffer + fUsed - sizeof(Footer), sizeof(Footer));
- // Skip ahead until aligned.
- fUsed += skip;
+ // That tells us where the T starts and how to destroy it.
+ footer.dtor(fBuffer + fUsed - sizeof(Footer) - footer.len);
- // Allocate size bytes.
- void* ptr = (fBuffer+fUsed);
- fUsed += size;
-
- // Stamp a footer that we can use to clean up.
- uint32_t skip_and_size = SkToU32(skip + size);
- memcpy(fBuffer+fUsed, &skip_and_size, 4);
- fUsed += 4;
+ // We can reuse bytes that stored the Footer, the T, and any that we skipped for alignment.
+ fUsed -= sizeof(Footer) + footer.len + footer.skip;
+}
- return ptr;
+void SkFixedAlloc::reset() {
+ while (fUsed) {
+ this->undo();
+ }
}
@@ -51,7 +37,8 @@ void SkFallbackAlloc::undo() {
if (fHeapAllocs.empty()) {
return fFixedAlloc->undo();
}
- sk_free(fHeapAllocs.back());
+ HeapAlloc alloc = fHeapAllocs.back();
+ alloc.deleter(alloc.ptr);
fHeapAllocs.pop_back();
}
diff --git a/src/core/SkFixedAlloc.h b/src/core/SkFixedAlloc.h
index 0f450576d9..d4e4d8f9de 100644
--- a/src/core/SkFixedAlloc.h
+++ b/src/core/SkFixedAlloc.h
@@ -11,51 +11,54 @@
#include "SkTFitsIn.h"
#include "SkTypes.h"
#include <new>
-#include <type_traits>
#include <utility>
#include <vector>
-// Before GCC 5, is_trivially_copyable had a pre-standard name.
-#if defined(__GLIBCXX__) && (__GLIBCXX__ < 20150801)
- namespace std {
- template <typename T>
- using is_trivially_copyable = has_trivial_copy_constructor<T>;
- }
-#endif
-
-// SkFixedAlloc allocates POD objects out of a fixed-size buffer.
+// SkFixedAlloc allocates objects out of a fixed-size buffer and destroys them when destroyed.
class SkFixedAlloc {
public:
SkFixedAlloc(void* ptr, size_t len);
~SkFixedAlloc() { this->reset(); }
- // Allocates space suitable for a T. If we can't, returns nullptr.
- template <typename T>
- void* alloc() {
- static_assert(std::is_standard_layout <T>::value
- && std::is_trivially_copyable<T>::value, "");
- return this->alloc(sizeof(T), alignof(T));
- }
-
+ // Allocates a new T in the buffer if possible. If not, returns nullptr.
template <typename T, typename... Args>
T* make(Args&&... args) {
- if (auto ptr = this->alloc<T>()) {
- return new (ptr) T(std::forward<Args>(args)...);
+ auto aligned = ((uintptr_t)(fBuffer+fUsed) + alignof(T) - 1) & ~(alignof(T)-1);
+ size_t skip = aligned - (uintptr_t)(fBuffer+fUsed);
+
+ if (!SkTFitsIn<uint32_t>(skip) ||
+ !SkTFitsIn<uint32_t>(sizeof(T)) ||
+ fUsed + skip + sizeof(T) + sizeof(Footer) > fLimit) {
+ return nullptr;
}
- return nullptr;
- }
- template <typename T>
- T* copy(const T& src) { return this->make<T>(src); }
+ // Skip ahead until our buffer is aligned for T.
+ fUsed += skip;
+
+ // Create the T.
+ auto ptr = (T*)(fBuffer+fUsed);
+ new (ptr) T(std::forward<Args>(args)...);
+ fUsed += sizeof(T);
- // Frees the space of the last object allocated.
+ // Stamp a footer after the T that we can use to clean it up.
+ Footer footer = { [](void* ptr) { ((T*)ptr)->~T(); }, SkToU32(skip), SkToU32(sizeof(T)) };
+ memcpy(fBuffer+fUsed, &footer, sizeof(Footer));
+ fUsed += sizeof(Footer);
+
+ return ptr;
+ }
+
+ // Destroys the last object allocated and frees its space in the buffer.
void undo();
- // Frees all space in the buffer.
+ // Destroys all objects and frees all space in the buffer.
void reset();
private:
- void* alloc(size_t, size_t);
+ struct Footer {
+ void (*dtor)(void*);
+ uint32_t skip, len;
+ };
char* fBuffer;
size_t fUsed, fLimit;
@@ -66,34 +69,34 @@ public:
explicit SkFallbackAlloc(SkFixedAlloc*);
~SkFallbackAlloc() { this->reset(); }
- template <typename T>
- void* alloc() {
- // Once we go heap we never go back to fixed. This keeps undo() working.
+ // Allocates a new T with the SkFixedAlloc if possible. If not, uses the heap.
+ template <typename T, typename... Args>
+ T* make(Args&&... args) {
+ // Once we go heap we never go back to fixed. This keeps destructor ordering sane.
if (fHeapAllocs.empty()) {
- if (void* ptr = fFixedAlloc->alloc<T>()) {
+ if (T* ptr = fFixedAlloc->make<T>(std::forward<Args>(args)...)) {
return ptr;
}
}
- void* ptr = sk_malloc_throw(sizeof(T));
- fHeapAllocs.push_back(ptr);
+ auto ptr = new T(std::forward<Args>(args)...);
+ fHeapAllocs.push_back({[](void* ptr) { delete (T*)ptr; }, ptr});
return ptr;
}
- template <typename T, typename... Args>
- T* make(Args&&... args) { return new (this->alloc<T>()) T(std::forward<Args>(args)...); }
-
- template <typename T>
- T* copy(const T& src) { return this->make<T>(src); }
-
- // Frees the last object allocated, including any space it used in the SkFixedAlloc.
+ // Destroys the last object allocated and frees any space it used in the SkFixedAlloc.
void undo();
- // Frees all objects and all space in the SkFixedAlloc.
+ // Destroys all objects and frees all space in the SkFixedAlloc.
void reset();
private:
- SkFixedAlloc* fFixedAlloc;
- std::vector<void*> fHeapAllocs;
+ struct HeapAlloc {
+ void (*deleter)(void*);
+ void* ptr;
+ };
+
+ SkFixedAlloc* fFixedAlloc;
+ std::vector<HeapAlloc> fHeapAllocs;
};
#endif//SkFixedAlloc_DEFINED
diff --git a/src/core/SkModeColorFilter.cpp b/src/core/SkModeColorFilter.cpp
index 1eb2946170..9c76f9efed 100644
--- a/src/core/SkModeColorFilter.cpp
+++ b/src/core/SkModeColorFilter.cpp
@@ -90,7 +90,7 @@ bool SkModeColorFilter::onAppendStages(SkRasterPipeline* p,
SkColorSpace* dst,
SkFallbackAlloc* scratch,
bool shaderIsOpaque) const {
- auto color = scratch->copy(SkPM4f_from_SkColor(fColor, dst));
+ auto color = scratch->make<SkPM4f>(SkPM4f_from_SkColor(fColor, dst));
p->append(SkRasterPipeline::move_src_dst);
p->append(SkRasterPipeline::constant_color, color);