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