wasmer_runtime_core_fl/
instance.rs

1//! This module contains types for manipulating and accessing Wasm instances.
2//!
3//! An "instance", or "instantiated module", is a compiled WebAssembly [`Module`] with its
4//! corresponding imports (via [`ImportObject`]) that is ready to execute.
5use 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
38// manually implemented because InstanceInner contains a raw pointer to Ctx
39unsafe impl Send for InstanceInner {}
40
41impl Drop for InstanceInner {
42    fn drop(&mut self) {
43        // Drop the vmctx.
44        unsafe { Box::from_raw(self.vmctx) };
45    }
46}
47
48/// An instantiated WebAssembly module.
49///
50/// An `Instance` represents a WebAssembly module that
51/// has been instantiated with an [`ImportObject`] and is
52/// ready to be called.
53///
54/// [`ImportObject`]: struct.ImportObject.html
55pub struct Instance {
56    /// Reference to the module used to instantiate this instance.
57    pub module: Arc<ModuleInner>,
58    inner: Pin<Box<InstanceInner>>,
59    /// The exports of this instance.
60    pub exports: Exports,
61    #[allow(dead_code)]
62    /// Import object of the Instance.
63    pub import_object: ImportObject,
64}
65
66impl Instance {
67    pub(crate) fn new(module: Arc<ModuleInner>, imports: &ImportObject) -> Result<Instance> {
68        // We need the backing and import_backing to create a vm::Ctx, but we need
69        // a vm::Ctx to create a backing and an import_backing. The solution is to create an
70        // uninitialized vm::Ctx and then initialize it in-place.
71        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        // Initialize the vm::Ctx in-place after the backing
84        // has been boxed.
85        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            // We know that the start function takes no arguments and returns no values.
112            // Therefore, we can call it without doing any signature checking, etc.
113
114            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    /// Load an `Instance` using the given loader.
160    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    /// Through generic magic and the awe-inspiring power of traits, we bring you...
167    ///
168    /// # "Func"
169    ///
170    /// A [`Func`] allows you to call functions exported from wasm with
171    /// near zero overhead.
172    ///
173    /// [`Func`]: struct.Func.html
174    /// # Usage:
175    ///
176    /// ```
177    /// # use wasmer_runtime_core::{Func, Instance, error::ResolveResult};
178    /// # fn typed_func(instance: Instance) -> ResolveResult<()> {
179    /// let func: Func<(i32, i32)> = instance.func("foo")?;
180    ///
181    /// func.call(42, 43);
182    /// # Ok(())
183    /// # }
184    /// ```
185    #[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    /// Resolve a function by name.
198    pub fn resolve_func(&self, name: &str) -> ResolveResult<usize> {
199        resolve_func_index(&*self.module, name).map(|fi| fi.index())
200    }
201
202    /// This returns the representation of a function that can be called
203    /// safely.
204    ///
205    /// # Usage:
206    /// ```
207    /// # use wasmer_runtime_core::Instance;
208    /// # use wasmer_runtime_core::error::CallResult;
209    /// # fn call_foo(instance: &mut Instance) -> CallResult<()> {
210    /// instance
211    ///     .dyn_func("foo")?
212    ///     .call(&[])?;
213    /// # Ok(())
214    /// # }
215    /// ```
216    #[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    /// Call an exported WebAssembly function given the export name.
225    /// Pass arguments by wrapping each one in the [`Value`] enum.
226    /// The returned values are also each wrapped in a [`Value`].
227    ///
228    /// [`Value`]: enum.Value.html
229    ///
230    /// # Note:
231    /// This returns `CallResult<Vec<Value>>` in order to support
232    /// the future multi-value returns WebAssembly feature.
233    ///
234    /// Consider using the more explicit [`Exports::get`]` with [`DynFunc::call`]
235    /// instead. For example:
236    ///
237    /// ```
238    /// # use wasmer_runtime_core::types::Value;
239    /// # use wasmer_runtime_core::error::Result;
240    /// # use wasmer_runtime_core::Instance;
241    /// # use wasmer_runtime_core::DynFunc;
242    /// # fn call_foo(instance: &mut Instance) -> Result<()> {
243    /// // ...
244    /// let foo: DynFunc = instance.exports.get("foo")?;
245    /// let results = foo.call(&[Value::I32(42)])?;
246    /// // ...
247    /// # Ok(())
248    /// # }
249    /// ```
250    ///
251    /// # Usage:
252    /// ```
253    /// # use wasmer_runtime_core::types::Value;
254    /// # use wasmer_runtime_core::error::Result;
255    /// # use wasmer_runtime_core::Instance;
256    /// # fn call_foo(instance: &mut Instance) -> Result<()> {
257    /// // ...
258    /// let results = instance.call("foo", &[Value::I32(42)])?;
259    /// // ...
260    /// # Ok(())
261    /// # }
262    /// ```
263    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    /// Returns an immutable reference to the
269    /// [`Ctx`] used by this Instance.
270    ///
271    /// [`Ctx`]: struct.Ctx.html
272    pub fn context(&self) -> &vm::Ctx {
273        unsafe { &*self.inner.vmctx }
274    }
275
276    /// Returns a mutable reference to the
277    /// [`Ctx`] used by this Instance.
278    ///
279    /// [`Ctx`]: struct.Ctx.html
280    pub fn context_mut(&mut self) -> &mut vm::Ctx {
281        unsafe { &mut *self.inner.vmctx }
282    }
283
284    /// Returns an iterator over all of the items
285    /// exported from this instance.
286    pub fn exports(&self) -> ExportIter {
287        ExportIter::new(&self.module, &self.inner)
288    }
289
290    /// The module used to instantiate this Instance.
291    pub fn module(&self) -> Module {
292        Module::new(Arc::clone(&self.module))
293    }
294
295    /// Get the value of an internal field
296    pub fn get_internal(&self, field: &InternalField) -> u64 {
297        self.inner.backing.internals.0[field.index()]
298    }
299
300    /// Set the value of an internal field.
301    pub fn set_internal(&mut self, field: &InternalField, value: u64) {
302        self.inner.backing.internals.0[field.index()] = value;
303    }
304}
305
306/// Private function used to find the [`FuncIndex`] of a given export.
307fn 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
667/// A representation of an exported WebAssembly function.
668pub 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    /// Call an exported WebAssembly function safely.
677    ///
678    /// Pass arguments by wrapping each one in the [`Value`] enum.
679    /// The returned values are also each wrapped in a [`Value`].
680    ///
681    /// [`Value`]: enum.Value.html
682    ///
683    /// # Note:
684    /// This returns `CallResult<Vec<Value>>` in order to support
685    /// the future multi-value returns WebAssembly feature.
686    ///
687    /// # Usage:
688    /// ```
689    /// # use wasmer_runtime_core::Instance;
690    /// # use wasmer_runtime_core::error::CallResult;
691    /// # fn call_foo(instance: &mut Instance) -> CallResult<()> {
692    /// instance
693    ///     .dyn_func("foo")?
694    ///     .call(&[])?;
695    /// # Ok(())
696    /// # }
697    /// ```
698    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    /// Gets the signature of this `Dynfunc`.
715    pub fn signature(&self) -> &FuncSig {
716        &*self.signature
717    }
718
719    /// Gets a const pointer to the function represent by this `DynFunc`.
720    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
880/// `Exports` is used to get exports like [`Func`]s, [`DynFunc`]s, [`Memory`]s,
881/// [`Global`]s, and [`Table`]s from an [`Instance`].
882///
883/// Use `Instance.exports` to get an `Exports` from an [`Instance`].
884pub struct Exports {
885    // We want to avoid the borrow checker here.
886    // This is safe because
887    // 1. `Exports` can't be constructed, its fields inspected (directly or via methods),
888    //    or copied outside of this module/in Instance, so it can't safely outlive `Instance`.
889    // 2. `InstanceInner` is `Pin<Box<>>`, thus we know that it will not move.
890    instance_inner: *const InstanceInner,
891    module: Arc<ModuleInner>,
892}
893
894// this is safe because the lifetime of `Exports` is tied to `Instance` and
895// `*const InstanceInner` comes from a `Pin<Box<InstanceInner>>`
896unsafe impl Send for Exports {}
897
898impl Exports {
899    /// Get an export.
900    ///
901    /// ```
902    /// # use wasmer_runtime_core::{DynFunc, Func, Instance};
903    /// # use wasmer_runtime_core::global::Global;
904    /// # use wasmer_runtime_core::types::Value;
905    /// # use wasmer_runtime_core::error::ResolveResult;
906    /// # fn example_fn(instance: &Instance) -> ResolveResult<()> {
907    /// // We can get a function as a static `Func`
908    /// let func: Func<i32, i32> = instance.exports.get("my_func")?;
909    /// let _result = func.call(42);
910    ///
911    /// // Or we can get it as a dynamic `DynFunc`
912    /// let dyn_func: DynFunc = instance.exports.get("my_func")?;
913    /// let _result= dyn_func.call(&[Value::I32(42)]);
914    ///
915    /// // We can also get other exports like `Global`s, `Memory`s, and `Table`s
916    /// let _counter: Global = instance.exports.get("counter")?;
917    ///
918    /// # Ok(())
919    /// # }
920    /// ```
921    pub fn get<'a, T: Exportable<'a>>(&'a self, name: &str) -> ResolveResult<T> {
922        T::get_self(self, name)
923    }
924
925    /// This method must remain private for `Exports` to be sound.
926    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    /// Iterate the exports.
933    ///
934    /// ```
935    /// # use wasmer_runtime_core::instance::Instance;
936    /// # fn iterate_exports_example(instance: &Instance) {
937    /// for (export_name, export_value) in instance.exports.into_iter() {
938    ///    println!("Found export `{}` with value `{:?}`", export_name, export_value);
939    /// }
940    /// # }
941    /// ```
942    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}