Skip to content

Commit 48d0c5a

Browse files
committed
YJIT: Fix panic from overly loose filtering in identity method inlining
Credits to @rwstauner for noticing this issue in rubyGH-15533.
1 parent e76adc6 commit 48d0c5a

2 files changed

Lines changed: 21 additions & 0 deletions

File tree

bootstraptest/test_yjit.rb

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5528,3 +5528,18 @@ def jit_caller = test_body("session_id")
55285528
alias some_method binding # induce environment escape
55295529
test_body(:symbol)
55305530
}
5531+
5532+
# regression test for missing check in identity method inlining
5533+
assert_normal_exit %q{
5534+
# Use dead code (if false) to create a local
5535+
# without initialization instructions.
5536+
def foo(a)
5537+
if false
5538+
x = nil
5539+
end
5540+
x
5541+
end
5542+
def test = foo(1)
5543+
test
5544+
test
5545+
}

yjit/src/codegen.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7455,6 +7455,12 @@ fn iseq_get_return_value(iseq: IseqPtr, captured_opnd: Option<Opnd>, block: Opti
74557455
let ep_offset = unsafe { *rb_iseq_pc_at_idx(iseq, 1) }.as_u32();
74567456
let local_idx = ep_offset_to_local_idx(iseq, ep_offset);
74577457

7458+
// Only inline getlocal on a parameter. DCE in the IESQ builder can
7459+
// make a two-instruction ISEQ that does not return a parameter.
7460+
if local_idx >= unsafe { get_iseq_body_param_size(iseq) } {
7461+
return None;
7462+
}
7463+
74587464
if unsafe { rb_simple_iseq_p(iseq) } {
74597465
return Some(IseqReturn::LocalVariable(local_idx));
74607466
} else if unsafe { rb_iseq_only_kwparam_p(iseq) } {

0 commit comments

Comments
 (0)