diff options
author | 2017-01-23 21:20:09 +0100 | |
---|---|---|
committer | 2017-01-25 22:17:47 +0100 | |
commit | 25152bd69a070aa7ba84248b368b0803e407272a (patch) | |
tree | 7a0704f433857e91cbda2cda93dca07e643e075a /src/lib/netlist/plib/pconfig.h | |
parent | 093bda019317a5a66699b35f8b25ab73802f1f1c (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.h | 139 |
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_ */ |