Skip to content

Commit

Permalink
YJIT: add --yjit-disable-code-gc
Browse files Browse the repository at this point in the history
Will need a rebase for integrating with master since:
 - ruby#8582
 - ruby#8583
  • Loading branch information
XrXr committed Oct 4, 2023
1 parent accda74 commit f6c2f76
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 7 deletions.
1 change: 1 addition & 0 deletions ruby.c
Expand Up @@ -373,6 +373,7 @@ usage(const char *name, int help, int highlight, int columns)
M("--yjit-trace-exits", "", "Record Ruby source location when exiting from generated code"),
M("--yjit-trace-exits-sample-rate", "", "Trace exit locations only every Nth occurrence"),
M("--yjit-exec-mem-size=num", "", "Size of executable memory block in MiB (default: 128)"),
M("--yjit-disable-code-gc", "", "Don't run code GC after exhausting exec-mem-size"),
M("--yjit-call-threshold=num", "", "Number of calls to trigger JIT (default: 30)"),
M("--yjit-max-versions=num", "", "Maximum number of versions per basic block (default: 4)"),
M("--yjit-greedy-versioning", "", "Greedy versioning mode (default: disabled)"),
Expand Down
24 changes: 18 additions & 6 deletions yjit/src/core.rs
Expand Up @@ -2196,7 +2196,9 @@ pub fn gen_entry_point(iseq: IseqPtr, ec: EcPtr, jit_exception: bool) -> Option<
// Compilation failed
None => {
// Trigger code GC. This entry point will be recompiled later.
cb.code_gc(ocb);
if !get_option!(disable_code_gc) {
cb.code_gc(ocb);
}
return None;
}

Expand Down Expand Up @@ -2300,7 +2302,11 @@ fn entry_stub_hit_body(entry_ptr: *const c_void, ec: EcPtr) -> Option<*const u8>
Some(blockref) => blockref,
None => { // No space
// Trigger code GC. This entry point will be recompiled later.
cb.code_gc(ocb);
if !get_option!(disable_code_gc) {
cb.code_gc(ocb);
}
cb.mark_all_executable();
ocb.unwrap().mark_all_executable();
return None;
}
}
Expand Down Expand Up @@ -2488,6 +2494,9 @@ fn branch_stub_hit_body(branch_ptr: *const c_void, target_idx: u32, ec: EcPtr) -
(target.get_blockid(), target.get_ctx())
};

let cb = CodegenGlobals::get_inline_cb();
let ocb = CodegenGlobals::get_outlined_cb();

let (cfp, original_interp_sp) = unsafe {
let cfp = get_ec_cfp(ec);
let original_interp_sp = get_cfp_sp(cfp);
Expand All @@ -2509,6 +2518,10 @@ fn branch_stub_hit_body(branch_ptr: *const c_void, target_idx: u32, ec: EcPtr) -
// So we do it here instead.
rb_set_cfp_sp(cfp, reconned_sp);

if get_option!(disable_code_gc) && (cb.has_dropped_bytes() || ocb.unwrap().has_dropped_bytes()) {
return CodegenGlobals::get_stub_exit_code().raw_ptr();
}

// Bail if we're about to run out of native stack space.
// We've just reconstructed interpreter state.
if rb_ec_stack_check(ec as _) != 0 {
Expand All @@ -2518,9 +2531,6 @@ fn branch_stub_hit_body(branch_ptr: *const c_void, target_idx: u32, ec: EcPtr) -
(cfp, original_interp_sp)
};

let cb = CodegenGlobals::get_inline_cb();
let ocb = CodegenGlobals::get_outlined_cb();

// Try to find an existing compiled version of this block
let mut block = find_block_version(target_blockid, &target_ctx);
let mut branch_modified = false;
Expand Down Expand Up @@ -2586,7 +2596,9 @@ fn branch_stub_hit_body(branch_ptr: *const c_void, target_idx: u32, ec: EcPtr) -
// because incomplete code could be used when cb.dropped_bytes is flipped
// by code GC. So this place, after all compilation, is the safest place
// to hook code GC on branch_stub_hit.
cb.code_gc(ocb);
if !get_option!(disable_code_gc) {
cb.code_gc(ocb);
}

// Failed to service the stub by generating a new block so now we
// need to exit to the interpreter at the stubbed location. We are
Expand Down
15 changes: 14 additions & 1 deletion yjit/src/options.rs
Expand Up @@ -42,6 +42,9 @@ pub struct Options {
// compile anything)
pub pause: bool,

// Stop generating new code when exec_mem_size is reached. Don't run code GC
pub disable_code_gc: bool,

/// Dump compiled and executed instructions for debugging
pub dump_insns: bool,

Expand All @@ -68,6 +71,7 @@ pub static mut OPTIONS: Options = Options {
print_stats: true,
trace_exits_sample_rate: 0,
pause: false,
disable_code_gc: false,
dump_insns: false,
dump_disasm: None,
verify_ctx: false,
Expand All @@ -87,7 +91,12 @@ macro_rules! get_option {
// Unsafe is ok here because options are initialized
// once before any Ruby code executes
($option_name:ident) => {
unsafe { OPTIONS.$option_name }
{
// make this a statement since attributes on expressions are experimental
#[allow(unused_unsafe)]
let ret = unsafe { OPTIONS.$option_name };
ret
}
};
}
pub(crate) use get_option;
Expand Down Expand Up @@ -154,6 +163,10 @@ pub fn parse_option(str_ptr: *const std::os::raw::c_char) -> Option<()> {
OPTIONS.pause = true;
},

("disable-code-gc", "") => unsafe {
OPTIONS.disable_code_gc = true;
}

("temp-regs", _) => match opt_val.parse() {
Ok(n) => {
assert!(n <= TEMP_REGS.len(), "--yjit-temp-regs must be <= {}", TEMP_REGS.len());
Expand Down

0 comments on commit f6c2f76

Please sign in to comment.