summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHenry Gressmann <mail@henrygressmann.de>2024-02-24 14:35:20 +0100
committerHenry Gressmann <mail@henrygressmann.de>2024-02-24 14:50:06 +0100
commitdea93272b80a7ae658318ce7af21f00cacae054d (patch)
tree4fceb367b1f84e57b37d047641d0fc63ff581fec
parent1313cc071f45f5a0ce97637d130d4334a5e9bdfd (diff)
pref: improve parser performance
Signed-off-by: Henry Gressmann <mail@henrygressmann.de>
-rw-r--r--Cargo.lock20
-rw-r--r--crates/benchmarks/benches/selfhosted.rs18
-rw-r--r--crates/parser/src/conversion.rs47
-rw-r--r--examples/rust/README.md2
-rw-r--r--examples/rust/rust-toolchain.toml2
5 files changed, 61 insertions, 28 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 8508a3a..fbfe381 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -280,9 +280,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5"
[[package]]
name = "cc"
-version = "1.0.86"
+version = "1.0.87"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7f9fa1897e4325be0d68d48df6aa1a71ac2ed4d27723887e7754192705350730"
+checksum = "3286b845d0fccbdd15af433f61c5970e711987036cb468f437ff6badd70f4e24"
[[package]]
name = "cfg-if"
@@ -649,9 +649,9 @@ dependencies = [
[[package]]
name = "darling"
-version = "0.20.6"
+version = "0.20.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c376d08ea6aa96aafe61237c7200d1241cb177b7d3a542d791f2d118e9cbb955"
+checksum = "54e36fcd13ed84ffdfda6f5be89b31287cbb80c439841fe69e04841435464391"
dependencies = [
"darling_core",
"darling_macro",
@@ -659,9 +659,9 @@ dependencies = [
[[package]]
name = "darling_core"
-version = "0.20.6"
+version = "0.20.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "33043dcd19068b8192064c704b3f83eb464f91f1ff527b44a4e2b08d9cdb8855"
+checksum = "9c2cf1c23a687a1feeb728783b993c4e1ad83d99f351801977dd809b48d0a70f"
dependencies = [
"fnv",
"ident_case",
@@ -672,9 +672,9 @@ dependencies = [
[[package]]
name = "darling_macro"
-version = "0.20.6"
+version = "0.20.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c5a91391accf613803c2a9bf9abccdbaa07c54b4244a5b64883f9c3c137c86be"
+checksum = "a668eda54683121533a393014d8692171709ff57a7d61f187b6e782719f8933f"
dependencies = [
"darling_core",
"quote",
@@ -1121,9 +1121,9 @@ dependencies = [
[[package]]
name = "image"
-version = "0.24.8"
+version = "0.24.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "034bbe799d1909622a74d1193aa50147769440040ff36cb2baa947609b0a4e23"
+checksum = "5690139d2f55868e080017335e4b94cb7414274c74f1669c84fb5feba2c9f69d"
dependencies = [
"bytemuck",
"byteorder",
diff --git a/crates/benchmarks/benches/selfhosted.rs b/crates/benchmarks/benches/selfhosted.rs
index b022fd1..985577c 100644
--- a/crates/benchmarks/benches/selfhosted.rs
+++ b/crates/benchmarks/benches/selfhosted.rs
@@ -53,13 +53,19 @@ fn run_wasmer(wasm: &[u8]) {
const TINYWASM: &[u8] = include_bytes!("../../../examples/rust/out/tinywasm.wasm");
fn criterion_benchmark(c: &mut Criterion) {
- let twasm = util::wasm_to_twasm(TINYWASM);
+ {
+ let mut group = c.benchmark_group("selfhosted-parse");
+ group.bench_function("tinywasm", |b| b.iter(|| util::wasm_to_twasm(TINYWASM)));
+ }
- let mut group = c.benchmark_group("selfhosted");
- group.bench_function("native", |b| b.iter(run_native));
- group.bench_function("tinywasm", |b| b.iter(|| run_tinywasm(&twasm)));
- group.bench_function("wasmi", |b| b.iter(|| run_wasmi(TINYWASM)));
- group.bench_function("wasmer", |b| b.iter(|| run_wasmer(TINYWASM)));
+ {
+ let twasm = util::wasm_to_twasm(TINYWASM);
+ let mut group = c.benchmark_group("selfhosted");
+ // group.bench_function("native", |b| b.iter(run_native));
+ group.bench_function("tinywasm", |b| b.iter(|| run_tinywasm(&twasm)));
+ // group.bench_function("wasmi", |b| b.iter(|| run_wasmi(TINYWASM)));
+ // group.bench_function("wasmer", |b| b.iter(|| run_wasmer(TINYWASM)));
+ }
}
criterion_group!(
diff --git a/crates/parser/src/conversion.rs b/crates/parser/src/conversion.rs
index 38a2ada..cd8840a 100644
--- a/crates/parser/src/conversion.rs
+++ b/crates/parser/src/conversion.rs
@@ -163,7 +163,7 @@ pub(crate) fn convert_module_code(
}
let body_reader = func.get_operators_reader()?;
- let body = process_operators(body_reader.original_position(), body_reader.into_iter(), validator)?;
+ let body = process_operators(body_reader, validator)?;
Ok(CodeSection { locals: locals.into_boxed_slice(), body })
}
@@ -228,28 +228,47 @@ pub(crate) fn process_const_operator(op: wasmparser::Operator<'_>) -> Result<Con
}
}
-pub(crate) fn process_operators<'a>(
- mut offset: usize,
- ops: impl Iterator<Item = Result<wasmparser::Operator<'a>, wasmparser::BinaryReaderError>>,
+pub(crate) fn process_operators(
+ ops: OperatorsReader<'_>,
mut validator: FuncValidator<ValidatorResources>,
) -> Result<Box<[Instruction]>> {
- let mut instructions = Vec::new();
- let mut labels_ptrs = Vec::new(); // indexes into the instructions array
+ let mut instructions = Vec::with_capacity(1024);
+ let mut labels_ptrs = Vec::with_capacity(32);
+ // indexes into the instructions array
+ let mut offset = ops.original_position();
for op in ops {
- log::debug!("op: {:?}", op);
+ let op = match op {
+ Ok(op) => op,
+ Err(e) => {
+ cold();
+ log::error!("Error while processing operators: {:?}", e);
+ return Err(crate::ParseError::UnsupportedOperator("Error while processing operators".to_string()));
+ }
+ };
- let op = op?;
- validator.op(offset, &op)?;
+ match validator.op(offset, &op) {
+ Ok(_) => (),
+ Err(e) => {
+ cold();
+ log::error!("Error while processing operators: {:?}", e);
+ return Err(crate::ParseError::UnsupportedOperator("Error while processing operators".to_string()));
+ }
+ }
offset += 1;
use wasmparser::Operator::*;
let res = match op {
BrTable { targets } => {
let def = targets.default();
- let targets = targets.targets().collect::<Result<Vec<u32>, wasmparser::BinaryReaderError>>()?;
- instructions.push(Instruction::BrTable(def, targets.len()));
- instructions.extend(targets.into_iter().map(Instruction::BrLabel));
+
+ let instrs = targets
+ .targets()
+ .map(|t| t.map(Instruction::BrLabel))
+ .collect::<Result<Vec<Instruction>, wasmparser::BinaryReaderError>>()?;
+
+ instructions.push(Instruction::BrTable(def, instrs.len()));
+ instructions.extend(instrs);
continue;
}
Unreachable => Instruction::Unreachable,
@@ -510,6 +529,7 @@ pub(crate) fn process_operators<'a>(
TableSize { table } => Instruction::TableSize(table),
TableFill { table } => Instruction::TableFill(table),
op => {
+ cold();
log::error!("Unsupported instruction: {:?}", op);
return Err(crate::ParseError::UnsupportedOperator(format!("Unsupported instruction: {:?}", op)));
}
@@ -524,3 +544,6 @@ pub(crate) fn process_operators<'a>(
validator.finish(offset)?;
Ok(instructions.into_boxed_slice())
}
+
+#[cold]
+fn cold() {}
diff --git a/examples/rust/README.md b/examples/rust/README.md
index 1b6be2f..c24054c 100644
--- a/examples/rust/README.md
+++ b/examples/rust/README.md
@@ -2,3 +2,5 @@
This is a seperate crate that generates WebAssembly from Rust code.
It is used by the `wasm-rust` example.
+
+Requires the `wasm32-unknown-unknown` target to be installed.
diff --git a/examples/rust/rust-toolchain.toml b/examples/rust/rust-toolchain.toml
new file mode 100644
index 0000000..6c22ba5
--- /dev/null
+++ b/examples/rust/rust-toolchain.toml
@@ -0,0 +1,2 @@
+[toolchain]
+channel="nightly-2024-02-11"