wasmer_vm/
export.rs

1// This file contains code from external sources.
2// Attributions: https://github.com/wasmerio/wasmer/blob/master/ATTRIBUTIONS.md
3
4use crate::global::Global;
5use crate::instance::WeakOrStrongInstanceRef;
6use crate::memory::{Memory, MemoryStyle};
7use crate::table::{Table, TableStyle};
8use crate::vmcontext::{VMFunctionBody, VMFunctionEnvironment, VMFunctionKind, VMTrampoline};
9use crate::VMSharedSignatureIndex;
10use std::sync::Arc;
11use wasmer_types::{MemoryType, TableType};
12
13/// The value of an export passed from one instance to another.
14#[derive(Debug)]
15pub enum VMExtern {
16    /// A function export value.
17    Function(VMFunction),
18
19    /// A table export value.
20    Table(VMTable),
21
22    /// A memory export value.
23    Memory(VMMemory),
24
25    /// A global export value.
26    Global(VMGlobal),
27}
28
29/// A function export value.
30#[derive(Clone, Debug, PartialEq)]
31pub struct VMFunction {
32    /// The address of the native-code function.
33    pub address: *const VMFunctionBody,
34
35    /// Pointer to the containing `VMContext`.
36    pub vmctx: VMFunctionEnvironment,
37
38    /// The function type, used for compatibility checking.
39    pub signature: VMSharedSignatureIndex,
40
41    /// The function kind (specifies the calling convention for the
42    /// function).
43    pub kind: VMFunctionKind,
44
45    /// Address of the function call trampoline owned by the same
46    /// VMContext that owns the VMFunctionBody.
47    ///
48    /// May be `None` when the function is a host function (`FunctionType`
49    /// == `Dynamic` or `vmctx` == `nullptr`).
50    pub call_trampoline: Option<VMTrampoline>,
51
52    /// A “reference” to the instance through the
53    /// `InstanceRef`. `None` if it is a host function.
54    pub instance_ref: Option<WeakOrStrongInstanceRef>,
55}
56
57impl VMFunction {
58    /// Converts the stored instance ref into a strong `InstanceRef` if it is weak.
59    /// Returns None if it cannot be upgraded.
60    pub fn upgrade_instance_ref(&mut self) -> Option<()> {
61        if let Some(ref mut ir) = self.instance_ref {
62            *ir = ir.upgrade()?;
63        }
64        Some(())
65    }
66}
67
68/// # Safety
69/// There is no non-threadsafe logic directly in this type. Calling the function
70/// may not be threadsafe.
71unsafe impl Send for VMFunction {}
72/// # Safety
73/// The members of an VMFunction are immutable after construction.
74unsafe impl Sync for VMFunction {}
75
76impl From<VMFunction> for VMExtern {
77    fn from(func: VMFunction) -> Self {
78        Self::Function(func)
79    }
80}
81
82/// A table export value.
83#[derive(Clone, Debug)]
84pub struct VMTable {
85    /// Pointer to the containing `Table`.
86    pub from: Arc<dyn Table>,
87
88    /// A “reference” to the instance through the
89    /// `InstanceRef`. `None` if it is a host table.
90    pub instance_ref: Option<WeakOrStrongInstanceRef>,
91}
92
93/// # Safety
94/// This is correct because there is no non-threadsafe logic directly in this type;
95/// correct use of the raw table from multiple threads via `definition` requires `unsafe`
96/// and is the responsibilty of the user of this type.
97unsafe impl Send for VMTable {}
98
99/// # Safety
100/// This is correct because the values directly in `definition` should be considered immutable
101/// and the type is both `Send` and `Clone` (thus marking it `Sync` adds no new behavior, it
102/// only makes this type easier to use)
103unsafe impl Sync for VMTable {}
104
105impl VMTable {
106    /// Get the table type for this exported table
107    pub fn ty(&self) -> &TableType {
108        self.from.ty()
109    }
110
111    /// Get the style for this exported table
112    pub fn style(&self) -> &TableStyle {
113        self.from.style()
114    }
115
116    /// Returns whether or not the two `VMTable`s refer to the same Memory.
117    pub fn same(&self, other: &Self) -> bool {
118        Arc::ptr_eq(&self.from, &other.from)
119    }
120
121    /// Converts the stored instance ref into a strong `InstanceRef` if it is weak.
122    /// Returns None if it cannot be upgraded.
123    pub fn upgrade_instance_ref(&mut self) -> Option<()> {
124        if let Some(ref mut ir) = self.instance_ref {
125            *ir = ir.upgrade()?;
126        }
127        Some(())
128    }
129}
130
131impl From<VMTable> for VMExtern {
132    fn from(table: VMTable) -> Self {
133        Self::Table(table)
134    }
135}
136
137/// A memory export value.
138#[derive(Debug, Clone)]
139pub struct VMMemory {
140    /// Pointer to the containing `Memory`.
141    pub from: Arc<dyn Memory>,
142
143    /// A “reference” to the instance through the
144    /// `InstanceRef`. `None` if it is a host memory.
145    pub instance_ref: Option<WeakOrStrongInstanceRef>,
146}
147
148/// # Safety
149/// This is correct because there is no non-threadsafe logic directly in this type;
150/// correct use of the raw memory from multiple threads via `definition` requires `unsafe`
151/// and is the responsibilty of the user of this type.
152unsafe impl Send for VMMemory {}
153
154/// # Safety
155/// This is correct because the values directly in `definition` should be considered immutable
156/// and the type is both `Send` and `Clone` (thus marking it `Sync` adds no new behavior, it
157/// only makes this type easier to use)
158unsafe impl Sync for VMMemory {}
159
160impl VMMemory {
161    /// Get the type for this exported memory
162    pub fn ty(&self) -> MemoryType {
163        self.from.ty()
164    }
165
166    /// Get the style for this exported memory
167    pub fn style(&self) -> &MemoryStyle {
168        self.from.style()
169    }
170
171    /// Returns whether or not the two `VMMemory`s refer to the same Memory.
172    pub fn same(&self, other: &Self) -> bool {
173        Arc::ptr_eq(&self.from, &other.from)
174    }
175
176    /// Converts the stored instance ref into a strong `InstanceRef` if it is weak.
177    /// Returns None if it cannot be upgraded.
178    pub fn upgrade_instance_ref(&mut self) -> Option<()> {
179        if let Some(ref mut ir) = self.instance_ref {
180            *ir = ir.upgrade()?;
181        }
182        Some(())
183    }
184}
185
186impl From<VMMemory> for VMExtern {
187    fn from(memory: VMMemory) -> Self {
188        Self::Memory(memory)
189    }
190}
191
192/// A global export value.
193#[derive(Debug, Clone)]
194pub struct VMGlobal {
195    /// The global declaration, used for compatibility checking.
196    pub from: Arc<Global>,
197
198    /// A “reference” to the instance through the
199    /// `InstanceRef`. `None` if it is a host global.
200    pub instance_ref: Option<WeakOrStrongInstanceRef>,
201}
202
203/// # Safety
204/// This is correct because there is no non-threadsafe logic directly in this type;
205/// correct use of the raw global from multiple threads via `definition` requires `unsafe`
206/// and is the responsibilty of the user of this type.
207unsafe impl Send for VMGlobal {}
208
209/// # Safety
210/// This is correct because the values directly in `definition` should be considered immutable
211/// from the perspective of users of this type and the type is both `Send` and `Clone` (thus
212/// marking it `Sync` adds no new behavior, it only makes this type easier to use)
213unsafe impl Sync for VMGlobal {}
214
215impl VMGlobal {
216    /// Returns whether or not the two `VMGlobal`s refer to the same Global.
217    pub fn same(&self, other: &Self) -> bool {
218        Arc::ptr_eq(&self.from, &other.from)
219    }
220
221    /// Converts the stored instance ref into a strong `InstanceRef` if it is weak.
222    /// Returns None if it cannot be upgraded.
223    pub fn upgrade_instance_ref(&mut self) -> Option<()> {
224        if let Some(ref mut ir) = self.instance_ref {
225            *ir = ir.upgrade()?;
226        }
227        Some(())
228    }
229}
230
231impl From<VMGlobal> for VMExtern {
232    fn from(global: VMGlobal) -> Self {
233        Self::Global(global)
234    }
235}