Skip to content

Commit b076e02

Browse files
committed
evmasm codegen: don't update free memory pointer for value type returns
1 parent 68d416c commit b076e02

File tree

44 files changed

+177
-111
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+177
-111
lines changed

libsolidity/codegen/ExpressionCompiler.cpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2942,11 +2942,10 @@ void ExpressionCompiler::appendExternalFunctionCall(
29422942
utils().fetchFreeMemoryPointer();
29432943
// Stack: return_data_start
29442944

2945-
// The old decoder did not allocate any memory (i.e. did not touch the free
2946-
// memory pointer), but kept references to the return data for
2947-
// (statically-sized) arrays
2945+
// Only update free memory pointer if any return type needs memory (reference types).
2946+
// Value types are decoded directly to the stack via mload.
29482947
bool needToUpdateFreeMemoryPtr = false;
2949-
if (dynamicReturnSize || m_context.useABICoderV2())
2948+
if (dynamicReturnSize)
29502949
needToUpdateFreeMemoryPtr = true;
29512950
else
29522951
for (auto const& retType: returnTypes)
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
pragma abicoder v1;
2+
3+
interface I {
4+
function getUint() external returns (uint256);
5+
}
6+
7+
contract Impl is I {
8+
function getUint() external pure returns (uint256) { return 42; }
9+
}
10+
11+
// With ABICoderV1, value types should NOT allocate memory.
12+
contract C {
13+
I immutable impl = I(address(new Impl()));
14+
15+
function freeMemory() internal pure returns (uint m) { assembly { m := mload(0x40) } }
16+
17+
function testValueType() public returns (uint memDiff) {
18+
uint memBefore = freeMemory();
19+
impl.getUint();
20+
memDiff = freeMemory() - memBefore;
21+
}
22+
23+
function testNoMemoryGrowthInLoop() public returns (uint memDiff) {
24+
uint memBefore = freeMemory();
25+
for (uint i = 0; i < 10; i++) {
26+
impl.getUint();
27+
}
28+
memDiff = freeMemory() - memBefore;
29+
}
30+
}
31+
// ====
32+
// compileViaYul: false
33+
// ----
34+
// testValueType() -> 0
35+
// testNoMemoryGrowthInLoop() -> 0

test/libsolidity/semanticTests/abiEncoderV1/struct/struct_storage_ptr.sol

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,5 +25,5 @@ contract C {
2525
// library: L
2626
// f() -> 8, 7, 1, 2, 7, 12
2727
// gas irOptimized: 166609
28-
// gas legacy: 170486
29-
// gas legacyOptimized: 167252
28+
// gas legacy: 170439
29+
// gas legacyOptimized: 167202
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
pragma abicoder v2;
2+
3+
interface I {
4+
function getUint() external returns (uint256);
5+
}
6+
7+
contract Impl is I {
8+
function getUint() external pure returns (uint256) { return 42; }
9+
}
10+
11+
// With ABICoderV2, value types should NOT allocate memory.
12+
// They are decoded directly to the stack via mload.
13+
contract C {
14+
I immutable impl = I(address(new Impl()));
15+
16+
function freeMemory() internal pure returns (uint m) { assembly { m := mload(0x40) } }
17+
18+
function testValueType() public returns (uint memDiff) {
19+
uint memBefore = freeMemory();
20+
impl.getUint();
21+
memDiff = freeMemory() - memBefore;
22+
}
23+
24+
function testNoMemoryGrowthInLoop() public returns (uint memDiff) {
25+
uint memBefore = freeMemory();
26+
for (uint i = 0; i < 10; i++) {
27+
impl.getUint();
28+
}
29+
memDiff = freeMemory() - memBefore;
30+
}
31+
}
32+
// ====
33+
// compileViaYul: false
34+
// ----
35+
// testValueType() -> 0
36+
// testNoMemoryGrowthInLoop() -> 0

test/libsolidity/semanticTests/arithmetics/check_var_init.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,5 +16,5 @@ contract D {
1616
// ----
1717
// f() -> FAILURE, hex"4e487b71", 0x11
1818
// g(), 100 wei -> 1
19-
// gas legacy: 76780
19+
// gas legacy: 76745
2020
// gas legacy code: 23600

test/libsolidity/semanticTests/array/function_array_cross_calls.sol

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ contract C {
4444
// test() -> 5, 6, 7
4545
// gas irOptimized: 85886
4646
// gas irOptimized code: 158000
47-
// gas legacy: 97551
48-
// gas legacy code: 342800
49-
// gas legacyOptimized: 87808
50-
// gas legacyOptimized code: 193000
47+
// gas legacy: 97317
48+
// gas legacy code: 333800
49+
// gas legacyOptimized: 87541
50+
// gas legacyOptimized code: 183400

test/libsolidity/semanticTests/array/reusing_memory.sol

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ contract Main {
2626
// f(uint256): 0x34 -> 0x46bddb1178e94d7f2892ff5f366840eb658911794f2c3a44c450aa2c505186c1
2727
// gas irOptimized: 99328
2828
// gas irOptimized code: 12400
29-
// gas legacy: 101551
29+
// gas legacy: 101478
3030
// gas legacy code: 23600
31-
// gas legacyOptimized: 99612
31+
// gas legacyOptimized: 99533
3232
// gas legacyOptimized code: 13400

test/libsolidity/semanticTests/constructor/arrays_in_constructors.sol

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ contract Creator {
2828
// f(uint256,address[]): 7, 0x40, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 -> 7, 8
2929
// gas irOptimized: 327542
3030
// gas irOptimized code: 94000
31-
// gas legacy: 338477
31+
// gas legacy: 338407
3232
// gas legacy code: 244800
33-
// gas legacyOptimized: 329166
33+
// gas legacyOptimized: 329090
3434
// gas legacyOptimized code: 117000

test/libsolidity/semanticTests/constructor/bytes_in_constructors_packer.sol

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ contract Creator {
2828
// f(uint256,bytes): 7, 0x40, 78, "abcdefghijklmnopqrstuvwxyzabcdef", "ghijklmnopqrstuvwxyzabcdefghijkl", "mnopqrstuvwxyz" -> 7, "h"
2929
// gas irOptimized: 169055
3030
// gas irOptimized code: 99600
31-
// gas legacy: 172946
31+
// gas legacy: 172876
3232
// gas legacy code: 239800
33-
// gas legacyOptimized: 169823
33+
// gas legacyOptimized: 169747
3434
// gas legacyOptimized code: 118600

test/libsolidity/semanticTests/constructor/constructor_function_complex.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,5 +19,5 @@ contract C {
1919
// bytecodeFormat: legacy,>=EOFv1
2020
// ----
2121
// f() -> 16
22-
// gas legacy: 78477
22+
// gas legacy: 78399
2323
// gas legacy code: 23600

0 commit comments

Comments
 (0)