mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #11268 from ethereum/refactorByteArrayPopSol2Yul
[Sol->Yul] Refactor ByteArrayPop to use unchecked index access
This commit is contained in:
commit
c3d73982ea
@ -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())
|
||||||
|
@ -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;
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user