diff --git a/libsolidity/codegen/CompilerUtils.cpp b/libsolidity/codegen/CompilerUtils.cpp index 88ad76336..b32e744b1 100644 --- a/libsolidity/codegen/CompilerUtils.cpp +++ b/libsolidity/codegen/CompilerUtils.cpp @@ -70,6 +70,13 @@ void CompilerUtils::allocateMemory() storeFreeMemoryPointer(); } +void CompilerUtils::allocateMemory(u256 const& size) +{ + fetchFreeMemoryPointer(); + m_context << Instruction::DUP1 << size << Instruction::ADD; + storeFreeMemoryPointer(); +} + void CompilerUtils::toSizeAfterFreeMemoryPointer() { fetchFreeMemoryPointer(); @@ -813,9 +820,8 @@ void CompilerUtils::convertType( { auto const& arrayType = dynamic_cast(_targetType); solAssert(arrayType.isByteArray(), ""); - u256 storageSize(32 + ((data.size() + 31) / 32) * 32); - m_context << storageSize; - allocateMemory(); + unsigned storageSize = 32 + ((data.size() + 31) / 32) * 32; + allocateMemory(storageSize); // stack: mempos m_context << Instruction::DUP1 << u256(data.size()); storeInMemoryDynamic(IntegerType::uint256()); @@ -938,8 +944,7 @@ void CompilerUtils::convertType( { case DataLocation::Storage: // stack: - m_context << typeOnStack.memorySize(); - allocateMemory(); + allocateMemory(typeOnStack.memorySize()); m_context << Instruction::SWAP1 << Instruction::DUP2; // stack: for (auto const& member: typeOnStack.members(nullptr)) @@ -1103,8 +1108,7 @@ void CompilerUtils::pushZeroValue(Type const& _type) 1, [type](CompilerContext& _context) { CompilerUtils utils(_context); - _context << u256(max(32u, type->calldataEncodedSize())); - utils.allocateMemory(); + utils.allocateMemory(max(32u, type->calldataEncodedSize())); _context << Instruction::DUP1; if (auto structType = dynamic_cast(type.get())) diff --git a/libsolidity/codegen/CompilerUtils.h b/libsolidity/codegen/CompilerUtils.h index 90657626e..5e07e7bb4 100644 --- a/libsolidity/codegen/CompilerUtils.h +++ b/libsolidity/codegen/CompilerUtils.h @@ -49,6 +49,10 @@ public: /// Stack pre: /// Stack post: void allocateMemory(); + /// Allocates a number of bytes in memory as given on the stack. + /// Stack pre: + /// Stack post: + void allocateMemory(u256 const& size); /// Appends code that transforms memptr to (memptr - free_memptr) memptr /// Stack pre: /// Stack post: diff --git a/libsolidity/codegen/ExpressionCompiler.cpp b/libsolidity/codegen/ExpressionCompiler.cpp index c126e61dd..a72b31dfe 100644 --- a/libsolidity/codegen/ExpressionCompiler.cpp +++ b/libsolidity/codegen/ExpressionCompiler.cpp @@ -317,8 +317,7 @@ bool ExpressionCompiler::visit(TupleExpression const& _tuple) ArrayType const& arrayType = dynamic_cast(*_tuple.annotation().type); solAssert(!arrayType.isDynamicallySized(), "Cannot create dynamically sized inline array."); - m_context << max(u256(32u), arrayType.memorySize()); - utils().allocateMemory(); + utils().allocateMemory(max(u256(32u), arrayType.memorySize())); m_context << Instruction::DUP1; for (auto const& component: _tuple.components()) @@ -527,8 +526,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) TypeType const& type = dynamic_cast(*_functionCall.expression().annotation().type); auto const& structType = dynamic_cast(*type.actualType()); - m_context << max(u256(32u), structType.memorySize()); - utils().allocateMemory(); + utils().allocateMemory(max(u256(32u), structType.memorySize())); m_context << Instruction::DUP1; for (unsigned i = 0; i < arguments.size(); ++i) @@ -1396,8 +1394,7 @@ bool ExpressionCompiler::visit(MemberAccess const& _memberAccess) { TypePointer arg = dynamic_cast(*_memberAccess.expression().annotation().type).typeArgument(); ContractDefinition const& contract = dynamic_cast(*arg).contractDefinition(); - m_context << u256(contract.name().length() + 32); - utils().allocateMemory(); + utils().allocateMemory(contract.name().length() + 32); // store string length m_context << u256(contract.name().length()) << Instruction::DUP2 << Instruction::MSTORE; // adjust pointer diff --git a/test/cmdlineTests/gas_test_abiv2/output b/test/cmdlineTests/gas_test_abiv2/output index c404940ce..bc2d1f97b 100644 --- a/test/cmdlineTests/gas_test_abiv2/output +++ b/test/cmdlineTests/gas_test_abiv2/output @@ -2,7 +2,7 @@ ======= gas_test_abiv2/input.sol:C ======= Gas estimation: construction: - 1147 + 1103200 = 1104347 + 1147 + 1103000 = 1104147 external: a(): 530 b(uint256): 1124 diff --git a/test/cmdlineTests/gas_test_abiv2_optimize_yul/output b/test/cmdlineTests/gas_test_abiv2_optimize_yul/output index 824544721..c61965bea 100644 --- a/test/cmdlineTests/gas_test_abiv2_optimize_yul/output +++ b/test/cmdlineTests/gas_test_abiv2_optimize_yul/output @@ -2,7 +2,7 @@ ======= gas_test_abiv2_optimize_yul/input.sol:C ======= Gas estimation: construction: - 651 + 617600 = 618251 + 651 + 617400 = 618051 external: a(): 429 b(uint256): 887