@@ -1382,6 +1382,11 @@ impl Function {
1382
1382
}
1383
1383
1384
1384
fn try_rewrite_fixnum_op ( & mut self , block : BlockId , orig_insn_id : InsnId , f : & dyn Fn ( InsnId , InsnId ) -> Insn , bop : u32 , left : InsnId , right : InsnId , state : InsnId ) {
1385
+ if !unsafe { rb_BASIC_OP_UNREDEFINED_P ( bop, INTEGER_REDEFINED_OP_FLAG ) } {
1386
+ // If the basic operation is already redefined, we cannot optimize it.
1387
+ self . push_insn_id ( block, orig_insn_id) ;
1388
+ return ;
1389
+ }
1385
1390
if self . arguments_likely_fixnums ( left, right, state) {
1386
1391
if bop == BOP_NEQ {
1387
1392
// For opt_neq, the interpreter checks that both neq and eq are unchanged.
@@ -1399,6 +1404,11 @@ impl Function {
1399
1404
}
1400
1405
1401
1406
fn rewrite_if_frozen ( & mut self , block : BlockId , orig_insn_id : InsnId , self_val : InsnId , klass : u32 , bop : u32 , state : InsnId ) {
1407
+ if !unsafe { rb_BASIC_OP_UNREDEFINED_P ( bop, klass) } {
1408
+ // If the basic operation is already redefined, we cannot optimize it.
1409
+ self . push_insn_id ( block, orig_insn_id) ;
1410
+ return ;
1411
+ }
1402
1412
let self_type = self . type_of ( self_val) ;
1403
1413
if let Some ( obj) = self_type. ruby_object ( ) {
1404
1414
if obj. is_frozen ( ) {
@@ -1431,6 +1441,11 @@ impl Function {
1431
1441
}
1432
1442
1433
1443
fn try_rewrite_aref ( & mut self , block : BlockId , orig_insn_id : InsnId , self_val : InsnId , idx_val : InsnId , state : InsnId ) {
1444
+ if !unsafe { rb_BASIC_OP_UNREDEFINED_P ( BOP_AREF , ARRAY_REDEFINED_OP_FLAG ) } {
1445
+ // If the basic operation is already redefined, we cannot optimize it.
1446
+ self . push_insn_id ( block, orig_insn_id) ;
1447
+ return ;
1448
+ }
1434
1449
let self_type = self . type_of ( self_val) ;
1435
1450
let idx_type = self . type_of ( idx_val) ;
1436
1451
if self_type. is_subtype ( types:: ArrayExact ) {
@@ -2667,6 +2682,11 @@ pub fn iseq_to_hir(iseq: *const rb_iseq_t) -> Result<Function, ParseError> {
2667
2682
break ; // End the block
2668
2683
} ,
2669
2684
} ;
2685
+ if !unsafe { rb_BASIC_OP_UNREDEFINED_P ( bop, ARRAY_REDEFINED_OP_FLAG ) } {
2686
+ // If the basic operation is already redefined, we cannot optimize it.
2687
+ fun. push_insn ( block, Insn :: SideExit { state : exit_id, reason : SideExitReason :: PatchPoint ( Invariant :: BOPRedefined { klass : ARRAY_REDEFINED_OP_FLAG , bop } ) } ) ;
2688
+ break ; // End the block
2689
+ }
2670
2690
fun. push_insn ( block, Insn :: PatchPoint { invariant : Invariant :: BOPRedefined { klass : ARRAY_REDEFINED_OP_FLAG , bop } , state : exit_id } ) ;
2671
2691
state. stack_push ( fun. push_insn ( block, insn) ) ;
2672
2692
}
@@ -5590,6 +5610,25 @@ mod opt_tests {
5590
5610
"# ] ] ) ;
5591
5611
}
5592
5612
5613
+ #[ test]
5614
+ fn test_dont_optimize_fixnum_add_if_redefined ( ) {
5615
+ eval ( "
5616
+ class Integer
5617
+ def +(other)
5618
+ 100
5619
+ end
5620
+ end
5621
+ def test(a, b) = a + b
5622
+ test(1,2); test(3,4)
5623
+ " ) ;
5624
+ assert_optimized_method_hir ( "test" , expect ! [ [ r#"
5625
+ fn test@<compiled>:7:
5626
+ bb0(v0:BasicObject, v1:BasicObject, v2:BasicObject):
5627
+ v5:BasicObject = SendWithoutBlock v1, :+, v2
5628
+ Return v5
5629
+ "# ] ] ) ;
5630
+ }
5631
+
5593
5632
#[ test]
5594
5633
fn test_optimize_send_into_fixnum_add_both_profiled ( ) {
5595
5634
eval ( "
@@ -6628,6 +6667,23 @@ mod opt_tests {
6628
6667
"# ] ] ) ;
6629
6668
}
6630
6669
6670
+ #[ test]
6671
+ fn test_dont_optimize_hash_freeze_if_redefined ( ) {
6672
+ eval ( "
6673
+ class Hash
6674
+ def freeze; end
6675
+ end
6676
+ def test = {}.freeze
6677
+ " ) ;
6678
+ assert_optimized_method_hir ( "test" , expect ! [ [ r#"
6679
+ fn test@<compiled>:5:
6680
+ bb0(v0:BasicObject):
6681
+ v3:HashExact[VALUE(0x1000)] = Const Value(VALUE(0x1000))
6682
+ v4:BasicObject = SendWithoutBlock v3, :freeze
6683
+ Return v4
6684
+ "# ] ] ) ;
6685
+ }
6686
+
6631
6687
#[ test]
6632
6688
fn test_elide_freeze_with_refrozen_hash ( ) {
6633
6689
eval ( "
@@ -6973,6 +7029,44 @@ mod opt_tests {
6973
7029
"# ] ] ) ;
6974
7030
}
6975
7031
7032
+ #[ test]
7033
+ fn test_dont_optimize_array_aref_if_redefined ( ) {
7034
+ eval ( r##"
7035
+ class Array
7036
+ def [](index); end
7037
+ end
7038
+ def test = [4,5,6].freeze[10]
7039
+ "## ) ;
7040
+ assert_optimized_method_hir ( "test" , expect ! [ [ r#"
7041
+ fn test@<compiled>:5:
7042
+ bb0(v0:BasicObject):
7043
+ v3:ArrayExact[VALUE(0x1000)] = Const Value(VALUE(0x1000))
7044
+ PatchPoint BOPRedefined(ARRAY_REDEFINED_OP_FLAG, BOP_FREEZE)
7045
+ v5:Fixnum[10] = Const Value(10)
7046
+ v7:BasicObject = SendWithoutBlock v3, :[], v5
7047
+ Return v7
7048
+ "# ] ] ) ;
7049
+ }
7050
+
7051
+ #[ test]
7052
+ fn test_dont_optimize_array_max_if_redefined ( ) {
7053
+ eval ( r##"
7054
+ class Array
7055
+ def max = 10
7056
+ end
7057
+ def test = [4,5,6].max
7058
+ "## ) ;
7059
+ assert_optimized_method_hir ( "test" , expect ! [ [ r#"
7060
+ fn test@<compiled>:5:
7061
+ bb0(v0:BasicObject):
7062
+ v2:ArrayExact[VALUE(0x1000)] = Const Value(VALUE(0x1000))
7063
+ v4:ArrayExact = ArrayDup v2
7064
+ PatchPoint MethodRedefined(Array@0x1008, max@0x1010)
7065
+ v9:BasicObject = SendWithoutBlockDirect v4, :max (0x1018)
7066
+ Return v9
7067
+ "# ] ] ) ;
7068
+ }
7069
+
6976
7070
#[ test]
6977
7071
fn test_set_type_from_constant ( ) {
6978
7072
eval ( "
0 commit comments