virtual_machine/
instance.rs1use 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 }
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 #[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}