@@ -11,13 +11,14 @@ Let's start by defining some basic and universal instructions' parameters.
11
11
1 . Base gas cost.
12
12
13
13
This is the static gas cost of instructions. Some instructions may have
14
- additional cost depending on their operand values - these have to be
15
- handled individually during the instruction execution.
14
+ _ additional_ cost depending on their operand values and/or the environment
15
+ — these have to be handled individually during the instruction execution.
16
+ The _ final_ cost is never less than the _ base_ cost.
16
17
17
18
2 . Stack height requirement.
18
19
19
20
This is the minimum stack height (number of items on the stack)
20
- required for the instruction execution.
21
+ required prior to the instruction execution.
21
22
22
23
3 . Stack height change.
23
24
@@ -36,45 +37,49 @@ Examples:
36
37
| CALL | 700 | 7 | -6 |
37
38
38
39
39
- ## Basic blocks
40
+ ## Basic instruction blocks
40
41
41
- A _ basic block_ is a sequence of instructions that are executed "straight-line"
42
- without being interrupted by jumps. I.e. they are nodes in the _ control flow graph_ .
42
+ A _ basic instruction block_ is a sequence of "straight-line" instructions
43
+ without jumps and jumpdests in the middle.
44
+ Jumpdests are only allowed at the entry, jumps at the exit.
45
+ Basic blocks are nodes in the _ control flow graph_ .
46
+ See [ Basic Block] in Wikipedia.
43
47
44
- The name "basic block" has been taken from LLVM. Other names are: just "block"
45
- in wasm or "subroutine" in subroutine-threaded interpreters.
48
+ In EVM there are simple rules to identify basic instruction block boundaries:
46
49
47
- In EVM there are simple rules to identify basic block boundaries:
50
+ 1 . A basic instruction block _ starts_ right before:
51
+ - the first instruction in the code,
52
+ - ` JUMPDEST ` instruction.
48
53
49
- 1 . The following instructions _ end _ a basic block :
54
+ 2 . A basic instruction block _ ends _ after the "terminator" instructions :
50
55
- ` JUMP ` ,
51
56
- ` JUMPI ` ,
52
57
- ` STOP ` ,
53
58
- ` RETURN ` ,
54
59
- ` REVERT ` ,
55
- - ` SELFDESTRUCT ` ,
56
- - an instruction directly preceding ` JUMPDEST ` .
60
+ - ` SELFDESTRUCT ` .
57
61
58
- 2 . The following instructions _ start_ a basic block:
59
- - ` JUMPDEST ` ,
60
- - the first instruction in the code,
61
- - an instruction directly after an instruction that has ended previous basic block.
62
+ A basic instruction block is a shortest sequence of instructions such that
63
+ a basic block starts before the first instruction and ends after the last.
62
64
65
+ In some cases multiple of the above rules can apply to single basic instruction
66
+ block boundary.
63
67
64
68
## Algorithm
65
69
66
- The algorithm for calculating gas and checking stack requirements precomputes
67
- the values for basic blocks and during execution the checks are done once per block.
70
+ The algorithm for calculating gas and checking stack requirements pre-computes
71
+ the values for basic instruction blocks and during execution the checks
72
+ are done only once per instruction block.
68
73
69
74
### Collecting requirements for basic blocks
70
75
71
- For a basic block we need to collect following information:
76
+ For a basic block we need to collect the following information:
72
77
73
- - total base gas required by instructions,
74
- - the stack height required (the minimum stack height needed to execute
75
- all instructions in the block),
76
- - ~~ the start-to-end stack height change ~~ ,
77
- - the relative maximum stack height .
78
+ - total ** base gas cost ** of all instructions,
79
+ - the ** stack height required** (the minimum stack height needed to execute all
80
+ instructions in the block),
81
+ - the ** maximum stack height growth ** relative to the stack height at block
82
+ start .
78
83
79
84
This is done as follows:
80
85
@@ -83,26 +88,26 @@ This is done as follows:
83
88
84
89
``` python
85
90
class Instruction :
86
- gas_required = 0
91
+ base_gas_cost = 0
87
92
stack_required = 0
88
93
stack_change = 0
89
94
90
95
class BasicBlock :
91
- gas_required = 0
96
+ base_gas_cost = 0
92
97
stack_required = 0
93
- stack_change = 0 # FIXME : We don't have too keep it.
94
- stack_max = 0
98
+ stack_max_growth = 0
95
99
96
100
def collect_basic_block_requirements (basic_block ):
101
+ stack_change = 0
97
102
for instruction in basic_block:
98
- basic_block.gas_required += instruction.gas_required
103
+ basic_block.base_gas_cost += instruction.base_gas_cost
99
104
100
- current_stack_required = instruction.stack_required - basic_block. stack_change
105
+ current_stack_required = instruction.stack_required - stack_change
101
106
basic_block.stack_required = max (basic_block.stack_required, current_stack_required)
102
107
103
- basic_block. stack_change += instruction.stack_change
108
+ stack_change += instruction.stack_change
104
109
105
- basic_block.stack_max = max (basic_block.stack_max, basic_block. stack_change)
110
+ basic_block.stack_max_growth = max (basic_block.stack_max_growth, stack_change)
106
111
```
107
112
108
113
### Checking basic block requirements
@@ -116,22 +121,22 @@ class ExecutionState:
116
121
stack = []
117
122
118
123
def check_basic_block_requirements (state , basic_block ):
119
- state.gas_left -= basic_block.gas_required
124
+ state.gas_left -= basic_block.base_gas_cost
120
125
if state.gas_left < 0 :
121
126
raise OutOfGas()
122
127
123
128
if len (state.stack) < basic_block.stack_required:
124
129
raise StackUnderflow()
125
130
126
- if len (state.stack) + basic_block.stack_max > 1024 :
131
+ if len (state.stack) + basic_block.stack_max_growth > 1024 :
127
132
raise StackOverflow()
128
133
```
129
134
130
135
## Misc
131
136
132
137
### EVM may terminate earlier
133
138
134
- Because requirements for a whole basic blocks are checked up front, the instructions
139
+ Because requirements for a whole basic block are checked up front, the instructions
135
140
that have observable external effects might not be executed although they would be
136
141
executed if the gas counting would have been done per instruction.
137
142
This is not a consensus issue because the execution terminates with a "hard" exception
@@ -140,17 +145,19 @@ or terminate with a different exception type.
140
145
141
146
### Current "gas left" value
142
147
143
- In EVMJIT also ` GAS ` and _ call _ instructions begin a basic block . This is because
148
+ In EVMJIT additional instructions that begin a basic block are ` GAS ` and any of the _ call _ instructions . This is because
144
149
these instructions need to know the precise _ gas left_ counter value.
145
150
However, in evmone this problem has been solved without additional blocks splitting
146
151
by attaching the correction value to the mentioned instructions.
147
152
153
+ ### Undefined instructions
148
154
155
+ Undefined instructions have base gas cost 0 and not stack requirements.
149
156
150
157
151
158
152
159
160
+ [ Basic Block ] : https://en.wikipedia.org/wiki/Basic_block
153
161
154
162
155
-
156
-
163
+
0 commit comments