last day (18 days later) » 

11:54
1
Q: why does it copy into memory?

Nika KurashviliLet's say I have the following.. contract D { function again(uint256[3] memory bla) external returns(uint) { return bla[0]; } } contract A { function test(D f, uint256[3] memory haha) external returns (uint) { return f.again(haha); } } We ...

You can replace uint[3] memory bla and uint[3] memory haha to uint[3] calldata .... The compiler copies it since you wrote that the array is in memory.
Thanks, but that doesn't answer my question. When I called test function, it copied array from calldata to memory. now, before calling f.again(haha) , it copies the array again, even though array was already in memory. Why is the second copy needed ? after this, when it calls again, it will copy the array into memory again but for contract D. The question is, why does it copy before calling f.again
Because it's an external call. Actually my older comment was incorrect. There would be a copy even when both the arguments are in calldata. Because the call opcode needs its input in memory. So I think using memory or calldata in your test function probably doesn't make any difference, gas wise. However, changing to calldata in again should be cheaper.
I think it still should make sense to use calldata in test, because if you use memory, you would have 2 copies , before calling again, but if you use calldata, you would have only 1 copy
If you use memory then there would be the copies: calldata -> memory -> call-opcode. The same remains even when you use calldata.
11:54
if we use calldata, we can have calldata -> call-opcode. Can't we ?
No. If you look here, call opcode needs its input from memory. So calldata -> memory is a must.
I still don't get something. I get that call opcode needs data to be in memory, but if test function's parameter was memory, it means it was copied into memory already. So call can use that data already for again function, but it still uses copy again before calling again.
I think, I was right. You said the following - using memory or calldata in your test function probably doesn't make any difference, gas wise.. But it actually makes a difference by 330 gas. I can't test how many times the copying happens if I specify calldata in test function, since there's a bug in remix so I can't follow opcode sequences and all that, but gas difference makes me believe that copying would happen only one time if calldata is used in test.
Is that difference with the optimizer enabled?
yes, but if you disable optimizer, the difference becomes 353. So, I think what I said is correct. There's no other explanation. Would be good to be able to test this in remix, but somehow they have a bug.
Interesting. I was taking a quick look at the intermediate representation.
There seems to be an extra copy.
11:55
yes
So, there're 2 things i don't understand
1) if you specify memory in the caller, and memory in the callee contract, before the callee contract's function gets called, 2 copies happen. The thing is I don't know why the second copy is needed, since the data is already in memory :D
Yeah. Not sure about this. I've to look more into the reasons.
one reason could be that before the call, it also allocates the space where the returned data should be stored.
maybe, because it doesn't want some kind of overflowing to happen, it's just an extra step for more safety
not sure though...

  last day (18 days later) »