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, 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 wasm_instance_t { 21 instance: HostRef::new(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 mut instance = ptr::null_mut(); 39 let mut trap = ptr::null_mut(); 40 let err = wasmtime_instance_new( 41 store, 42 wasm_module, 43 imports, 44 wasm_module.imports.len(), 45 &mut instance, 46 &mut trap, 47 ); 48 match err { 49 Some(err) => { 50 assert!(trap.is_null()); 51 assert!(instance.is_null()); 52 if let Some(result) = result { 53 *result = Box::into_raw(err.to_trap()); 54 } 55 None 56 } 57 None => { 58 if instance.is_null() { 59 assert!(!trap.is_null()); 60 if let Some(result) = result { 61 *result = trap; 62 } else { 63 drop(Box::from_raw(trap)) 64 } 65 None 66 } else { 67 assert!(trap.is_null()); 68 Some(Box::from_raw(instance)) 69 } 70 } 71 } 72 } 73 74 #[no_mangle] 75 pub unsafe extern "C" fn wasmtime_instance_new( 76 store: &wasm_store_t, 77 module: &wasm_module_t, 78 imports: *const Box<wasm_extern_t>, 79 num_imports: usize, 80 instance_ptr: &mut *mut wasm_instance_t, 81 trap_ptr: &mut *mut wasm_trap_t, 82 ) -> Option<Box<wasmtime_error_t>> { 83 _wasmtime_instance_new( 84 store, 85 module, 86 std::slice::from_raw_parts(imports, num_imports), 87 instance_ptr, 88 trap_ptr, 89 ) 90 } 91 92 fn _wasmtime_instance_new( 93 store: &wasm_store_t, 94 module: &wasm_module_t, 95 imports: &[Box<wasm_extern_t>], 96 instance_ptr: &mut *mut wasm_instance_t, 97 trap_ptr: &mut *mut wasm_trap_t, 98 ) -> Option<Box<wasmtime_error_t>> { 99 let store = &store.store; 100 let imports = imports 101 .iter() 102 .map(|import| match &import.which { 103 ExternHost::Func(e) => Extern::Func(e.borrow().clone()), 104 ExternHost::Table(e) => Extern::Table(e.borrow().clone()), 105 ExternHost::Global(e) => Extern::Global(e.borrow().clone()), 106 ExternHost::Memory(e) => Extern::Memory(e.borrow().clone()), 107 }) 108 .collect::<Vec<_>>(); 109 let module = &module.module.borrow(); 110 handle_instantiate( 111 Instance::new(store, module, &imports), 112 instance_ptr, 113 trap_ptr, 114 ) 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