1use revm_context_interface::{
8 ContextSetters, ContextTr,
9 journaled_state::JournalTr,
10 result::{EVMError, HaltReason, InvalidTransaction, ResultAndState},
11};
12use revm_handler::{
13 EthFrame, EvmTr, ExecuteEvm, FrameInitOrResult, FrameTr, Handler, ItemOrResult, MainnetHandler,
14 PrecompileProvider, evm::ContextDbError,
15};
16use revm_inspector::{
17 InspectCommitEvm, InspectEvm, Inspector, InspectorEvmTr, InspectorFrame, InspectorHandler,
18 JournalExt,
19};
20use revm_interpreter::{InstructionResult, InterpreterAction, InterpreterResult, InterpreterTypes};
21use revm_primitives::{B256, map::B256Map};
22use revm_state::EvmState;
23
24use crate::{EvmCompilerFn, RawEvmCompilerFn};
25
26#[allow(missing_debug_implementations)]
33pub struct JitEvm<EVM, F = fn(B256, &[u8]) -> Option<EvmCompilerFn>> {
34 inner: EVM,
35 functions: B256Map<RawEvmCompilerFn>,
36 on_miss: F,
37}
38
39fn no_miss(_: B256, _: &[u8]) -> Option<EvmCompilerFn> {
40 None
41}
42
43impl<EVM> JitEvm<EVM> {
44 pub fn new(inner: EVM, functions: B256Map<RawEvmCompilerFn>) -> Self {
46 Self { inner, functions, on_miss: no_miss }
47 }
48}
49
50impl<EVM, F> JitEvm<EVM, F> {
51 pub fn with_on_miss(inner: EVM, functions: B256Map<RawEvmCompilerFn>, on_miss: F) -> Self {
53 Self { inner, functions, on_miss }
54 }
55
56 pub fn into_inner(self) -> EVM {
58 self.inner
59 }
60}
61
62impl<EVM, F> core::ops::Deref for JitEvm<EVM, F> {
63 type Target = EVM;
64 fn deref(&self) -> &EVM {
65 &self.inner
66 }
67}
68
69impl<EVM, F> core::ops::DerefMut for JitEvm<EVM, F> {
70 fn deref_mut(&mut self) -> &mut EVM {
71 &mut self.inner
72 }
73}
74
75impl<EVM, F> EvmTr for JitEvm<EVM, F>
76where
77 EVM: EvmTr<
78 Frame = EthFrame,
79 Precompiles: PrecompileProvider<EVM::Context, Output = InterpreterResult>,
80 >,
81 F: FnMut(B256, &[u8]) -> Option<EvmCompilerFn>,
82{
83 type Context = EVM::Context;
84 type Instructions = EVM::Instructions;
85 type Precompiles = EVM::Precompiles;
86 type Frame = EVM::Frame;
87
88 fn all(
89 &self,
90 ) -> (
91 &Self::Context,
92 &Self::Instructions,
93 &Self::Precompiles,
94 &revm_context_interface::FrameStack<Self::Frame>,
95 ) {
96 self.inner.all()
97 }
98
99 fn all_mut(
100 &mut self,
101 ) -> (
102 &mut Self::Context,
103 &mut Self::Instructions,
104 &mut Self::Precompiles,
105 &mut revm_context_interface::FrameStack<Self::Frame>,
106 ) {
107 self.inner.all_mut()
108 }
109
110 fn frame_init(
111 &mut self,
112 frame_input: <Self::Frame as FrameTr>::FrameInit,
113 ) -> Result<
114 ItemOrResult<&mut Self::Frame, <Self::Frame as FrameTr>::FrameResult>,
115 ContextDbError<Self::Context>,
116 > {
117 self.inner.frame_init(frame_input)
118 }
119
120 fn frame_run(
121 &mut self,
122 ) -> Result<FrameInitOrResult<Self::Frame>, ContextDbError<Self::Context>> {
123 let frame = self.inner.frame_stack().get();
124 let code_hash = frame.interpreter.bytecode.get_or_calculate_hash();
125
126 let f = if let Some(&raw_fn) = self.functions.get(&code_hash) {
127 Some(EvmCompilerFn::new(raw_fn))
128 } else {
129 let code = frame.interpreter.bytecode.original_bytes();
130 (self.on_miss)(code_hash, &code)
131 };
132
133 if let Some(f) = f {
134 let (ctx, _, _, frame_stack) = self.inner.all_mut();
135 let frame = frame_stack.get();
136 let action = unsafe { f.call_with_interpreter(&mut frame.interpreter, ctx) };
137 Ok(frame.process_next_action::<_, ContextDbError<Self::Context>>(ctx, action).inspect(
138 |i| {
139 if i.is_result() {
140 frame.set_finished(true);
141 }
142 },
143 )?)
144 } else {
145 self.inner.frame_run()
146 }
147 }
148
149 fn frame_return_result(
150 &mut self,
151 result: <Self::Frame as FrameTr>::FrameResult,
152 ) -> Result<Option<<Self::Frame as FrameTr>::FrameResult>, ContextDbError<Self::Context>> {
153 self.inner.frame_return_result(result)
154 }
155}
156
157impl<EVM, F> ExecuteEvm for JitEvm<EVM, F>
158where
159 EVM: EvmTr<
160 Frame = EthFrame,
161 Context: ContextTr<Journal: JournalTr<State = EvmState>> + ContextSetters,
162 Precompiles: PrecompileProvider<EVM::Context, Output = InterpreterResult>,
163 >,
164 F: FnMut(B256, &[u8]) -> Option<EvmCompilerFn>,
165{
166 type ExecutionResult = revm_context_interface::result::ExecutionResult<HaltReason>;
167 type State = EvmState;
168 type Error = EVMError<
169 <<EVM::Context as ContextTr>::Db as revm_context_interface::Database>::Error,
170 InvalidTransaction,
171 >;
172 type Tx = <EVM::Context as ContextTr>::Tx;
173 type Block = <EVM::Context as ContextTr>::Block;
174
175 fn transact_one(&mut self, tx: Self::Tx) -> Result<Self::ExecutionResult, Self::Error> {
176 self.ctx_mut().set_tx(tx);
177 MainnetHandler::default().run(self)
178 }
179
180 fn finalize(&mut self) -> Self::State {
181 self.ctx_mut().journal_mut().finalize()
182 }
183
184 fn set_block(&mut self, block: Self::Block) {
185 self.ctx_mut().set_block(block);
186 }
187
188 fn replay(&mut self) -> Result<ResultAndState<HaltReason>, Self::Error> {
189 MainnetHandler::default().run(self).map(|result| {
190 let state = self.ctx_mut().journal_mut().finalize();
191 ResultAndState::new(result, state)
192 })
193 }
194}
195
196impl<EVM, F> InspectorEvmTr for JitEvm<EVM, F>
197where
198 EVM: EvmTr<
199 Frame = EthFrame,
200 Precompiles: PrecompileProvider<EVM::Context, Output = InterpreterResult>,
201 > + InspectorEvmTr,
202 F: FnMut(B256, &[u8]) -> Option<EvmCompilerFn>,
203{
204 type Inspector = <EVM as InspectorEvmTr>::Inspector;
205
206 #[inline]
207 fn all_inspector(
208 &self,
209 ) -> (
210 &Self::Context,
211 &Self::Instructions,
212 &Self::Precompiles,
213 &revm_context_interface::FrameStack<Self::Frame>,
214 &Self::Inspector,
215 ) {
216 self.inner.all_inspector()
217 }
218
219 #[inline]
220 fn all_mut_inspector(
221 &mut self,
222 ) -> (
223 &mut Self::Context,
224 &mut Self::Instructions,
225 &mut Self::Precompiles,
226 &mut revm_context_interface::FrameStack<Self::Frame>,
227 &mut Self::Inspector,
228 ) {
229 self.inner.all_mut_inspector()
230 }
231
232 #[inline]
233 fn inspect_frame_run(
234 &mut self,
235 ) -> Result<FrameInitOrResult<Self::Frame>, ContextDbError<Self::Context>> {
236 let frame = self.inner.frame_stack().get();
237 let code_hash = frame.interpreter.bytecode.get_or_calculate_hash();
238
239 let f = if let Some(&raw_fn) = self.functions.get(&code_hash) {
240 Some(EvmCompilerFn::new(raw_fn))
241 } else {
242 let code = frame.interpreter.bytecode.original_bytes();
243 (self.on_miss)(code_hash, &code)
244 };
245
246 let Some(f) = f else {
247 return self.inner.inspect_frame_run();
248 };
249
250 let (ctx, inspector) = self.ctx_inspector();
257 let ctx_ptr: *mut EVM::Context = ctx;
258 let inspector_ptr: *mut <EVM as InspectorEvmTr>::Inspector = inspector;
259 let mut on_log = move |log: &revm_primitives::Log| unsafe {
260 (*inspector_ptr).log(&mut *ctx_ptr, log.clone());
261 };
262
263 let (ctx, _, _, frame_stack) = self.inner.all_mut();
264 let frame = frame_stack.get();
265 let action = unsafe {
266 f.call_with_interpreter_with(&mut frame.interpreter, ctx, |ecx| {
267 ecx.on_log = Some(core::mem::transmute::<
271 &mut dyn FnMut(&revm_primitives::Log),
272 &mut (dyn FnMut(&revm_primitives::Log) + '_),
273 >(&mut on_log));
274 })
275 };
276
277 let (ctx, inspector) = self.ctx_inspector();
279 if let InterpreterAction::Return(result) = &action
280 && result.result == InstructionResult::SelfDestruct
281 {
282 inspect_selfdestruct(ctx, inspector);
283 }
284
285 let (ctx, _, _, frame_stack) = self.inner.all_mut();
286 let frame = frame_stack.get();
287 let mut result = frame.process_next_action::<_, ContextDbError<Self::Context>>(ctx, action);
288
289 if let Ok(ItemOrResult::Result(frame_result)) = &mut result {
290 let (ctx, inspector, frame) = self.ctx_inspector_frame();
291 if let Some(frame) = frame.eth_frame() {
292 revm_inspector::handler::frame_end(ctx, inspector, &frame.input, frame_result);
293 frame.set_finished(true);
294 }
295 }
296 result
297 }
298}
299
300impl<EVM, F> InspectEvm for JitEvm<EVM, F>
301where
302 EVM: EvmTr<
303 Frame = EthFrame,
304 Context: ContextTr<Journal: JournalTr<State = EvmState> + JournalExt> + ContextSetters,
305 Precompiles: PrecompileProvider<EVM::Context, Output = InterpreterResult>,
306 > + InspectorEvmTr,
307 F: FnMut(B256, &[u8]) -> Option<EvmCompilerFn>,
308{
309 type Inspector = <EVM as InspectorEvmTr>::Inspector;
310
311 #[inline]
312 fn set_inspector(&mut self, inspector: Self::Inspector) {
313 *self.inner.inspector() = inspector;
314 }
315
316 #[inline]
317 fn inspect_one_tx(&mut self, tx: Self::Tx) -> Result<Self::ExecutionResult, Self::Error> {
318 self.ctx_mut().set_tx(tx);
319 MainnetHandler::default().inspect_run(self)
320 }
321}
322
323impl<EVM, F> InspectCommitEvm for JitEvm<EVM, F> where
324 Self: InspectEvm + revm_handler::ExecuteCommitEvm
325{
326}
327
328#[inline(never)]
329#[cold]
330fn inspect_selfdestruct<CTX, IT>(context: &mut CTX, inspector: &mut impl Inspector<CTX, IT>)
331where
332 CTX: ContextTr<Journal: JournalExt> + revm_context_interface::Host,
333 IT: InterpreterTypes,
334{
335 use revm_context::JournalEntry;
336
337 if let Some(
338 JournalEntry::AccountDestroyed {
339 address: contract, target: to, had_balance: balance, ..
340 }
341 | JournalEntry::BalanceTransfer { from: contract, to, balance, .. },
342 ) = context.journal_mut().journal().last()
343 {
344 inspector.selfdestruct(*contract, *to, *balance);
345 }
346}