diff --git a/lib/evmone/analysis.hpp b/lib/evmone/analysis.hpp index 037ae013b1..43c1b98234 100644 --- a/lib/evmone/analysis.hpp +++ b/lib/evmone/analysis.hpp @@ -20,18 +20,6 @@ using bytes32 = std::array; using bytes = std::basic_string; -/// The status code value indicating that the execution should continue. -/// The 0 value is used. -constexpr auto continue_status = EVMC_SUCCESS; -static_assert(continue_status == 0, "The 'continue' status is not 0"); - -/// The status code value indicating that the execution should be stopped. -/// The internal error (-1) is used. We could use any other negative value, -/// but using one of the constants defined by evmc_status_code avoids -/// warnings in Undefined Behavior Sanitizer. -/// The EVMC_INTERNAL_ERROR MUST NOT be used in evmone for any other case. -constexpr auto stop_status = EVMC_INTERNAL_ERROR; - /// The stack for 256-bit EVM words. /// /// This implementation reserves memory inplace for all possible stack items (1024), @@ -68,10 +56,12 @@ struct evm_stack uint256 pop() noexcept { return *top_item--; } }; +struct instr_info; + struct execution_state { + const instr_info* next_instr{nullptr}; evmc_status_code status = EVMC_SUCCESS; - size_t pc = 0; int64_t gas_left = 0; evm_stack stack; @@ -100,11 +90,8 @@ struct execution_state /// Terminates the execution with the given status code. void exit(evmc_status_code status_code) noexcept { - // If the status_code matches the "continue" status, replace it with the "stop" status. - // That will be revert after the execution loop terminates. - if (status_code == continue_status) - status_code = stop_status; status = status_code; + next_instr = nullptr; } }; diff --git a/lib/evmone/execution.cpp b/lib/evmone/execution.cpp index af5169a460..810734d438 100644 --- a/lib/evmone/execution.cpp +++ b/lib/evmone/execution.cpp @@ -22,26 +22,26 @@ evmc_result execute(evmc_instance*, evmc_context* ctx, evmc_revision rev, const auto state = std::make_unique(); state->analysis = &analysis; + state->next_instr = &state->analysis->instrs[0]; state->msg = msg; state->code = code; state->code_size = code_size; state->host = evmc::HostContext{ctx}; state->gas_left = msg->gas; state->rev = rev; - while (state->status == continue_status) + while (state->next_instr) { - auto& instr = analysis.instrs[state->pc]; + const auto& instr = *state->next_instr; - // Advance the PC not to allow jump opcodes to overwrite it. - ++state->pc; + // Advance next_instr to allow jump opcodes to overwrite it. + ++state->next_instr; instr.fn(*state, instr.arg); } evmc_result result{}; - // Assign status code, revert the "stop" status back to "continue" status - see .exit(). - result.status_code = state->status != stop_status ? state->status : continue_status; + result.status_code = state->status; if (result.status_code == EVMC_SUCCESS || result.status_code == EVMC_REVERT) result.gas_left = state->gas_left; diff --git a/lib/evmone/instructions.cpp b/lib/evmone/instructions.cpp index f12390c1b6..55df30b0c8 100644 --- a/lib/evmone/instructions.cpp +++ b/lib/evmone/instructions.cpp @@ -484,7 +484,7 @@ void op_jump(execution_state& state, instr_argument) noexcept (pc = state.analysis->find_jumpdest(static_cast(dst))) < 0) return state.exit(EVMC_BAD_JUMP_DESTINATION); - state.pc = static_cast(pc); + state.next_instr = &state.analysis->instrs[static_cast(pc)]; } void op_jumpi(execution_state& state, instr_argument arg) noexcept