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) if (_statement.type() == typeid(FunctionDefinition) && m_ignoreFunctions)
return; 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 (!( else if (!(
_statement.type() == typeid(Block) || _statement.type() == typeid(Block) ||
_statement.type() == typeid(ExpressionStatement) || _statement.type() == typeid(ExpressionStatement) ||

View File

@ -37,6 +37,11 @@ namespace yul
* - 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
* 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 class CodeSize: public ASTWalker
{ {

View File

@ -2,7 +2,7 @@
======= gas_test_abiv2_optimize_yul/input.sol:C ======= ======= gas_test_abiv2_optimize_yul/input.sol:C =======
Gas estimation: Gas estimation:
construction: construction:
651 + 616600 = 617251 645 + 608800 = 609445
external: external:
a(): 429 a(): 429
b(uint256): 884 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_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() BOOST_AUTO_TEST_SUITE_END()
} }

View File

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