mod calls;
mod values;
pub use self::{
calls::{CallFrame, CallStack, StackOffsets},
values::{
BaseValueStackOffset,
FrameParams,
FrameRegisters,
FrameValueStackOffset,
ValueStack,
},
};
use crate::{core::TrapCode, Instance, StackLimits};
#[cold]
fn err_stack_overflow() -> TrapCode {
TrapCode::StackOverflow
}
#[derive(Debug, Default)]
pub struct Stack {
pub calls: CallStack,
pub values: ValueStack,
}
impl Stack {
pub fn new(limits: StackLimits) -> Self {
let calls = CallStack::new(limits.maximum_recursion_depth);
let values = ValueStack::new(
limits.initial_value_stack_height,
limits.maximum_value_stack_height,
);
Self { calls, values }
}
pub fn reset(&mut self) {
self.calls.reset();
self.values.reset();
}
pub fn empty() -> Self {
Self {
values: ValueStack::empty(),
calls: CallStack::default(),
}
}
pub fn capacity(&self) -> usize {
self.values.capacity()
}
#[inline(always)]
#[must_use]
pub unsafe fn merge_call_frames(&mut self, callee: &mut CallFrame) -> Option<Instance> {
let (caller, instance) = self.calls.pop().expect("caller call frame must exist");
debug_assert_eq!(callee.results(), caller.results());
debug_assert!(caller.base_offset() <= callee.base_offset());
let len_drained = self
.values
.drain(caller.frame_offset(), callee.frame_offset());
callee.move_down(len_drained);
instance
}
}