@@ -1537,22 +1537,31 @@ impl Function {
1537
1537
// It allows you to use a faster ISEQ if possible.
1538
1538
cme = unsafe { rb_check_overloaded_cme ( cme, ci) } ;
1539
1539
let def_type = unsafe { get_cme_def_type ( cme) } ;
1540
- if def_type ! = VM_METHOD_TYPE_ISEQ {
1540
+ if def_type = = VM_METHOD_TYPE_ISEQ {
1541
1541
// TODO(max): Allow non-iseq; cache cme
1542
+ // Only specialize positional-positional calls
1543
+ // TODO(max): Handle other kinds of parameter passing
1544
+ let iseq = unsafe { get_def_iseq_ptr ( ( * cme) . def ) } ;
1545
+ if !can_direct_send ( iseq) {
1546
+ self . push_insn_id ( block, insn_id) ; continue ;
1547
+ }
1548
+ self . push_insn ( block, Insn :: PatchPoint { invariant : Invariant :: MethodRedefined { klass, method : mid, cme } , state } ) ;
1549
+ if let Some ( profiled_type) = profiled_type {
1550
+ self_val = self . push_insn ( block, Insn :: GuardType { val : self_val, guard_type : Type :: from_profiled_type ( profiled_type) , state } ) ;
1551
+ }
1552
+ let send_direct = self . push_insn ( block, Insn :: SendWithoutBlockDirect { self_val, cd, cme, iseq, args, state } ) ;
1553
+ self . make_equal_to ( insn_id, send_direct) ;
1554
+ } else if def_type == VM_METHOD_TYPE_IVAR && args. is_empty ( ) {
1555
+ self . push_insn ( block, Insn :: PatchPoint { invariant : Invariant :: MethodRedefined { klass, method : mid, cme } , state } ) ;
1556
+ if let Some ( profiled_type) = profiled_type {
1557
+ self_val = self . push_insn ( block, Insn :: GuardType { val : self_val, guard_type : Type :: from_profiled_type ( profiled_type) , state } ) ;
1558
+ }
1559
+ let id = unsafe { get_cme_def_body_attr_id ( cme) } ;
1560
+ let getivar = self . push_insn ( block, Insn :: GetIvar { self_val, id, state } ) ;
1561
+ self . make_equal_to ( insn_id, getivar) ;
1562
+ } else {
1542
1563
self . push_insn_id ( block, insn_id) ; continue ;
1543
1564
}
1544
- // Only specialize positional-positional calls
1545
- // TODO(max): Handle other kinds of parameter passing
1546
- let iseq = unsafe { get_def_iseq_ptr ( ( * cme) . def ) } ;
1547
- if !can_direct_send ( iseq) {
1548
- self . push_insn_id ( block, insn_id) ; continue ;
1549
- }
1550
- self . push_insn ( block, Insn :: PatchPoint { invariant : Invariant :: MethodRedefined { klass, method : mid, cme } , state } ) ;
1551
- if let Some ( profiled_type) = profiled_type {
1552
- self_val = self . push_insn ( block, Insn :: GuardType { val : self_val, guard_type : Type :: from_profiled_type ( profiled_type) , state } ) ;
1553
- }
1554
- let send_direct = self . push_insn ( block, Insn :: SendWithoutBlockDirect { self_val, cd, cme, iseq, args, state } ) ;
1555
- self . make_equal_to ( insn_id, send_direct) ;
1556
1565
}
1557
1566
Insn :: GetConstantPath { ic, state, .. } => {
1558
1567
let idlist: * const ID = unsafe { ( * ic) . segments } ;
@@ -7422,4 +7431,94 @@ mod opt_tests {
7422
7431
Return v7
7423
7432
"# ] ] ) ;
7424
7433
}
7434
+
7435
+ #[ test]
7436
+ fn test_inline_attr_reader_constant ( ) {
7437
+ eval ( "
7438
+ class C
7439
+ attr_reader :foo
7440
+ end
7441
+
7442
+ O = C.new
7443
+ def test = O.foo
7444
+ test
7445
+ test
7446
+ " ) ;
7447
+ assert_optimized_method_hir ( "test" , expect ! [ [ r#"
7448
+ fn test@<compiled>:7:
7449
+ bb0(v0:BasicObject):
7450
+ PatchPoint SingleRactorMode
7451
+ PatchPoint StableConstantNames(0x1000, O)
7452
+ v9:BasicObject[VALUE(0x1008)] = Const Value(VALUE(0x1008))
7453
+ PatchPoint MethodRedefined(C@0x1010, foo@0x1018, cme:0x1020)
7454
+ v11:BasicObject = GetIvar v9, :@foo
7455
+ Return v11
7456
+ "# ] ] ) ;
7457
+ }
7458
+
7459
+ #[ test]
7460
+ fn test_inline_attr_accessor_constant ( ) {
7461
+ eval ( "
7462
+ class C
7463
+ attr_accessor :foo
7464
+ end
7465
+
7466
+ O = C.new
7467
+ def test = O.foo
7468
+ test
7469
+ test
7470
+ " ) ;
7471
+ assert_optimized_method_hir ( "test" , expect ! [ [ r#"
7472
+ fn test@<compiled>:7:
7473
+ bb0(v0:BasicObject):
7474
+ PatchPoint SingleRactorMode
7475
+ PatchPoint StableConstantNames(0x1000, O)
7476
+ v9:BasicObject[VALUE(0x1008)] = Const Value(VALUE(0x1008))
7477
+ PatchPoint MethodRedefined(C@0x1010, foo@0x1018, cme:0x1020)
7478
+ v11:BasicObject = GetIvar v9, :@foo
7479
+ Return v11
7480
+ "# ] ] ) ;
7481
+ }
7482
+
7483
+ #[ test]
7484
+ fn test_inline_attr_reader ( ) {
7485
+ eval ( "
7486
+ class C
7487
+ attr_reader :foo
7488
+ end
7489
+
7490
+ def test(o) = o.foo
7491
+ test C.new
7492
+ test C.new
7493
+ " ) ;
7494
+ assert_optimized_method_hir ( "test" , expect ! [ [ r#"
7495
+ fn test@<compiled>:6:
7496
+ bb0(v0:BasicObject, v1:BasicObject):
7497
+ PatchPoint MethodRedefined(C@0x1000, foo@0x1008, cme:0x1010)
7498
+ v7:BasicObject[class_exact:C] = GuardType v1, BasicObject[class_exact:C]
7499
+ v8:BasicObject = GetIvar v7, :@foo
7500
+ Return v8
7501
+ "# ] ] ) ;
7502
+ }
7503
+
7504
+ #[ test]
7505
+ fn test_inline_attr_accessor ( ) {
7506
+ eval ( "
7507
+ class C
7508
+ attr_accessor :foo
7509
+ end
7510
+
7511
+ def test(o) = o.foo
7512
+ test C.new
7513
+ test C.new
7514
+ " ) ;
7515
+ assert_optimized_method_hir ( "test" , expect ! [ [ r#"
7516
+ fn test@<compiled>:6:
7517
+ bb0(v0:BasicObject, v1:BasicObject):
7518
+ PatchPoint MethodRedefined(C@0x1000, foo@0x1008, cme:0x1010)
7519
+ v7:BasicObject[class_exact:C] = GuardType v1, BasicObject[class_exact:C]
7520
+ v8:BasicObject = GetIvar v7, :@foo
7521
+ Return v8
7522
+ "# ] ] ) ;
7523
+ }
7425
7524
}
0 commit comments