Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Baseline API #314

Merged
merged 2 commits into from
May 4, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 14 additions & 14 deletions lib/evmone/baseline.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,16 @@
#include <evmc/instructions.h>
#include <memory>

namespace evmone
namespace evmone::baseline
{
JumpdestMap build_jumpdest_map(const uint8_t* code, size_t code_size)
CodeAnalysis analyze(const uint8_t* code, size_t code_size)
{
// To find if op is any PUSH opcode (OP_PUSH1 <= op <= OP_PUSH32)
// it can be noticed that OP_PUSH32 is INT8_MAX (0x7f) therefore
// static_cast<int8_t>(op) <= OP_PUSH32 is always true and can be skipped.
static_assert(OP_PUSH32 == std::numeric_limits<int8_t>::max());

JumpdestMap map(code_size); // Allocate and init bitmap with zeros.
CodeAnalysis::JumpdestMap map(code_size); // Allocate and init bitmap with zeros.
for (size_t i = 0; i < code_size; ++i)
{
const auto op = code[i];
Expand All @@ -26,12 +26,13 @@ JumpdestMap build_jumpdest_map(const uint8_t* code, size_t code_size)
else if (INTX_UNLIKELY(op == OP_JUMPDEST))
map[i] = true;
}
return map;
return CodeAnalysis{std::move(map)};
}

namespace
{
const uint8_t* op_jump(ExecutionState& state, const JumpdestMap& jumpdest_map) noexcept
const uint8_t* op_jump(
ExecutionState& state, const CodeAnalysis::JumpdestMap& jumpdest_map) noexcept
{
const auto dst = state.stack.pop();
if (dst >= jumpdest_map.size() || !jumpdest_map[static_cast<size_t>(dst)])
Expand Down Expand Up @@ -95,16 +96,15 @@ inline evmc_status_code check_requirements(const char* const* instruction_names,
}
} // namespace

evmc_result baseline_execute(evmc_vm* /*vm*/, const evmc_host_interface* host,
evmc_host_context* ctx, evmc_revision rev, const evmc_message* msg, const uint8_t* code,
size_t code_size) noexcept
evmc_result execute(evmc_vm* /*vm*/, const evmc_host_interface* host, evmc_host_context* ctx,
evmc_revision rev, const evmc_message* msg, const uint8_t* code, size_t code_size) noexcept
{
const auto jumpdest_map = build_jumpdest_map(code, code_size);
const auto jumpdest_map = analyze(code, code_size);
auto state = std::make_unique<ExecutionState>(*msg, rev, *host, ctx, code, code_size);
return baseline_execute(*state, jumpdest_map);
return execute(*state, jumpdest_map);
}

evmc_result baseline_execute(ExecutionState& state, const JumpdestMap& jumpdest_map) noexcept
evmc_result execute(ExecutionState& state, const CodeAnalysis& analysis) noexcept
{
const auto rev = state.rev;
const auto code = state.code.data();
Expand Down Expand Up @@ -382,12 +382,12 @@ evmc_result baseline_execute(ExecutionState& state, const JumpdestMap& jumpdest_
}

case OP_JUMP:
pc = op_jump(state, jumpdest_map);
pc = op_jump(state, analysis.jumpdest_map);
continue;
case OP_JUMPI:
if (state.stack[1] != 0)
{
pc = op_jump(state, jumpdest_map);
pc = op_jump(state, analysis.jumpdest_map);
}
else
{
Expand Down Expand Up @@ -761,4 +761,4 @@ evmc_result baseline_execute(ExecutionState& state, const JumpdestMap& jumpdest_
return evmc::make_result(state.status, gas_left,
state.output_size != 0 ? &state.memory[state.output_offset] : nullptr, state.output_size);
}
} // namespace evmone
} // namespace evmone::baseline
19 changes: 12 additions & 7 deletions lib/evmone/baseline.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,22 @@
#include <evmc/utils.h>
#include <vector>

namespace evmone
namespace evmone::baseline
{
using JumpdestMap = std::vector<bool>;
struct CodeAnalysis
{
using JumpdestMap = std::vector<bool>;

JumpdestMap jumpdest_map;
};

/// Builds the bitmap of valid JUMPDEST locations in the code.
EVMC_EXPORT JumpdestMap build_jumpdest_map(const uint8_t* code, size_t code_size);
/// Analyze the code to build the bitmap of valid JUMPDEST locations.
EVMC_EXPORT CodeAnalysis analyze(const uint8_t* code, size_t code_size);

/// Executes in Baseline interpreter using EVMC-compatible parameters.
evmc_result baseline_execute(evmc_vm* vm, const evmc_host_interface* host, evmc_host_context* ctx,
evmc_result execute(evmc_vm* vm, const evmc_host_interface* host, evmc_host_context* ctx,
evmc_revision rev, const evmc_message* msg, const uint8_t* code, size_t code_size) noexcept;

/// Executes in Baseline interpreter on the given external and initialized state.
evmc_result baseline_execute(ExecutionState& state, const JumpdestMap& jumpdest_map) noexcept;
} // namespace evmone
evmc_result execute(ExecutionState& state, const CodeAnalysis& analysis) noexcept;
} // namespace evmone::baseline
2 changes: 1 addition & 1 deletion lib/evmone/evmone.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ evmc_set_option_result set_option(evmc_vm* vm, char const* name, char const* val
{
if (value[0] == '0' && value[1] == '\0') // O=0
{
vm->execute = evmone::baseline_execute;
vm->execute = evmone::baseline::execute;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice! Will you also move the other one to the evmone::advanced namesapce?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It was easy esthetic change, but I don't plan to do it more right now.

return EVMC_SET_OPTION_SUCCESS;
}
else if (value[0] == '2' && value[1] == '\0') // O=2
Expand Down
2 changes: 1 addition & 1 deletion test/bench/bench.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ void register_benchmarks(const std::vector<BenchmarkCase>& benchmark_cases)
if (registered_vms.count("baseline"))
{
RegisterBenchmark(("baseline/analyse/" + b.name).c_str(), [&b](State& state) {
build_jumpdest_map(state, b.code);
baseline_analyze(state, b.code);
})->Unit(kMicrosecond);
}

Expand Down
4 changes: 2 additions & 2 deletions test/bench/helpers.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,12 @@ inline void analyse(benchmark::State& state, evmc_revision rev, bytes_view code)
state.counters["rate"] = Counter(static_cast<double>(bytes_analysed), Counter::kIsRate);
}

inline void build_jumpdest_map(benchmark::State& state, bytes_view code) noexcept
inline void baseline_analyze(benchmark::State& state, bytes_view code) noexcept
{
auto bytes_analysed = uint64_t{0};
for (auto _ : state)
{
auto r = evmone::build_jumpdest_map(code.data(), code.size());
auto r = evmone::baseline::analyze(code.data(), code.size());
benchmark::DoNotOptimize(r);
bytes_analysed += code.size();
}
Expand Down