Skip to content

Commit 5d03df9

Browse files
committed
Remove support for the lazy jit mode
I might re-implement it in the future, but would probably do so by replacing cranelift-jit. cranelift-jit's api doesn't quite work well for lazy jitting. And even so it adds complexity to cranelift-jit and breaks cranelift-jit outside of x86_64.
1 parent 0fcd068 commit 5d03df9

File tree

6 files changed

+18
-241
lines changed

6 files changed

+18
-241
lines changed

build_system/tests.rs

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -384,20 +384,6 @@ impl<'a> TestRunner<'a> {
384384
jit_cmd.env("CG_CLIF_JIT_ARGS", args);
385385
}
386386
spawn_and_wait(jit_cmd);
387-
388-
eprintln!("[JIT-lazy] {testname}");
389-
let mut jit_cmd = self.rustc_command([
390-
"-Zunstable-options",
391-
"-Cllvm-args=mode=jit-lazy",
392-
"-Cprefer-dynamic",
393-
source,
394-
"--cfg",
395-
"jit",
396-
]);
397-
if !args.is_empty() {
398-
jit_cmd.env("CG_CLIF_JIT_ARGS", args);
399-
}
400-
spawn_and_wait(jit_cmd);
401387
}
402388
}
403389
}

docs/usage.md

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -41,20 +41,13 @@ or
4141
$ $cg_clif_dir/dist/rustc-clif -Cllvm-args=jit-mode -Cprefer-dynamic my_crate.rs
4242
```
4343

44-
There is also an experimental lazy jit mode. In this mode functions are only compiled once they are
45-
first called.
46-
47-
```bash
48-
$ $cg_clif_dir/dist/cargo-clif lazy-jit
49-
```
50-
5144
## Shell
5245

5346
These are a few functions that allow you to easily run rust code from the shell using cg_clif as jit.
5447

5548
```bash
5649
function jit_naked() {
57-
echo "$@" | $cg_clif_dir/dist/rustc-clif - -Zunstable-options -Cllvm-args=jit-mode -Cllvm-args=jit-lazy -Cprefer-dynamic
50+
echo "$@" | $cg_clif_dir/dist/rustc-clif - -Zunstable-options -Cllvm-args=jit-mode-Cprefer-dynamic
5851
}
5952

6053
function jit() {

scripts/cargo-clif.rs

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -54,19 +54,6 @@ fn main() {
5454
])
5555
.collect()
5656
}
57-
Some("lazy-jit") => {
58-
rustflags.push("-Cprefer-dynamic".to_owned());
59-
args.remove(0);
60-
IntoIterator::into_iter(["rustc".to_string()])
61-
.chain(args)
62-
.chain([
63-
"--".to_string(),
64-
"-Zunstable-options".to_string(),
65-
"-Cllvm-args=jit-mode".to_string(),
66-
"-Cllvm-args=jit-lazy".to_string(),
67-
])
68-
.collect()
69-
}
7057
_ => args,
7158
};
7259

src/config.rs

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,6 @@ pub struct BackendConfig {
66
/// Defaults to AOT compilation. Can be set using `-Cllvm-args=jit-mode`.
77
pub jit_mode: bool,
88

9-
/// When JIT executing should the lazy JIT mode be used.
10-
///
11-
/// Defaults to false. Can be set using `-Cllvm-args=jit-lazy`.
12-
pub lazy_jit: bool,
13-
149
/// When JIT mode is enable pass these arguments to the program.
1510
///
1611
/// Defaults to the value of `CG_CLIF_JIT_ARGS`.
@@ -22,7 +17,6 @@ impl BackendConfig {
2217
pub fn from_opts(opts: &[String]) -> Result<Self, String> {
2318
let mut config = BackendConfig {
2419
jit_mode: false,
25-
lazy_jit: false,
2620
jit_args: match std::env::var("CG_CLIF_JIT_ARGS") {
2721
Ok(args) => args.split(' ').map(|arg| arg.to_string()).collect(),
2822
Err(std::env::VarError::NotPresent) => vec![],
@@ -40,7 +34,6 @@ impl BackendConfig {
4034
}
4135
match &**opt {
4236
"jit-mode" => config.jit_mode = true,
43-
"jit-lazy" => config.lazy_jit = true,
4437
_ => return Err(format!("Unknown option `{}`", opt)),
4538
}
4639
}

src/driver/jit.rs

Lines changed: 16 additions & 198 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,9 @@
11
//! The JIT driver uses [`cranelift_jit`] to JIT execute programs without writing any object
22
//! files.
33
4-
use std::cell::RefCell;
54
use std::ffi::CString;
65
use std::os::raw::{c_char, c_int};
7-
use std::sync::{Mutex, OnceLock, mpsc};
86

9-
use cranelift_frontend::{FunctionBuilder, FunctionBuilderContext};
107
use cranelift_jit::{JITBuilder, JITModule};
118
use rustc_codegen_ssa::CrateInfo;
129
use rustc_middle::mir::mono::MonoItem;
@@ -18,58 +15,13 @@ use crate::debuginfo::TypeDebugContext;
1815
use crate::prelude::*;
1916
use crate::unwind_module::UnwindModule;
2017

21-
struct JitState {
22-
jit_module: UnwindModule<JITModule>,
23-
}
24-
25-
thread_local! {
26-
static LAZY_JIT_STATE: RefCell<Option<JitState>> = const { RefCell::new(None) };
27-
}
28-
29-
/// The Sender owned by the rustc thread
30-
static GLOBAL_MESSAGE_SENDER: OnceLock<Mutex<mpsc::Sender<UnsafeMessage>>> = OnceLock::new();
31-
32-
/// A message that is sent from the jitted runtime to the rustc thread.
33-
/// Senders are responsible for upholding `Send` semantics.
34-
enum UnsafeMessage {
35-
/// Request that the specified `Instance` be lazily jitted.
36-
///
37-
/// Nothing accessible through `instance_ptr` may be moved or mutated by the sender after
38-
/// this message is sent.
39-
JitFn {
40-
instance_ptr: *const Instance<'static>,
41-
trampoline_ptr: *const u8,
42-
tx: mpsc::Sender<*const u8>,
43-
},
44-
}
45-
unsafe impl Send for UnsafeMessage {}
46-
47-
impl UnsafeMessage {
48-
/// Send the message.
49-
fn send(self) {
50-
thread_local! {
51-
/// The Sender owned by the local thread
52-
static LOCAL_MESSAGE_SENDER: mpsc::Sender<UnsafeMessage> =
53-
GLOBAL_MESSAGE_SENDER
54-
.get().unwrap()
55-
.lock().unwrap()
56-
.clone();
57-
}
58-
LOCAL_MESSAGE_SENDER.with(|sender| {
59-
sender.send(self).expect("rustc thread hung up before lazy JIT request was sent")
60-
})
61-
}
62-
}
63-
64-
fn create_jit_module(tcx: TyCtxt<'_>, hotswap: bool) -> (UnwindModule<JITModule>, CodegenCx) {
18+
fn create_jit_module(tcx: TyCtxt<'_>) -> (UnwindModule<JITModule>, CodegenCx) {
6519
let crate_info = CrateInfo::new(tcx, "dummy_target_cpu".to_string());
6620

6721
let isa = crate::build_isa(tcx.sess);
6822
let mut jit_builder = JITBuilder::with_isa(isa, cranelift_module::default_libcall_names());
69-
jit_builder.hotswap(hotswap);
7023
crate::compiler_builtins::register_functions_for_jit(&mut jit_builder);
7124
jit_builder.symbol_lookup_fn(dep_symbol_lookup_fn(tcx.sess, crate_info));
72-
jit_builder.symbol("__clif_jit_fn", clif_jit_fn as *const u8);
7325
let mut jit_module = UnwindModule::new(JITModule::new(jit_builder), false);
7426

7527
let cx = crate::CodegenCx::new(tcx, jit_module.isa(), false, sym::dummy_cgu_name);
@@ -79,7 +31,7 @@ fn create_jit_module(tcx: TyCtxt<'_>, hotswap: bool) -> (UnwindModule<JITModule>
7931
(jit_module, cx)
8032
}
8133

82-
pub(crate) fn run_jit(tcx: TyCtxt<'_>, jit_lazy: bool, jit_args: Vec<String>) -> ! {
34+
pub(crate) fn run_jit(tcx: TyCtxt<'_>, jit_args: Vec<String>) -> ! {
8335
if !tcx.sess.opts.output_types.should_codegen() {
8436
tcx.dcx().fatal("JIT mode doesn't work with `cargo check`");
8537
}
@@ -88,7 +40,7 @@ pub(crate) fn run_jit(tcx: TyCtxt<'_>, jit_lazy: bool, jit_args: Vec<String>) ->
8840
tcx.dcx().fatal("can't jit non-executable crate");
8941
}
9042

91-
let (mut jit_module, mut cx) = create_jit_module(tcx, jit_lazy);
43+
let (mut jit_module, mut cx) = create_jit_module(tcx);
9244
let mut cached_context = Context::new();
9345

9446
let cgus = tcx.collect_and_partition_mono_items(()).codegen_units;
@@ -105,17 +57,13 @@ pub(crate) fn run_jit(tcx: TyCtxt<'_>, jit_lazy: bool, jit_args: Vec<String>) ->
10557
for (mono_item, _) in mono_items {
10658
match mono_item {
10759
MonoItem::Fn(inst) => {
108-
if jit_lazy {
109-
codegen_shim(tcx, &mut cached_context, &mut jit_module, inst)
110-
} else {
111-
codegen_and_compile_fn(
112-
tcx,
113-
&mut cx,
114-
&mut cached_context,
115-
&mut jit_module,
116-
inst,
117-
);
118-
}
60+
codegen_and_compile_fn(
61+
tcx,
62+
&mut cx,
63+
&mut cached_context,
64+
&mut jit_module,
65+
inst,
66+
);
11967
}
12068
MonoItem::Static(def_id) => {
12169
crate::constant::codegen_static(tcx, &mut jit_module, def_id);
@@ -158,41 +106,17 @@ pub(crate) fn run_jit(tcx: TyCtxt<'_>, jit_lazy: bool, jit_args: Vec<String>) ->
158106
let start_func_id = jit_module.declare_function("main", Linkage::Import, &start_sig).unwrap();
159107
let finalized_start: *const u8 = jit_module.module.get_finalized_function(start_func_id);
160108

161-
LAZY_JIT_STATE.with(|lazy_jit_state| {
162-
let mut lazy_jit_state = lazy_jit_state.borrow_mut();
163-
assert!(lazy_jit_state.is_none());
164-
*lazy_jit_state = Some(JitState { jit_module });
165-
});
166-
167109
let f: extern "C" fn(c_int, *const *const c_char) -> c_int =
168110
unsafe { ::std::mem::transmute(finalized_start) };
169111

170-
let (tx, rx) = mpsc::channel();
171-
GLOBAL_MESSAGE_SENDER.set(Mutex::new(tx)).unwrap();
172-
173-
// Spawn the jitted runtime in a new thread so that this rustc thread can handle messages
174-
// (eg to lazily JIT further functions as required)
175-
std::thread::spawn(move || {
176-
let mut argv = args.iter().map(|arg| arg.as_ptr()).collect::<Vec<_>>();
112+
let mut argv = args.iter().map(|arg| arg.as_ptr()).collect::<Vec<_>>();
177113

178-
// Push a null pointer as a terminating argument. This is required by POSIX and
179-
// useful as some dynamic linkers use it as a marker to jump over.
180-
argv.push(std::ptr::null());
114+
// Push a null pointer as a terminating argument. This is required by POSIX and
115+
// useful as some dynamic linkers use it as a marker to jump over.
116+
argv.push(std::ptr::null());
181117

182-
let ret = f(args.len() as c_int, argv.as_ptr());
183-
std::process::exit(ret);
184-
});
185-
186-
// Handle messages
187-
loop {
188-
match rx.recv().unwrap() {
189-
// lazy JIT compilation request - compile requested instance and return pointer to result
190-
UnsafeMessage::JitFn { instance_ptr, trampoline_ptr, tx } => {
191-
tx.send(jit_fn(instance_ptr, trampoline_ptr))
192-
.expect("jitted runtime hung up before response to lazy JIT request was sent");
193-
}
194-
}
195-
}
118+
let ret = f(args.len() as c_int, argv.as_ptr());
119+
std::process::exit(ret);
196120
}
197121

198122
pub(crate) fn codegen_and_compile_fn<'tcx>(
@@ -224,58 +148,6 @@ pub(crate) fn codegen_and_compile_fn<'tcx>(
224148
});
225149
}
226150

227-
extern "C" fn clif_jit_fn(
228-
instance_ptr: *const Instance<'static>,
229-
trampoline_ptr: *const u8,
230-
) -> *const u8 {
231-
// send the JIT request to the rustc thread, with a channel for the response
232-
let (tx, rx) = mpsc::channel();
233-
UnsafeMessage::JitFn { instance_ptr, trampoline_ptr, tx }.send();
234-
235-
// block on JIT compilation result
236-
rx.recv().expect("rustc thread hung up before responding to sent lazy JIT request")
237-
}
238-
239-
fn jit_fn(instance_ptr: *const Instance<'static>, trampoline_ptr: *const u8) -> *const u8 {
240-
rustc_middle::ty::tls::with(|tcx| {
241-
// lift is used to ensure the correct lifetime for instance.
242-
let instance = tcx.lift(unsafe { *instance_ptr }).unwrap();
243-
244-
LAZY_JIT_STATE.with(|lazy_jit_state| {
245-
let mut lazy_jit_state = lazy_jit_state.borrow_mut();
246-
let lazy_jit_state = lazy_jit_state.as_mut().unwrap();
247-
let jit_module = &mut lazy_jit_state.jit_module;
248-
249-
let name = tcx.symbol_name(instance).name;
250-
let sig = crate::abi::get_function_sig(
251-
tcx,
252-
jit_module.target_config().default_call_conv,
253-
instance,
254-
);
255-
let func_id = jit_module.declare_function(name, Linkage::Export, &sig).unwrap();
256-
257-
let current_ptr = jit_module.module.read_got_entry(func_id);
258-
259-
// If the function's GOT entry has already been updated to point at something other
260-
// than the shim trampoline, don't re-jit but just return the new pointer instead.
261-
// This does not need synchronization as this code is executed only by a sole rustc
262-
// thread.
263-
if current_ptr != trampoline_ptr {
264-
return current_ptr;
265-
}
266-
267-
jit_module.module.prepare_for_function_redefine(func_id).unwrap();
268-
269-
let mut cx = crate::CodegenCx::new(tcx, jit_module.isa(), false, sym::dummy_cgu_name);
270-
codegen_and_compile_fn(tcx, &mut cx, &mut Context::new(), jit_module, instance);
271-
272-
assert!(cx.global_asm.is_empty());
273-
jit_module.finalize_definitions();
274-
jit_module.module.get_finalized_function(func_id)
275-
})
276-
})
277-
}
278-
279151
fn dep_symbol_lookup_fn(
280152
sess: &Session,
281153
crate_info: CrateInfo,
@@ -323,57 +195,3 @@ fn dep_symbol_lookup_fn(
323195
None
324196
})
325197
}
326-
327-
fn codegen_shim<'tcx>(
328-
tcx: TyCtxt<'tcx>,
329-
cached_context: &mut Context,
330-
module: &mut UnwindModule<JITModule>,
331-
inst: Instance<'tcx>,
332-
) {
333-
let pointer_type = module.target_config().pointer_type();
334-
335-
let name = tcx.symbol_name(inst).name;
336-
let sig = crate::abi::get_function_sig(tcx, module.target_config().default_call_conv, inst);
337-
let func_id = module.declare_function(name, Linkage::Export, &sig).unwrap();
338-
339-
let instance_ptr = Box::into_raw(Box::new(inst));
340-
341-
let jit_fn = module
342-
.declare_function(
343-
"__clif_jit_fn",
344-
Linkage::Import,
345-
&Signature {
346-
call_conv: module.target_config().default_call_conv,
347-
params: vec![AbiParam::new(pointer_type), AbiParam::new(pointer_type)],
348-
returns: vec![AbiParam::new(pointer_type)],
349-
},
350-
)
351-
.unwrap();
352-
353-
let context = cached_context;
354-
context.clear();
355-
let trampoline = &mut context.func;
356-
trampoline.signature = sig.clone();
357-
358-
let mut builder_ctx = FunctionBuilderContext::new();
359-
let mut trampoline_builder = FunctionBuilder::new(trampoline, &mut builder_ctx);
360-
361-
let trampoline_fn = module.declare_func_in_func(func_id, trampoline_builder.func);
362-
let jit_fn = module.declare_func_in_func(jit_fn, trampoline_builder.func);
363-
let sig_ref = trampoline_builder.func.import_signature(sig);
364-
365-
let entry_block = trampoline_builder.create_block();
366-
trampoline_builder.append_block_params_for_function_params(entry_block);
367-
let fn_args = trampoline_builder.func.dfg.block_params(entry_block).to_vec();
368-
369-
trampoline_builder.switch_to_block(entry_block);
370-
let instance_ptr = trampoline_builder.ins().iconst(pointer_type, instance_ptr as u64 as i64);
371-
let trampoline_ptr = trampoline_builder.ins().func_addr(pointer_type, trampoline_fn);
372-
let jitted_fn = trampoline_builder.ins().call(jit_fn, &[instance_ptr, trampoline_ptr]);
373-
let jitted_fn = trampoline_builder.func.dfg.inst_results(jitted_fn)[0];
374-
let call_inst = trampoline_builder.ins().call_indirect(sig_ref, jitted_fn, &fn_args);
375-
let ret_vals = trampoline_builder.func.dfg.inst_results(call_inst).to_vec();
376-
trampoline_builder.ins().return_(&ret_vals);
377-
378-
module.define_function(func_id, context).unwrap();
379-
}

src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,7 @@ impl CodegenBackend for CraneliftCodegenBackend {
215215
});
216216
if config.jit_mode {
217217
#[cfg(feature = "jit")]
218-
driver::jit::run_jit(tcx, config.lazy_jit, config.jit_args);
218+
driver::jit::run_jit(tcx, config.jit_args);
219219

220220
#[cfg(not(feature = "jit"))]
221221
tcx.dcx().fatal("jit support was disabled when compiling rustc_codegen_cranelift");

0 commit comments

Comments
 (0)