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