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}