Skip to content

Commit

Permalink
Merge pull request #5334 from ethereum/stringPerformance
Browse files Browse the repository at this point in the history
[Yul] String performance
  • Loading branch information
chriseth authored Nov 7, 2018
2 parents 0a96f09 + 674e17c commit deed8e2
Show file tree
Hide file tree
Showing 59 changed files with 351 additions and 243 deletions.
8 changes: 4 additions & 4 deletions libsolidity/analysis/ReferencesResolver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -271,16 +271,16 @@ bool ReferencesResolver::visit(InlineAssembly const& _inlineAssembly)
ErrorReporter errorsIgnored(errors);
yul::ExternalIdentifierAccess::Resolver resolver =
[&](assembly::Identifier const& _identifier, yul::IdentifierContext, bool _crossesFunctionBoundary) {
auto declarations = m_resolver.nameFromCurrentScope(_identifier.name);
bool isSlot = boost::algorithm::ends_with(_identifier.name, "_slot");
bool isOffset = boost::algorithm::ends_with(_identifier.name, "_offset");
auto declarations = m_resolver.nameFromCurrentScope(_identifier.name.str());
bool isSlot = boost::algorithm::ends_with(_identifier.name.str(), "_slot");
bool isOffset = boost::algorithm::ends_with(_identifier.name.str(), "_offset");
if (isSlot || isOffset)
{
// special mode to access storage variables
if (!declarations.empty())
// the special identifier exists itself, we should not allow that.
return size_t(-1);
string realName = _identifier.name.substr(0, _identifier.name.size() - (
string realName = _identifier.name.str().substr(0, _identifier.name.str().size() - (
isSlot ?
string("_slot").size() :
string("_offset").size()
Expand Down
2 changes: 1 addition & 1 deletion libsolidity/ast/ASTJsonConverter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -459,7 +459,7 @@ bool ASTJsonConverter::visit(InlineAssembly const& _node)
if (it.first)
{
Json::Value tuple(Json::objectValue);
tuple[it.first->name] = inlineAssemblyIdentifierToJson(it);
tuple[it.first->name.str()] = inlineAssemblyIdentifierToJson(it);
externalReferences.append(tuple);
}
}
Expand Down
5 changes: 3 additions & 2 deletions libsolidity/codegen/CompilerContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
#include <libsolidity/inlineasm/AsmCodeGen.h>
#include <libsolidity/inlineasm/AsmAnalysis.h>
#include <libsolidity/inlineasm/AsmAnalysisInfo.h>
#include <libyul/YulString.h>

#include <boost/algorithm/string/replace.hpp>

Expand Down Expand Up @@ -326,7 +327,7 @@ void CompilerContext::appendInlineAssembly(
bool
)
{
auto it = std::find(_localVariables.begin(), _localVariables.end(), _identifier.name);
auto it = std::find(_localVariables.begin(), _localVariables.end(), _identifier.name.str());
return it == _localVariables.end() ? size_t(-1) : 1;
};
identifierAccess.generateCode = [&](
Expand All @@ -335,7 +336,7 @@ void CompilerContext::appendInlineAssembly(
yul::AbstractAssembly& _assembly
)
{
auto it = std::find(_localVariables.begin(), _localVariables.end(), _identifier.name);
auto it = std::find(_localVariables.begin(), _localVariables.end(), _identifier.name.str());
solAssert(it != _localVariables.end(), "");
int stackDepth = _localVariables.end() - it;
int stackDiff = _assembly.stackHeight() - startStackHeight + stackDepth;
Expand Down
22 changes: 11 additions & 11 deletions libsolidity/inlineasm/AsmAnalysis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,17 +79,17 @@ bool AsmAnalyzer::operator()(assembly::Instruction const& _instruction)

bool AsmAnalyzer::operator()(assembly::Literal const& _literal)
{
expectValidType(_literal.type, _literal.location);
expectValidType(_literal.type.str(), _literal.location);
++m_stackHeight;
if (_literal.kind == assembly::LiteralKind::String && _literal.value.size() > 32)
if (_literal.kind == assembly::LiteralKind::String && _literal.value.str().size() > 32)
{
m_errorReporter.typeError(
_literal.location,
"String literal too long (" + to_string(_literal.value.size()) + " > 32)"
"String literal too long (" + to_string(_literal.value.str().size()) + " > 32)"
);
return false;
}
else if (_literal.kind == assembly::LiteralKind::Number && bigint(_literal.value) > u256(-1))
else if (_literal.kind == assembly::LiteralKind::Number && bigint(_literal.value.str()) > u256(-1))
{
m_errorReporter.typeError(
_literal.location,
Expand All @@ -100,7 +100,7 @@ bool AsmAnalyzer::operator()(assembly::Literal const& _literal)
else if (_literal.kind == assembly::LiteralKind::Boolean)
{
solAssert(m_flavour == AsmFlavour::Yul, "");
solAssert(_literal.value == "true" || _literal.value == "false", "");
solAssert(_literal.value == YulString{string("true")} || _literal.value == YulString{string("false")}, "");
}
m_info.stackHeightInfo[&_literal] = m_stackHeight;
return true;
Expand All @@ -118,7 +118,7 @@ bool AsmAnalyzer::operator()(assembly::Identifier const& _identifier)
{
m_errorReporter.declarationError(
_identifier.location,
"Variable " + _identifier.name + " used before it was declared."
"Variable " + _identifier.name.str() + " used before it was declared."
);
success = false;
}
Expand All @@ -132,7 +132,7 @@ bool AsmAnalyzer::operator()(assembly::Identifier const& _identifier)
{
m_errorReporter.typeError(
_identifier.location,
"Function " + _identifier.name + " used without being called."
"Function " + _identifier.name.str() + " used without being called."
);
success = false;
}
Expand Down Expand Up @@ -253,7 +253,7 @@ bool AsmAnalyzer::operator()(assembly::VariableDeclaration const& _varDecl)

for (auto const& variable: _varDecl.variables)
{
expectValidType(variable.type, variable.location);
expectValidType(variable.type.str(), variable.location);
m_activeVariables.insert(&boost::get<Scope::Variable>(m_currentScope->identifiers.at(variable.name)));
}
m_info.stackHeightInfo[&_varDecl] = m_stackHeight;
Expand All @@ -268,7 +268,7 @@ bool AsmAnalyzer::operator()(assembly::FunctionDefinition const& _funDef)
Scope& varScope = scope(virtualBlock);
for (auto const& var: _funDef.parameters + _funDef.returnVariables)
{
expectValidType(var.type, var.location);
expectValidType(var.type.str(), var.location);
m_activeVariables.insert(&boost::get<Scope::Variable>(varScope.identifiers.at(var.name)));
}

Expand Down Expand Up @@ -361,7 +361,7 @@ bool AsmAnalyzer::operator()(Switch const& _switch)
if (!expectExpression(*_switch.expression))
success = false;

set<tuple<LiteralKind, string>> cases;
set<tuple<LiteralKind, YulString>> cases;
for (auto const& _case: _switch.cases)
{
if (_case.value)
Expand Down Expand Up @@ -503,7 +503,7 @@ bool AsmAnalyzer::checkAssignment(assembly::Identifier const& _variable, size_t
{
m_errorReporter.declarationError(
_variable.location,
"Variable " + _variable.name + " used before it was declared."
"Variable " + _variable.name.str() + " used before it was declared."
);
success = false;
}
Expand Down
19 changes: 13 additions & 6 deletions libsolidity/inlineasm/AsmData.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,13 @@
#include <libevmasm/Instruction.h>
#include <libevmasm/SourceLocation.h>

#include <libyul/YulString.h>

#include <boost/variant.hpp>
#include <boost/noncopyable.hpp>

#include <map>
#include <memory>

namespace dev
{
Expand All @@ -36,20 +42,21 @@ namespace solidity
namespace assembly
{

using Type = std::string;
using YulString = dev::yul::YulString;
using Type = YulString;

struct TypedName { SourceLocation location; std::string name; Type type; };
struct TypedName { SourceLocation location; YulString name; Type type; };
using TypedNameList = std::vector<TypedName>;

/// Direct EVM instruction (except PUSHi and JUMPDEST)
struct Instruction { SourceLocation location; solidity::Instruction instruction; };
/// Literal number or string (up to 32 bytes)
enum class LiteralKind { Number, Boolean, String };
struct Literal { SourceLocation location; LiteralKind kind; std::string value; Type type; };
struct Literal { SourceLocation location; LiteralKind kind; YulString value; Type type; };
/// External / internal identifier or label reference
struct Identifier { SourceLocation location; std::string name; };
struct Identifier { SourceLocation location; YulString name; };
/// Jump label ("name:")
struct Label { SourceLocation location; std::string name; };
struct Label { SourceLocation location; YulString name; };
/// Assignment from stack (":= x", moves stack top into x, potentially multiple slots)
struct StackAssignment { SourceLocation location; Identifier variableName; };
/// Assignment ("x := mload(20:u256)", expects push-1-expression on the right hand
Expand All @@ -69,7 +76,7 @@ struct VariableDeclaration { SourceLocation location; TypedNameList variables; s
/// Block that creates a scope (frees declared stack variables)
struct Block { SourceLocation location; std::vector<Statement> statements; };
/// Function definition ("function f(a, b) -> (d, e) { ... }")
struct FunctionDefinition { SourceLocation location; std::string name; TypedNameList parameters; TypedNameList returnVariables; Block body; };
struct FunctionDefinition { SourceLocation location; YulString name; TypedNameList parameters; TypedNameList returnVariables; Block body; };
/// Conditional execution without "else" part.
struct If { SourceLocation location; std::shared_ptr<Expression> condition; Block body; };
/// Switch case or default case
Expand Down
20 changes: 10 additions & 10 deletions libsolidity/inlineasm/AsmParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -112,8 +112,8 @@ assembly::Statement Parser::parseStatement()
advance();
expectToken(Token::Colon);
assignment.variableName.location = location();
assignment.variableName.name = currentLiteral();
if (instructions().count(assignment.variableName.name))
assignment.variableName.name = YulString(currentLiteral());
if (instructions().count(assignment.variableName.name.str()))
fatalParserError("Identifier expected, got instruction name.");
assignment.location.end = endPosition();
expectToken(Token::Identifier);
Expand Down Expand Up @@ -173,7 +173,7 @@ assembly::Statement Parser::parseStatement()
if (currentToken() == Token::Assign && peekNextToken() != Token::Colon)
{
assembly::Assignment assignment = createWithLocation<assembly::Assignment>(identifier.location);
if (m_flavour != AsmFlavour::Yul && instructions().count(identifier.name))
if (m_flavour != AsmFlavour::Yul && instructions().count(identifier.name.str()))
fatalParserError("Cannot use instruction names for identifier names.");
advance();
assignment.variableNames.emplace_back(identifier);
Expand Down Expand Up @@ -363,7 +363,7 @@ Parser::ElementaryOperation Parser::parseElementaryOperation()
ret = Instruction{location(), instr};
}
else
ret = Identifier{location(), literal};
ret = Identifier{location(), YulString{literal}};
advance();
break;
}
Expand Down Expand Up @@ -394,15 +394,15 @@ Parser::ElementaryOperation Parser::parseElementaryOperation()
Literal literal{
location(),
kind,
currentLiteral(),
""
YulString{currentLiteral()},
{}
};
advance();
if (m_flavour == AsmFlavour::Yul)
{
expectToken(Token::Colon);
literal.location.end = endPosition();
literal.type = expectAsmIdentifier();
literal.type = YulString{expectAsmIdentifier()};
}
else if (kind == LiteralKind::Boolean)
fatalParserError("True and false are not valid literals.");
Expand Down Expand Up @@ -449,7 +449,7 @@ assembly::FunctionDefinition Parser::parseFunctionDefinition()
RecursionGuard recursionGuard(*this);
FunctionDefinition funDef = createWithLocation<FunctionDefinition>();
expectToken(Token::Function);
funDef.name = expectAsmIdentifier();
funDef.name = YulString{expectAsmIdentifier()};
expectToken(Token::LParen);
while (currentToken() != Token::RParen)
{
Expand Down Expand Up @@ -564,12 +564,12 @@ TypedName Parser::parseTypedName()
{
RecursionGuard recursionGuard(*this);
TypedName typedName = createWithLocation<TypedName>();
typedName.name = expectAsmIdentifier();
typedName.name = YulString{expectAsmIdentifier()};
if (m_flavour == AsmFlavour::Yul)
{
expectToken(Token::Colon);
typedName.location.end = endPosition();
typedName.type = expectAsmIdentifier();
typedName.type = YulString{expectAsmIdentifier()};
}
return typedName;
}
Expand Down
22 changes: 11 additions & 11 deletions libsolidity/inlineasm/AsmPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,17 +52,17 @@ string AsmPrinter::operator()(assembly::Literal const& _literal)
switch (_literal.kind)
{
case LiteralKind::Number:
solAssert(isValidDecimal(_literal.value) || isValidHex(_literal.value), "Invalid number literal");
return _literal.value + appendTypeName(_literal.type);
solAssert(isValidDecimal(_literal.value.str()) || isValidHex(_literal.value.str()), "Invalid number literal");
return _literal.value.str() + appendTypeName(_literal.type);
case LiteralKind::Boolean:
solAssert(_literal.value == "true" || _literal.value == "false", "Invalid bool literal.");
return ((_literal.value == "true") ? "true" : "false") + appendTypeName(_literal.type);
solAssert(_literal.value.str() == "true" || _literal.value.str() == "false", "Invalid bool literal.");
return ((_literal.value.str() == "true") ? "true" : "false") + appendTypeName(_literal.type);
case LiteralKind::String:
break;
}

string out;
for (char c: _literal.value)
for (char c: _literal.value.str())
if (c == '\\')
out += "\\\\";
else if (c == '"')
Expand Down Expand Up @@ -93,7 +93,7 @@ string AsmPrinter::operator()(assembly::Literal const& _literal)
string AsmPrinter::operator()(assembly::Identifier const& _identifier)
{
solAssert(!_identifier.name.empty(), "Invalid identifier.");
return _identifier.name;
return _identifier.name.str();
}

string AsmPrinter::operator()(assembly::FunctionalInstruction const& _functionalInstruction)
Expand All @@ -118,7 +118,7 @@ string AsmPrinter::operator()(assembly::Label const& _label)
{
solAssert(!m_yul, "");
solAssert(!_label.name.empty(), "Invalid label.");
return _label.name + ":";
return _label.name.str() + ":";
}

string AsmPrinter::operator()(assembly::StackAssignment const& _assignment)
Expand Down Expand Up @@ -157,7 +157,7 @@ string AsmPrinter::operator()(assembly::VariableDeclaration const& _variableDecl
string AsmPrinter::operator()(assembly::FunctionDefinition const& _functionDefinition)
{
solAssert(!_functionDefinition.name.empty(), "Invalid function name.");
string out = "function " + _functionDefinition.name + "(";
string out = "function " + _functionDefinition.name.str() + "(";
out += boost::algorithm::join(
_functionDefinition.parameters | boost::adaptors::transformed(
[this](TypedName argument) { return formatTypedName(argument); }
Expand Down Expand Up @@ -239,12 +239,12 @@ string AsmPrinter::operator()(Block const& _block)
string AsmPrinter::formatTypedName(TypedName _variable) const
{
solAssert(!_variable.name.empty(), "Invalid variable name.");
return _variable.name + appendTypeName(_variable.type);
return _variable.name.str() + appendTypeName(_variable.type);
}

string AsmPrinter::appendTypeName(std::string const& _type) const
string AsmPrinter::appendTypeName(YulString _type) const
{
if (m_yul)
return ":" + _type;
return ":" + _type.str();
return "";
}
4 changes: 3 additions & 1 deletion libsolidity/inlineasm/AsmPrinter.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@

#include <libsolidity/inlineasm/AsmDataForward.h>

#include <libyul/YulString.h>

#include <boost/variant.hpp>

namespace dev
Expand Down Expand Up @@ -56,7 +58,7 @@ class AsmPrinter: public boost::static_visitor<std::string>

private:
std::string formatTypedName(TypedName _variable) const;
std::string appendTypeName(std::string const& _type) const;
std::string appendTypeName(yul::YulString _type) const;

bool m_yul = false;
};
Expand Down
10 changes: 5 additions & 5 deletions libsolidity/inlineasm/AsmScope.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,15 @@ using namespace std;
using namespace dev::solidity::assembly;


bool Scope::registerLabel(string const& _name)
bool Scope::registerLabel(yul::YulString _name)
{
if (exists(_name))
return false;
identifiers[_name] = Label();
return true;
}

bool Scope::registerVariable(string const& _name, YulType const& _type)
bool Scope::registerVariable(yul::YulString _name, YulType const& _type)
{
if (exists(_name))
return false;
Expand All @@ -42,15 +42,15 @@ bool Scope::registerVariable(string const& _name, YulType const& _type)
return true;
}

bool Scope::registerFunction(string const& _name, std::vector<YulType> const& _arguments, std::vector<YulType> const& _returns)
bool Scope::registerFunction(yul::YulString _name, std::vector<YulType> const& _arguments, std::vector<YulType> const& _returns)
{
if (exists(_name))
return false;
identifiers[_name] = Function{_arguments, _returns};
return true;
}

Scope::Identifier* Scope::lookup(string const& _name)
Scope::Identifier* Scope::lookup(yul::YulString _name)
{
bool crossedFunctionBoundary = false;
for (Scope* s = this; s; s = s->superScope)
Expand All @@ -70,7 +70,7 @@ Scope::Identifier* Scope::lookup(string const& _name)
return nullptr;
}

bool Scope::exists(string const& _name) const
bool Scope::exists(yul::YulString _name) const
{
if (identifiers.count(_name))
return true;
Expand Down
Loading

0 comments on commit deed8e2

Please sign in to comment.