Compare commits

...

1 Commits

Author SHA1 Message Date
Jason Turner
caf2b39995 Attempt caching optimization of object lookups 2016-05-03 08:15:03 -06:00
6 changed files with 55 additions and 24 deletions

View File

@ -231,8 +231,8 @@ namespace chaiscript
auto pointer_sentinel(std::shared_ptr<T> &ptr) const
{
struct Sentinel {
Sentinel(std::shared_ptr<T> &ptr, Data &data)
: m_ptr(ptr), m_data(data)
Sentinel(std::shared_ptr<T> &t_ptr, Data &data)
: m_ptr(t_ptr), m_data(data)
{
}

View File

@ -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<T&>(*get_tracer_ptr());
return *static_cast<T*>(get_tracer_ptr());
}
protected:

View File

@ -219,7 +219,7 @@ namespace chaiscript
std::vector<std::string> t_modulepaths = std::vector<std::string>(),
std::vector<std::string> t_usepaths = std::vector<std::string>())
: m_module_paths(std::move(t_modulepaths)), m_use_paths(std::move(t_usepaths)),
m_parser(std::make_unique<parser::ChaiScript_Parser<eval::Noop_Tracer, optimizer::Optimizer<optimizer::Block, optimizer::Constant_Fold, optimizer::If, optimizer::Return, optimizer::For_Loop>>>()),
m_parser(std::make_unique<parser::ChaiScript_Parser<eval::Noop_Tracer, optimizer::Optimizer<optimizer::Block, optimizer::Caching_Id, optimizer::Constant_Fold, optimizer::If, optimizer::Return, optimizer::For_Loop>>>()),
m_engine(*m_parser)
{
@ -246,7 +246,7 @@ namespace chaiscript
ChaiScript( std::vector<std::string> t_modulepaths = std::vector<std::string>(),
std::vector<std::string> t_usepaths = std::vector<std::string>())
: m_module_paths(std::move(t_modulepaths)), m_use_paths(std::move(t_usepaths)),
m_parser(std::make_unique<parser::ChaiScript_Parser<eval::Noop_Tracer, optimizer::Optimizer<optimizer::Block, optimizer::Constant_Fold, optimizer::If, optimizer::Return, optimizer::For_Loop>>>()),
m_parser(std::make_unique<parser::ChaiScript_Parser<eval::Noop_Tracer, optimizer::Optimizer<optimizer::Block, optimizer::Caching_Id, optimizer::Constant_Fold, optimizer::If, optimizer::Return, optimizer::For_Loop>>>()),
m_engine(*m_parser)
{
if (m_module_paths.empty())

View File

@ -201,6 +201,40 @@ namespace chaiscript
Boxed_Value m_value;
};
template<typename T>
struct Caching_Id_AST_Node final : AST_Node_Impl<T> {
Caching_Id_AST_Node(const std::string &t_ast_node_text, Parse_Location t_loc) :
AST_Node_Impl<T>(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<Boxed_Value> m_cache;
};
template<typename T>
struct Id_AST_Node final : AST_Node_Impl<T> {
Id_AST_Node(const std::string &t_ast_node_text, Parse_Location t_loc) :
@ -710,21 +744,6 @@ namespace chaiscript
}
};
template<typename T>
struct Ternary_Cond_AST_Node final : AST_Node_Impl<T> {
Ternary_Cond_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_Node_Impl_Ptr<T>> t_children) :
AST_Node_Impl<T>(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<typename T>
struct If_AST_Node final : AST_Node_Impl<T> {

View File

@ -113,7 +113,7 @@ namespace chaiscript {
struct If {
template<typename T>
auto optimize(const eval::AST_Node_Impl_Ptr<T> &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<typename T>
auto optimize(const eval::AST_Node_Impl_Ptr<T> &node) {
if (node->identifier == AST_Node_Type::Id)
{
return chaiscript::make_shared<eval::AST_Node_Impl<T>, eval::Caching_Id_AST_Node<T>>(node->text, node->location);
} else {
return node;
}
}
};
struct Constant_Fold {
template<typename T>
auto optimize(const eval::AST_Node_Impl_Ptr<T> &node) {

View File

@ -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<eval::Ternary_Cond_AST_Node<Tracer>>(prev_stack_top);
build_match<eval::If_AST_Node<Tracer>>(prev_stack_top);
}
else {
throw exception::eval_error("Incomplete '" + oper + "' expression",