@@ -8633,4 +8633,138 @@ mod hir_opt_tests {
86338633 Return v60
86348634 " ) ;
86358635 }
8636+
8637+ #[ test]
8638+ fn test_eliminate_guard_type_on_frozen_object ( ) {
8639+ // When a frozen constant object matches the guard type, eliminate the GuardType
8640+ eval ( r#"
8641+ class C
8642+ def foo = 42
8643+ end
8644+ FROZEN = C.new.freeze
8645+ def test = FROZEN.foo
8646+ test; test
8647+ "# ) ;
8648+ // The GuardType should be eliminated because FROZEN is a frozen C object
8649+ // and the guard is for HeapObject[class_exact:C]
8650+ assert_snapshot ! ( hir_string( "test" ) , @r"
8651+ fn test@<compiled>:6:
8652+ bb0():
8653+ EntryPoint interpreter
8654+ v1:BasicObject = LoadSelf
8655+ Jump bb2(v1)
8656+ bb1(v4:BasicObject):
8657+ EntryPoint JIT(0)
8658+ Jump bb2(v4)
8659+ bb2(v6:BasicObject):
8660+ PatchPoint SingleRactorMode
8661+ PatchPoint StableConstantNames(0x1000, FROZEN)
8662+ v20:HeapObject[VALUE(0x1008)] = Const Value(VALUE(0x1008))
8663+ PatchPoint MethodRedefined(C@0x1010, foo@0x1018, cme:0x1020)
8664+ PatchPoint NoSingletonClass(C@0x1010)
8665+ IncrCounter inline_iseq_optimized_send_count
8666+ v25:Fixnum[42] = Const Value(42)
8667+ CheckInterrupts
8668+ Return v25
8669+ " ) ;
8670+ }
8671+
8672+ #[ test]
8673+ fn test_eliminate_guard_type_on_unfrozen_constant_object ( ) {
8674+ // Even unfrozen constant objects have their GuardType eliminated because
8675+ // the type system already knows the exact class from the constant VALUE.
8676+ // The frozen object optimization is defense-in-depth for edge cases.
8677+ eval ( r#"
8678+ class C
8679+ def foo = 42
8680+ end
8681+ UNFROZEN = C.new # Not frozen, but class is still known
8682+ def test = UNFROZEN.foo
8683+ test; test
8684+ "# ) ;
8685+ // The GuardType is eliminated because the constant's type is fully known
8686+ assert_snapshot ! ( hir_string( "test" ) , @r"
8687+ fn test@<compiled>:6:
8688+ bb0():
8689+ EntryPoint interpreter
8690+ v1:BasicObject = LoadSelf
8691+ Jump bb2(v1)
8692+ bb1(v4:BasicObject):
8693+ EntryPoint JIT(0)
8694+ Jump bb2(v4)
8695+ bb2(v6:BasicObject):
8696+ PatchPoint SingleRactorMode
8697+ PatchPoint StableConstantNames(0x1000, UNFROZEN)
8698+ v20:HeapObject[VALUE(0x1008)] = Const Value(VALUE(0x1008))
8699+ PatchPoint MethodRedefined(C@0x1010, foo@0x1018, cme:0x1020)
8700+ PatchPoint NoSingletonClass(C@0x1010)
8701+ IncrCounter inline_iseq_optimized_send_count
8702+ v25:Fixnum[42] = Const Value(42)
8703+ CheckInterrupts
8704+ Return v25
8705+ " ) ;
8706+ }
8707+
8708+ #[ test]
8709+ fn test_eliminate_guard_type_on_frozen_string_constant ( ) {
8710+ // Frozen string literals should also benefit from this optimization
8711+ eval ( r#"
8712+ # frozen_string_literal: true
8713+ STR = "hello"
8714+ def test = STR.size
8715+ test; test
8716+ "# ) ;
8717+ // The GuardType for StringExact should be eliminated
8718+ assert_snapshot ! ( hir_string( "test" ) , @r"
8719+ fn test@<compiled>:4:
8720+ bb0():
8721+ EntryPoint interpreter
8722+ v1:BasicObject = LoadSelf
8723+ Jump bb2(v1)
8724+ bb1(v4:BasicObject):
8725+ EntryPoint JIT(0)
8726+ Jump bb2(v4)
8727+ bb2(v6:BasicObject):
8728+ PatchPoint SingleRactorMode
8729+ PatchPoint StableConstantNames(0x1000, STR)
8730+ v21:StringExact[VALUE(0x1008)] = Const Value(VALUE(0x1008))
8731+ PatchPoint MethodRedefined(String@0x1010, size@0x1018, cme:0x1020)
8732+ PatchPoint NoSingletonClass(String@0x1010)
8733+ IncrCounter inline_cfunc_optimized_send_count
8734+ v26:Fixnum = CCall String#size@0x1048, v21
8735+ CheckInterrupts
8736+ Return v26
8737+ " ) ;
8738+ }
8739+
8740+ #[ test]
8741+ fn test_eliminate_guard_type_on_frozen_array_constant ( ) {
8742+ // Frozen arrays should also benefit from this optimization
8743+ eval ( r#"
8744+ ARR = [1, 2, 3].freeze
8745+ def test = ARR.size
8746+ test; test
8747+ "# ) ;
8748+ // The GuardType for ArrayExact should be eliminated
8749+ assert_snapshot ! ( hir_string( "test" ) , @r"
8750+ fn test@<compiled>:3:
8751+ bb0():
8752+ EntryPoint interpreter
8753+ v1:BasicObject = LoadSelf
8754+ Jump bb2(v1)
8755+ bb1(v4:BasicObject):
8756+ EntryPoint JIT(0)
8757+ Jump bb2(v4)
8758+ bb2(v6:BasicObject):
8759+ PatchPoint SingleRactorMode
8760+ PatchPoint StableConstantNames(0x1000, ARR)
8761+ v21:ArrayExact[VALUE(0x1008)] = Const Value(VALUE(0x1008))
8762+ PatchPoint MethodRedefined(Array@0x1010, size@0x1018, cme:0x1020)
8763+ PatchPoint NoSingletonClass(Array@0x1010)
8764+ IncrCounter inline_cfunc_optimized_send_count
8765+ v26:Fixnum = CCall Array#size@0x1048, v21
8766+ CheckInterrupts
8767+ Return v26
8768+ " ) ;
8769+ }
86368770}
0 commit comments