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 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] 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 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 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] 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