Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
80ce780
feat(runtime): add JIT process mode
DaniPopes Apr 29, 2026
d4ffc0b
feat(llvm): link JIT object buffers
DaniPopes Apr 29, 2026
c01b57c
feat(codegen): emit objects from JIT modules
DaniPopes Apr 29, 2026
3ad367a
feat(runtime): link worker-emitted JIT objects
DaniPopes Apr 29, 2026
ca6f8bc
feat(runtime): spawn JIT helper processes
DaniPopes Apr 29, 2026
567674d
docs: update out-of-process JIT status
DaniPopes Apr 29, 2026
e193770
feat(runtime): configure JIT helper path
DaniPopes Apr 29, 2026
158ccb5
fix(runtime): reject unsupported helper options
DaniPopes Apr 29, 2026
7228bda
feat(runtime): keep persistent JIT helpers
DaniPopes Apr 29, 2026
fac7b9f
refactor(runtime): rename JIT mode config
DaniPopes Apr 29, 2026
18a9ff1
refactor(runtime): share JIT helper process
DaniPopes Apr 29, 2026
e541a98
refactor(llvm): reuse ensured ORC state
DaniPopes Apr 29, 2026
8fd53ed
refactor(runtime): encapsulate JIT helper state
DaniPopes Apr 29, 2026
4913491
refactor(runtime): use JSON helper IPC
DaniPopes Apr 29, 2026
fd6df05
refactor(runtime): use domain types in JIT IPC
DaniPopes Apr 29, 2026
b6dad68
Merge remote-tracking branch 'origin/main' into dani/out-of-process-jit
DaniPopes May 16, 2026
1edc3cf
fix(runtime): wire out-of-process jit env
DaniPopes May 16, 2026
1361e41
fix(runtime): link out-of-process jit objects
DaniPopes May 16, 2026
dd4eb94
fix(runtime): cancel out-of-process jit helper
DaniPopes May 16, 2026
0863c98
fix(runtime): refine out-of-process jit ipc
DaniPopes May 16, 2026
d409fb0
fix(runtime): bound jit helper shutdown
DaniPopes May 16, 2026
bb46d4c
fix(runtime): use wincode schemas for ipc
DaniPopes May 16, 2026
4c2e625
fix(runtime): stream jit helper ipc writes
DaniPopes May 16, 2026
da3b32a
fix(runtime): stream jit helper ipc reads
DaniPopes May 16, 2026
eb1a410
fix(runtime): use wincode std ipc adapters
DaniPopes May 16, 2026
29f5ce4
fix(runtime): scope jit helper cancellation
DaniPopes May 17, 2026
5b0bb53
fix(runtime): carry jit helper config
DaniPopes May 18, 2026
37dde3c
fix(runtime): reuse jit object linker
DaniPopes May 18, 2026
3fb4d2c
fix(runtime): log jit helper restarts
DaniPopes May 18, 2026
a1eb76b
static
DaniPopes May 18, 2026
4878a17
fix(runtime): kill stalled jit helper groups
DaniPopes May 18, 2026
eb3d846
refactor(runtime): gate jit helper on unix
DaniPopes May 18, 2026
e91d7ad
refactor(runtime): use wincode stream framing
DaniPopes May 18, 2026
6273c0b
refactor(runtime): remove helper stream peek
DaniPopes May 18, 2026
7838d64
refactor(runtime): share jit compile state
DaniPopes May 18, 2026
9e615f3
fix(runtime): isolate linked jit objects
DaniPopes May 19, 2026
62c9a93
feat(runtime): track jit helper stats
DaniPopes May 19, 2026
1e249be
feat(runtime): parallelize jit helper jobs
DaniPopes May 19, 2026
83190a1
feat(runtime): pause background jit
DaniPopes May 19, 2026
42b3879
fix(runtime): signal jit helper on pause
DaniPopes May 19, 2026
fcf9273
fix(runtime): keep events flowing while paused
DaniPopes May 19, 2026
f5c352d
fix(runtime): gracefully pause jit helper
DaniPopes May 19, 2026
668dbb9
test(runtime): cover jit helper pause
DaniPopes May 19, 2026
4e6efca
feat(runtime): track jit helper pause metrics
DaniPopes May 19, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 75 additions & 5 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ revm-statetest-types = { version = "17.0.0", default-features = false }

crossbeam-channel = "0.5"
crossbeam-queue = "0.3"
libc = "0.2"
rayon = "1.10"
color-eyre = "0.6"
criterion = { package = "codspeed-criterion-compat", version = "4", default-features = false, features = ["cargo_bench_support"] }
Expand All @@ -72,6 +73,8 @@ tracing-subscriber = "0.3"
tracing-tracy = "0.11"
paste = "1.0"
quanta = "0.12"
wait-timeout = "0.2"
wincode = { version = "0.5.4", features = ["derive"] }

[profile.dev]
opt-level = 3
Expand Down
8 changes: 8 additions & 0 deletions crates/revmc-builtins/src/ir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ macro_rules! builtins {
#[allow(unused_variables)]
impl Builtin {
pub const COUNT: usize = builtins!(@count $($ident),*);
pub const ALL: &[Self; Self::COUNT] = &[$(Self::$ident),*];

pub const fn name(self) -> &'static str {
match self {
Expand All @@ -139,6 +140,13 @@ macro_rules! builtins {
}
}

pub fn parse(name: &str) -> Option<Self> {
match name {
$(stringify!($name) => Some(Self::$ident),)*
_ => None,
}
}

pub fn ret<B: TypeMethods>(self, $bcx: &mut B) -> Option<B::Type> {
$($types_init)*
match self {
Expand Down
3 changes: 3 additions & 0 deletions crates/revmc-cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ enum Command {
}

fn main() -> Result<()> {
if revmc::runtime::maybe_run_jit_helper()?.is_break() {
return Ok(());
}
if std::env::var_os("RUST_BACKTRACE").is_none() {
// SAFETY: This is called at the very beginning of main, before any other threads are
// spawned.
Expand Down
3 changes: 1 addition & 2 deletions crates/revmc-codegen/src/compiler/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -502,9 +502,8 @@ impl<B: Backend> EvmCompiler<B> {
Ok(())
}

/// (AOT) Finalizes the module and writes the compiled object to the given writer.
/// Finalizes the module and writes the compiled object to the given writer.
pub fn write_object<W: io::Write>(&mut self, w: W) -> Result<()> {
ensure!(self.is_aot(), "cannot write AOT object during JIT compilation");
self.finalize()?;
{
let _t = self.remarks.time(|r| &r.codegen);
Expand Down
54 changes: 53 additions & 1 deletion crates/revmc-llvm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ use revmc_backend::{
};
use std::{
cell::Cell,
ffi::CString,
ffi::{CStr, CString},
fmt::{self, Write},
iter,
mem::ManuallyDrop,
Expand Down Expand Up @@ -453,6 +453,20 @@ impl OrcJitState {
}
}

fn link_jit_object_in_dylib(
orc: &OrcJitState,
jd: orc::JITDylibRef,
symbol_name: &CStr,
object: &[u8],
symbols: &[(CString, usize)],
) -> Result<(usize, orc::ResourceTracker)> {
orc.global.define_builtins(symbols);
let tracker = jd.create_resource_tracker();
orc.global.jit.add_object_with_rt(symbol_name, object, &tracker).map_err(error_msg)?;
let addr = orc.global.jit.lookup_in(jd, symbol_name).map_err(error_msg)?;
Ok((addr, tracker))
}

/// Wraps a module in a [`orc::ThreadSafeModule`] for transfer to LLJIT.
///
/// Uses a raw pointer cast to work around `Module<'ctx>` invariance — the module's
Expand Down Expand Up @@ -738,6 +752,44 @@ impl EvmLlvmBackend {
Ok(())
}

/// Returns pending absolute symbols collected while translating the current JIT module.
pub fn pending_symbol_names(&self) -> Vec<CString> {
self.orc
.as_ref()
.map(|orc| orc.pending_symbols.iter().map(|(name, _)| name.clone()).collect())
.unwrap_or_default()
}

/// Links a relocatable object into this backend's JITDylib and returns the function address
/// and resource tracker that owns the linked code.
pub fn link_jit_object(
&mut self,
symbol_name: &CStr,
object: &[u8],
symbols: &[(CString, usize)],
) -> Result<(usize, orc::ResourceTracker)> {
let orc = self.ensure_orc()?;
let (addr, tracker) =
link_jit_object_in_dylib(orc, orc.jd(), symbol_name, object, symbols)?;
orc.loaded_trackers.push(tracker);
Ok((addr, orc.loaded_trackers.pop().unwrap()))
}

/// Links a relocatable object into a fresh JITDylib and returns the function address,
/// resource tracker, and guard for the JITDylib that owns the linked code.
pub fn link_jit_object_in_fresh_dylib(
&mut self,
symbol_name: &CStr,
object: &[u8],
symbols: &[(CString, usize)],
) -> Result<(usize, orc::ResourceTracker, Arc<JitDylibGuard>)> {
let orc = self.ensure_orc()?;
let jd = orc.global.create_jit_dylib();
let jd_guard = Arc::new(JitDylibGuard { global: orc.global, jd });
let (addr, tracker) = link_jit_object_in_dylib(orc, jd, symbol_name, object, symbols)?;
Ok((addr, tracker, jd_guard))
}

/// Pops and returns the [`ResourceTracker`](orc::ResourceTracker) for the last committed
/// JIT module.
///
Expand Down
22 changes: 21 additions & 1 deletion crates/revmc-llvm/src/orc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,10 @@ use crate::llvm_string;
use inkwell::{
context::Context,
llvm_sys::{
core::{LLVMContextCreate, LLVMModuleCreateWithNameInContext},
core::{
LLVMContextCreate, LLVMCreateMemoryBufferWithMemoryRangeCopy,
LLVMModuleCreateWithNameInContext,
},
error::*,
orc2::{lljit::*, *},
prelude::*,
Expand Down Expand Up @@ -1398,6 +1401,23 @@ impl LLJIT {
})
}

/// Add a relocatable object file to the given ResourceTracker's JITDylib.
pub fn add_object_with_rt(
&self,
name: &CStr,
object: &[u8],
rt: &ResourceTracker,
) -> Result<(), LLVMString> {
let buf = unsafe {
LLVMCreateMemoryBufferWithMemoryRangeCopy(
object.as_ptr().cast(),
object.len(),
name.as_ptr(),
)
};
cvt(unsafe { LLVMOrcLLJITAddObjectFileWithRT(self.as_inner(), rt.as_inner(), buf) })
}

/// Gets the execution session.
pub fn get_execution_session(&self) -> ExecutionSessionRef<'_> {
unsafe { ExecutionSessionRef::from_inner(LLVMOrcLLJITGetExecutionSession(self.as_inner())) }
Expand Down
4 changes: 4 additions & 0 deletions crates/revmc-runtime/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ revmc-backend.workspace = true
revmc-codegen.workspace = true
revmc-context = { workspace = true, features = ["evm"] }
revmc-llvm = { workspace = true, optional = true }
revmc-builtins = { workspace = true, features = ["ir"] }

alloy-primitives = { workspace = true, features = ["std", "map-fxhash"] }
alloy-evm = { workspace = true, optional = true }
Expand All @@ -45,11 +46,14 @@ crossbeam-queue.workspace = true
dashmap = "6"
derive_more = { version = "2", default-features = false, features = ["debug"] }
eyre.workspace = true
libc.workspace = true
libloading = "0.9"
tempfile = "3.10"
quanta.workspace = true
rayon.workspace = true
tracing.workspace = true
wait-timeout.workspace = true
wincode.workspace = true

[dev-dependencies]
revmc-statetest = { path = "../revmc-statetest" }
Expand Down
Loading
Loading