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}