Next Generation WASM Microkernel Operating System
at trap_handler 168 lines 6.0 kB view raw
1// Copyright 2025 Jonas Kruckenberg 2// 3// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or 4// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or 5// http://opensource.org/licenses/MIT>, at your option. This file may not be 6// copied, modified, or distributed except according to those terms. 7 8use crate::util::zip_eq::IteratorExt; 9use crate::wasm::indices::EntityIndex; 10use crate::wasm::module::Module; 11use crate::wasm::store::{StoreOpaque, Stored}; 12use crate::wasm::vm::{ConstExprEvaluator, Imports, InstanceHandle}; 13use crate::wasm::{Extern, Func, Global, Memory, Table}; 14use alloc::vec; 15use alloc::vec::Vec; 16 17/// An instantiated WebAssembly module. 18/// 19/// This is the main representation of all runtime state associated with a running WebAssembly module. 20/// 21/// # Instance and `VMContext` 22/// 23/// `Instance` and `VMContext` are essentially two halves of the same data structure. `Instance` is 24/// the privileged host-side half responsible for administrating execution, while `VMContext` holds the 25/// actual data that is accessed by compiled WASM code. 26#[derive(Debug, Clone, Copy)] 27#[repr(transparent)] 28pub struct Instance(Stored<InstanceData>); 29#[derive(Debug)] 30pub(super) struct InstanceData { 31 pub handle: InstanceHandle, 32 /// A lazily-populated list of exports of this instance. The order of 33 /// exports here matches the order of the exports in the original 34 /// module. 35 exports: Vec<Option<Extern>>, 36} 37 38#[derive(Clone)] 39pub struct Export<'instance> { 40 /// The name of the export. 41 pub name: &'instance str, 42 /// The definition of the export. 43 pub definition: Extern, 44} 45 46impl Instance { 47 /// Instantiates a new `Instance`. 48 /// 49 /// # Safety 50 /// 51 /// This functions assumes the provided `imports` have already been validated and typechecked for 52 /// compatibility with the `module` being instantiated. 53 pub(crate) unsafe fn new_unchecked( 54 store: &mut StoreOpaque, 55 const_eval: &mut ConstExprEvaluator, 56 module: Module, 57 imports: Imports, 58 ) -> crate::Result<Self> { 59 let mut handle = store.alloc_mut().allocate_module(module.clone())?; 60 61 let is_bulk_memory = module.required_features().bulk_memory(); 62 63 handle.initialize(store, const_eval, &module, imports, is_bulk_memory)?; 64 65 let stored = store.add_instance(InstanceData { 66 handle, 67 exports: vec![None; module.exports().len()], 68 }); 69 70 Ok(Self(stored)) 71 } 72 73 /// Returns the module this instance was instantiated from. 74 pub fn module(self, store: &StoreOpaque) -> &Module { 75 store[self.0].handle.module() 76 } 77 78 /// Returns an iterator over the exports of this instance. 79 pub(crate) fn exports( 80 self, 81 store: &mut StoreOpaque, 82 ) -> impl ExactSizeIterator<Item = Export<'_>> { 83 let exports = &store[self.0].exports; 84 85 if exports.iter().any(Option::is_none) { 86 let module = store[self.0].handle.module().clone(); 87 88 for name in module.translated().exports.keys() { 89 if let Some((export_name_index, _, &entity)) = 90 module.translated().exports.get_full(name) 91 { 92 self.get_export_inner(store, entity, export_name_index); 93 } 94 } 95 } 96 97 let instance = &store[self.0]; 98 let module = instance.handle.module(); 99 module 100 .translated() 101 .exports 102 .iter() 103 .zip_eq(&instance.exports) 104 .map(|((name, _), export)| Export { 105 name, 106 definition: export.clone().unwrap(), 107 }) 108 } 109 110 /// Attempts to get an export from this instance. 111 pub fn get_export(self, store: &mut StoreOpaque, name: &str) -> Option<Extern> { 112 let (export_name_index, _, index) = 113 self.module(store).translated().exports.get_full(name)?; 114 Some(self.get_export_inner(store, *index, export_name_index)) 115 } 116 117 /// Attempts to get an exported `Func` from this instance. 118 pub fn get_func(self, store: &mut StoreOpaque, name: &str) -> Option<Func> { 119 self.get_export(store, name)?.into_func() 120 } 121 122 /// Attempts to get an exported `Table` from this instance. 123 pub fn get_table(self, store: &mut StoreOpaque, name: &str) -> Option<Table> { 124 self.get_export(store, name)?.into_table() 125 } 126 127 /// Attempts to get an exported `Memory` from this instance. 128 pub fn get_memory(self, store: &mut StoreOpaque, name: &str) -> Option<Memory> { 129 self.get_export(store, name)?.into_memory() 130 } 131 132 /// Attempts to get an exported `Global` from this instance. 133 pub fn get_global(self, store: &mut StoreOpaque, name: &str) -> Option<Global> { 134 self.get_export(store, name)?.into_global() 135 } 136 137 fn get_export_inner( 138 self, 139 store: &mut StoreOpaque, 140 entity: EntityIndex, 141 export_name_index: usize, 142 ) -> Extern { 143 // Instantiated instances will lazily fill in exports, so we process 144 // all that lazy logic here. 145 let data = &store[self.0]; 146 147 if let Some(export) = &data.exports[export_name_index] { 148 return export.clone(); 149 } 150 151 let instance = &mut store[self.0]; // Reborrow the &mut InstanceHandle 152 // Safety: we just took `instance` from the store, so all its exports must also belong to the store 153 let item = 154 unsafe { Extern::from_export(instance.handle.get_export_by_index(entity), store) }; 155 let data = &mut store[self.0]; 156 data.exports[export_name_index] = Some(item.clone()); 157 item 158 } 159 160 pub(crate) fn comes_from_same_store(self, store: &StoreOpaque) -> bool { 161 store.has_instance(self.0) 162 } 163 164 /// Print a debug representation of this instances `VMContext` to the logger. 165 pub fn debug_vmctx(self, store: &StoreOpaque) { 166 store[self.0].handle.debug_vmctx(); 167 } 168}