Skip to content

Commit

Permalink
Keep block info in instruction argument
Browse files Browse the repository at this point in the history
  • Loading branch information
chfast committed Sep 9, 2019
1 parent 0329757 commit 7897280
Show file tree
Hide file tree
Showing 5 changed files with 14 additions and 26 deletions.
10 changes: 4 additions & 6 deletions lib/evmone/analysis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -179,9 +179,8 @@ code_analysis analyze(
static_cast<int16_t>(block.stack_req) :
std::numeric_limits<int16_t>::max();
const auto stack_max_growth = static_cast<int16_t>(block.stack_max_growth);
analysis.blocks.emplace_back(block_info{block.gas_cost, stack_req, stack_max_growth});
analysis.instrs[block.first_instruction_index].arg.p.number =
static_cast<int>(analysis.blocks.size() - 1);
analysis.instrs[block.first_instruction_index].arg.block = {
block.gas_cost, stack_req, stack_max_growth};

// Create new block.
analysis.instrs.emplace_back(fns[OPX_BEGINBLOCK]);
Expand All @@ -194,9 +193,8 @@ code_analysis analyze(
static_cast<int16_t>(block.stack_req) :
std::numeric_limits<int16_t>::max();
const auto stack_max_growth = static_cast<int16_t>(block.stack_max_growth);
analysis.blocks.emplace_back(block_info{block.gas_cost, stack_req, stack_max_growth});
analysis.instrs[block.first_instruction_index].arg.p.number =
static_cast<int>(analysis.blocks.size() - 1);
analysis.instrs[block.first_instruction_index].arg.block = {
block.gas_cost, stack_req, stack_max_growth};

// Make sure the last block is terminated.
// TODO: This is not needed if the last instruction is a terminating one.
Expand Down
1 change: 0 additions & 1 deletion lib/evmone/analysis.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,6 @@ static_assert(sizeof(block_info) == 8);
struct code_analysis
{
std::vector<instr_info> instrs;
std::vector<block_info> blocks;

/// Storage for large push values.
std::vector<intx::uint256> push_values;
Expand Down
2 changes: 1 addition & 1 deletion lib/evmone/instructions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1200,7 +1200,7 @@ const instr_info* op_selfdestruct(const instr_info*, execution_state& state) noe

const instr_info* opx_beginblock(const instr_info* instr, execution_state& state) noexcept
{
auto& block = state.analysis->blocks[static_cast<size_t>(instr->arg.p.number)];
auto& block = instr->arg.block;

if ((state.gas_left -= block.gas_cost) < 0)
return state.exit(EVMC_OUT_OF_GAS);
Expand Down
25 changes: 8 additions & 17 deletions test/unittests/analysis_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ TEST(analysis, example1)
ASSERT_EQ(analysis.instrs.size(), 8);

EXPECT_EQ(analysis.instrs[0].fn, fake_fn_table[OPX_BEGINBLOCK]);
EXPECT_EQ(analysis.instrs[0].arg.p.number, 0);
EXPECT_EQ(analysis.instrs[1].fn, fake_fn_table[OP_PUSH1]);
EXPECT_EQ(analysis.instrs[2].fn, fake_fn_table[OP_PUSH1]);
EXPECT_EQ(analysis.instrs[3].fn, fake_fn_table[OP_MSTORE8]);
Expand All @@ -39,10 +38,9 @@ TEST(analysis, example1)
EXPECT_EQ(analysis.instrs[6].fn, fake_fn_table[OP_SSTORE]);
EXPECT_EQ(analysis.instrs[7].fn, fake_fn_table[OP_STOP]);

ASSERT_EQ(analysis.blocks.size(), 1);
EXPECT_EQ(analysis.blocks[0].gas_cost, 14);
EXPECT_EQ(analysis.blocks[0].stack_req, 0);
EXPECT_EQ(analysis.blocks[0].stack_max_growth, 2);
EXPECT_EQ(analysis.instrs[0].arg.block.gas_cost, 14);
EXPECT_EQ(analysis.instrs[0].arg.block.stack_req, 0);
EXPECT_EQ(analysis.instrs[0].arg.block.stack_max_growth, 2);
}

TEST(analysis, stack_up_and_down)
Expand All @@ -52,16 +50,14 @@ TEST(analysis, stack_up_and_down)

ASSERT_EQ(analysis.instrs.size(), 20);
EXPECT_EQ(analysis.instrs[0].fn, fake_fn_table[OPX_BEGINBLOCK]);
EXPECT_EQ(analysis.instrs[0].arg.p.number, 0);
EXPECT_EQ(analysis.instrs[1].fn, fake_fn_table[OP_DUP2]);
EXPECT_EQ(analysis.instrs[2].fn, fake_fn_table[OP_DUP1]);
EXPECT_EQ(analysis.instrs[8].fn, fake_fn_table[OP_POP]);
EXPECT_EQ(analysis.instrs[18].fn, fake_fn_table[OP_PUSH1]);

ASSERT_EQ(analysis.blocks.size(), 1);
EXPECT_EQ(analysis.blocks[0].gas_cost, 7 * 3 + 10 * 2 + 3);
EXPECT_EQ(analysis.blocks[0].stack_req, 3);
EXPECT_EQ(analysis.blocks[0].stack_max_growth, 7);
EXPECT_EQ(analysis.instrs[0].arg.block.gas_cost, 7 * 3 + 10 * 2 + 3);
EXPECT_EQ(analysis.instrs[0].arg.block.stack_req, 3);
EXPECT_EQ(analysis.instrs[0].arg.block.stack_max_growth, 7);
}

TEST(analysis, push)
Expand All @@ -86,11 +82,12 @@ TEST(analysis, jumpdest_skip)
const auto code = bytecode{} + OP_STOP + OP_JUMPDEST;
auto analysis = evmone::analyze(fake_fn_table, rev, &code[0], code.size());

EXPECT_EQ(analysis.blocks.size(), 2);
ASSERT_EQ(analysis.instrs.size(), 4);
EXPECT_EQ(analysis.instrs[0].fn, fake_fn_table[OPX_BEGINBLOCK]);
EXPECT_EQ(analysis.instrs[0].arg.block.gas_cost, 0);
EXPECT_EQ(analysis.instrs[1].fn, fake_fn_table[OP_STOP]);
EXPECT_EQ(analysis.instrs[2].fn, fake_fn_table[OP_JUMPDEST]);
EXPECT_EQ(analysis.instrs[2].arg.block.gas_cost, 1);
EXPECT_EQ(analysis.instrs[3].fn, fake_fn_table[OP_STOP]);
}

Expand All @@ -99,7 +96,6 @@ TEST(analysis, jump1)
const auto code = jump(add(4, 2)) + OP_JUMPDEST + mstore(0, 3) + ret(0, 0x20) + jump(6);
const auto analysis = analyze(fake_fn_table, rev, &code[0], code.size());

ASSERT_EQ(analysis.blocks.size(), 4);
ASSERT_EQ(analysis.jumpdest_offsets.size(), 1);
ASSERT_EQ(analysis.jumpdest_targets.size(), 1);
EXPECT_EQ(analysis.jumpdest_offsets[0], 6);
Expand All @@ -114,7 +110,6 @@ TEST(analysis, empty)
bytes code;
auto analysis = evmone::analyze(fake_fn_table, rev, &code[0], code.size());

EXPECT_EQ(analysis.blocks.size(), 1);
EXPECT_EQ(analysis.instrs.size(), 2);
EXPECT_EQ(analysis.instrs[0].fn, fake_fn_table[OPX_BEGINBLOCK]);
EXPECT_EQ(analysis.instrs[1].fn, fake_fn_table[OP_STOP]);
Expand All @@ -125,7 +120,6 @@ TEST(analysis, only_jumpdest)
const auto code = bytecode{OP_JUMPDEST};
auto analysis = evmone::analyze(fake_fn_table, rev, &code[0], code.size());

ASSERT_EQ(analysis.blocks.size(), 1);
ASSERT_EQ(analysis.jumpdest_offsets.size(), 1);
ASSERT_EQ(analysis.jumpdest_targets.size(), 1);
EXPECT_EQ(analysis.jumpdest_offsets[0], 0);
Expand All @@ -137,7 +131,6 @@ TEST(analysis, jumpi_at_the_end)
const auto code = bytecode{OP_JUMPI};
auto analysis = evmone::analyze(fake_fn_table, rev, &code[0], code.size());

EXPECT_EQ(analysis.blocks.size(), 2);
ASSERT_EQ(analysis.instrs.size(), 4);
EXPECT_EQ(analysis.instrs[0].fn, fake_fn_table[OPX_BEGINBLOCK]);
EXPECT_EQ(analysis.instrs[1].fn, fake_fn_table[OP_JUMPI]);
Expand All @@ -152,7 +145,6 @@ TEST(analysis, terminated_last_block)
const auto code = ret(0, 0);
auto analysis = evmone::analyze(fake_fn_table, rev, &code[0], code.size());

EXPECT_EQ(analysis.blocks.size(), 2);
ASSERT_EQ(analysis.instrs.size(), 6);
EXPECT_EQ(analysis.instrs[0].fn, fake_fn_table[OPX_BEGINBLOCK]);
EXPECT_EQ(analysis.instrs[3].fn, fake_fn_table[OP_RETURN]);
Expand All @@ -165,7 +157,6 @@ TEST(analysis, jumpdests_groups)
const auto code = 3 * OP_JUMPDEST + push(1) + 3 * OP_JUMPDEST + push(2) + OP_JUMPI;
auto analysis = evmone::analyze(fake_fn_table, rev, &code[0], code.size());

EXPECT_EQ(analysis.blocks.size(), 7);
ASSERT_EQ(analysis.instrs.size(), 11);
EXPECT_EQ(analysis.instrs[0].fn, fake_fn_table[OP_JUMPDEST]);
EXPECT_EQ(analysis.instrs[1].fn, fake_fn_table[OP_JUMPDEST]);
Expand Down
2 changes: 1 addition & 1 deletion test/utils/dump.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ void dump(const evmone::code_analysis& analysis)

if (c == OPX_BEGINBLOCK)
{
block = &analysis.blocks[size_t(instr.arg.p.number)];
block = &instr.arg.block;

const auto get_jumpdest_offset = [&analysis](size_t index) noexcept
{
Expand Down

0 comments on commit 7897280

Please sign in to comment.