[Sol->Yul] Remove index access from byte array pop function to optimize it.

This commit is contained in:
Djordje Mijovic 2021-04-20 18:06:06 +02:00
parent c3f639b355
commit 0dd59fa0a2
2 changed files with 28 additions and 5 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;