Merge pull request #11268 from ethereum/refactorByteArrayPopSol2Yul

[Sol->Yul] Refactor ByteArrayPop to use unchecked index access
This commit is contained in:
chriseth 2021-04-21 13:05:00 +02:00 committed by GitHub
commit c3d73982ea
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 40 additions and 17 deletions

View File

@ -1348,6 +1348,24 @@ string YulUtilFunctions::shortByteArrayEncodeUsedAreaSetLengthFunction()
}); });
} }
string YulUtilFunctions::longByteArrayStorageIndexAccessNoCheckFunction()
{
return m_functionCollector.createFunction(
"long_byte_array_index_access_no_checks",
[&](vector<string>& _args, vector<string>& _returnParams) {
_args = {"array", "index"};
_returnParams = {"slot", "offset"};
return Whiskers(R"(
offset := sub(31, mod(index, 0x20))
let dataArea := <dataAreaFunc>(array)
slot := add(dataArea, div(index, 0x20))
)")
("dataAreaFunc", arrayDataAreaFunction(*TypeProvider::bytesStorage()))
.render();
}
);
}
string YulUtilFunctions::storageArrayPopFunction(ArrayType const& _type) string YulUtilFunctions::storageArrayPopFunction(ArrayType const& _type)
{ {
solAssert(_type.location() == DataLocation::Storage, ""); solAssert(_type.location() == DataLocation::Storage, "");
@ -1406,7 +1424,7 @@ string YulUtilFunctions::storageByteArrayPopFunction(ArrayType const& _type)
sstore(array, <encodeUsedSetLen>(data, newLen)) sstore(array, <encodeUsedSetLen>(data, newLen))
} }
default { default {
let slot, offset := <indexAccess>(array, newLen) let slot, offset := <indexAccessNoChecks>(array, newLen)
<setToZero>(slot, offset) <setToZero>(slot, offset)
sstore(array, sub(data, 2)) sstore(array, sub(data, 2))
} }
@ -1417,7 +1435,7 @@ string YulUtilFunctions::storageByteArrayPopFunction(ArrayType const& _type)
("extractByteArrayLength", extractByteArrayLengthFunction()) ("extractByteArrayLength", extractByteArrayLengthFunction())
("transitLongToShort", byteArrayTransitLongToShortFunction(_type)) ("transitLongToShort", byteArrayTransitLongToShortFunction(_type))
("encodeUsedSetLen", shortByteArrayEncodeUsedAreaSetLengthFunction()) ("encodeUsedSetLen", shortByteArrayEncodeUsedAreaSetLengthFunction())
("indexAccess", storageArrayIndexAccessFunction(_type)) ("indexAccessNoChecks", longByteArrayStorageIndexAccessNoCheckFunction())
("setToZero", storageSetToZeroFunction(*_type.baseType())) ("setToZero", storageSetToZeroFunction(*_type.baseType()))
.render(); .render();
}); });
@ -2112,13 +2130,12 @@ string YulUtilFunctions::storageArrayIndexAccessFunction(ArrayType const& _type)
<?multipleItemsPerSlot> <?multipleItemsPerSlot>
<?isBytesArray> <?isBytesArray>
offset := sub(31, mod(index, 0x20))
switch lt(arrayLength, 0x20) switch lt(arrayLength, 0x20)
case 0 { case 0 {
let dataArea := <dataAreaFunc>(array) slot, offset := <indexAccessNoChecks>(array, index)
slot := add(dataArea, div(index, 0x20))
} }
default { default {
offset := sub(31, mod(index, 0x20))
slot := array slot := array
} }
<!isBytesArray> <!isBytesArray>
@ -2137,6 +2154,7 @@ string YulUtilFunctions::storageArrayIndexAccessFunction(ArrayType const& _type)
("panic", panicFunction(PanicCode::ArrayOutOfBounds)) ("panic", panicFunction(PanicCode::ArrayOutOfBounds))
("arrayLen", arrayLengthFunction(_type)) ("arrayLen", arrayLengthFunction(_type))
("dataAreaFunc", arrayDataAreaFunction(_type)) ("dataAreaFunc", arrayDataAreaFunction(_type))
("indexAccessNoChecks", longByteArrayStorageIndexAccessNoCheckFunction())
("multipleItemsPerSlot", _type.baseType()->storageBytes() <= 16) ("multipleItemsPerSlot", _type.baseType()->storageBytes() <= 16)
("isBytesArray", _type.isByteArray()) ("isBytesArray", _type.isByteArray())
("storageSize", _type.baseType()->storageSize().str()) ("storageSize", _type.baseType()->storageSize().str())

View File

@ -552,6 +552,11 @@ private:
/// signature: (data, len) -> data /// signature: (data, len) -> data
std::string shortByteArrayEncodeUsedAreaSetLengthFunction(); std::string shortByteArrayEncodeUsedAreaSetLengthFunction();
/// @returns the name of a function that calculates slot and offset for index
/// Doesn't perform length checks, assumes that index is in bounds
/// signature: (array, index)
std::string longByteArrayStorageIndexAccessNoCheckFunction();
langutil::EVMVersion m_evmVersion; langutil::EVMVersion m_evmVersion;
RevertStrings m_revertStrings; RevertStrings m_revertStrings;
MultiUseYulFunctionCollector& m_functionCollector; MultiUseYulFunctionCollector& m_functionCollector;

View File

@ -139,14 +139,14 @@ object "C_59" {
} }
function storage_array_index_access_struct_S_1252() -> slot, offset function storage_array_index_access_struct_S_1252() -> slot, offset
{ {
if iszero(lt(slot, 0x02)) { panic_error_0x32() } if iszero(lt(offset, 0x02)) { panic_error_0x32() }
slot := add(slot, slot) slot := add(offset, offset)
offset := offset offset := offset
} }
function storage_array_index_access_struct_S() -> slot, offset function storage_array_index_access_struct_S() -> slot, offset
{ {
if iszero(lt(slot, 0x02)) { panic_error_0x32() } if iszero(lt(offset, 0x02)) { panic_error_0x32() }
slot := add(0x02, slot) slot := add(0x02, offset)
offset := offset offset := offset
} }
} }

View File

@ -19,6 +19,6 @@ contract c {
// compileViaYul: also // compileViaYul: also
// ---- // ----
// test() -> 0 // test() -> 0
// gas irOptimized: 311472 // gas irOptimized: 310460
// gas legacy: 483915 // gas legacy: 483915
// gas legacyOptimized: 478672 // gas legacyOptimized: 478672

View File

@ -44,7 +44,7 @@ contract c {
// ---- // ----
// getLengths() -> 0, 0 // getLengths() -> 0, 0
// setLengths(uint256,uint256): 48, 49 -> // setLengths(uint256,uint256): 48, 49 ->
// gas irOptimized: 275838 // gas irOptimized: 276212
// gas legacy: 308271 // gas legacy: 308271
// gas legacyOptimized: 300117 // gas legacyOptimized: 300117
// getLengths() -> 48, 49 // getLengths() -> 48, 49

View File

@ -12,6 +12,6 @@ contract c {
// compileViaYul: also // compileViaYul: also
// ---- // ----
// test() -> 0x20, 29, 0x0303030303030303030303030303030303030303030303030303030303000000 // test() -> 0x20, 29, 0x0303030303030303030303030303030303030303030303030303030303000000
// gas irOptimized: 163572 // gas irOptimized: 162649
// gas legacy: 245809 // gas legacy: 245809
// gas legacyOptimized: 242636 // gas legacyOptimized: 242636

View File

@ -18,7 +18,7 @@ contract c {
// compileViaYul: also // compileViaYul: also
// ---- // ----
// test() -> true // test() -> true
// gas irOptimized: 455893 // gas irOptimized: 447028
// gas legacy: 552064 // gas legacy: 552064
// gas legacyOptimized: 533164 // gas legacyOptimized: 533164
// storage: empty // storage: empty

View File

@ -17,7 +17,7 @@ contract c {
// compileViaYul: also // compileViaYul: also
// ---- // ----
// test() -> // test() ->
// gas irOptimized: 300849 // gas irOptimized: 291984
// gas legacy: 372763 // gas legacy: 372763
// gas legacyOptimized: 366846 // gas legacyOptimized: 366846
// storage: empty // storage: empty

View File

@ -12,6 +12,6 @@ contract c {
// compileViaYul: also // compileViaYul: also
// ---- // ----
// test() -> 0x20, 33, 0x303030303030303030303030303030303030303030303030303030303030303, 0x0300000000000000000000000000000000000000000000000000000000000000 // test() -> 0x20, 33, 0x303030303030303030303030303030303030303030303030303030303030303, 0x0300000000000000000000000000000000000000000000000000000000000000
// gas irOptimized: 160904 // gas irOptimized: 160043
// gas legacy: 243287 // gas legacy: 243287
// gas legacyOptimized: 240361 // gas legacyOptimized: 240361

View File

@ -23,7 +23,7 @@ contract C {
// ---- // ----
// l() -> 0 // l() -> 0
// g(uint256): 70 -> // g(uint256): 70 ->
// gas irOptimized: 428769 // gas irOptimized: 429679
// gas legacy: 419791 // gas legacy: 419791
// gas legacyOptimized: 415408 // gas legacyOptimized: 415408
// l() -> 70 // l() -> 70

View File

@ -26,6 +26,6 @@ contract Creator {
// compileViaYul: also // compileViaYul: also
// ---- // ----
// f(uint256,bytes): 7, 0x40, 78, "abcdefghijklmnopqrstuvwxyzabcdef", "ghijklmnopqrstuvwxyzabcdefghijkl", "mnopqrstuvwxyz" -> 7, "h" // f(uint256,bytes): 7, 0x40, 78, "abcdefghijklmnopqrstuvwxyzabcdef", "ghijklmnopqrstuvwxyzabcdefghijkl", "mnopqrstuvwxyz" -> 7, "h"
// gas irOptimized: 323391 // gas irOptimized: 322968
// gas legacy: 414850 // gas legacy: 414850
// gas legacyOptimized: 290278 // gas legacyOptimized: 290278