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

Commit dea9327

Browse files
pref: improve parser performance
Signed-off-by: Henry Gressmann <[email protected]>
1 parent 1313cc0 commit dea9327

File tree

5 files changed

+61
-28
lines changed

5 files changed

+61
-28
lines changed

Cargo.lock

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

crates/benchmarks/benches/selfhosted.rs

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -53,13 +53,19 @@ fn run_wasmer(wasm: &[u8]) {
5353

5454
const TINYWASM: &[u8] = include_bytes!("../../../examples/rust/out/tinywasm.wasm");
5555
fn criterion_benchmark(c: &mut Criterion) {
56-
let twasm = util::wasm_to_twasm(TINYWASM);
56+
{
57+
let mut group = c.benchmark_group("selfhosted-parse");
58+
group.bench_function("tinywasm", |b| b.iter(|| util::wasm_to_twasm(TINYWASM)));
59+
}
5760

58-
let mut group = c.benchmark_group("selfhosted");
59-
group.bench_function("native", |b| b.iter(run_native));
60-
group.bench_function("tinywasm", |b| b.iter(|| run_tinywasm(&twasm)));
61-
group.bench_function("wasmi", |b| b.iter(|| run_wasmi(TINYWASM)));
62-
group.bench_function("wasmer", |b| b.iter(|| run_wasmer(TINYWASM)));
61+
{
62+
let twasm = util::wasm_to_twasm(TINYWASM);
63+
let mut group = c.benchmark_group("selfhosted");
64+
// group.bench_function("native", |b| b.iter(run_native));
65+
group.bench_function("tinywasm", |b| b.iter(|| run_tinywasm(&twasm)));
66+
// group.bench_function("wasmi", |b| b.iter(|| run_wasmi(TINYWASM)));
67+
// group.bench_function("wasmer", |b| b.iter(|| run_wasmer(TINYWASM)));
68+
}
6369
}
6470

6571
criterion_group!(

crates/parser/src/conversion.rs

Lines changed: 35 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ pub(crate) fn convert_module_code(
163163
}
164164

165165
let body_reader = func.get_operators_reader()?;
166-
let body = process_operators(body_reader.original_position(), body_reader.into_iter(), validator)?;
166+
let body = process_operators(body_reader, validator)?;
167167

168168
Ok(CodeSection { locals: locals.into_boxed_slice(), body })
169169
}
@@ -228,28 +228,47 @@ pub(crate) fn process_const_operator(op: wasmparser::Operator<'_>) -> Result<Con
228228
}
229229
}
230230

231-
pub(crate) fn process_operators<'a>(
232-
mut offset: usize,
233-
ops: impl Iterator<Item = Result<wasmparser::Operator<'a>, wasmparser::BinaryReaderError>>,
231+
pub(crate) fn process_operators(
232+
ops: OperatorsReader<'_>,
234233
mut validator: FuncValidator<ValidatorResources>,
235234
) -> Result<Box<[Instruction]>> {
236-
let mut instructions = Vec::new();
237-
let mut labels_ptrs = Vec::new(); // indexes into the instructions array
235+
let mut instructions = Vec::with_capacity(1024);
236+
let mut labels_ptrs = Vec::with_capacity(32);
237+
// indexes into the instructions array
238+
let mut offset = ops.original_position();
238239

239240
for op in ops {
240-
log::debug!("op: {:?}", op);
241+
let op = match op {
242+
Ok(op) => op,
243+
Err(e) => {
244+
cold();
245+
log::error!("Error while processing operators: {:?}", e);
246+
return Err(crate::ParseError::UnsupportedOperator("Error while processing operators".to_string()));
247+
}
248+
};
241249

242-
let op = op?;
243-
validator.op(offset, &op)?;
250+
match validator.op(offset, &op) {
251+
Ok(_) => (),
252+
Err(e) => {
253+
cold();
254+
log::error!("Error while processing operators: {:?}", e);
255+
return Err(crate::ParseError::UnsupportedOperator("Error while processing operators".to_string()));
256+
}
257+
}
244258
offset += 1;
245259

246260
use wasmparser::Operator::*;
247261
let res = match op {
248262
BrTable { targets } => {
249263
let def = targets.default();
250-
let targets = targets.targets().collect::<Result<Vec<u32>, wasmparser::BinaryReaderError>>()?;
251-
instructions.push(Instruction::BrTable(def, targets.len()));
252-
instructions.extend(targets.into_iter().map(Instruction::BrLabel));
264+
265+
let instrs = targets
266+
.targets()
267+
.map(|t| t.map(Instruction::BrLabel))
268+
.collect::<Result<Vec<Instruction>, wasmparser::BinaryReaderError>>()?;
269+
270+
instructions.push(Instruction::BrTable(def, instrs.len()));
271+
instructions.extend(instrs);
253272
continue;
254273
}
255274
Unreachable => Instruction::Unreachable,
@@ -510,6 +529,7 @@ pub(crate) fn process_operators<'a>(
510529
TableSize { table } => Instruction::TableSize(table),
511530
TableFill { table } => Instruction::TableFill(table),
512531
op => {
532+
cold();
513533
log::error!("Unsupported instruction: {:?}", op);
514534
return Err(crate::ParseError::UnsupportedOperator(format!("Unsupported instruction: {:?}", op)));
515535
}
@@ -524,3 +544,6 @@ pub(crate) fn process_operators<'a>(
524544
validator.finish(offset)?;
525545
Ok(instructions.into_boxed_slice())
526546
}
547+
548+
#[cold]
549+
fn cold() {}

examples/rust/README.md

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

33
This is a seperate crate that generates WebAssembly from Rust code.
44
It is used by the `wasm-rust` example.
5+
6+
Requires the `wasm32-unknown-unknown` target to be installed.

examples/rust/rust-toolchain.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
[toolchain]
2+
channel="nightly-2024-02-11"

0 commit comments

Comments
 (0)