Merge pull request #6594 from ethereum/adjustCodeMetric

Increase code cost for branching statements.
This commit is contained in:
chriseth 2019-04-29 09:48:59 +02:00 committed by GitHub
commit 578d618065
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 107 additions and 27 deletions

View File

@ -63,6 +63,16 @@ void CodeSize::visit(Statement const& _statement)
{
if (_statement.type() == typeid(FunctionDefinition) && m_ignoreFunctions)
return;
else if (
_statement.type() == typeid(If) ||
_statement.type() == typeid(Break) ||
_statement.type() == typeid(Continue)
)
m_size += 2;
else if (_statement.type() == typeid(ForLoop))
m_size += 3;
else if (_statement.type() == typeid(Switch))
m_size += 1 + 2 * boost::get<Switch>(_statement).cases.size();
else if (!(
_statement.type() == typeid(Block) ||
_statement.type() == typeid(ExpressionStatement) ||

View File

@ -37,6 +37,11 @@ namespace yul
* - variable references
* - variable declarations (only the right hand side has a cost)
* - assignments (only the value has a cost)
*
* As another exception, each statement incurs and additional cost of one
* 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,
* and for loops cost 3.
*/
class CodeSize: public ASTWalker
{

View File

@ -2,7 +2,7 @@
======= gas_test_abiv2_optimize_yul/input.sol:C =======
Gas estimation:
construction:
651 + 616600 = 617251
645 + 608800 = 609445
external:
a(): 429
b(uint256): 884

View File

@ -110,6 +110,69 @@ BOOST_AUTO_TEST_CASE(assignment_complex)
BOOST_CHECK_EQUAL(codeSize("{ let a let x := mload(a) a := sload(x) }"), 2);
}
BOOST_AUTO_TEST_CASE(empty_for_loop)
{
BOOST_CHECK_EQUAL(codeSize(
"{ for {} 1 {} {} }"
), 4);
}
BOOST_AUTO_TEST_CASE(break_statement)
{
BOOST_CHECK_EQUAL(codeSize(
"{ for {} 1 {} { break } }"
), 6);
}
BOOST_AUTO_TEST_CASE(continue_statement)
{
BOOST_CHECK_EQUAL(codeSize(
"{ for {} 1 {} { continue } }"
), 6);
}
BOOST_AUTO_TEST_CASE(regular_for_loop)
{
BOOST_CHECK_EQUAL(codeSize(
"{ for { let x := 0 } lt(x, 10) { x := add(x, 1) } { mstore(x, 1) } }"
), 10);
}
BOOST_AUTO_TEST_CASE(if_statement)
{
BOOST_CHECK_EQUAL(codeSize(
"{ if 1 {} }"
), 3);
}
BOOST_AUTO_TEST_CASE(switch_statement_tiny)
{
BOOST_CHECK_EQUAL(codeSize(
"{ switch calldatasize() default {} }"
), 4);
}
BOOST_AUTO_TEST_CASE(switch_statement_small)
{
BOOST_CHECK_EQUAL(codeSize(
"{ switch calldatasize() case 0 {} default {} }"
), 6);
}
BOOST_AUTO_TEST_CASE(switch_statement_medium)
{
BOOST_CHECK_EQUAL(codeSize(
"{ switch calldatasize() case 0 {} case 1 {} case 2 {} }"
), 8);
}
BOOST_AUTO_TEST_CASE(switch_statement_large)
{
BOOST_CHECK_EQUAL(codeSize(
"{ switch calldatasize() case 0 {} case 1 {} case 2 {} default {} }"
), 10);
}
BOOST_AUTO_TEST_SUITE_END()
}

View File

@ -476,44 +476,30 @@
// i := add(i, 1)
// }
// {
// let _4 := mload(srcPtr)
// let pos_1 := pos
// let srcPtr_1 := _4
// let i_1 := _2
// for {
// }
// lt(i_1, 0x3)
// {
// i_1 := add(i_1, 1)
// }
// {
// mstore(pos_1, and(mload(srcPtr_1), 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))
// srcPtr_1 := add(srcPtr_1, _1)
// pos_1 := add(pos_1, _1)
// }
// abi_encode_t_array$_t_contract$_C_$55_$3_memory_to_t_array$_t_address_$3_memory_ptr(mload(srcPtr), pos)
// srcPtr := add(srcPtr, _1)
// pos := add(pos, 0x60)
// }
// let _5 := mload(64)
// let _6 := mload(_1)
// if slt(sub(_5, _6), 128)
// let _4 := mload(64)
// let _5 := mload(_1)
// if slt(sub(_4, _5), 128)
// {
// revert(_2, _2)
// }
// let offset := calldataload(add(_6, 64))
// let _7 := 0xffffffffffffffff
// if gt(offset, _7)
// let offset := calldataload(add(_5, 64))
// let _6 := 0xffffffffffffffff
// if gt(offset, _6)
// {
// revert(_2, _2)
// }
// let value2 := abi_decode_t_array$_t_uint256_$dyn_memory_ptr(add(_6, offset), _5)
// let offset_1 := calldataload(add(_6, 96))
// if gt(offset_1, _7)
// let value2 := abi_decode_t_array$_t_uint256_$dyn_memory_ptr(add(_5, offset), _4)
// let offset_1 := calldataload(add(_5, 96))
// if gt(offset_1, _6)
// {
// revert(_2, _2)
// }
// let value3 := abi_decode_t_array$_t_array$_t_uint256_$2_memory_$dyn_memory_ptr(add(_6, offset_1), _5)
// sstore(calldataload(_6), calldataload(add(_6, _1)))
// let value3 := abi_decode_t_array$_t_array$_t_uint256_$2_memory_$dyn_memory_ptr(add(_5, offset_1), _4)
// sstore(calldataload(_5), calldataload(add(_5, _1)))
// sstore(value2, value3)
// sstore(_2, pos)
// }
@ -601,6 +587,22 @@
// src := add(src, _1)
// }
// }
// function abi_encode_t_array$_t_contract$_C_$55_$3_memory_to_t_array$_t_address_$3_memory_ptr(value, pos)
// {
// let srcPtr := value
// let i := 0
// for {
// }
// lt(i, 0x3)
// {
// i := add(i, 1)
// }
// {
// mstore(pos, and(mload(srcPtr), 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))
// srcPtr := add(srcPtr, 0x20)
// pos := add(pos, 0x20)
// }
// }
// function allocateMemory(size) -> memPtr
// {
// memPtr := mload(64)