@@ -195,6 +195,34 @@ impl<'a> JITState<'a> {
195195 self . outlined_code_block
196196 }
197197
198+ /// Leave a code stub to re-enter the compiler at runtime when the compiling program point is
199+ /// reached. Should always be used in tail position like `return jit.defer_compilation(asm);`.
200+ #[ must_use]
201+ fn defer_compilation ( & mut self , asm : & mut Assembler ) -> Option < CodegenStatus > {
202+ if crate :: core:: defer_compilation ( self , asm) . is_err ( ) {
203+ // If we can't leave a stub, the block isn't usable and we have to bail.
204+ self . block_abandoned = true ;
205+ }
206+ Some ( EndBlock )
207+ }
208+
209+ /// Generate a branch with either end possibly stubbed out
210+ fn gen_branch (
211+ & mut self ,
212+ asm : & mut Assembler ,
213+ target0 : BlockId ,
214+ ctx0 : & Context ,
215+ target1 : Option < BlockId > ,
216+ ctx1 : Option < & Context > ,
217+ gen_fn : BranchGenFn ,
218+ ) {
219+ if crate :: core:: gen_branch ( self , asm, target0, ctx0, target1, ctx1, gen_fn) . is_none ( ) {
220+ // If we can't meet the request for a branch, the code is
221+ // essentially corrupt and we have to discard the block.
222+ self . block_abandoned = true ;
223+ }
224+ }
225+
198226 /// Return true if the current ISEQ could escape an environment.
199227 ///
200228 /// As of vm_push_frame(), EP is always equal to BP. However, after pushing
@@ -1538,8 +1566,7 @@ fn fuse_putobject_opt_ltlt(
15381566 return None ;
15391567 }
15401568 if !jit. at_compile_target ( ) {
1541- defer_compilation ( jit, asm) ;
1542- return Some ( EndBlock ) ;
1569+ return jit. defer_compilation ( asm) ;
15431570 }
15441571
15451572 let lhs = jit. peek_at_stack ( & asm. ctx , 0 ) ;
@@ -1661,8 +1688,7 @@ fn gen_opt_plus(
16611688 let two_fixnums = match asm. ctx . two_fixnums_on_stack ( jit) {
16621689 Some ( two_fixnums) => two_fixnums,
16631690 None => {
1664- defer_compilation ( jit, asm) ;
1665- return Some ( EndBlock ) ;
1691+ return jit. defer_compilation ( asm) ;
16661692 }
16671693 } ;
16681694
@@ -1802,8 +1828,7 @@ fn gen_splatkw(
18021828) -> Option < CodegenStatus > {
18031829 // Defer compilation so we can specialize on a runtime hash operand
18041830 if !jit. at_compile_target ( ) {
1805- defer_compilation ( jit, asm) ;
1806- return Some ( EndBlock ) ;
1831+ return jit. defer_compilation ( asm) ;
18071832 }
18081833
18091834 let comptime_hash = jit. peek_at_stack ( & asm. ctx , 1 ) ;
@@ -2176,8 +2201,7 @@ fn gen_expandarray(
21762201
21772202 // Defer compilation so we can specialize on a runtime `self`
21782203 if !jit. at_compile_target ( ) {
2179- defer_compilation ( jit, asm) ;
2180- return Some ( EndBlock ) ;
2204+ return jit. defer_compilation ( asm) ;
21812205 }
21822206
21832207 let comptime_recv = jit. peek_at_stack ( & asm. ctx , 0 ) ;
@@ -2718,10 +2742,7 @@ fn jit_chain_guard(
27182742 idx : jit. insn_idx ,
27192743 } ;
27202744
2721- // Bail if we can't generate the branch
2722- if gen_branch ( jit, asm, bid, & deeper, None , None , target0_gen_fn) . is_none ( ) {
2723- jit. block_abandoned = true ;
2724- }
2745+ jit. gen_branch ( asm, bid, & deeper, None , None , target0_gen_fn) ;
27252746 } else {
27262747 target0_gen_fn. call ( asm, Target :: side_exit ( counter) , None ) ;
27272748 }
@@ -2895,8 +2916,7 @@ fn gen_getinstancevariable(
28952916) -> Option < CodegenStatus > {
28962917 // Defer compilation so we can specialize on a runtime `self`
28972918 if !jit. at_compile_target ( ) {
2898- defer_compilation ( jit, asm) ;
2899- return Some ( EndBlock ) ;
2919+ return jit. defer_compilation ( asm) ;
29002920 }
29012921
29022922 let ivar_name = jit. get_arg ( 0 ) . as_u64 ( ) ;
@@ -2959,8 +2979,7 @@ fn gen_setinstancevariable(
29592979) -> Option < CodegenStatus > {
29602980 // Defer compilation so we can specialize on a runtime `self`
29612981 if !jit. at_compile_target ( ) {
2962- defer_compilation ( jit, asm) ;
2963- return Some ( EndBlock ) ;
2982+ return jit. defer_compilation ( asm) ;
29642983 }
29652984
29662985 let ivar_name = jit. get_arg ( 0 ) . as_u64 ( ) ;
@@ -3270,8 +3289,7 @@ fn gen_definedivar(
32703289) -> Option < CodegenStatus > {
32713290 // Defer compilation so we can specialize base on a runtime receiver
32723291 if !jit. at_compile_target ( ) {
3273- defer_compilation ( jit, asm) ;
3274- return Some ( EndBlock ) ;
3292+ return jit. defer_compilation ( asm) ;
32753293 }
32763294
32773295 let ivar_name = jit. get_arg ( 0 ) . as_u64 ( ) ;
@@ -3500,8 +3518,7 @@ fn gen_fixnum_cmp(
35003518 Some ( two_fixnums) => two_fixnums,
35013519 None => {
35023520 // Defer compilation so we can specialize based on a runtime receiver
3503- defer_compilation ( jit, asm) ;
3504- return Some ( EndBlock ) ;
3521+ return jit. defer_compilation ( asm) ;
35053522 }
35063523 } ;
35073524
@@ -3680,8 +3697,7 @@ fn gen_opt_eq(
36803697 Some ( specialized) => specialized,
36813698 None => {
36823699 // Defer compilation so we can specialize base on a runtime receiver
3683- defer_compilation ( jit, asm) ;
3684- return Some ( EndBlock ) ;
3700+ return jit. defer_compilation ( asm) ;
36853701 }
36863702 } ;
36873703
@@ -3718,8 +3734,7 @@ fn gen_opt_aref(
37183734
37193735 // Defer compilation so we can specialize base on a runtime receiver
37203736 if !jit. at_compile_target ( ) {
3721- defer_compilation ( jit, asm) ;
3722- return Some ( EndBlock ) ;
3737+ return jit. defer_compilation ( asm) ;
37233738 }
37243739
37253740 // Specialize base on compile time values
@@ -3819,8 +3834,7 @@ fn gen_opt_aset(
38193834) -> Option < CodegenStatus > {
38203835 // Defer compilation so we can specialize on a runtime `self`
38213836 if !jit. at_compile_target ( ) {
3822- defer_compilation ( jit, asm) ;
3823- return Some ( EndBlock ) ;
3837+ return jit. defer_compilation ( asm) ;
38243838 }
38253839
38263840 let comptime_recv = jit. peek_at_stack ( & asm. ctx , 2 ) ;
@@ -3951,8 +3965,7 @@ fn gen_opt_and(
39513965 Some ( two_fixnums) => two_fixnums,
39523966 None => {
39533967 // Defer compilation so we can specialize on a runtime `self`
3954- defer_compilation ( jit, asm) ;
3955- return Some ( EndBlock ) ;
3968+ return jit. defer_compilation ( asm) ;
39563969 }
39573970 } ;
39583971
@@ -3990,8 +4003,7 @@ fn gen_opt_or(
39904003 Some ( two_fixnums) => two_fixnums,
39914004 None => {
39924005 // Defer compilation so we can specialize on a runtime `self`
3993- defer_compilation ( jit, asm) ;
3994- return Some ( EndBlock ) ;
4006+ return jit. defer_compilation ( asm) ;
39954007 }
39964008 } ;
39974009
@@ -4029,8 +4041,7 @@ fn gen_opt_minus(
40294041 Some ( two_fixnums) => two_fixnums,
40304042 None => {
40314043 // Defer compilation so we can specialize on a runtime `self`
4032- defer_compilation ( jit, asm) ;
4033- return Some ( EndBlock ) ;
4044+ return jit. defer_compilation ( asm) ;
40344045 }
40354046 } ;
40364047
@@ -4069,8 +4080,7 @@ fn gen_opt_mult(
40694080 let two_fixnums = match asm. ctx . two_fixnums_on_stack ( jit) {
40704081 Some ( two_fixnums) => two_fixnums,
40714082 None => {
4072- defer_compilation ( jit, asm) ;
4073- return Some ( EndBlock ) ;
4083+ return jit. defer_compilation ( asm) ;
40744084 }
40754085 } ;
40764086
@@ -4121,8 +4131,7 @@ fn gen_opt_mod(
41214131 Some ( two_fixnums) => two_fixnums,
41224132 None => {
41234133 // Defer compilation so we can specialize on a runtime `self`
4124- defer_compilation ( jit, asm) ;
4125- return Some ( EndBlock ) ;
4134+ return jit. defer_compilation ( asm) ;
41264135 }
41274136 } ;
41284137
@@ -4459,8 +4468,7 @@ fn gen_opt_case_dispatch(
44594468 // hash lookup, at least for small hashes, but it's worth revisiting this
44604469 // assumption in the future.
44614470 if !jit. at_compile_target ( ) {
4462- defer_compilation ( jit, asm) ;
4463- return Some ( EndBlock ) ;
4471+ return jit. defer_compilation ( asm) ;
44644472 }
44654473
44664474 let case_hash = jit. get_arg ( 0 ) ;
@@ -4572,15 +4580,14 @@ fn gen_branchif(
45724580
45734581 // Generate the branch instructions
45744582 let ctx = asm. ctx ;
4575- gen_branch (
4576- jit,
4583+ jit. gen_branch (
45774584 asm,
45784585 jump_block,
45794586 & ctx,
45804587 Some ( next_block) ,
45814588 Some ( & ctx) ,
45824589 BranchGenFn :: BranchIf ( Cell :: new ( BranchShape :: Default ) ) ,
4583- ) ? ;
4590+ ) ;
45844591 }
45854592
45864593 Some ( EndBlock )
@@ -4626,15 +4633,14 @@ fn gen_branchunless(
46264633
46274634 // Generate the branch instructions
46284635 let ctx = asm. ctx ;
4629- gen_branch (
4630- jit,
4636+ jit. gen_branch (
46314637 asm,
46324638 jump_block,
46334639 & ctx,
46344640 Some ( next_block) ,
46354641 Some ( & ctx) ,
46364642 BranchGenFn :: BranchUnless ( Cell :: new ( BranchShape :: Default ) ) ,
4637- ) ? ;
4643+ ) ;
46384644 }
46394645
46404646 Some ( EndBlock )
@@ -4677,15 +4683,14 @@ fn gen_branchnil(
46774683 asm. cmp ( val_opnd, Opnd :: UImm ( Qnil . into ( ) ) ) ;
46784684 // Generate the branch instructions
46794685 let ctx = asm. ctx ;
4680- gen_branch (
4681- jit,
4686+ jit. gen_branch (
46824687 asm,
46834688 jump_block,
46844689 & ctx,
46854690 Some ( next_block) ,
46864691 Some ( & ctx) ,
46874692 BranchGenFn :: BranchNil ( Cell :: new ( BranchShape :: Default ) ) ,
4688- ) ? ;
4693+ ) ;
46894694 }
46904695
46914696 Some ( EndBlock )
@@ -8004,19 +8009,14 @@ fn gen_send_iseq(
80048009 return_asm. ctx . set_as_return_landing ( ) ;
80058010
80068011 // Write the JIT return address on the callee frame
8007- if gen_branch (
8008- jit,
8012+ jit. gen_branch (
80098013 asm,
80108014 return_block,
80118015 & return_asm. ctx ,
80128016 None ,
80138017 None ,
80148018 BranchGenFn :: JITReturn ,
8015- ) . is_none ( ) {
8016- // Returning None here would have send_dynamic() code following incomplete
8017- // send code. Abandon the block instead.
8018- jit. block_abandoned = true ;
8019- }
8019+ ) ;
80208020
80218021 // ec->cfp is updated after cfp->jit_return for rb_profile_frames() safety
80228022 asm_comment ! ( asm, "switch to new CFP" ) ;
@@ -8711,8 +8711,7 @@ fn gen_send_general(
87118711
87128712 // Defer compilation so we can specialize on class of receiver
87138713 if !jit. at_compile_target ( ) {
8714- defer_compilation ( jit, asm) ;
8715- return Some ( EndBlock ) ;
8714+ return jit. defer_compilation ( asm) ;
87168715 }
87178716
87188717 let ci_flags = unsafe { vm_ci_flag ( ci) } ;
@@ -9275,8 +9274,7 @@ fn gen_invokeblock_specialized(
92759274 cd : * const rb_call_data ,
92769275) -> Option < CodegenStatus > {
92779276 if !jit. at_compile_target ( ) {
9278- defer_compilation ( jit, asm) ;
9279- return Some ( EndBlock ) ;
9277+ return jit. defer_compilation ( asm) ;
92809278 }
92819279
92829280 // Fallback to dynamic dispatch if this callsite is megamorphic
@@ -9438,8 +9436,7 @@ fn gen_invokesuper_specialized(
94389436) -> Option < CodegenStatus > {
94399437 // Defer compilation so we can specialize on class of receiver
94409438 if !jit. at_compile_target ( ) {
9441- defer_compilation ( jit, asm) ;
9442- return Some ( EndBlock ) ;
9439+ return jit. defer_compilation ( asm) ;
94439440 }
94449441
94459442 // Handle the last two branches of vm_caller_setup_arg_block
@@ -9672,8 +9669,7 @@ fn gen_objtostring(
96729669 asm : & mut Assembler ,
96739670) -> Option < CodegenStatus > {
96749671 if !jit. at_compile_target ( ) {
9675- defer_compilation ( jit, asm) ;
9676- return Some ( EndBlock ) ;
9672+ return jit. defer_compilation ( asm) ;
96779673 }
96789674
96799675 let recv = asm. stack_opnd ( 0 ) ;
@@ -10014,8 +10010,7 @@ fn gen_getblockparamproxy(
1001410010 asm : & mut Assembler ,
1001510011) -> Option < CodegenStatus > {
1001610012 if !jit. at_compile_target ( ) {
10017- defer_compilation ( jit, asm) ;
10018- return Some ( EndBlock ) ;
10013+ return jit. defer_compilation ( asm) ;
1001910014 }
1002010015
1002110016 // EP level
0 commit comments