From 48224afe45b7d153f95bec603ade8d75d9334f03 Mon Sep 17 00:00:00 2001 From: Deukhoofd Date: Tue, 25 Jun 2019 15:18:36 +0200 Subject: [PATCH] Reduce amount of copies for HashedString for improved performance Signed-off-by: Deukhoofd --- src/Binder/BoundVariables/BoundScope.cpp | 8 ++--- src/Binder/BoundVariables/BoundScope.hpp | 8 ++--- src/Evaluator/EvalValues/TableEvalValue.hpp | 8 ++--- src/Evaluator/Evaluator.cpp | 2 +- src/Parser/Lexer.cpp | 2 +- src/Script.cpp | 6 ++-- src/Script.hpp | 1 - src/TableScriptType.hpp | 4 +-- src/Utilities/HashedString.hpp | 39 +++++++++++---------- src/Utilities/StringUtils.cpp | 5 +++ src/Utilities/StringUtils.hpp | 2 +- tests/parser/LexerTests.cpp | 2 +- tests/parser/ParserTests.cpp | 32 ++++++++--------- 13 files changed, 62 insertions(+), 57 deletions(-) create mode 100644 src/Utilities/StringUtils.cpp diff --git a/src/Binder/BoundVariables/BoundScope.cpp b/src/Binder/BoundVariables/BoundScope.cpp index 12a5d3d..9e0a5a9 100644 --- a/src/Binder/BoundVariables/BoundScope.cpp +++ b/src/Binder/BoundVariables/BoundScope.cpp @@ -39,7 +39,7 @@ namespace Porygon::Binder { _currentScope--; } - int BoundScope::Exists(Utilities::HashedString key) { + int BoundScope::Exists(const Utilities::HashedString& key) { auto found = this->_tableScope->find(key); if (found != _tableScope->end()) { return 0; @@ -54,7 +54,7 @@ namespace Porygon::Binder { return -1; } - BoundVariable *BoundScope::GetVariable(uint32_t scope, Utilities::HashedString identifier) { + BoundVariable *BoundScope::GetVariable(uint32_t scope, const Utilities::HashedString& identifier) { if (scope == 0) { auto find = this->_tableScope->find(identifier); if (find != _tableScope->end()) { @@ -71,7 +71,7 @@ namespace Porygon::Binder { } } - VariableAssignment BoundScope::CreateExplicitLocal(Utilities::HashedString identifier, std::shared_ptr type) { + VariableAssignment BoundScope::CreateExplicitLocal(const Utilities::HashedString& identifier, std::shared_ptr type) { auto scope = this->_localScope.at(this->_currentScope - 1); if (scope->find(identifier) != scope->end()) { return VariableAssignment(VariableAssignmentResult::ExplicitLocalVariableExists, nullptr); @@ -81,7 +81,7 @@ namespace Porygon::Binder { new BoundVariableKey(identifier, this->_currentScope, true)); } - VariableAssignment BoundScope::AssignVariable(Utilities::HashedString identifier, const std::shared_ptr &type) { + VariableAssignment BoundScope::AssignVariable(const Utilities::HashedString& identifier, const std::shared_ptr &type) { int exists = this->Exists(identifier); if (exists == -1) { // Creation diff --git a/src/Binder/BoundVariables/BoundScope.hpp b/src/Binder/BoundVariables/BoundScope.hpp index 1af538b..795f532 100644 --- a/src/Binder/BoundVariables/BoundScope.hpp +++ b/src/Binder/BoundVariables/BoundScope.hpp @@ -28,13 +28,13 @@ namespace Porygon::Binder { void GoOuterScope(); - int Exists(Utilities::HashedString key); + int Exists(const Utilities::HashedString& key); - BoundVariable *GetVariable(uint32_t scope, Utilities::HashedString identifier); + BoundVariable *GetVariable(uint32_t scope, const Utilities::HashedString& identifier); - VariableAssignment CreateExplicitLocal(Utilities::HashedString identifier, std::shared_ptr type); + VariableAssignment CreateExplicitLocal(const Utilities::HashedString& identifier, std::shared_ptr type); - VariableAssignment AssignVariable(Utilities::HashedString identifier, const std::shared_ptr &type); + VariableAssignment AssignVariable(const Utilities::HashedString& identifier, const std::shared_ptr &type); size_t GetLocalVariableCount() { return _localScope.size(); diff --git a/src/Evaluator/EvalValues/TableEvalValue.hpp b/src/Evaluator/EvalValues/TableEvalValue.hpp index 9a14c8b..755e185 100644 --- a/src/Evaluator/EvalValues/TableEvalValue.hpp +++ b/src/Evaluator/EvalValues/TableEvalValue.hpp @@ -40,21 +40,21 @@ namespace Porygon::Evaluation { const shared_ptr IndexValue(EvalValue *val) const final { const auto stringKey = val->EvaluateString(); - return this->_table->at(Utilities::HashedString(stringKey)); + return this->_table->at(Utilities::HashedString::CreateLookup(stringKey)); } const shared_ptr IndexValue(uint32_t hash) const final { - return this->_table->at(Utilities::HashedString(hash)); + return this->_table->at(Utilities::HashedString::CreateLookup(hash)); } const shared_ptr IndexValue(const char *val) const { auto hash = Utilities::HashedString::ConstHash(val); - return this->_table->at(Utilities::HashedString(hash)); + return this->_table->at(Utilities::HashedString::CreateLookup(hash)); } void SetIndexValue(EvalValue *key, const shared_ptr &value) const final { auto hash = key->GetHashCode(); - this->_table->at(Utilities::HashedString(hash)) = value; + this->_table->at(Utilities::HashedString::CreateLookup(hash)) = value; } const _Rb_tree_const_iterator>> GetTableIterator() const{ diff --git a/src/Evaluator/Evaluator.cpp b/src/Evaluator/Evaluator.cpp index 75f85a6..c111952 100644 --- a/src/Evaluator/Evaluator.cpp +++ b/src/Evaluator/Evaluator.cpp @@ -392,7 +392,7 @@ namespace Porygon::Evaluation { auto values = new map>(); for (int i = 0; i < valueExpressions->size(); i++) { auto val = this->EvaluateExpression(valueExpressions->at(i)); - auto key = Utilities::StringUtils::IntToString(i + 1); + auto key = new u16string(Utilities::StringUtils::IntToString(i + 1)); values->insert({Utilities::HashedString(key), val}); } auto valuesPointer = shared_ptr>>(values); diff --git a/src/Parser/Lexer.cpp b/src/Parser/Lexer.cpp index 39b5b8d..43d3699 100644 --- a/src/Parser/Lexer.cpp +++ b/src/Parser/Lexer.cpp @@ -256,7 +256,7 @@ namespace Porygon::Parser { case HashedString::ConstHash("while"): return new SimpleToken(TokenKind::WhileKeyword, start, 5); default: - return new IdentifierToken(HashedString(s), start, s.length()); + return new IdentifierToken(HashedString(new u16string(s)), start, s.length()); } } diff --git a/src/Script.cpp b/src/Script.cpp index 3fdd55b..4b2c241 100644 --- a/src/Script.cpp +++ b/src/Script.cpp @@ -67,11 +67,11 @@ void Porygon::Script::Parse(const u16string& script) { } EvalValue *Porygon::Script::GetVariable(const u16string &key) { - return _scriptVariables -> at(HashedString(key)).get(); + return _scriptVariables -> at(HashedString::CreateLookup(key)).get(); } bool Porygon::Script::HasVariable(const u16string &key) { - auto f = _scriptVariables->find(HashedString(key)); + auto f = _scriptVariables->find(HashedString::CreateLookup(key)); return f != _scriptVariables->end(); } @@ -80,7 +80,7 @@ EvalValue *Porygon::Script::GetLastValue() { } bool Porygon::Script::HasFunction(const u16string &key) { - auto f = _scriptVariables->find(HashedString(key)); + auto f = _scriptVariables->find(HashedString::CreateLookup(key)); return f != _scriptVariables->end() && f.operator->()->second->GetTypeClass() == TypeClass ::Function; } diff --git a/src/Script.hpp b/src/Script.hpp index 33a3998..23486e7 100644 --- a/src/Script.hpp +++ b/src/Script.hpp @@ -1,4 +1,3 @@ -#include #ifndef PORYGONLANG_SCRIPT_HPP #define PORYGONLANG_SCRIPT_HPP diff --git a/src/TableScriptType.hpp b/src/TableScriptType.hpp index af9fdc5..77fde1c 100644 --- a/src/TableScriptType.hpp +++ b/src/TableScriptType.hpp @@ -33,13 +33,13 @@ namespace Porygon{ const shared_ptr GetIndexedType(ScriptType* indexer) const final{ auto stringKey = (StringScriptType*)indexer; if (stringKey->IsKnownAtBind()){ - return _values-> at(Utilities::HashedString(stringKey->GetHashValue()))->GetType(); + return _values-> at(Utilities::HashedString::CreateLookup(stringKey->GetHashValue()))->GetType(); } throw "TODO: indexing with dynamic keys"; } const shared_ptr GetIndexedType(uint32_t hash) const final{ - return _values-> at(Utilities::HashedString(hash))->GetType(); + return _values-> at(Utilities::HashedString::CreateLookup(hash))->GetType(); } const map* GetValues() const{ diff --git a/src/Utilities/HashedString.hpp b/src/Utilities/HashedString.hpp index 4b77c32..520369a 100644 --- a/src/Utilities/HashedString.hpp +++ b/src/Utilities/HashedString.hpp @@ -3,32 +3,33 @@ #define PORYGONLANG_HASHEDSTRING_HPP #include +#include namespace Porygon::Utilities{ class HashedString{ const uint32_t _hash; - const std::u16string _string; + const std::shared_ptr _string; + + explicit HashedString(const std::u16string& s) : _hash(ConstHash(s.c_str())),_string(nullptr){ + } + + explicit HashedString(uint32_t hash) : _hash(hash), _string(nullptr){ + } + public: - explicit HashedString(const std::u16string& s) - : _hash(ConstHash(s.c_str())), - _string(s) + explicit HashedString(const std::u16string* s) + : _hash(ConstHash(s->c_str())), + _string(std::shared_ptr(s)) { } - explicit HashedString(char16_t const *input) - : _hash(ConstHash(input)), - _string(std::u16string(input)) - { + static HashedString CreateLookup(const std::u16string& s){ + return HashedString(s); + } + static HashedString CreateLookup(uint32_t hash){ + return HashedString(hash); } - explicit HashedString(char const *input) : _hash(ConstHash(input)){ - } - - explicit HashedString(uint32_t hash) : _hash(hash){ - } - - HashedString(const HashedString& b) :_hash(b._hash), _string(b._string){ - - }; + HashedString(const HashedString& b) = default; static uint32_t constexpr ConstHash(char16_t const *input) { return *input ? @@ -46,8 +47,8 @@ namespace Porygon::Utilities{ return _hash; } - const std::u16string* GetString() const{ - return &_string; + const std::shared_ptr GetString() const{ + return _string; } bool operator==(const HashedString& b) const{ diff --git a/src/Utilities/StringUtils.cpp b/src/Utilities/StringUtils.cpp new file mode 100644 index 0000000..9429e84 --- /dev/null +++ b/src/Utilities/StringUtils.cpp @@ -0,0 +1,5 @@ +#include "StringUtils.hpp" + +namespace Porygon::Utilities{ + std::wstring_convert, char16_t> StringUtils::conv; +} diff --git a/src/Utilities/StringUtils.hpp b/src/Utilities/StringUtils.hpp index 10dc159..91cfe67 100644 --- a/src/Utilities/StringUtils.hpp +++ b/src/Utilities/StringUtils.hpp @@ -10,9 +10,9 @@ namespace Porygon::Utilities{ class StringUtils{ + static std::wstring_convert, char16_t> conv; public: static std::u16string IntToString(long const &i) { - std::wstring_convert, char16_t> conv; return conv.from_bytes(std::to_string(i)); } }; diff --git a/tests/parser/LexerTests.cpp b/tests/parser/LexerTests.cpp index d101ad0..4d9a8a6 100644 --- a/tests/parser/LexerTests.cpp +++ b/tests/parser/LexerTests.cpp @@ -349,7 +349,7 @@ TEST_CASE( "Lex identifier", "[lexer]" ) { REQUIRE(tokens.size() == 2); const IToken* firstToken = tokens[0]; REQUIRE(firstToken -> GetKind() == TokenKind::Identifier); - REQUIRE(((IdentifierToken*)firstToken) -> GetValue() == HashedString("foo")); + REQUIRE(((IdentifierToken*)firstToken) -> GetValue() == HashedString::CreateLookup(u"foo")); for (auto t: tokens){ delete t; } diff --git a/tests/parser/ParserTests.cpp b/tests/parser/ParserTests.cpp index 78537f2..ff644e3 100644 --- a/tests/parser/ParserTests.cpp +++ b/tests/parser/ParserTests.cpp @@ -203,7 +203,7 @@ TEST_CASE( "Parse String Tokens", "[parser]" ) { TEST_CASE( "Parse Global Assignment", "[parser]" ) { vector v { - new IdentifierToken(HashedString("foo"),0,0), + new IdentifierToken(HashedString::CreateLookup(u"foo"),0,0), new SimpleToken(TokenKind::AssignmentToken,0,0), new SimpleToken(TokenKind::TrueKeyword,0,0), new SimpleToken(TokenKind::EndOfFile,0,0) @@ -216,7 +216,7 @@ TEST_CASE( "Parse Global Assignment", "[parser]" ) { REQUIRE(firstStatement -> GetKind() == ParsedStatementKind::Assignment); auto assignment = (ParsedAssignmentStatement*)firstStatement; REQUIRE(!assignment -> IsLocal()); - REQUIRE(assignment->GetIdentifier().GetHash() == HashedString("foo").GetHash()); + REQUIRE(assignment->GetIdentifier().GetHash() == HashedString::CreateLookup(u"foo").GetHash()); REQUIRE(((LiteralBoolExpression*)assignment->GetExpression()) -> GetValue()); for (auto t : v){ @@ -228,7 +228,7 @@ TEST_CASE( "Parse Global Assignment", "[parser]" ) { TEST_CASE( "Parse local Assignment", "[parser]" ) { vector v { new SimpleToken(TokenKind::LocalKeyword,0,0), - new IdentifierToken(HashedString("foo"),0,0), + new IdentifierToken(HashedString(new u16string(u"foo")),0,0), new SimpleToken(TokenKind::AssignmentToken,0,0), new SimpleToken(TokenKind::TrueKeyword,0,0), new SimpleToken(TokenKind::EndOfFile,0,0) @@ -241,7 +241,7 @@ TEST_CASE( "Parse local Assignment", "[parser]" ) { REQUIRE(firstStatement -> GetKind() == ParsedStatementKind::Assignment); auto assignment = (ParsedAssignmentStatement*)firstStatement; REQUIRE(assignment -> IsLocal()); - REQUIRE(assignment->GetIdentifier().GetHash() == HashedString("foo").GetHash()); + REQUIRE(assignment->GetIdentifier().GetHash() == HashedString::CreateLookup(u"foo").GetHash()); REQUIRE(((LiteralBoolExpression*)assignment->GetExpression()) -> GetValue()); for (auto t : v){ @@ -254,17 +254,17 @@ TEST_CASE( "Parse local Assignment", "[parser]" ) { TEST_CASE( "Parse function declaration", "[parser]" ){ vector v { new SimpleToken(TokenKind::FunctionKeyword,0,0), - new IdentifierToken(HashedString("foo"),0,0), + new IdentifierToken(HashedString(new u16string(u"foo")),0,0), new SimpleToken(TokenKind::OpenParenthesis,0,0), - new IdentifierToken(HashedString("number"),0,0), - new IdentifierToken(HashedString("bar"),0,0), + new IdentifierToken(HashedString(new u16string(u"number")),0,0), + new IdentifierToken(HashedString(new u16string(u"bar")),0,0), new SimpleToken(TokenKind::CommaToken,0,0), - new IdentifierToken(HashedString("number"),0,0), - new IdentifierToken(HashedString("par"),0,0), + new IdentifierToken(HashedString(new u16string(u"number")),0,0), + new IdentifierToken(HashedString(new u16string(u"par")),0,0), new SimpleToken(TokenKind::CloseParenthesis,0,0), - new IdentifierToken(HashedString("bar"),0,0), + new IdentifierToken(HashedString(new u16string(u"bar")),0,0), new SimpleToken(TokenKind::PlusToken,0,0), - new IdentifierToken(HashedString("par"),0,0), + new IdentifierToken(HashedString(new u16string(u"par")),0,0), new SimpleToken(TokenKind::EndKeyword,0,0), new SimpleToken(TokenKind::EndOfFile,0,0), }; @@ -275,12 +275,12 @@ TEST_CASE( "Parse function declaration", "[parser]" ){ auto firstStatement = parsedStatements -> at(0); REQUIRE(firstStatement -> GetKind() == ParsedStatementKind::FunctionDeclaration); auto functionDeclaration = (ParsedFunctionDeclarationStatement*)firstStatement; - REQUIRE(functionDeclaration->GetIdentifier() == HashedString("foo")); + REQUIRE(functionDeclaration->GetIdentifier() == HashedString::CreateLookup(u"foo")); auto parameters = functionDeclaration->GetParameters(); - CHECK(parameters -> at(0) ->GetType() == HashedString("number")); - CHECK(parameters -> at(0) ->GetIdentifier() == HashedString("bar")); - CHECK(parameters -> at(1) ->GetType() == HashedString("number")); - CHECK(parameters -> at(1) ->GetIdentifier() == HashedString("par")); + CHECK(parameters -> at(0) ->GetType() == HashedString::CreateLookup(u"number")); + CHECK(parameters -> at(0) ->GetIdentifier() == HashedString::CreateLookup(u"bar")); + CHECK(parameters -> at(1) ->GetType() == HashedString::CreateLookup(u"number")); + CHECK(parameters -> at(1) ->GetIdentifier() == HashedString::CreateLookup(u"par")); for (auto t : v){ delete t;