virtual_machine/
instance.rs

1use core::ffi::c_void;
2
3use alloc::{boxed::Box, vec, vec::Vec};
4use wamr_rust_sdk::{
5    function::Function,
6    instance,
7    sys::{
8        wasm_runtime_addr_app_to_native, wasm_runtime_addr_native_to_app,
9        wasm_runtime_get_custom_data, wasm_runtime_validate_native_addr,
10    },
11    value::WasmValue,
12};
13
14use crate::{CustomData, Error, Result, WasmPointer, module::Module, runtime::Runtime};
15
16pub struct Instance<'module> {
17    instance: instance::Instance<'module>,
18}
19
20unsafe impl Send for Instance<'_> {}
21
22impl Drop for Instance<'_> {
23    fn drop(&mut self) {
24        let instance = self.get_inner_reference().get_inner_instance();
25        unsafe {
26            let user_data = wasm_runtime_get_custom_data(instance) as *mut CustomData;
27
28            if !user_data.is_null() {
29                let _ = Box::from_raw(user_data);
30            }
31        }
32
33        // User data is dropped here.
34    }
35}
36
37impl<'module> Instance<'module> {
38    pub fn new(
39        runtime: &Runtime,
40        module: &'module Module<'module>,
41        stack_size: usize,
42    ) -> Result<Self> {
43        let wamr_instance = instance::Instance::new(
44            runtime.get_inner_reference(),
45            module.get_inner_reference(),
46            stack_size as u32,
47        )?;
48
49        let instance = Instance {
50            instance: wamr_instance,
51        };
52
53        Ok(instance)
54    }
55
56    pub fn validate_native_pointer<T>(&self, pointer: *const T, size: usize) -> bool {
57        unsafe {
58            wasm_runtime_validate_native_addr(
59                self.get_inner_reference().get_inner_instance(),
60                pointer as *mut c_void,
61                size as u64,
62            )
63        }
64    }
65
66    pub fn validate_wasm_pointer(&self, address: WasmPointer, size: usize) -> bool {
67        unsafe {
68            wasm_runtime_validate_native_addr(
69                self.get_inner_reference().get_inner_instance(),
70                address as *mut c_void,
71                size as u64,
72            )
73        }
74    }
75
76    pub fn convert_to_wasm_pointer<T>(&self, pointer: *const T) -> WasmPointer {
77        unsafe {
78            wasm_runtime_addr_native_to_app(
79                self.get_inner_reference().get_inner_instance(),
80                pointer as *mut c_void,
81            ) as WasmPointer
82        }
83    }
84
85    /// # Safety
86    ///
87    /// This function is unsafe because it is not checked that the address is valid.
88    #[allow(clippy::mut_from_ref)]
89    pub unsafe fn convert_to_native_pointer<T>(&self, address: WasmPointer) -> *mut T {
90        unsafe {
91            wasm_runtime_addr_app_to_native(
92                self.get_inner_reference().get_inner_instance(),
93                address as u64,
94            ) as *mut T
95        }
96    }
97
98    pub fn call_export_function(
99        &self,
100        name: &str,
101        parameters: &Vec<WasmValue>,
102    ) -> Result<Vec<WasmValue>> {
103        if parameters.is_empty() {
104            Ok(
105                Function::find_export_func(self.get_inner_reference(), name)?
106                    .call(&self.instance, &vec![WasmValue::I32(0)])?,
107            )
108        } else {
109            Ok(
110                Function::find_export_func(self.get_inner_reference(), name)?
111                    .call(&self.instance, parameters)?,
112            )
113        }
114    }
115
116    pub fn call_main(&self, parameters: &Vec<WasmValue>) -> Result<Vec<WasmValue>> {
117        self.call_export_function("_start", parameters)
118    }
119
120    pub fn allocate<T>(&mut self, size: usize) -> Result<*mut T> {
121        let result = self.call_export_function("Allocate", &vec![WasmValue::I32(size as i32)])?;
122
123        if let Some(WasmValue::I32(pointer)) = result.first() {
124            let pointer = unsafe { self.convert_to_native_pointer(*pointer as u32) };
125
126            Ok(pointer)
127        } else {
128            Err(Error::AllocationFailure)
129        }
130    }
131
132    pub fn deallocate<T>(&mut self, data: *mut T) {
133        let _ = self.call_export_function("Deallocate", &vec![WasmValue::I32(data as i32)]);
134    }
135
136    pub fn get_inner_reference(&'_ self) -> &'_ instance::Instance<'_> {
137        &self.instance
138    }
139}