@@ -6,7 +6,7 @@ use crate::backend::lir::Assembler;
66use crate :: codegen:: max_iseq_versions;
77use crate :: cruby:: * ;
88use crate :: hir:: { Insn , iseq_to_hir} ;
9- use crate :: options:: { get_option, rb_zjit_prepare_options, set_call_threshold, set_inline_threshold} ;
9+ use crate :: options:: { get_option, rb_zjit_prepare_options, set_call_threshold, set_inline_threshold, set_max_versions } ;
1010use crate :: payload:: IseqVersion ;
1111use crate :: hir:: tests:: hir_build_tests:: assert_contains_opcode;
1212use crate :: payload:: * ;
@@ -7198,6 +7198,61 @@ fn test_regression_gc_stress_with_lazy_block_code() {
71987198 "# ) , @":ok" ) ;
71997199}
72007200
7201+ // Hash recursion uses catch/throw internally. The target frame remains in JIT
7202+ // code after the caught throw, so longjmp must not materialize and detach it
7203+ // before a callee side exit uses its updated PC and stack map.
7204+ #[ test]
7205+ fn test_keep_jit_frame_for_caught_jump ( ) {
7206+ rb_zjit_prepare_options ( ) ;
7207+ let old_call_threshold = unsafe { crate :: options:: rb_zjit_call_threshold } ;
7208+ let old_inline_threshold = get_option ! ( inline_threshold) ;
7209+ let old_max_versions = get_option ! ( max_versions) ;
7210+ set_call_threshold ( 1 ) ;
7211+ set_inline_threshold ( 0 ) ;
7212+ set_max_versions ( 2 ) ;
7213+ let result = inspect ( r#"
7214+ module KeepJITFrameAssertions
7215+ def assert_receiver(*)
7216+ raise unless is_a?(KeepJITFrameBase)
7217+ end
7218+ end
7219+
7220+ class KeepJITFrameBase
7221+ include KeepJITFrameAssertions
7222+
7223+ def hash_class = Hash
7224+
7225+ def test
7226+ hash = hash_class[]
7227+ recursive = [hash]
7228+ hash[:x] = recursive
7229+ object = Object.new
7230+ lookup = { hash => object }
7231+
7232+ [recursive, [hash]].each do |key|
7233+ key = { x: key }
7234+ assert_receiver(object, lookup[key], -> { key.inspect })
7235+ end
7236+ end
7237+ end
7238+
7239+ class KeepJITFrameHash < Hash
7240+ end
7241+
7242+ class KeepJITFrameSubclass < KeepJITFrameBase
7243+ def hash_class = KeepJITFrameHash
7244+ end
7245+
7246+ KeepJITFrameBase.new.test
7247+ KeepJITFrameSubclass.new.test
7248+ :ok
7249+ "# ) ;
7250+ set_max_versions ( old_max_versions) ;
7251+ set_inline_threshold ( old_inline_threshold) ;
7252+ set_call_threshold ( old_call_threshold) ;
7253+ assert_snapshot ! ( result, @":ok" ) ;
7254+ }
7255+
72017256#[ test]
72027257fn test_float_arithmetic ( ) {
72037258 set_call_threshold ( 1 ) ;
0 commit comments