From caf2b39995dba38ac2378889b3ae4c0d4dda3dd2 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Tue, 3 May 2016 08:15:03 -0600 Subject: [PATCH] Attempt caching optimization of object lookups --- .../chaiscript/dispatchkit/boxed_value.hpp | 4 +- .../chaiscript/language/chaiscript_common.hpp | 6 +-- .../chaiscript/language/chaiscript_engine.hpp | 4 +- .../chaiscript/language/chaiscript_eval.hpp | 49 +++++++++++++------ .../language/chaiscript_optimizer.hpp | 14 +++++- .../chaiscript/language/chaiscript_parser.hpp | 2 +- 6 files changed, 55 insertions(+), 24 deletions(-) diff --git a/include/chaiscript/dispatchkit/boxed_value.hpp b/include/chaiscript/dispatchkit/boxed_value.hpp index 53c5867..4d017a4 100644 --- a/include/chaiscript/dispatchkit/boxed_value.hpp +++ b/include/chaiscript/dispatchkit/boxed_value.hpp @@ -231,8 +231,8 @@ namespace chaiscript auto pointer_sentinel(std::shared_ptr &ptr) const { struct Sentinel { - Sentinel(std::shared_ptr &ptr, Data &data) - : m_ptr(ptr), m_data(data) + Sentinel(std::shared_ptr &t_ptr, Data &data) + : m_ptr(t_ptr), m_data(data) { } diff --git a/include/chaiscript/language/chaiscript_common.hpp b/include/chaiscript/language/chaiscript_common.hpp index 2f06f21..b7330cd 100644 --- a/include/chaiscript/language/chaiscript_common.hpp +++ b/include/chaiscript/language/chaiscript_common.hpp @@ -32,7 +32,7 @@ namespace chaiscript /// Types of AST nodes available to the parser and eval - enum class AST_Node_Type { Id, Fun_Call, Arg_List, Equation, Var_Decl, + enum class AST_Node_Type { Id, Caching_Id, Fun_Call, Arg_List, Equation, Var_Decl, Array_Call, Dot_Access, Lambda, Block, Def, While, If, For, Inline_Array, Inline_Map, Return, File, Prefix, Break, Continue, Map_Pair, Value_Range, Inline_Range, Try, Catch, Finally, Method, Attr_Decl, @@ -45,7 +45,7 @@ namespace chaiscript { /// Helper lookup to get the name of each node type const char *ast_node_type_to_string(AST_Node_Type ast_node_type) { - static const char * const ast_node_types[] = { "Id", "Fun_Call", "Arg_List", "Equation", "Var_Decl", + static const char * const ast_node_types[] = { "Id", "Caching_Id", "Fun_Call", "Arg_List", "Equation", "Var_Decl", "Array_Call", "Dot_Access", "Lambda", "Block", "Def", "While", "If", "For", "Inline_Array", "Inline_Map", "Return", "File", "Prefix", "Break", "Continue", "Map_Pair", "Value_Range", "Inline_Range", "Try", "Catch", "Finally", "Method", "Attr_Decl", @@ -553,7 +553,7 @@ namespace chaiscript T &get_tracer() { // to do type check this somehow? - return static_cast(*get_tracer_ptr()); + return *static_cast(get_tracer_ptr()); } protected: diff --git a/include/chaiscript/language/chaiscript_engine.hpp b/include/chaiscript/language/chaiscript_engine.hpp index 05f0e84..fb16c01 100644 --- a/include/chaiscript/language/chaiscript_engine.hpp +++ b/include/chaiscript/language/chaiscript_engine.hpp @@ -219,7 +219,7 @@ namespace chaiscript std::vector t_modulepaths = std::vector(), std::vector t_usepaths = std::vector()) : m_module_paths(std::move(t_modulepaths)), m_use_paths(std::move(t_usepaths)), - m_parser(std::make_unique>>()), + m_parser(std::make_unique>>()), m_engine(*m_parser) { @@ -246,7 +246,7 @@ namespace chaiscript ChaiScript( std::vector t_modulepaths = std::vector(), std::vector t_usepaths = std::vector()) : m_module_paths(std::move(t_modulepaths)), m_use_paths(std::move(t_usepaths)), - m_parser(std::make_unique>>()), + m_parser(std::make_unique>>()), m_engine(*m_parser) { if (m_module_paths.empty()) diff --git a/include/chaiscript/language/chaiscript_eval.hpp b/include/chaiscript/language/chaiscript_eval.hpp index 0464e4d..d5a0c98 100644 --- a/include/chaiscript/language/chaiscript_eval.hpp +++ b/include/chaiscript/language/chaiscript_eval.hpp @@ -201,6 +201,40 @@ namespace chaiscript Boxed_Value m_value; }; + template + struct Caching_Id_AST_Node final : AST_Node_Impl { + Caching_Id_AST_Node(const std::string &t_ast_node_text, Parse_Location t_loc) : + AST_Node_Impl(t_ast_node_text, AST_Node_Type::Caching_Id, std::move(t_loc)), + m_loc(0), + m_cache(this) + { } + + Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override { + try { + const uint32_t loc = m_loc; + if (loc == 0) { + Boxed_Value bv = t_ss.get_object(this->text, m_loc); + if ((m_loc & 0x40000000) == 0) { + *m_cache = bv; + } + return bv; + } else if ((loc & 0x40000000) != 0) { + /// \todo this is a magic number now to see if it's a local - we shouldn't be doing this + return t_ss.get_object(this->text, m_loc); + } else { + return *m_cache; + } + } + catch (std::exception &) { + throw exception::eval_error("Can not find object: " + this->text); + } + } + + private: + mutable std::atomic_uint_fast32_t m_loc; + mutable chaiscript::detail::threading::Thread_Storage m_cache; + }; + template struct Id_AST_Node final : AST_Node_Impl { Id_AST_Node(const std::string &t_ast_node_text, Parse_Location t_loc) : @@ -710,21 +744,6 @@ namespace chaiscript } }; - template - struct Ternary_Cond_AST_Node final : AST_Node_Impl { - Ternary_Cond_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector> t_children) : - AST_Node_Impl(std::move(t_ast_node_text), AST_Node_Type::Ternary_Cond, std::move(t_loc), std::move(t_children)) - { assert(this->children.size() == 3); } - - Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override { - if (this->get_bool_condition(this->children[0]->eval(t_ss))) { - return this->children[1]->eval(t_ss); - } else { - return this->children[2]->eval(t_ss); - } - } - - }; template struct If_AST_Node final : AST_Node_Impl { diff --git a/include/chaiscript/language/chaiscript_optimizer.hpp b/include/chaiscript/language/chaiscript_optimizer.hpp index dd3bb1f..395c9ee 100644 --- a/include/chaiscript/language/chaiscript_optimizer.hpp +++ b/include/chaiscript/language/chaiscript_optimizer.hpp @@ -113,7 +113,7 @@ namespace chaiscript { struct If { template auto optimize(const eval::AST_Node_Impl_Ptr &node) { - if ((node->identifier == AST_Node_Type::If || node->identifier == AST_Node_Type::Ternary_Cond) + if (node->identifier == AST_Node_Type::If && node->children.size() >= 2 && node->children[0]->identifier == AST_Node_Type::Constant) { @@ -131,6 +131,18 @@ namespace chaiscript { } }; + struct Caching_Id { + template + auto optimize(const eval::AST_Node_Impl_Ptr &node) { + if (node->identifier == AST_Node_Type::Id) + { + return chaiscript::make_shared, eval::Caching_Id_AST_Node>(node->text, node->location); + } else { + return node; + } + } + }; + struct Constant_Fold { template auto optimize(const eval::AST_Node_Impl_Ptr &node) { diff --git a/include/chaiscript/language/chaiscript_parser.hpp b/include/chaiscript/language/chaiscript_parser.hpp index bba9b6a..6fe0652 100644 --- a/include/chaiscript/language/chaiscript_parser.hpp +++ b/include/chaiscript/language/chaiscript_parser.hpp @@ -2106,7 +2106,7 @@ namespace chaiscript throw exception::eval_error("Incomplete '" + oper + "' expression", File_Position(m_position.line, m_position.col), *m_filename); } - build_match>(prev_stack_top); + build_match>(prev_stack_top); } else { throw exception::eval_error("Incomplete '" + oper + "' expression",