Skip to content

Commit 30a5b94

Browse files
maximecbk0kubun
andauthored
YJIT: implement side chain fallback for setlocal to avoid exiting (#8227)
* YJIT: implement side chain fallback for setlocal to avoid exiting * Update yjit/src/codegen.rs Co-authored-by: Takashi Kokubun <takashikkbn@gmail.com> --------- Co-authored-by: Takashi Kokubun <takashikkbn@gmail.com>
1 parent 7433c8f commit 30a5b94

File tree

6 files changed

+50
-10
lines changed

6 files changed

+50
-10
lines changed

test/ruby/test_yjit.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -661,7 +661,7 @@ def jit_method
661661

662662
def test_send_block
663663
# Setlocal_wc_0 sometimes side-exits on write barrier
664-
assert_compiles(<<~'RUBY', result: "b:n/b:y/b:y/b:n", exits: { :setlocal_WC_0 => 0..1 })
664+
assert_compiles(<<~'RUBY', result: "b:n/b:y/b:y/b:n")
665665
def internal_method(&b)
666666
"b:#{block_given? ? "y" : "n"}"
667667
end

vm_core.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1758,6 +1758,7 @@ rb_thread_t * ruby_thread_from_native(void);
17581758
int ruby_thread_set_native(rb_thread_t *th);
17591759
int rb_vm_control_frame_id_and_class(const rb_control_frame_t *cfp, ID *idp, ID *called_idp, VALUE *klassp);
17601760
void rb_vm_rewind_cfp(rb_execution_context_t *ec, rb_control_frame_t *cfp);
1761+
void rb_vm_env_write(const VALUE *ep, int index, VALUE v);
17611762
VALUE rb_vm_bh_to_procval(const rb_execution_context_t *ec, VALUE block_handler);
17621763

17631764
void rb_vm_register_special_exception_str(enum ruby_special_exceptions sp, VALUE exception_class, VALUE mesg);

vm_insnhelper.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -505,6 +505,12 @@ vm_env_write(const VALUE *ep, int index, VALUE v)
505505
}
506506
}
507507

508+
void
509+
rb_vm_env_write(const VALUE *ep, int index, VALUE v)
510+
{
511+
vm_env_write(ep, index, v);
512+
}
513+
508514
VALUE
509515
rb_vm_bh_to_procval(const rb_execution_context_t *ec, VALUE block_handler)
510516
{

yjit/bindgen/src/main.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,7 @@ fn main() {
283283
.blocklist_type("rb_control_frame_struct")
284284
.opaque_type("rb_control_frame_struct")
285285
.allowlist_function("rb_vm_bh_to_procval")
286+
.allowlist_function("rb_vm_env_write")
286287
.allowlist_function("rb_vm_ep_local_ep")
287288
.allowlist_type("vm_special_object_type")
288289
.allowlist_var("VM_ENV_DATA_INDEX_SPECVAL")

yjit/src/codegen.rs

Lines changed: 40 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1546,8 +1546,7 @@ fn gen_expandarray(
15461546

15471547
let array_opnd = asm.stack_opnd(0);
15481548

1549-
// num is the number of requested values. If there aren't enough in the
1550-
// array then we're going to push on nils.
1549+
// If the array operand is nil, just push on nils
15511550
if asm.ctx.get_opnd_type(array_opnd.into()) == Type::Nil {
15521551
asm.stack_pop(1); // pop after using the type info
15531552
// special case for a, b = nil pattern
@@ -1762,6 +1761,7 @@ fn gen_getlocal_wc1(
17621761
fn gen_setlocal_generic(
17631762
jit: &mut JITState,
17641763
asm: &mut Assembler,
1764+
ocb: &mut OutlinedCb,
17651765
ep_offset: u32,
17661766
level: u32,
17671767
) -> Option<CodegenStatus> {
@@ -1770,6 +1770,29 @@ fn gen_setlocal_generic(
17701770
// Load environment pointer EP at level
17711771
let ep_opnd = gen_get_ep(asm, level);
17721772

1773+
// Fallback because of write barrier
1774+
if asm.ctx.get_chain_depth() > 0
1775+
{
1776+
// Save the PC and SP because it runs GC
1777+
jit_prepare_routine_call(jit, asm);
1778+
1779+
// Pop the value to write from the stack
1780+
let value_opnd = asm.stack_pop(1);
1781+
1782+
// void rb_vm_env_write(const VALUE *ep, int index, VALUE v)
1783+
let index = -(ep_offset as i64);
1784+
asm.ccall(
1785+
rb_vm_env_write as *const u8,
1786+
vec![
1787+
ep_opnd,
1788+
index.into(),
1789+
value_opnd,
1790+
]
1791+
);
1792+
1793+
return Some(KeepCompiling);
1794+
}
1795+
17731796
// Write barriers may be required when VM_ENV_FLAG_WB_REQUIRED is set, however write barriers
17741797
// only affect heap objects being written. If we know an immediate value is being written we
17751798
// can skip this check.
@@ -1783,7 +1806,15 @@ fn gen_setlocal_generic(
17831806
asm.test(flags_opnd, VM_ENV_FLAG_WB_REQUIRED.into());
17841807

17851808
// if (flags & VM_ENV_FLAG_WB_REQUIRED) != 0
1786-
asm.jnz(Target::side_exit(Counter::setlocal_wb_required));
1809+
assert!(asm.ctx.get_chain_depth() == 0);
1810+
jit_chain_guard(
1811+
JCC_JNZ,
1812+
jit,
1813+
asm,
1814+
ocb,
1815+
1,
1816+
Counter::setlocal_wb_required,
1817+
);
17871818
}
17881819

17891820
if level == 0 {
@@ -1804,29 +1835,29 @@ fn gen_setlocal_generic(
18041835
fn gen_setlocal(
18051836
jit: &mut JITState,
18061837
asm: &mut Assembler,
1807-
_ocb: &mut OutlinedCb,
1838+
ocb: &mut OutlinedCb,
18081839
) -> Option<CodegenStatus> {
18091840
let idx = jit.get_arg(0).as_u32();
18101841
let level = jit.get_arg(1).as_u32();
1811-
gen_setlocal_generic(jit, asm, idx, level)
1842+
gen_setlocal_generic(jit, asm, ocb, idx, level)
18121843
}
18131844

18141845
fn gen_setlocal_wc0(
18151846
jit: &mut JITState,
18161847
asm: &mut Assembler,
1817-
_ocb: &mut OutlinedCb,
1848+
ocb: &mut OutlinedCb,
18181849
) -> Option<CodegenStatus> {
18191850
let idx = jit.get_arg(0).as_u32();
1820-
gen_setlocal_generic(jit, asm, idx, 0)
1851+
gen_setlocal_generic(jit, asm, ocb, idx, 0)
18211852
}
18221853

18231854
fn gen_setlocal_wc1(
18241855
jit: &mut JITState,
18251856
asm: &mut Assembler,
1826-
_ocb: &mut OutlinedCb,
1857+
ocb: &mut OutlinedCb,
18271858
) -> Option<CodegenStatus> {
18281859
let idx = jit.get_arg(0).as_u32();
1829-
gen_setlocal_generic(jit, asm, idx, 1)
1860+
gen_setlocal_generic(jit, asm, ocb, idx, 1)
18301861
}
18311862

18321863
// new hash initialized from top N values

yjit/src/cruby_bindings.inc.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1166,6 +1166,7 @@ extern "C" {
11661166
pub static mut rb_block_param_proxy: VALUE;
11671167
pub fn rb_vm_ep_local_ep(ep: *const VALUE) -> *const VALUE;
11681168
pub fn rb_iseq_path(iseq: *const rb_iseq_t) -> VALUE;
1169+
pub fn rb_vm_env_write(ep: *const VALUE, index: ::std::os::raw::c_int, v: VALUE);
11691170
pub fn rb_vm_bh_to_procval(ec: *const rb_execution_context_t, block_handler: VALUE) -> VALUE;
11701171
pub fn rb_vm_frame_method_entry(
11711172
cfp: *const rb_control_frame_t,

0 commit comments

Comments
 (0)