Skip to content

Commit 9a857c5

Browse files
authored
ZJIT: Generate polymorphic branches for skewed polymorphic getivar (ruby#16533)
This PR lets skewed polymorphic callsites to generate polymorphic code. Currently, skewed polymorphic callsites are considered monomorphic and don't use ruby#16476, but doing so seems to help lobsters.
1 parent 04774d3 commit 9a857c5

File tree

2 files changed

+73
-1
lines changed

2 files changed

+73
-1
lines changed

zjit/src/hir.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3323,7 +3323,7 @@ impl Function {
33233323
let recv = self.chase_insn(recv);
33243324
for (entry_insn, entry_type_summary) in entries {
33253325
if self.union_find.borrow().find_const(*entry_insn) == recv {
3326-
if entry_type_summary.is_polymorphic() {
3326+
if entry_type_summary.is_polymorphic() || entry_type_summary.is_skewed_polymorphic() {
33273327
return Some(entry_type_summary.clone());
33283328
}
33293329
return None;

zjit/src/hir/opt_tests.rs

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7510,6 +7510,78 @@ mod hir_opt_tests {
75107510
");
75117511
}
75127512

7513+
#[test]
7514+
fn test_optimize_getivar_skewed_polymorphic() {
7515+
// Use threshold=6 so we get 5 profile samples.
7516+
// 4 calls with shape A, 1 with shape B = 80% skew (>= 75% threshold).
7517+
set_call_threshold(6);
7518+
eval(r#"
7519+
class C
7520+
def foo_then_bar
7521+
@foo = 1
7522+
@bar = 2
7523+
end
7524+
7525+
def bar_then_foo
7526+
1000.times { |i| instance_variable_set(:"@v#{i}", i) }
7527+
@bar = 3
7528+
@foo = 4
7529+
end
7530+
7531+
def foo = @foo + 1
7532+
end
7533+
7534+
O1 = C.new
7535+
O1.foo_then_bar
7536+
O2 = C.new
7537+
O2.bar_then_foo
7538+
O1.foo
7539+
O1.foo
7540+
O1.foo
7541+
O1.foo
7542+
O2.foo
7543+
"#);
7544+
assert_snapshot!(hir_string_proc("C.instance_method(:foo)"), @"
7545+
fn foo@<compiled>:14:
7546+
bb1():
7547+
EntryPoint interpreter
7548+
v1:BasicObject = LoadSelf
7549+
Jump bb3(v1)
7550+
bb2():
7551+
EntryPoint JIT(0)
7552+
v4:BasicObject = LoadArg :self@0
7553+
Jump bb3(v4)
7554+
bb3(v6:BasicObject):
7555+
PatchPoint SingleRactorMode
7556+
v11:HeapBasicObject = GuardType v6, HeapBasicObject
7557+
v12:CShape = LoadField v11, :_shape_id@0x1000
7558+
v14:CShape[0x1001] = Const CShape(0x1001)
7559+
v15:CBool = IsBitEqual v12, v14
7560+
IfTrue v15, bb5()
7561+
v19:CShape[0x1002] = Const CShape(0x1002)
7562+
v20:CBool = IsBitEqual v12, v19
7563+
IfTrue v20, bb6()
7564+
v38:CShape = LoadField v11, :_shape_id@0x1000
7565+
v39:CShape[0x1001] = GuardBitEquals v38, CShape(0x1001)
7566+
v40:BasicObject = LoadField v11, :@foo@0x1003
7567+
Jump bb4(v40)
7568+
bb5():
7569+
v17:BasicObject = LoadField v11, :@foo@0x1003
7570+
Jump bb4(v17)
7571+
bb6():
7572+
v22:CPtr = LoadField v11, :_as_heap@0x1003
7573+
v23:BasicObject = LoadField v22, :@foo@0x1004
7574+
Jump bb4(v23)
7575+
bb4(v13:BasicObject):
7576+
v28:Fixnum[1] = Const Value(1)
7577+
PatchPoint MethodRedefined(Integer@0x1008, +@0x1010, cme:0x1018)
7578+
v43:Fixnum = GuardType v13, Fixnum
7579+
v44:Fixnum = FixnumAdd v43, v28
7580+
CheckInterrupts
7581+
Return v44
7582+
");
7583+
}
7584+
75137585
#[test]
75147586
fn test_optimize_getivar_polymorphic_with_subclass() {
75157587
set_call_threshold(3);

0 commit comments

Comments
 (0)