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