summaryrefslogtreecommitdiff
path: root/crates/parser/src/conversion.rs
diff options
context:
space:
mode:
authorHenry <mail@henrygressmann.de>2026-07-15 18:07:43 +0200
committerHenry <mail@henrygressmann.de>2026-07-15 18:07:43 +0200
commit4d66c97493a8a92bab81f48baa3f9d9b6c85027d (patch)
treea04506c6d8fba35d818c501d528a390a42ca8dc5 /crates/parser/src/conversion.rs
parent957b62bf1d6205409bac94a4ced790dfb8007e3d (diff)
perf: improve parser performance
Signed-off-by: Henry <mail@henrygressmann.de>
Diffstat (limited to 'crates/parser/src/conversion.rs')
-rw-r--r--crates/parser/src/conversion.rs36
1 files changed, 21 insertions, 15 deletions
diff --git a/crates/parser/src/conversion.rs b/crates/parser/src/conversion.rs
index cfc0e84..586cac5 100644
--- a/crates/parser/src/conversion.rs
+++ b/crates/parser/src/conversion.rs
@@ -180,8 +180,7 @@ pub(crate) fn convert_module_type(ty: wasmparser::RecGroup) -> Result<Arc<FuncTy
ty.composite_type
)));
};
- let params: Vec<_> = ty.params().iter().map(convert_valtype).collect();
- let params = params.into_iter().collect::<Result<Vec<_>>>()?;
+ let params = ty.params().iter().map(convert_valtype).collect::<Result<Vec<_>>>()?;
let results = ty.results().iter().map(convert_valtype).collect::<Result<Vec<_>>>()?;
Ok(FuncType::new(&params, &results).into())
}
@@ -209,17 +208,20 @@ pub(crate) fn convert_valtype(valtype: &wasmparser::ValType) -> Result<WasmType>
}
pub(crate) fn process_const_operators(ops: OperatorsReader<'_>) -> Result<Box<[ConstInstruction]>> {
- let ops = ops.into_iter().collect::<wasmparser::Result<Vec<_>>>()?;
- // In practice, the len can never be something other than 2,
- // but we'll keep this here since it's part of the spec
- // Invalid modules will be rejected by the validator anyway (there are also tests for this in the testsuite)
- debug_assert!(ops.len() >= 2);
- debug_assert!(matches!(ops[ops.len() - 1], wasmparser::Operator::End));
+ let mut out = Vec::new();
+ let mut operator_count = 0;
+ let mut end_reached = false;
+
+ for op in ops {
+ let op = op?;
+ operator_count += 1;
+ if matches!(op, wasmparser::Operator::End) {
+ end_reached = true;
+ break;
+ }
- let mut out = Vec::with_capacity(ops.len().saturating_sub(1));
- for op in ops.iter().take(ops.len() - 1) {
let instr = match op {
- wasmparser::Operator::RefNull { hty } => match convert_heaptype(*hty)? {
+ wasmparser::Operator::RefNull { hty } => match convert_heaptype(hty)? {
WasmType::RefFunc => ConstInstruction::RefFunc(None),
WasmType::RefExtern => ConstInstruction::RefExtern(None),
other => {
@@ -228,13 +230,13 @@ pub(crate) fn process_const_operators(ops: OperatorsReader<'_>) -> Result<Box<[C
)));
}
},
- wasmparser::Operator::RefFunc { function_index } => ConstInstruction::RefFunc(Some(*function_index)),
- wasmparser::Operator::I32Const { value } => ConstInstruction::I32Const(*value),
- wasmparser::Operator::I64Const { value } => ConstInstruction::I64Const(*value),
+ wasmparser::Operator::RefFunc { function_index } => ConstInstruction::RefFunc(Some(function_index)),
+ wasmparser::Operator::I32Const { value } => ConstInstruction::I32Const(value),
+ wasmparser::Operator::I64Const { value } => ConstInstruction::I64Const(value),
wasmparser::Operator::F32Const { value } => ConstInstruction::F32Const(f32::from_bits(value.bits())),
wasmparser::Operator::F64Const { value } => ConstInstruction::F64Const(f64::from_bits(value.bits())),
wasmparser::Operator::V128Const { value } => ConstInstruction::V128Const(*value.bytes()),
- wasmparser::Operator::GlobalGet { global_index } => ConstInstruction::GlobalGet(*global_index),
+ wasmparser::Operator::GlobalGet { global_index } => ConstInstruction::GlobalGet(global_index),
wasmparser::Operator::I32Add => ConstInstruction::I32Add,
wasmparser::Operator::I32Sub => ConstInstruction::I32Sub,
wasmparser::Operator::I32Mul => ConstInstruction::I32Mul,
@@ -250,6 +252,10 @@ pub(crate) fn process_const_operators(ops: OperatorsReader<'_>) -> Result<Box<[C
out.push(instr);
}
+ if operator_count < 2 || !end_reached {
+ return Err(crate::ParseError::Other("constant expression did not end correctly".into()));
+ }
+
Ok(out.into_boxed_slice())
}