summaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
authorHenry Gressmann <mail@henrygressmann.de>2023-12-04 17:01:05 +0100
committerHenry Gressmann <mail@henrygressmann.de>2023-12-04 17:01:05 +0100
commitcff17ced4464acb6b0b4af96f093653c1eb24da0 (patch)
treeabc447af17c2585b9e3fb511261f3f9bbfe59835 /crates
parent767ea3207a7919d69e95791d2bdc71f9fa22cfe3 (diff)
feat: add store ids
Signed-off-by: Henry Gressmann <mail@henrygressmann.de>
Diffstat (limited to 'crates')
-rw-r--r--crates/cli/Cargo.toml2
-rw-r--r--crates/tinywasm/src/error.rs3
-rw-r--r--crates/tinywasm/src/instance.rs17
-rw-r--r--crates/tinywasm/src/module.rs1
-rw-r--r--crates/tinywasm/src/store.rs44
5 files changed, 60 insertions, 7 deletions
diff --git a/crates/cli/Cargo.toml b/crates/cli/Cargo.toml
index 60c3ad8..d34aeff 100644
--- a/crates/cli/Cargo.toml
+++ b/crates/cli/Cargo.toml
@@ -12,7 +12,7 @@ path="src/bin.rs"
[dependencies]
tinywasm={path="../tinywasm"}
argh="0.1"
-color-eyre={default-features=false}
+color-eyre={version="0.6", default-features=false}
log="0.4"
pretty_env_logger="0.5"
wast={version="69.0", optional=true}
diff --git a/crates/tinywasm/src/error.rs b/crates/tinywasm/src/error.rs
index 084a49c..82f00b9 100644
--- a/crates/tinywasm/src/error.rs
+++ b/crates/tinywasm/src/error.rs
@@ -11,6 +11,8 @@ pub enum Error {
FuncDidNotReturn,
StackUnderflow,
+ InvalidStore,
+
#[cfg(feature = "std")]
Io(crate::std::io::Error),
}
@@ -23,6 +25,7 @@ impl Display for Error {
Self::ParseError(err) => write!(f, "error parsing module: {:?}", err),
Self::UnsupportedFeature(feature) => write!(f, "unsupported feature: {}", feature),
Self::Other(message) => write!(f, "unknown error: {}", message),
+ Self::InvalidStore => write!(f, "invalid store"),
#[cfg(feature = "std")]
Self::Io(err) => write!(f, "I/O error: {}", err),
}
diff --git a/crates/tinywasm/src/instance.rs b/crates/tinywasm/src/instance.rs
index c90cec6..598dba1 100644
--- a/crates/tinywasm/src/instance.rs
+++ b/crates/tinywasm/src/instance.rs
@@ -3,17 +3,20 @@ use tinywasm_types::{Export, FuncAddr, FuncType, ModuleInstanceAddr};
use crate::{
func::{FromWasmValueTuple, IntoWasmValueTuple},
- ExportInstance, FuncHandle, Result, Store, TypedFuncHandle,
+ Error, ExportInstance, FuncHandle, Result, Store, TypedFuncHandle,
};
-/// A WebAssembly Module Instance.
+/// A WebAssembly Module Instance
+///
/// Addrs are indices into the store's data structures.
+///
/// See https://webassembly.github.io/spec/core/exec/runtime.html#module-instances
#[derive(Debug, Clone)]
pub struct ModuleInstance(Arc<ModuleInstanceInner>);
#[derive(Debug)]
struct ModuleInstanceInner {
+ pub(crate) store_id: usize,
pub(crate) _idx: ModuleInstanceAddr,
pub(crate) func_start: Option<FuncAddr>,
pub(crate) types: Box<[FuncType]>,
@@ -34,8 +37,10 @@ impl ModuleInstance {
exports: Box<[Export]>,
func_addrs: Vec<FuncAddr>,
idx: ModuleInstanceAddr,
+ store_id: usize,
) -> Self {
Self(Arc::new(ModuleInstanceInner {
+ store_id,
_idx: idx,
types,
func_start,
@@ -46,6 +51,10 @@ impl ModuleInstance {
/// Get an exported function by name
pub fn get_func(&self, store: &Store, name: &str) -> Result<FuncHandle> {
+ if self.0.store_id != store.id() {
+ return Err(Error::InvalidStore);
+ }
+
let export = self.0.exports.func(name)?;
let func_addr = self.0.func_addrs[export.index as usize];
let func = store.get_func(func_addr as usize)?;
@@ -78,6 +87,10 @@ impl ModuleInstance {
/// (which is not part of the spec, but used by llvm)
/// https://webassembly.github.io/spec/core/syntax/modules.html#start-function
pub fn get_start_func(&mut self, store: &Store) -> Result<Option<FuncHandle>> {
+ if self.0.store_id != store.id() {
+ return Err(Error::InvalidStore);
+ }
+
let func_index = match self.0.func_start {
Some(func_index) => func_index,
None => {
diff --git a/crates/tinywasm/src/module.rs b/crates/tinywasm/src/module.rs
index 8e258fd..04320a2 100644
--- a/crates/tinywasm/src/module.rs
+++ b/crates/tinywasm/src/module.rs
@@ -52,6 +52,7 @@ impl Module {
self.data.exports,
func_addrs,
idx,
+ store.id(),
);
store.add_instance(instance.clone())?;
diff --git a/crates/tinywasm/src/store.rs b/crates/tinywasm/src/store.rs
index a74163e..0e73ece 100644
--- a/crates/tinywasm/src/store.rs
+++ b/crates/tinywasm/src/store.rs
@@ -1,13 +1,25 @@
+use core::sync::atomic::{AtomicUsize, Ordering};
+
use alloc::{format, vec::Vec};
use tinywasm_types::{FuncAddr, Function, Instruction, ModuleInstanceAddr, TypeAddr, ValType};
use crate::{runtime::Runtime, Error, ModuleInstance, Result};
-/// global state that can be manipulated by WebAssembly programs
-/// data should only be addressable by the module that owns it
-/// https://webassembly.github.io/spec/core/exec/runtime.html#store
-#[derive(Debug, Default)]
+// global store id counter
+static STORE_ID: AtomicUsize = AtomicUsize::new(0);
+
+/// Global state that can be manipulated by WebAssembly programs
+///
+/// Data should only be addressable by the module that owns it
+///
+/// Note that the state doesn't do any garbage collection - so it will grow
+/// indefinitely if you keep adding modules to it. When calling temporary
+/// functions, you should create a new store and then drop it when you're done (e.g. in a request handler)
+///
+/// See also: https://webassembly.github.io/spec/core/exec/runtime.html#store
+#[derive(Debug)]
pub struct Store {
+ id: usize,
module_instances: Vec<ModuleInstance>,
module_instance_count: usize,
@@ -15,6 +27,26 @@ pub struct Store {
pub(crate) runtime: Runtime,
}
+impl PartialEq for Store {
+ fn eq(&self, other: &Self) -> bool {
+ self.id == other.id
+ }
+}
+
+impl Default for Store {
+ fn default() -> Self {
+ let id = STORE_ID.fetch_add(1, Ordering::Relaxed);
+
+ Self {
+ id,
+ module_instances: Vec::new(),
+ module_instance_count: 0,
+ data: StoreData::default(),
+ runtime: Runtime::default(),
+ }
+ }
+}
+
#[derive(Debug)]
pub struct FunctionInstance {
pub(crate) func: Function,
@@ -50,6 +82,10 @@ pub struct StoreData {
}
impl Store {
+ pub fn id(&self) -> usize {
+ self.id
+ }
+
pub(crate) fn next_module_instance_idx(&self) -> ModuleInstanceAddr {
self.module_instance_count as ModuleInstanceAddr
}