diff --git a/crates/wasmparser/benches/benchmark.rs b/crates/wasmparser/benches/benchmark.rs index 573c1fe558..4ef5db293f 100644 --- a/crates/wasmparser/benches/benchmark.rs +++ b/crates/wasmparser/benches/benchmark.rs @@ -89,7 +89,7 @@ fn read_all_wasm(wasm: &[u8]) -> Result<()> { let mut ops = OperatorsReader::new_with_allocs(reader, mem::take(&mut allocs)); while !ops.eof() { - ops.visit_operator(&mut NopVisit)?; + ops.visit_operator_owned(NopVisit)?; } ops.finish()?; allocs = ops.into_allocations(); diff --git a/crates/wasmparser/src/binary_reader.rs b/crates/wasmparser/src/binary_reader.rs index 9c4b88df49..aafa2aa8d6 100644 --- a/crates/wasmparser/src/binary_reader.rs +++ b/crates/wasmparser/src/binary_reader.rs @@ -828,6 +828,20 @@ impl<'a> BinaryReader<'a> { /// See the documentation for [`OperatorsReader::visit_operator`] for a version that /// does not require the visitor to implement [`FrameStack`]. pub fn visit_operator(&mut self, visitor: &mut T) -> Result<>::Output> + where + T: VisitOperator<'a> + FrameStack, + { + self.visit_operator_owned(visitor) + } + + /// Visit the next available operator with the specified [`VisitOperator`] instance + /// that is also a [`FrameStack`]. + /// + /// Owned (faster) version of [`BinaryReader::visit_operator`], because this one does not use pointer `&mut T`. + pub fn visit_operator_owned( + &mut self, + mut visitor: T, + ) -> Result<>::Output> where T: VisitOperator<'a> + FrameStack, { @@ -846,7 +860,7 @@ impl<'a> BinaryReader<'a> { 0x03 => visitor.visit_loop(self.read_block_type()?), 0x04 => visitor.visit_if(self.read_block_type()?), 0x05 => { - self.expect_frame(visitor, FrameKind::If, "else")?; + self.expect_frame(&visitor, FrameKind::If, "else")?; visitor.visit_else() } 0x06 => { @@ -865,9 +879,9 @@ impl<'a> BinaryReader<'a> { "legacy_exceptions feature required for catch instruction", pos, )?; - match self.expect_frame(visitor, FrameKind::LegacyCatch, "catch") { + match self.expect_frame(&visitor, FrameKind::LegacyCatch, "catch") { Ok(()) => (), - Err(_) => self.expect_frame(visitor, FrameKind::LegacyTry, "catch")?, + Err(_) => self.expect_frame(&visitor, FrameKind::LegacyTry, "catch")?, } visitor.visit_catch(self.read_var_u32()?) } @@ -890,7 +904,7 @@ impl<'a> BinaryReader<'a> { 0x14 => visitor.visit_call_ref(self.read()?), 0x15 => visitor.visit_return_call_ref(self.read()?), 0x18 => { - self.expect_frame(visitor, FrameKind::LegacyTry, "delegate")?; + self.expect_frame(&visitor, FrameKind::LegacyTry, "delegate")?; visitor.visit_delegate(self.read_var_u32()?) } 0x19 => { @@ -900,9 +914,9 @@ impl<'a> BinaryReader<'a> { "legacy_exceptions feature required for catch_all instruction", pos, )?; - match self.expect_frame(visitor, FrameKind::LegacyCatch, "catch_all") { + match self.expect_frame(&visitor, FrameKind::LegacyCatch, "catch_all") { Ok(()) => (), - Err(_) => self.expect_frame(visitor, FrameKind::LegacyTry, "catch_all")?, + Err(_) => self.expect_frame(&visitor, FrameKind::LegacyTry, "catch_all")?, } visitor.visit_catch_all() } @@ -1134,7 +1148,7 @@ impl<'a> BinaryReader<'a> { fn visit_0xfb_operator( &mut self, pos: u64, - visitor: &mut T, + mut visitor: T, ) -> Result<>::Output> where T: VisitOperator<'a>, @@ -1351,7 +1365,7 @@ impl<'a> BinaryReader<'a> { fn visit_0xfc_operator( &mut self, pos: u64, - visitor: &mut T, + mut visitor: T, ) -> Result<>::Output> where T: VisitOperator<'a>, @@ -1748,7 +1762,7 @@ impl<'a> BinaryReader<'a> { fn visit_0xfe_operator( &mut self, pos: u64, - visitor: &mut T, + mut visitor: T, ) -> Result<>::Output> where T: VisitOperator<'a>, diff --git a/crates/wasmparser/src/readers/core/operators.rs b/crates/wasmparser/src/readers/core/operators.rs index 478ba3c07f..550c9df12e 100644 --- a/crates/wasmparser/src/readers/core/operators.rs +++ b/crates/wasmparser/src/readers/core/operators.rs @@ -353,6 +353,12 @@ pub trait FrameStack { fn current_frame(&self) -> Option; } +impl FrameStack for &mut T { + fn current_frame(&self) -> Option { + (**self).current_frame() + } +} + /// The Wasm control stack for the [`OperatorsReader`]. #[derive(Debug, Default, Clone)] pub struct ControlStack { @@ -398,7 +404,7 @@ impl ControlStack { /// Adapters from VisitOperators to FrameStacks struct FrameStackAdapter<'a, T> { stack: &'a mut ControlStack, - visitor: &'a mut T, + visitor: T, } impl FrameStack for FrameStackAdapter<'_, T> { @@ -407,12 +413,12 @@ impl FrameStack for FrameStackAdapter<'_, T> { } } -struct SingleFrameAdapter<'a, T> { +struct SingleFrameAdapter { current_frame: FrameKind, - visitor: &'a mut T, + visitor: T, } -impl FrameStack for SingleFrameAdapter<'_, T> { +impl FrameStack for SingleFrameAdapter { fn current_frame(&self) -> Option { Some(self.current_frame) } @@ -502,7 +508,7 @@ impl<'a> OperatorsReader<'a> { /// If `OperatorsReader` has less bytes remaining than required to parse /// the `Operator`, or if the input is malformed. pub fn read(&mut self) -> Result> { - self.visit_operator(&mut OperatorFactory) + self.visit_operator_owned(OperatorFactory) } /// Visit the next available operator with the specified [`VisitOperator`] instance. @@ -555,7 +561,20 @@ impl<'a> OperatorsReader<'a> { where T: VisitOperator<'a>, { - self.reader.visit_operator(&mut FrameStackAdapter { + self.visit_operator_owned(visitor) + } + + /// Visit the next available operator with the specified [`VisitOperator`] instance. + /// + /// Owned (faster) version of [`OperatorsReader::visit_operator`], because this one does not use pointer `&mut T`. + pub fn visit_operator_owned( + &mut self, + visitor: T, + ) -> Result<>::Output> + where + T: VisitOperator<'a>, + { + self.reader.visit_operator_owned(FrameStackAdapter { stack: &mut self.stack, visitor, }) @@ -1085,7 +1104,7 @@ macro_rules! define_passthrough_visit_operator { }; } -impl<'a, T: VisitOperator<'a>> VisitOperator<'a> for SingleFrameAdapter<'_, T> { +impl<'a, T: VisitOperator<'a>> VisitOperator<'a> for SingleFrameAdapter { type Output = T::Output; #[cfg(feature = "simd")] @@ -1104,14 +1123,14 @@ impl<'a> BinaryReader<'a> { /// If `BinaryReader` has less bytes remaining than required to parse /// the `Operator`, or if the input is malformed. pub fn peek_operator(&self, stack: &T) -> Result> { - self.clone().visit_operator(&mut SingleFrameAdapter { + self.clone().visit_operator_owned(SingleFrameAdapter { current_frame: stack.current_frame().ok_or_else(|| { format_err!( self.original_position(), "operators remaining after end of function body or expression" ) })?, - visitor: &mut OperatorFactory, + visitor: OperatorFactory, }) } } diff --git a/crates/wasmparser/src/validator/func.rs b/crates/wasmparser/src/validator/func.rs index 325cfc8735..eecd4f2b43 100644 --- a/crates/wasmparser/src/validator/func.rs +++ b/crates/wasmparser/src/validator/func.rs @@ -144,7 +144,7 @@ impl FuncValidator { (reader.clone(), arity) }; - reader.visit_operator(&mut self.visitor(reader.original_position()))??; + reader.visit_operator_owned(self.visitor(reader.original_position()))??; #[cfg(debug_assertions)] { diff --git a/crates/wasmprinter/src/operand_stack.rs b/crates/wasmprinter/src/operand_stack.rs index 924b483a25..8d2bd2fadf 100644 --- a/crates/wasmprinter/src/operand_stack.rs +++ b/crates/wasmprinter/src/operand_stack.rs @@ -50,7 +50,7 @@ impl FuncValidator { let pos = reader.original_position(); reader .clone() - .visit_operator(&mut self.validator.visitor(pos))??; + .visit_operator_owned(self.validator.visitor(pos))??; if !is_end { let op = reader.clone().read()?; diff --git a/crates/wasmprinter/src/operator.rs b/crates/wasmprinter/src/operator.rs index d286ddbd77..28ac21f9ef 100644 --- a/crates/wasmprinter/src/operator.rs +++ b/crates/wasmprinter/src/operator.rs @@ -1531,9 +1531,8 @@ impl OpPrinter for PrintOperatorFolded<'_, '_, '_, '_> { code_section_hints: Vec::new(), }; - let mut op_printer = - PrintOperator::new(&mut internal_printer, self.state, self.operator_state); - reader.visit_operator(&mut op_printer)??; + let op_printer = PrintOperator::new(&mut internal_printer, self.state, self.operator_state); + reader.visit_operator_owned(op_printer)??; if let Some(s) = annotation { internal_printer.result.start_comment()?; write!(internal_printer.result, " (; {s}")?;