mirror of
https://github.com/status-im/EIPs.git
synced 2025-02-22 11:48:19 +00:00
Update eip-2315.md (#3792)
This commit is contained in:
parent
4a79c79abf
commit
2e045b7c5b
@ -13,7 +13,7 @@ created: 2019-10-17
|
||||
|
||||
This proposal introduces three opcodes to better support subroutines: `BEGINSUB`, `JUMPSUB` and `RETURNSUB`.
|
||||
|
||||
This change supports substantial reductions in the gas costs of using subroutines.
|
||||
This change supports substantial reductions – as much as 54% - in the gas costs of using subroutines.
|
||||
|
||||
## Motivation
|
||||
|
||||
@ -75,23 +75,23 @@ _Notes:_
|
||||
|
||||
### Dependencies
|
||||
|
||||
We need [EIP-3540: EVM Object Format (EOF)](./eip-3540.md) to allow for immediate arguments without special encoding and to deprecate dynamic use of JUMP and JUMPI.
|
||||
We need [EIP-3540: EVM Object Format (EOF)](./eip-3540.md) to allow for immediate arguments without special encoding.
|
||||
|
||||
## Rationale
|
||||
|
||||
We modeled this design on Moore's 1970 [Forth virtual machine](http://www.ultratechnology.com/4th_1970.pdf). It is a two-stack design the data stack is supplemented with a return stack to support jumping into and returning from subroutines, as specified above. The return address (Turing's "note") is pushed onto the return stack (Turing's "delay line") when calling, and the stack is popped into the `PC` when returning.
|
||||
We modeled this design on Moore's 1970 [Forth virtual machine](http://www.ultratechnology.com/4th_1970.pdf). It is a two-stack design – the data stack is supplemented with a return stack to support jumping into and returning from subroutines, as specified above. The return address (Turing's "note") is pushed onto the return stack (Turing's "delay line") when calling, and the stack is popped into the `PC` when returning.
|
||||
|
||||
The alternative design is to push the return address and the destination address on the data stack before jumping, and to pop the data stack and jump back to the popped `PC` to return. We prefer the separate return stack because it ensures that the return address cannot be overwritten or mislaid, uses fewer data stack slots, and obviates any need to swap the return address past the arguments or return values on the stack. Crucially, a dynamic jump is not needed to implement subroutine returns, allowing for deprecation of `JUMP` and `JUMPI`.
|
||||
|
||||
The _low_ cost of `JUMPSUB` is justified by needing only about six Go operations to push the return address on the return stack, and decode the immediate two byte destination to the `PC`. The _verylow_ cost of `RETURNSUB` is justified by needing only about three Go operations to pop the return stack into the `PC`. No 256-bit arithmetic or checking for valid destinations is needed. Also, `JUMP` is assigned _mid_, and `JUMPSUB` should be more efficient, as decoding immediate bytes should be cheaper than than converting 32-byte stack items, and the destination address will not need to be checked for either `JUMPSUB` or `RETURNSUB`. Benchmarking will be needed to tell if the costs are well-balanced.
|
||||
|
||||
### Gas Costs in Practice
|
||||
### Gas Cost Examples
|
||||
|
||||
These opcodes reduce the gas costs of both ordinary subroutine calls and low-level optimizations. The savings reported here will of course be less relevant to programs that use a few large subroutines rather than being a factored than in to smaller ones. The choice of gas costs for the new opcodes above does not make a large difference in this analysis, as much of the improvement is due to PUSH and SWAP operations that are no longer needed.
|
||||
These opcodes reduce the gas costs of both ordinary subroutine calls and low-level optimizations. The savings reported here will of course be less relevant to programs that use a few large subroutines rather than being a factored than in to smaller ones. The choice of gas costs for the new opcodes above does not make a large difference in this analysis, as much of the improvement is due to PUSH and SWAP operations that are no longer needed. Even if `JUMPSUB` cost the same as `JUMP` – 8 gas rather than 5 - a simple subroutine call would still be 52% less costly versus 54%.
|
||||
|
||||
**_Note**: the **JUMP** versions of the examples below are all **valid code**._
|
||||
|
||||
#### Subroutine Call
|
||||
#### Simple Subroutine Call
|
||||
|
||||
Consider this example of calling a minimal subroutine
|
||||
using `JUMPSUB`
|
||||
@ -132,7 +132,7 @@ ADDITION:
|
||||
|
||||
Total: 48 gas
|
||||
```
|
||||
Using `JUMP` uses **_48 - 22 = 26_** more gas than using `JUMPSUB`.
|
||||
Using `JUMPSUB` saves **_48 - 22 = 26_** gas versus using `JUMP` – a 54% performance improvement.
|
||||
|
||||
#### Tail Call Optimization
|
||||
|
||||
@ -168,7 +168,7 @@ ADDITION:
|
||||
|
||||
Total: 33 gas
|
||||
```
|
||||
Using `JUMP` cost **_33 - 20 = 13_** more gas than using `JUMPSUB`.
|
||||
Using `JUMPSUB` saves **_33 - 20 = 13_** gas versus using `JUMP` – a 39% performance improvement.
|
||||
|
||||
#### Tail Call Elimination
|
||||
|
||||
@ -199,7 +199,7 @@ ADDITION:
|
||||
|
||||
Total: 24 gas
|
||||
```
|
||||
Using `JUMP` costs **_22 - 14 = 8_** more gas than using `JUMPSUB`.
|
||||
Using `JUMPSUB` saves **_22 - 14 = 8_** gas versus using `JUMP` – a 36% performance improvement.
|
||||
|
||||
## Backwards and Forwards Compatibility
|
||||
|
||||
@ -213,6 +213,8 @@ These changes are compatible with using [EIP-3337](https://eips.ethereum.org/EIP
|
||||
|
||||
These changes do introduce new flow control instructions, so any software which does static/dynamic analysis of EVM code needs to be modified accordingly. The `JUMPSUB` semantics are similar to `JUMP` (but jumping to a `BEGINSUB`), whereas the `RETURNSUB` instruction is different, since it can 'land' on any opcode (but the possible destinations can be statically inferred).
|
||||
|
||||
If [`EIP-`3779](./eip-3779.md) – Safe Control Flow for the EVM – advances then the requirement on `JUMPSUB` to `abort` if the opcode at `location` is not a `BEGINSUB` will need to be enforced at creation time rather than runtime.
|
||||
|
||||
## Test Cases
|
||||
|
||||
### Simple routine
|
||||
|
Loading…
x
Reference in New Issue
Block a user