wasmtime/runtime/vm/stack_switching/
stack.rs

1//! This module contains a modified version of the `wasmtime_fiber` crate,
2//! specialized for executing stack switching continuations.
3
4use anyhow::Result;
5use core::ops::Range;
6
7use crate::runtime::vm::stack_switching::VMHostArray;
8use crate::runtime::vm::{VMContext, VMFuncRef, ValRaw};
9
10cfg_if::cfg_if! {
11    if #[cfg(all(feature = "stack-switching", unix, target_arch = "x86_64"))] {
12        mod unix;
13        use unix as imp;
14    } else {
15        mod dummy;
16        use dummy as imp;
17    }
18}
19
20/// Represents an execution stack to use for a fiber.
21#[derive(Debug)]
22#[repr(C)]
23pub struct VMContinuationStack(imp::VMContinuationStack);
24
25impl VMContinuationStack {
26    /// Creates a new fiber stack of the given size.
27    pub fn new(size: usize) -> Result<Self> {
28        Ok(Self(imp::VMContinuationStack::new(size)?))
29    }
30
31    /// Returns a stack of size 0.
32    pub fn unallocated() -> Self {
33        Self(imp::VMContinuationStack::unallocated())
34    }
35
36    /// Is this stack unallocated/of size 0?
37    pub fn is_unallocated(&self) -> bool {
38        imp::VMContinuationStack::is_unallocated(&self.0)
39    }
40
41    /// Creates a new fiber stack with the given pointer to the bottom of the
42    /// stack plus the byte length of the stack.
43    ///
44    /// The `bottom` pointer should be addressable for `len` bytes. The page
45    /// beneath `bottom` should be unmapped as a guard page.
46    ///
47    /// # Safety
48    ///
49    /// This is unsafe because there is no validation of the given pointer.
50    ///
51    /// The caller must properly allocate the stack space with a guard page and
52    /// make the pages accessible for correct behavior.
53    pub unsafe fn from_raw_parts(bottom: *mut u8, guard_size: usize, len: usize) -> Result<Self> {
54        Ok(Self(unsafe {
55            imp::VMContinuationStack::from_raw_parts(bottom, guard_size, len)?
56        }))
57    }
58
59    /// Is this a manually-managed stack created from raw parts? If so, it is up
60    /// to whoever created it to manage the stack's memory allocation.
61    pub fn is_from_raw_parts(&self) -> bool {
62        self.0.is_from_raw_parts()
63    }
64
65    /// Gets the top of the stack.
66    ///
67    /// Returns `None` if the platform does not support getting the top of the
68    /// stack.
69    pub fn top(&self) -> Option<*mut u8> {
70        self.0.top()
71    }
72
73    /// Returns the range of where this stack resides in memory if the platform
74    /// supports it.
75    pub fn range(&self) -> Option<Range<usize>> {
76        self.0.range()
77    }
78
79    /// Returns the instruction pointer stored in the Fiber's ControlContext.
80    pub fn control_context_instruction_pointer(&self) -> usize {
81        self.0.control_context_instruction_pointer()
82    }
83
84    /// Returns the frame pointer stored in the Fiber's ControlContext.
85    pub fn control_context_frame_pointer(&self) -> usize {
86        self.0.control_context_frame_pointer()
87    }
88
89    /// Returns the stack pointer stored in the Fiber's ControlContext.
90    pub fn control_context_stack_pointer(&self) -> usize {
91        self.0.control_context_stack_pointer()
92    }
93
94    /// Initializes this stack, such that it will execute the function denoted
95    /// by `func_ref`. `parameter_count` and `return_value_count` must be the
96    /// corresponding number of parameters and return values of `func_ref`.
97    /// `args` must point to the `args` field of the `VMContRef` owning this pointer.
98    ///
99    /// It will be updated by this function to correctly describe
100    /// the buffer used by this function for its arguments and return values.
101    pub fn initialize(
102        &self,
103        func_ref: *const VMFuncRef,
104        caller_vmctx: *mut VMContext,
105        args: *mut VMHostArray<ValRaw>,
106        parameter_count: u32,
107        return_value_count: u32,
108    ) {
109        self.0.initialize(
110            func_ref,
111            caller_vmctx,
112            args,
113            parameter_count,
114            return_value_count,
115        )
116    }
117}