summaryrefslogtreecommitdiffstats
path: root/src/lib/netlist/plib/pconfig.h
diff options
context:
space:
mode:
author couriersud <couriersud@gmx.org>2017-01-23 21:20:09 +0100
committer couriersud <couriersud@gmx.org>2017-01-25 22:17:47 +0100
commit25152bd69a070aa7ba84248b368b0803e407272a (patch)
tree7a0704f433857e91cbda2cda93dca07e643e075a /src/lib/netlist/plib/pconfig.h
parent093bda019317a5a66699b35f8b25ab73802f1f1c (diff)
Netlist refactoring:
- Refactored netlist pmf code. - Small optimization for diode calculations. - Minor refactoring across the board. (nw)
Diffstat (limited to 'src/lib/netlist/plib/pconfig.h')
-rw-r--r--src/lib/netlist/plib/pconfig.h139
1 files changed, 131 insertions, 8 deletions
diff --git a/src/lib/netlist/plib/pconfig.h b/src/lib/netlist/plib/pconfig.h
index 9cd917ceb28..198da5a4cc5 100644
--- a/src/lib/netlist/plib/pconfig.h
+++ b/src/lib/netlist/plib/pconfig.h
@@ -63,6 +63,42 @@ typedef __int128_t INT128;
// cut down delegate implementation
//============================================================
+/*
+ *
+ * NL_PMF_TYPE_GNUC_PMF
+ * Use standard pointer to member function syntax C++11
+ *
+ * NL_PMF_TYPE_GNUC_PMF_CONV
+ * Use gnu extension and convert the pmf to a function pointer.
+ * This is not standard compliant and needs
+ * -Wno-pmf-conversions to compile.
+ *
+ * NL_PMF_TYPE_INTERNAL
+ * Use the same approach as MAME for deriving the function pointer.
+ * This is compiler-dependent as well
+ *
+ * Benchmarks for ./nltool -c run -f src/mame/machine/nl_pong.cpp -t 10 -n pong_fast
+ *
+ * NL_PMF_TYPE_INTERNAL: 215% 215%
+ * NL_PMF_TYPE_GNUC_PMF: 163% 196%
+ * NL_PMF_TYPE_GNUC_PMF_CONV: 215% 215%
+ * NL_PMF_TYPE_VIRTUAL: 213% 209%
+ *
+ * The whole exercise was done to avoid virtual calls. In prior versions of
+ * netlist, the INTERNAL and GNUC_PMF_CONV approach provided significant improvement.
+ * Since than, "hot" was removed from functions declared as virtual.
+ * This may explain that the recent benchmarks show no difference at all.
+ *
+ */
+
+// This will be autodetected
+// #define PPMF_TYPE 1
+
+#define PPMF_TYPE_PMF 0
+#define PPMF_TYPE_GNUC_PMF_CONV 1
+#define PPMF_TYPE_INTERNAL 2
+
+
#if defined(__GNUC__)
/* does not work in versions over 4.7.x of 32bit MINGW */
#if defined(__MINGW32__) && !defined(__x86_64) && defined(__i386__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)))
@@ -87,6 +123,18 @@ typedef __int128_t INT128;
#define MEMBER_ABI
#endif
+#ifndef PPMF_TYPE
+ #if PHAS_PMF_INTERNAL
+ #define PPMF_TYPE PPMF_TYPE_INTERNAL
+ #else
+ #define PPMF_TYPE PPMF_TYPE_PMF
+ #endif
+#endif
+
+#if (PPMF_TYPE == PPMF_TYPE_GNUC_PMF_CONV)
+#pragma GCC diagnostic ignored "-Wpmf-conversions"
+#endif
+
namespace plib {
/*
* The following class was derived from the MAME delegate.h code.
@@ -108,18 +156,13 @@ namespace plib {
*reinterpret_cast<MemberFunctionType *>(this) = mftp;
}
- // binding helper
- template<typename FunctionType, typename ObjectType>
- FunctionType update_after_bind(ObjectType *object)
- {
- return reinterpret_cast<FunctionType>(
- convert_to_generic(reinterpret_cast<generic_class *>(object)));
- }
template<typename FunctionType, typename MemberFunctionType, typename ObjectType>
static FunctionType get_mfp(MemberFunctionType mftp, ObjectType *object)
{
mfp mfpo(mftp);
- return mfpo.update_after_bind<FunctionType>(object);
+ //return mfpo.update_after_bind<FunctionType>(object);
+ return reinterpret_cast<FunctionType>(
+ mfpo.convert_to_generic(reinterpret_cast<generic_class *>(object)));
}
private:
@@ -144,9 +187,89 @@ namespace plib {
// if odd, it's the byte offset into the vtable
int m_this_delta; // delta to apply to the 'this' pointer
};
+#endif
+
+#if (PPMF_TYPE == PPMF_TYPE_PMF)
+ template<typename R, typename... Targs>
+ class pmfp_base
+ {
+ public:
+ class generic_class;
+ using generic_function = R (generic_class::*)(Targs...);
+ pmfp_base() : m_func(nullptr) {}
+
+ template<typename MemberFunctionType, typename O>
+ void set_base(MemberFunctionType mftp, O *object)
+ {
+ using function_ptr = R (O::*)(Targs...);
+ function_ptr t = mftp;
+ m_func = reinterpret_cast<generic_function>(t);
+ }
+ template<typename O>
+ inline R call(O *obj, Targs... args) const
+ {
+ using function_ptr = R (O::*)(Targs...);
+ function_ptr t = reinterpret_cast<function_ptr>(m_func);
+ return (obj->*t)(std::forward<Targs>(args)...);
+ }
+ private:
+ generic_function m_func;
+ };
+#elif ((PPMF_TYPE == PPMF_TYPE_GNUC_PMF_CONV) || (PPMF_TYPE == PPMF_TYPE_INTERNAL))
+ template<typename R, typename... Targs>
+ class pmfp_base
+ {
+ public:
+ using generic_function = void (*)();
+
+ pmfp_base() : m_func(nullptr) {}
+
+ template<typename MemberFunctionType, typename O>
+ void set_base(MemberFunctionType mftp, O *object)
+ {
+ #if (PPMF_TYPE == PPMF_TYPE_INTERNAL)
+ using function_ptr = MEMBER_ABI R (*)(O *obj, Targs... args);
+ m_func = reinterpret_cast<generic_function>(plib::mfp::get_mfp<function_ptr>(mftp, object));
+ #elif (PPMF_TYPE == PPMF_TYPE_GNUC_PMF_CONV)
+ R (O::* pFunc)(Targs...) = mftp;
+ m_func = reinterpret_cast<generic_function>((object->*pFunc));
+ #endif
+ }
+ template<typename O>
+ inline R call(O *obj, Targs... args) const
+ {
+ using function_ptr = MEMBER_ABI R (*)(O *obj, Targs... args);
+ return (*reinterpret_cast<function_ptr>(m_func))(obj, std::forward<Targs>(args)...);
+ }
+ private:
+ generic_function m_func;
+ };
#endif
+ template<typename R, typename... Targs>
+ class pmfp : public pmfp_base<R, Targs...>
+ {
+ public:
+ class generic_class;
+ pmfp() : pmfp_base<R, Targs...>(), m_obj(nullptr) {}
+
+ template<typename MemberFunctionType, typename O>
+ void set(MemberFunctionType mftp, O *object)
+ {
+ this->set_base(mftp, object);
+ m_obj = reinterpret_cast<generic_class *>(object);
+ }
+
+ inline R operator()(Targs... args) const
+ {
+ return this->call(m_obj, std::forward<Targs>(args)...);
+ }
+ private:
+ generic_class *m_obj;
+ };
+
+
}
#endif /* PCONFIG_H_ */