Skip to content

Commit ab68bd3

Browse files
authored
Merge pull request #167 from ethereum/hide_instruction_table
Drop op_table parameter in analysis()
2 parents a346ca3 + fb08633 commit ab68bd3

File tree

6 files changed

+61
-66
lines changed

6 files changed

+61
-66
lines changed

lib/evmone/analysis.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@ inline constexpr uint64_t load64be(const unsigned char* data) noexcept
1515
(uint64_t{data[1]} << 48) | (uint64_t{data[0]} << 56);
1616
}
1717

18-
code_analysis analyze(
19-
const exec_fn_table& fns, evmc_revision rev, const uint8_t* code, size_t code_size) noexcept
18+
code_analysis analyze(evmc_revision rev, const uint8_t* code, size_t code_size) noexcept
2019
{
20+
const auto& fns = get_op_table(rev);
2121
code_analysis analysis;
2222

2323
const auto max_instrs_size = code_size + 1;

lib/evmone/analysis.hpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,8 @@ inline int find_jumpdest(const code_analysis& analysis, int offset) noexcept
212212
}
213213

214214
EVMC_EXPORT code_analysis analyze(
215-
const exec_fn_table& fns, evmc_revision rev, const uint8_t* code, size_t code_size) noexcept;
215+
evmc_revision rev, const uint8_t* code, size_t code_size) noexcept;
216+
217+
EVMC_EXPORT const exec_fn_table& get_op_table(evmc_revision rev) noexcept;
216218

217219
} // namespace evmone

lib/evmone/execution.cpp

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,14 @@
44

55
#include "execution.hpp"
66
#include "analysis.hpp"
7-
87
#include <memory>
98

109
namespace evmone
1110
{
12-
extern const exec_fn_table op_table[];
13-
1411
evmc_result execute(evmc_instance*, evmc_context* ctx, evmc_revision rev, const evmc_message* msg,
1512
const uint8_t* code, size_t code_size) noexcept
1613
{
17-
auto analysis = analyze(op_table[rev], rev, code, code_size);
14+
auto analysis = analyze(rev, code, code_size);
1815

1916
auto state = std::make_unique<execution_state>();
2017
state->analysis = &analysis;

lib/evmone/instructions.cpp

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1367,9 +1367,8 @@ constexpr exec_fn_table create_op_table_istanbul() noexcept
13671367
auto table = create_op_table_constantinople();
13681368
return table;
13691369
}
1370-
} // namespace
13711370

1372-
extern const exec_fn_table op_table[] = {
1371+
constexpr exec_fn_table op_tables[] = {
13731372
create_op_table_frontier(), // Frontier
13741373
create_op_table_homestead(), // Homestead
13751374
create_op_table_homestead(), // Tangerine Whistle
@@ -1379,4 +1378,12 @@ extern const exec_fn_table op_table[] = {
13791378
create_op_table_constantinople(), // Petersburg
13801379
create_op_table_istanbul(), // Istanbul
13811380
};
1381+
static_assert(sizeof(op_tables) / sizeof(op_tables[0]) > EVMC_MAX_REVISION,
1382+
"op table entry missing for an EVMC revision");
1383+
} // namespace
1384+
1385+
EVMC_EXPORT const exec_fn_table& get_op_table(evmc_revision rev) noexcept
1386+
{
1387+
return op_tables[rev];
1388+
}
13821389
} // namespace evmone

test/bench/bench.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,14 +59,12 @@ void execute(State& state, bytes_view code, bytes_view input) noexcept
5959
state.counters["gas_rate"] = Counter(static_cast<double>(total_gas_used), Counter::kIsRate);
6060
}
6161

62-
constexpr auto fn_table = evmone::exec_fn_table{};
63-
6462
void analyse(State& state, bytes_view code) noexcept
6563
{
6664
auto bytes_analysed = uint64_t{0};
6765
for (auto _ : state)
6866
{
69-
auto r = evmone::analyze(fn_table, EVMC_PETERSBURG, code.data(), code.size());
67+
auto r = evmone::analyze(EVMC_PETERSBURG, code.data(), code.size());
7068
DoNotOptimize(r);
7169
bytes_analysed += code.size();
7270
}

test/unittests/analysis_test.cpp

Lines changed: 45 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -11,33 +11,24 @@
1111
using namespace evmone;
1212

1313
constexpr auto rev = EVMC_BYZANTIUM;
14-
15-
const auto fake_fn_table = []() noexcept
16-
{
17-
evmone::exec_fn_table fns;
18-
for (size_t i = 0; i < fns.size(); ++i)
19-
fns[i] = (evmone::exec_fn)i;
20-
return fns;
21-
}
22-
();
23-
14+
const auto& op_table = get_op_table(rev);
2415

2516
TEST(analysis, example1)
2617
{
2718
const auto code = push(0x2a) + push(0x1e) + OP_MSTORE8 + OP_MSIZE + push(0) + OP_SSTORE;
28-
const auto analysis = analyze(fake_fn_table, rev, &code[0], code.size());
19+
const auto analysis = analyze(rev, &code[0], code.size());
2920

3021
ASSERT_EQ(analysis.instrs.size(), 8);
3122

32-
EXPECT_EQ(analysis.instrs[0].fn, fake_fn_table[OPX_BEGINBLOCK]);
23+
EXPECT_EQ(analysis.instrs[0].fn, op_table[OPX_BEGINBLOCK]);
3324
EXPECT_EQ(analysis.instrs[0].arg.number, 0);
34-
EXPECT_EQ(analysis.instrs[1].fn, fake_fn_table[OP_PUSH1]);
35-
EXPECT_EQ(analysis.instrs[2].fn, fake_fn_table[OP_PUSH1]);
36-
EXPECT_EQ(analysis.instrs[3].fn, fake_fn_table[OP_MSTORE8]);
37-
EXPECT_EQ(analysis.instrs[4].fn, fake_fn_table[OP_MSIZE]);
38-
EXPECT_EQ(analysis.instrs[5].fn, fake_fn_table[OP_PUSH1]);
39-
EXPECT_EQ(analysis.instrs[6].fn, fake_fn_table[OP_SSTORE]);
40-
EXPECT_EQ(analysis.instrs[7].fn, fake_fn_table[OP_STOP]);
25+
EXPECT_EQ(analysis.instrs[1].fn, op_table[OP_PUSH1]);
26+
EXPECT_EQ(analysis.instrs[2].fn, op_table[OP_PUSH1]);
27+
EXPECT_EQ(analysis.instrs[3].fn, op_table[OP_MSTORE8]);
28+
EXPECT_EQ(analysis.instrs[4].fn, op_table[OP_MSIZE]);
29+
EXPECT_EQ(analysis.instrs[5].fn, op_table[OP_PUSH1]);
30+
EXPECT_EQ(analysis.instrs[6].fn, op_table[OP_SSTORE]);
31+
EXPECT_EQ(analysis.instrs[7].fn, op_table[OP_STOP]);
4132

4233
ASSERT_EQ(analysis.blocks.size(), 1);
4334
EXPECT_EQ(analysis.blocks[0].gas_cost, 14);
@@ -48,15 +39,15 @@ TEST(analysis, example1)
4839
TEST(analysis, stack_up_and_down)
4940
{
5041
const auto code = OP_DUP2 + 6 * OP_DUP1 + 10 * OP_POP + push(0);
51-
const auto analysis = analyze(fake_fn_table, rev, &code[0], code.size());
42+
const auto analysis = analyze(rev, &code[0], code.size());
5243

5344
ASSERT_EQ(analysis.instrs.size(), 20);
54-
EXPECT_EQ(analysis.instrs[0].fn, fake_fn_table[OPX_BEGINBLOCK]);
45+
EXPECT_EQ(analysis.instrs[0].fn, op_table[OPX_BEGINBLOCK]);
5546
EXPECT_EQ(analysis.instrs[0].arg.number, 0);
56-
EXPECT_EQ(analysis.instrs[1].fn, fake_fn_table[OP_DUP2]);
57-
EXPECT_EQ(analysis.instrs[2].fn, fake_fn_table[OP_DUP1]);
58-
EXPECT_EQ(analysis.instrs[8].fn, fake_fn_table[OP_POP]);
59-
EXPECT_EQ(analysis.instrs[18].fn, fake_fn_table[OP_PUSH1]);
47+
EXPECT_EQ(analysis.instrs[1].fn, op_table[OP_DUP2]);
48+
EXPECT_EQ(analysis.instrs[2].fn, op_table[OP_DUP1]);
49+
EXPECT_EQ(analysis.instrs[8].fn, op_table[OP_POP]);
50+
EXPECT_EQ(analysis.instrs[18].fn, op_table[OP_PUSH1]);
6051

6152
ASSERT_EQ(analysis.blocks.size(), 1);
6253
EXPECT_EQ(analysis.blocks[0].gas_cost, 7 * 3 + 10 * 2 + 3);
@@ -68,11 +59,11 @@ TEST(analysis, push)
6859
{
6960
constexpr auto push_value = 0x8807060504030201;
7061
const auto code = push(push_value) + "7f00ee";
71-
const auto analysis = analyze(fake_fn_table, rev, &code[0], code.size());
62+
const auto analysis = analyze(rev, &code[0], code.size());
7263

7364
ASSERT_EQ(analysis.instrs.size(), 4);
7465
ASSERT_EQ(analysis.push_values.size(), 1);
75-
EXPECT_EQ(analysis.instrs[0].fn, fake_fn_table[OPX_BEGINBLOCK]);
66+
EXPECT_EQ(analysis.instrs[0].fn, op_table[OPX_BEGINBLOCK]);
7667
EXPECT_EQ(analysis.instrs[1].arg.small_push_value, push_value);
7768
EXPECT_EQ(analysis.instrs[2].arg.push_value, &analysis.push_values[0]);
7869
EXPECT_EQ(analysis.push_values[0], intx::uint256{0xee} << 240);
@@ -84,20 +75,20 @@ TEST(analysis, jumpdest_skip)
8475
// and no new block should be created in this place.
8576

8677
const auto code = bytecode{} + OP_STOP + OP_JUMPDEST;
87-
auto analysis = evmone::analyze(fake_fn_table, rev, &code[0], code.size());
78+
auto analysis = evmone::analyze(rev, &code[0], code.size());
8879

8980
EXPECT_EQ(analysis.blocks.size(), 2);
9081
ASSERT_EQ(analysis.instrs.size(), 4);
91-
EXPECT_EQ(analysis.instrs[0].fn, fake_fn_table[OPX_BEGINBLOCK]);
92-
EXPECT_EQ(analysis.instrs[1].fn, fake_fn_table[OP_STOP]);
93-
EXPECT_EQ(analysis.instrs[2].fn, fake_fn_table[OP_JUMPDEST]);
94-
EXPECT_EQ(analysis.instrs[3].fn, fake_fn_table[OP_STOP]);
82+
EXPECT_EQ(analysis.instrs[0].fn, op_table[OPX_BEGINBLOCK]);
83+
EXPECT_EQ(analysis.instrs[1].fn, op_table[OP_STOP]);
84+
EXPECT_EQ(analysis.instrs[2].fn, op_table[OP_JUMPDEST]);
85+
EXPECT_EQ(analysis.instrs[3].fn, op_table[OP_STOP]);
9586
}
9687

9788
TEST(analysis, jump1)
9889
{
9990
const auto code = jump(add(4, 2)) + OP_JUMPDEST + mstore(0, 3) + ret(0, 0x20) + jump(6);
100-
const auto analysis = analyze(fake_fn_table, rev, &code[0], code.size());
91+
const auto analysis = analyze(rev, &code[0], code.size());
10192

10293
ASSERT_EQ(analysis.blocks.size(), 3);
10394
ASSERT_EQ(analysis.jumpdest_offsets.size(), 1);
@@ -112,17 +103,17 @@ TEST(analysis, jump1)
112103
TEST(analysis, empty)
113104
{
114105
bytes code;
115-
auto analysis = evmone::analyze(fake_fn_table, rev, &code[0], code.size());
106+
auto analysis = evmone::analyze(rev, &code[0], code.size());
116107

117108
EXPECT_EQ(analysis.blocks.size(), 0);
118109
ASSERT_EQ(analysis.instrs.size(), 1);
119-
EXPECT_EQ(analysis.instrs[0].fn, fake_fn_table[OP_STOP]);
110+
EXPECT_EQ(analysis.instrs[0].fn, op_table[OP_STOP]);
120111
}
121112

122113
TEST(analysis, only_jumpdest)
123114
{
124115
const auto code = bytecode{OP_JUMPDEST};
125-
auto analysis = evmone::analyze(fake_fn_table, rev, &code[0], code.size());
116+
auto analysis = evmone::analyze(rev, &code[0], code.size());
126117

127118
ASSERT_EQ(analysis.blocks.size(), 1);
128119
ASSERT_EQ(analysis.jumpdest_offsets.size(), 1);
@@ -134,45 +125,45 @@ TEST(analysis, only_jumpdest)
134125
TEST(analysis, jumpi_at_the_end)
135126
{
136127
const auto code = bytecode{OP_JUMPI};
137-
auto analysis = evmone::analyze(fake_fn_table, rev, &code[0], code.size());
128+
auto analysis = evmone::analyze(rev, &code[0], code.size());
138129

139130
EXPECT_EQ(analysis.blocks.size(), 1);
140131
ASSERT_EQ(analysis.instrs.size(), 3);
141-
EXPECT_EQ(analysis.instrs[0].fn, fake_fn_table[OPX_BEGINBLOCK]);
142-
EXPECT_EQ(analysis.instrs[1].fn, fake_fn_table[OP_JUMPI]);
143-
EXPECT_EQ(analysis.instrs[2].fn, fake_fn_table[OP_STOP]);
132+
EXPECT_EQ(analysis.instrs[0].fn, op_table[OPX_BEGINBLOCK]);
133+
EXPECT_EQ(analysis.instrs[1].fn, op_table[OP_JUMPI]);
134+
EXPECT_EQ(analysis.instrs[2].fn, op_table[OP_STOP]);
144135
}
145136

146137
TEST(analysis, terminated_last_block)
147138
{
148139
// TODO: Even if the last basic block is properly terminated an additional artificial block
149140
// is going to be created with only STOP instruction.
150141
const auto code = ret(0, 0);
151-
auto analysis = evmone::analyze(fake_fn_table, rev, &code[0], code.size());
142+
auto analysis = evmone::analyze(rev, &code[0], code.size());
152143

153144
EXPECT_EQ(analysis.blocks.size(), 1);
154145
ASSERT_EQ(analysis.instrs.size(), 4);
155-
EXPECT_EQ(analysis.instrs[0].fn, fake_fn_table[OPX_BEGINBLOCK]);
156-
EXPECT_EQ(analysis.instrs[3].fn, fake_fn_table[OP_RETURN]);
146+
EXPECT_EQ(analysis.instrs[0].fn, op_table[OPX_BEGINBLOCK]);
147+
EXPECT_EQ(analysis.instrs[3].fn, op_table[OP_RETURN]);
157148
}
158149

159150
TEST(analysis, jumpdests_groups)
160151
{
161152
const auto code = 3 * OP_JUMPDEST + push(1) + 3 * OP_JUMPDEST + push(2) + OP_JUMPI;
162-
auto analysis = evmone::analyze(fake_fn_table, rev, &code[0], code.size());
153+
auto analysis = evmone::analyze(rev, &code[0], code.size());
163154

164155
EXPECT_EQ(analysis.blocks.size(), 6);
165156
ASSERT_EQ(analysis.instrs.size(), 10);
166-
EXPECT_EQ(analysis.instrs[0].fn, fake_fn_table[OP_JUMPDEST]);
167-
EXPECT_EQ(analysis.instrs[1].fn, fake_fn_table[OP_JUMPDEST]);
168-
EXPECT_EQ(analysis.instrs[2].fn, fake_fn_table[OP_JUMPDEST]);
169-
EXPECT_EQ(analysis.instrs[3].fn, fake_fn_table[OP_PUSH1]);
170-
EXPECT_EQ(analysis.instrs[4].fn, fake_fn_table[OP_JUMPDEST]);
171-
EXPECT_EQ(analysis.instrs[5].fn, fake_fn_table[OP_JUMPDEST]);
172-
EXPECT_EQ(analysis.instrs[6].fn, fake_fn_table[OP_JUMPDEST]);
173-
EXPECT_EQ(analysis.instrs[7].fn, fake_fn_table[OP_PUSH1]);
174-
EXPECT_EQ(analysis.instrs[8].fn, fake_fn_table[OP_JUMPI]);
175-
EXPECT_EQ(analysis.instrs[9].fn, fake_fn_table[OP_STOP]);
157+
EXPECT_EQ(analysis.instrs[0].fn, op_table[OP_JUMPDEST]);
158+
EXPECT_EQ(analysis.instrs[1].fn, op_table[OP_JUMPDEST]);
159+
EXPECT_EQ(analysis.instrs[2].fn, op_table[OP_JUMPDEST]);
160+
EXPECT_EQ(analysis.instrs[3].fn, op_table[OP_PUSH1]);
161+
EXPECT_EQ(analysis.instrs[4].fn, op_table[OP_JUMPDEST]);
162+
EXPECT_EQ(analysis.instrs[5].fn, op_table[OP_JUMPDEST]);
163+
EXPECT_EQ(analysis.instrs[6].fn, op_table[OP_JUMPDEST]);
164+
EXPECT_EQ(analysis.instrs[7].fn, op_table[OP_PUSH1]);
165+
EXPECT_EQ(analysis.instrs[8].fn, op_table[OP_JUMPI]);
166+
EXPECT_EQ(analysis.instrs[9].fn, op_table[OP_STOP]);
176167

177168

178169
ASSERT_EQ(analysis.jumpdest_offsets.size(), 6);

0 commit comments

Comments
 (0)