mirror of
https://github.com/status-im/EIPs.git
synced 2025-02-22 11:48:19 +00:00
Update eip-2315.md (#3854)
This commit is contained in:
parent
6fb83045dc
commit
26d3e383e7
@ -11,9 +11,9 @@ created: 2019-10-17
|
||||
|
||||
## Abstract
|
||||
|
||||
This proposal introduces three opcodes to better support subroutines: `BEGINSUB`, `JUMPSUB` and `RETURNSUB`.
|
||||
This proposal introduces five opcodes to better support simple subroutines and relative jumps: `BEGINSUB`, `JUMPSUB` `RETURNSUB`, `JUMPR` and `JUMPRI`.
|
||||
|
||||
This change supports substantial reductions in the gas costs of calling simple subroutines – from %33 to as much as 54%.
|
||||
This change supports substantial reductions in the gas costs of calling and optimizing simple subroutines – from %33 to as much as 54%.
|
||||
|
||||
## Motivation
|
||||
|
||||
@ -31,7 +31,7 @@ The concept goes back to [Turing, 1946](http://www.alanturing.net/turing_archive
|
||||
> ...
|
||||
> When we wish to start on a subsidiary operation we need only make a note of where we left off the major operation and then apply the first instruction of the subsidiary. When the subsidiary is over we look up the note and continue with the major operation. Each subsidiary operation can end with instructions for this recovery of the note. How is the burying and disinterring of the note to be done? There are of course many ways. One is to keep a list of these notes in one or more standard size delay lines, (1024) with the most recent last. The position of the most recent of these will be kept in a fixed TS, and this reference will be modified every time a subsidiary is started or finished...
|
||||
|
||||
We propose to follow Turing's simple mechanism concept in our subroutine design, as specified below. Note that this specification is entirely semantic. It constrains only stack usage and control flow and imposes no syntax on code beyond being a sequence of bytes to be executed.
|
||||
We propose to follow Turing's simple concept in our subroutine design, as specified below. Note that this specification is entirely semantic. It constrains only stack usage and control flow and imposes no syntax on code beyond being a sequence of bytes to be executed.
|
||||
|
||||
## Specification
|
||||
|
||||
@ -69,9 +69,9 @@ We introduce one more stack into the EVM in addition to the existing `data stack
|
||||
>
|
||||
> * _pops one item off the `return stack`_
|
||||
|
||||
To take full advantage of the performance and benefits of subroutines we also provide two new static, relative jump functions that take their arguments as immediate data rather off the stack.
|
||||
To take full advantage of the performance benefits of simple subroutines we also provide two new static, relative jump functions that take their arguments as immediate data rather then off the stack.
|
||||
|
||||
#### `JUMPR (0x5d) offset`
|
||||
#### `JUMPR (0x??) offset`
|
||||
|
||||
> Transfers control to the address `PC + offset`, where offset is a three-byte, MSB first, twos-complement integer.
|
||||
>
|
||||
@ -81,7 +81,7 @@ To take full advantage of the performance and benefits of subroutines we also pr
|
||||
>
|
||||
> The cost is _low_.
|
||||
|
||||
#### `JUMPRI (0x5d) offset`
|
||||
#### `JUMPRI (0x??) offset`
|
||||
|
||||
> Conditionally transfers control to the address `PC + offset`, where offset is a three-byte, MSB first, twos-complement integer.
|
||||
> 1. Decode the `offset` from the immediate data. The data is encoded as three bytes, MSB first, twos-complement.
|
||||
@ -116,7 +116,7 @@ These opcodes reduce the gas costs of both ordinary subroutine calls and low-lev
|
||||
|
||||
**_Note**: the **JUMP** versions of the examples below are all **valid code**._
|
||||
|
||||
#### Simple Subroutine Call
|
||||
#### **Simple Subroutine Call**
|
||||
|
||||
Consider this example of calling a minimal subroutine
|
||||
using `JUMPSUB`
|
||||
@ -142,7 +142,7 @@ TEST_ADD:
|
||||
RTN_ADD ; 3 gas
|
||||
0x02 ; 3 gas
|
||||
0x03 ; 3 gas
|
||||
ADDITION ; 3 gas
|
||||
ADDITION ; 3 gas
|
||||
jump ; 8 gas
|
||||
RTN_ADD:
|
||||
jumpdest ; 1 gas
|
||||
@ -161,7 +161,7 @@ Using `JUMPSUB` saves **_48 - 22 = 26_** gas versus using `JUMP` – a 54% perfo
|
||||
|
||||
The advantages of JUMPR can be seen in, e.g., the tail simple subroutine call.
|
||||
|
||||
#### Tail Call Optimization
|
||||
#### **Tail Call Optimization**
|
||||
|
||||
Of course in cases like this one we can optimize the tail call, so that the final `RETURNSUB` in `ADDITION` actually returns from TEST_ADD.
|
||||
```
|
||||
@ -197,7 +197,7 @@ Total: 33 gas
|
||||
```
|
||||
Using `JUMPSUB` saves **_33 - 20 = 13_** gas versus using `JUMP` – a 39% performance improvement.
|
||||
|
||||
#### Tail Call Elimination
|
||||
#### **Tail Call Elimination**
|
||||
|
||||
We can even take advantage of `ADDITION` just happening to directly follow `TEST_ADD` and just fall through rather than jump at all.
|
||||
```
|
||||
@ -230,7 +230,7 @@ Using `JUMPSUB` saves **_22 - 14 = 8_** gas versus using `JUMP` – a 36% perfor
|
||||
|
||||
Finally, we can take a look at using `JUMPR` instead of `JUMP`
|
||||
|
||||
#### Tail Calls with JUMPR
|
||||
#### **Tail Calls with JUMPR**
|
||||
```
|
||||
TEST_ADD:
|
||||
jumpdest ; 1 gas
|
||||
|
Loading…
x
Reference in New Issue
Block a user