pub struct Stack {
pub values: Box<[U256; 1024]>,
pub offset: usize,
}Expand description
The EVM uses a stack-based architecture and does not use registers like some other VMs.
The specification says the stack is limited to 1024 items, aka. 32KiB, which is reasonable enough for allocating it all at once to make sense. Every time an item is pushed into the stack, its bounds have to be checked; by making the stack grow downwards, the underflow detection of the offset update operation can also be reused to check for stack overflow.
A few opcodes require pushing and/or popping multiple elements. The push and
pop methods support working with multiple elements instead of a single one,
reducing the number of checks performed on the stack.
Fields§
§values: Box<[U256; 1024]>§offset: usizeImplementations§
Source§impl Stack
impl Stack
pub fn pop<const N: usize>(&mut self) -> Result<&[U256; N], ExceptionalHalt>
pub fn pop1(&mut self) -> Result<U256, ExceptionalHalt>
Sourcepub fn top_mut(&mut self) -> Result<&mut U256, ExceptionalHalt>
pub fn top_mut(&mut self) -> Result<&mut U256, ExceptionalHalt>
Mutable reference to the top item without changing depth (one underflow check,
no offset write). For stack-neutral unary ops (ISZERO, NOT, CLZ), replacing
pop1 + push with *top_mut() = f(*top) avoids the read-modify-write of the
shared offset, which is the per-opcode serial dependency that pins dispatch IPC.
Sourcepub fn pop1_and_top_mut(&mut self) -> Result<(U256, &mut U256), ExceptionalHalt>
pub fn pop1_and_top_mut(&mut self) -> Result<(U256, &mut U256), ExceptionalHalt>
Pop the top value and return it together with a mutable reference to the new top.
For binary ops: let (a, b) = pop1_and_top_mut()?; *b = f(a, *b) writes the result
in place (one offset write instead of pop::<2> + push’s two), where a is the
original top and *b the original second operand.
Sourcepub fn push(&mut self, value: U256) -> Result<(), ExceptionalHalt>
pub fn push(&mut self, value: U256) -> Result<(), ExceptionalHalt>
Push a single U256 value to the stack, faster than the generic push.
pub fn push_zero(&mut self) -> Result<(), ExceptionalHalt>
pub fn len(&self) -> usize
pub fn is_empty(&self) -> bool
pub fn swap<const N: usize>(&mut self) -> Result<(), ExceptionalHalt>
pub fn clear(&mut self)
Trait Implementations§
impl Eq for Stack
impl StructuralPartialEq for Stack
Auto Trait Implementations§
impl Freeze for Stack
impl RefUnwindSafe for Stack
impl Send for Stack
impl Sync for Stack
impl Unpin for Stack
impl UnsafeUnpin for Stack
impl UnwindSafe for Stack
Blanket Implementations§
Source§impl<T> ArchivePointee for T
impl<T> ArchivePointee for T
Source§type ArchivedMetadata = ()
type ArchivedMetadata = ()
Source§fn pointer_metadata(
_: &<T as ArchivePointee>::ArchivedMetadata,
) -> <T as Pointee>::Metadata
fn pointer_metadata( _: &<T as ArchivePointee>::ArchivedMetadata, ) -> <T as Pointee>::Metadata
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
key and return true if they are equal.Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§impl<T> LayoutRaw for T
impl<T> LayoutRaw for T
Source§fn layout_raw(_: <T as Pointee>::Metadata) -> Result<Layout, LayoutError>
fn layout_raw(_: <T as Pointee>::Metadata) -> Result<Layout, LayoutError>
Source§impl<T, N1, N2> Niching<NichedOption<T, N1>> for N2
impl<T, N1, N2> Niching<NichedOption<T, N1>> for N2
Source§unsafe fn is_niched(niched: *const NichedOption<T, N1>) -> bool
unsafe fn is_niched(niched: *const NichedOption<T, N1>) -> bool
Source§fn resolve_niched(out: Place<NichedOption<T, N1>>)
fn resolve_niched(out: Place<NichedOption<T, N1>>)
out indicating that a T is niched.