1 use crate::{wasm_extern_t, wasm_extern_vec_t, wasm_module_t, wasm_trap_t}; 2 use crate::{wasm_store_t, ExternHost}; 3 use anyhow::Result; 4 use std::cell::RefCell; 5 use std::ptr; 6 use wasmtime::{Extern, HostRef, Instance, Store, Trap}; 7 8 #[repr(C)] 9 #[derive(Clone)] 10 pub struct wasm_instance_t { 11 pub(crate) instance: HostRef<Instance>, 12 exports_cache: RefCell<Option<Vec<ExternHost>>>, 13 } 14 15 wasmtime_c_api_macros::declare_ref!(wasm_instance_t); 16 17 impl wasm_instance_t { 18 fn new(instance: Instance) -> wasm_instance_t { 19 wasm_instance_t { 20 instance: HostRef::new(instance), 21 exports_cache: RefCell::new(None), 22 } 23 } 24 25 fn anyref(&self) -> wasmtime::AnyRef { 26 self.instance.anyref() 27 } 28 } 29 30 #[no_mangle] 31 pub unsafe extern "C" fn wasm_instance_new( 32 store: &wasm_store_t, 33 module: &wasm_module_t, 34 imports: *const Box<wasm_extern_t>, 35 result: Option<&mut *mut wasm_trap_t>, 36 ) -> Option<Box<wasm_instance_t>> { 37 let mut externs: Vec<Extern> = Vec::with_capacity((*module).imports.len()); 38 for i in 0..(*module).imports.len() { 39 let import = &*imports.add(i); 40 externs.push(match &import.which { 41 ExternHost::Func(e) => Extern::Func(e.borrow().clone()), 42 ExternHost::Table(e) => Extern::Table(e.borrow().clone()), 43 ExternHost::Global(e) => Extern::Global(e.borrow().clone()), 44 ExternHost::Memory(e) => Extern::Memory(e.borrow().clone()), 45 }); 46 } 47 let store = &(*store).store.borrow(); 48 let module = &(*module).module.borrow(); 49 if !Store::same(&store, module.store()) { 50 if let Some(result) = result { 51 let trap = Trap::new("wasm_store_t must match store in wasm_module_t"); 52 let trap = Box::new(wasm_trap_t { 53 trap: HostRef::new(trap), 54 }); 55 *result = Box::into_raw(trap); 56 } 57 return None; 58 } 59 handle_instantiate(Instance::new(module, &externs), result) 60 } 61 62 pub fn handle_instantiate( 63 instance: Result<Instance>, 64 result: Option<&mut *mut wasm_trap_t>, 65 ) -> Option<Box<wasm_instance_t>> { 66 match instance { 67 Ok(instance) => { 68 if let Some(result) = result { 69 *result = ptr::null_mut(); 70 } 71 Some(Box::new(wasm_instance_t::new(instance))) 72 } 73 Err(trap) => { 74 if let Some(result) = result { 75 let trap = match trap.downcast::<Trap>() { 76 Ok(trap) => trap, 77 Err(e) => Trap::new(format!("{:?}", e)), 78 }; 79 let trap = Box::new(wasm_trap_t { 80 trap: HostRef::new(trap), 81 }); 82 *result = Box::into_raw(trap); 83 } 84 None 85 } 86 } 87 } 88 89 #[no_mangle] 90 pub extern "C" fn wasm_instance_exports(instance: &wasm_instance_t, out: &mut wasm_extern_vec_t) { 91 let mut cache = instance.exports_cache.borrow_mut(); 92 let exports = cache.get_or_insert_with(|| { 93 let instance = &instance.instance.borrow(); 94 instance 95 .exports() 96 .iter() 97 .map(|e| match e { 98 Extern::Func(f) => ExternHost::Func(HostRef::new(f.clone())), 99 Extern::Global(f) => ExternHost::Global(HostRef::new(f.clone())), 100 Extern::Memory(f) => ExternHost::Memory(HostRef::new(f.clone())), 101 Extern::Table(f) => ExternHost::Table(HostRef::new(f.clone())), 102 }) 103 .collect() 104 }); 105 let mut buffer = Vec::with_capacity(exports.len()); 106 for e in exports { 107 let ext = Box::new(wasm_extern_t { which: e.clone() }); 108 buffer.push(Some(ext)); 109 } 110 out.set_buffer(buffer); 111 } 112