Add allocateMemory helper with value known at compile time

This commit is contained in:
Alex Beregszaszi 2019-02-26 12:56:23 +00:00 committed by chriseth
parent 9c80f0fc76
commit a96cc6e0e8
5 changed files with 20 additions and 15 deletions

View File

@ -70,6 +70,13 @@ void CompilerUtils::allocateMemory()
storeFreeMemoryPointer(); storeFreeMemoryPointer();
} }
void CompilerUtils::allocateMemory(u256 const& size)
{
fetchFreeMemoryPointer();
m_context << Instruction::DUP1 << size << Instruction::ADD;
storeFreeMemoryPointer();
}
void CompilerUtils::toSizeAfterFreeMemoryPointer() void CompilerUtils::toSizeAfterFreeMemoryPointer()
{ {
fetchFreeMemoryPointer(); fetchFreeMemoryPointer();
@ -813,9 +820,8 @@ void CompilerUtils::convertType(
{ {
auto const& arrayType = dynamic_cast<ArrayType const&>(_targetType); auto const& arrayType = dynamic_cast<ArrayType const&>(_targetType);
solAssert(arrayType.isByteArray(), ""); solAssert(arrayType.isByteArray(), "");
u256 storageSize(32 + ((data.size() + 31) / 32) * 32); unsigned storageSize = 32 + ((data.size() + 31) / 32) * 32;
m_context << storageSize; allocateMemory(storageSize);
allocateMemory();
// stack: mempos // stack: mempos
m_context << Instruction::DUP1 << u256(data.size()); m_context << Instruction::DUP1 << u256(data.size());
storeInMemoryDynamic(IntegerType::uint256()); storeInMemoryDynamic(IntegerType::uint256());
@ -938,8 +944,7 @@ void CompilerUtils::convertType(
{ {
case DataLocation::Storage: case DataLocation::Storage:
// stack: <source ref> // stack: <source ref>
m_context << typeOnStack.memorySize(); allocateMemory(typeOnStack.memorySize());
allocateMemory();
m_context << Instruction::SWAP1 << Instruction::DUP2; m_context << Instruction::SWAP1 << Instruction::DUP2;
// stack: <memory ptr> <source ref> <memory ptr> // stack: <memory ptr> <source ref> <memory ptr>
for (auto const& member: typeOnStack.members(nullptr)) for (auto const& member: typeOnStack.members(nullptr))
@ -1103,8 +1108,7 @@ void CompilerUtils::pushZeroValue(Type const& _type)
1, 1,
[type](CompilerContext& _context) { [type](CompilerContext& _context) {
CompilerUtils utils(_context); CompilerUtils utils(_context);
_context << u256(max(32u, type->calldataEncodedSize())); utils.allocateMemory(max(32u, type->calldataEncodedSize()));
utils.allocateMemory();
_context << Instruction::DUP1; _context << Instruction::DUP1;
if (auto structType = dynamic_cast<StructType const*>(type.get())) if (auto structType = dynamic_cast<StructType const*>(type.get()))

View File

@ -49,6 +49,10 @@ public:
/// Stack pre: <size> /// Stack pre: <size>
/// Stack post: <mem_start> /// Stack post: <mem_start>
void allocateMemory(); void allocateMemory();
/// Allocates a number of bytes in memory as given on the stack.
/// Stack pre:
/// Stack post: <mem_start>
void allocateMemory(u256 const& size);
/// Appends code that transforms memptr to (memptr - free_memptr) memptr /// Appends code that transforms memptr to (memptr - free_memptr) memptr
/// Stack pre: <mem_end> /// Stack pre: <mem_end>
/// Stack post: <size> <mem_start> /// Stack post: <size> <mem_start>

View File

@ -317,8 +317,7 @@ bool ExpressionCompiler::visit(TupleExpression const& _tuple)
ArrayType const& arrayType = dynamic_cast<ArrayType const&>(*_tuple.annotation().type); ArrayType const& arrayType = dynamic_cast<ArrayType const&>(*_tuple.annotation().type);
solAssert(!arrayType.isDynamicallySized(), "Cannot create dynamically sized inline array."); solAssert(!arrayType.isDynamicallySized(), "Cannot create dynamically sized inline array.");
m_context << max(u256(32u), arrayType.memorySize()); utils().allocateMemory(max(u256(32u), arrayType.memorySize()));
utils().allocateMemory();
m_context << Instruction::DUP1; m_context << Instruction::DUP1;
for (auto const& component: _tuple.components()) for (auto const& component: _tuple.components())
@ -527,8 +526,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
TypeType const& type = dynamic_cast<TypeType const&>(*_functionCall.expression().annotation().type); TypeType const& type = dynamic_cast<TypeType const&>(*_functionCall.expression().annotation().type);
auto const& structType = dynamic_cast<StructType const&>(*type.actualType()); auto const& structType = dynamic_cast<StructType const&>(*type.actualType());
m_context << max(u256(32u), structType.memorySize()); utils().allocateMemory(max(u256(32u), structType.memorySize()));
utils().allocateMemory();
m_context << Instruction::DUP1; m_context << Instruction::DUP1;
for (unsigned i = 0; i < arguments.size(); ++i) for (unsigned i = 0; i < arguments.size(); ++i)
@ -1396,8 +1394,7 @@ bool ExpressionCompiler::visit(MemberAccess const& _memberAccess)
{ {
TypePointer arg = dynamic_cast<MagicType const&>(*_memberAccess.expression().annotation().type).typeArgument(); TypePointer arg = dynamic_cast<MagicType const&>(*_memberAccess.expression().annotation().type).typeArgument();
ContractDefinition const& contract = dynamic_cast<ContractType const&>(*arg).contractDefinition(); ContractDefinition const& contract = dynamic_cast<ContractType const&>(*arg).contractDefinition();
m_context << u256(contract.name().length() + 32); utils().allocateMemory(contract.name().length() + 32);
utils().allocateMemory();
// store string length // store string length
m_context << u256(contract.name().length()) << Instruction::DUP2 << Instruction::MSTORE; m_context << u256(contract.name().length()) << Instruction::DUP2 << Instruction::MSTORE;
// adjust pointer // adjust pointer

View File

@ -2,7 +2,7 @@
======= gas_test_abiv2/input.sol:C ======= ======= gas_test_abiv2/input.sol:C =======
Gas estimation: Gas estimation:
construction: construction:
1147 + 1103200 = 1104347 1147 + 1103000 = 1104147
external: external:
a(): 530 a(): 530
b(uint256): 1124 b(uint256): 1124

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 + 617600 = 618251 651 + 617400 = 618051
external: external:
a(): 429 a(): 429
b(uint256): 887 b(uint256): 887