Skip to content

Commit 2bfa923

Browse files
committed
attr_reader on constant
1 parent 4bdcc9f commit 2bfa923

2 files changed

Lines changed: 53 additions & 12 deletions

File tree

zjit/src/hir.rs

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3234,25 +3234,34 @@ impl Function {
32343234
is_t_object: recv_type.flags().is_t_object(),
32353235
is_embedded: recv_type.flags().is_embedded()
32363236
});
3237-
self.push_insn(block, Insn::GetIvar { self_val: refined_recv, id, ic: std::ptr::null(), state })
3237+
self.push_insn(block, Insn::GetIvar { self_val: refined_recv, id, ic: ptr::null(), state })
32383238
} else {
3239-
self.push_insn(block, Insn::GetIvar { self_val: recv, id, ic: std::ptr::null(), state })
3239+
self.push_insn(block, Insn::GetIvar { self_val: recv, id, ic: ptr::null(), state })
32403240
}
32413241
} else if let Some(val) = self.type_of(recv).ruby_object() {
32423242
// Constant receiver: get shape info from the VALUE directly
3243-
let recv_shape = val.shape_id_of();
3244-
if recv_shape.is_valid() && !recv_shape.is_too_complex() {
3245-
let shape = self.load_shape(block, recv);
3246-
self.guard_shape(block, shape, recv_shape, state);
3247-
let is_t_object = unsafe { RB_TYPE_P(val, RUBY_T_OBJECT) };
3248-
let is_embedded = is_t_object && val.embedded_p();
3249-
let refined_recv = self.push_insn(block, Insn::RefineShape { val: recv, shape: recv_shape, is_t_object, is_embedded });
3250-
self.push_insn(block, Insn::GetIvar { self_val: refined_recv, id, ic: std::ptr::null(), state })
3243+
// TODO missing snapshot test: attr reader on special const. Also
3244+
// missing: fallback reason
3245+
if !val.special_const_p() {
3246+
let recv_shape = val.shape_id_of();
3247+
if recv_shape.is_valid() && !recv_shape.is_too_complex() {
3248+
// load_shape is valid here without guard because type says recv is on-heap.
3249+
let shape = self.load_shape(block, recv);
3250+
self.guard_shape(block, shape, recv_shape, state);
3251+
let is_t_object = unsafe { RB_TYPE_P(val, RUBY_T_OBJECT) };
3252+
let is_embedded = is_t_object && val.embedded_p();
3253+
let refined_recv = self.push_insn(block, Insn::RefineShape { val: recv, shape: recv_shape, is_t_object, is_embedded });
3254+
self.push_insn(block, Insn::GetIvar { self_val: refined_recv, id, ic: ptr::null(), state })
3255+
} else {
3256+
self.push_insn(block, Insn::GetIvar { self_val: recv, id, ic: ptr::null(), state })
3257+
}
32513258
} else {
3252-
self.push_insn(block, Insn::GetIvar { self_val: recv, id, ic: std::ptr::null(), state })
3259+
// attr_reader on immediates always return nil
3260+
self.push_insn(block, Insn::Const { val: Const::Value(Qnil) })
32533261
}
32543262
} else {
3255-
self.push_insn(block, Insn::GetIvar { self_val: recv, id, ic: std::ptr::null(), state })
3263+
// No profile and no static type info
3264+
self.push_insn(block, Insn::GetIvar { self_val: recv, id, ic: ptr::null(), state })
32563265
};
32573266
self.make_equal_to(insn_id, getivar);
32583267
} else if let (false, VM_METHOD_TYPE_ATTRSET, &[val]) = (has_block, def_type, args.as_slice()) {

zjit/src/hir/opt_tests.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6905,6 +6905,38 @@ mod hir_opt_tests {
69056905
");
69066906
}
69076907

6908+
#[test]
6909+
fn test_inline_attr_reader_special_const() {
6910+
eval("
6911+
class Integer
6912+
attr_reader :ivar
6913+
end
6914+
6915+
X = 42
6916+
def test = X.ivar
6917+
test
6918+
test
6919+
");
6920+
assert_snapshot!(hir_string("test"), @"
6921+
fn test@<compiled>:7:
6922+
bb0():
6923+
EntryPoint interpreter
6924+
v1:BasicObject = LoadSelf
6925+
Jump bb2(v1)
6926+
bb1(v4:BasicObject):
6927+
EntryPoint JIT(0)
6928+
Jump bb2(v4)
6929+
bb2(v6:BasicObject):
6930+
PatchPoint SingleRactorMode
6931+
PatchPoint StableConstantNames(0x1000, X)
6932+
v20:Fixnum[42] = Const Value(42)
6933+
PatchPoint MethodRedefined(Integer@0x1008, ivar@0x1010, cme:0x1018)
6934+
v22:NilClass = Const Value(nil)
6935+
CheckInterrupts
6936+
Return v22
6937+
");
6938+
}
6939+
69086940
#[test]
69096941
fn test_inline_attr_accessor_constant() {
69106942
eval("

0 commit comments

Comments
 (0)