Skip to content

Commit 27004a8

Browse files
docs: rework documentation, prepare pre-release
Signed-off-by: Henry <mail@henrygressmann.de>
1 parent 40bd20b commit 27004a8

20 files changed

Lines changed: 258 additions & 156 deletions

File tree

ARCHITECTURE.md

Lines changed: 55 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,62 @@
1-
# TinyWasm's Architecture
1+
# TinyWasm Architecture
22

3-
TinyWasm follows the general Runtime Structure described in the [WebAssembly Specification](https://webassembly.github.io/spec/core/exec/runtime.html).
3+
TinyWasm follows the general runtime model described in the [WebAssembly specification](https://webassembly.github.io/spec/core/exec/runtime.html), but lowers validated WebAssembly into a compact internal instruction format before execution.
44

5-
Key runtime layout:
5+
## Runtime Layout
66

7-
- Values are stored in four fixed-capacity typed stacks: `stack_32` (`i32`/`f32`/`funcref`/`externref`), `stack_64` (`i64`/`f64`), `stack_128` (`v128`)
8-
- Locals are allocated in those value stacks. Each `CallFrame` stores `locals_base`, and local ops index from that base.
9-
- Calls use a separate fixed-capacity `CallStack` of `CallFrame`s.
10-
- Structured control (`block`/`loop`/`if`/`br*`) is lowered during parsing to jump-oriented instructions: `Jump`, `JumpIfZero`, `BranchTable*`, `DropKeep*`, and `Return`.
11-
- The interpreter executes this lowered bytecode in a single iterative loop.
7+
- Values are stored in untyped stacks:
8+
- `stack_32` for `i32`, `f32`, `funcref`, and `externref`
9+
- `stack_64` for `i64` and `f64`
10+
- `stack_128` for `v128`
11+
- Locals are stored directly in the value stacks. Each `CallFrame` stores a `locals_base`, and local instructions index from that base.
12+
- Structured control flow (`block`, `loop`, `if`, `br*`) is lowered during parsing to jump-oriented internal instructions such as `Jump`, `JumpIfZero`, `BranchTable*`, `DropKeep*`, and `Return`.
13+
- Execution is a single iterative interpreter loop over the lowered instruction stream.
1214

13-
## Precompiled Modules
15+
## Internal Bytecode
1416

15-
Modules can be serialized to `.twasm` (`serialize_twasm`) and loaded later (`from_twasm`).
16-
This allows deployments that execute precompiled modules without enabling the parser in the runtime binary.
17+
TinyWasm does not interpret WebAssembly instructions directly. During parsing and validation, WebAssembly is translated into TinyWasm's internal bytecode format.
1718

18-
See:
19+
This internal representation is designed to make execution simpler and cheaper:
1920

20-
- [visit.rs](./crates/parser/src/visit.rs)
21-
- [instructions.rs](./crates/types/src/instructions.rs)
22-
- [value_stack.rs](./crates/tinywasm/src/interpreter/stack/value_stack.rs)
23-
- [call_stack.rs](./crates/tinywasm/src/interpreter/stack/call_stack.rs)
21+
- structured control flow is resolved ahead of time
22+
- stack effects are made explicit
23+
- common instruction sequences can be fused into superinstructions
24+
- modules can optionally be serialized as `.twasm` for reuse
25+
26+
## Optimizer
27+
28+
During parsing, a peephole optimizer (`optimize.rs`) fuses common instruction sequences into superinstructions. These reduce interpreter dispatch overhead by combining multiple logical operations into one internal instruction.
29+
30+
Examples include:
31+
32+
- **Fused binops**: `BinOpLocalLocal*`, `BinOpLocalConst*`, `BinOpStackGlobal*`
33+
Combine local/global access, a binary operation, and sometimes a store/tee.
34+
- **Fused jumps**: `JumpCmpLocalConst*`, `JumpCmpLocalLocal*`, `JumpCmpStackConst*`
35+
Combine comparison and conditional branch logic.
36+
37+
## Memory Backends
38+
39+
Linear memory is implemented through the `LinearMemory` trait. The backend is selected with `engine::Config::with_memory_backend()`.
40+
41+
Available backends:
42+
43+
- `VecMemory` - contiguous `Vec<u8>` backing; the default backend.
44+
- `PagedMemory` - chunk-based allocation, useful when growing memory without reallocating one large buffer.
45+
- `LazyLinearMemory` - wraps another backend and allocates memory on first access.
46+
- Custom backends through `MemoryBackend::custom()`.
47+
48+
## Future Experiments
49+
50+
TinyWasm's interpreter is intentionally simple today: validated WebAssembly is lowered to internal instructions, optimized with peephole fusion, and executed by an iterative dispatch loop.
51+
52+
Future work may explore additional dispatch and code-generation strategies, including Rust's experimental `loop_match` state-machine work, explicit tail calls, more aggressive superinstruction fusion, top-of-stack register allocation, or even optional JIT compilation.
53+
54+
## Code Map
55+
56+
- [visit.rs](./crates/parser/src/visit.rs) - WebAssembly binary visitor
57+
- [optimize.rs](./crates/parser/src/optimize.rs) - peephole optimizer and superinstruction fusion
58+
- [parallel.rs](./crates/parser/src/parallel.rs) - multithreaded function parsing
59+
- [instructions.rs](./crates/types/src/instructions.rs) - internal instruction set
60+
- [value_stack.rs](./crates/tinywasm/src/interpreter/stack/value_stack.rs) - typed value stacks
61+
- [call_stack.rs](./crates/tinywasm/src/interpreter/stack/call_stack.rs) - call frame stack
62+
- [memory/mod.rs](./crates/tinywasm/src/store/memory/mod.rs) - memory backend trait and implementations

CHANGELOG.md

Lines changed: 46 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -7,67 +7,62 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
This release is a major runtime and API rework. It adds support for several newer WebAssembly proposals, introduces the new `Engine` configuration API, rewrites large parts of execution and validation, and changes the internal `twasm` archive format. Benchmarks in the repository currently show roughly 30-90% improvement over 0.8.0 depending on workload and execution mode.
11+
1012
### Added
1113

1214
- Support for the `custom_page_sizes` proposal ([#22](https://github.com/explodingcamera/tinywasm/pull/22) by [@danielstuart14](https://github.com/danielstuart14))
13-
- Support for the `tail_call` proposal
14-
- Support for the `memory64` proposal
15-
- Support for the `simd` proposal
16-
- Support for the `relaxed_simd` proposal
17-
- Support for the `wide_arithmetic` proposal
15+
- Support for the `tail_call`, `memory64`, `simd`, `relaxed_simd`, `wide_arithmetic`, and `extended_const` proposals ([#37](https://github.com/explodingcamera/tinywasm/pull/37), [#38](https://github.com/explodingcamera/tinywasm/pull/38), [#39](https://github.com/explodingcamera/tinywasm/pull/39))
16+
- Parse-only support for the `annotations` proposal
1817
- New `Engine` API (`tinywasm::Engine` and `engine::Config`) for runtime configuration
19-
- Resumable function execution with fuel/time-budget APIs (`call_resumable`, `resume_with_fuel`, `resume_with_time_budget`, `ExecProgress`)
18+
- Resumable execution APIs: `call_resumable`, `resume_with_fuel`, `resume_with_time_budget`, and `ExecProgress`
2019
- Host-function fuel APIs: `FuncContext::charge_fuel` and `FuncContext::remaining_fuel`
21-
- `engine::FuelPolicy` and `engine::Config::fuel_policy` for fuel accounting behavior
22-
- New `canonicalize_nans` feature flag to enable canonicalizing NaN values in the `f32`, `f64`, and `v128` types
23-
- Public API rework for runtime object access:
24-
- export lookups: `func_untyped`/`func`, `memory`, `table`, `global`
25-
- table/global value access: `global_get`, `global_set`
26-
- generic export access: `extern_item` and `ExternItem`
27-
- export iteration: `ModuleInstance::exports`
28-
- module descriptors: `Module::imports`, `Module::exports`
29-
- handle-based runtime objects with explicit store access: `Memory`, `Table`, `Global`, `Function`
20+
- `engine::Config` support for fuel policy, stack sizing, memory backend selection, and trap-on-OOM behavior
21+
- New feature flags: `canonicalize-nans`, `simd-x86`, `guest-debug`, `debug`, and `parallel-parser`
22+
- Top-level parser re-exports behind the `parser` feature: `parse_bytes`, `parse_file`, and `parse_stream`
3023

3124
### Changed
3225

33-
- Locals are now stored in the typed value stacks instead of a separate locals structure
34-
- Structured control flow is fully lowered to jump-oriented internal instructions during parsing
35-
- Stack and call-stack limits can now be configured via `engine::Config`
36-
- Module-internal by-index inspection APIs are now gated behind the `guest_debug` feature
37-
38-
### Breaking Changes
39-
40-
- New backwards-incompatible version of the twasm format based on `postcard` (thanks [@dragonnn](https://github.com/dragonnn))
41-
- `RefNull` has been removed and replaced with new `FuncRef` and `ExternRef` structs
42-
- `Store::new` now takes an `Engine`; use `Store::default()` for default settings
43-
- `Error`, `Trap`, and `LinkingError` are now `#[non_exhaustive]`
44-
- `Trap` variant discriminant values changed (if you cast variants to integers)
45-
- `tinywasm::interpreter` is no longer a public module; `InterpreterRuntime` and `TinyWasmValue` are no longer public API
46-
- `FuncHandle::name` was removed
47-
- Cargo feature `simd` was removed
48-
- Cargo feature `tinywasm-parser` was renamed to`parser`
49-
- Cargo feature `logging` was renamed to `log`
50-
- Increased MSRV to 1.90
51-
- `Error::ParseError` was renamed to `Error::Parser`, and `Error::Twasm` was added
52-
- `ModuleInstance` export lookup APIs were renamed:
53-
- `exported_func_untyped` -> `func_untyped`
54-
- `exported_func` -> `func`
55-
- `exported_memory` -> `memory`
56-
- `ModuleInstance` mutable export lookup variants were removed:
57-
- `memory_mut`, `table_mut`, `global_mut`
58-
- `extern_item_mut`
59-
- `FuncHandle` / `FuncHandleTyped` were renamed to `Function` / `FunctionTyped`
60-
- `HostFunction::new` / `HostFunction::func` / `HostFunction::typed` now require `&mut Store`
61-
- `Imports::link_module` now takes a `ModuleInstance` instead of a raw module instance id
62-
- `func_typed` now validates the exact wasm signature at lookup time and fails immediately on mismatches
26+
- `Store::new` now takes an `Engine`; use `Store::default()` for default settings.
27+
- `ModuleInstance::func` now validates exact Wasm signatures at lookup time and fails immediately on mismatches.
28+
- Stack and call-stack limits now come from `engine::Config`, and memory allocation is lazy until first access.
29+
- Module-internal by-index inspection APIs are now gated behind `guest-debug`, and runtime `Debug` implementations are gated behind `debug`.
30+
- `Module` is now re-exported directly from `tinywasm_types`; the `module` submodule was removed.
31+
- MSRV increased to 1.95 and the crate now uses Rust 2024.
32+
- `Error`, `Trap`, and `LinkingError` are now `#[non_exhaustive]`.
33+
- `Trap` variant discriminants changed; do not rely on casting variants to integers.
34+
- `HostFunction::new`, `HostFunction::func`, and `HostFunction::typed` now require `&mut Store`, and `Imports::link_module` now takes a `ModuleInstance` instead of a raw module instance id.
35+
- Cargo features were renamed from `tinywasm-parser` to `parser` and from `logging` to `log`.
36+
- `Error::ParseError` was renamed to `Error::Parser`, and `Error::Twasm` was added.
37+
- `FuncHandle` and `FuncHandleTyped` were renamed to `Function` and `FunctionTyped`, and module export lookups moved from `exported_*` to `func_untyped`, `func`, and `memory`.
38+
- The `twasm` archive format is now postcard-based and backwards-incompatible with previous versions (thanks [@dragonnn](https://github.com/dragonnn)).
39+
- The interpreter was refactored around more superinstruction fusion, lower-overhead dispatch, typed-stack locals, jump-oriented lowering, and optional parallel parsing.
40+
41+
### Removed
42+
43+
- Cargo feature `simd` was removed.
44+
- `RefNull` was removed and replaced with `FuncRef` and `ExternRef`.
45+
- `tinywasm::interpreter` is no longer a public module.
46+
- `InterpreterRuntime` and `TinyWasmValue` are no longer public API.
47+
- `FuncHandle::name` was removed.
48+
- Mutable `ModuleInstance` export lookup variants `memory_mut`, `table_mut`, `global_mut`, and `extern_item_mut` were removed.
6349

6450
### Fixed
6551

66-
- Fixed archive **no_std** support which was broken in the previous release, and added more tests to ensure it stays working
67-
- `ModuleInstance::exported_memory` and `FuncContext::exported_memory` are now actually immutable ([#41](https://github.com/explodingcamera/tinywasm/pull/41))
68-
- Check returns in untyped host functions ([#27](https://github.com/explodingcamera/tinywasm/pull/27)) (thanks [@WhaleKit](https://github.com/WhaleKit))
69-
- `MemoryRefMut::copy_within(src, dst, len)` now follows its documented argument order
70-
- Imported tables created with `Extern::table(ty, init)` now honor the provided init value
52+
- Fixed archive **no_std** support, which was broken in the previous release, and added tests to ensure it stays working.
53+
- `ModuleInstance::memory` and `FuncContext::memory` are now actually immutable ([#41](https://github.com/explodingcamera/tinywasm/pull/41)).
54+
- Untyped host functions now check return values correctly ([#27](https://github.com/explodingcamera/tinywasm/pull/27)) by [@WhaleKit](https://github.com/WhaleKit).
55+
- `MemoryRefMut::copy_within(src, dst, len)` now follows its documented argument order.
56+
- Imported tables created with `Extern::table(ty, init)` now honor the provided init value.
57+
- Fixed unchecked memory offsets causing issues on 32-bit platforms.
58+
59+
### Migration Notes
60+
61+
- Replace `Store::new()` with `Store::default()` for default settings, or `Store::new(Engine::new(config))` for custom runtime configuration.
62+
- Rename the cargo features `tinywasm-parser` to `parser` and `logging` to `log`.
63+
- Rename `FuncHandle` to `Function` and `FuncHandleTyped` to `FunctionTyped`.
64+
- Rename module export lookups from `exported_*` methods to `func`, `func_untyped`, and `memory`.
65+
- Regenerate any persisted `twasm` archives; the format is now postcard-based and not backwards compatible with earlier releases.
7166

7267
## [0.8.0] - 2024-08-29
7368

@@ -184,7 +179,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
184179
- Lots of bug fixes
185180
- Full `no_std` support
186181

187-
## [0.3.0] - 2024-01-11
182+
## [0.2.0] - 2024-01-11
188183

189184
**All Commits**: https://github.com/explodingcamera/tinywasm/compare/v0.1.0...v0.2.0
190185

CONTRIBUTING.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ Example usage:
4848

4949
```bash
5050
cargo install --locked samply
51-
samply record -- cargo run --release --example wasm-rust -- selfhosted
51+
samply record -- cargo run --release --example wasm-rust -- tinywasm
5252
```
5353

5454
## Commits

Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@ edition="2024"
2424
license="MIT OR Apache-2.0"
2525
authors=["Henry Gressmann <crates@henrygressmann.de>"]
2626
repository="https://github.com/explodingcamera/tinywasm"
27-
categories=["wasm", "no-std"]
28-
keywords=["tinywasm"]
27+
categories=["wasm", "no-std", "compilers", "virtualization", "embedded"]
28+
keywords=["tinywasm", "wasm", "webassembly", "interpreter", "no-std"]
2929

3030
[package]
3131
name="tinywasm-root"

0 commit comments

Comments
 (0)