Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Track EVM stack "end" instead of "top" #895

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
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
4 changes: 2 additions & 2 deletions lib/evmone/advanced_analysis.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,11 +57,11 @@ struct AdvancedExecutionState : ExecutionState
/// Computes the current EVM stack height.
[[nodiscard]] int stack_size() noexcept
{
return static_cast<int>((&stack.top() - stack_space.bottom()));
return static_cast<int>(stack.end() - stack_space.bottom());
}

/// Adjust the EVM stack height by given change.
void adjust_stack_size(int change) noexcept { stack = &stack.top() + change; }
void adjust_stack_size(int change) noexcept { stack = stack.end() + change; }

/// Terminates the execution with the given status code.
const Instruction* exit(evmc_status_code status_code) noexcept
Expand Down
28 changes: 14 additions & 14 deletions lib/evmone/baseline.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -153,23 +153,23 @@ inline evmc_status_code check_requirements(const CostTable& cost_table, int64_t&
struct Position
{
code_iterator code_it; ///< The position in the code.
uint256* stack_top; ///< The pointer to the stack top.
uint256* stack_end; ///< The pointer to the stack end.
};

/// Helpers for invoking instruction implementations of different signatures.
/// @{
[[release_inline]] inline code_iterator invoke(void (*instr_fn)(StackTop) noexcept, Position pos,
int64_t& /*gas*/, ExecutionState& /*state*/) noexcept
{
instr_fn(pos.stack_top);
instr_fn(pos.stack_end);
return pos.code_it + 1;
}

[[release_inline]] inline code_iterator invoke(
Result (*instr_fn)(StackTop, int64_t, ExecutionState&) noexcept, Position pos, int64_t& gas,
ExecutionState& state) noexcept
{
const auto o = instr_fn(pos.stack_top, gas, state);
const auto o = instr_fn(pos.stack_end, gas, state);
gas = o.gas_left;
if (o.status != EVMC_SUCCESS)
{
Expand All @@ -182,29 +182,29 @@ struct Position
[[release_inline]] inline code_iterator invoke(void (*instr_fn)(StackTop, ExecutionState&) noexcept,
Position pos, int64_t& /*gas*/, ExecutionState& state) noexcept
{
instr_fn(pos.stack_top, state);
instr_fn(pos.stack_end, state);
return pos.code_it + 1;
}

[[release_inline]] inline code_iterator invoke(
code_iterator (*instr_fn)(StackTop, ExecutionState&, code_iterator) noexcept, Position pos,
int64_t& /*gas*/, ExecutionState& state) noexcept
{
return instr_fn(pos.stack_top, state, pos.code_it);
return instr_fn(pos.stack_end, state, pos.code_it);
}

[[release_inline]] inline code_iterator invoke(
code_iterator (*instr_fn)(StackTop, code_iterator) noexcept, Position pos, int64_t& /*gas*/,
ExecutionState& /*state*/) noexcept
{
return instr_fn(pos.stack_top, pos.code_it);
return instr_fn(pos.stack_end, pos.code_it);
}

[[release_inline]] inline code_iterator invoke(
TermResult (*instr_fn)(StackTop, int64_t, ExecutionState&) noexcept, Position pos, int64_t& gas,
ExecutionState& state) noexcept
{
const auto result = instr_fn(pos.stack_top, gas, state);
const auto result = instr_fn(pos.stack_end, gas, state);
gas = result.gas_left;
state.status = result.status;
return nullptr;
Expand All @@ -214,7 +214,7 @@ struct Position
Result (*instr_fn)(StackTop, int64_t, ExecutionState&, code_iterator&) noexcept, Position pos,
int64_t& gas, ExecutionState& state) noexcept
{
const auto result = instr_fn(pos.stack_top, gas, state, pos.code_it);
const auto result = instr_fn(pos.stack_end, gas, state, pos.code_it);
gas = result.gas_left;
if (result.status != EVMC_SUCCESS)
{
Expand All @@ -228,7 +228,7 @@ struct Position
TermResult (*instr_fn)(StackTop, int64_t, ExecutionState&, code_iterator) noexcept,
Position pos, int64_t& gas, ExecutionState& state) noexcept
{
const auto result = instr_fn(pos.stack_top, gas, state, pos.code_it);
const auto result = instr_fn(pos.stack_end, gas, state, pos.code_it);
gas = result.gas_left;
state.status = result.status;
return nullptr;
Expand All @@ -239,14 +239,14 @@ template <Opcode Op>
[[release_inline]] inline Position invoke(const CostTable& cost_table, const uint256* stack_bottom,
Position pos, int64_t& gas, ExecutionState& state) noexcept
{
if (const auto status = check_requirements<Op>(cost_table, gas, pos.stack_top, stack_bottom);
if (const auto status = check_requirements<Op>(cost_table, gas, pos.stack_end, stack_bottom);
status != EVMC_SUCCESS)
{
state.status = status;
return {nullptr, pos.stack_top};
return {nullptr, pos.stack_end};
}
const auto new_pos = invoke(instr::core::impl<Op>, pos, gas, state);
const auto new_stack_top = pos.stack_top + instr::traits[Op].stack_height_change;
const auto new_stack_top = pos.stack_end + instr::traits[Op].stack_height_change;
return {new_pos, new_stack_top};
}

Expand All @@ -265,11 +265,11 @@ int64_t dispatch(const CostTable& cost_table, ExecutionState& state, int64_t gas
if constexpr (TracingEnabled)
{
const auto offset = static_cast<uint32_t>(position.code_it - code);
const auto stack_height = static_cast<int>(position.stack_top - stack_bottom);
const auto stack_height = static_cast<int>(position.stack_end - stack_bottom);
if (offset < state.original_code.size()) // Skip STOP from code padding.
{
tracer->notify_instruction_start(
offset, position.stack_top, stack_height, gas, state);
offset, position.stack_end - 1, stack_height, gas, state);
}
}

Expand Down
5 changes: 1 addition & 4 deletions lib/evmone/execution_state.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,7 @@ class StackSpace
static constexpr auto limit = 1024;

/// Returns the pointer to the "bottom", i.e. below the stack space.
[[nodiscard, clang::no_sanitize("bounds")]] uint256* bottom() noexcept
{
return m_stack_space - 1;
}
[[nodiscard]] uint256* bottom() noexcept { return m_stack_space; }

private:
/// The storage allocated for maximum possible number of items.
Expand Down
15 changes: 9 additions & 6 deletions lib/evmone/instructions.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,25 +18,28 @@ using code_iterator = const uint8_t*;
/// and allows retrieving stack items and manipulating the pointer.
class StackTop
{
uint256* m_top;
uint256* m_end; ///< Pointer to the stack end (1 slot above the stack top item).

public:
StackTop(uint256* top) noexcept : m_top{top} {}
explicit(false) StackTop(uint256* end) noexcept : m_end{end} {}

/// Returns the pointer to the stack end (the stack slot above the top item).
[[nodiscard]] uint256* end() noexcept { return m_end; }

/// Returns the reference to the stack item by index, where 0 means the top item
/// and positive index values the items further down the stack.
/// Using [-1] is also valid, but .push() should be used instead.
[[nodiscard]] uint256& operator[](int index) noexcept { return m_top[-index]; }
[[nodiscard]] uint256& operator[](int index) noexcept { return m_end[-1 - index]; }

/// Returns the reference to the stack top item.
[[nodiscard]] uint256& top() noexcept { return *m_top; }
[[nodiscard]] uint256& top() noexcept { return m_end[-1]; }

/// Returns the current top item and move the stack top pointer down.
/// The value is returned by reference because the stack slot remains valid.
[[nodiscard]] uint256& pop() noexcept { return *m_top--; }
[[nodiscard]] uint256& pop() noexcept { return *--m_end; }

/// Assigns the value to the stack top and moves the stack top pointer up.
void push(const uint256& value) noexcept { *++m_top = value; }
void push(const uint256& value) noexcept { *m_end++ = value; }
};


Expand Down