diff --git a/lib/evmone/analysis.cpp b/lib/evmone/analysis.cpp index a3047a7567..bb360d1904 100644 --- a/lib/evmone/analysis.cpp +++ b/lib/evmone/analysis.cpp @@ -65,7 +65,10 @@ code_analysis analyze( beginblock_instr.arg.p.number = static_cast(analysis.blocks.size() - 1); if (jumpdest) // Add the jumpdest to the map. - analysis.jumpdest_map.emplace_back(static_cast(i), instr_index); + { + analysis.jumpdest_offsets.emplace_back(static_cast(i)); + analysis.jumpdest_targets.emplace_back(static_cast(instr_index)); + } else // Increase instruction count because additional BEGINBLOCK was injected. ++instr_index; } diff --git a/lib/evmone/analysis.hpp b/lib/evmone/analysis.hpp index 40be182078..92c57caf06 100644 --- a/lib/evmone/analysis.hpp +++ b/lib/evmone/analysis.hpp @@ -152,15 +152,23 @@ struct code_analysis /// invalidated when the container grows. std::deque args_storage; - std::vector> jumpdest_map; + /// The offsets of JUMPDESTs in the original code. + /// These are values that JUMP/JUMPI receives as an argument. + /// The elements are sorted. + std::vector jumpdest_offsets; + + /// The indexes of the instructions in the generated instruction table + /// matching the elements from jumdest_offsets. + /// This is value to which the next instruction pointer must be set in JUMP/JUMPI. + std::vector jumpdest_targets; }; inline int find_jumpdest(const code_analysis& analysis, int offset) noexcept { - const auto& m = analysis.jumpdest_map; - const auto it = std::lower_bound(std::begin(m), std::end(m), offset, - [](std::pair p, int v) noexcept { return p.first < v; }); - return (it != std::end(m) && it->first == offset) ? it->second : -1; + const auto begin = std::begin(analysis.jumpdest_offsets); + const auto end = std::end(analysis.jumpdest_offsets); + const auto it = std::lower_bound(begin, end, offset); + return (it != end && *it == offset) ? analysis.jumpdest_targets[it - begin] : -1; } EVMC_EXPORT code_analysis analyze( diff --git a/test/unittests/analysis_test.cpp b/test/unittests/analysis_test.cpp index 1dd33cc3f4..9401bdad26 100644 --- a/test/unittests/analysis_test.cpp +++ b/test/unittests/analysis_test.cpp @@ -86,8 +86,10 @@ TEST(analysis, jump1) const auto analysis = analyze(fake_fn_table, rev, &code[0], code.size()); ASSERT_EQ(analysis.blocks.size(), 3); - ASSERT_EQ(analysis.jumpdest_map.size(), 1); - EXPECT_EQ(analysis.jumpdest_map[0], std::pair(6, 5)); + ASSERT_EQ(analysis.jumpdest_offsets.size(), 1); + ASSERT_EQ(analysis.jumpdest_targets.size(), 1); + EXPECT_EQ(analysis.jumpdest_offsets[0], 6); + EXPECT_EQ(analysis.jumpdest_targets[0], 5); EXPECT_EQ(find_jumpdest(analysis, 6), 5); EXPECT_EQ(find_jumpdest(analysis, 0), -1); EXPECT_EQ(find_jumpdest(analysis, 7), -1); @@ -109,8 +111,10 @@ TEST(analysis, only_jumpdest) auto analysis = evmone::analyze(fake_fn_table, rev, &code[0], code.size()); ASSERT_EQ(analysis.blocks.size(), 1); - ASSERT_EQ(analysis.jumpdest_map.size(), 1); - EXPECT_EQ(analysis.jumpdest_map[0], std::pair(0, 0)); + ASSERT_EQ(analysis.jumpdest_offsets.size(), 1); + ASSERT_EQ(analysis.jumpdest_targets.size(), 1); + EXPECT_EQ(analysis.jumpdest_offsets[0], 0); + EXPECT_EQ(analysis.jumpdest_targets[0], 0); } TEST(analysis, jumpi_at_the_end) diff --git a/test/utils/dump.cpp b/test/utils/dump.cpp index 735019bb9f..83eb470fd9 100644 --- a/test/utils/dump.cpp +++ b/test/utils/dump.cpp @@ -32,12 +32,12 @@ void dump_analysis(const evmone::code_analysis& analysis) auto get_jumpdest_offset = [&analysis](size_t index) noexcept { - for (const auto& d : analysis.jumpdest_map) + for (size_t i = 0; i < analysis.jumpdest_targets.size(); ++i) { - if (d.second == static_cast(index)) - return d.first; + if (i == index) + return analysis.jumpdest_offsets[i]; } - return -1; + return int16_t{-1}; }; std::cout << "┌ ";