mirror of
https://github.com/ruby/ruby.git
synced 2025-08-15 13:39:04 +02:00
ZJIT: Inline attr_reader/attr_accessor (#14126)
We can rewrite SendWithoutBlock to GetIvar.
This commit is contained in:
parent
4a70f946a7
commit
ba4a36e226
2 changed files with 144 additions and 13 deletions
|
@ -887,6 +887,38 @@ class TestZJIT < Test::Unit::TestCase
|
|||
}
|
||||
end
|
||||
|
||||
def test_attr_reader
|
||||
assert_compiles '[4, 4]', %q{
|
||||
class C
|
||||
attr_reader :foo
|
||||
|
||||
def initialize
|
||||
@foo = 4
|
||||
end
|
||||
end
|
||||
|
||||
def test(c) = c.foo
|
||||
c = C.new
|
||||
[test(c), test(c)]
|
||||
}, call_threshold: 2, insns: [:opt_send_without_block]
|
||||
end
|
||||
|
||||
def test_attr_accessor
|
||||
assert_compiles '[4, 4]', %q{
|
||||
class C
|
||||
attr_accessor :foo
|
||||
|
||||
def initialize
|
||||
@foo = 4
|
||||
end
|
||||
end
|
||||
|
||||
def test(c) = c.foo
|
||||
c = C.new
|
||||
[test(c), test(c)]
|
||||
}, call_threshold: 2, insns: [:opt_send_without_block]
|
||||
end
|
||||
|
||||
def test_uncached_getconstant_path
|
||||
assert_compiles RUBY_COPYRIGHT.dump, %q{
|
||||
def test = RUBY_COPYRIGHT
|
||||
|
|
125
zjit/src/hir.rs
125
zjit/src/hir.rs
|
@ -1537,22 +1537,31 @@ impl Function {
|
|||
// It allows you to use a faster ISEQ if possible.
|
||||
cme = unsafe { rb_check_overloaded_cme(cme, ci) };
|
||||
let def_type = unsafe { get_cme_def_type(cme) };
|
||||
if def_type != VM_METHOD_TYPE_ISEQ {
|
||||
if def_type == VM_METHOD_TYPE_ISEQ {
|
||||
// TODO(max): Allow non-iseq; cache cme
|
||||
// Only specialize positional-positional calls
|
||||
// TODO(max): Handle other kinds of parameter passing
|
||||
let iseq = unsafe { get_def_iseq_ptr((*cme).def) };
|
||||
if !can_direct_send(iseq) {
|
||||
self.push_insn_id(block, insn_id); continue;
|
||||
}
|
||||
self.push_insn(block, Insn::PatchPoint { invariant: Invariant::MethodRedefined { klass, method: mid, cme }, state });
|
||||
if let Some(profiled_type) = profiled_type {
|
||||
self_val = self.push_insn(block, Insn::GuardType { val: self_val, guard_type: Type::from_profiled_type(profiled_type), state });
|
||||
}
|
||||
let send_direct = self.push_insn(block, Insn::SendWithoutBlockDirect { self_val, cd, cme, iseq, args, state });
|
||||
self.make_equal_to(insn_id, send_direct);
|
||||
} else if def_type == VM_METHOD_TYPE_IVAR && args.is_empty() {
|
||||
self.push_insn(block, Insn::PatchPoint { invariant: Invariant::MethodRedefined { klass, method: mid, cme }, state });
|
||||
if let Some(profiled_type) = profiled_type {
|
||||
self_val = self.push_insn(block, Insn::GuardType { val: self_val, guard_type: Type::from_profiled_type(profiled_type), state });
|
||||
}
|
||||
let id = unsafe { get_cme_def_body_attr_id(cme) };
|
||||
let getivar = self.push_insn(block, Insn::GetIvar { self_val, id, state });
|
||||
self.make_equal_to(insn_id, getivar);
|
||||
} else {
|
||||
self.push_insn_id(block, insn_id); continue;
|
||||
}
|
||||
// Only specialize positional-positional calls
|
||||
// TODO(max): Handle other kinds of parameter passing
|
||||
let iseq = unsafe { get_def_iseq_ptr((*cme).def) };
|
||||
if !can_direct_send(iseq) {
|
||||
self.push_insn_id(block, insn_id); continue;
|
||||
}
|
||||
self.push_insn(block, Insn::PatchPoint { invariant: Invariant::MethodRedefined { klass, method: mid, cme }, state });
|
||||
if let Some(profiled_type) = profiled_type {
|
||||
self_val = self.push_insn(block, Insn::GuardType { val: self_val, guard_type: Type::from_profiled_type(profiled_type), state });
|
||||
}
|
||||
let send_direct = self.push_insn(block, Insn::SendWithoutBlockDirect { self_val, cd, cme, iseq, args, state });
|
||||
self.make_equal_to(insn_id, send_direct);
|
||||
}
|
||||
Insn::GetConstantPath { ic, state, .. } => {
|
||||
let idlist: *const ID = unsafe { (*ic).segments };
|
||||
|
@ -7422,4 +7431,94 @@ mod opt_tests {
|
|||
Return v7
|
||||
"#]]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_inline_attr_reader_constant() {
|
||||
eval("
|
||||
class C
|
||||
attr_reader :foo
|
||||
end
|
||||
|
||||
O = C.new
|
||||
def test = O.foo
|
||||
test
|
||||
test
|
||||
");
|
||||
assert_optimized_method_hir("test", expect![[r#"
|
||||
fn test@<compiled>:7:
|
||||
bb0(v0:BasicObject):
|
||||
PatchPoint SingleRactorMode
|
||||
PatchPoint StableConstantNames(0x1000, O)
|
||||
v9:BasicObject[VALUE(0x1008)] = Const Value(VALUE(0x1008))
|
||||
PatchPoint MethodRedefined(C@0x1010, foo@0x1018, cme:0x1020)
|
||||
v11:BasicObject = GetIvar v9, :@foo
|
||||
Return v11
|
||||
"#]]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_inline_attr_accessor_constant() {
|
||||
eval("
|
||||
class C
|
||||
attr_accessor :foo
|
||||
end
|
||||
|
||||
O = C.new
|
||||
def test = O.foo
|
||||
test
|
||||
test
|
||||
");
|
||||
assert_optimized_method_hir("test", expect![[r#"
|
||||
fn test@<compiled>:7:
|
||||
bb0(v0:BasicObject):
|
||||
PatchPoint SingleRactorMode
|
||||
PatchPoint StableConstantNames(0x1000, O)
|
||||
v9:BasicObject[VALUE(0x1008)] = Const Value(VALUE(0x1008))
|
||||
PatchPoint MethodRedefined(C@0x1010, foo@0x1018, cme:0x1020)
|
||||
v11:BasicObject = GetIvar v9, :@foo
|
||||
Return v11
|
||||
"#]]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_inline_attr_reader() {
|
||||
eval("
|
||||
class C
|
||||
attr_reader :foo
|
||||
end
|
||||
|
||||
def test(o) = o.foo
|
||||
test C.new
|
||||
test C.new
|
||||
");
|
||||
assert_optimized_method_hir("test", expect![[r#"
|
||||
fn test@<compiled>:6:
|
||||
bb0(v0:BasicObject, v1:BasicObject):
|
||||
PatchPoint MethodRedefined(C@0x1000, foo@0x1008, cme:0x1010)
|
||||
v7:BasicObject[class_exact:C] = GuardType v1, BasicObject[class_exact:C]
|
||||
v8:BasicObject = GetIvar v7, :@foo
|
||||
Return v8
|
||||
"#]]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_inline_attr_accessor() {
|
||||
eval("
|
||||
class C
|
||||
attr_accessor :foo
|
||||
end
|
||||
|
||||
def test(o) = o.foo
|
||||
test C.new
|
||||
test C.new
|
||||
");
|
||||
assert_optimized_method_hir("test", expect![[r#"
|
||||
fn test@<compiled>:6:
|
||||
bb0(v0:BasicObject, v1:BasicObject):
|
||||
PatchPoint MethodRedefined(C@0x1000, foo@0x1008, cme:0x1010)
|
||||
v7:BasicObject[class_exact:C] = GuardType v1, BasicObject[class_exact:C]
|
||||
v8:BasicObject = GetIvar v7, :@foo
|
||||
Return v8
|
||||
"#]]);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue