From f11e8504f5b1bae8f32e209bcbafe4fe7c1faf9c Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Sat, 15 Jun 2024 10:37:29 +0200 Subject: [PATCH] Add `StackOffsets` utility type (#1070) add StackOffsets utility type --- .../wasmi/src/engine/executor/instrs/call.rs | 11 ++--- crates/wasmi/src/engine/executor/mod.rs | 5 +- .../wasmi/src/engine/executor/stack/calls.rs | 49 +++++++++++++------ .../wasmi/src/engine/executor/stack/values.rs | 10 ++-- 4 files changed, 46 insertions(+), 29 deletions(-) diff --git a/crates/wasmi/src/engine/executor/instrs/call.rs b/crates/wasmi/src/engine/executor/instrs/call.rs index 0964ee35be..820b269993 100644 --- a/crates/wasmi/src/engine/executor/instrs/call.rs +++ b/crates/wasmi/src/engine/executor/instrs/call.rs @@ -222,13 +222,12 @@ impl<'engine> Executor<'engine> { .call_stack .peek() .expect("need to have a caller on the call stack"); - let (mut uninit_params, base_ptr, frame_ptr) = - self.value_stack.alloc_call_frame(func, |this| { - // Safety: We use the base offset of a live call frame on the call stack. - self.sp = unsafe { this.stack_ptr_at(caller.base_offset()) }; - })?; + let (mut uninit_params, offsets) = self.value_stack.alloc_call_frame(func, |this| { + // Safety: We use the base offset of a live call frame on the call stack. + self.sp = unsafe { this.stack_ptr_at(caller.base_offset()) }; + })?; let instr_ptr = InstructionPtr::new(func.instrs().as_ptr()); - let frame = CallFrame::new(instr_ptr, frame_ptr, base_ptr, results, *instance); + let frame = CallFrame::new(instr_ptr, offsets, results, *instance); if ::HAS_PARAMS { self.copy_call_params(&mut uninit_params); } diff --git a/crates/wasmi/src/engine/executor/mod.rs b/crates/wasmi/src/engine/executor/mod.rs index 663d4679ad..9b65cca15a 100644 --- a/crates/wasmi/src/engine/executor/mod.rs +++ b/crates/wasmi/src/engine/executor/mod.rs @@ -207,7 +207,7 @@ impl<'engine> EngineExecutor<'engine> { .res .code_map .get(Some(store.inner.fuel_mut()), compiled_func)?; - let (mut uninit_params, base_ptr, frame_ptr) = self + let (mut uninit_params, offsets) = self .stack .values .alloc_call_frame(compiled_func, do_nothing)?; @@ -217,8 +217,7 @@ impl<'engine> EngineExecutor<'engine> { uninit_params.init_zeroes(); self.stack.calls.push(CallFrame::new( InstructionPtr::new(compiled_func.instrs().as_ptr()), - frame_ptr, - base_ptr, + offsets, RegisterSpan::new(Register::from_i16(0)), instance, ))?; diff --git a/crates/wasmi/src/engine/executor/stack/calls.rs b/crates/wasmi/src/engine/executor/stack/calls.rs index 70c5cce07d..9408c406b3 100644 --- a/crates/wasmi/src/engine/executor/stack/calls.rs +++ b/crates/wasmi/src/engine/executor/stack/calls.rs @@ -113,15 +113,39 @@ impl CallStack { } } +/// Offsets for a [`CallFrame`] into the [`ValueStack`]. +#[derive(Debug, Copy, Clone)] +pub struct StackOffsets { + /// Offset to the first mutable cell of a [`CallFrame`]. + pub base: BaseValueStackOffset, + /// Offset to the first cell of a [`CallFrame`]. + pub frame: FrameValueStackOffset, +} + +impl StackOffsets { + /// Moves the [`StackOffsets`] values down by `delta`. + /// + /// # Note + /// + /// This is used for the implementation of tail calls. + #[inline(always)] + fn move_down(&mut self, delta: usize) { + let base = usize::from(self.base); + let frame = usize::from(self.frame); + debug_assert!(delta <= base); + debug_assert!(delta <= frame); + self.base = BaseValueStackOffset::new(base - delta); + self.frame = FrameValueStackOffset::new(frame - delta); + } +} + /// A single frame of a called [`CompiledFunc`]. #[derive(Debug, Copy, Clone)] pub struct CallFrame { /// The pointer to the [`Instruction`] that is executed next. instr_ptr: InstructionPtr, - /// Pointer to the first mutable cell of a [`CallFrame`]. - base_ptr: BaseValueStackOffset, - /// Pointer to the first cell of a [`CallFrame`]. - frame_ptr: FrameValueStackOffset, + /// Offsets of the [`CallFrame`] into the [`ValueStack`]. + offsets: StackOffsets, /// Span of registers were the caller expects them in its [`CallFrame`]. results: RegisterSpan, /// The instance in which the function has been defined. @@ -137,15 +161,13 @@ impl CallFrame { /// Creates a new [`CallFrame`]. pub fn new( instr_ptr: InstructionPtr, - frame_ptr: FrameValueStackOffset, - base_ptr: BaseValueStackOffset, + offsets: StackOffsets, results: RegisterSpan, instance: Instance, ) -> Self { Self { instr_ptr, - base_ptr, - frame_ptr, + offsets, results, instance, } @@ -157,12 +179,7 @@ impl CallFrame { /// /// This is used for the implementation of tail calls. pub fn move_down(&mut self, delta: usize) { - let base_index = usize::from(self.base_offset()); - let frame_index = usize::from(self.frame_offset()); - debug_assert!(delta <= base_index); - debug_assert!(delta <= frame_index); - self.base_ptr = BaseValueStackOffset::new(base_index - delta); - self.frame_ptr = FrameValueStackOffset::new(frame_index - delta); + self.offsets.move_down(delta); } /// Updates the [`InstructionPtr`] of the [`CallFrame`]. @@ -181,12 +198,12 @@ impl CallFrame { /// Returns the [`FrameValueStackOffset`] of the [`CallFrame`]. pub fn frame_offset(&self) -> FrameValueStackOffset { - self.frame_ptr + self.offsets.frame } /// Returns the [`BaseValueStackOffset`] of the [`CallFrame`]. pub fn base_offset(&self) -> BaseValueStackOffset { - self.base_ptr + self.offsets.base } /// Returns the [`RegisterSpan`] of the [`CallFrame`]. diff --git a/crates/wasmi/src/engine/executor/stack/values.rs b/crates/wasmi/src/engine/executor/stack/values.rs index e14f4cdaaa..25ee99324e 100644 --- a/crates/wasmi/src/engine/executor/stack/values.rs +++ b/crates/wasmi/src/engine/executor/stack/values.rs @@ -1,4 +1,4 @@ -use super::err_stack_overflow; +use super::{calls::StackOffsets, err_stack_overflow}; use crate::{ core::{TrapCode, UntypedVal}, engine::{bytecode::Register, CompiledFuncEntity}, @@ -225,7 +225,7 @@ impl ValueStack { &mut self, func: &CompiledFuncEntity, on_resize: impl FnMut(&mut Self), - ) -> Result<(FrameParams, BaseValueStackOffset, FrameValueStackOffset), TrapCode> { + ) -> Result<(FrameParams, StackOffsets), TrapCode> { let len_registers = func.len_registers(); let len_consts = func.consts().len(); let len = self.len(); @@ -242,8 +242,10 @@ impl ValueStack { let base = ValueStackOffset(len + len_consts); Ok(( params, - BaseValueStackOffset(base), - FrameValueStackOffset(frame), + StackOffsets { + base: BaseValueStackOffset(base), + frame: FrameValueStackOffset(frame), + }, )) }