Netlist: It is now possible to have multiple handlers per device ...

... for updates. This will make device implementation more flexible and
faster. A nice side-effect is that there was some minor (<5%)
performance increase already. Each input is now assigned a notification
handler. Currently this is update, but going forward this may be a
custom handler. In addition
- fixed MEMPOOL on OSX
- removed dead code
- avoid bit-rot
- added delegate support for emscripten and arm processors
- added delegate support for VS 2015 x64
[Couriersud]
This commit is contained in:
couriersud 2017-02-04 01:23:12 +01:00
parent 427cf984db
commit 70051f6c1f
12 changed files with 232 additions and 115 deletions

View File

@ -172,15 +172,18 @@ maketree: $(sort $(OBJDIRS))
# Special targets # Special targets
#------------------------------------------------- #-------------------------------------------------
.PHONY: clang mingw doc .PHONY: clang clang-5 mingw doc
clang: clang:
$(MAKE) CC=clang++-5.0 LD=clang++-5.0 CEXTRAFLAGS="-march=native -Weverything -Werror -Wno-padded -Wno-weak-vtables -Wno-missing-variable-declarations -Wconversion -Wno-c++98-compat -Wno-float-equal -Wno-global-constructors -Wno-c++98-compat-pedantic -Wno-format-nonliteral -Wno-weak-template-vtables -Wno-exit-time-destructors" $(MAKE) CC=clang++ LD=clang++ CEXTRAFLAGS="-march=native -Weverything -Werror -Wno-padded -Wno-weak-vtables -Wno-missing-variable-declarations -Wconversion -Wno-c++98-compat -Wno-float-equal -Wno-global-constructors -Wno-c++98-compat-pedantic -Wno-format-nonliteral -Wno-weak-template-vtables -Wno-exit-time-destructors"
clang-5:
$(MAKE) CC=clang++-5.0 LD=clang++-5.0 CEXTRAFLAGS="-march=native -Weverything -Werror -Wno-unreachable-code -Wno-padded -Wno-weak-vtables -Wno-missing-variable-declarations -Wconversion -Wno-c++98-compat -Wno-float-equal -Wno-global-constructors -Wno-c++98-compat-pedantic -Wno-format-nonliteral -Wno-weak-template-vtables -Wno-exit-time-destructors"
# #
# Mostly done: -Wno-weak-vtables -Wno-cast-align # Mostly done: -Wno-weak-vtables -Wno-cast-align
# FIXME: -Wno-weak-vtables -Wno-missing-variable-declarations -Wno-conversion -Wno-exit-time-destructors # FIXME: -Wno-weak-vtables -Wno-missing-variable-declarations -Wno-conversion -Wno-exit-time-destructors
# # FIXME: -Wunreachable-code : False warnings, this a documented clang bug: https://llvm.org/bugs/show_bug.cgi?id=28994
mingw: mingw:
$(MAKE) LDEXTRAFLAGS="-Wl,--subsystem,console" LIBS= MD=@mkdir.exe SHELL=sh.exe $(MAKE) LDEXTRAFLAGS="-Wl,--subsystem,console" LIBS= MD=@mkdir.exe SHELL=sh.exe

View File

@ -15,14 +15,8 @@
#define xstr(s) # s #define xstr(s) # s
#if 0
#define ENTRY1(nic, name, defparam) factory.register_device<nic>( # name, xstr(nic), defparam );
#define ENTRY(nic, name, defparam) ENTRY1(NETLIB_NAME(nic), name, defparam)
#endif
#define NETLIB_DEVICE_DECL(chip) extern factory::constructor_ptr_t decl_ ## chip; #define NETLIB_DEVICE_DECL(chip) extern factory::constructor_ptr_t decl_ ## chip;
//#define ENTRYX1(nic, name, defparam, decl) factory.register_device( decl (# name, xstr(nic), defparam) );
#define ENTRYX1(nic, name, defparam, decl) factory.register_device( decl (pstring(# name), pstring(xstr(nic)), pstring(defparam)) ); #define ENTRYX1(nic, name, defparam, decl) factory.register_device( decl (pstring(# name), pstring(xstr(nic)), pstring(defparam)) );
#define ENTRYX(nic, name, defparam) { NETLIB_DEVICE_DECL(nic) ENTRYX1(NETLIB_NAME(nic), name, defparam, decl_ ## nic) } #define ENTRYX(nic, name, defparam) { NETLIB_DEVICE_DECL(nic) ENTRYX1(NETLIB_NAME(nic), name, defparam, decl_ ## nic) }

View File

@ -22,6 +22,8 @@ namespace netlist
{ {
} }
NETLIB_UPDATEI();
public: public:
void shift(); void shift();
@ -109,6 +111,11 @@ namespace netlist
m_last_CP = m_CP(); m_last_CP = m_CP();
} }
NETLIB_UPDATE(Am2847_shifter)
{
/* do nothing */
}
inline NETLIB_FUNC_VOID(Am2847_shifter, shift, (void)) inline NETLIB_FUNC_VOID(Am2847_shifter, shift, (void))
{ {
uint32_t out = m_buffer[0] & 1; uint32_t out = m_buffer[0] & 1;

View File

@ -25,31 +25,35 @@ namespace netlist
{ {
namespace detail namespace detail
{ {
#if (USE_MEMPOOL)
static plib::mempool pool(6553600, 64);
void * object_t::operator new (size_t size) static plib::mempool *pool()
{ {
return pool.alloc(size); static plib::mempool *s_pool = nullptr;
} if (s_pool == nullptr)
s_pool = new plib::mempool(65536, 16);
return s_pool;
}
void object_t::operator delete (void * mem) void * object_t::operator new (size_t size)
{ {
if (mem) void *ret = nullptr;
pool.free(mem); if ((USE_MEMPOOL))
} ret = pool()->alloc(size);
#else else
void * object_t::operator new (size_t size) ret = ::operator new(size);
{ return ret;
return ::operator new(size); }
}
void object_t::operator delete (void * mem) void object_t::operator delete (void * mem)
{ {
if (mem) if (mem)
::operator delete(mem); {
} if ((USE_MEMPOOL))
#endif pool()->free(mem);
else
::operator delete(mem);
}
}
} }
@ -361,12 +365,6 @@ void netlist_t::start()
/* resolve inputs */ /* resolve inputs */
setup().resolve_inputs(); setup().resolve_inputs();
/* Make sure devices are fully created - now done in register_dev */
log().debug("Setting delegate pointers ...\n");
for (auto &dev : m_devices)
dev->set_delegate_pointer();
log().verbose("looking for two terms connected to rail nets ..."); log().verbose("looking for two terms connected to rail nets ...");
for (auto & t : get_device_list<analog::NETLIB_NAME(twoterm)>()) for (auto & t : get_device_list<analog::NETLIB_NAME(twoterm)>())
{ {
@ -391,6 +389,14 @@ void netlist_t::start()
else else
m_solver->post_start(); m_solver->post_start();
for (auto &n : m_nets)
for (auto & term : n->m_core_terms)
{
//core_device_t *dev = reinterpret_cast<core_device_t *>(term->m_delegate.object());
core_device_t *dev = &term->device();
dev->set_default_delegate(*term);
}
} }
void netlist_t::stop() void netlist_t::stop()
@ -427,6 +433,14 @@ void netlist_t::reset()
//if (m_solver != nullptr) //if (m_solver != nullptr)
// m_solver->do_reset(); // m_solver->do_reset();
std::unordered_map<core_device_t *, bool> m;
for (auto &d : m_devices)
{
m[d.get()] = d->get_hint_deactivate();
}
// Reset all nets once ! // Reset all nets once !
for (auto & n : m_nets) for (auto & n : m_nets)
n->reset(); n->reset();
@ -444,15 +458,66 @@ void netlist_t::reset()
* INFO: The order here affects power up of e.g. breakout. However, such * INFO: The order here affects power up of e.g. breakout. However, such
* variations are explicitly stated in the breakout manual. * variations are explicitly stated in the breakout manual.
*/ */
#if 0
for (std::size_t i = 0; i < m_devices.size(); i++) const unsigned startup_strategy = 1; //! \note make this a parameter
switch (startup_strategy)
{ {
m_devices[i]->update_dev(); case 0:
{
std::vector<core_device_t *> d;
std::vector<nldelegate *> t;
log().verbose("Using default startup strategy");
for (auto &n : m_nets)
for (auto & term : n->m_core_terms)
if (term->m_delegate.has_object())
{
if (!plib::container::contains(t, &term->m_delegate))
{
t.push_back(&term->m_delegate);
term->m_delegate();
}
core_device_t *dev = reinterpret_cast<core_device_t *>(term->m_delegate.object());
if (!plib::container::contains(d, dev))
d.push_back(dev);
}
log().verbose("Call update on devices which need parameter update:");
for (auto & dev : m_devices)
if (dev->needs_update_after_param_change())
{
if (!plib::container::contains(d, dev.get()))
{
d.push_back(dev.get());
log().verbose("\t ...{1}", dev->name());
dev->update_dev();
}
}
log().verbose("Devices not yet updated:");
for (auto &dev : m_devices)
if (!plib::container::contains(d, dev.get()))
log().verbose("\t ...{1}", dev->name());
//x->update_dev();
}
break;
case 1: // brute force backward
{
std::size_t i = m_devices.size();
while (i>0)
m_devices[--i]->update_dev();
}
break;
case 2: // brute force forward
{
for (std::size_t i = 0; i < m_devices.size(); i++)
m_devices[i]->update_dev();
}
break;
} }
#else
std::size_t i = m_devices.size(); #if 1
while (i>0) /* the above may screw up m_active and the list */
m_devices[--i]->update_dev(); for (auto &n : m_nets)
n->rebuild_list();
#endif #endif
} }
@ -594,9 +659,6 @@ core_device_t::core_device_t(netlist_t &owner, const pstring &name)
, logic_family_t() , logic_family_t()
, netlist_ref(owner) , netlist_ref(owner)
, m_hint_deactivate(false) , m_hint_deactivate(false)
#if (!NL_USE_PMF_VIRTUAL)
, m_static_update()
#endif
{ {
if (logic_family() == nullptr) if (logic_family() == nullptr)
set_logic_family(family_TTL()); set_logic_family(family_TTL());
@ -607,9 +669,6 @@ core_device_t::core_device_t(core_device_t &owner, const pstring &name)
, logic_family_t() , logic_family_t()
, netlist_ref(owner.netlist()) , netlist_ref(owner.netlist())
, m_hint_deactivate(false) , m_hint_deactivate(false)
#if (!NL_USE_PMF_VIRTUAL)
, m_static_update()
#endif
{ {
set_logic_family(owner.logic_family()); set_logic_family(owner.logic_family());
if (logic_family() == nullptr) if (logic_family() == nullptr)
@ -621,11 +680,9 @@ core_device_t::~core_device_t()
{ {
} }
void core_device_t::set_delegate_pointer() void core_device_t::set_default_delegate(detail::core_terminal_t &term)
{ {
#if (!NL_USE_PMF_VIRTUAL) term.m_delegate.set(&core_device_t::update, this);
m_static_update.set_base(&core_device_t::update, this);
#endif
} }
plib::plog_base<NL_DEBUG> &core_device_t::log() plib::plog_base<NL_DEBUG> &core_device_t::log()
@ -789,7 +846,7 @@ void detail::net_t::update_devs() NL_NOEXCEPT
{ {
p.device().m_stat_call_count.inc(); p.device().m_stat_call_count.inc();
if ((p.state() & mask) != 0) if ((p.state() & mask) != 0)
p.device().update_dev(); p.m_delegate();
} }
} }
@ -891,6 +948,8 @@ detail::core_terminal_t::core_terminal_t(core_device_t &dev, const pstring &anam
, m_net(nullptr) , m_net(nullptr)
, m_state(*this, "m_state", state) , m_state(*this, "m_state", state)
{ {
//m_delegate.set(&core_device_t::update, &dev);
//m_delegate.set(&core_device_t::update_dev, &dev);
} }
detail::core_terminal_t::~core_terminal_t() detail::core_terminal_t::~core_terminal_t()

View File

@ -455,6 +455,10 @@ namespace netlist
core_device_t & m_device; core_device_t & m_device;
}; };
/*! Delegate type for device notification.
*
*/
typedef plib::pmfp<void> nldelegate;
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// core_terminal_t // core_terminal_t
@ -509,6 +513,8 @@ namespace netlist
void reset(); void reset();
nldelegate m_delegate;
private: private:
net_t * m_net; net_t * m_net;
state_var<state_e> m_state; state_var<state_e> m_state;
@ -1044,14 +1050,16 @@ namespace netlist
void do_reset() { reset(); } void do_reset() { reset(); }
void set_hint_deactivate(bool v) { m_hint_deactivate = v; } void set_hint_deactivate(bool v) { m_hint_deactivate = v; }
bool get_hint_deactivate() { return m_hint_deactivate; }
void set_delegate_pointer(); void set_default_delegate(detail::core_terminal_t &term);
/* stats */ /* stats */
nperftime_t m_stat_total_time; nperftime_t m_stat_total_time;
nperfcount_t m_stat_call_count; nperfcount_t m_stat_call_count;
nperfcount_t m_stat_inc_active; nperfcount_t m_stat_inc_active;
protected: protected:
virtual void update() NL_NOEXCEPT { } virtual void update() NL_NOEXCEPT { }
@ -1061,11 +1069,7 @@ namespace netlist
void do_update() NL_NOEXCEPT void do_update() NL_NOEXCEPT
{ {
#if (NL_USE_PMF_VIRTUAL)
update(); update();
#else
m_static_update.call(this);
#endif
} }
plib::plog_base<NL_DEBUG> &log(); plib::plog_base<NL_DEBUG> &log();
@ -1081,10 +1085,6 @@ namespace netlist
private: private:
bool m_hint_deactivate; bool m_hint_deactivate;
#if (!NL_USE_PMF_VIRTUAL)
plib::pmfp_base<void> m_static_update;
#endif
}; };
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------

View File

@ -95,16 +95,6 @@ using nl_double = double;
* approach will be automatically selected. * approach will be automatically selected.
*/ */
//#define NL_USE_PMF_VIRTUAL 1
#ifndef NL_USE_PMF_VIRTUAL
#if PPMF_TYPE == PPMF_TYPE_PMF
#define NL_USE_PMF_VIRTUAL 1
#else
#define NL_USE_PMF_VIRTUAL 0
#endif
#endif
//============================================================ //============================================================
// WARNINGS // WARNINGS
//============================================================ //============================================================
@ -115,9 +105,4 @@ using nl_double = double;
#endif #endif
#endif #endif
#ifdef __APPLE__
#undef USE_MEMPOOL
#define USE_MEMPOOL (0)
#endif
#endif /* NLCONFIG_H_ */ #endif /* NLCONFIG_H_ */

View File

@ -54,7 +54,7 @@ namespace netlist
struct entry_t final struct entry_t final
{ {
constexpr entry_t() { } constexpr entry_t() : m_exec_time(), m_object(nullptr) { }
constexpr entry_t(const Time &t, const Element &o) : m_exec_time(t), m_object(o) { } constexpr entry_t(const Time &t, const Element &o) : m_exec_time(t), m_object(o) { }
constexpr entry_t(const entry_t &e) : m_exec_time(e.m_exec_time), m_object(e.m_object) { } constexpr entry_t(const entry_t &e) : m_exec_time(e.m_exec_time), m_object(e.m_object) { }
constexpr entry_t(entry_t &&e) : m_exec_time(e.m_exec_time), m_object(e.m_object) { } constexpr entry_t(entry_t &&e) : m_exec_time(e.m_exec_time), m_object(e.m_object) { }

23
src/lib/netlist/plib/palloc.cpp Normal file → Executable file
View File

@ -5,6 +5,8 @@
* *
*/ */
#include <algorithm>
#include "pconfig.h" #include "pconfig.h"
#include "palloc.h" #include "palloc.h"
#include "pfmtlog.h" #include "pfmtlog.h"
@ -27,7 +29,7 @@ mempool::~mempool()
{ {
fprintf(stderr, "Found block with %d dangling allocations\n", static_cast<int>(b.m_num_alloc)); fprintf(stderr, "Found block with %d dangling allocations\n", static_cast<int>(b.m_num_alloc));
} }
delete b.data; ::operator delete(b.data);
} }
m_blocks.clear(); m_blocks.clear();
} }
@ -35,7 +37,7 @@ mempool::~mempool()
size_t mempool::new_block() size_t mempool::new_block()
{ {
block b; block b;
b.data = new char[m_min_alloc]; b.data = static_cast<char *>(::operator new(m_min_alloc));
b.cur_ptr = b.data; b.cur_ptr = b.data;
b.m_free = m_min_alloc; b.m_free = m_min_alloc;
b.m_num_alloc = 0; b.m_num_alloc = 0;
@ -43,10 +45,19 @@ size_t mempool::new_block()
return m_blocks.size() - 1; return m_blocks.size() - 1;
} }
size_t mempool::mininfosize()
{
size_t sinfo = sizeof(mempool::info);
size_t ma = 8;
#ifdef __APPLE__
ma = 16;
#endif
return ((std::max(m_min_align, sinfo) + ma - 1) / ma) * ma;
}
void *mempool::alloc(size_t size) void *mempool::alloc(size_t size)
{ {
size_t rs = (size + sizeof(info) + m_min_align - 1) & ~(m_min_align - 1); size_t rs = (size + mininfosize() + m_min_align - 1) & ~(m_min_align - 1);
for (size_t bn=0; bn < m_blocks.size(); bn++) for (size_t bn=0; bn < m_blocks.size(); bn++)
{ {
auto &b = m_blocks[bn]; auto &b = m_blocks[bn];
@ -56,7 +67,7 @@ void *mempool::alloc(size_t size)
b.m_num_alloc++; b.m_num_alloc++;
auto i = reinterpret_cast<info *>(b.cur_ptr); auto i = reinterpret_cast<info *>(b.cur_ptr);
i->m_block = bn; i->m_block = bn;
auto ret = reinterpret_cast<void *>(b.cur_ptr + sizeof(info)); auto ret = reinterpret_cast<void *>(b.cur_ptr + mininfosize());
b.cur_ptr += rs; b.cur_ptr += rs;
return ret; return ret;
} }
@ -68,7 +79,7 @@ void *mempool::alloc(size_t size)
b.m_free = m_min_alloc - rs; b.m_free = m_min_alloc - rs;
auto i = reinterpret_cast<info *>(b.cur_ptr); auto i = reinterpret_cast<info *>(b.cur_ptr);
i->m_block = bn; i->m_block = bn;
auto ret = reinterpret_cast<void *>(b.cur_ptr + sizeof(info)); auto ret = reinterpret_cast<void *>(b.cur_ptr + mininfosize());
b.cur_ptr += rs; b.cur_ptr += rs;
return ret; return ret;
} }
@ -78,7 +89,7 @@ void mempool::free(void *ptr)
{ {
auto p = reinterpret_cast<char *>(ptr); auto p = reinterpret_cast<char *>(ptr);
auto i = reinterpret_cast<info *>(p - sizeof(info)); auto i = reinterpret_cast<info *>(p - mininfosize());
block *b = &m_blocks[i->m_block]; block *b = &m_blocks[i->m_block];
if (b->m_num_alloc == 0) if (b->m_num_alloc == 0)
fprintf(stderr, "Argh .. double free\n"); fprintf(stderr, "Argh .. double free\n");

View File

@ -144,6 +144,7 @@ private:
}; };
size_t new_block(); size_t new_block();
size_t mininfosize();
struct info struct info
{ {
@ -151,6 +152,11 @@ private:
size_t m_block; size_t m_block;
}; };
size_t m_min_alloc;
size_t m_min_align;
std::vector<block> m_blocks;
public: public:
mempool(size_t min_alloc, size_t min_align); mempool(size_t min_alloc, size_t min_align);
~mempool(); ~mempool();
@ -158,10 +164,6 @@ public:
void *alloc(size_t size); void *alloc(size_t size);
void free(void *ptr); void free(void *ptr);
size_t m_min_alloc;
size_t m_min_align;
std::vector<block> m_blocks;
}; };
} }

10
src/lib/netlist/plib/pconfig.h Normal file → Executable file
View File

@ -71,13 +71,13 @@ typedef __int128_t INT128;
#define MEMBER_ABI _thiscall #define MEMBER_ABI _thiscall
#elif defined(__clang__) && defined(__i386__) && defined(_WIN32) #elif defined(__clang__) && defined(__i386__) && defined(_WIN32)
#define PHAS_PMF_INTERNAL 0 #define PHAS_PMF_INTERNAL 0
#elif defined(EMSCRIPTEN) #elif defined(__arm__) || defined(__ARMEL__) || defined(__aarch64__) || defined(__MIPSEL__) || defined(__mips_isa_rev) || defined(__mips64) || defined(EMSCRIPTEN)
#define PHAS_PMF_INTERNAL 0 #define PHAS_PMF_INTERNAL 2
#elif defined(__arm__) || defined(__ARMEL__)
#define PHAS_PMF_INTERNAL 0
#else #else
#define PHAS_PMF_INTERNAL 1 #define PHAS_PMF_INTERNAL 1
#endif #endif
#elif defined(_MSC_VER) && defined (_M_X64)
#define PHAS_PMF_INTERNAL 3
#else #else
#define PHAS_PMF_INTERNAL 0 #define PHAS_PMF_INTERNAL 0
#endif #endif
@ -87,7 +87,7 @@ typedef __int128_t INT128;
#endif #endif
#ifndef PPMF_TYPE #ifndef PPMF_TYPE
#if PHAS_PMF_INTERNAL #if (PHAS_PMF_INTERNAL > 0)
#define PPMF_TYPE PPMF_TYPE_INTERNAL #define PPMF_TYPE PPMF_TYPE_INTERNAL
#else #else
#define PPMF_TYPE PPMF_TYPE_PMF #define PPMF_TYPE PPMF_TYPE_PMF

95
src/lib/netlist/plib/ppmf.h Normal file → Executable file
View File

@ -51,44 +51,82 @@ namespace plib {
* It derives a pointer to a member function. * It derives a pointer to a member function.
*/ */
#if (PHAS_PMF_INTERNAL) #if (PHAS_PMF_INTERNAL > 0)
class mfp class mfp
{ {
public: public:
// construct from any member function pointer // construct from any member function pointer
#ifdef _MSC_VER
class __single_inheritance si_generic_class;
class generic_class { };
#else
class generic_class; class generic_class;
#endif
using generic_function = void (*)(); using generic_function = void (*)();
template<typename MemberFunctionType> template<typename MemberFunctionType>
mfp(MemberFunctionType mftp) mfp(MemberFunctionType mftp)
: m_function(0), m_this_delta(0) : m_function(0), m_this_delta(0), m_size(sizeof(mfp))
{ {
*reinterpret_cast<MemberFunctionType *>(this) = mftp; *reinterpret_cast<MemberFunctionType *>(this) = mftp;
} }
template<typename FunctionType, typename MemberFunctionType, typename ObjectType> template<typename MemberFunctionType, typename FunctionType, typename ObjectType>
static FunctionType get_mfp(MemberFunctionType mftp, ObjectType *object) static void get_mfp(MemberFunctionType mftp, FunctionType &func, ObjectType *&object)
{ {
mfp mfpo(mftp); mfp mfpo(mftp);
//return mfpo.update_after_bind<FunctionType>(object); //return mfpo.update_after_bind<FunctionType>(object);
return reinterpret_cast<FunctionType>( generic_function rfunc(nullptr);
mfpo.convert_to_generic(reinterpret_cast<generic_class *>(object))); generic_class *robject = reinterpret_cast<generic_class *>(object);
mfpo.convert_to_generic(rfunc, robject);
func = reinterpret_cast<FunctionType>(rfunc);
object = reinterpret_cast<ObjectType *>(robject);
} }
private: private:
// extract the generic function and adjust the object pointer // extract the generic function and adjust the object pointer
generic_function convert_to_generic(generic_class * object) const void convert_to_generic(generic_function &func, generic_class *&object) const
{ {
// apply the "this" delta to the object first if (PHAS_PMF_INTERNAL == 1)
generic_class * o_p_delta = reinterpret_cast<generic_class *>(reinterpret_cast<std::uint8_t *>(object) + m_this_delta); {
// apply the "this" delta to the object first
generic_class * o_p_delta = reinterpret_cast<generic_class *>(reinterpret_cast<std::uint8_t *>(object) + m_this_delta);
// if the low bit of the vtable index is clear, then it is just a raw function pointer // if the low bit of the vtable index is clear, then it is just a raw function pointer
if (!(m_function & 1)) if (!(m_function & 1))
return reinterpret_cast<generic_function>(m_function); func = reinterpret_cast<generic_function>(m_function);
else
{
// otherwise, it is the byte index into the vtable where the actual function lives
std::uint8_t *vtable_base = *reinterpret_cast<std::uint8_t **>(o_p_delta);
func = *reinterpret_cast<generic_function *>(vtable_base + m_function - 1);
}
object = o_p_delta;
}
else if (PHAS_PMF_INTERNAL == 2)
{
if ((m_this_delta & 1) == 0) {
object = reinterpret_cast<generic_class *>(reinterpret_cast<std::uint8_t *>(object) + m_this_delta);
func = reinterpret_cast<generic_function>(m_function);
}
else
{
object = reinterpret_cast<generic_class *>(reinterpret_cast<std::uint8_t *>(object));
// otherwise, it is the byte index into the vtable where the actual function lives
std::uint8_t *vtable_base = *reinterpret_cast<std::uint8_t **>(object);
func = *reinterpret_cast<generic_function *>(vtable_base + m_function + m_this_delta - 1);
}
}
else if (PHAS_PMF_INTERNAL == 3)
{
const int SINGLE_MEMFUNCPTR_SIZE = sizeof(void (generic_class::*)());
func = reinterpret_cast<generic_function>(m_function);
if (m_size == SINGLE_MEMFUNCPTR_SIZE + sizeof(int))
object = reinterpret_cast<generic_class *>(reinterpret_cast<std::uint8_t *>(object) + m_this_delta);
}
// otherwise, it is the byte index into the vtable where the actual function lives
std::uint8_t *vtable_base = *reinterpret_cast<std::uint8_t **>(o_p_delta);
return *reinterpret_cast<generic_function *>(vtable_base + m_function - 1);
} }
// actual state // actual state
@ -96,6 +134,10 @@ namespace plib {
// if even, it's a pointer to the function // if even, it's a pointer to the function
// if odd, it's the byte offset into the vtable // if odd, it's the byte offset into the vtable
int m_this_delta; // delta to apply to the 'this' pointer int m_this_delta; // delta to apply to the 'this' pointer
int m_dummy1; // only used for visual studio x64
int m_dummy2;
int m_size;
}; };
#endif #endif
@ -107,12 +149,18 @@ namespace plib {
class generic_class; class generic_class;
#if defined (__INTEL_COMPILER) && defined (_M_X64) // needed for "Intel(R) C++ Intel(R) 64 Compiler XE for applications running on Intel(R) 64, Version 14.0.2.176 Build 20140130" at least #if defined (__INTEL_COMPILER) && defined (_M_X64) // needed for "Intel(R) C++ Intel(R) 64 Compiler XE for applications running on Intel(R) 64, Version 14.0.2.176 Build 20140130" at least
using generic_function = int [((sizeof(void *) + 4 * sizeof(int)) + (sizeof(int) - 1)) / sizeof(int)]; using generic_function = int [((sizeof(void *) + 4 * sizeof(int)) + (sizeof(int) - 1)) / sizeof(int)];
#elif defined(_MSC_VER)// all other cases - for MSVC maximum size is one pointer, plus 3 ints; all other implementations seem to be smaller #elif defined(_MSC_VER) // all other cases - for MSVC maximum size is one pointer, plus 3 ints; all other implementations seem to be smaller
using generic_function = int [((sizeof(void *) + 3 * sizeof(int)) + (sizeof(int) - 1)) / sizeof(int)]; using generic_function = int[((sizeof(void *) + 3 * sizeof(int)) + (sizeof(int) - 1)) / sizeof(int)];
#else #else
using generic_function = R (generic_class::*)(Targs...); using generic_function = R (generic_class::*)(Targs...);
#endif #endif
pmfp_base() {} pmfp_base()
{
int *p = reinterpret_cast<int *>(&m_func);
int *e = p + sizeof(generic_function) / sizeof(int);
for (; p < e; p++)
*p = 0;
}
template<typename MemberFunctionType, typename O> template<typename MemberFunctionType, typename O>
void set_base(MemberFunctionType mftp, O *object) void set_base(MemberFunctionType mftp, O *object)
@ -130,6 +178,9 @@ namespace plib {
} }
private: private:
generic_function m_func; generic_function m_func;
#if 0 && defined(_MSC_VER)
int dummy[4];
#endif
}; };
#elif ((PPMF_TYPE == PPMF_TYPE_GNUC_PMF_CONV) || (PPMF_TYPE == PPMF_TYPE_INTERNAL)) #elif ((PPMF_TYPE == PPMF_TYPE_GNUC_PMF_CONV) || (PPMF_TYPE == PPMF_TYPE_INTERNAL))
@ -146,7 +197,9 @@ namespace plib {
{ {
#if (PPMF_TYPE == PPMF_TYPE_INTERNAL) #if (PPMF_TYPE == PPMF_TYPE_INTERNAL)
using function_ptr = MEMBER_ABI R (*)(O *obj, Targs... args); using function_ptr = MEMBER_ABI R (*)(O *obj, Targs... args);
m_func = reinterpret_cast<generic_function>(plib::mfp::get_mfp<function_ptr>(mftp, object)); function_ptr func(nullptr);
plib::mfp::get_mfp(mftp, func, object);
m_func = reinterpret_cast<generic_function>(func);
#elif (PPMF_TYPE == PPMF_TYPE_GNUC_PMF_CONV) #elif (PPMF_TYPE == PPMF_TYPE_GNUC_PMF_CONV)
R (O::* pFunc)(Targs...) = mftp; R (O::* pFunc)(Targs...) = mftp;
m_func = reinterpret_cast<generic_function>((object->*pFunc)); m_func = reinterpret_cast<generic_function>((object->*pFunc));
@ -159,6 +212,7 @@ namespace plib {
return (reinterpret_cast<function_ptr>(m_func))(obj, std::forward<Targs>(args)...); return (reinterpret_cast<function_ptr>(m_func))(obj, std::forward<Targs>(args)...);
} }
bool is_set() { return m_func != nullptr; } bool is_set() { return m_func != nullptr; }
generic_function get_function() const { return m_func; }
private: private:
generic_function m_func; generic_function m_func;
}; };
@ -188,6 +242,9 @@ namespace plib {
{ {
return this->call(m_obj, std::forward<Targs>(args)...); return this->call(m_obj, std::forward<Targs>(args)...);
} }
generic_class *object() const { return m_obj; }
bool has_object() const { return m_obj != nullptr; }
private: private:
generic_class *m_obj; generic_class *m_obj;
}; };

View File

@ -404,7 +404,6 @@ void NETLIB_NAME(solver)::post_start()
} }
// FIXME ... // FIXME ...
ms->set_delegate_pointer();
ms->setup(grp); ms->setup(grp);
log().verbose("Solver {1}", ms->name()); log().verbose("Solver {1}", ms->name());