Merge pull request #10577 from ethereum/deleteMappingSol2Yul

[Sol->Yul] Skipping mapping types when deleting structs and arrays.
This commit is contained in:
Đorđe Mijović 2020-12-21 20:08:51 +01:00 committed by GitHub
commit b78443ac75
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 56 additions and 39 deletions

View File

@ -1108,7 +1108,7 @@ std::string YulUtilFunctions::resizeArrayFunction(ArrayType const& _type)
string functionName = "resize_array_" + _type.identifier(); string functionName = "resize_array_" + _type.identifier();
return m_functionCollector.createFunction(functionName, [&]() { return m_functionCollector.createFunction(functionName, [&]() {
return Whiskers(R"( Whiskers templ(R"(
function <functionName>(array, newLen) { function <functionName>(array, newLen) {
if gt(newLen, <maxArrayLength>) { if gt(newLen, <maxArrayLength>) {
<panic>() <panic>()
@ -1121,6 +1121,7 @@ std::string YulUtilFunctions::resizeArrayFunction(ArrayType const& _type)
sstore(array, newLen) sstore(array, newLen)
</isDynamic> </isDynamic>
<?needsClearing>
// Size was reduced, clear end of array // Size was reduced, clear end of array
if lt(newLen, oldLen) { if lt(newLen, oldLen) {
let oldSlotCount := <convertToSize>(oldLen) let oldSlotCount := <convertToSize>(oldLen)
@ -1136,20 +1137,26 @@ std::string YulUtilFunctions::resizeArrayFunction(ArrayType const& _type)
</packed> </packed>
<clearStorageRange>(deleteStart, deleteEnd) <clearStorageRange>(deleteStart, deleteEnd)
} }
})") </needsClearing>
("functionName", functionName) })");
("panic", panicFunction(PanicCode::ResourceError)) templ("functionName", functionName);
("fetchLength", arrayLengthFunction(_type)) templ("maxArrayLength", (u256(1) << 64).str());
("isDynamic", _type.isDynamicallySized()) templ("panic", panicFunction(util::PanicCode::ResourceError));
("convertToSize", arrayConvertLengthToSize(_type)) templ("fetchLength", arrayLengthFunction(_type));
("dataPosition", arrayDataAreaFunction(_type)) templ("isDynamic", _type.isDynamicallySized());
("clearStorageRange", clearStorageRangeFunction(*_type.baseType())) bool isMappingBase = _type.baseType()->category() == Type::Category::Mapping;
("maxArrayLength", (u256(1) << 64).str()) templ("needsClearing", !isMappingBase);
("packed", _type.baseType()->storageBytes() <= 16) if (!isMappingBase)
("itemsPerSlot", to_string(32 / _type.baseType()->storageBytes())) {
("storageBytes", to_string(_type.baseType()->storageBytes())) templ("convertToSize", arrayConvertLengthToSize(_type));
("partialClearStorageSlot", partialClearStorageSlotFunction()) templ("dataPosition", arrayDataAreaFunction(_type));
.render(); templ("clearStorageRange", clearStorageRangeFunction(*_type.baseType()));
templ("packed", _type.baseType()->storageBytes() <= 16);
templ("itemsPerSlot", to_string(32 / _type.baseType()->storageBytes()));
templ("storageBytes", to_string(_type.baseType()->storageBytes()));
templ("partialClearStorageSlot", partialClearStorageSlotFunction());
}
return templ.render();
}); });
} }
@ -1313,14 +1320,17 @@ string YulUtilFunctions::storageArrayPopFunction(ArrayType const& _type)
if iszero(oldLen) { <panic>() } if iszero(oldLen) { <panic>() }
let newLen := sub(oldLen, 1) let newLen := sub(oldLen, 1)
let slot, offset := <indexAccess>(array, newLen) let slot, offset := <indexAccess>(array, newLen)
<setToZero>(slot, offset) <?+setToZero><setToZero>(slot, offset)</+setToZero>
sstore(array, newLen) sstore(array, newLen)
})") })")
("functionName", functionName) ("functionName", functionName)
("panic", panicFunction(PanicCode::EmptyArrayPop)) ("panic", panicFunction(PanicCode::EmptyArrayPop))
("fetchLength", arrayLengthFunction(_type)) ("fetchLength", arrayLengthFunction(_type))
("indexAccess", storageArrayIndexAccessFunction(_type)) ("indexAccess", storageArrayIndexAccessFunction(_type))
("setToZero", storageSetToZeroFunction(*_type.baseType())) (
"setToZero",
_type.baseType()->category() != Type::Category::Mapping ? storageSetToZeroFunction(*_type.baseType()) : ""
)
.render(); .render();
}); });
} }
@ -1527,7 +1537,7 @@ string YulUtilFunctions::clearStorageArrayFunction(ArrayType const& _type)
<?dynamic> <?dynamic>
<resizeArray>(slot, 0) <resizeArray>(slot, 0)
<!dynamic> <!dynamic>
<clearRange>(slot, add(slot, <lenToSize>(<len>))) <?+clearRange><clearRange>(slot, add(slot, <lenToSize>(<len>)))</+clearRange>
</dynamic> </dynamic>
} }
)") )")
@ -1536,11 +1546,9 @@ string YulUtilFunctions::clearStorageArrayFunction(ArrayType const& _type)
("resizeArray", _type.isDynamicallySized() ? resizeArrayFunction(_type) : "") ("resizeArray", _type.isDynamicallySized() ? resizeArrayFunction(_type) : "")
( (
"clearRange", "clearRange",
clearStorageRangeFunction( _type.baseType()->category() != Type::Category::Mapping ?
(_type.baseType()->storageBytes() < 32) ? clearStorageRangeFunction((_type.baseType()->storageBytes() < 32) ? *TypeProvider::uint256() : *_type.baseType()) :
*TypeProvider::uint256() : ""
*_type.baseType()
)
) )
("lenToSize", arrayConvertLengthToSize(_type)) ("lenToSize", arrayConvertLengthToSize(_type))
("len", _type.length().str()) ("len", _type.length().str())
@ -1560,6 +1568,9 @@ string YulUtilFunctions::clearStorageStructFunction(StructType const& _type)
set<u256> slotsCleared; set<u256> slotsCleared;
for (auto const& member: structMembers) for (auto const& member: structMembers)
{
if (member.type->category() == Type::Category::Mapping)
continue;
if (member.type->storageBytes() < 32) if (member.type->storageBytes() < 32)
{ {
auto const& slotDiff = _type.storageOffsetsOfMember(member.name).first; auto const& slotDiff = _type.storageOffsetsOfMember(member.name).first;
@ -1583,6 +1594,7 @@ string YulUtilFunctions::clearStorageStructFunction(StructType const& _type)
.render() .render()
); );
} }
}
return Whiskers(R"( return Whiskers(R"(
function <functionName>(slot) { function <functionName>(slot) {
@ -1592,7 +1604,6 @@ string YulUtilFunctions::clearStorageStructFunction(StructType const& _type)
} }
)") )")
("functionName", functionName) ("functionName", functionName)
("allocStruct", allocateMemoryStructFunction(_type))
("storageSize", _type.storageSize().str()) ("storageSize", _type.storageSize().str())
("member", memberSetValues) ("member", memberSetValues)
.render(); .render();

View File

@ -28,6 +28,8 @@ contract C {
return a.length; return a.length;
} }
} }
// ====
// compileViaYul: also
// ---- // ----
// n1(uint256,uint256): 42, 64 -> // n1(uint256,uint256): 42, 64 ->
// map(uint256): 42 -> 64 // map(uint256): 42 -> 64

View File

@ -23,6 +23,8 @@ contract C {
return a.length; return a.length;
} }
} }
// ====
// compileViaYul: also
// ---- // ----
// n1(uint256,uint256): 42, 64 -> // n1(uint256,uint256): 42, 64 ->
// map(uint256): 42 -> 64 // map(uint256): 42 -> 64

View File

@ -38,6 +38,8 @@ contract test {
return str.nstr.nestedMapping[index]; return str.nstr.nestedMapping[index];
} }
} }
// ====
// compileViaYul: also
// ---- // ----
// getToDelete() -> 0 // getToDelete() -> 0
// getTopValue() -> 0 // getTopValue() -> 0