mirror of
https://github.com/holub/mame
synced 2025-10-05 16:50:57 +03:00
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:
parent
427cf984db
commit
70051f6c1f
@ -172,15 +172,18 @@ maketree: $(sort $(OBJDIRS))
|
||||
# Special targets
|
||||
#-------------------------------------------------
|
||||
|
||||
.PHONY: clang mingw doc
|
||||
.PHONY: clang clang-5 mingw doc
|
||||
|
||||
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
|
||||
# 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:
|
||||
$(MAKE) LDEXTRAFLAGS="-Wl,--subsystem,console" LIBS= MD=@mkdir.exe SHELL=sh.exe
|
||||
|
@ -15,14 +15,8 @@
|
||||
|
||||
#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 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 ENTRYX(nic, name, defparam) { NETLIB_DEVICE_DECL(nic) ENTRYX1(NETLIB_NAME(nic), name, defparam, decl_ ## nic) }
|
||||
|
||||
|
@ -22,6 +22,8 @@ namespace netlist
|
||||
{
|
||||
}
|
||||
|
||||
NETLIB_UPDATEI();
|
||||
|
||||
public:
|
||||
void shift();
|
||||
|
||||
@ -109,6 +111,11 @@ namespace netlist
|
||||
m_last_CP = m_CP();
|
||||
}
|
||||
|
||||
NETLIB_UPDATE(Am2847_shifter)
|
||||
{
|
||||
/* do nothing */
|
||||
}
|
||||
|
||||
inline NETLIB_FUNC_VOID(Am2847_shifter, shift, (void))
|
||||
{
|
||||
uint32_t out = m_buffer[0] & 1;
|
||||
|
@ -25,31 +25,35 @@ namespace netlist
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
#if (USE_MEMPOOL)
|
||||
static plib::mempool pool(6553600, 64);
|
||||
|
||||
void * object_t::operator new (size_t size)
|
||||
{
|
||||
return pool.alloc(size);
|
||||
}
|
||||
static plib::mempool *pool()
|
||||
{
|
||||
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)
|
||||
{
|
||||
if (mem)
|
||||
pool.free(mem);
|
||||
}
|
||||
#else
|
||||
void * object_t::operator new (size_t size)
|
||||
{
|
||||
return ::operator new(size);
|
||||
}
|
||||
void * object_t::operator new (size_t size)
|
||||
{
|
||||
void *ret = nullptr;
|
||||
if ((USE_MEMPOOL))
|
||||
ret = pool()->alloc(size);
|
||||
else
|
||||
ret = ::operator new(size);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void object_t::operator delete (void * mem)
|
||||
{
|
||||
if (mem)
|
||||
::operator delete(mem);
|
||||
}
|
||||
#endif
|
||||
void object_t::operator delete (void * mem)
|
||||
{
|
||||
if (mem)
|
||||
{
|
||||
if ((USE_MEMPOOL))
|
||||
pool()->free(mem);
|
||||
else
|
||||
::operator delete(mem);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -361,12 +365,6 @@ void netlist_t::start()
|
||||
/* 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 ...");
|
||||
for (auto & t : get_device_list<analog::NETLIB_NAME(twoterm)>())
|
||||
{
|
||||
@ -391,6 +389,14 @@ void netlist_t::start()
|
||||
else
|
||||
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()
|
||||
@ -427,6 +433,14 @@ void netlist_t::reset()
|
||||
//if (m_solver != nullptr)
|
||||
// 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 !
|
||||
for (auto & n : m_nets)
|
||||
n->reset();
|
||||
@ -444,15 +458,66 @@ void netlist_t::reset()
|
||||
* INFO: The order here affects power up of e.g. breakout. However, such
|
||||
* 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();
|
||||
while (i>0)
|
||||
m_devices[--i]->update_dev();
|
||||
|
||||
#if 1
|
||||
/* the above may screw up m_active and the list */
|
||||
for (auto &n : m_nets)
|
||||
n->rebuild_list();
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -594,9 +659,6 @@ core_device_t::core_device_t(netlist_t &owner, const pstring &name)
|
||||
, logic_family_t()
|
||||
, netlist_ref(owner)
|
||||
, m_hint_deactivate(false)
|
||||
#if (!NL_USE_PMF_VIRTUAL)
|
||||
, m_static_update()
|
||||
#endif
|
||||
{
|
||||
if (logic_family() == nullptr)
|
||||
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()
|
||||
, netlist_ref(owner.netlist())
|
||||
, m_hint_deactivate(false)
|
||||
#if (!NL_USE_PMF_VIRTUAL)
|
||||
, m_static_update()
|
||||
#endif
|
||||
{
|
||||
set_logic_family(owner.logic_family());
|
||||
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)
|
||||
m_static_update.set_base(&core_device_t::update, this);
|
||||
#endif
|
||||
term.m_delegate.set(&core_device_t::update, this);
|
||||
}
|
||||
|
||||
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();
|
||||
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_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()
|
||||
|
@ -455,6 +455,10 @@ namespace netlist
|
||||
core_device_t & m_device;
|
||||
};
|
||||
|
||||
/*! Delegate type for device notification.
|
||||
*
|
||||
*/
|
||||
typedef plib::pmfp<void> nldelegate;
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// core_terminal_t
|
||||
@ -509,6 +513,8 @@ namespace netlist
|
||||
|
||||
void reset();
|
||||
|
||||
nldelegate m_delegate;
|
||||
|
||||
private:
|
||||
net_t * m_net;
|
||||
state_var<state_e> m_state;
|
||||
@ -1044,14 +1050,16 @@ namespace netlist
|
||||
|
||||
void do_reset() { reset(); }
|
||||
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 */
|
||||
nperftime_t m_stat_total_time;
|
||||
nperfcount_t m_stat_call_count;
|
||||
nperfcount_t m_stat_inc_active;
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
virtual void update() NL_NOEXCEPT { }
|
||||
@ -1061,11 +1069,7 @@ namespace netlist
|
||||
|
||||
void do_update() NL_NOEXCEPT
|
||||
{
|
||||
#if (NL_USE_PMF_VIRTUAL)
|
||||
update();
|
||||
#else
|
||||
m_static_update.call(this);
|
||||
#endif
|
||||
}
|
||||
|
||||
plib::plog_base<NL_DEBUG> &log();
|
||||
@ -1081,10 +1085,6 @@ namespace netlist
|
||||
|
||||
private:
|
||||
bool m_hint_deactivate;
|
||||
|
||||
#if (!NL_USE_PMF_VIRTUAL)
|
||||
plib::pmfp_base<void> m_static_update;
|
||||
#endif
|
||||
};
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
@ -95,16 +95,6 @@ using nl_double = double;
|
||||
* 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
|
||||
//============================================================
|
||||
@ -115,9 +105,4 @@ using nl_double = double;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef __APPLE__
|
||||
#undef USE_MEMPOOL
|
||||
#define USE_MEMPOOL (0)
|
||||
#endif
|
||||
|
||||
#endif /* NLCONFIG_H_ */
|
||||
|
@ -54,7 +54,7 @@ namespace netlist
|
||||
|
||||
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 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
23
src/lib/netlist/plib/palloc.cpp
Normal file → Executable file
@ -5,6 +5,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "pconfig.h"
|
||||
#include "palloc.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));
|
||||
}
|
||||
delete b.data;
|
||||
::operator delete(b.data);
|
||||
}
|
||||
m_blocks.clear();
|
||||
}
|
||||
@ -35,7 +37,7 @@ mempool::~mempool()
|
||||
size_t mempool::new_block()
|
||||
{
|
||||
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.m_free = m_min_alloc;
|
||||
b.m_num_alloc = 0;
|
||||
@ -43,10 +45,19 @@ size_t mempool::new_block()
|
||||
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)
|
||||
{
|
||||
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++)
|
||||
{
|
||||
auto &b = m_blocks[bn];
|
||||
@ -56,7 +67,7 @@ void *mempool::alloc(size_t size)
|
||||
b.m_num_alloc++;
|
||||
auto i = reinterpret_cast<info *>(b.cur_ptr);
|
||||
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;
|
||||
return ret;
|
||||
}
|
||||
@ -68,7 +79,7 @@ void *mempool::alloc(size_t size)
|
||||
b.m_free = m_min_alloc - rs;
|
||||
auto i = reinterpret_cast<info *>(b.cur_ptr);
|
||||
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;
|
||||
return ret;
|
||||
}
|
||||
@ -78,7 +89,7 @@ void mempool::free(void *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];
|
||||
if (b->m_num_alloc == 0)
|
||||
fprintf(stderr, "Argh .. double free\n");
|
||||
|
@ -144,6 +144,7 @@ private:
|
||||
};
|
||||
|
||||
size_t new_block();
|
||||
size_t mininfosize();
|
||||
|
||||
struct info
|
||||
{
|
||||
@ -151,6 +152,11 @@ private:
|
||||
size_t m_block;
|
||||
};
|
||||
|
||||
size_t m_min_alloc;
|
||||
size_t m_min_align;
|
||||
|
||||
std::vector<block> m_blocks;
|
||||
|
||||
public:
|
||||
mempool(size_t min_alloc, size_t min_align);
|
||||
~mempool();
|
||||
@ -158,10 +164,6 @@ public:
|
||||
void *alloc(size_t size);
|
||||
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
10
src/lib/netlist/plib/pconfig.h
Normal file → Executable file
@ -71,13 +71,13 @@ typedef __int128_t INT128;
|
||||
#define MEMBER_ABI _thiscall
|
||||
#elif defined(__clang__) && defined(__i386__) && defined(_WIN32)
|
||||
#define PHAS_PMF_INTERNAL 0
|
||||
#elif defined(EMSCRIPTEN)
|
||||
#define PHAS_PMF_INTERNAL 0
|
||||
#elif defined(__arm__) || defined(__ARMEL__)
|
||||
#define PHAS_PMF_INTERNAL 0
|
||||
#elif defined(__arm__) || defined(__ARMEL__) || defined(__aarch64__) || defined(__MIPSEL__) || defined(__mips_isa_rev) || defined(__mips64) || defined(EMSCRIPTEN)
|
||||
#define PHAS_PMF_INTERNAL 2
|
||||
#else
|
||||
#define PHAS_PMF_INTERNAL 1
|
||||
#endif
|
||||
#elif defined(_MSC_VER) && defined (_M_X64)
|
||||
#define PHAS_PMF_INTERNAL 3
|
||||
#else
|
||||
#define PHAS_PMF_INTERNAL 0
|
||||
#endif
|
||||
@ -87,7 +87,7 @@ typedef __int128_t INT128;
|
||||
#endif
|
||||
|
||||
#ifndef PPMF_TYPE
|
||||
#if PHAS_PMF_INTERNAL
|
||||
#if (PHAS_PMF_INTERNAL > 0)
|
||||
#define PPMF_TYPE PPMF_TYPE_INTERNAL
|
||||
#else
|
||||
#define PPMF_TYPE PPMF_TYPE_PMF
|
||||
|
95
src/lib/netlist/plib/ppmf.h
Normal file → Executable file
95
src/lib/netlist/plib/ppmf.h
Normal file → Executable file
@ -51,44 +51,82 @@ namespace plib {
|
||||
* It derives a pointer to a member function.
|
||||
*/
|
||||
|
||||
#if (PHAS_PMF_INTERNAL)
|
||||
#if (PHAS_PMF_INTERNAL > 0)
|
||||
class mfp
|
||||
{
|
||||
public:
|
||||
// construct from any member function pointer
|
||||
#ifdef _MSC_VER
|
||||
class __single_inheritance si_generic_class;
|
||||
class generic_class { };
|
||||
#else
|
||||
class generic_class;
|
||||
#endif
|
||||
using generic_function = void (*)();
|
||||
|
||||
template<typename MemberFunctionType>
|
||||
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;
|
||||
}
|
||||
|
||||
template<typename FunctionType, typename MemberFunctionType, typename ObjectType>
|
||||
static FunctionType get_mfp(MemberFunctionType mftp, ObjectType *object)
|
||||
template<typename MemberFunctionType, typename FunctionType, typename ObjectType>
|
||||
static void get_mfp(MemberFunctionType mftp, FunctionType &func, ObjectType *&object)
|
||||
{
|
||||
mfp mfpo(mftp);
|
||||
//return mfpo.update_after_bind<FunctionType>(object);
|
||||
return reinterpret_cast<FunctionType>(
|
||||
mfpo.convert_to_generic(reinterpret_cast<generic_class *>(object)));
|
||||
generic_function rfunc(nullptr);
|
||||
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:
|
||||
// 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
|
||||
generic_class * o_p_delta = reinterpret_cast<generic_class *>(reinterpret_cast<std::uint8_t *>(object) + m_this_delta);
|
||||
if (PHAS_PMF_INTERNAL == 1)
|
||||
{
|
||||
// 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 (!(m_function & 1))
|
||||
return reinterpret_cast<generic_function>(m_function);
|
||||
// if the low bit of the vtable index is clear, then it is just a raw function pointer
|
||||
if (!(m_function & 1))
|
||||
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
|
||||
@ -96,6 +134,10 @@ namespace plib {
|
||||
// if even, it's a pointer to the function
|
||||
// if odd, it's the byte offset into the vtable
|
||||
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
|
||||
|
||||
@ -107,12 +149,18 @@ namespace plib {
|
||||
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
|
||||
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
|
||||
using generic_function = int [((sizeof(void *) + 3 * 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
|
||||
using generic_function = int[((sizeof(void *) + 3 * sizeof(int)) + (sizeof(int) - 1)) / sizeof(int)];
|
||||
#else
|
||||
using generic_function = R (generic_class::*)(Targs...);
|
||||
#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>
|
||||
void set_base(MemberFunctionType mftp, O *object)
|
||||
@ -130,6 +178,9 @@ namespace plib {
|
||||
}
|
||||
private:
|
||||
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))
|
||||
@ -146,7 +197,9 @@ namespace plib {
|
||||
{
|
||||
#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));
|
||||
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)
|
||||
R (O::* pFunc)(Targs...) = mftp;
|
||||
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)...);
|
||||
}
|
||||
bool is_set() { return m_func != nullptr; }
|
||||
generic_function get_function() const { return m_func; }
|
||||
private:
|
||||
generic_function m_func;
|
||||
};
|
||||
@ -188,6 +242,9 @@ namespace plib {
|
||||
{
|
||||
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:
|
||||
generic_class *m_obj;
|
||||
};
|
||||
|
@ -404,7 +404,6 @@ void NETLIB_NAME(solver)::post_start()
|
||||
}
|
||||
|
||||
// FIXME ...
|
||||
ms->set_delegate_pointer();
|
||||
ms->setup(grp);
|
||||
|
||||
log().verbose("Solver {1}", ms->name());
|
||||
|
Loading…
Reference in New Issue
Block a user