mod calls;
mod values;
pub use self::{
calls::{CallFrame, CallStack, StackOffsets},
values::{BaseValueStackOffset, FrameParams, FrameSlots, FrameValueStackOffset, ValueStack},
};
use crate::{engine::StackConfig, Instance, TrapCode};
#[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(config: &StackConfig) -> Self {
let calls = CallStack::new(config.max_recursion_depth());
let values = ValueStack::new(config.min_stack_height(), config.max_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]
#[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
}
}