Next Generation WASM Microkernel Operating System
at trap_handler 166 lines 5.4 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::wasm::indices::DefinedTableIndex; 9use crate::wasm::store::{StoreOpaque, Stored}; 10use crate::wasm::types::TableType; 11use crate::wasm::values::Ref; 12use crate::wasm::vm::{ExportedTable, InstanceAndStore, TableElement, VMTableImport, VmPtr}; 13use crate::wasm::{Func, vm}; 14use anyhow::Context; 15use core::ptr::NonNull; 16use core::sync::atomic::Ordering; 17use cranelift_entity::packed_option::ReservedValue; 18 19#[derive(Clone, Copy, Debug)] 20pub struct Table(Stored<ExportedTable>); 21 22impl Table { 23 pub fn new(store: &mut StoreOpaque, ty: TableType, init: Ref) -> crate::Result<Table> { 24 let wasm_ty = ty.to_wasm_table(); 25 26 // Safety: TODO 27 let mut t = unsafe { 28 store 29 .alloc_mut() 30 .allocate_table(wasm_ty, DefinedTableIndex::reserved_value())? 31 }; 32 33 let init = init.into_table_element(store, ty.element())?; 34 t.fill(0, init, ty.minimum())?; 35 36 let definition = store.add_host_table(t); 37 38 let stored = store.add_table(ExportedTable { 39 definition, 40 vmctx: store.default_caller(), 41 table: wasm_ty.clone(), 42 }); 43 Ok(Self(stored)) 44 } 45 46 pub fn ty(self, store: &StoreOpaque) -> TableType { 47 let export = &store[self.0]; 48 TableType::from_wasm_table(store.engine(), &export.table) 49 } 50 51 pub fn get(self, store: &mut StoreOpaque, index: u64) -> Option<Ref> { 52 // Safety: TODO 53 let table = unsafe { self.vmtable(store).as_mut() }; 54 let element = table.get(index)?; 55 56 match element { 57 TableElement::FuncRef(Some(func_ref)) => { 58 // Safety: TODO 59 let f = unsafe { Func::from_vm_func_ref(store, func_ref) }; 60 Some(Ref::Func(Some(f))) 61 } 62 TableElement::FuncRef(None) => Some(Ref::Func(None)), 63 } 64 } 65 66 pub fn set(self, store: &mut StoreOpaque, index: u64, val: Ref) -> crate::Result<()> { 67 let ty = self.ty(store); 68 let val = val.into_table_element(store, ty.element())?; 69 // Safety: TODO 70 let table = unsafe { self.vmtable(store).as_mut() }; 71 table.set(index, val)?; 72 73 Ok(()) 74 } 75 76 pub fn size(self, store: &StoreOpaque) -> u64 { 77 // Safety: TODO 78 unsafe { 79 u64::try_from( 80 store[self.0] 81 .definition 82 .as_ref() 83 .current_elements 84 .load(Ordering::Relaxed), 85 ) 86 .unwrap() 87 } 88 } 89 90 pub fn grow(self, store: &mut StoreOpaque, delta: u64, init: Ref) -> crate::Result<u64> { 91 let ty = self.ty(store); 92 let init = init.into_table_element(store, ty.element())?; 93 // Safety: TODO 94 let table = unsafe { self.vmtable(store).as_mut() }; 95 let old_size = table.grow(delta, init)?.context("failed to grow table")?; 96 Ok(u64::try_from(old_size).unwrap()) 97 } 98 99 pub fn copy( 100 store: &mut StoreOpaque, 101 dst_table: &Table, 102 dst_index: u64, 103 src_table: &Table, 104 src_index: u64, 105 len: u64, 106 ) -> crate::Result<()> { 107 let dst_ty = dst_table.ty(store); 108 let src_ty = src_table.ty(store); 109 110 src_ty 111 .element() 112 .ensure_matches(store.engine(), dst_ty.element()) 113 .context( 114 "type mismatch: source table's element type does not match \ 115 destination table's element type", 116 )?; 117 118 let dst_table = dst_table.vmtable(store); 119 let src_table = src_table.vmtable(store); 120 121 vm::Table::copy( 122 dst_table.as_ptr(), 123 src_table.as_ptr(), 124 dst_index, 125 src_index, 126 len, 127 )?; 128 129 Ok(()) 130 } 131 132 pub fn fill(self, store: &mut StoreOpaque, dst: u64, val: Ref, len: u64) -> crate::Result<()> { 133 let ty = self.ty(store); 134 let val = val.into_table_element(store, ty.element())?; 135 // Safety: TODO 136 let table = unsafe { self.vmtable(store).as_mut() }; 137 table.fill(dst, val, len)?; 138 139 Ok(()) 140 } 141 142 pub(super) fn from_exported_table(store: &mut StoreOpaque, export: ExportedTable) -> Self { 143 let stored = store.add_table(export); 144 Self(stored) 145 } 146 pub(super) fn vmtable(self, store: &mut StoreOpaque) -> NonNull<vm::Table> { 147 let ExportedTable { 148 definition, vmctx, .. 149 } = store[self.0]; 150 // Safety: TODO 151 unsafe { 152 InstanceAndStore::from_vmctx(vmctx, |pair| { 153 let (instance, _) = pair.unpack_mut(); 154 let def_index = instance.table_index(definition.as_ref()); 155 instance.get_defined_table(def_index) 156 }) 157 } 158 } 159 pub(super) fn as_vmtable_import(self, store: &mut StoreOpaque) -> VMTableImport { 160 let export = &store[self.0]; 161 VMTableImport { 162 from: VmPtr::from(export.definition), 163 vmctx: VmPtr::from(export.vmctx), 164 } 165 } 166}