1 use crate::host_ref::HostRef;
2 use crate::{wasm_extern_t, wasm_extern_vec_t, wasm_module_t, wasm_trap_t};
3 use crate::{wasm_store_t, wasmtime_error_t, ExternHost};
4 use anyhow::Result;
5 use std::cell::RefCell;
6 use std::ptr;
7 use wasmtime::{Extern, Instance, Store, Trap};
8
9 #[repr(C)]
10 #[derive(Clone)]
11 pub struct wasm_instance_t {
12 pub(crate) instance: HostRef<Instance>,
13 exports_cache: RefCell<Option<Vec<ExternHost>>>,
14 }
15
16 wasmtime_c_api_macros::declare_ref!(wasm_instance_t);
17
18 impl wasm_instance_t {
new(instance: Instance) -> wasm_instance_t19 pub(crate) fn new(instance: Instance) -> wasm_instance_t {
20 let store = instance.store().clone();
21 wasm_instance_t {
22 instance: HostRef::new(&store, instance),
23 exports_cache: RefCell::new(None),
24 }
25 }
26
externref(&self) -> wasmtime::ExternRef27 fn externref(&self) -> wasmtime::ExternRef {
28 self.instance.clone().into()
29 }
30 }
31
32 #[no_mangle]
wasm_instance_new( store: &wasm_store_t, wasm_module: &wasm_module_t, imports: *const Box<wasm_extern_t>, result: Option<&mut *mut wasm_trap_t>, ) -> Option<Box<wasm_instance_t>>33 pub unsafe extern "C" fn wasm_instance_new(
34 store: &wasm_store_t,
35 wasm_module: &wasm_module_t,
36 imports: *const Box<wasm_extern_t>,
37 result: Option<&mut *mut wasm_trap_t>,
38 ) -> Option<Box<wasm_instance_t>> {
39 let mut instance = ptr::null_mut();
40 let mut trap = ptr::null_mut();
41 let err = wasmtime_instance_new(
42 store,
43 wasm_module,
44 imports,
45 wasm_module.imports.len(),
46 &mut instance,
47 &mut trap,
48 );
49 match err {
50 Some(err) => {
51 assert!(trap.is_null());
52 assert!(instance.is_null());
53 if let Some(result) = result {
54 *result = Box::into_raw(err.to_trap(&store.store));
55 }
56 None
57 }
58 None => {
59 if instance.is_null() {
60 assert!(!trap.is_null());
61 if let Some(result) = result {
62 *result = trap;
63 } else {
64 drop(Box::from_raw(trap))
65 }
66 None
67 } else {
68 assert!(trap.is_null());
69 Some(Box::from_raw(instance))
70 }
71 }
72 }
73 }
74
75 #[no_mangle]
wasmtime_instance_new( store: &wasm_store_t, module: &wasm_module_t, imports: *const Box<wasm_extern_t>, num_imports: usize, instance_ptr: &mut *mut wasm_instance_t, trap_ptr: &mut *mut wasm_trap_t, ) -> Option<Box<wasmtime_error_t>>76 pub unsafe extern "C" fn wasmtime_instance_new(
77 store: &wasm_store_t,
78 module: &wasm_module_t,
79 imports: *const Box<wasm_extern_t>,
80 num_imports: usize,
81 instance_ptr: &mut *mut wasm_instance_t,
82 trap_ptr: &mut *mut wasm_trap_t,
83 ) -> Option<Box<wasmtime_error_t>> {
84 _wasmtime_instance_new(
85 store,
86 module,
87 std::slice::from_raw_parts(imports, num_imports),
88 instance_ptr,
89 trap_ptr,
90 )
91 }
92
_wasmtime_instance_new( store: &wasm_store_t, module: &wasm_module_t, imports: &[Box<wasm_extern_t>], instance_ptr: &mut *mut wasm_instance_t, trap_ptr: &mut *mut wasm_trap_t, ) -> Option<Box<wasmtime_error_t>>93 fn _wasmtime_instance_new(
94 store: &wasm_store_t,
95 module: &wasm_module_t,
96 imports: &[Box<wasm_extern_t>],
97 instance_ptr: &mut *mut wasm_instance_t,
98 trap_ptr: &mut *mut wasm_trap_t,
99 ) -> Option<Box<wasmtime_error_t>> {
100 let store = &store.store;
101 let imports = imports
102 .iter()
103 .map(|import| match &import.which {
104 ExternHost::Func(e) => Extern::Func(e.borrow().clone()),
105 ExternHost::Table(e) => Extern::Table(e.borrow().clone()),
106 ExternHost::Global(e) => Extern::Global(e.borrow().clone()),
107 ExternHost::Memory(e) => Extern::Memory(e.borrow().clone()),
108 })
109 .collect::<Vec<_>>();
110 let module = &module.module.borrow();
111 handle_instantiate(
112 store,
113 Instance::new(store, module, &imports),
114 instance_ptr,
115 trap_ptr,
116 )
117 }
118
handle_instantiate( store: &Store, instance: Result<Instance>, instance_ptr: &mut *mut wasm_instance_t, trap_ptr: &mut *mut wasm_trap_t, ) -> Option<Box<wasmtime_error_t>>119 pub fn handle_instantiate(
120 store: &Store,
121 instance: Result<Instance>,
122 instance_ptr: &mut *mut wasm_instance_t,
123 trap_ptr: &mut *mut wasm_trap_t,
124 ) -> Option<Box<wasmtime_error_t>> {
125 fn write<T>(ptr: &mut *mut T, val: T) {
126 *ptr = Box::into_raw(Box::new(val))
127 }
128
129 match instance {
130 Ok(instance) => {
131 write(instance_ptr, wasm_instance_t::new(instance));
132 None
133 }
134 Err(e) => match e.downcast::<Trap>() {
135 Ok(trap) => {
136 write(trap_ptr, wasm_trap_t::new(store, trap));
137 None
138 }
139 Err(e) => Some(Box::new(e.into())),
140 },
141 }
142 }
143
144 #[no_mangle]
wasm_instance_exports(instance: &wasm_instance_t, out: &mut wasm_extern_vec_t)145 pub extern "C" fn wasm_instance_exports(instance: &wasm_instance_t, out: &mut wasm_extern_vec_t) {
146 let mut cache = instance.exports_cache.borrow_mut();
147 let exports = cache.get_or_insert_with(|| {
148 let instance = &instance.instance.borrow();
149 instance
150 .exports()
151 .map(|e| match e.into_extern() {
152 Extern::Func(f) => ExternHost::Func(HostRef::new(instance.store(), f)),
153 Extern::Global(f) => ExternHost::Global(HostRef::new(instance.store(), f)),
154 Extern::Memory(f) => ExternHost::Memory(HostRef::new(instance.store(), f)),
155 Extern::Table(f) => ExternHost::Table(HostRef::new(instance.store(), f)),
156 })
157 .collect()
158 });
159 let mut buffer = Vec::with_capacity(exports.len());
160 for e in exports {
161 let ext = Box::new(wasm_extern_t { which: e.clone() });
162 buffer.push(Some(ext));
163 }
164 out.set_buffer(buffer);
165 }
166