1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
//! Defines WasmEdge CallingFrame.
use crate::{
executor::InnerExecutor,
ffi,
instance::{memory::InnerMemory, module::InnerInstance},
Executor, Instance, Memory,
};
use parking_lot::Mutex;
use std::sync::Arc;
/// Represents a calling frame on top of stack.
#[derive(Debug)]
pub struct CallingFrame {
pub(crate) inner: InnerCallingFrame,
}
impl Drop for CallingFrame {
fn drop(&mut self) {
if !self.inner.0.is_null() {
self.inner.0 = std::ptr::null();
}
}
}
impl CallingFrame {
/// Creates a CallingFrame instance.
pub(crate) fn create(ctx: *const ffi::WasmEdge_CallingFrameContext) -> Self {
Self {
inner: InnerCallingFrame(ctx),
}
}
/// Returns the [executor instance](crate::Executor) from this calling frame.
pub fn executor_mut(&self) -> Option<Executor> {
let ctx = unsafe { ffi::WasmEdge_CallingFrameGetExecutor(self.inner.0) };
match ctx.is_null() {
false => Some(Executor {
inner: std::sync::Arc::new(InnerExecutor(ctx)),
registered: true,
}),
true => None,
}
}
/// Returns the [module instance](crate::Instance) in this calling frame.
///
/// If the executing function instance is a host function and not added into any module instance, then returns `None`.
///
/// When a wasm function is executing and trying to call a host function inside, a frame with the module
/// instance the wasm function belongs to will be pushed onto the stack. And therefore the calling frame
/// context will record that module instance.
///
pub fn module_instance(&self) -> Option<Instance> {
let ctx = unsafe { ffi::WasmEdge_CallingFrameGetModuleInstance(self.inner.0) };
match ctx.is_null() {
false => Some(Instance {
inner: Arc::new(Mutex::new(InnerInstance(ctx as *mut _))),
registered: true,
}),
true => None,
}
}
/// Returns the [memory instance](crate::Memory) by the given index from the module instance of the current
/// calling frame. If the memory instance is not found, returns `None`.
///
/// By default, a WASM module has only one memory instance after instantiation. Therefore, users can pass in `0` as
/// the index to get the memory instance in host function body. When the [MultiMemories](crate::Config::multi_memories)
/// config option is enabled, there would be more than one memory instances in the wasm module. Users can retrieve
/// the target memory instance by specifying the index of the memory instance in the wasm module instance.
///
/// # Arguments
///
/// * idx - The index of the memory instance.
///
pub fn memory_mut(&self, idx: u32) -> Option<Memory> {
let ctx = unsafe { ffi::WasmEdge_CallingFrameGetMemoryInstance(self.inner.0, idx) };
match ctx.is_null() {
false => Some(Memory {
inner: std::sync::Arc::new(Mutex::new(InnerMemory(ctx))),
registered: true,
}),
true => None,
}
}
/// Provides a raw pointer to the inner CallingFrame context.
#[cfg(feature = "ffi")]
#[cfg_attr(docsrs, doc(cfg(feature = "ffi")))]
pub fn as_ptr(&self) -> *const ffi::WasmEdge_CallingFrameContext {
self.inner.0 as *const _
}
}
#[derive(Debug)]
pub(crate) struct InnerCallingFrame(pub(crate) *const ffi::WasmEdge_CallingFrameContext);
unsafe impl Send for InnerCallingFrame {}
unsafe impl Sync for InnerCallingFrame {}