1use crate::{
6 backend::RunnableModule,
7 backing::{ImportBacking, LocalBacking},
8 error::{CallResult, InvokeError, ResolveError, ResolveResult, Result, RuntimeError},
9 export::{Context, Export, ExportIter, Exportable, FuncPointer},
10 global::Global,
11 import::{ImportObject, LikeNamespace},
12 loader::Loader,
13 memory::Memory,
14 module::{ExportIndex, Module, ModuleInfo, ModuleInner},
15 sig_registry::SigRegistry,
16 structures::TypedIndex,
17 table::Table,
18 typed_func::{Func, Wasm, WasmTypeList},
19 types::{FuncIndex, FuncSig, GlobalIndex, LocalOrImport, MemoryIndex, TableIndex, Type, Value},
20 vm::{self, InternalField},
21};
22use smallvec::{smallvec, SmallVec};
23use std::{
24 borrow::Borrow,
25 mem,
26 pin::Pin,
27 ptr::{self, NonNull},
28 sync::{Arc, Mutex},
29};
30
31pub(crate) struct InstanceInner {
32 #[allow(dead_code)]
33 pub(crate) backing: LocalBacking,
34 import_backing: ImportBacking,
35 pub(crate) vmctx: *mut vm::Ctx,
36}
37
38unsafe impl Send for InstanceInner {}
40
41impl Drop for InstanceInner {
42 fn drop(&mut self) {
43 unsafe { Box::from_raw(self.vmctx) };
45 }
46}
47
48pub struct Instance {
56 pub module: Arc<ModuleInner>,
58 inner: Pin<Box<InstanceInner>>,
59 pub exports: Exports,
61 #[allow(dead_code)]
62 pub import_object: ImportObject,
64}
65
66impl Instance {
67 pub(crate) fn new(module: Arc<ModuleInner>, imports: &ImportObject) -> Result<Instance> {
68 let mut vmctx: Box<mem::MaybeUninit<vm::Ctx>> =
72 Box::new(mem::MaybeUninit::<vm::Ctx>::zeroed());
73
74 let import_backing = ImportBacking::new(&module, &imports, vmctx.as_mut_ptr())?;
75 let backing = LocalBacking::new(&module, &import_backing, vmctx.as_mut_ptr())?;
76
77 let mut inner = Box::pin(InstanceInner {
78 backing,
79 import_backing,
80 vmctx: vmctx.as_mut_ptr(),
81 });
82
83 unsafe {
86 let backing = &mut *(&mut inner.backing as *mut _);
87 let import_backing = &mut *(&mut inner.import_backing as *mut _);
88 let real_ctx = match imports.call_state_creator() {
89 Some((data, dtor)) => {
90 vm::Ctx::new_with_data(backing, import_backing, &module, data, dtor)
91 }
92 None => vm::Ctx::new(backing, import_backing, &module),
93 };
94 vmctx.as_mut_ptr().write(real_ctx);
95 };
96 Box::leak(vmctx);
97
98 let exports = Exports {
99 module: module.clone(),
100 instance_inner: &*inner as *const InstanceInner,
101 };
102
103 let instance = Instance {
104 module,
105 inner,
106 exports,
107 import_object: imports.clone(),
108 };
109
110 if let Some(start_index) = instance.module.info.start_func {
111 let func_ptr = match start_index.local_or_import(&instance.module.info) {
115 LocalOrImport::Local(local_func_index) => instance
116 .module
117 .runnable_module
118 .get_func(&instance.module.info, local_func_index)
119 .unwrap(),
120 LocalOrImport::Import(import_func_index) => NonNull::new(
121 instance.inner.import_backing.vm_functions[import_func_index].func as *mut _,
122 )
123 .unwrap(),
124 };
125
126 let ctx_ptr = match start_index.local_or_import(&instance.module.info) {
127 LocalOrImport::Local(_) => instance.inner.vmctx,
128 LocalOrImport::Import(imported_func_index) => unsafe {
129 instance.inner.import_backing.vm_functions[imported_func_index]
130 .func_ctx
131 .as_ref()
132 }
133 .vmctx
134 .as_ptr(),
135 };
136
137 let sig_index = *instance
138 .module
139 .info
140 .func_assoc
141 .get(start_index)
142 .expect("broken invariant, incorrect func index");
143
144 let wasm_trampoline = instance
145 .module
146 .runnable_module
147 .get_trampoline(&instance.module.info, sig_index)
148 .expect("wasm trampoline");
149
150 let start_func: Func<(), (), Wasm> =
151 unsafe { Func::from_raw_parts(wasm_trampoline, func_ptr, None, ctx_ptr) };
152
153 start_func.call()?;
154 }
155
156 Ok(instance)
157 }
158
159 pub fn load<T: Loader>(&self, loader: T) -> ::std::result::Result<T::Instance, T::Error> {
161 loader.load(&**self.module.runnable_module, &self.module.info, unsafe {
162 &*self.inner.vmctx
163 })
164 }
165
166 #[deprecated(
186 since = "0.17.0",
187 note = "Please use `instance.exports.get(name)` instead"
188 )]
189 pub fn func<Args, Rets>(&self, name: &str) -> ResolveResult<Func<Args, Rets, Wasm>>
190 where
191 Args: WasmTypeList,
192 Rets: WasmTypeList,
193 {
194 self.exports.get(name)
195 }
196
197 pub fn resolve_func(&self, name: &str) -> ResolveResult<usize> {
199 resolve_func_index(&*self.module, name).map(|fi| fi.index())
200 }
201
202 #[deprecated(
217 since = "0.17.0",
218 note = "Please use `instance.exports.get(name)` instead"
219 )]
220 pub fn dyn_func(&self, name: &str) -> ResolveResult<DynFunc> {
221 self.exports.get(name)
222 }
223
224 pub fn call(&self, name: &str, params: &[Value]) -> CallResult<Vec<Value>> {
264 let func: DynFunc = self.exports.get(name)?;
265 func.call(params)
266 }
267
268 pub fn context(&self) -> &vm::Ctx {
273 unsafe { &*self.inner.vmctx }
274 }
275
276 pub fn context_mut(&mut self) -> &mut vm::Ctx {
281 unsafe { &mut *self.inner.vmctx }
282 }
283
284 pub fn exports(&self) -> ExportIter {
287 ExportIter::new(&self.module, &self.inner)
288 }
289
290 pub fn module(&self) -> Module {
292 Module::new(Arc::clone(&self.module))
293 }
294
295 pub fn get_internal(&self, field: &InternalField) -> u64 {
297 self.inner.backing.internals.0[field.index()]
298 }
299
300 pub fn set_internal(&mut self, field: &InternalField, value: u64) {
302 self.inner.backing.internals.0[field.index()] = value;
303 }
304}
305
306fn resolve_func_index(module: &ModuleInner, name: &str) -> ResolveResult<FuncIndex> {
308 let export_index =
309 module
310 .info
311 .exports
312 .get(name)
313 .ok_or_else(|| ResolveError::ExportNotFound {
314 name: name.to_string(),
315 })?;
316
317 if let ExportIndex::Func(func_index) = export_index {
318 Ok(*func_index)
319 } else {
320 Err(ResolveError::ExportWrongType {
321 name: name.to_string(),
322 }
323 .into())
324 }
325}
326
327impl InstanceInner {
328 pub(crate) fn get_export_from_index(
329 &self,
330 module: &ModuleInner,
331 export_index: &ExportIndex,
332 ) -> Export {
333 match export_index {
334 ExportIndex::Func(func_index) => {
335 let (func, ctx, signature) = self.get_func_from_index(module, *func_index);
336
337 Export::Function {
338 func,
339 ctx: match ctx {
340 Context::Internal => Context::External(self.vmctx),
341 ctx @ Context::External(_) => ctx,
342 ctx @ Context::ExternalWithEnv(_, _) => ctx,
343 },
344 signature,
345 }
346 }
347 ExportIndex::Memory(memory_index) => {
348 let memory = self.get_memory_from_index(module, *memory_index);
349 Export::Memory(memory)
350 }
351 ExportIndex::Global(global_index) => {
352 let global = self.get_global_from_index(module, *global_index);
353 Export::Global(global)
354 }
355 ExportIndex::Table(table_index) => {
356 let table = self.get_table_from_index(module, *table_index);
357 Export::Table(table)
358 }
359 }
360 }
361
362 fn get_func_from_index(
363 &self,
364 module: &ModuleInner,
365 func_index: FuncIndex,
366 ) -> (FuncPointer, Context, Arc<FuncSig>) {
367 let sig_index = *module
368 .info
369 .func_assoc
370 .get(func_index)
371 .expect("broken invariant, incorrect func index");
372
373 let (func_ptr, ctx) = match func_index.local_or_import(&module.info) {
374 LocalOrImport::Local(local_func_index) => (
375 module
376 .runnable_module
377 .get_func(&module.info, local_func_index)
378 .expect("broken invariant, func resolver not synced with module.exports")
379 .cast()
380 .as_ptr() as *const _,
381 Context::Internal,
382 ),
383 LocalOrImport::Import(imported_func_index) => {
384 let imported_func = &self.import_backing.vm_functions[imported_func_index];
385 let func_ctx = unsafe { imported_func.func_ctx.as_ref() };
386
387 (
388 imported_func.func as *const _,
389 Context::ExternalWithEnv(func_ctx.vmctx.as_ptr(), func_ctx.func_env),
390 )
391 }
392 };
393
394 let signature = SigRegistry.lookup_signature_ref(&module.info.signatures[sig_index]);
395
396 (unsafe { FuncPointer::new(func_ptr) }, ctx, signature)
397 }
398
399 fn get_memory_from_index(&self, module: &ModuleInner, mem_index: MemoryIndex) -> Memory {
400 match mem_index.local_or_import(&module.info) {
401 LocalOrImport::Local(local_mem_index) => self.backing.memories[local_mem_index].clone(),
402 LocalOrImport::Import(imported_mem_index) => {
403 self.import_backing.memories[imported_mem_index].clone()
404 }
405 }
406 }
407
408 fn get_global_from_index(&self, module: &ModuleInner, global_index: GlobalIndex) -> Global {
409 match global_index.local_or_import(&module.info) {
410 LocalOrImport::Local(local_global_index) => {
411 self.backing.globals[local_global_index].clone()
412 }
413 LocalOrImport::Import(import_global_index) => {
414 self.import_backing.globals[import_global_index].clone()
415 }
416 }
417 }
418
419 fn get_table_from_index(&self, module: &ModuleInner, table_index: TableIndex) -> Table {
420 match table_index.local_or_import(&module.info) {
421 LocalOrImport::Local(local_table_index) => {
422 self.backing.tables[local_table_index].clone()
423 }
424 LocalOrImport::Import(imported_table_index) => {
425 self.import_backing.tables[imported_table_index].clone()
426 }
427 }
428 }
429}
430
431impl LikeNamespace for Instance {
432 fn get_export(&self, name: &str) -> Option<Export> {
433 let export_index = self.module.info.exports.get(name)?;
434
435 Some(self.inner.get_export_from_index(&self.module, export_index))
436 }
437
438 fn get_exports(&self) -> Vec<(String, Export)> {
439 unimplemented!("Use the exports method instead");
440 }
441
442 fn maybe_insert(&mut self, _name: &str, _export: Export) -> Option<()> {
443 None
444 }
445}
446
447use std::rc::Rc;
448impl LikeNamespace for Rc<Instance> {
449 fn get_export(&self, name: &str) -> Option<Export> {
450 let export_index = self.module.info.exports.get(name)?;
451
452 Some(self.inner.get_export_from_index(&self.module, export_index))
453 }
454
455 fn get_exports(&self) -> Vec<(String, Export)> {
456 unimplemented!("Use the exports method instead");
457 }
458
459 fn maybe_insert(&mut self, _name: &str, _export: Export) -> Option<()> {
460 None
461 }
462}
463
464impl LikeNamespace for Arc<Mutex<Instance>> {
465 fn get_export(&self, name: &str) -> Option<Export> {
466 let instance = self.lock().unwrap();
467 let export_index = instance.module.info.exports.get(name)?;
468
469 Some(
470 instance
471 .inner
472 .get_export_from_index(&instance.module, export_index),
473 )
474 }
475
476 fn get_exports(&self) -> Vec<(String, Export)> {
477 unimplemented!("Use the exports method instead");
478 }
479
480 fn maybe_insert(&mut self, _name: &str, _export: Export) -> Option<()> {
481 None
482 }
483}
484
485#[must_use]
486fn call_func_with_index(
487 info: &ModuleInfo,
488 runnable: &dyn RunnableModule,
489 import_backing: &ImportBacking,
490 local_ctx: *mut vm::Ctx,
491 func_index: FuncIndex,
492 args: &[Value],
493 rets: &mut Vec<Value>,
494) -> CallResult<()> {
495 let sig_index = *info
496 .func_assoc
497 .get(func_index)
498 .expect("broken invariant, incorrect func index");
499
500 let signature = &info.signatures[sig_index];
501
502 let func_ptr = match func_index.local_or_import(info) {
503 LocalOrImport::Local(local_func_index) => {
504 runnable.get_func(info, local_func_index).unwrap()
505 }
506 LocalOrImport::Import(import_func_index) => {
507 NonNull::new(import_backing.vm_functions[import_func_index].func as *mut _).unwrap()
508 }
509 };
510
511 let ctx_ptr = match func_index.local_or_import(info) {
512 LocalOrImport::Local(_) => local_ctx,
513 LocalOrImport::Import(imported_func_index) => unsafe {
514 import_backing.vm_functions[imported_func_index]
515 .func_ctx
516 .as_ref()
517 }
518 .vmctx
519 .as_ptr(),
520 };
521
522 let wasm = runnable
523 .get_trampoline(info, sig_index)
524 .expect("wasm trampoline");
525
526 call_func_with_index_inner(ctx_ptr, func_ptr, signature, wasm, args, rets)
527}
528
529pub(crate) fn call_func_with_index_inner(
530 ctx_ptr: *mut vm::Ctx,
531 func_ptr: NonNull<vm::Func>,
532 signature: &FuncSig,
533 wasm: Wasm,
534 args: &[Value],
535 rets: &mut Vec<Value>,
536) -> CallResult<()> {
537 rets.clear();
538
539 let num_results = signature.returns().len();
540 let num_results = num_results
541 + signature
542 .returns()
543 .iter()
544 .filter(|&&ty| ty == Type::V128)
545 .count();
546 rets.reserve(num_results);
547
548 if !signature.check_param_value_types(args) {
549 Err(ResolveError::Signature {
550 expected: signature.clone(),
551 found: args.iter().map(|val| val.ty()).collect(),
552 })?
553 }
554
555 let mut raw_args: SmallVec<[u64; 8]> = SmallVec::new();
556 for v in args {
557 match v {
558 Value::I32(i) => {
559 raw_args.push(*i as u64);
560 }
561 Value::I64(i) => {
562 raw_args.push(*i as u64);
563 }
564 Value::F32(f) => {
565 raw_args.push(f.to_bits() as u64);
566 }
567 Value::F64(f) => {
568 raw_args.push(f.to_bits() as u64);
569 }
570 Value::V128(v) => {
571 let bytes = v.to_le_bytes();
572 let mut lo = [0u8; 8];
573 lo.clone_from_slice(&bytes[0..8]);
574 raw_args.push(u64::from_le_bytes(lo));
575 let mut hi = [0u8; 8];
576 hi.clone_from_slice(&bytes[8..16]);
577 raw_args.push(u64::from_le_bytes(hi));
578 }
579 }
580 }
581
582 let Wasm {
583 trampoline,
584 invoke,
585 invoke_env,
586 } = wasm;
587
588 let run_wasm = |result_space: *mut u64| -> CallResult<()> {
589 let mut error_out = None;
590
591 let success = unsafe {
592 invoke(
593 trampoline,
594 ctx_ptr,
595 func_ptr,
596 raw_args.as_ptr(),
597 result_space,
598 &mut error_out,
599 invoke_env,
600 )
601 };
602
603 if success {
604 Ok(())
605 } else {
606 let error: RuntimeError = error_out.map_or_else(
607 || RuntimeError::InvokeError(InvokeError::FailedWithNoError),
608 Into::into,
609 );
610 dbg!(&error);
611 Err(error.into())
612 }
613 };
614
615 let raw_to_value = |raw, ty| match ty {
616 Type::I32 => Value::I32(raw as i32),
617 Type::I64 => Value::I64(raw as i64),
618 Type::F32 => Value::F32(f32::from_bits(raw as u32)),
619 Type::F64 => Value::F64(f64::from_bits(raw)),
620 Type::V128 => unreachable!("V128 does not map to any single value"),
621 };
622
623 match signature.returns() {
624 &[] => {
625 run_wasm(ptr::null_mut())?;
626 Ok(())
627 }
628 &[Type::V128] => {
629 let mut result = [0u64; 2];
630
631 run_wasm(result.as_mut_ptr())?;
632
633 let mut bytes = [0u8; 16];
634 let lo = result[0].to_le_bytes();
635 let hi = result[1].to_le_bytes();
636 bytes[..8].clone_from_slice(&lo);
637 bytes[8..16].clone_from_slice(&hi);
638 rets.push(Value::V128(u128::from_le_bytes(bytes)));
639 Ok(())
640 }
641 &[ty] => {
642 let mut result = 0u64;
643
644 run_wasm(&mut result)?;
645
646 rets.push(raw_to_value(result, ty));
647
648 Ok(())
649 }
650 result_tys @ _ => {
651 let mut results: SmallVec<[u64; 8]> = smallvec![0; num_results];
652
653 run_wasm(results.as_mut_ptr())?;
654
655 rets.extend(
656 results
657 .iter()
658 .zip(result_tys.iter())
659 .map(|(&raw, &ty)| raw_to_value(raw, ty)),
660 );
661
662 Ok(())
663 }
664 }
665}
666
667pub struct DynFunc<'a> {
669 pub(crate) signature: Arc<FuncSig>,
670 module: &'a ModuleInner,
671 pub(crate) instance_inner: &'a InstanceInner,
672 func_index: FuncIndex,
673}
674
675impl<'a> DynFunc<'a> {
676 pub fn call(&self, params: &[Value]) -> CallResult<Vec<Value>> {
699 let mut results = Vec::new();
700
701 call_func_with_index(
702 &self.module.info,
703 &**self.module.runnable_module,
704 &self.instance_inner.import_backing,
705 self.instance_inner.vmctx,
706 self.func_index,
707 params,
708 &mut results,
709 )?;
710
711 Ok(results)
712 }
713
714 pub fn signature(&self) -> &FuncSig {
716 &*self.signature
717 }
718
719 pub fn raw(&self) -> *const vm::Func {
721 match self.func_index.local_or_import(&self.module.info) {
722 LocalOrImport::Local(local_func_index) => self
723 .module
724 .runnable_module
725 .get_func(&self.module.info, local_func_index)
726 .unwrap()
727 .as_ptr(),
728 LocalOrImport::Import(import_func_index) => {
729 self.instance_inner.import_backing.vm_functions[import_func_index].func
730 }
731 }
732 }
733}
734
735impl<'a> Exportable<'a> for Memory {
736 fn get_self(exports: &'a Exports, name: &str) -> ResolveResult<Self> {
737 let (inst_inner, module) = exports.get_inner();
738 let export_index =
739 module
740 .info
741 .exports
742 .get(name)
743 .ok_or_else(|| ResolveError::ExportNotFound {
744 name: name.to_string(),
745 })?;
746 if let ExportIndex::Memory(idx) = export_index {
747 Ok(inst_inner.get_memory_from_index(module, *idx))
748 } else {
749 Err(ResolveError::ExportWrongType {
750 name: name.to_string(),
751 })
752 }
753 }
754}
755
756impl<'a> Exportable<'a> for Table {
757 fn get_self(exports: &'a Exports, name: &str) -> ResolveResult<Self> {
758 let (inst_inner, module) = exports.get_inner();
759 let export_index =
760 module
761 .info
762 .exports
763 .get(name)
764 .ok_or_else(|| ResolveError::ExportNotFound {
765 name: name.to_string(),
766 })?;
767 if let ExportIndex::Table(idx) = export_index {
768 Ok(inst_inner.get_table_from_index(module, *idx))
769 } else {
770 Err(ResolveError::ExportWrongType {
771 name: name.to_string(),
772 })
773 }
774 }
775}
776
777impl<'a> Exportable<'a> for Global {
778 fn get_self(exports: &'a Exports, name: &str) -> ResolveResult<Self> {
779 let (inst_inner, module) = exports.get_inner();
780 let export_index =
781 module
782 .info
783 .exports
784 .get(name)
785 .ok_or_else(|| ResolveError::ExportNotFound {
786 name: name.to_string(),
787 })?;
788 if let ExportIndex::Global(idx) = export_index {
789 Ok(inst_inner.get_global_from_index(module, *idx))
790 } else {
791 Err(ResolveError::ExportWrongType {
792 name: name.to_string(),
793 })
794 }
795 }
796}
797
798impl<'a> Exportable<'a> for DynFunc<'a> {
799 fn get_self(exports: &'a Exports, name: &str) -> ResolveResult<Self> {
800 let (inst_inner, module) = exports.get_inner();
801 let func_index = resolve_func_index(module, name)?;
802
803 let sig_index = *module
804 .info
805 .func_assoc
806 .get(func_index)
807 .expect("broken invariant, incorrect func index");
808 let signature = SigRegistry.lookup_signature_ref(&module.info.signatures[sig_index]);
809
810 Ok(DynFunc {
811 signature,
812 module: &module,
813 instance_inner: &inst_inner,
814 func_index: func_index,
815 })
816 }
817}
818
819impl<'a, Args: WasmTypeList, Rets: WasmTypeList> Exportable<'a> for Func<'a, Args, Rets, Wasm> {
820 fn get_self(exports: &'a Exports, name: &str) -> ResolveResult<Self> {
821 let (inst_inner, module) = exports.get_inner();
822
823 let func_index = resolve_func_index(module, name)?;
824
825 let sig_index = *module
826 .info
827 .func_assoc
828 .get(func_index)
829 .expect("broken invariant, incorrect func index");
830 let signature = SigRegistry.lookup_signature_ref(&module.info.signatures[sig_index]);
831
832 if signature.params() != Args::types() || signature.returns() != Rets::types() {
833 Err(ResolveError::Signature {
834 expected: (*signature).clone(),
835 found: Args::types().to_vec(),
836 })?;
837 }
838
839 let ctx = match func_index.local_or_import(&module.info) {
840 LocalOrImport::Local(_) => inst_inner.vmctx,
841 LocalOrImport::Import(imported_func_index) => unsafe {
842 inst_inner.import_backing.vm_functions[imported_func_index]
843 .func_ctx
844 .as_ref()
845 }
846 .vmctx
847 .as_ptr(),
848 };
849
850 let func_wasm_inner = module
851 .runnable_module
852 .get_trampoline(&module.info, sig_index)
853 .unwrap();
854
855 let (func_ptr, func_env) = match func_index.local_or_import(&module.info) {
856 LocalOrImport::Local(local_func_index) => (
857 module
858 .runnable_module
859 .get_func(&module.info, local_func_index)
860 .unwrap(),
861 None,
862 ),
863 LocalOrImport::Import(import_func_index) => {
864 let imported_func = &inst_inner.import_backing.vm_functions[import_func_index];
865
866 (
867 NonNull::new(imported_func.func as *mut _).unwrap(),
868 unsafe { imported_func.func_ctx.as_ref() }.func_env,
869 )
870 }
871 };
872
873 let typed_func: Func<Args, Rets, Wasm> =
874 unsafe { Func::from_raw_parts(func_wasm_inner, func_ptr, func_env, ctx) };
875
876 Ok(typed_func)
877 }
878}
879
880pub struct Exports {
885 instance_inner: *const InstanceInner,
891 module: Arc<ModuleInner>,
892}
893
894unsafe impl Send for Exports {}
897
898impl Exports {
899 pub fn get<'a, T: Exportable<'a>>(&'a self, name: &str) -> ResolveResult<T> {
922 T::get_self(self, name)
923 }
924
925 fn get_inner(&self) -> (&InstanceInner, &ModuleInner) {
927 let inst_inner = unsafe { &*self.instance_inner };
928 let module = self.module.borrow();
929 (inst_inner, module)
930 }
931
932 pub fn into_iter(&self) -> ExportIter {
943 let (inst_inner, module) = self.get_inner();
944 ExportIter::new(&module, &inst_inner)
945 }
946}
947
948#[cfg(test)]
949mod test {
950 use super::*;
951
952 fn is_send<T: Send>() {}
953
954 #[test]
955 fn test_instance_is_send() {
956 is_send::<Instance>();
957 }
958}