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};
22#[cfg(unix)]
23use crate::{
24    fault::{pop_code_version, push_code_version},
25    state::CodeVersion,
26};
27use smallvec::{smallvec, SmallVec};
28use std::{
29    borrow::Borrow,
30    mem,
31    pin::Pin,
32    ptr::{self, NonNull},
33    sync::{Arc, Mutex},
34};
35
36pub(crate) struct InstanceInner {
37    #[allow(dead_code)]
38    pub(crate) backing: LocalBacking,
39    import_backing: ImportBacking,
40    pub(crate) vmctx: *mut vm::Ctx,
41    #[allow(dead_code)]
43    code_version_pushed: bool,
44}
45
46unsafe impl Send for InstanceInner {}
48
49impl Drop for InstanceInner {
50    fn drop(&mut self) {
51        unsafe { Box::from_raw(self.vmctx) };
53        #[cfg(unix)]
55        {
56            if self.code_version_pushed {
57                pop_code_version();
58            }
59        }
60    }
61}
62
63pub struct Instance {
71    pub module: Arc<ModuleInner>,
73    inner: Pin<Box<InstanceInner>>,
74    pub exports: Exports,
76    #[allow(dead_code)]
77    import_object: ImportObject,
78}
79
80impl Instance {
81    pub(crate) fn new(module: Arc<ModuleInner>, imports: &ImportObject) -> Result<Instance> {
82        let mut vmctx: Box<mem::MaybeUninit<vm::Ctx>> =
86            Box::new(mem::MaybeUninit::<vm::Ctx>::zeroed());
87
88        let import_backing = ImportBacking::new(&module, &imports, vmctx.as_mut_ptr())?;
89        let backing = LocalBacking::new(&module, &import_backing, vmctx.as_mut_ptr())?;
90
91        let mut inner = Box::pin(InstanceInner {
92            backing,
93            import_backing,
94            vmctx: vmctx.as_mut_ptr(),
95            code_version_pushed: false,
96        });
97
98        unsafe {
101            let backing = &mut *(&mut inner.backing as *mut _);
102            let import_backing = &mut *(&mut inner.import_backing as *mut _);
103            let real_ctx = match imports.call_state_creator() {
104                Some((data, dtor)) => {
105                    vm::Ctx::new_with_data(backing, import_backing, &module, data, dtor)
106                }
107                None => vm::Ctx::new(backing, import_backing, &module),
108            };
109            vmctx.as_mut_ptr().write(real_ctx);
110        };
111        Box::leak(vmctx);
112
113        let exports = Exports {
114            module: module.clone(),
115            instance_inner: &*inner as *const InstanceInner,
116        };
117
118        #[cfg(unix)]
121        {
122            let push_code_version_logic = || {
123                if let Some(msm) = module.runnable_module.get_module_state_map() {
124                    push_code_version(CodeVersion {
125                        baseline: true,
126                        msm,
127                        base: module.runnable_module.get_code()?.as_ptr() as usize,
128                        backend: match module.info.backend.as_ref() {
132                            "llvm" => "llvm",
133                            "cranelift" => "cranelift",
134                            "singlepass" => "singlepass",
135                            "auto" => "auto",
136                            _ => "unknown backend",
137                        },
138                        runnable_module: module.runnable_module.clone(),
139                    });
140                    Some(())
141                } else {
142                    None
143                }
144            };
145            inner.code_version_pushed = push_code_version_logic().is_some();
146        }
147
148        let instance = Instance {
149            module,
150            inner,
151            exports,
152            import_object: imports.clone(),
153        };
154
155        if let Some(start_index) = instance.module.info.start_func {
156            let func_ptr = match start_index.local_or_import(&instance.module.info) {
160                LocalOrImport::Local(local_func_index) => instance
161                    .module
162                    .runnable_module
163                    .get_func(&instance.module.info, local_func_index)
164                    .unwrap(),
165                LocalOrImport::Import(import_func_index) => NonNull::new(
166                    instance.inner.import_backing.vm_functions[import_func_index].func as *mut _,
167                )
168                .unwrap(),
169            };
170
171            let ctx_ptr = match start_index.local_or_import(&instance.module.info) {
172                LocalOrImport::Local(_) => instance.inner.vmctx,
173                LocalOrImport::Import(imported_func_index) => {
174                    instance.inner.import_backing.vm_functions[imported_func_index]
175                        .func_ctx
176                        .vmctx
177                        .as_ptr()
178                }
179            };
180
181            let sig_index = *instance
182                .module
183                .info
184                .func_assoc
185                .get(start_index)
186                .expect("broken invariant, incorrect func index");
187
188            let wasm_trampoline = instance
189                .module
190                .runnable_module
191                .get_trampoline(&instance.module.info, sig_index)
192                .expect("wasm trampoline");
193
194            let start_func: Func<(), (), Wasm> =
195                unsafe { Func::from_raw_parts(wasm_trampoline, func_ptr, None, ctx_ptr) };
196
197            start_func.call()?;
198        }
199
200        Ok(instance)
201    }
202
203    pub fn load<T: Loader>(&self, loader: T) -> ::std::result::Result<T::Instance, T::Error> {
205        loader.load(&**self.module.runnable_module, &self.module.info, unsafe {
206            &*self.inner.vmctx
207        })
208    }
209
210    #[deprecated(
230        since = "0.17.0",
231        note = "Please use `instance.exports.get(name)` instead"
232    )]
233    pub fn func<Args, Rets>(&self, name: &str) -> ResolveResult<Func<Args, Rets, Wasm>>
234    where
235        Args: WasmTypeList,
236        Rets: WasmTypeList,
237    {
238        self.exports.get(name)
239    }
240
241    pub fn resolve_func(&self, name: &str) -> ResolveResult<usize> {
243        resolve_func_index(&*self.module, name).map(|fi| fi.index())
244    }
245
246    #[deprecated(
261        since = "0.17.0",
262        note = "Please use `instance.exports.get(name)` instead"
263    )]
264    pub fn dyn_func(&self, name: &str) -> ResolveResult<DynFunc> {
265        self.exports.get(name)
266    }
267
268    pub fn call(&self, name: &str, params: &[Value]) -> CallResult<Vec<Value>> {
308        let func: DynFunc = self.exports.get(name)?;
309        func.call(params)
310    }
311
312    pub fn context(&self) -> &vm::Ctx {
317        unsafe { &*self.inner.vmctx }
318    }
319
320    pub fn context_mut(&mut self) -> &mut vm::Ctx {
325        unsafe { &mut *self.inner.vmctx }
326    }
327
328    pub fn exports(&self) -> ExportIter {
331        ExportIter::new(&self.module, &self.inner)
332    }
333
334    pub fn module(&self) -> Module {
336        Module::new(Arc::clone(&self.module))
337    }
338
339    pub fn get_internal(&self, field: &InternalField) -> u64 {
341        self.inner.backing.internals.0[field.index()]
342    }
343
344    pub fn set_internal(&mut self, field: &InternalField, value: u64) {
346        self.inner.backing.internals.0[field.index()] = value;
347    }
348}
349
350fn resolve_func_index(module: &ModuleInner, name: &str) -> ResolveResult<FuncIndex> {
352    let export_index =
353        module
354            .info
355            .exports
356            .map
357            .get(name)
358            .ok_or_else(|| ResolveError::ExportNotFound {
359                name: name.to_string(),
360            })?;
361
362    if let ExportIndex::Func(func_index) = export_index {
363        Ok(*func_index)
364    } else {
365        Err(ResolveError::ExportWrongType {
366            name: name.to_string(),
367        }
368        .into())
369    }
370}
371
372impl InstanceInner {
373    pub(crate) fn get_export_from_index(
374        &self,
375        module: &ModuleInner,
376        export_index: &ExportIndex,
377    ) -> Export {
378        match export_index {
379            ExportIndex::Func(func_index) => {
380                let (func, ctx, signature) = self.get_func_from_index(module, *func_index);
381
382                Export::Function {
383                    func,
384                    ctx: match ctx {
385                        Context::Internal => Context::External(self.vmctx),
386                        ctx @ Context::External(_) => ctx,
387                        ctx @ Context::ExternalWithEnv(_, _) => ctx,
388                    },
389                    signature,
390                }
391            }
392            ExportIndex::Memory(memory_index) => {
393                let memory = self.get_memory_from_index(module, *memory_index);
394                Export::Memory(memory)
395            }
396            ExportIndex::Global(global_index) => {
397                let global = self.get_global_from_index(module, *global_index);
398                Export::Global(global)
399            }
400            ExportIndex::Table(table_index) => {
401                let table = self.get_table_from_index(module, *table_index);
402                Export::Table(table)
403            }
404        }
405    }
406
407    fn get_func_from_index(
408        &self,
409        module: &ModuleInner,
410        func_index: FuncIndex,
411    ) -> (FuncPointer, Context, Arc<FuncSig>) {
412        let sig_index = *module
413            .info
414            .func_assoc
415            .get(func_index)
416            .expect("broken invariant, incorrect func index");
417
418        let (func_ptr, ctx) = match func_index.local_or_import(&module.info) {
419            LocalOrImport::Local(local_func_index) => (
420                module
421                    .runnable_module
422                    .get_func(&module.info, local_func_index)
423                    .expect("broken invariant, func resolver not synced with module.exports")
424                    .cast()
425                    .as_ptr() as *const _,
426                Context::Internal,
427            ),
428            LocalOrImport::Import(imported_func_index) => {
429                let imported_func = &self.import_backing.vm_functions[imported_func_index];
430                let func_ctx = &*imported_func.func_ctx;
431
432                (
433                    imported_func.func as *const _,
434                    Context::ExternalWithEnv(func_ctx.vmctx.as_ptr(), func_ctx.func_env),
435                )
436            }
437        };
438
439        let signature = SigRegistry.lookup_signature_ref(&module.info.signatures[sig_index]);
440
441        (unsafe { FuncPointer::new(func_ptr) }, ctx, signature)
442    }
443
444    fn get_memory_from_index(&self, module: &ModuleInner, mem_index: MemoryIndex) -> Memory {
445        match mem_index.local_or_import(&module.info) {
446            LocalOrImport::Local(local_mem_index) => self.backing.memories[local_mem_index].clone(),
447            LocalOrImport::Import(imported_mem_index) => {
448                self.import_backing.memories[imported_mem_index].clone()
449            }
450        }
451    }
452
453    fn get_global_from_index(&self, module: &ModuleInner, global_index: GlobalIndex) -> Global {
454        match global_index.local_or_import(&module.info) {
455            LocalOrImport::Local(local_global_index) => {
456                self.backing.globals[local_global_index].clone()
457            }
458            LocalOrImport::Import(import_global_index) => {
459                self.import_backing.globals[import_global_index].clone()
460            }
461        }
462    }
463
464    fn get_table_from_index(&self, module: &ModuleInner, table_index: TableIndex) -> Table {
465        match table_index.local_or_import(&module.info) {
466            LocalOrImport::Local(local_table_index) => {
467                self.backing.tables[local_table_index].clone()
468            }
469            LocalOrImport::Import(imported_table_index) => {
470                self.import_backing.tables[imported_table_index].clone()
471            }
472        }
473    }
474}
475
476impl LikeNamespace for Instance {
477    fn get_export(&self, name: &str) -> Option<Export> {
478        let export_index = self.module.info.exports.map.get(name)?;
479
480        Some(self.inner.get_export_from_index(&self.module, export_index))
481    }
482
483    fn get_exports(&self) -> Vec<(String, Export)> {
484        unimplemented!("Use the exports method instead");
485    }
486
487    fn maybe_insert(&mut self, _name: &str, _export: Export) -> Option<()> {
488        None
489    }
490}
491
492use std::rc::Rc;
493impl LikeNamespace for Rc<Instance> {
494    fn get_export(&self, name: &str) -> Option<Export> {
495        let export_index = self.module.info.exports.map.get(name)?;
496
497        Some(self.inner.get_export_from_index(&self.module, export_index))
498    }
499
500    fn get_exports(&self) -> Vec<(String, Export)> {
501        unimplemented!("Use the exports method instead");
502    }
503
504    fn maybe_insert(&mut self, _name: &str, _export: Export) -> Option<()> {
505        None
506    }
507}
508
509impl LikeNamespace for Arc<Mutex<Instance>> {
510    fn get_export(&self, name: &str) -> Option<Export> {
511        let instance = self.lock().unwrap();
512        let export_index = instance.module.info.exports.map.get(name)?;
513
514        Some(
515            instance
516                .inner
517                .get_export_from_index(&instance.module, export_index),
518        )
519    }
520
521    fn get_exports(&self) -> Vec<(String, Export)> {
522        unimplemented!("Use the exports method instead");
523    }
524
525    fn maybe_insert(&mut self, _name: &str, _export: Export) -> Option<()> {
526        None
527    }
528}
529
530#[must_use]
531fn call_func_with_index(
532    info: &ModuleInfo,
533    runnable: &dyn RunnableModule,
534    import_backing: &ImportBacking,
535    local_ctx: *mut vm::Ctx,
536    func_index: FuncIndex,
537    args: &[Value],
538    rets: &mut Vec<Value>,
539) -> CallResult<()> {
540    let sig_index = *info
541        .func_assoc
542        .get(func_index)
543        .expect("broken invariant, incorrect func index");
544
545    let signature = &info.signatures[sig_index];
546
547    let func_ptr = match func_index.local_or_import(info) {
548        LocalOrImport::Local(local_func_index) => {
549            runnable.get_func(info, local_func_index).unwrap()
550        }
551        LocalOrImport::Import(import_func_index) => {
552            NonNull::new(import_backing.vm_functions[import_func_index].func as *mut _).unwrap()
553        }
554    };
555
556    let ctx_ptr = match func_index.local_or_import(info) {
557        LocalOrImport::Local(_) => local_ctx,
558        LocalOrImport::Import(imported_func_index) => import_backing.vm_functions
559            [imported_func_index]
560            .func_ctx
561            .vmctx
562            .as_ptr(),
563    };
564
565    let wasm = runnable
566        .get_trampoline(info, sig_index)
567        .expect("wasm trampoline");
568
569    call_func_with_index_inner(ctx_ptr, func_ptr, signature, wasm, args, rets)
570}
571
572pub(crate) fn call_func_with_index_inner(
573    ctx_ptr: *mut vm::Ctx,
574    func_ptr: NonNull<vm::Func>,
575    signature: &FuncSig,
576    wasm: Wasm,
577    args: &[Value],
578    rets: &mut Vec<Value>,
579) -> CallResult<()> {
580    rets.clear();
581
582    let num_results = signature.returns().len();
583    let num_results = num_results
584        + signature
585            .returns()
586            .iter()
587            .filter(|&&ty| ty == Type::V128)
588            .count();
589    rets.reserve(num_results);
590
591    if !signature.check_param_value_types(args) {
592        Err(ResolveError::Signature {
593            expected: signature.clone(),
594            found: args.iter().map(|val| val.ty()).collect(),
595        })?
596    }
597
598    let mut raw_args: SmallVec<[u64; 8]> = SmallVec::new();
599    for v in args {
600        match v {
601            Value::I32(i) => {
602                raw_args.push(*i as u64);
603            }
604            Value::I64(i) => {
605                raw_args.push(*i as u64);
606            }
607            Value::F32(f) => {
608                raw_args.push(f.to_bits() as u64);
609            }
610            Value::F64(f) => {
611                raw_args.push(f.to_bits() as u64);
612            }
613            Value::V128(v) => {
614                let bytes = v.to_le_bytes();
615                let mut lo = [0u8; 8];
616                lo.clone_from_slice(&bytes[0..8]);
617                raw_args.push(u64::from_le_bytes(lo));
618                let mut hi = [0u8; 8];
619                hi.clone_from_slice(&bytes[8..16]);
620                raw_args.push(u64::from_le_bytes(hi));
621            }
622        }
623    }
624
625    let Wasm {
626        trampoline,
627        invoke,
628        invoke_env,
629    } = wasm;
630
631    let run_wasm = |result_space: *mut u64| -> CallResult<()> {
632        let mut error_out = None;
633
634        let success = unsafe {
635            invoke(
636                trampoline,
637                ctx_ptr,
638                func_ptr,
639                raw_args.as_ptr(),
640                result_space,
641                &mut error_out,
642                invoke_env,
643            )
644        };
645
646        if success {
647            Ok(())
648        } else {
649            let error: RuntimeError = error_out.map_or_else(
650                || RuntimeError::InvokeError(InvokeError::FailedWithNoError),
651                Into::into,
652            );
653            Err(error.into())
654        }
655    };
656
657    let raw_to_value = |raw, ty| match ty {
658        Type::I32 => Value::I32(raw as i32),
659        Type::I64 => Value::I64(raw as i64),
660        Type::F32 => Value::F32(f32::from_bits(raw as u32)),
661        Type::F64 => Value::F64(f64::from_bits(raw)),
662        Type::V128 => unreachable!("V128 does not map to any single value"),
663    };
664
665    match signature.returns() {
666        &[] => {
667            run_wasm(ptr::null_mut())?;
668            Ok(())
669        }
670        &[Type::V128] => {
671            let mut result = [0u64; 2];
672
673            run_wasm(result.as_mut_ptr())?;
674
675            let mut bytes = [0u8; 16];
676            let lo = result[0].to_le_bytes();
677            let hi = result[1].to_le_bytes();
678            bytes[..8].clone_from_slice(&lo);
679            bytes[8..16].clone_from_slice(&hi);
680            rets.push(Value::V128(u128::from_le_bytes(bytes)));
681            Ok(())
682        }
683        &[ty] => {
684            let mut result = 0u64;
685
686            run_wasm(&mut result)?;
687
688            rets.push(raw_to_value(result, ty));
689
690            Ok(())
691        }
692        result_tys @ _ => {
693            let mut results: SmallVec<[u64; 8]> = smallvec![0; num_results];
694
695            run_wasm(results.as_mut_ptr())?;
696
697            rets.extend(
698                results
699                    .iter()
700                    .zip(result_tys.iter())
701                    .map(|(&raw, &ty)| raw_to_value(raw, ty)),
702            );
703
704            Ok(())
705        }
706    }
707}
708
709pub struct DynFunc<'a> {
711    pub(crate) signature: Arc<FuncSig>,
712    module: &'a ModuleInner,
713    pub(crate) instance_inner: &'a InstanceInner,
714    func_index: FuncIndex,
715}
716
717impl<'a> DynFunc<'a> {
718    pub fn call(&self, params: &[Value]) -> CallResult<Vec<Value>> {
741        let mut results = Vec::new();
742
743        call_func_with_index(
744            &self.module.info,
745            &**self.module.runnable_module,
746            &self.instance_inner.import_backing,
747            self.instance_inner.vmctx,
748            self.func_index,
749            params,
750            &mut results,
751        )?;
752
753        Ok(results)
754    }
755
756    pub fn signature(&self) -> &FuncSig {
758        &*self.signature
759    }
760
761    pub fn raw(&self) -> *const vm::Func {
763        match self.func_index.local_or_import(&self.module.info) {
764            LocalOrImport::Local(local_func_index) => self
765                .module
766                .runnable_module
767                .get_func(&self.module.info, local_func_index)
768                .unwrap()
769                .as_ptr(),
770            LocalOrImport::Import(import_func_index) => {
771                self.instance_inner.import_backing.vm_functions[import_func_index].func
772            }
773        }
774    }
775}
776
777impl<'a> Exportable<'a> for Memory {
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                .map
785                .get(name)
786                .ok_or_else(|| ResolveError::ExportNotFound {
787                    name: name.to_string(),
788                })?;
789        if let ExportIndex::Memory(idx) = export_index {
790            Ok(inst_inner.get_memory_from_index(module, *idx))
791        } else {
792            Err(ResolveError::ExportWrongType {
793                name: name.to_string(),
794            })
795        }
796    }
797}
798
799impl<'a> Exportable<'a> for Table {
800    fn get_self(exports: &'a Exports, name: &str) -> ResolveResult<Self> {
801        let (inst_inner, module) = exports.get_inner();
802        let export_index =
803            module
804                .info
805                .exports
806                .map
807                .get(name)
808                .ok_or_else(|| ResolveError::ExportNotFound {
809                    name: name.to_string(),
810                })?;
811        if let ExportIndex::Table(idx) = export_index {
812            Ok(inst_inner.get_table_from_index(module, *idx))
813        } else {
814            Err(ResolveError::ExportWrongType {
815                name: name.to_string(),
816            })
817        }
818    }
819}
820
821impl<'a> Exportable<'a> for Global {
822    fn get_self(exports: &'a Exports, name: &str) -> ResolveResult<Self> {
823        let (inst_inner, module) = exports.get_inner();
824        let export_index =
825            module
826                .info
827                .exports
828                .map
829                .get(name)
830                .ok_or_else(|| ResolveError::ExportNotFound {
831                    name: name.to_string(),
832                })?;
833        if let ExportIndex::Global(idx) = export_index {
834            Ok(inst_inner.get_global_from_index(module, *idx))
835        } else {
836            Err(ResolveError::ExportWrongType {
837                name: name.to_string(),
838            })
839        }
840    }
841}
842
843impl<'a> Exportable<'a> for DynFunc<'a> {
844    fn get_self(exports: &'a Exports, name: &str) -> ResolveResult<Self> {
845        let (inst_inner, module) = exports.get_inner();
846        let func_index = resolve_func_index(module, name)?;
847
848        let sig_index = *module
849            .info
850            .func_assoc
851            .get(func_index)
852            .expect("broken invariant, incorrect func index");
853        let signature = SigRegistry.lookup_signature_ref(&module.info.signatures[sig_index]);
854
855        Ok(DynFunc {
856            signature,
857            module: &module,
858            instance_inner: &inst_inner,
859            func_index: func_index,
860        })
861    }
862}
863
864impl<'a, Args: WasmTypeList, Rets: WasmTypeList> Exportable<'a> for Func<'a, Args, Rets, Wasm> {
865    fn get_self(exports: &'a Exports, name: &str) -> ResolveResult<Self> {
866        let (inst_inner, module) = exports.get_inner();
867
868        let func_index = resolve_func_index(module, name)?;
869
870        let sig_index = *module
871            .info
872            .func_assoc
873            .get(func_index)
874            .expect("broken invariant, incorrect func index");
875        let signature = SigRegistry.lookup_signature_ref(&module.info.signatures[sig_index]);
876
877        if signature.params() != Args::types() || signature.returns() != Rets::types() {
878            Err(ResolveError::Signature {
879                expected: (*signature).clone(),
880                found: Args::types().to_vec(),
881            })?;
882        }
883
884        let ctx = match func_index.local_or_import(&module.info) {
885            LocalOrImport::Local(_) => inst_inner.vmctx,
886            LocalOrImport::Import(imported_func_index) => inst_inner.import_backing.vm_functions
887                [imported_func_index]
888                .func_ctx
889                .vmctx
890                .as_ptr(),
891        };
892
893        let func_wasm_inner = module
894            .runnable_module
895            .get_trampoline(&module.info, sig_index)
896            .unwrap();
897
898        let (func_ptr, func_env) = match func_index.local_or_import(&module.info) {
899            LocalOrImport::Local(local_func_index) => (
900                module
901                    .runnable_module
902                    .get_func(&module.info, local_func_index)
903                    .unwrap(),
904                None,
905            ),
906            LocalOrImport::Import(import_func_index) => {
907                let imported_func = &inst_inner.import_backing.vm_functions[import_func_index];
908
909                (
910                    NonNull::new(imported_func.func as *mut _).unwrap(),
911                    imported_func.func_ctx.func_env,
912                )
913            }
914        };
915
916        let typed_func: Func<Args, Rets, Wasm> =
917            unsafe { Func::from_raw_parts(func_wasm_inner, func_ptr, func_env, ctx) };
918
919        Ok(typed_func)
920    }
921}
922
923pub struct Exports {
928    instance_inner: *const InstanceInner,
934    module: Arc<ModuleInner>,
935}
936
937unsafe impl Send for Exports {}
940
941impl Exports {
942    pub fn get<'a, T: Exportable<'a>>(&'a self, name: &str) -> ResolveResult<T> {
965        T::get_self(self, name)
966    }
967
968    fn get_inner(&self) -> (&InstanceInner, &ModuleInner) {
970        let inst_inner = unsafe { &*self.instance_inner };
971        let module = self.module.borrow();
972        (inst_inner, module)
973    }
974
975    pub fn into_iter(&self) -> ExportIter {
986        let (inst_inner, module) = self.get_inner();
987        ExportIter::new(&module, &inst_inner)
988    }
989}
990
991#[cfg(test)]
992mod test {
993    use super::*;
994
995    fn is_send<T: Send>() {}
996
997    #[test]
998    fn test_instance_is_send() {
999        is_send::<Instance>();
1000    }
1001}