-
Notifications
You must be signed in to change notification settings - Fork 103
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
In-place binary/jit updating #1087
Comments
Thanks for pointing me to that post! Binary patching is probably hard to implement. Doing this for the JIT mode of cg_clif is much more possible. cranelift-simplejit currently doesn't support hot code swapping. I already wanted to implement this for lazy compilation in JIT mode though. Rustc doesn't have a |
@bjorn3 That's fantastic, I'm glad to hear that the prerequisite components for this to work are mostly already on the roadmap. As for the binary reloading, I don't think it'd actually be too bad, since the way that Zig does this is by including a function lookup table in the binary that can be modified very easily to redirect functions to new versions. It would require logic for each output format (mach, elf, pe, wasm, etc) though. I am more immediately excited for a jit mode, since continuous in-memory compilation would be faster than touching disk anyhow. |
I have been trying to revive an old branch for lazy compilation in jit mode. Currently the following program sometimes panics. (about one in five tries I think) #![feature(
no_core, start, lang_items, box_syntax, never_type, linkage,
extern_types, thread_local
)]
#![no_core]
#![allow(dead_code, non_camel_case_types)]
extern crate mini_core;
use mini_core::*;
use mini_core::libc::*;
unsafe extern "C" fn my_puts(s: *const i8) {
puts(s);
}
#[lang = "termination"]
trait Termination {
fn report(self) -> i32;
}
impl Termination for () {
fn report(self) -> i32 {
unsafe {
0
}
}
}
#[lang = "start"]
fn start<T: Termination + 'static>(
main: fn() -> T,
argc: isize,
argv: *const *const u8,
) -> isize {
main().report();
0
}
macro_rules! assert_eq {
($l:expr, $r: expr) => {
if $l != $r {
panic(stringify!($l != $r));
}
}
}
struct Unique<T: ?Sized> {
pointer: *const T,
_marker: PhantomData<T>,
}
impl<T: ?Sized, U: ?Sized> CoerceUnsized<Unique<U>> for Unique<T> where T: Unsize<U> {}
fn take_unique(_u: Unique<()>) {}
fn main() {
take_unique(Unique {
pointer: 0 as *const (),
_marker: PhantomData,
});
extern {
#[linkage = "extern_weak"]
static ABC: *const u8;
}
{
extern {
#[linkage = "extern_weak"]
static ABC: *const u8;
}
}
unsafe { assert_eq!(ABC as usize, 0); }
} |
Found the problem. I wasn't correctly saving definitions of weak linkage statics. |
Currently lazy jit compilation is significantly slower. Probably because of the fact that once a function is jitted, previous references of it still go through the compilation shim.
This should be fixable using a GOT, which would also help with other kinds of function replacement, like the in-place jit updating proposed by this issue. |
Implemented a GOT+PLT for SimpleJIT. It mostly works, but crashes for mutable static writes. (haven't tried reads) #![feature(
no_core, start, lang_items, box_syntax, never_type, linkage,
extern_types, thread_local
)]
#![no_core]
extern crate mini_core;
#[lang = "start"]
fn start(main: fn(), argc: isize, argv: *const *const u8) -> isize {
unsafe {
NUM = 43;
}
0
}
static mut NUM: u8 = 6 * 7;
fn main() {}
|
Looks like you're getting there! |
I was accidentally reading the got entry in Edit: |
Discussion on the Bevy discord about how to handle changing types in case of hot code swapping: https://discord.com/channels/691052431525675048/692572690833473578/828930167648813086 |
…r=wesleywiser Introduce CompileMonoItem DepNode This is likely required for allowing efficient hot code swap support in cg_clif's jit mode. My prototype currently requires re-compiling all functions, which is both slow and uses a lot of memory as there is not support for freeing the memory used by replaced functions yet. cc https://github.com/bjorn3/rustc_codegen_cranelift/issues/1087
For future reference: some more discussion at https://discord.com/channels/691052431525675048/730525730601041940/866626266173276170 |
Hi @bjorn3, |
There is no support for in place binary patching. The default system linker is used by cg_clif. Supporting in place binary patching requires a linker with specific support for this, which the system linker doesn't have. As for jitting, there is support for a jit mode (disabled in the rustup distributed version of cg_clif), but it is generally slower than aot compilation as it is entirely incompatible with incr comp. There is a branch for runtime patching in jit mode, but I haven't touched it in years and it leaks a lot of memory on every update, quickly leading to a crash. |
Is using Zig as a linker an option? They explicitly have binary patching style linking as a feature. There's a cargo plugin for Zig and some positive experience reports: https://users.rust-lang.org/t/costs-of-using-zig-linker/88525 Andrew Kelley had a live coding session on Vimeo where he hot-swapped parts of the program via ptrace API on Linux. All done in milliseconds. Sadly, it seems the video got deleted since and I can't find it anymore. There's an open GitHub issue about this functionality so it's not finished. It would be fantastic if Rust feedback cycles could be shortened thanks to Cranelift. |
My understanding is that |
Loris Cro and Andrew Kelley recently published a blog post (https://kristoff.it/blog/zig-new-relationship-llvm/) about Ziglang's new self-hosted compiler. Part of the post is about how they can do in-place patching of the binary to avoid doing linking when changing small amounts of code (or maybe larger amounts too, I'm not sure). This seems extremely powerful. Linking is consistently a significant bottleneck in compiling rust, and completely skipping it would probably result in crazy speedups for compiling.
I'm proposing that this project pursue this either in a similar way to Zig, by patching individual functions in the output binary, or by keeping the jit open and recompiling individual functions as the source changes.
The text was updated successfully, but these errors were encountered: