Skip to content

Commit 73fdd90

Browse files
authored
ZJIT: Compile opt_new to slow-path SendWithoutBlock (#13216)
1 parent c659919 commit 73fdd90

File tree

1 file changed

+86
-0
lines changed

1 file changed

+86
-0
lines changed

zjit/src/hir.rs

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1600,6 +1600,10 @@ fn compute_jump_targets(iseq: *const rb_iseq_t) -> Vec<u32> {
16001600
let offset = get_arg(pc, 0).as_i64();
16011601
jump_targets.insert(insn_idx_at_offset(insn_idx, offset));
16021602
}
1603+
YARVINSN_opt_new => {
1604+
let offset = get_arg(pc, 1).as_i64();
1605+
jump_targets.insert(insn_idx_at_offset(insn_idx, offset));
1606+
}
16031607
YARVINSN_leave | YARVINSN_opt_invokebuiltin_delegate_leave => {
16041608
if insn_idx < iseq_size {
16051609
jump_targets.insert(insn_idx);
@@ -1800,6 +1804,17 @@ pub fn iseq_to_hir(iseq: *const rb_iseq_t) -> Result<Function, ParseError> {
18001804
});
18011805
queue.push_back((state.clone(), target, target_idx));
18021806
}
1807+
YARVINSN_opt_new => {
1808+
let offset = get_arg(pc, 1).as_i64();
1809+
// TODO(max): Check interrupts
1810+
let target_idx = insn_idx_at_offset(insn_idx, offset);
1811+
let target = insn_idx_to_block[&target_idx];
1812+
// Skip the fast-path and go straight to the fallback code. We will let the
1813+
// optimizer take care of the converting Class#new->alloc+initialize instead.
1814+
fun.push_insn(block, Insn::Jump(BranchEdge { target, args: state.as_args() }));
1815+
queue.push_back((state.clone(), target, target_idx));
1816+
break; // Don't enqueue the next block as a successor
1817+
}
18031818
YARVINSN_jump => {
18041819
let offset = get_arg(pc, 0).as_i64();
18051820
// TODO(max): Check interrupts
@@ -2796,6 +2811,26 @@ mod tests {
27962811
");
27972812
assert_compile_fails("test", ParseError::UnknownOpcode("sendforward".into()))
27982813
}
2814+
2815+
#[test]
2816+
fn test_opt_new() {
2817+
eval("
2818+
class C; end
2819+
def test = C.new
2820+
");
2821+
assert_method_hir("test", expect![[r#"
2822+
fn test:
2823+
bb0():
2824+
v1:BasicObject = GetConstantPath 0x1000
2825+
v2:NilClassExact = Const Value(nil)
2826+
Jump bb1(v2, v1)
2827+
bb1(v4:NilClassExact, v5:BasicObject):
2828+
v8:BasicObject = SendWithoutBlock v5, :new
2829+
Jump bb2(v8, v4)
2830+
bb2(v10:BasicObject, v11:NilClassExact):
2831+
Return v10
2832+
"#]]);
2833+
}
27992834
}
28002835

28012836
#[cfg(test)]
@@ -3688,4 +3723,55 @@ mod opt_tests {
36883723
Return v5
36893724
"#]]);
36903725
}
3726+
3727+
#[test]
3728+
fn test_opt_new_no_initialize() {
3729+
eval("
3730+
class C; end
3731+
def test = C.new
3732+
test
3733+
");
3734+
assert_optimized_method_hir("test", expect![[r#"
3735+
fn test:
3736+
bb0():
3737+
PatchPoint SingleRactorMode
3738+
PatchPoint StableConstantNames(0x1000, C)
3739+
v16:BasicObject[VALUE(0x1008)] = Const Value(VALUE(0x1008))
3740+
v2:NilClassExact = Const Value(nil)
3741+
Jump bb1(v2, v16)
3742+
bb1(v4:NilClassExact, v5:BasicObject[VALUE(0x1008)]):
3743+
v8:BasicObject = SendWithoutBlock v5, :new
3744+
Jump bb2(v8, v4)
3745+
bb2(v10:BasicObject, v11:NilClassExact):
3746+
Return v10
3747+
"#]]);
3748+
}
3749+
3750+
#[test]
3751+
fn test_opt_new_initialize() {
3752+
eval("
3753+
class C
3754+
def initialize x
3755+
@x = x
3756+
end
3757+
end
3758+
def test = C.new 1
3759+
test
3760+
");
3761+
assert_optimized_method_hir("test", expect![[r#"
3762+
fn test:
3763+
bb0():
3764+
PatchPoint SingleRactorMode
3765+
PatchPoint StableConstantNames(0x1000, C)
3766+
v18:BasicObject[VALUE(0x1008)] = Const Value(VALUE(0x1008))
3767+
v2:NilClassExact = Const Value(nil)
3768+
v3:Fixnum[1] = Const Value(1)
3769+
Jump bb1(v2, v18, v3)
3770+
bb1(v5:NilClassExact, v6:BasicObject[VALUE(0x1008)], v7:Fixnum[1]):
3771+
v10:BasicObject = SendWithoutBlock v6, :new, v7
3772+
Jump bb2(v10, v5)
3773+
bb2(v12:BasicObject, v13:NilClassExact):
3774+
Return v12
3775+
"#]]);
3776+
}
36913777
}

0 commit comments

Comments
 (0)