Skip to content

Commit 951c807

Browse files
chore: remove LinearMemory trait (#53)
Signed-off-by: Henry <mail@henrygressmann.de>
1 parent 358a183 commit 951c807

37 files changed

Lines changed: 663 additions & 2009 deletions

‎ARCHITECTURE.md‎

Lines changed: 7 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# TinyWasm Architecture
22

3-
TinyWasm follows the general runtime model described in the [WebAssembly specification](https://webassembly.github.io/spec/core/exec/runtime.html). It is a stack-based interpreter with a compact internal bytecode, width-specific value stacks, and configurable linear-memory backends.
3+
TinyWasm follows the general runtime model described in the [WebAssembly specification](https://webassembly.github.io/spec/core/exec/runtime.html). It is a stack-based interpreter with a compact internal bytecode, width-specific value stacks, and a contiguous `Vec`-backed linear memory.
44

55
## Execution Pipeline
66

@@ -40,29 +40,20 @@ The default runtime remains safe Rust throughout rather than relying on unchecke
4040

4141
SIMD instructions have a portable safe-Rust implementation built from fixed-size arrays and lane operations, relying on the compiler to auto-vectorize where possible. Generated code is inspected with `cargo asm`, and benchmarks determine where architecture-specific alternatives are worthwhile. WebAssembly targets use native SIMD intrinsics where available, while the optional `simd-x86` feature provides selected x86 implementations for operations where the generic code produces worse results.
4242

43-
## Memory Backends
43+
## Linear Memory
4444

45-
Linear memory is implemented through the `LinearMemory` trait. The backend is selected with `engine::Config::with_memory_backend()`.
45+
Linear memory is a contiguous `Vec<u8>` allocation owned by a `MemoryInstance`. The interpreter accesses it through the internal `MemoryStorage` type, a small concrete boundary that keeps the `Vec` representation out of the executor so an mmap-backed storage can be substituted later without touching load and store paths.
4646

47-
`LinearMemory` exposes separate fixed-width read and write methods for 8-, 16-, 32-, 64-, and 128-bit accesses. A const-generic method would not be callable through a `dyn LinearMemory` trait object, so each width is an explicit vtable entry that backends can optimize independently.
47+
Fixed-width loads and stores use a single const-generic `read_fixed::<N>` / `write_fixed::<N>` pair rather than per-width vtable methods. Scalar operations reduce to an effective-address computation, a bounds check, a slice access, and a `from_le_bytes` / `to_le_bytes` conversion, with out-of-bounds construction kept on cold paths. Bulk operations such as `fill` and `copy_within` map directly to native slice methods.
4848

49-
This flexibility has a measurable cost: guest loads and stores cross the `dyn LinearMemory` boundary, adding an indirect call and generally preventing the backend operation from being inlined into the interpreter. The fixed-width methods keep the work behind that boundary as small and specialized as possible.
49+
Memory growth keeps the Wasm page count and limits on `MemoryInstance`. Before memory or table backing storage is allocated or resized, the configured `ResourceLimiter` is consulted so a host can bound guest resource consumption. The limiter is shared across the stores created from one `Engine` and lives behind an `Arc`.
5050

51-
Available backends:
52-
53-
- `VecMemory` - contiguous `Vec<u8>` backing and the default backend.
54-
- `PagedMemory` - sparse chunk-based allocation, with untouched chunks left unallocated and growth avoiding relocation of one contiguous buffer.
55-
- `LazyLinearMemory` - serves zero-filled reads without allocation and creates the configured backend on the first mutation or growth.
56-
- Custom backends through `MemoryBackend::custom()`.
57-
58-
`VecMemory` growth may reallocate, though operating-system allocators can often grow page-backed allocations without copying the full buffer. Applications on conventional operating systems should generally keep it unless sparse allocation or non-relocating growth is specifically needed. Bounded dynamic stacks and sparse paged memory trade some runtime overhead for a smaller initial footprint on embedded and other resource-constrained systems.
51+
For conventional operating systems, a future mmap-backed storage could reserve virtual address space and use guard pages to move more bounds enforcement to the operating system, reducing explicit checks in linear-memory hot paths. This is the same broad approach described in [Wasmtime's linear-memory architecture](https://docs.wasmtime.dev/contributing-architecture.html#linear-memory), where virtual-memory reservations and guard regions eliminate or deduplicate explicit bounds checks.
5952

6053
## Future Experiments
6154

6255
Future work may explore additional dispatch and code-generation strategies, including Rust's experimental `loop_match` state-machine work, a tail-call-based interpreter once Rust's explicit tail-call support matures, more aggressive superinstruction fusion, top-of-stack register allocation, or optional JIT compilation.
6356

64-
For conventional operating systems, a future `mmap`-based memory backend could reserve virtual address space and use guard pages to move more bounds enforcement to the operating system, reducing explicit checks in linear-memory hot paths. This is the same broad approach described in [Wasmtime's linear-memory architecture](https://docs.wasmtime.dev/contributing-architecture.html#linear-memory), where virtual-memory reservations and guard regions eliminate or deduplicate explicit bounds checks.
65-
6657
## Important Modules
6758

6859
- [visit.rs](./crates/parser/src/visit.rs) - function-body operator lowering
@@ -71,4 +62,4 @@ For conventional operating systems, a future `mmap`-based memory backend could r
7162
- [instructions.rs](./crates/types/src/instructions.rs) - internal instruction set
7263
- [value_stack.rs](./crates/tinywasm/src/interpreter/stack/value_stack.rs) - width-specific stacks
7364
- [call_stack.rs](./crates/tinywasm/src/interpreter/stack/call_stack.rs) - call frame stack
74-
- [memory/mod.rs](./crates/tinywasm/src/store/memory/mod.rs) - memory backend trait and implementations
65+
- [memory/mod.rs](./crates/tinywasm/src/store/memory/mod.rs) - linear memory storage

‎CHANGELOG.md‎

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1717
- Added `ValueLane` for mapping WebAssembly value types to their physical 32-bit, 64-bit, or 128-bit storage lane.
1818
- Added a `validate` feature to `tinywasm` and `tinywasm-parser` (enabled by default) to optionally skip wasmparser validation for faster parsing of trusted modules.
1919
- Added optional parse-time operand deduplication to reduce precompiled module and `.twasm` archive size.
20+
- Added a `ResourceLimiter` trait, configurable through `engine::Config::with_resource_limiter`, to bound guest memory and table allocation and growth.
2021

2122
### Changed
2223

@@ -25,14 +26,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
2526
- Typed function tuples now support up to 20 parameters or results. `WasmTupleChain` is deprecated. Use untyped functions for larger signatures.
2627
- Module types now use one dense recursive type space, while function types are resolved through `Function::ty(&Store)`.
2728
- Globals are stored in separate 32-bit, 64-bit, and 128-bit value lanes, avoiding tagged value conversion during guest execution.
28-
- `LinearMemory` mutation methods and custom memory-backend factories now return `Trap` errors so lazy backend failures can be propagated.
29+
- Linear memory now uses a single contiguous `Vec`-backed storage with const-generic fixed-width loads and stores.
30+
- Increased the minimum supported Rust version from 1.95 to 1.98.
2931

3032
### Fixed
3133

3234
- Directly defined imports now reject handles from a different `Store`.
3335
- Tail calls to host functions now return directly to the caller frame.
3436
- Fixed Memory64 bulk-memory operations and optimized stores using the wrong value-stack lane.
35-
- Fixed `memory.init` bounds checks, operand lowering, and local-memory allocation analysis.
37+
- Fixed `memory.init` bounds checks and operand lowering.
3638
- Fixed Memory64 default limits and host-size handling, including 32-bit targets.
3739

3840
### Breaking Changes
@@ -44,6 +46,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
4446
- Renamed `ModuleInstanceAddr` to `ModuleInstanceId`.
4547
- Removed `HostFunction::ty` and `WasmFunction::ty`. Use `Function::ty(&Store)` for runtime function types.
4648
- Changed `TableType::element_type` and `Element::ty` from `WasmType` to `RefType`, and replaced module `table_types` with `TableDefinition { ty, init }`.
49+
- Removed the pluggable memory backend system (`LinearMemory`, `MemoryBackend`, `VecMemory`, `PagedMemory`, `LazyLinearMemory`, and `Config::with_memory_backend`). Linear memory is always `Vec`-backed. To limit initial memory allocation and growth, configure a `ResourceLimiter` with `Config::with_resource_limiter`.
50+
- Removed the local-memory allocation analysis (`LocalMemoryAllocation` and `ParserOptions::optimize_local_memory_allocation`). Local memories are always allocated eagerly.
51+
- Removed `Config::with_trap_on_oom`. A `ResourceLimiter` can return a trap when rejecting a memory or table allocation or growth request.
52+
- `Table::grow` now returns `Result<Option<usize>>`, matching `Memory::grow`. Growth limits and allocation failures return `None`, while limiter-provided traps return an error.
4753

4854
## [0.10.0] - 2026-07-24
4955

‎Cargo.lock‎

Lines changed: 14 additions & 14 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎Cargo.toml‎

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ default-members = [".", "crates/parser", "crates/tinywasm", "crates/types"]
1313
[workspace.package]
1414
version = "0.11.0-pre.0"
1515
edition = "2024"
16-
rust-version = "1.95"
16+
rust-version = "1.98"
1717
repository = "https://github.com/explodingcamera/tinywasm"
1818
license = "MIT OR Apache-2.0"
1919
keywords = ["interpreter", "no-std", "tinywasm", "wasm", "webassembly"]
@@ -31,9 +31,9 @@ pretty_env_logger = "0.5"
3131
serde = { version = "1.0", features = ["derive"] }
3232
serde_json = { version = "1.0" }
3333
wasm-testsuite = { version = "0.7" }
34-
wasmparser = { version = "0.256", default-features = false }
35-
wast = "256"
36-
wat = "1.256"
34+
wasmparser = { version = "0.257", default-features = false }
35+
wast = "257"
36+
wat = "1.257"
3737

3838
criterion = { version = "0.8", default-features = false, features = ["cargo_bench_support", "rayon"] }
3939

@@ -57,10 +57,6 @@ name = "tinywasm"
5757
harness = false
5858
name = "tinywasm_modes"
5959

60-
[[bench]]
61-
harness = false
62-
name = "memory_backends"
63-
6460
[dev-dependencies]
6561
anyhow.workspace = true
6662
criterion.workspace = true

‎README.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ TinyWasm modules can be compiled to the internal `twasm` bytecode format, which
6161

6262
With default features disabled, `tinywasm` depends only on `core`, `alloc`, and `libm`[^libm], making it usable in `no_std + alloc` environments.
6363

64-
Use `Engine` and `engine::Config` when you need non-default runtime settings such as fuel accounting, stack sizing, memory backend selection, the GC collection threshold, or trap-on-OOM behavior.
64+
Use `Engine` and `engine::Config` when you need non-default runtime settings such as fuel accounting, stack sizing, or the GC collection threshold. A `ResourceLimiter` attached to the engine's config bounds guest memory and table allocation and growth and can trap rejected requests.
6565

6666
[^libm]: [rust-lang/rust#137578](https://github.com/rust-lang/rust/issues/137578) — tracking issue for floating-point math support in `no_std`.
6767

‎benches/memory_backends.rs‎

Lines changed: 0 additions & 151 deletions
This file was deleted.

0 commit comments

Comments
 (0)