Fun location caching phase2

This shows ~25% performance over develop
This commit is contained in:
Jason Turner 2015-08-31 11:00:56 -06:00
parent f06e5cdcd6
commit 52e11bf001
2 changed files with 57 additions and 43 deletions

View File

@ -659,7 +659,7 @@ namespace chaiscript
// no? is it a function object? // no? is it a function object?
auto obj = get_function_object_int(name, loc); auto obj = get_function_object_int(name, loc);
if (obj.first != loc) t_loc.store(obj.first); if (obj.first != loc) t_loc.store(obj.first, std::memory_order_relaxed);
return obj.second; return obj.second;
@ -720,20 +720,29 @@ namespace chaiscript
return std::vector<std::pair<std::string, Type_Info> >(m_state.m_types.begin(), m_state.m_types.end()); return std::vector<std::pair<std::string, Type_Info> >(m_state.m_types.begin(), m_state.m_types.end());
} }
std::shared_ptr<std::vector<Proxy_Function>> get_method_missing_functions() const
{
uint_fast32_t method_missing_loc = m_method_missing_loc.load(std::memory_order_relaxed);
auto method_missing_funs = get_function("method_missing", method_missing_loc);
if (method_missing_funs.first != method_missing_loc) m_method_missing_loc.store(method_missing_funs.first, std::memory_order_relaxed);
return std::move(method_missing_funs.second);
}
/// Return a function by name /// Return a function by name
std::shared_ptr<std::vector< Proxy_Function>> get_function(const std::string &t_name) const std::pair<size_t, std::shared_ptr<std::vector< Proxy_Function>>> get_function(const std::string &t_name, const size_t t_hint) const
{ {
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex); chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
const auto &funs = get_functions_int(); const auto &funs = get_functions_int();
auto itr = find_keyed_value(funs, t_name); auto itr = find_keyed_value(funs, t_name, t_hint);
if (itr != funs.end()) if (itr != funs.end())
{ {
return itr->second; return std::make_pair(std::distance(funs.begin(), itr), itr->second);
} else { } else {
return std::make_shared<std::vector<Proxy_Function>>(); return std::make_pair(size_t(0), std::make_shared<std::vector<Proxy_Function>>());
} }
} }
@ -910,9 +919,11 @@ namespace chaiscript
#pragma warning(push) #pragma warning(push)
#pragma warning(disable : 4715) #pragma warning(disable : 4715)
#endif #endif
Boxed_Value call_member(const std::string &t_name, const std::vector<Boxed_Value> &params, bool t_has_params) Boxed_Value call_member(const std::string &t_name, std::atomic_uint_fast32_t &t_loc, const std::vector<Boxed_Value> &params, bool t_has_params)
{ {
const auto funs = get_function(t_name); uint_fast32_t loc = t_loc.load(std::memory_order_relaxed);
const auto funs = get_function(t_name, loc);
if (funs.first != loc) t_loc.store(funs.first, std::memory_order_relaxed);
const auto do_attribute_call = const auto do_attribute_call =
[this](int l_num_params, const std::vector<Boxed_Value> &l_params, const std::vector<Proxy_Function> &l_funs, const Type_Conversions &l_conversions)->Boxed_Value [this](int l_num_params, const std::vector<Boxed_Value> &l_params, const std::vector<Proxy_Function> &l_funs, const Type_Conversions &l_conversions)->Boxed_Value
@ -948,14 +959,14 @@ namespace chaiscript
} }
}; };
if (is_attribute_call(*funs, params, t_has_params)) { if (is_attribute_call(*funs.second, params, t_has_params)) {
return do_attribute_call(1, params, *funs, m_conversions); return do_attribute_call(1, params, *funs.second, m_conversions);
} else { } else {
std::exception_ptr except; std::exception_ptr except;
if (!funs->empty()) { if (!funs.second->empty()) {
try { try {
return dispatch::dispatch(*funs, params, m_conversions); return dispatch::dispatch(*funs.second, params, m_conversions);
} catch(chaiscript::exception::dispatch_error&) { } catch(chaiscript::exception::dispatch_error&) {
except = std::current_exception(); except = std::current_exception();
} }
@ -967,7 +978,8 @@ namespace chaiscript
const auto functions = [&]()->std::vector<Proxy_Function> { const auto functions = [&]()->std::vector<Proxy_Function> {
std::vector<Proxy_Function> fs; std::vector<Proxy_Function> fs;
const auto method_missing_funs = get_function("method_missing"); const auto method_missing_funs = get_method_missing_functions();
for (const auto &f : *method_missing_funs) for (const auto &f : *method_missing_funs)
{ {
if(f->compare_first_type(params[0], m_conversions)) { if(f->compare_first_type(params[0], m_conversions)) {
@ -1004,7 +1016,7 @@ namespace chaiscript
if (except) { if (except) {
std::rethrow_exception(except); std::rethrow_exception(except);
} else { } else {
throw chaiscript::exception::dispatch_error(params, std::vector<Const_Proxy_Function>(funs->begin(), funs->end())); throw chaiscript::exception::dispatch_error(params, std::vector<Const_Proxy_Function>(funs.second->begin(), funs.second->end()));
} }
} }
} }
@ -1014,10 +1026,12 @@ namespace chaiscript
Boxed_Value call_function(const std::string &t_name, const std::vector<Boxed_Value> &params) const Boxed_Value call_function(const std::string &t_name, std::atomic_uint_fast32_t &t_loc, const std::vector<Boxed_Value> &params) const
{ {
const auto funs = get_function(t_name); uint_fast32_t loc = t_loc.load(std::memory_order_relaxed);
Boxed_Value bv = dispatch::dispatch(*funs, params, m_conversions); const auto funs = get_function(t_name, loc);
if (funs.first != loc) t_loc.store(funs.first, std::memory_order_relaxed);
Boxed_Value bv = dispatch::dispatch(*funs.second, params, m_conversions);
// the result of a clone is never to be marked as a return_value // the result of a clone is never to be marked as a return_value
if (t_name == "clone") { if (t_name == "clone") {
bv.reset_return_value(); bv.reset_return_value();
@ -1025,20 +1039,6 @@ namespace chaiscript
return bv; return bv;
} }
Boxed_Value call_function(const std::string &t_name) const
{
return call_function(t_name, std::vector<Boxed_Value>());
}
Boxed_Value call_function(const std::string &t_name, Boxed_Value p1) const
{
return call_function(t_name, std::vector<Boxed_Value>({std::move(p1)}));
}
Boxed_Value call_function(const std::string &t_name, Boxed_Value p1, Boxed_Value p2) const
{
return call_function(t_name, std::vector<Boxed_Value>({std::move(p1), std::move(p2)}));
}
/// Dump object info to stdout /// Dump object info to stdout
void dump_object(const Boxed_Value &o) const void dump_object(const Boxed_Value &o) const
@ -1483,6 +1483,7 @@ namespace chaiscript
Type_Conversions m_conversions; Type_Conversions m_conversions;
chaiscript::detail::threading::Thread_Storage<Stack_Holder> m_stack_holder; chaiscript::detail::threading::Thread_Storage<Stack_Holder> m_stack_holder;
mutable std::atomic_uint_fast32_t m_method_missing_loc;
State m_state; State m_state;
}; };

View File

@ -118,7 +118,7 @@ namespace chaiscript
} else { } else {
chaiscript::eval::detail::Function_Push_Pop fpp(t_ss); chaiscript::eval::detail::Function_Push_Pop fpp(t_ss);
fpp.save_params({t_lhs, t_rhs}); fpp.save_params({t_lhs, t_rhs});
return t_ss->call_function(t_oper_string, t_lhs, t_rhs); return t_ss->call_function(t_oper_string, m_loc, {t_lhs, t_rhs});
} }
} }
catch(const exception::dispatch_error &e){ catch(const exception::dispatch_error &e){
@ -128,6 +128,7 @@ namespace chaiscript
private: private:
Operators::Opers m_oper; Operators::Opers m_oper;
mutable std::atomic_uint_fast32_t m_loc;
}; };
struct Int_AST_Node : public AST_Node { struct Int_AST_Node : public AST_Node {
@ -396,6 +397,8 @@ namespace chaiscript
{ assert(children.size() == 3); } { assert(children.size() == 3); }
Operators::Opers m_oper; Operators::Opers m_oper;
mutable std::atomic_uint_fast32_t m_loc;
mutable std::atomic_uint_fast32_t m_clone_loc;
virtual ~Equation_AST_Node() {} virtual ~Equation_AST_Node() {}
virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE { virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE {
@ -431,14 +434,14 @@ namespace chaiscript
} else { } else {
if (!rhs.is_return_value()) if (!rhs.is_return_value())
{ {
rhs = t_ss->call_function("clone", rhs); rhs = t_ss->call_function("clone", m_clone_loc, {rhs});
} }
rhs.reset_return_value(); rhs.reset_return_value();
} }
} }
try { try {
return t_ss->call_function(this->children[1]->text, std::move(lhs), rhs); return t_ss->call_function(this->children[1]->text, m_loc, {std::move(lhs), rhs});
} }
catch(const exception::dispatch_error &e){ catch(const exception::dispatch_error &e){
throw exception::eval_error("Unable to find appropriate'" + this->children[1]->text + "' operator.", e.parameters, e.functions, false, *t_ss); throw exception::eval_error("Unable to find appropriate'" + this->children[1]->text + "' operator.", e.parameters, e.functions, false, *t_ss);
@ -458,7 +461,7 @@ namespace chaiscript
} }
else { else {
try { try {
return t_ss->call_function(this->children[1]->text, std::move(lhs), rhs); return t_ss->call_function(this->children[1]->text, m_loc, {std::move(lhs), rhs});
} catch(const exception::dispatch_error &e){ } catch(const exception::dispatch_error &e){
throw exception::eval_error("Unable to find appropriate'" + this->children[1]->text + "' operator.", e.parameters, e.functions, false, *t_ss); throw exception::eval_error("Unable to find appropriate'" + this->children[1]->text + "' operator.", e.parameters, e.functions, false, *t_ss);
} }
@ -541,7 +544,7 @@ namespace chaiscript
try { try {
fpp.save_params(params); fpp.save_params(params);
return t_ss->call_function("[]", params); return t_ss->call_function("[]", m_loc, params);
} }
catch(const exception::dispatch_error &e){ catch(const exception::dispatch_error &e){
throw exception::eval_error("Can not find appropriate array lookup operator '[]'.", e.parameters, e.functions, false, *t_ss ); throw exception::eval_error("Can not find appropriate array lookup operator '[]'.", e.parameters, e.functions, false, *t_ss );
@ -563,6 +566,8 @@ namespace chaiscript
return oss.str(); return oss.str();
} }
mutable std::atomic_uint_fast32_t m_loc;
}; };
struct Dot_Access_AST_Node : public AST_Node { struct Dot_Access_AST_Node : public AST_Node {
@ -592,7 +597,7 @@ namespace chaiscript
fpp.save_params(params); fpp.save_params(params);
try { try {
retval = t_ss->call_member(m_fun_name, std::move(params), has_function_params); retval = t_ss->call_member(m_fun_name, m_loc, std::move(params), has_function_params);
} }
catch(const exception::dispatch_error &e){ catch(const exception::dispatch_error &e){
if (e.functions.empty()) if (e.functions.empty())
@ -608,7 +613,7 @@ namespace chaiscript
if (this->children[2]->identifier == AST_Node_Type::Array_Call) { if (this->children[2]->identifier == AST_Node_Type::Array_Call) {
try { try {
retval = t_ss->call_function("[]", retval, this->children[2]->children[1]->eval(t_ss)); retval = t_ss->call_function("[]", m_array_loc, {retval, this->children[2]->children[1]->eval(t_ss)});
} }
catch(const exception::dispatch_error &e){ catch(const exception::dispatch_error &e){
throw exception::eval_error("Can not find appropriate array lookup operator '[]'.", e.parameters, e.functions, true, *t_ss); throw exception::eval_error("Can not find appropriate array lookup operator '[]'.", e.parameters, e.functions, true, *t_ss);
@ -619,6 +624,8 @@ namespace chaiscript
} }
private: private:
mutable std::atomic_uint_fast32_t m_loc;
mutable std::atomic_uint_fast32_t m_array_loc;
std::string m_fun_name; std::string m_fun_name;
}; };
@ -932,7 +939,7 @@ namespace chaiscript
if (this->children[currentCase]->identifier == AST_Node_Type::Case) { if (this->children[currentCase]->identifier == AST_Node_Type::Case) {
//This is a little odd, but because want to see both the switch and the case simultaneously, I do a downcast here. //This is a little odd, but because want to see both the switch and the case simultaneously, I do a downcast here.
try { try {
if (hasMatched || boxed_cast<bool>(t_ss->call_function("==", match_value, this->children[currentCase]->children[0]->eval(t_ss)))) { if (hasMatched || boxed_cast<bool>(t_ss->call_function("==", m_loc, {match_value, this->children[currentCase]->children[0]->eval(t_ss)}))) {
this->children[currentCase]->eval(t_ss); this->children[currentCase]->eval(t_ss);
hasMatched = true; hasMatched = true;
} }
@ -953,6 +960,8 @@ namespace chaiscript
} }
return Boxed_Value(); return Boxed_Value();
} }
mutable std::atomic_uint_fast32_t m_loc;
}; };
struct Case_AST_Node : public AST_Node { struct Case_AST_Node : public AST_Node {
@ -999,7 +1008,7 @@ namespace chaiscript
for (const auto &child : children[0]->children) { for (const auto &child : children[0]->children) {
auto obj = child->eval(t_ss); auto obj = child->eval(t_ss);
if (!obj.is_return_value()) { if (!obj.is_return_value()) {
vec.push_back(t_ss->call_function("clone", obj)); vec.push_back(t_ss->call_function("clone", m_loc, {obj}));
} else { } else {
vec.push_back(std::move(obj)); vec.push_back(std::move(obj));
} }
@ -1016,6 +1025,8 @@ namespace chaiscript
{ {
return "[" + AST_Node::pretty_print() + "]"; return "[" + AST_Node::pretty_print() + "]";
} }
mutable std::atomic_uint_fast32_t m_loc;
}; };
struct Inline_Map_AST_Node : public AST_Node { struct Inline_Map_AST_Node : public AST_Node {
@ -1030,7 +1041,7 @@ namespace chaiscript
for (const auto &child : children[0]->children) { for (const auto &child : children[0]->children) {
auto obj = child->children[1]->eval(t_ss); auto obj = child->children[1]->eval(t_ss);
if (!obj.is_return_value()) { if (!obj.is_return_value()) {
obj = t_ss->call_function("clone", obj); obj = t_ss->call_function("clone", m_loc, {obj});
} }
retval[t_ss->boxed_cast<std::string>(child->children[0]->eval(t_ss))] = std::move(obj); retval[t_ss->boxed_cast<std::string>(child->children[0]->eval(t_ss))] = std::move(obj);
@ -1043,6 +1054,7 @@ namespace chaiscript
} }
} }
mutable std::atomic_uint_fast32_t m_loc;
}; };
struct Return_AST_Node : public AST_Node { struct Return_AST_Node : public AST_Node {
@ -1125,7 +1137,7 @@ namespace chaiscript
} else { } else {
chaiscript::eval::detail::Function_Push_Pop fpp(t_ss); chaiscript::eval::detail::Function_Push_Pop fpp(t_ss);
fpp.save_params({bv}); fpp.save_params({bv});
return t_ss->call_function(children[0]->text, std::move(bv)); return t_ss->call_function(children[0]->text, m_loc, {std::move(bv)});
} }
} catch (const exception::dispatch_error &e) { } catch (const exception::dispatch_error &e) {
throw exception::eval_error("Error with prefix operator evaluation: '" + children[0]->text + "'", e.parameters, e.functions, false, *t_ss); throw exception::eval_error("Error with prefix operator evaluation: '" + children[0]->text + "'", e.parameters, e.functions, false, *t_ss);
@ -1134,6 +1146,7 @@ namespace chaiscript
private: private:
Operators::Opers m_oper; Operators::Opers m_oper;
mutable std::atomic_uint_fast32_t m_loc;
}; };
struct Break_AST_Node : public AST_Node { struct Break_AST_Node : public AST_Node {
@ -1196,14 +1209,14 @@ namespace chaiscript
try { try {
auto oper1 = children[0]->children[0]->children[0]->eval(t_ss); auto oper1 = children[0]->children[0]->children[0]->eval(t_ss);
auto oper2 = children[0]->children[0]->children[1]->eval(t_ss); auto oper2 = children[0]->children[0]->children[1]->eval(t_ss);
return t_ss->call_function("generate_range", return t_ss->call_function("generate_range", m_loc, {oper1, oper2});
oper1, oper2);
} }
catch (const exception::dispatch_error &e) { catch (const exception::dispatch_error &e) {
throw exception::eval_error("Unable to generate range vector, while calling 'generate_range'", e.parameters, e.functions, false, *t_ss); throw exception::eval_error("Unable to generate range vector, while calling 'generate_range'", e.parameters, e.functions, false, *t_ss);
} }
} }
mutable std::atomic_uint_fast32_t m_loc;
}; };
struct Annotation_AST_Node : public AST_Node { struct Annotation_AST_Node : public AST_Node {