@@ -1919,7 +1919,7 @@ fn gen_jbe_to_target0(cb: &mut CodeBlock, target0: CodePtr, target1: Option<Code
19191919
19201920// Generate a jump to a stub that recompiles the current YARV instruction on failure.
19211921// When depth_limitk is exceeded, generate a jump to a side exit.
1922- fn jit_chain_guard ( jcc : JCCKinds , jit : & JITState , ctx : & Context , cb : & mut CodeBlock , depth_limit : i32 , side_exit : CodePtr )
1922+ fn jit_chain_guard ( jcc : JCCKinds , jit : & JITState , ctx : & Context , cb : & mut CodeBlock , ocb : & mut OutlinedCb , depth_limit : i32 , side_exit : CodePtr )
19231923{
19241924 let target0_gen_fn = match jcc {
19251925 JCC_JNE | JCC_JNZ => gen_jnz_to_target0,
@@ -1935,11 +1935,13 @@ fn jit_chain_guard(jcc:JCCKinds, jit: &JITState, ctx: &Context, cb: &mut CodeBlo
19351935 gen_branch (
19361936 jit,
19371937 ctx,
1938+ cb,
1939+ ocb,
19381940 bid,
19391941 & deeper,
19401942 None ,
19411943 None ,
1942- target0_gen_fn
1944+ target0_gen_fn,
19431945 ) ;
19441946 }
19451947 else {
@@ -2043,7 +2045,7 @@ fn gen_get_ivar(jit: &mut JITState, ctx: &mut Context, cb: &mut CodeBlock, ocb:
20432045 mov(cb, REG1, member_opnd(REG0, struct RBasic, flags));
20442046 and(cb, REG1, imm_opnd(RUBY_T_MASK));
20452047 cmp(cb, REG1, imm_opnd(T_OBJECT));
2046- jit_chain_guard(JCC_JNE, jit, &starting_context, cb, max_chain_depth, side_exit);
2048+ jit_chain_guard(JCC_JNE, jit, &starting_context, cb, ocb, max_chain_depth, side_exit);
20472049 */
20482050
20492051 // FIXME: Mapping the index could fail when there is too many ivar names. If we're
@@ -2066,7 +2068,8 @@ fn gen_get_ivar(jit: &mut JITState, ctx: &mut Context, cb: &mut CodeBlock, ocb:
20662068 add_comment ( cb, "guard embedded getivar" ) ;
20672069 let flags_opnd = mem_opnd ( 64 , REG0 , RUBY_OFFSET_RBASIC_FLAGS ) ;
20682070 test ( cb, flags_opnd, uimm_opnd ( ROBJECT_EMBED as u64 ) ) ;
2069- jit_chain_guard ( JCC_JZ , jit, & starting_context, cb, max_chain_depth, counted_exit ! ( ocb, side_exit, getivar_megamorphic) ) ;
2071+ let side_exit = counted_exit ! ( ocb, side_exit, getivar_megamorphic) ;
2072+ jit_chain_guard ( JCC_JZ , jit, & starting_context, cb, ocb, max_chain_depth, side_exit) ;
20702073
20712074 // Load the variable
20722075 let offs = RUBY_OFFSET_ROBJECT_AS_ARY + ( ivar_index * SIZEOF_VALUE ) as i32 ;
@@ -2090,7 +2093,8 @@ fn gen_get_ivar(jit: &mut JITState, ctx: &mut Context, cb: &mut CodeBlock, ocb:
20902093 add_comment ( cb, "guard extended getivar" ) ;
20912094 let flags_opnd = mem_opnd ( 64 , REG0 , RUBY_OFFSET_RBASIC_FLAGS ) ;
20922095 test ( cb, flags_opnd, uimm_opnd ( ROBJECT_EMBED as u64 ) ) ;
2093- jit_chain_guard ( JCC_JNZ , jit, & starting_context, cb, max_chain_depth, counted_exit ! ( ocb, side_exit, getivar_megamorphic) ) ;
2096+ let side_exit = counted_exit ! ( ocb, side_exit, getivar_megamorphic) ;
2097+ jit_chain_guard ( JCC_JNZ , jit, & starting_context, cb, ocb, max_chain_depth, side_exit) ;
20942098
20952099 // check that the extended table is big enough
20962100 if ivar_index >= ROBJECT_EMBED_LEN_MAX + 1 {
@@ -2142,7 +2146,7 @@ fn gen_getinstancevariable(jit: &mut JITState, ctx: &mut Context, cb: &mut CodeB
21422146 // Guard that the receiver has the same class as the one from compile time.
21432147 mov ( cb, REG0 , mem_opnd ( 64 , REG_CFP , RUBY_OFFSET_CFP_SELF ) ) ;
21442148
2145- jit_guard_known_klass ( jit, ctx, cb, comptime_val_klass, InsnOpnd :: SelfOpnd , comptime_val, GET_IVAR_MAX_DEPTH , side_exit) ;
2149+ jit_guard_known_klass ( jit, ctx, cb, ocb , comptime_val_klass, InsnOpnd :: SelfOpnd , comptime_val, GET_IVAR_MAX_DEPTH , side_exit) ;
21462150
21472151 gen_get_ivar ( jit, ctx, cb, ocb, GET_IVAR_MAX_DEPTH , comptime_val, ivar_name, InsnOpnd :: SelfOpnd , side_exit)
21482152}
@@ -2452,7 +2456,7 @@ fn gen_equality_specialized(jit: &mut JITState, ctx: &mut Context, cb: &mut Code
24522456 mov ( cb, REG0 , C_ARG_REGS [ 0 ] ) ;
24532457 unsafe {
24542458 // Use of rb_cString here requires an unsafe block
2455- jit_guard_known_klass ( jit, ctx, cb, rb_cString, StackOpnd ( 1 ) , comptime_a, SEND_MAX_DEPTH , side_exit) ;
2459+ jit_guard_known_klass ( jit, ctx, cb, ocb , rb_cString, StackOpnd ( 1 ) , comptime_a, SEND_MAX_DEPTH , side_exit) ;
24562460 }
24572461
24582462 let ret = cb. new_label ( "ret" . to_string ( ) ) ;
@@ -2468,7 +2472,7 @@ fn gen_equality_specialized(jit: &mut JITState, ctx: &mut Context, cb: &mut Code
24682472 // Note: any T_STRING is valid here, but we check for a ::String for simplicity
24692473 // To pass a mutable static variable (rb_cString) requires an unsafe block
24702474 unsafe {
2471- jit_guard_known_klass ( jit, ctx, cb, rb_cString, StackOpnd ( 0 ) , comptime_b, SEND_MAX_DEPTH , side_exit) ;
2475+ jit_guard_known_klass ( jit, ctx, cb, ocb , rb_cString, StackOpnd ( 0 ) , comptime_b, SEND_MAX_DEPTH , side_exit) ;
24722476 }
24732477 }
24742478
@@ -2570,7 +2574,7 @@ fn gen_opt_aref(jit: &mut JITState, ctx: &mut Context, cb: &mut CodeBlock, ocb:
25702574 mov ( cb, REG1 , mem_opnd ( 64 , REG0 , RUBY_OFFSET_RBASIC_KLASS ) ) ;
25712575 mov ( cb, REG0 , uimm_opnd ( unsafe { rb_cArray } . into ( ) ) ) ;
25722576 cmp ( cb, REG0 , REG1 ) ;
2573- jit_chain_guard ( JCC_JNE , jit, & starting_context, cb, OPT_AREF_MAX_CHAIN_DEPTH , side_exit) ;
2577+ jit_chain_guard ( JCC_JNE , jit, & starting_context, cb, ocb , OPT_AREF_MAX_CHAIN_DEPTH , side_exit) ;
25742578
25752579 // Bail if idx is not a FIXNUM
25762580 mov ( cb, REG1 , idx_opnd) ;
@@ -2606,7 +2610,7 @@ fn gen_opt_aref(jit: &mut JITState, ctx: &mut Context, cb: &mut CodeBlock, ocb:
26062610
26072611 // Guard that the receiver is a hash
26082612 mov ( cb, REG0 , recv_opnd) ;
2609- jit_guard_known_klass ( jit, ctx, cb, unsafe { rb_cHash } , StackOpnd ( 1 ) , comptime_recv, OPT_AREF_MAX_CHAIN_DEPTH , side_exit) ;
2613+ jit_guard_known_klass ( jit, ctx, cb, ocb , unsafe { rb_cHash } , StackOpnd ( 1 ) , comptime_recv, OPT_AREF_MAX_CHAIN_DEPTH , side_exit) ;
26102614
26112615 // Setup arguments for rb_hash_aref().
26122616 mov ( cb, C_ARG_REGS [ 0 ] , REG0 ) ;
@@ -2655,11 +2659,11 @@ fn gen_opt_aset(jit: &mut JITState, ctx: &mut Context, cb: &mut CodeBlock, ocb:
26552659
26562660 // Guard receiver is an Array
26572661 mov ( cb, REG0 , recv) ;
2658- jit_guard_known_klass ( jit, ctx, cb, unsafe { rb_cArray } , StackOpnd ( 2 ) , comptime_recv, SEND_MAX_DEPTH , side_exit) ;
2662+ jit_guard_known_klass ( jit, ctx, cb, ocb , unsafe { rb_cArray } , StackOpnd ( 2 ) , comptime_recv, SEND_MAX_DEPTH , side_exit) ;
26592663
26602664 // Guard key is a fixnum
26612665 mov ( cb, REG0 , key) ;
2662- jit_guard_known_klass ( jit, ctx, cb, unsafe { rb_cInteger } , StackOpnd ( 1 ) , comptime_key, SEND_MAX_DEPTH , side_exit) ;
2666+ jit_guard_known_klass ( jit, ctx, cb, ocb , unsafe { rb_cInteger } , StackOpnd ( 1 ) , comptime_key, SEND_MAX_DEPTH , side_exit) ;
26632667
26642668 // Call rb_ary_store
26652669 mov ( cb, C_ARG_REGS [ 0 ] , recv) ;
@@ -2689,7 +2693,7 @@ fn gen_opt_aset(jit: &mut JITState, ctx: &mut Context, cb: &mut CodeBlock, ocb:
26892693
26902694 // Guard receiver is a Hash
26912695 mov ( cb, REG0 , recv) ;
2692- jit_guard_known_klass ( jit, ctx, cb, unsafe { rb_cHash } , StackOpnd ( 2 ) , comptime_recv, SEND_MAX_DEPTH , side_exit) ;
2696+ jit_guard_known_klass ( jit, ctx, cb, ocb , unsafe { rb_cHash } , StackOpnd ( 2 ) , comptime_recv, SEND_MAX_DEPTH , side_exit) ;
26932697
26942698 // Call rb_hash_aset
26952699 mov ( cb, C_ARG_REGS [ 0 ] , recv) ;
@@ -3017,6 +3021,8 @@ fn gen_branchif(jit: &mut JITState, ctx: &mut Context, cb: &mut CodeBlock, ocb:
30173021 gen_branch (
30183022 jit,
30193023 ctx,
3024+ cb,
3025+ ocb,
30203026 jump_block,
30213027 ctx,
30223028 Some ( next_block) ,
@@ -3065,6 +3071,8 @@ fn gen_branchunless(jit: &mut JITState, ctx: &mut Context, cb: &mut CodeBlock, o
30653071 gen_branch (
30663072 jit,
30673073 ctx,
3074+ cb,
3075+ ocb,
30683076 jump_block,
30693077 ctx,
30703078 Some ( next_block) ,
@@ -3112,6 +3120,8 @@ fn gen_branchnil(jit: &mut JITState, ctx: &mut Context, cb: &mut CodeBlock, ocb:
31123120 gen_branch (
31133121 jit,
31143122 ctx,
3123+ cb,
3124+ ocb,
31153125 jump_block,
31163126 ctx,
31173127 Some ( next_block) ,
@@ -3154,7 +3164,7 @@ fn gen_jump(jit: &mut JITState, ctx: &mut Context, cb: &mut CodeBlock, ocb: &mut
31543164///
31553165/// Recompile as contingency if possible, or take side exit a last resort.
31563166
3157- fn jit_guard_known_klass ( jit : & mut JITState , ctx : & mut Context , cb : & mut CodeBlock , known_klass : VALUE , insn_opnd : InsnOpnd , sample_instance : VALUE , max_chain_depth : i32 , side_exit : CodePtr ) -> bool
3167+ fn jit_guard_known_klass ( jit : & mut JITState , ctx : & mut Context , cb : & mut CodeBlock , ocb : & mut OutlinedCb , known_klass : VALUE , insn_opnd : InsnOpnd , sample_instance : VALUE , max_chain_depth : i32 , side_exit : CodePtr ) -> bool
31583168{
31593169 let val_type = ctx. get_opnd_type ( insn_opnd) ;
31603170
@@ -3165,7 +3175,7 @@ fn jit_guard_known_klass(jit: &mut JITState, ctx: &mut Context, cb: &mut CodeBlo
31653175
31663176 add_comment ( cb, "guard object is nil" ) ;
31673177 cmp ( cb, REG0 , imm_opnd ( Qnil . into ( ) ) ) ;
3168- jit_chain_guard ( JCC_JNE , jit, ctx, cb, max_chain_depth, side_exit) ;
3178+ jit_chain_guard ( JCC_JNE , jit, ctx, cb, ocb , max_chain_depth, side_exit) ;
31693179
31703180 ctx. upgrade_opnd_type ( insn_opnd, Type :: Nil ) ;
31713181 }
@@ -3177,7 +3187,7 @@ fn jit_guard_known_klass(jit: &mut JITState, ctx: &mut Context, cb: &mut CodeBlo
31773187
31783188 add_comment ( cb, "guard object is true" ) ;
31793189 cmp ( cb, REG0 , imm_opnd ( Qtrue . into ( ) ) ) ;
3180- jit_chain_guard ( JCC_JNE , jit, ctx, cb, max_chain_depth, side_exit) ;
3190+ jit_chain_guard ( JCC_JNE , jit, ctx, cb, ocb , max_chain_depth, side_exit) ;
31813191
31823192 ctx. upgrade_opnd_type ( insn_opnd, Type :: True ) ;
31833193 }
@@ -3190,7 +3200,7 @@ fn jit_guard_known_klass(jit: &mut JITState, ctx: &mut Context, cb: &mut CodeBlo
31903200 add_comment ( cb, "guard object is false" ) ;
31913201 assert ! ( Qfalse . as_i32( ) == 0 ) ;
31923202 test ( cb, REG0 , REG0 ) ;
3193- jit_chain_guard ( JCC_JNZ , jit, ctx, cb, max_chain_depth, side_exit) ;
3203+ jit_chain_guard ( JCC_JNZ , jit, ctx, cb, ocb , max_chain_depth, side_exit) ;
31943204
31953205 ctx. upgrade_opnd_type ( insn_opnd, Type :: False ) ;
31963206 }
@@ -3204,7 +3214,7 @@ fn jit_guard_known_klass(jit: &mut JITState, ctx: &mut Context, cb: &mut CodeBlo
32043214
32053215 add_comment ( cb, "guard object is fixnum" ) ;
32063216 test ( cb, REG0 , imm_opnd ( RUBY_FIXNUM_FLAG as i64 ) ) ;
3207- jit_chain_guard ( JCC_JZ , jit, ctx, cb, max_chain_depth, side_exit) ;
3217+ jit_chain_guard ( JCC_JZ , jit, ctx, cb, ocb , max_chain_depth, side_exit) ;
32083218 ctx. upgrade_opnd_type ( insn_opnd, Type :: Fixnum ) ;
32093219 }
32103220 }
@@ -3218,7 +3228,7 @@ fn jit_guard_known_klass(jit: &mut JITState, ctx: &mut Context, cb: &mut CodeBlo
32183228 add_comment ( cb, "guard object is static symbol" ) ;
32193229 assert ! ( RUBY_SPECIAL_SHIFT == 8 ) ;
32203230 cmp ( cb, REG0_8 , uimm_opnd ( RUBY_SYMBOL_FLAG as u64 ) ) ;
3221- jit_chain_guard ( JCC_JNE , jit, ctx, cb, max_chain_depth, side_exit) ;
3231+ jit_chain_guard ( JCC_JNE , jit, ctx, cb, ocb , max_chain_depth, side_exit) ;
32223232 ctx. upgrade_opnd_type ( insn_opnd, Type :: ImmSymbol ) ;
32233233 }
32243234 }
@@ -3232,7 +3242,7 @@ fn jit_guard_known_klass(jit: &mut JITState, ctx: &mut Context, cb: &mut CodeBlo
32323242 mov ( cb, REG1 , REG0 ) ;
32333243 and ( cb, REG1 , uimm_opnd ( RUBY_FLONUM_MASK as u64 ) ) ;
32343244 cmp ( cb, REG1 , uimm_opnd ( RUBY_FLONUM_FLAG as u64 ) ) ;
3235- jit_chain_guard ( JCC_JNE , jit, ctx, cb, max_chain_depth, side_exit) ;
3245+ jit_chain_guard ( JCC_JNE , jit, ctx, cb, ocb , max_chain_depth, side_exit) ;
32363246 ctx. upgrade_opnd_type ( insn_opnd, Type :: Flonum ) ;
32373247 }
32383248 }
@@ -3252,7 +3262,7 @@ fn jit_guard_known_klass(jit: &mut JITState, ctx: &mut Context, cb: &mut CodeBlo
32523262 // TODO: jit_mov_gc_ptr keeps a strong reference, which leaks the object.
32533263 jit_mov_gc_ptr ( jit, cb, REG1 , sample_instance) ;
32543264 cmp ( cb, REG0 , REG1 ) ;
3255- jit_chain_guard ( JCC_JNE , jit, ctx, cb, max_chain_depth, side_exit) ;
3265+ jit_chain_guard ( JCC_JNE , jit, ctx, cb, ocb , max_chain_depth, side_exit) ;
32563266 }
32573267 else {
32583268 assert ! ( !val_type. is_imm( ) ) ;
@@ -3263,9 +3273,9 @@ fn jit_guard_known_klass(jit: &mut JITState, ctx: &mut Context, cb: &mut CodeBlo
32633273 add_comment ( cb, "guard not immediate" ) ;
32643274 assert ! ( Qfalse . as_i32( ) < Qnil . as_i32( ) ) ;
32653275 test ( cb, REG0 , imm_opnd ( RUBY_IMMEDIATE_MASK as i64 ) ) ;
3266- jit_chain_guard ( JCC_JNZ , jit, ctx, cb, max_chain_depth, side_exit) ;
3276+ jit_chain_guard ( JCC_JNZ , jit, ctx, cb, ocb , max_chain_depth, side_exit) ;
32673277 cmp ( cb, REG0 , imm_opnd ( Qnil . into ( ) ) ) ;
3268- jit_chain_guard ( JCC_JBE , jit, ctx, cb, max_chain_depth, side_exit) ;
3278+ jit_chain_guard ( JCC_JBE , jit, ctx, cb, ocb , max_chain_depth, side_exit) ;
32693279
32703280 ctx. upgrade_opnd_type ( insn_opnd, Type :: UnknownHeap ) ;
32713281 }
@@ -3277,7 +3287,7 @@ fn jit_guard_known_klass(jit: &mut JITState, ctx: &mut Context, cb: &mut CodeBlo
32773287 add_comment ( cb, "guard known class" ) ;
32783288 jit_mov_gc_ptr ( jit, cb, REG1 , known_klass) ;
32793289 cmp ( cb, klass_opnd, REG1 ) ;
3280- jit_chain_guard ( JCC_JNE , jit, ctx, cb, max_chain_depth, side_exit) ;
3290+ jit_chain_guard ( JCC_JNE , jit, ctx, cb, ocb , max_chain_depth, side_exit) ;
32813291 }
32823292
32833293 true
@@ -4161,6 +4171,8 @@ fn gen_send_iseq(jit: &mut JITState, ctx: &mut Context, cb: &mut CodeBlock, ocb:
41614171 gen_branch (
41624172 jit,
41634173 ctx,
4174+ cb,
4175+ ocb,
41644176 return_block,
41654177 & return_ctx,
41664178 Some ( return_block) ,
@@ -4311,7 +4323,7 @@ fn gen_send_general(jit: &mut JITState, ctx: &mut Context, cb: &mut CodeBlock, o
43114323 let recv = ctx. stack_opnd ( argc) ;
43124324 let recv_opnd = StackOpnd ( argc. try_into ( ) . unwrap ( ) ) ;
43134325 mov ( cb, REG0 , recv) ;
4314- if !jit_guard_known_klass ( jit, ctx, cb, comptime_recv_klass, recv_opnd, comptime_recv, SEND_MAX_DEPTH , side_exit) {
4326+ if !jit_guard_known_klass ( jit, ctx, cb, ocb , comptime_recv_klass, recv_opnd, comptime_recv, SEND_MAX_DEPTH , side_exit) {
43154327 return CantCompile ;
43164328 }
43174329
@@ -4725,7 +4737,7 @@ fn gen_objtostring(jit: &mut JITState, ctx: &mut Context, cb: &mut CodeBlock, oc
47254737 let side_exit = get_side_exit ( jit, ocb, ctx) ;
47264738
47274739 mov ( cb, REG0 , recv) ;
4728- jit_guard_known_klass ( jit, ctx, cb, comptime_recv. class_of ( ) , StackOpnd ( 0 ) , comptime_recv, SEND_MAX_DEPTH , side_exit) ;
4740+ jit_guard_known_klass ( jit, ctx, cb, ocb , comptime_recv. class_of ( ) , StackOpnd ( 0 ) , comptime_recv, SEND_MAX_DEPTH , side_exit) ;
47294741 // No work needed. The string value is already on the top of the stack.
47304742 KeepCompiling
47314743 }
0 commit comments