Skip to content

Commit 8dc26ab

Browse files
committed
perf: box inspectors in InspectorStack
1 parent 391f37f commit 8dc26ab

File tree

5 files changed

+46
-40
lines changed

5 files changed

+46
-40
lines changed

crates/cheatcodes/src/inspector.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ pub trait CheatcodesExecutor {
111111
}
112112

113113
/// Returns a mutable reference to the tracing inspector if it is available.
114-
fn tracing_inspector(&mut self) -> Option<&mut Option<TracingInspector>> {
114+
fn tracing_inspector(&mut self) -> Option<&mut Option<Box<TracingInspector>>> {
115115
None
116116
}
117117
}

crates/evm/evm/src/executors/invariant/mod.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -609,8 +609,11 @@ impl<'a> InvariantExecutor<'a> {
609609
));
610610
}
611611

612-
self.executor.inspector_mut().fuzzer =
613-
Some(Fuzzer { call_generator, fuzz_state: fuzz_state.clone(), collect: true });
612+
self.executor.inspector_mut().set_fuzzer(Fuzzer {
613+
call_generator,
614+
fuzz_state: fuzz_state.clone(),
615+
collect: true,
616+
});
614617

615618
// Let's make sure the invariant is sound before actually starting the run:
616619
// We'll assert the invariant in its initial state, and if it fails, we'll

crates/evm/evm/src/executors/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -842,7 +842,7 @@ pub struct RawCallResult {
842842
/// The `revm::Env` after the call
843843
pub env: Env,
844844
/// The cheatcode states after execution
845-
pub cheatcodes: Option<Cheatcodes>,
845+
pub cheatcodes: Option<Box<Cheatcodes>>,
846846
/// The raw output of the execution
847847
pub out: Option<Output>,
848848
/// The chisel state

crates/evm/evm/src/inspectors/stack.rs

Lines changed: 36 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,7 @@ pub struct InspectorData {
262262
pub traces: Option<SparsedTraceArena>,
263263
pub line_coverage: Option<HitMaps>,
264264
pub edge_coverage: Option<Vec<u8>>,
265-
pub cheatcodes: Option<Cheatcodes>,
265+
pub cheatcodes: Option<Box<Cheatcodes>>,
266266
pub chisel_state: Option<(Vec<U256>, Vec<u8>, Option<InstructionResult>)>,
267267
pub reverter: Option<Address>,
268268
}
@@ -290,7 +290,7 @@ pub struct InnerContextData {
290290
/// collection, etc.
291291
#[derive(Clone, Debug, Default)]
292292
pub struct InspectorStack {
293-
pub cheatcodes: Option<Cheatcodes>,
293+
pub cheatcodes: Option<Box<Cheatcodes>>,
294294
pub inner: InspectorStackInner,
295295
}
296296

@@ -300,15 +300,15 @@ pub struct InspectorStack {
300300
#[derive(Default, Clone, Debug)]
301301
pub struct InspectorStackInner {
302302
// Inspectors.
303-
pub chisel_state: Option<ChiselState>,
304-
pub edge_coverage: Option<EdgeCovInspector>,
305-
pub fuzzer: Option<Fuzzer>,
306-
pub line_coverage: Option<LineCoverageCollector>,
307-
pub log_collector: Option<LogCollector>,
308-
pub printer: Option<CustomPrintTracer>,
309-
pub revert_diag: Option<RevertDiagnostic>,
310-
pub script_execution_inspector: Option<ScriptExecutionInspector>,
311-
pub tracer: Option<TracingInspector>,
303+
pub chisel_state: Option<Box<ChiselState>>,
304+
pub edge_coverage: Option<Box<EdgeCovInspector>>,
305+
pub fuzzer: Option<Box<Fuzzer>>,
306+
pub line_coverage: Option<Box<LineCoverageCollector>>,
307+
pub log_collector: Option<Box<LogCollector>>,
308+
pub printer: Option<Box<CustomPrintTracer>>,
309+
pub revert_diag: Option<Box<RevertDiagnostic>>,
310+
pub script_execution_inspector: Option<Box<ScriptExecutionInspector>>,
311+
pub tracer: Option<Box<TracingInspector>>,
312312

313313
// InspectorExt and other internal data.
314314
pub enable_isolation: bool,
@@ -335,7 +335,7 @@ impl CheatcodesExecutor for InspectorStackInner {
335335
Box::new(InspectorStackRefMut { cheatcodes: Some(cheats), inner: self })
336336
}
337337

338-
fn tracing_inspector(&mut self) -> Option<&mut Option<TracingInspector>> {
338+
fn tracing_inspector(&mut self) -> Option<&mut Option<Box<TracingInspector>>> {
339339
Some(&mut self.tracer)
340340
}
341341
}
@@ -398,19 +398,19 @@ impl InspectorStack {
398398
/// Set the cheatcodes inspector.
399399
#[inline]
400400
pub fn set_cheatcodes(&mut self, cheatcodes: Cheatcodes) {
401-
self.cheatcodes = Some(cheatcodes);
401+
self.cheatcodes = Some(cheatcodes.into());
402402
}
403403

404404
/// Set the fuzzer inspector.
405405
#[inline]
406406
pub fn set_fuzzer(&mut self, fuzzer: Fuzzer) {
407-
self.fuzzer = Some(fuzzer);
407+
self.fuzzer = Some(fuzzer.into());
408408
}
409409

410410
/// Set the Chisel inspector.
411411
#[inline]
412412
pub fn set_chisel(&mut self, final_pc: usize) {
413-
self.chisel_state = Some(ChiselState::new(final_pc));
413+
self.chisel_state = Some(ChiselState::new(final_pc).into());
414414
}
415415

416416
/// Set whether to enable the line coverage collector.
@@ -422,7 +422,8 @@ impl InspectorStack {
422422
/// Set whether to enable the edge coverage collector.
423423
#[inline]
424424
pub fn collect_edge_coverage(&mut self, yes: bool) {
425-
self.edge_coverage = yes.then(EdgeCovInspector::new); // TODO configurable edge size?
425+
// TODO: configurable edge size?
426+
self.edge_coverage = yes.then(EdgeCovInspector::new).map(Into::into);
426427
}
427428

428429
/// Set whether to enable call isolation.
@@ -459,11 +460,7 @@ impl InspectorStack {
459460
/// Revert diagnostic inspector is activated when `mode != TraceMode::None`
460461
#[inline]
461462
pub fn tracing(&mut self, mode: TraceMode) {
462-
if mode.is_none() {
463-
self.revert_diag = None;
464-
} else {
465-
self.revert_diag = Some(RevertDiagnostic::default());
466-
}
463+
self.revert_diag = (!mode.is_none()).then(RevertDiagnostic::default).map(Into::into);
467464

468465
if let Some(config) = mode.into_config() {
469466
*self.tracer.get_or_insert_with(Default::default).config_mut() = config;
@@ -480,7 +477,6 @@ impl InspectorStack {
480477
}
481478

482479
/// Collects all the data gathered during inspection into a single struct.
483-
#[inline]
484480
pub fn collect(self) -> InspectorData {
485481
let Self {
486482
mut cheatcodes,
@@ -531,7 +527,7 @@ impl InspectorStack {
531527

532528
#[inline(always)]
533529
fn as_mut(&mut self) -> InspectorStackRefMut<'_> {
534-
InspectorStackRefMut { cheatcodes: self.cheatcodes.as_mut(), inner: &mut self.inner }
530+
InspectorStackRefMut { cheatcodes: self.cheatcodes.as_deref_mut(), inner: &mut self.inner }
535531
}
536532
}
537533

@@ -740,17 +736,16 @@ impl InspectorStackRefMut<'_> {
740736
/// it.
741737
fn with_stack<O>(&mut self, f: impl FnOnce(&mut InspectorStack) -> O) -> O {
742738
let mut stack = InspectorStack {
743-
cheatcodes: self
744-
.cheatcodes
745-
.as_deref_mut()
746-
.map(|cheats| core::mem::replace(cheats, Cheatcodes::new(cheats.config.clone()))),
739+
cheatcodes: self.cheatcodes.as_deref_mut().map(|cheats| {
740+
core::mem::replace(cheats, Cheatcodes::new(cheats.config.clone())).into()
741+
}),
747742
inner: std::mem::take(self.inner),
748743
};
749744

750745
let out = f(&mut stack);
751746

752747
if let Some(cheats) = self.cheatcodes.as_deref_mut() {
753-
*cheats = stack.cheatcodes.take().unwrap();
748+
*cheats = *stack.cheatcodes.take().unwrap();
754749
}
755750

756751
*self.inner = stack.inner;
@@ -791,6 +786,11 @@ impl InspectorStackRefMut<'_> {
791786
}
792787
}
793788

789+
// We take extra care in optimizing `step` and `step_end`, as they're are likely the most
790+
// hot functions in all of Foundry.
791+
// We want to `#[inline(always)]` these functions so that `InspectorStack` does not
792+
// delegate to `InspectorStackRefMut` in this case.
793+
794794
#[inline(always)]
795795
fn step_inlined(
796796
&mut self,
@@ -799,17 +799,18 @@ impl InspectorStackRefMut<'_> {
799799
) {
800800
call_inspectors!(
801801
[
802+
// These are sorted in definition order.
803+
&mut self.edge_coverage,
802804
&mut self.fuzzer,
803-
&mut self.tracer,
804805
&mut self.line_coverage,
805-
&mut self.edge_coverage,
806-
&mut self.script_execution_inspector,
807806
&mut self.printer,
808807
&mut self.revert_diag,
808+
&mut self.script_execution_inspector,
809+
&mut self.tracer,
809810
// Keep `cheatcodes` last to make use of the tail call.
810811
&mut self.cheatcodes,
811812
],
812-
|inspector| (*inspector).step(interpreter, ecx),
813+
|inspector| (**inspector).step(interpreter, ecx),
813814
);
814815
}
815816

@@ -821,14 +822,15 @@ impl InspectorStackRefMut<'_> {
821822
) {
822823
call_inspectors!(
823824
[
824-
&mut self.tracer,
825+
// These are sorted in definition order.
825826
&mut self.chisel_state,
826827
&mut self.printer,
827828
&mut self.revert_diag,
829+
&mut self.tracer,
828830
// Keep `cheatcodes` last to make use of the tail call.
829831
&mut self.cheatcodes,
830832
],
831-
|inspector| (*inspector).step_end(interpreter, ecx),
833+
|inspector| (**inspector).step_end(interpreter, ecx),
832834
);
833835
}
834836
}

crates/evm/fuzz/src/inspector.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,10 @@ use revm::{
99
/// An inspector that can fuzz and collect data for that effect.
1010
#[derive(Clone, Debug)]
1111
pub struct Fuzzer {
12-
/// Given a strategy, it generates a random call.
13-
pub call_generator: Option<RandomCallGenerator>,
1412
/// If set, it collects `stack` and `memory` values for fuzzing purposes.
1513
pub collect: bool,
14+
/// Given a strategy, it generates a random call.
15+
pub call_generator: Option<RandomCallGenerator>,
1616
/// If `collect` is set, we store the collected values in this fuzz dictionary.
1717
pub fuzz_state: EvmFuzzState,
1818
}
@@ -21,6 +21,7 @@ impl<CTX> Inspector<CTX> for Fuzzer
2121
where
2222
CTX: ContextTr<Journal: JournalExt>,
2323
{
24+
#[inline]
2425
fn step(&mut self, interp: &mut Interpreter, _context: &mut CTX) {
2526
// We only collect `stack` and `memory` data before and after calls.
2627
if self.collect {

0 commit comments

Comments
 (0)