Skip to content

Commit c67ce64

Browse files
feat: add nightly tail-call interpreter dispatch
Signed-off-by: Henry <mail@henrygressmann.de>
1 parent bb17468 commit c67ce64

16 files changed

Lines changed: 2577 additions & 2318 deletions

File tree

.github/workflows/test.yaml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,10 @@ jobs:
5454
- os: ubuntu-latest
5555
rust: nightly
5656
name: "Linux x86 (nightly)"
57+
- os: ubuntu-latest
58+
rust: nightly
59+
name: "Linux x86 (nightly tail calls)"
60+
args: "--features tinywasm/nightly-tail-calls"
5761
- os: ubuntu-latest
5862
rust: stable
5963
name: "Linux x86 (stable, no default features)"
@@ -62,6 +66,10 @@ jobs:
6266
rust: nightly
6367
name: "Linux x86 (nightly, no default features)"
6468
args: "--no-default-features"
69+
- os: ubuntu-latest
70+
rust: nightly
71+
name: "Linux x86 (nightly tail calls, no default features)"
72+
args: "--no-default-features --features tinywasm/nightly-tail-calls"
6573
- os: macos-14
6674
rust: stable
6775
name: "macOS arm64 (Apple M1)"

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1515
- Optional parse-time operand deduplication to reduce `.twasm` archive size
1616
- Optional `send` support for moving stores and store-local handles across threads
1717
- Optional portable atomic shared pointers and counters for targets without native compare-and-swap
18+
- Optional `nightly-tail-calls` backend using Rust's unstable explicit tail calls for interpreter dispatch
1819

1920
### Changed
2021

README.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,15 +50,17 @@ See the [examples](./examples) directory and [documentation](https://docs.rs/tin
5050

5151
- **`full`:** Enables `archive`, `parallel-parser`, `parser`, and `validate`. Enabled by default.
5252
- **`std`:** Enables `std` and parsing from files and streams. Enabled by default.
53-
- **`log`:** Enables integration with the `log` crate. Enabled by default.
5453
- **`parser`:** Enables `tinywasm-parser` and top-level parse helpers. Enabled by default.
5554
- **`validate`:** Enables WebAssembly validation while parsing. Enabled by default and configurable through [`ParserOptions`](https://docs.rs/tinywasm/latest/tinywasm/parser/struct.ParserOptions.html).
55+
- **`parallel-parser`:** Parallelizes function parsing when `std` is enabled. Enabled by default.
5656
- **`archive`:** Enables serialization and deserialization of the internal `twasm` format. Enabled by default.
57+
- **`log`:** Enables integration with the `log` crate. Enabled by default.
58+
- **`send`:** Makes stores and store-local handles movable across threads.
59+
- **`portable-atomic`:** Supports targets without native atomic compare-and-swap.
5760
- **`canonicalize-nans`:** Uses a [canonical NaN](https://en.wikipedia.org/wiki/NaN#Canonical_NaN) for normalized NaN results. Enabled by default.
5861
- **`debug`:** Derives `Debug` for runtime types. Enabled by default.
59-
- **`parallel-parser`:** Parallelizes function parsing when `std` is enabled. Enabled by default.
6062
- **`guest-debug`:** Exposes module-internal by-index inspection APIs (`*_by_index`).
61-
- **`send`:** Makes stores and store-local handles movable across threads
63+
- **`nightly-tail-calls`:** Uses Rust's unstable explicit tail calls for interpreter dispatch. Requires nightly Rust (recommended for maximum performance).
6264
- **`simd-x86`:** Enables x86-specific SIMD intrinsics and uses `unsafe` internally.
6365

6466
With default features disabled, `tinywasm` supports `no_std + alloc` and depends only on `libm`.

crates/cli/src/wast_runner.rs

Lines changed: 6 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -50,10 +50,8 @@ impl ModuleRegistry {
5050
}
5151

5252
fn definition(&self, id: Option<wast::token::Id<'_>>) -> Option<Module> {
53-
match id {
54-
Some(id) => self.definitions.get(id.name()).cloned(),
55-
None => self.last_definition.clone(),
56-
}
53+
let Some(id) = id else { return self.last_definition.clone() };
54+
self.definitions.get(id.name()).cloned()
5755
}
5856

5957
fn update_last_instance(&mut self, instance: ModuleInstance, name: Option<String>) {
@@ -71,21 +69,13 @@ impl ModuleRegistry {
7169
}
7270

7371
fn get_idx(&self, module_id: Option<wast::token::Id<'_>>) -> Option<u32> {
74-
match module_id {
75-
Some(module) => {
76-
self.registered.get(module.name()).or_else(|| self.instances.get(module.name())).map(ModuleInstance::id)
77-
}
78-
None => self.last_instance.as_ref().map(ModuleInstance::id),
79-
}
72+
let Some(module_id) = module_id else { return self.last_instance.as_ref().map(ModuleInstance::id) };
73+
self.registered.get(module_id.name()).or_else(|| self.instances.get(module_id.name())).map(ModuleInstance::id)
8074
}
8175

8276
fn get(&self, module_id: Option<wast::token::Id<'_>>) -> Option<ModuleInstance> {
83-
match module_id {
84-
Some(module_id) => {
85-
self.registered.get(module_id.name()).or_else(|| self.instances.get(module_id.name())).cloned()
86-
}
87-
None => self.last_instance.clone(),
88-
}
77+
let Some(module_id) = module_id else { return self.last_instance.clone() };
78+
self.registered.get(module_id.name()).or_else(|| self.instances.get(module_id.name())).cloned()
8979
}
9080
}
9181

crates/parser/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,3 +32,6 @@ std = ["tinywasm-types/std", "wasmparser/std"]
3232

3333
# validate WebAssembly while parsing
3434
validate = ["wasmparser/features", "wasmparser/validate"]
35+
36+
[lints.rust]
37+
unexpected_cfgs = { level = "warn", check-cfg = ["cfg(rust_analyzer)"] }

crates/tinywasm/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,9 @@ debug = ["tinywasm-types/debug"]
122122
# expose module-internal by-index inspection APIs for non-exported entities (for testing and debugging)
123123
guest-debug = []
124124

125+
# use explicit tail calls for interpreter dispatch (requires nightly Rust)
126+
nightly-tail-calls = []
127+
125128
# enable x86-specific SIMD intrinsics in Value128 (uses unsafe code)
126129
# note: for x86 backend selection, compile with x86-64-v3 target features
127130
# (for example: `RUSTFLAGS="-C target-cpu=x86-64-v3"`)

0 commit comments

Comments
 (0)