@@ -1382,6 +1382,11 @@ impl Function {
13821382 }
13831383
13841384 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+ }
13851390 if self . arguments_likely_fixnums ( left, right, state) {
13861391 if bop == BOP_NEQ {
13871392 // For opt_neq, the interpreter checks that both neq and eq are unchanged.
@@ -1399,6 +1404,11 @@ impl Function {
13991404 }
14001405
14011406 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+ }
14021412 let self_type = self . type_of ( self_val) ;
14031413 if let Some ( obj) = self_type. ruby_object ( ) {
14041414 if obj. is_frozen ( ) {
@@ -1431,6 +1441,11 @@ impl Function {
14311441 }
14321442
14331443 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+ }
14341449 let self_type = self . type_of ( self_val) ;
14351450 let idx_type = self . type_of ( idx_val) ;
14361451 if self_type. is_subtype ( types:: ArrayExact ) {
@@ -2667,6 +2682,11 @@ pub fn iseq_to_hir(iseq: *const rb_iseq_t) -> Result<Function, ParseError> {
26672682 break ; // End the block
26682683 } ,
26692684 } ;
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+ }
26702690 fun. push_insn ( block, Insn :: PatchPoint { invariant : Invariant :: BOPRedefined { klass : ARRAY_REDEFINED_OP_FLAG , bop } , state : exit_id } ) ;
26712691 state. stack_push ( fun. push_insn ( block, insn) ) ;
26722692 }
@@ -5590,6 +5610,25 @@ mod opt_tests {
55905610 "# ] ] ) ;
55915611 }
55925612
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+
55935632 #[ test]
55945633 fn test_optimize_send_into_fixnum_add_both_profiled ( ) {
55955634 eval ( "
@@ -6628,6 +6667,23 @@ mod opt_tests {
66286667 "# ] ] ) ;
66296668 }
66306669
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+
66316687 #[ test]
66326688 fn test_elide_freeze_with_refrozen_hash ( ) {
66336689 eval ( "
@@ -6973,6 +7029,44 @@ mod opt_tests {
69737029 "# ] ] ) ;
69747030 }
69757031
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+
69767070 #[ test]
69777071 fn test_set_type_from_constant ( ) {
69787072 eval ( "
0 commit comments