git.iko.soy/rowtype-yoga/purescript-native
on golang help sign in
C++: function pointer optimization
0711464Andy Arvanitis
pcc/include/purescript.cc+12−3
@@ -26,7 +26,8 @@ namespace PureScript {
26 case Type::String: new (&s) shared<string> (src.s); break; \
26 case Type::String: new (&s) shared<string> (src.s); break; \
27 case Type::Map: new (&m) shared<map> (src.m); break; \
27 case Type::Map: new (&m) shared<map> (src.m); break; \
28 case Type::Vector: new (&v) shared<vector> (src.v); break; \
28 case Type::Vector: new (&v) shared<vector> (src.v); break; \
29− case Type::Function: new (&f) shared<fn> (src.f); break; \
29+ case Type::Function: f = src.f; break; \
30+ case Type::Closure: new (&l) shared<closure> (src.l); break; \
30 case Type::EffFunction: new (&e) shared<eff_fn> (src.e); break; \
31 case Type::EffFunction: new (&e) shared<eff_fn> (src.e); break; \
31 case Type::Thunk: t = src.t; break; \
32 case Type::Thunk: t = src.t; break; \
32 case Type::Pointer: new (&p) shared<void> (src.p); break; \
33 case Type::Pointer: new (&p) shared<void> (src.p); break; \
@@ -44,7 +45,8 @@ namespace PureScript {
44 case Type::String: new (&s) shared<string> (std::move(src.s)); break; \
45 case Type::String: new (&s) shared<string> (std::move(src.s)); break; \
45 case Type::Map: new (&m) shared<map> (std::move(src.m)); break; \
46 case Type::Map: new (&m) shared<map> (std::move(src.m)); break; \
46 case Type::Vector: new (&v) shared<vector> (std::move(src.v)); break; \
47 case Type::Vector: new (&v) shared<vector> (std::move(src.v)); break; \
48+ case Type::Function: f = src.f; break; \
47− case Type::Function: new (&f) shared<fn> (std::move(src.f)); break; \
49+ case Type::Closure: new (&l) shared<closure> (std::move(src.l)); break; \
48 case Type::EffFunction: new (&e) shared<eff_fn> (std::move(src.e)); break; \
50 case Type::EffFunction: new (&e) shared<eff_fn> (std::move(src.e)); break; \
49 case Type::Thunk: t = src.t; break; \
51 case Type::Thunk: t = src.t; break; \
50 case Type::Pointer: new (&p) shared<void> (std::move(src.p)); break; \
52 case Type::Pointer: new (&p) shared<void> (std::move(src.p)); break; \
@@ -86,7 +88,8 @@ any::~any() {
86 case Type::String: s.~shared<string>(); break;
88 case Type::String: s.~shared<string>(); break;
87 case Type::Map: m.~shared<map>(); break;
89 case Type::Map: m.~shared<map>(); break;
88 case Type::Vector: v.~shared<vector>(); break;
90 case Type::Vector: v.~shared<vector>(); break;
89− case Type::Function: f.~shared<fn>(); break;
91+ case Type::Function: ; break;
92+ case Type::Closure: l.~shared<closure>(); break;
90 case Type::EffFunction: e.~shared<eff_fn>(); break;
93 case Type::EffFunction: e.~shared<eff_fn>(); break;
91 case Type::Thunk: ; break;
94 case Type::Thunk: ; break;
92 case Type::Pointer: p.~shared<void>(); break;
95 case Type::Pointer: p.~shared<void>(); break;
@@ -163,6 +166,9 @@ any::~any() {
163 if (type == Type::Function) {
166 if (type == Type::Function) {
164 return (*f)(arg);
167 return (*f)(arg);
165 }
168 }
169+ if (type == Type::Closure) {
170+ return (*l)(arg);
171+ }
166 const any* valuePtr = this;
172 const any* valuePtr = this;
167 do {
173 do {
168 assert(valuePtr->type == Type::Thunk);
174 assert(valuePtr->type == Type::Thunk);
@@ -170,6 +176,9 @@ any::~any() {
170 if (value.type == Type::Function) {
176 if (value.type == Type::Function) {
171 return (*value.f)(arg);
177 return (*value.f)(arg);
172 }
178 }
179+ if (value.type == Type::Closure) {
180+ return (*value.l)(arg);
181+ }
173 valuePtr = &value;
182 valuePtr = &value;
174 } while (valuePtr->type != Type::Unknown);
183 } while (valuePtr->type != Type::Unknown);
175 assert(false && "Unknown value type");
184 assert(false && "Unknown value type");
pcc/include/purescript.hh+13−5
@@ -56,6 +56,7 @@ class any {
56 Map,
56 Map,
57 Vector,
57 Vector,
58 Function,
58 Function,
59+ Closure,
59 EffFunction,
60 EffFunction,
60 Thunk,
61 Thunk,
61 Pointer
62 Pointer
@@ -69,7 +70,8 @@ class any {
69
70
70 using map = std::unordered_map<const map_key_t, const any, map_key_t::hasher, map_key_t::equal>;
71 using map = std::unordered_map<const map_key_t, const any, map_key_t::hasher, map_key_t::equal>;
71 using vector = std::vector<any>;
72 using vector = std::vector<any>;
73+ using fn = auto (*)(const any&) -> any;
72− using fn = std::function<any(const any&)>;
74+ using closure = std::function<any(const any&)>;
73 using eff_fn = std::function<any()>;
75 using eff_fn = std::function<any()>;
74 using thunk = auto (*)(const as_thunk) -> const any&;
76 using thunk = auto (*)(const as_thunk) -> const any&;
75
77
@@ -90,7 +92,8 @@ class any {
90 mutable shared<string> s;
92 mutable shared<string> s;
91 mutable shared<map> m;
93 mutable shared<map> m;
92 mutable shared<vector> v;
94 mutable shared<vector> v;
93− mutable shared<fn> f;
95+ mutable fn f;
96+ mutable shared<closure> l;
94 mutable shared<eff_fn> e;
97 mutable shared<eff_fn> e;
95 mutable thunk t;
98 mutable thunk t;
96 mutable shared<void> p;
99 mutable shared<void> p;
@@ -117,9 +120,14 @@ class any {
117 any(const vector& val) : type(Type::Vector), v(make_shared<vector>(val)) {}
120 any(const vector& val) : type(Type::Vector), v(make_shared<vector>(val)) {}
118 any(vector&& val) noexcept : type(Type::Vector), v(make_shared<vector>(std::move(val))) {}
121 any(vector&& val) noexcept : type(Type::Vector), v(make_shared<vector>(std::move(val))) {}
119
122
123+ template <typename T>
124+ any(const T& val, typename std::enable_if<std::is_convertible<T,fn>::value>::type* = 0)
125+ : type(Type::Function), f(val) {}
126+
120− template <typename T, typename = typename std::enable_if<!std::is_same<any,T>::value>::type>
127+ template <typename T, typename = typename std::enable_if<!std::is_same<any,T>::value &&
128+ !std::is_convertible<T,fn>::value>::type>
121− any(const T& val, typename std::enable_if<std::is_assignable<fn,T>::value>::type* = 0)
129+ any(const T& val, typename std::enable_if<std::is_assignable<closure,T>::value>::type* = 0)
122− : type(Type::Function), f(make_shared<fn>(val)) {}
130+ : type(Type::Closure), l(make_shared<closure>(val)) {}
123
131
124 template <typename T>
132 template <typename T>
125 any(const T& val, typename std::enable_if<std::is_assignable<eff_fn,T>::value>::type* = 0)
133 any(const T& val, typename std::enable_if<std::is_assignable<eff_fn,T>::value>::type* = 0)