Skip to content
This repository was archived by the owner on Oct 3, 2025. It is now read-only.

Commit 062515c

Browse files
feat: new parser architecture
Signed-off-by: Henry Gressmann <[email protected]>
1 parent a0368bc commit 062515c

File tree

8 files changed

+521
-353
lines changed

8 files changed

+521
-353
lines changed

BENCHMARKS.md

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,12 @@ All runtimes are compiled with the following settings:
3030

3131
| Benchmark | Native | TinyWasm\* | Wasmi | Wasmer (Single Pass) |
3232
| ------------ | -------- | ---------- | --------- | -------------------- |
33-
| `fib` | \*\* | ` 44.11µs` | `49.46µs` | ` 50.65µs` |
33+
| `fib` | \*\* | ` 43.81µs` | `48.60µs` | ` 43.97µs` |
3434
| `fib-rec` | `0.26ms` | ` 20.99ms` | ` 4.64ms` | ` 0.50ms` |
35-
| `argon2id` | `0.53ms` | `109.38ms` | `45.85ms` | ` 4.82ms` |
36-
| `selfhosted` | `0.05ms` | ` 1.97ms` | ` 4.26ms` | `260.32ms` |
35+
| `argon2id` | `0.53ms` | `107.77ms` | `47.76ms` | ` 4.49ms` |
36+
| `selfhosted` | `0.06ms` | ` 2.88ms` | ` 6.20ms` | `359.33ms` |
3737

3838
_\* converting WASM to TinyWasm bytecode is not included. I takes ~7ms to convert `tinywasm.wasm` to TinyWasm bytecode._
39-
4039
_\*\* essentially instant as it gets computed at compile time._
4140

4241
### Fib

crates/benchmarks/benches/selfhosted.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ const TINYWASM: &[u8] = include_bytes!("../../../examples/rust/out/tinywasm.wasm
5555
fn criterion_benchmark(c: &mut Criterion) {
5656
{
5757
let mut group = c.benchmark_group("selfhosted-parse");
58-
group.bench_function("tinywasm", |b| b.iter(|| util::wasm_to_twasm(TINYWASM)));
58+
group.bench_function("tinywasm", |b| b.iter(|| util::parse_wasm(TINYWASM)));
5959
}
6060

6161
{

crates/benchmarks/benches/util/mod.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@
22

33
use tinywasm::{self, parser::Parser, types::TinyWasmModule};
44

5+
pub fn parse_wasm(wasm: &[u8]) -> TinyWasmModule {
6+
let parser = Parser::new();
7+
parser.parse_module_bytes(wasm).expect("parse_module_bytes")
8+
}
9+
510
pub fn wasm_to_twasm(wasm: &[u8]) -> Vec<u8> {
611
let parser = Parser::new();
712
let res = parser.parse_module_bytes(wasm).expect("parse_module_bytes");

crates/parser/src/conversion.rs

Lines changed: 8 additions & 328 deletions
Large diffs are not rendered by default.

crates/parser/src/lib.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#![forbid(unsafe_code)]
88
#![cfg_attr(not(feature = "std"), feature(error_in_core))]
99
//! See [`tinywasm`](https://docs.rs/tinywasm) for documentation.
10+
#![recursion_limit = "1028"]
1011

1112
mod std;
1213
extern crate alloc;
@@ -28,6 +29,7 @@ mod log {
2829
mod conversion;
2930
mod error;
3031
mod module;
32+
mod visit;
3133
use alloc::{string::ToString, vec::Vec};
3234
pub use error::*;
3335
use module::ModuleReader;
@@ -155,11 +157,11 @@ impl TryFrom<ModuleReader> for TinyWasmModule {
155157
.code
156158
.into_iter()
157159
.zip(code_type_addrs)
158-
.map(|(f, ty_idx)| TypedWasmFunction {
160+
.map(|((instructions, locals), ty_idx)| TypedWasmFunction {
159161
type_addr: ty_idx,
160162
wasm_function: WasmFunction {
161-
instructions: f.body,
162-
locals: f.locals,
163+
instructions,
164+
locals,
163165
ty: reader.func_types.get(ty_idx as usize).expect("No func type for func, this is a bug").clone(),
164166
},
165167
})

crates/parser/src/module.rs

Lines changed: 11 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,17 @@
11
use crate::log::debug;
22
use crate::{conversion, ParseError, Result};
33
use alloc::{boxed::Box, format, vec::Vec};
4-
use core::fmt::Debug;
54
use tinywasm_types::{Data, Element, Export, FuncType, Global, Import, Instruction, MemoryType, TableType, ValType};
65
use wasmparser::{Payload, Validator};
76

8-
#[derive(Debug, Clone)]
9-
pub(crate) struct CodeSection {
10-
pub(crate) locals: Box<[ValType]>,
11-
pub(crate) body: Box<[Instruction]>,
12-
}
13-
147
#[derive(Default)]
158
pub(crate) struct ModuleReader {
169
pub(crate) version: Option<u16>,
1710
pub(crate) start_func: Option<u32>,
1811
pub(crate) func_types: Vec<FuncType>,
1912
pub(crate) code_type_addrs: Vec<u32>,
2013
pub(crate) exports: Vec<Export>,
21-
pub(crate) code: Vec<CodeSection>,
14+
pub(crate) code: Vec<(Box<[Instruction]>, Box<[ValType]>)>,
2215
pub(crate) globals: Vec<Global>,
2316
pub(crate) table_types: Vec<TableType>,
2417
pub(crate) memory_types: Vec<MemoryType>,
@@ -66,15 +59,7 @@ impl ModuleReader {
6659
.map(|t| conversion::convert_module_type(t?))
6760
.collect::<Result<Vec<FuncType>>>()?;
6861
}
69-
FunctionSection(reader) => {
70-
if !self.code_type_addrs.is_empty() {
71-
return Err(ParseError::DuplicateSection("Function section".into()));
72-
}
7362

74-
debug!("Found function section");
75-
validator.function_section(&reader)?;
76-
self.code_type_addrs = reader.into_iter().map(|f| Ok(f?)).collect::<Result<Vec<_>>>()?;
77-
}
7863
GlobalSection(reader) => {
7964
if !self.globals.is_empty() {
8065
return Err(ParseError::DuplicateSection("Global section".into()));
@@ -122,11 +107,21 @@ impl ModuleReader {
122107
}
123108
validator.data_count_section(count, &range)?;
124109
}
110+
FunctionSection(reader) => {
111+
if !self.code_type_addrs.is_empty() {
112+
return Err(ParseError::DuplicateSection("Function section".into()));
113+
}
114+
115+
debug!("Found function section");
116+
validator.function_section(&reader)?;
117+
self.code_type_addrs = reader.into_iter().map(|f| Ok(f?)).collect::<Result<Vec<_>>>()?;
118+
}
125119
CodeSectionStart { count, range, .. } => {
126120
debug!("Found code section ({} functions)", count);
127121
if !self.code.is_empty() {
128122
return Err(ParseError::DuplicateSection("Code section".into()));
129123
}
124+
self.code.reserve(count as usize);
130125
validator.code_section_start(count, &range)?;
131126
}
132127
CodeSectionEntry(function) => {

0 commit comments

Comments
 (0)