@@ -8539,6 +8539,159 @@ mod hir_opt_tests {
85398539 " ) ;
85408540 }
85418541
8542+ #[ test]
8543+ fn test_optimize_array_push_with_array_subclass ( ) {
8544+ eval ( "
8545+ class PushSubArray < Array
8546+ def <<(val) = super
8547+ end
8548+ test = PushSubArray.new
8549+ test << 1
8550+ " ) ;
8551+ assert_snapshot ! ( hir_string_proc( "PushSubArray.new.method(:<<)" ) , @r"
8552+ fn <<@<compiled>:3:
8553+ bb0():
8554+ EntryPoint interpreter
8555+ v1:BasicObject = LoadSelf
8556+ v2:BasicObject = GetLocal :val, l0, SP@4
8557+ Jump bb2(v1, v2)
8558+ bb1(v5:BasicObject, v6:BasicObject):
8559+ EntryPoint JIT(0)
8560+ Jump bb2(v5, v6)
8561+ bb2(v8:BasicObject, v9:BasicObject):
8562+ PatchPoint MethodRedefined(Array@0x1000, <<@0x1008, cme:0x1010)
8563+ v21:CPtr = GetLEP
8564+ v22:RubyValue = LoadField v21, :_ep_method_entry@0x1038
8565+ v23:CallableMethodEntry[VALUE(0x1040)] = GuardBitEquals v22, Value(VALUE(0x1040))
8566+ v24:RubyValue = LoadField v21, :_ep_specval@0x1048
8567+ v25:FalseClass = GuardBitEquals v24, Value(false)
8568+ v26:Array = GuardType v8, Array
8569+ ArrayPush v26, v9
8570+ IncrCounter inline_cfunc_optimized_send_count
8571+ CheckInterrupts
8572+ Return v26
8573+ " ) ;
8574+ }
8575+
8576+ #[ test]
8577+ fn test_optimize_array_pop_with_array_subclass ( ) {
8578+ eval ( "
8579+ class PopSubArray < Array
8580+ def pop = super
8581+ end
8582+ test = PopSubArray.new([1])
8583+ test.pop
8584+ " ) ;
8585+ assert_snapshot ! ( hir_string_proc( "PopSubArray.new.method(:pop)" ) , @r"
8586+ fn pop@<compiled>:3:
8587+ bb0():
8588+ EntryPoint interpreter
8589+ v1:BasicObject = LoadSelf
8590+ Jump bb2(v1)
8591+ bb1(v4:BasicObject):
8592+ EntryPoint JIT(0)
8593+ Jump bb2(v4)
8594+ bb2(v6:BasicObject):
8595+ PatchPoint MethodRedefined(Array@0x1000, pop@0x1008, cme:0x1010)
8596+ v17:CPtr = GetLEP
8597+ v18:RubyValue = LoadField v17, :_ep_method_entry@0x1038
8598+ v19:CallableMethodEntry[VALUE(0x1040)] = GuardBitEquals v18, Value(VALUE(0x1040))
8599+ v20:RubyValue = LoadField v17, :_ep_specval@0x1048
8600+ v21:FalseClass = GuardBitEquals v20, Value(false)
8601+ PatchPoint MethodRedefined(Array@0x1000, pop@0x1008, cme:0x1010)
8602+ v27:CPtr = GetLEP
8603+ v28:RubyValue = LoadField v27, :_ep_method_entry@0x1038
8604+ v29:CallableMethodEntry[VALUE(0x1040)] = GuardBitEquals v28, Value(VALUE(0x1040))
8605+ v30:RubyValue = LoadField v27, :_ep_specval@0x1048
8606+ v31:FalseClass = GuardBitEquals v30, Value(false)
8607+ v22:Array = GuardType v6, Array
8608+ v23:CUInt64 = LoadField v22, :_rbasic_flags@0x1049
8609+ v24:CUInt64 = GuardNoBitsSet v23, RUBY_ELTS_SHARED=CUInt64(4096)
8610+ v25:BasicObject = ArrayPop v22
8611+ IncrCounter inline_cfunc_optimized_send_count
8612+ CheckInterrupts
8613+ Return v25
8614+ " ) ;
8615+ }
8616+
8617+ #[ test]
8618+ fn test_optimize_array_aref_with_array_subclass_and_fixnum ( ) {
8619+ eval ( "
8620+ class ArefSubArray < Array
8621+ def [](idx) = super
8622+ end
8623+ test = ArefSubArray.new([1])
8624+ test[0]
8625+ " ) ;
8626+ assert_snapshot ! ( hir_string_proc( "ArefSubArray.new.method(:[])" ) , @r"
8627+ fn []@<compiled>:3:
8628+ bb0():
8629+ EntryPoint interpreter
8630+ v1:BasicObject = LoadSelf
8631+ v2:BasicObject = GetLocal :idx, l0, SP@4
8632+ Jump bb2(v1, v2)
8633+ bb1(v5:BasicObject, v6:BasicObject):
8634+ EntryPoint JIT(0)
8635+ Jump bb2(v5, v6)
8636+ bb2(v8:BasicObject, v9:BasicObject):
8637+ PatchPoint MethodRedefined(Array@0x1000, []@0x1008, cme:0x1010)
8638+ v21:CPtr = GetLEP
8639+ v22:RubyValue = LoadField v21, :_ep_method_entry@0x1038
8640+ v23:CallableMethodEntry[VALUE(0x1040)] = GuardBitEquals v22, Value(VALUE(0x1040))
8641+ v24:RubyValue = LoadField v21, :_ep_specval@0x1048
8642+ v25:FalseClass = GuardBitEquals v24, Value(false)
8643+ PatchPoint MethodRedefined(Array@0x1000, []@0x1008, cme:0x1010)
8644+ v35:CPtr = GetLEP
8645+ v36:RubyValue = LoadField v35, :_ep_method_entry@0x1038
8646+ v37:CallableMethodEntry[VALUE(0x1040)] = GuardBitEquals v36, Value(VALUE(0x1040))
8647+ v38:RubyValue = LoadField v35, :_ep_specval@0x1048
8648+ v39:FalseClass = GuardBitEquals v38, Value(false)
8649+ v26:Array = GuardType v8, Array
8650+ v27:Fixnum = GuardType v9, Fixnum
8651+ v28:CInt64 = UnboxFixnum v27
8652+ v29:CInt64 = ArrayLength v26
8653+ v30:CInt64 = GuardLess v28, v29
8654+ v31:CInt64[0] = Const CInt64(0)
8655+ v32:CInt64 = GuardGreaterEq v30, v31
8656+ v33:BasicObject = ArrayAref v26, v32
8657+ IncrCounter inline_cfunc_optimized_send_count
8658+ CheckInterrupts
8659+ Return v33
8660+ " ) ;
8661+ }
8662+
8663+ #[ test]
8664+ fn test_dont_optimize_array_aref_with_array_subclass_and_non_fixnum ( ) {
8665+ eval ( "
8666+ class ArefSubArrayRange < Array
8667+ def [](idx) = super
8668+ end
8669+ test = ArefSubArrayRange.new([1, 2, 3])
8670+ test[0..1]
8671+ " ) ;
8672+ assert_snapshot ! ( hir_string_proc( "ArefSubArrayRange.new.method(:[])" ) , @r"
8673+ fn []@<compiled>:3:
8674+ bb0():
8675+ EntryPoint interpreter
8676+ v1:BasicObject = LoadSelf
8677+ v2:BasicObject = GetLocal :idx, l0, SP@4
8678+ Jump bb2(v1, v2)
8679+ bb1(v5:BasicObject, v6:BasicObject):
8680+ EntryPoint JIT(0)
8681+ Jump bb2(v5, v6)
8682+ bb2(v8:BasicObject, v9:BasicObject):
8683+ PatchPoint MethodRedefined(Array@0x1000, []@0x1008, cme:0x1010)
8684+ v21:CPtr = GetLEP
8685+ v22:RubyValue = LoadField v21, :_ep_method_entry@0x1038
8686+ v23:CallableMethodEntry[VALUE(0x1040)] = GuardBitEquals v22, Value(VALUE(0x1040))
8687+ v24:RubyValue = LoadField v21, :_ep_specval@0x1048
8688+ v25:FalseClass = GuardBitEquals v24, Value(false)
8689+ v26:BasicObject = CCallVariadic v8, :Array#[]@0x1050, v9
8690+ CheckInterrupts
8691+ Return v26
8692+ " ) ;
8693+ }
8694+
85428695 #[ test]
85438696 fn test_optimize_array_length ( ) {
85448697 eval ( "
0 commit comments