Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(300)

Unified Diff: src/core/SkFunction.h

Issue 1048243002: small-object optimization for SkFunction (Closed) Base URL: https://skia.googlesource.com/skia@master
Patch Set: windows Created 5 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | src/utils/SkTLogic.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/core/SkFunction.h
diff --git a/src/core/SkFunction.h b/src/core/SkFunction.h
index 9ec421e2a6789c69db1d1691091dd80fbfe8151e..300959342139646064c533c12ef7d3a9bfab821a 100644
--- a/src/core/SkFunction.h
+++ b/src/core/SkFunction.h
@@ -11,6 +11,7 @@
// TODO: document
#include "SkTypes.h"
+#include "SkTLogic.h"
template <typename> class SkFunction;
@@ -23,31 +24,41 @@ public:
}
template <typename Fn>
- explicit SkFunction(Fn fn) : fVTable(GetVTable<Fn>()) {
- // We've got a functor. The basic thing we can always do is copy it onto the heap.
+ explicit SkFunction(Fn fn, SK_WHEN_C((sizeof(Fn) > sizeof(void*)), void*) = nullptr)
+ : fVTable(GetOutlineVTable<Fn>()) {
+ // We've got a functor larger than a pointer. We've go to copy it onto the heap.
fFunction = SkNEW_ARGS(Fn, (fn));
}
- ~SkFunction() { fVTable.fDelete(fFunction); }
+ template <typename Fn>
+ explicit SkFunction(Fn fn, SK_WHEN_C((sizeof(Fn) <= sizeof(void*)), void*) = nullptr)
+ : fVTable(GetInlineVTable<Fn>()) {
+ // We've got a functor that fits in a pointer. We copy it right inline.
+ SkNEW_PLACEMENT_ARGS(&fFunction, Fn, (fn));
+ }
+
+ ~SkFunction() { fVTable.fCleanUp(fFunction); }
R operator()(Args... args) { return fVTable.fCall(fFunction, args...); }
private:
struct VTable {
R (*fCall)(void*, Args...);
- void (*fDelete)(void*);
+ void (*fCleanUp)(void*);
};
+ // Used when fFunction is a function pointer of type R(*)(Args...).
static const VTable& GetFunctionPointerVTable() {
static const VTable vtable = {
[](void* fn, Args... args) { return reinterpret_cast<R(*)(Args...)>(fn)(args...); },
- [](void*) { /* Don't delete function pointers. */ },
+ [](void*) { /* Nothing to clean up for function pointers. */ }
};
return vtable;
}
+ // Used when fFunction is a pointer to a functor of type Fn on the heap (we own it).
template <typename Fn>
- static const VTable& GetVTable() {
+ static const VTable& GetOutlineVTable() {
static const VTable vtable = {
[](void* fn, Args... args) { return (*static_cast<Fn*>(fn))(args...); },
[](void* fn) { SkDELETE(static_cast<Fn*>(fn)); },
@@ -55,7 +66,25 @@ private:
return vtable;
}
- void* fFunction; // Either a function pointer, or a pointer to a functor.
+ // Used when fFunction _is_ a functor of type Fn, not a pointer to the functor.
+ template <typename Fn>
+ static const VTable& GetInlineVTable() {
+ static const VTable vtable = {
+ [](void* fn, Args... args) {
+ union { void* p; Fn f; } pun = { fn };
+ return pun.f(args...);
+ },
+ [](void* fn) {
+ union { void* p; Fn f; } pun = { fn };
+ pun.f.~Fn();
+ (void)(pun.f); // Otherwise, when ~Fn() is trivial, MSVC complains pun is unused.
+ }
+ };
+ return vtable;
+ }
+
+
+ void* fFunction; // A function pointer, a pointer to a functor, or an inlined functor.
const VTable& fVTable; // How to call, delete (and one day copy, move) fFunction.
};
@@ -65,6 +94,5 @@ private:
// - make SkFunction copyable
// - emulate std::forward for moveable functors (e.g. lambdas)
// - forward args too?
-// - implement small-object optimization to store functors inline
#endif//SkFunction_DEFINED
« no previous file with comments | « no previous file | src/utils/SkTLogic.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698