Skip to content

Commit

Permalink
chore: refactor module instances, fix named module tests
Browse files Browse the repository at this point in the history
Signed-off-by: Henry Gressmann <mail@henrygressmann.de>
  • Loading branch information
explodingcamera committed Jan 23, 2024
1 parent 4c1386b commit 3e71f86
Show file tree
Hide file tree
Showing 6 changed files with 53 additions and 39 deletions.
34 changes: 20 additions & 14 deletions crates/tinywasm/src/instance.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use alloc::{boxed::Box, format, string::ToString, sync::Arc, vec::Vec};
use alloc::{boxed::Box, format, string::ToString, sync::Arc};
use tinywasm_types::{
DataAddr, ElemAddr, Export, ExternVal, ExternalKind, FuncAddr, FuncType, GlobalAddr, Import, MemAddr,
ModuleInstanceAddr, TableAddr,
Expand All @@ -11,11 +11,11 @@ use crate::{

/// A WebAssembly Module Instance
///
/// Addrs are indices into the store's data structures.
/// Backed by an Arc, so cloning is cheap
///
/// See <https://webassembly.github.io/spec/core/exec/runtime.html#module-instances>
#[derive(Debug, Clone)]
pub struct ModuleInstance(pub(crate) Arc<ModuleInstanceInner>);
pub struct ModuleInstance(Arc<ModuleInstanceInner>);

#[allow(dead_code)]
#[derive(Debug)]
Expand All @@ -25,19 +25,24 @@ pub(crate) struct ModuleInstanceInner {

pub(crate) types: Box<[FuncType]>,

pub(crate) func_addrs: Vec<FuncAddr>,
pub(crate) table_addrs: Vec<TableAddr>,
pub(crate) mem_addrs: Vec<MemAddr>,
pub(crate) global_addrs: Vec<GlobalAddr>,
pub(crate) elem_addrs: Vec<ElemAddr>,
pub(crate) data_addrs: Vec<DataAddr>,
pub(crate) func_addrs: Box<[FuncAddr]>,
pub(crate) table_addrs: Box<[TableAddr]>,
pub(crate) mem_addrs: Box<[MemAddr]>,
pub(crate) global_addrs: Box<[GlobalAddr]>,
pub(crate) elem_addrs: Box<[ElemAddr]>,
pub(crate) data_addrs: Box<[DataAddr]>,

pub(crate) func_start: Option<FuncAddr>,
pub(crate) imports: Box<[Import]>,
pub(crate) exports: Box<[Export]>,
}

impl ModuleInstance {
// drop the module instance reference and swap it with another one
pub(crate) fn swap(&mut self, other: Self) {
self.0 = other.0;
}

/// Get the module instance's address
pub fn id(&self) -> ModuleInstanceAddr {
self.0.idx
Expand All @@ -57,6 +62,7 @@ impl ModuleInstance {
let mut addrs = imports.link(store, &module, idx)?;
let data = module.data;

// TODO: check if the compiler correctly optimizes this to prevent wasted allocations
addrs.globals.extend(store.init_globals(data.globals.into(), idx)?);
addrs.funcs.extend(store.init_funcs(data.funcs.into(), idx)?);
addrs.tables.extend(store.init_tables(data.table_types.into(), idx)?);
Expand All @@ -70,12 +76,12 @@ impl ModuleInstance {
idx,

types: data.func_types,
func_addrs: addrs.funcs,
table_addrs: addrs.tables,
mem_addrs: addrs.mems,
global_addrs: addrs.globals,
func_addrs: addrs.funcs.into_boxed_slice(),
table_addrs: addrs.tables.into_boxed_slice(),
mem_addrs: addrs.mems.into_boxed_slice(),
global_addrs: addrs.globals.into_boxed_slice(),
elem_addrs,
data_addrs,
data_addrs: data_addrs,
func_start: data.start_func,
imports: data.imports,
exports: data.exports,
Expand Down
6 changes: 3 additions & 3 deletions crates/tinywasm/src/runtime/executor/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,6 @@ impl DefaultRuntime {

let mut current_module = module;

// TODO: we might be able to index into the instructions directly
// since the instruction pointer should always be in bounds
while let Some(instr) = instrs.get(cf.instr_ptr) {
match exec_one(&mut cf, instr, instrs, stack, store, &current_module)? {
// Continue execution at the new top of the call stack
Expand All @@ -42,7 +40,7 @@ impl DefaultRuntime {
instrs = &wasm_func.instructions;

if cf.module != current_module.id() {
current_module = store.get_module_instance(cf.module).unwrap().clone()
current_module.swap(store.get_module_instance(cf.module).unwrap().clone());
}

continue;
Expand Down Expand Up @@ -168,6 +166,8 @@ fn exec_one(
let table_idx = module.resolve_table_addr(*table_addr);
let table = store.get_table(table_idx as usize)?;

// TODO: currently, the type resolution is subtlely broken for imported functions

let call_ty = module.func_ty(*type_addr);

let func_idx = stack.values.pop_t::<u32>()?;
Expand Down
13 changes: 8 additions & 5 deletions crates/tinywasm/src/store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use core::{
sync::atomic::{AtomicUsize, Ordering},
};

use alloc::{format, rc::Rc, string::ToString, vec, vec::Vec};
use alloc::{boxed::Box, format, rc::Rc, string::ToString, vec, vec::Vec};
use tinywasm_types::*;

use crate::{
Expand Down Expand Up @@ -180,7 +180,7 @@ impl Store {
table_addrs: &[TableAddr],
elems: Vec<Element>,
idx: ModuleInstanceAddr,
) -> Result<Vec<Addr>> {
) -> Result<Box<[Addr]>> {
let elem_count = self.data.elems.len();
let mut elem_addrs = Vec::with_capacity(elem_count);
for (i, elem) in elems.into_iter().enumerate() {
Expand Down Expand Up @@ -232,7 +232,8 @@ impl Store {
elem_addrs.push((i + elem_count) as Addr);
}

Ok(elem_addrs)
// this should be optimized out by the compiler
Ok(elem_addrs.into_boxed_slice())
}

/// Add data to the store, returning their addresses in the store
Expand All @@ -241,7 +242,7 @@ impl Store {
mem_addrs: &[MemAddr],
datas: Vec<Data>,
idx: ModuleInstanceAddr,
) -> Result<Vec<Addr>> {
) -> Result<Box<[Addr]>> {
let data_count = self.data.datas.len();
let mut data_addrs = Vec::with_capacity(data_count);
for (i, data) in datas.into_iter().enumerate() {
Expand Down Expand Up @@ -276,7 +277,9 @@ impl Store {
self.data.datas.push(DataInstance::new(data.data.to_vec(), idx));
data_addrs.push((i + data_count) as Addr);
}
Ok(data_addrs)

// this should be optimized out by the compiler
Ok(data_addrs.into_boxed_slice())
}

pub(crate) fn add_global(&mut self, ty: GlobalType, value: RawWasmValue, idx: ModuleInstanceAddr) -> Result<Addr> {
Expand Down
Loading

0 comments on commit 3e71f86

Please sign in to comment.