Fun location caching phase2
This shows ~25% performance over develop
This commit is contained in:
parent
f06e5cdcd6
commit
52e11bf001
@ -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> ¶ms, 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> ¶ms, 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> ¶ms) const
|
Boxed_Value call_function(const std::string &t_name, std::atomic_uint_fast32_t &t_loc, const std::vector<Boxed_Value> ¶ms) 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;
|
||||||
};
|
};
|
||||||
|
@ -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 {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user