mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Add configurable weights to CodeSize metric
This commit is contained in:
parent
678a801daf
commit
d199fc537b
@ -36,30 +36,71 @@ using namespace solidity;
|
|||||||
using namespace solidity::yul;
|
using namespace solidity::yul;
|
||||||
using namespace solidity::util;
|
using namespace solidity::util;
|
||||||
|
|
||||||
size_t CodeSize::codeSize(Statement const& _statement)
|
size_t CodeWeights::costOf(Statement const& _statement) const
|
||||||
{
|
{
|
||||||
CodeSize cs;
|
if (holds_alternative<ExpressionStatement>(_statement))
|
||||||
|
return expressionStatementCost;
|
||||||
|
else if (holds_alternative<Assignment>(_statement))
|
||||||
|
return assignmentCost;
|
||||||
|
else if (holds_alternative<VariableDeclaration>(_statement))
|
||||||
|
return variableDeclarationCost;
|
||||||
|
else if (holds_alternative<FunctionDefinition>(_statement))
|
||||||
|
return functionDefinitionCost;
|
||||||
|
else if (holds_alternative<If>(_statement))
|
||||||
|
return ifCost;
|
||||||
|
else if (holds_alternative<Switch>(_statement))
|
||||||
|
return switchCost + caseCost * std::get<Switch>(_statement).cases.size();
|
||||||
|
else if (holds_alternative<ForLoop>(_statement))
|
||||||
|
return forLoopCost;
|
||||||
|
else if (holds_alternative<Break>(_statement))
|
||||||
|
return breakCost;
|
||||||
|
else if (holds_alternative<Continue>(_statement))
|
||||||
|
return continueCost;
|
||||||
|
else if (holds_alternative<Leave>(_statement))
|
||||||
|
return leaveCost;
|
||||||
|
else if (holds_alternative<Block>(_statement))
|
||||||
|
return blockCost;
|
||||||
|
else
|
||||||
|
yulAssert(false, "If you add a new statement type, you must update CodeWeights.");
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t CodeWeights::costOf(Expression const& _expression) const
|
||||||
|
{
|
||||||
|
if (holds_alternative<FunctionCall>(_expression))
|
||||||
|
return functionCallCost;
|
||||||
|
else if (holds_alternative<Identifier>(_expression))
|
||||||
|
return identifierCost;
|
||||||
|
else if (holds_alternative<Literal>(_expression))
|
||||||
|
return literalCost;
|
||||||
|
else
|
||||||
|
yulAssert(false, "If you add a new expression type, you must update CodeWeights.");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
size_t CodeSize::codeSize(Statement const& _statement, CodeWeights const& _weights)
|
||||||
|
{
|
||||||
|
CodeSize cs(true, _weights);
|
||||||
cs.visit(_statement);
|
cs.visit(_statement);
|
||||||
return cs.m_size;
|
return cs.m_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t CodeSize::codeSize(Expression const& _expression)
|
size_t CodeSize::codeSize(Expression const& _expression, CodeWeights const& _weights)
|
||||||
{
|
{
|
||||||
CodeSize cs;
|
CodeSize cs(true, _weights);
|
||||||
cs.visit(_expression);
|
cs.visit(_expression);
|
||||||
return cs.m_size;
|
return cs.m_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t CodeSize::codeSize(Block const& _block)
|
size_t CodeSize::codeSize(Block const& _block, CodeWeights const& _weights)
|
||||||
{
|
{
|
||||||
CodeSize cs;
|
CodeSize cs(true, _weights);
|
||||||
cs(_block);
|
cs(_block);
|
||||||
return cs.m_size;
|
return cs.m_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t CodeSize::codeSizeIncludingFunctions(Block const& _block)
|
size_t CodeSize::codeSizeIncludingFunctions(Block const& _block, CodeWeights const& _weights)
|
||||||
{
|
{
|
||||||
CodeSize cs(false);
|
CodeSize cs(false, _weights);
|
||||||
cs(_block);
|
cs(_block);
|
||||||
return cs.m_size;
|
return cs.m_size;
|
||||||
}
|
}
|
||||||
@ -68,32 +109,14 @@ void CodeSize::visit(Statement const& _statement)
|
|||||||
{
|
{
|
||||||
if (holds_alternative<FunctionDefinition>(_statement) && m_ignoreFunctions)
|
if (holds_alternative<FunctionDefinition>(_statement) && m_ignoreFunctions)
|
||||||
return;
|
return;
|
||||||
else if (
|
|
||||||
holds_alternative<If>(_statement) ||
|
|
||||||
holds_alternative<Break>(_statement) ||
|
|
||||||
holds_alternative<Continue>(_statement) ||
|
|
||||||
holds_alternative<Leave>(_statement)
|
|
||||||
)
|
|
||||||
m_size += 2;
|
|
||||||
else if (holds_alternative<ForLoop>(_statement))
|
|
||||||
m_size += 3;
|
|
||||||
else if (holds_alternative<Switch>(_statement))
|
|
||||||
m_size += 1 + 2 * std::get<Switch>(_statement).cases.size();
|
|
||||||
else if (!(
|
|
||||||
holds_alternative<Block>(_statement) ||
|
|
||||||
holds_alternative<ExpressionStatement>(_statement) ||
|
|
||||||
holds_alternative<Assignment>(_statement) ||
|
|
||||||
holds_alternative<VariableDeclaration>(_statement)
|
|
||||||
))
|
|
||||||
++m_size;
|
|
||||||
|
|
||||||
|
m_size += m_weights.costOf(_statement);
|
||||||
ASTWalker::visit(_statement);
|
ASTWalker::visit(_statement);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CodeSize::visit(Expression const& _expression)
|
void CodeSize::visit(Expression const& _expression)
|
||||||
{
|
{
|
||||||
if (!holds_alternative<Identifier>(_expression))
|
m_size += m_weights.costOf(_expression);
|
||||||
++m_size;
|
|
||||||
ASTWalker::visit(_expression);
|
ASTWalker::visit(_expression);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,33 +30,67 @@ struct Dialect;
|
|||||||
struct EVMDialect;
|
struct EVMDialect;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Metric for the size of code.
|
* Weights to be assigned to specific yul statements and expressions by a metric.
|
||||||
* More specifically, the number of AST nodes.
|
|
||||||
* Ignores function definitions while traversing the AST by default.
|
|
||||||
* If you want to know the size of a function, you have to invoke this on its body.
|
|
||||||
*
|
*
|
||||||
* As an exception, the following AST elements have a cost of zero:
|
* The default values are meant to reflect specifically the number of AST nodes.
|
||||||
|
*
|
||||||
|
* The following AST elements have a default cost of zero (because the cleanup phase would
|
||||||
|
* remove them anyway or they are just wrappers around something else will be counted instead):
|
||||||
* - expression statement (only the expression inside has a cost)
|
* - expression statement (only the expression inside has a cost)
|
||||||
* - block (only the statements inside have a cost)
|
* - block (only the statements inside have a cost)
|
||||||
* - variable references
|
* - variable references
|
||||||
* - variable declarations (only the right hand side has a cost)
|
* - variable declarations (only the right hand side has a cost)
|
||||||
* - assignments (only the value has a cost)
|
* - assignments (only the value has a cost)
|
||||||
*
|
*
|
||||||
* As another exception, each statement incurs and additional cost of one
|
* Each statement incurs and additional cost of one
|
||||||
* per jump/branch. This means if, break and continue statements have a cost of 2,
|
* per jump/branch. This means if, break and continue statements have a cost of 2,
|
||||||
* switch statements have a cost of 1 plus the number of cases times two,
|
* switch statements have a cost of 1 plus the number of cases times two,
|
||||||
* and for loops cost 3.
|
* and for loops cost 3.
|
||||||
|
*/
|
||||||
|
struct CodeWeights
|
||||||
|
{
|
||||||
|
// Statements
|
||||||
|
size_t expressionStatementCost = 0;
|
||||||
|
size_t assignmentCost = 0;
|
||||||
|
size_t variableDeclarationCost = 0;
|
||||||
|
size_t functionDefinitionCost = 1;
|
||||||
|
size_t ifCost = 2;
|
||||||
|
size_t switchCost = 1;
|
||||||
|
size_t caseCost = 2;
|
||||||
|
size_t forLoopCost = 3;
|
||||||
|
size_t breakCost = 2;
|
||||||
|
size_t continueCost = 2;
|
||||||
|
size_t leaveCost = 2;
|
||||||
|
size_t blockCost = 0;
|
||||||
|
|
||||||
|
// Expressions
|
||||||
|
size_t functionCallCost = 1;
|
||||||
|
size_t identifierCost = 0;
|
||||||
|
size_t literalCost = 1;
|
||||||
|
|
||||||
|
size_t costOf(Statement const& _statement) const;
|
||||||
|
size_t costOf(Expression const& _expression) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Metric for the size of code.
|
||||||
|
* Ignores function definitions while traversing the AST by default.
|
||||||
|
* If you want to know the size of a function, you have to invoke this on its body.
|
||||||
|
*
|
||||||
|
* The cost of each statement and expression type is configurable via CodeWeights.
|
||||||
*/
|
*/
|
||||||
class CodeSize: public ASTWalker
|
class CodeSize: public ASTWalker
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static size_t codeSize(Statement const& _statement);
|
static size_t codeSize(Statement const& _statement, CodeWeights const& _weights = {});
|
||||||
static size_t codeSize(Expression const& _expression);
|
static size_t codeSize(Expression const& _expression, CodeWeights const& _weights = {});
|
||||||
static size_t codeSize(Block const& _block);
|
static size_t codeSize(Block const& _block, CodeWeights const& _weights = {});
|
||||||
static size_t codeSizeIncludingFunctions(Block const& _block);
|
static size_t codeSizeIncludingFunctions(Block const& _block, CodeWeights const& _weights = {});
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CodeSize(bool _ignoreFunctions = true): m_ignoreFunctions(_ignoreFunctions) {}
|
CodeSize(bool _ignoreFunctions = true, CodeWeights const& _weights = {}):
|
||||||
|
m_ignoreFunctions(_ignoreFunctions),
|
||||||
|
m_weights(_weights) {}
|
||||||
|
|
||||||
void visit(Statement const& _statement) override;
|
void visit(Statement const& _statement) override;
|
||||||
void visit(Expression const& _expression) override;
|
void visit(Expression const& _expression) override;
|
||||||
@ -64,6 +98,7 @@ private:
|
|||||||
private:
|
private:
|
||||||
bool m_ignoreFunctions;
|
bool m_ignoreFunctions;
|
||||||
size_t m_size = 0;
|
size_t m_size = 0;
|
||||||
|
CodeWeights m_weights;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -36,15 +36,38 @@ namespace solidity::yul::test
|
|||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
|
||||||
size_t codeSize(string const& _source)
|
size_t codeSize(string const& _source, CodeWeights const _weights = {})
|
||||||
{
|
{
|
||||||
shared_ptr<Block> ast = parse(_source, false).first;
|
shared_ptr<Block> ast = parse(_source, false).first;
|
||||||
BOOST_REQUIRE(ast);
|
BOOST_REQUIRE(ast);
|
||||||
return CodeSize::codeSize(*ast);
|
return CodeSize::codeSize(*ast, _weights);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class CustomWeightFixture
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
CodeWeights m_weights{
|
||||||
|
/* expressionStatementCost = */ 1,
|
||||||
|
/* assignmentCost = */ 2,
|
||||||
|
/* variableDeclarationCost = */ 3,
|
||||||
|
/* functionDefinitionCost = */ 4,
|
||||||
|
/* ifCost = */ 5,
|
||||||
|
/* switchCost = */ 6,
|
||||||
|
/* caseCost = */ 7,
|
||||||
|
/* forLoopCost = */ 8,
|
||||||
|
/* breakCost = */ 9,
|
||||||
|
/* continueCost = */ 10,
|
||||||
|
/* leaveCost = */ 11,
|
||||||
|
/* blockCost = */ 12,
|
||||||
|
|
||||||
|
/* functionCallCost = */ 13,
|
||||||
|
/* identifierCost = */ 14,
|
||||||
|
/* literalCost = */ 15,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
BOOST_AUTO_TEST_SUITE(YulCodeSize)
|
BOOST_AUTO_TEST_SUITE(YulCodeSize)
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(empty_code)
|
BOOST_AUTO_TEST_CASE(empty_code)
|
||||||
@ -52,41 +75,103 @@ BOOST_AUTO_TEST_CASE(empty_code)
|
|||||||
BOOST_CHECK_EQUAL(codeSize("{}"), 0);
|
BOOST_CHECK_EQUAL(codeSize("{}"), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOST_FIXTURE_TEST_CASE(empty_code_custom_weights, CustomWeightFixture)
|
||||||
|
{
|
||||||
|
BOOST_CHECK_EQUAL(codeSize("{}", m_weights), 0);
|
||||||
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(nested_blocks)
|
BOOST_AUTO_TEST_CASE(nested_blocks)
|
||||||
{
|
{
|
||||||
BOOST_CHECK_EQUAL(codeSize("{ {} {} {{ }} }"), 0);
|
BOOST_CHECK_EQUAL(codeSize("{ {} {} {{ }} }"), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOST_FIXTURE_TEST_CASE(nested_blocks_custom_weights, CustomWeightFixture)
|
||||||
|
{
|
||||||
|
BOOST_CHECK_EQUAL(codeSize("{ {} {} {{ }} }", m_weights), 4 * m_weights.blockCost);
|
||||||
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(instruction)
|
BOOST_AUTO_TEST_CASE(instruction)
|
||||||
{
|
{
|
||||||
BOOST_CHECK_EQUAL(codeSize("{ pop(calldatasize()) }"), 2);
|
BOOST_CHECK_EQUAL(codeSize("{ pop(calldatasize()) }"), 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOST_FIXTURE_TEST_CASE(instruction_custom_weights, CustomWeightFixture)
|
||||||
|
{
|
||||||
|
BOOST_CHECK_EQUAL(
|
||||||
|
codeSize("{ pop(calldatasize()) }", m_weights),
|
||||||
|
2 * m_weights.functionCallCost +
|
||||||
|
1 * m_weights.expressionStatementCost
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(variables_are_free)
|
BOOST_AUTO_TEST_CASE(variables_are_free)
|
||||||
{
|
{
|
||||||
BOOST_CHECK_EQUAL(codeSize("{ let x let y let a, b, c }"), 0);
|
BOOST_CHECK_EQUAL(codeSize("{ let x let y let a, b, c }"), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOST_FIXTURE_TEST_CASE(variables_custom_weights, CustomWeightFixture)
|
||||||
|
{
|
||||||
|
BOOST_CHECK_EQUAL(
|
||||||
|
codeSize("{ let x let y let a, b, c }", m_weights),
|
||||||
|
3 * m_weights.variableDeclarationCost
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(constants_cost_one)
|
BOOST_AUTO_TEST_CASE(constants_cost_one)
|
||||||
{
|
{
|
||||||
BOOST_CHECK_EQUAL(codeSize("{ let x := 3 }"), 1);
|
BOOST_CHECK_EQUAL(codeSize("{ let x := 3 }"), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOST_FIXTURE_TEST_CASE(constants_custom_weights, CustomWeightFixture)
|
||||||
|
{
|
||||||
|
BOOST_CHECK_EQUAL(
|
||||||
|
codeSize("{ let x := 3 }", m_weights),
|
||||||
|
1 * m_weights.variableDeclarationCost +
|
||||||
|
1 * m_weights.literalCost
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(functions_are_skipped)
|
BOOST_AUTO_TEST_CASE(functions_are_skipped)
|
||||||
{
|
{
|
||||||
BOOST_CHECK_EQUAL(codeSize("{ function f(x) -> r { r := mload(x) } }"), 0);
|
BOOST_CHECK_EQUAL(codeSize("{ function f(x) -> r { r := mload(x) } }"), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOST_FIXTURE_TEST_CASE(functions_are_skipped_custom_weights, CustomWeightFixture)
|
||||||
|
{
|
||||||
|
BOOST_CHECK_EQUAL(codeSize("{ function f(x) -> r { r := mload(x) } }", m_weights), 0);
|
||||||
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(function_with_arguments)
|
BOOST_AUTO_TEST_CASE(function_with_arguments)
|
||||||
{
|
{
|
||||||
BOOST_CHECK_EQUAL(codeSize("{ function f(x) { sstore(x, 2) } f(2) }"), 2);
|
BOOST_CHECK_EQUAL(codeSize("{ function f(x) { sstore(x, 2) } f(2) }"), 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOST_FIXTURE_TEST_CASE(function_with_arguments_custom_weights, CustomWeightFixture)
|
||||||
|
{
|
||||||
|
BOOST_CHECK_EQUAL(
|
||||||
|
codeSize("{ function f(x) { sstore(x, 2) } f(2) }", m_weights),
|
||||||
|
1 * m_weights.expressionStatementCost +
|
||||||
|
1 * m_weights.functionCallCost +
|
||||||
|
1 * m_weights.literalCost
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(function_with_variables_as_arguments)
|
BOOST_AUTO_TEST_CASE(function_with_variables_as_arguments)
|
||||||
{
|
{
|
||||||
BOOST_CHECK_EQUAL(codeSize("{ function f(x) { sstore(x, 2) } let y f(y) }"), 1);
|
BOOST_CHECK_EQUAL(codeSize("{ function f(x) { sstore(x, 2) } let y f(y) }"), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOST_FIXTURE_TEST_CASE(function_with_variables_as_arguments_custom_weights, CustomWeightFixture)
|
||||||
|
{
|
||||||
|
BOOST_CHECK_EQUAL(
|
||||||
|
codeSize("{ function f(x) { sstore(x, 2) } let y f(y) }", m_weights),
|
||||||
|
1 * m_weights.variableDeclarationCost +
|
||||||
|
1 * m_weights.expressionStatementCost +
|
||||||
|
1 * m_weights.functionCallCost +
|
||||||
|
1 * m_weights.identifierCost
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(function_with_variables_and_constants_as_arguments)
|
BOOST_AUTO_TEST_CASE(function_with_variables_and_constants_as_arguments)
|
||||||
{
|
{
|
||||||
BOOST_CHECK_EQUAL(codeSize(
|
BOOST_CHECK_EQUAL(codeSize(
|
||||||
@ -94,21 +179,69 @@ BOOST_AUTO_TEST_CASE(function_with_variables_and_constants_as_arguments)
|
|||||||
), 2);
|
), 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOST_FIXTURE_TEST_CASE(
|
||||||
|
function_with_variables_and_constants_as_arguments_custom_weights,
|
||||||
|
CustomWeightFixture
|
||||||
|
)
|
||||||
|
{
|
||||||
|
BOOST_CHECK_EQUAL(
|
||||||
|
codeSize(
|
||||||
|
"{ function f(x, r) -> z { sstore(x, r) z := r } let y let t := f(y, 2) }",
|
||||||
|
m_weights
|
||||||
|
),
|
||||||
|
2 * m_weights.variableDeclarationCost +
|
||||||
|
1 * m_weights.functionCallCost +
|
||||||
|
1 * m_weights.identifierCost +
|
||||||
|
1 * m_weights.literalCost
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(assignment)
|
BOOST_AUTO_TEST_CASE(assignment)
|
||||||
{
|
{
|
||||||
BOOST_CHECK_EQUAL(codeSize("{ let a a := 3 }"), 1);
|
BOOST_CHECK_EQUAL(codeSize("{ let a a := 3 }"), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOST_FIXTURE_TEST_CASE(assignment_custom_weights, CustomWeightFixture)
|
||||||
|
{
|
||||||
|
BOOST_CHECK_EQUAL(
|
||||||
|
codeSize("{ let a a := 3 }", m_weights),
|
||||||
|
1 * m_weights.variableDeclarationCost +
|
||||||
|
1 * m_weights.assignmentCost +
|
||||||
|
1 * m_weights.literalCost
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(assignments_between_vars_are_free)
|
BOOST_AUTO_TEST_CASE(assignments_between_vars_are_free)
|
||||||
{
|
{
|
||||||
BOOST_CHECK_EQUAL(codeSize("{ let a let b := a a := b }"), 0);
|
BOOST_CHECK_EQUAL(codeSize("{ let a let b := a a := b }"), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOST_FIXTURE_TEST_CASE(assignments_between_vars_are_free_custom_weights, CustomWeightFixture)
|
||||||
|
{
|
||||||
|
BOOST_CHECK_EQUAL(
|
||||||
|
codeSize("{ let a let b := a a := b }", m_weights),
|
||||||
|
2 * m_weights.variableDeclarationCost +
|
||||||
|
1 * m_weights.assignmentCost +
|
||||||
|
2 * m_weights.identifierCost
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(assignment_complex)
|
BOOST_AUTO_TEST_CASE(assignment_complex)
|
||||||
{
|
{
|
||||||
BOOST_CHECK_EQUAL(codeSize("{ let a let x := mload(a) a := sload(x) }"), 2);
|
BOOST_CHECK_EQUAL(codeSize("{ let a let x := mload(a) a := sload(x) }"), 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOST_FIXTURE_TEST_CASE(assignment_complex_custom_weights, CustomWeightFixture)
|
||||||
|
{
|
||||||
|
BOOST_CHECK_EQUAL(
|
||||||
|
codeSize("{ let a let x := mload(a) a := sload(x) }", m_weights),
|
||||||
|
2 * m_weights.variableDeclarationCost +
|
||||||
|
1 * m_weights.assignmentCost +
|
||||||
|
2 * m_weights.identifierCost +
|
||||||
|
2 * m_weights.functionCallCost
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(empty_for_loop)
|
BOOST_AUTO_TEST_CASE(empty_for_loop)
|
||||||
{
|
{
|
||||||
BOOST_CHECK_EQUAL(codeSize(
|
BOOST_CHECK_EQUAL(codeSize(
|
||||||
@ -116,6 +249,15 @@ BOOST_AUTO_TEST_CASE(empty_for_loop)
|
|||||||
), 4);
|
), 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOST_FIXTURE_TEST_CASE(empty_for_loop_custom_weights, CustomWeightFixture)
|
||||||
|
{
|
||||||
|
BOOST_CHECK_EQUAL(
|
||||||
|
codeSize("{ for {} 1 {} {} }", m_weights),
|
||||||
|
1 * m_weights.forLoopCost +
|
||||||
|
1 * m_weights.literalCost
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(break_statement)
|
BOOST_AUTO_TEST_CASE(break_statement)
|
||||||
{
|
{
|
||||||
BOOST_CHECK_EQUAL(codeSize(
|
BOOST_CHECK_EQUAL(codeSize(
|
||||||
@ -123,6 +265,16 @@ BOOST_AUTO_TEST_CASE(break_statement)
|
|||||||
), 6);
|
), 6);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOST_FIXTURE_TEST_CASE(break_statement_custom_weights, CustomWeightFixture)
|
||||||
|
{
|
||||||
|
BOOST_CHECK_EQUAL(
|
||||||
|
codeSize("{ for {} 1 {} { break } }", m_weights),
|
||||||
|
1 * m_weights.forLoopCost +
|
||||||
|
1 * m_weights.literalCost +
|
||||||
|
1 * m_weights.breakCost
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(continue_statement)
|
BOOST_AUTO_TEST_CASE(continue_statement)
|
||||||
{
|
{
|
||||||
BOOST_CHECK_EQUAL(codeSize(
|
BOOST_CHECK_EQUAL(codeSize(
|
||||||
@ -130,6 +282,16 @@ BOOST_AUTO_TEST_CASE(continue_statement)
|
|||||||
), 6);
|
), 6);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOST_FIXTURE_TEST_CASE(continue_statement_custom_weights, CustomWeightFixture)
|
||||||
|
{
|
||||||
|
BOOST_CHECK_EQUAL(
|
||||||
|
codeSize("{ for {} 1 {} { continue } }", m_weights),
|
||||||
|
1 * m_weights.forLoopCost +
|
||||||
|
1 * m_weights.literalCost +
|
||||||
|
1 * m_weights.continueCost
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(regular_for_loop)
|
BOOST_AUTO_TEST_CASE(regular_for_loop)
|
||||||
{
|
{
|
||||||
BOOST_CHECK_EQUAL(codeSize(
|
BOOST_CHECK_EQUAL(codeSize(
|
||||||
@ -137,6 +299,20 @@ BOOST_AUTO_TEST_CASE(regular_for_loop)
|
|||||||
), 10);
|
), 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOST_FIXTURE_TEST_CASE(regular_for_loop_custom_weights, CustomWeightFixture)
|
||||||
|
{
|
||||||
|
BOOST_CHECK_EQUAL(
|
||||||
|
codeSize("{ for { let x := 0 } lt(x, 10) { x := add(x, 1) } { mstore(x, 1) } }", m_weights),
|
||||||
|
1 * m_weights.forLoopCost +
|
||||||
|
1 * m_weights.variableDeclarationCost +
|
||||||
|
1 * m_weights.assignmentCost +
|
||||||
|
3 * m_weights.functionCallCost +
|
||||||
|
4 * m_weights.literalCost +
|
||||||
|
3 * m_weights.identifierCost +
|
||||||
|
1 * m_weights.expressionStatementCost
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(if_statement)
|
BOOST_AUTO_TEST_CASE(if_statement)
|
||||||
{
|
{
|
||||||
BOOST_CHECK_EQUAL(codeSize(
|
BOOST_CHECK_EQUAL(codeSize(
|
||||||
@ -144,6 +320,15 @@ BOOST_AUTO_TEST_CASE(if_statement)
|
|||||||
), 3);
|
), 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOST_FIXTURE_TEST_CASE(if_statement_custom_weights, CustomWeightFixture)
|
||||||
|
{
|
||||||
|
BOOST_CHECK_EQUAL(
|
||||||
|
codeSize("{ if 1 {} }", m_weights),
|
||||||
|
1 * m_weights.ifCost +
|
||||||
|
1 * m_weights.literalCost
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(switch_statement_tiny)
|
BOOST_AUTO_TEST_CASE(switch_statement_tiny)
|
||||||
{
|
{
|
||||||
BOOST_CHECK_EQUAL(codeSize(
|
BOOST_CHECK_EQUAL(codeSize(
|
||||||
@ -158,6 +343,16 @@ BOOST_AUTO_TEST_CASE(switch_statement_small)
|
|||||||
), 6);
|
), 6);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOST_FIXTURE_TEST_CASE(switch_statement_small_custom_weights, CustomWeightFixture)
|
||||||
|
{
|
||||||
|
BOOST_CHECK_EQUAL(
|
||||||
|
codeSize("{ switch calldatasize() case 0 {} default {} }", m_weights),
|
||||||
|
1 * m_weights.functionCallCost +
|
||||||
|
1 * m_weights.switchCost +
|
||||||
|
2 * m_weights.caseCost
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(switch_statement_medium)
|
BOOST_AUTO_TEST_CASE(switch_statement_medium)
|
||||||
{
|
{
|
||||||
BOOST_CHECK_EQUAL(codeSize(
|
BOOST_CHECK_EQUAL(codeSize(
|
||||||
@ -172,6 +367,16 @@ BOOST_AUTO_TEST_CASE(switch_statement_large)
|
|||||||
), 10);
|
), 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOST_FIXTURE_TEST_CASE(switch_statement_large_custom_weights, CustomWeightFixture)
|
||||||
|
{
|
||||||
|
BOOST_CHECK_EQUAL(
|
||||||
|
codeSize("{ switch calldatasize() case 0 {} case 1 {} case 2 {} default {} }", m_weights),
|
||||||
|
1 * m_weights.functionCallCost +
|
||||||
|
1 * m_weights.switchCost +
|
||||||
|
4 * m_weights.caseCost
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_SUITE_END()
|
BOOST_AUTO_TEST_SUITE_END()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user