-
Notifications
You must be signed in to change notification settings - Fork 719
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add PUSH and POP instructions. #407
Comments
The gas cost should definitely be better than chaining How would the VM know the memory location of the registers to |
It shouldn"t, it"s up to the compiler or dev to do it. So And conceivably they could be used to batch move a bunch of values between registers -- |
I guess the implications of |
Yeah, similar if we allow popping into reserved registers, although it sounds dangerous, as I kinda mentioned above your comment. I think maybe a special instruction which just creates a new stack at the end of the current one would be safer for #346, and these |
I have some suggestions on possible improvements. Some of these are mutually exclusive, and are mostly included to show what alternatives should be considered. Since any register is readable, I don"t think is makes much sense to disallow However, there is one interesting optimization opportunity that I would like to consider. Instead of Also introducing a heap push (but not pop) operation might be a good to have, although at least the heap has a nice property that after One more idea would be to streamline in-context subroutine calls using "push $pc and jump to $reg` and "pop into $pc" -style instructions. This is definitely a separate feature, but I feel like there are not many reasons not to do this in case we add PUSH and POP. Going even further, we could consider completely removing the idea of user writable data in the stack, and use it only for loaded code and call frames. Then, what"s currently called the heap, would be the stack, and heap as a concept would simply consist of the Sway compiler emulating heap using the stack. This makes operations involving dynamicly-sized runtime allocation somewhat harder/constly, but I don"t feel think code is common in smart contracts anyways. |
I don"t think this is a reasonable assumption to make. To my knowledge, people commonly use dynamically sized types in Solidity. And devs are already complaining about our lackluster support for them as it is. |
Use case
When creating a local function call frame (as opposed to a more global contract call frame) the compiler must preserve the value of usually several general purpose registers to avoid clobbering values in the caller.
It is currently (not merged yet, but soon) doing this manually by copying
$SP
, usingCFEI
and performing severalSTORE
s, potentially up to ~40 in the worst case at the start of a function, and reversing the process with up to ~40LOAD
s at the end.Even fairly small functions may use around 8 GP regs which would equate to 20 instructions to save and restore them, or 80 bytes of binary executable. Per function.
Proposal
I propose we introduce
PUSH
andPOP
to do all this with single instructions, saving a lot of wasted bytecode. 80 bytes becomes 8 bytes. A difference this significant could determine whether a function is inlined or not and so has further implications for optimisation.The arguments could be a range of registers, first to last inclusive.
PUSH $r0 $r3
would save all 4 of$r0
,$r1
,$r2
and$r3
to the stack.POP $r0 $r3
would restore them correctly.I assume it"s possible for the gas cost to just remain the equivalent of a
CFEI
followed by nSTORE
instructions.The text was updated successfully, but these errors were encountered: