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