Decrease compile times by 30% and runtimes by 10% by eliminating use of boost::bind during function dispatch

This commit is contained in:
Jason Turner
2009-09-10 03:44:42 +00:00
parent f23f0edc70
commit f369afed77
5 changed files with 92 additions and 67 deletions

View File

@@ -75,7 +75,8 @@ namespace chaiscript
{ {
public: public:
Dispatch_Function(const std::vector<std::pair<std::string, Proxy_Function > > &t_funcs) Dispatch_Function(const std::vector<std::pair<std::string, Proxy_Function > > &t_funcs)
: m_funcs(t_funcs) : Proxy_Function_Base(std::vector<Type_Info>()),
m_funcs(t_funcs)
{ {
} }
@@ -91,11 +92,6 @@ namespace chaiscript
return dispatch(m_funcs.begin(), m_funcs.end(), params); return dispatch(m_funcs.begin(), m_funcs.end(), params);
} }
virtual std::vector<Type_Info> get_param_types() const
{
return std::vector<Type_Info>();
}
virtual int get_arity() const virtual int get_arity() const
{ {
return -1; return -1;

View File

@@ -23,27 +23,27 @@ namespace chaiscript
template<typename Ret> template<typename Ret>
struct Handle_Return struct Handle_Return
{ {
static Boxed_Value call(const boost::function<Ret ()> &f) static Boxed_Value handle(const Ret &r)
{ {
return Boxed_Value(f()); return Boxed_Value(r);
} }
}; };
template<typename Ret> template<typename Ret>
struct Handle_Return<boost::shared_ptr<Ret> &> struct Handle_Return<boost::shared_ptr<Ret> &>
{ {
static Boxed_Value call(const boost::function<boost::shared_ptr<Ret> & ()> &f) static Boxed_Value handle(const boost::shared_ptr<Ret> &r)
{ {
return Boxed_Value(f()); return Boxed_Value(r);
} }
}; };
template<typename Ret> template<typename Ret>
struct Handle_Return<const boost::shared_ptr<Ret> &> struct Handle_Return<const boost::shared_ptr<Ret> &>
{ {
static Boxed_Value call(const boost::function<const boost::shared_ptr<Ret> & ()> &f) static Boxed_Value handle(const boost::shared_ptr<Ret> &r)
{ {
return Boxed_Value(f()); return Boxed_Value(r);
} }
}; };
@@ -53,9 +53,9 @@ namespace chaiscript
template<typename Ret> template<typename Ret>
struct Handle_Return<Ret &> struct Handle_Return<Ret &>
{ {
static Boxed_Value call(const boost::function<Ret &()> &f) static Boxed_Value handle(Ret &r)
{ {
return Boxed_Value(boost::ref(f())); return Boxed_Value(boost::ref(r));
} }
}; };
@@ -65,9 +65,9 @@ namespace chaiscript
template<> template<>
struct Handle_Return<Boxed_Value> struct Handle_Return<Boxed_Value>
{ {
static Boxed_Value call(const boost::function<Boxed_Value ()> &f) static Boxed_Value handle(const Boxed_Value &r)
{ {
return f(); return r;
} }
}; };
@@ -77,9 +77,9 @@ namespace chaiscript
template<> template<>
struct Handle_Return<Boxed_Value &> struct Handle_Return<Boxed_Value &>
{ {
static Boxed_Value call(const boost::function<Boxed_Value &()> &f) static Boxed_Value handle(const Boxed_Value &r)
{ {
return f(); return r;
} }
}; };
@@ -89,9 +89,8 @@ namespace chaiscript
template<> template<>
struct Handle_Return<void> struct Handle_Return<void>
{ {
static Boxed_Value call(const boost::function<void ()> &f) static Boxed_Value handle()
{ {
f();
return Boxed_Value(Boxed_Value::Void_Type()); return Boxed_Value(Boxed_Value::Void_Type());
} }
}; };

View File

@@ -13,7 +13,6 @@
#include "type_info.hpp" #include "type_info.hpp"
#include <string> #include <string>
#include <boost/function.hpp> #include <boost/function.hpp>
#include <stdexcept> #include <stdexcept>
#include <vector> #include <vector>
#include "proxy_functions_detail.hpp" #include "proxy_functions_detail.hpp"
@@ -64,7 +63,9 @@ namespace chaiscript
public: public:
virtual ~Proxy_Function_Base() {} virtual ~Proxy_Function_Base() {}
virtual Boxed_Value operator()(const std::vector<Boxed_Value> &params) = 0; virtual Boxed_Value operator()(const std::vector<Boxed_Value> &params) = 0;
virtual std::vector<Type_Info> get_param_types() const = 0;
std::vector<Type_Info> get_param_types() const { return m_types; }
virtual bool operator==(const Proxy_Function_Base &) const = 0; virtual bool operator==(const Proxy_Function_Base &) const = 0;
virtual bool call_match(const std::vector<Boxed_Value> &vals) const = 0; virtual bool call_match(const std::vector<Boxed_Value> &vals) const = 0;
@@ -109,6 +110,32 @@ namespace chaiscript
virtual int get_arity() const = 0; virtual int get_arity() const = 0;
virtual std::string annotation() const = 0; virtual std::string annotation() const = 0;
protected:
Proxy_Function_Base(const std::vector<Type_Info> &t_types)
: m_types(t_types)
{
}
bool compare_types(const std::vector<Type_Info> &tis, const std::vector<Boxed_Value> &bvs) const
{
if (tis.size() - 1 != bvs.size())
{
return false;
} else {
const int size = bvs.size();
for (int i = 0; i < size; ++i)
{
if (!(tis[i+1].bare_equal(bvs[i].get_type_info()) && tis[i+1].is_const() >= bvs[i].get_type_info().is_const() ))
{
return false;
}
}
}
return true;
}
std::vector<Type_Info> m_types;
}; };
typedef boost::shared_ptr<Proxy_Function_Base> Proxy_Function; typedef boost::shared_ptr<Proxy_Function_Base> Proxy_Function;
@@ -139,8 +166,8 @@ namespace chaiscript
int t_arity=-1, int t_arity=-1,
const std::string &t_description = "", const std::string &t_description = "",
const Proxy_Function &t_guard = Proxy_Function()) const Proxy_Function &t_guard = Proxy_Function())
: m_f(t_f), m_arity(t_arity), m_description(t_description), m_guard(t_guard), : Proxy_Function_Base(build_param_type_list(t_arity)),
m_types(build_param_type_list(t_arity)) m_f(t_f), m_arity(t_arity), m_description(t_description), m_guard(t_guard)
{ {
} }
@@ -179,11 +206,6 @@ namespace chaiscript
return m_arity; return m_arity;
} }
virtual std::vector<Type_Info> get_param_types() const
{
return m_types;
}
virtual std::string annotation() const virtual std::string annotation() const
{ {
return m_description; return m_description;
@@ -251,7 +273,8 @@ namespace chaiscript
public: public:
Bound_Function(const Proxy_Function &t_f, Bound_Function(const Proxy_Function &t_f,
const std::vector<Boxed_Value> &t_args) const std::vector<Boxed_Value> &t_args)
: m_f(t_f), m_args(t_args), m_arity(m_f->get_arity()<0?-1:(m_f->get_arity() - m_args.size())) : Proxy_Function_Base(std::vector<Type_Info>()),
m_f(t_f), m_args(t_args), m_arity(m_f->get_arity()<0?-1:(m_f->get_arity() - m_args.size()))
{ {
} }
@@ -310,11 +333,6 @@ namespace chaiscript
return args; return args;
} }
virtual std::vector<Type_Info> get_param_types() const
{
return std::vector<Type_Info>();
}
virtual int get_arity() const virtual int get_arity() const
{ {
return m_arity; return m_arity;
@@ -341,7 +359,8 @@ namespace chaiscript
{ {
public: public:
Proxy_Function_Impl(const boost::function<Func> &f) Proxy_Function_Impl(const boost::function<Func> &f)
: m_f(f), m_dummy_func(0), m_types(build_param_type_list(m_dummy_func)) : Proxy_Function_Base(build_param_type_list((Func *)(0))),
m_f(f), m_dummy_func(0)
{ {
} }
@@ -359,12 +378,7 @@ namespace chaiscript
virtual Boxed_Value operator()(const std::vector<Boxed_Value> &params) virtual Boxed_Value operator()(const std::vector<Boxed_Value> &params)
{ {
return call_func(m_f, params); return Do_Call<typename boost::function<Func>::result_type>::go(m_f, params);
}
virtual std::vector<Type_Info> get_param_types() const
{
return m_types;
} }
virtual int get_arity() const virtual int get_arity() const
@@ -375,7 +389,12 @@ namespace chaiscript
virtual bool call_match(const std::vector<Boxed_Value> &vals) const virtual bool call_match(const std::vector<Boxed_Value> &vals) const
{ {
return compare_types(m_dummy_func, vals); if (int(vals.size()) != get_arity())
{
return false;
}
return compare_types(m_types, vals) || compare_types_cast(m_dummy_func, vals);
} }
virtual std::string annotation() const virtual std::string annotation() const
@@ -386,7 +405,6 @@ namespace chaiscript
private: private:
boost::function<Func> m_f; boost::function<Func> m_f;
Func *m_dummy_func; Func *m_dummy_func;
std::vector<Type_Info> m_types;
}; };
/** /**

View File

@@ -7,11 +7,9 @@
#include <boost/preprocessor.hpp> #include <boost/preprocessor.hpp>
#define gettypeinfo(z,n,text) ti.push_back(detail::Get_Type_Info<Param ## n>::get()); #define gettypeinfo(z,n,text) ti.push_back(detail::Get_Type_Info<Param ## n>::get());
#define casthelper(z,n,text) ,chaiscript::boxed_cast< Param ## n >(params[n]) #define casthelper(z,n,text) BOOST_PP_COMMA_IF(n) chaiscript::boxed_cast< Param ## n >(params[n])
#define comparetype(z,n,text) && ((detail::Get_Type_Info<Param ## n>::get() == params[n].get_type_info()))
#define trycast(z,n,text) chaiscript::boxed_cast<Param ## n>(params[n]); #define trycast(z,n,text) chaiscript::boxed_cast<Param ## n>(params[n]);
#ifndef BOOST_PP_IS_ITERATING #ifndef BOOST_PP_IS_ITERATING
#ifndef __proxy_functions_detail_hpp__ #ifndef __proxy_functions_detail_hpp__
#define __proxy_functions_detail_hpp__ #define __proxy_functions_detail_hpp__
@@ -45,6 +43,27 @@ namespace chaiscript
int got; int got;
int expected; int expected;
}; };
template<typename Ret>
struct Do_Call
{
template<typename Fun>
static Boxed_Value go(const boost::function<Fun> &fun, const std::vector<Boxed_Value> &params)
{
return Handle_Return<Ret>::handle(call_func(fun, params, false));
}
};
template<>
struct Do_Call<void>
{
template<typename Fun>
static Boxed_Value go(const boost::function<Fun> &fun, const std::vector<Boxed_Value> &params)
{
call_func(fun, params, false);
return Handle_Return<void>::handle();
};
};
} }
#define BOOST_PP_ITERATION_LIMITS ( 0, 10 ) #define BOOST_PP_ITERATION_LIMITS ( 0, 10 )
@@ -68,7 +87,7 @@ namespace chaiscript
std::vector<Type_Info> ti; std::vector<Type_Info> ti;
ti.push_back(detail::Get_Type_Info<Ret>::get()); ti.push_back(detail::Get_Type_Info<Ret>::get());
BOOST_PP_REPEAT(n, gettypeinfo, ~) BOOST_PP_REPEAT(n, gettypeinfo, ~)
return ti; return ti;
} }
@@ -80,14 +99,14 @@ namespace chaiscript
* the bad_boxed_cast is passed up to the caller. * the bad_boxed_cast is passed up to the caller.
*/ */
template<typename Ret BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param)> template<typename Ret BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param)>
Boxed_Value call_func(const boost::function<Ret (BOOST_PP_ENUM_PARAMS(n, Param))> &f, Ret call_func(const boost::function<Ret (BOOST_PP_ENUM_PARAMS(n, Param))> &f,
const std::vector<Boxed_Value> &params) const std::vector<Boxed_Value> &params, bool t_test)
{ {
if (params.size() != n) if (params.size() != n)
{ {
throw arity_error(params.size(), n); throw arity_error(params.size(), n);
} else { } else {
return Handle_Return<Ret>::call(boost::bind(f BOOST_PP_REPEAT(n, casthelper, ~))); return f(BOOST_PP_REPEAT(n, casthelper, ~));
} }
} }
@@ -97,25 +116,18 @@ namespace chaiscript
* registration of two functions with the exact same signatures * registration of two functions with the exact same signatures
*/ */
template<typename Ret BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param)> template<typename Ret BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param)>
bool compare_types(Ret (*)(BOOST_PP_ENUM_PARAMS(n, Param)), bool compare_types_cast(Ret (*)(BOOST_PP_ENUM_PARAMS(n, Param)),
const std::vector<Boxed_Value> &params) const std::vector<Boxed_Value> &params)
{ {
if (params.size() != n) try {
{ BOOST_PP_REPEAT(n, trycast, ~);
} catch (const bad_boxed_cast &) {
return false; return false;
} else {
bool val = true BOOST_PP_REPEAT(n, comparetype, ~);
if (val) return true;
try {
BOOST_PP_REPEAT(n, trycast, ~);
} catch (const bad_boxed_cast &) {
return false;
}
return true;
} }
return true;
} }
} }
#endif #endif

View File

@@ -45,7 +45,7 @@ struct System
} }
}; };
void take_shared_ptr(const boost::shared_ptr<std::string> &p) void take_shared_ptr(const boost::shared_ptr<const std::string> &p)
{ {
std::cout << *p << std::endl; std::cout << *p << std::endl;
} }
@@ -130,7 +130,7 @@ int main(int argc, char *argv[]) {
chai.add(bootstrap::vector_type<std::vector<int> >("IntVector")); chai.add(bootstrap::vector_type<std::vector<int> >("IntVector"));
chai("dump_system()"); // chai("dump_system()");
chai("take_shared_ptr(\"Hello World as a shared_ptr\");"); chai("take_shared_ptr(\"Hello World as a shared_ptr\");");
} }