Skip to main content

revmc_runtime/runtime/
api.rs

1//! Public types and handle methods.
2
3use crate::{
4    EvmCompilerFn,
5    runtime::{storage::RuntimeCacheKey, worker::JitCodeBacking},
6};
7use alloy_primitives::{B256, Bytes};
8use revm_primitives::hardfork::SpecId;
9use std::sync::Arc;
10
11/// Request to look up a compiled function.
12#[derive(Clone, Debug)]
13pub struct LookupRequest {
14    /// The cache key (code hash + spec).
15    pub key: RuntimeCacheKey,
16    /// The raw contract bytecode.
17    pub code: Bytes,
18}
19
20/// Result of a lookup.
21#[derive(Clone, Debug)]
22pub enum LookupDecision {
23    /// A compiled function is available.
24    Compiled(Arc<CompiledProgram>),
25    /// The caller should interpret instead.
26    Interpret(InterpretReason),
27}
28
29/// Reason why the runtime returned "interpret" instead of a compiled function.
30#[derive(Clone, Copy, Debug, PartialEq, Eq)]
31pub enum InterpretReason {
32    /// The runtime is disabled.
33    Disabled,
34    /// The contract is not eligible for compilation.
35    Ineligible,
36    /// No compiled program is ready for this key.
37    NotReady,
38    /// JIT compilation failed for this contract.
39    JitFailed,
40}
41
42/// A compiled EVM program kept alive in the resident map.
43pub struct CompiledProgram {
44    /// The callable compiled function.
45    pub func: EvmCompilerFn,
46    /// The cache key this program was compiled for.
47    pub key: RuntimeCacheKey,
48    /// Whether this is an AOT or JIT program.
49    pub kind: ProgramKind,
50    /// Keeps the backing memory (shared library / JIT module) alive.
51    _backing: ProgramBacking,
52}
53
54impl std::fmt::Debug for CompiledProgram {
55    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
56        f.debug_struct("CompiledProgram")
57            .field("key", &self.key)
58            .field("kind", &self.kind)
59            .field("func", &self.func)
60            .finish_non_exhaustive()
61    }
62}
63
64impl CompiledProgram {
65    /// Creates a new compiled program backed by a loaded shared library.
66    pub(crate) fn new_aot(
67        key: RuntimeCacheKey,
68        func: EvmCompilerFn,
69        library: Arc<LoadedLibrary>,
70    ) -> Self {
71        Self { key, kind: ProgramKind::Aot, func, _backing: ProgramBacking::LoadedLibrary(library) }
72    }
73
74    /// Creates a new compiled program backed by a JIT module's
75    /// [`ResourceTracker`](crate::llvm::orc::ResourceTracker).
76    pub(crate) fn new_jit(
77        key: RuntimeCacheKey,
78        func: EvmCompilerFn,
79        backing: Arc<JitCodeBacking>,
80    ) -> Self {
81        Self { key, kind: ProgramKind::Jit, func, _backing: ProgramBacking::JitModule(backing) }
82    }
83}
84
85/// Request to prepare an AOT artifact.
86#[derive(Clone, Debug)]
87pub struct AotRequest {
88    /// The code hash of the contract bytecode.
89    pub code_hash: B256,
90    /// The raw contract bytecode.
91    pub code: Bytes,
92    /// The EVM spec (hardfork) for compilation.
93    pub spec_id: SpecId,
94}
95
96/// Whether this program was compiled AOT or JIT.
97#[derive(Clone, Copy, Debug, PartialEq, Eq)]
98pub enum ProgramKind {
99    /// Loaded from a pre-compiled artifact at startup.
100    Aot,
101    /// Compiled at runtime by the JIT.
102    Jit,
103}
104
105/// Backing storage that keeps compiled code alive.
106#[expect(dead_code, reason = "variant fields are held alive for Drop")]
107enum ProgramBacking {
108    /// A dynamically loaded shared library (AOT).
109    LoadedLibrary(Arc<LoadedLibrary>),
110    /// An ORCv2 ResourceTracker that owns JIT machine code.
111    /// Dropping the last reference calls `tracker.remove()`, freeing the code.
112    JitModule(Arc<JitCodeBacking>),
113}
114
115/// Owns a loaded shared library.
116///
117/// Dropping this unloads the library.
118pub(crate) struct LoadedLibrary {
119    /// The loaded library.
120    _library: libloading::Library,
121}
122
123impl LoadedLibrary {
124    /// Creates a new loaded library wrapper.
125    pub(crate) fn new(library: libloading::Library) -> Self {
126        Self { _library: library }
127    }
128}