@@ -223,6 +223,17 @@ impl<'a> JITState<'a> {
223223 }
224224 }
225225
226+ /// Wrapper for [self::gen_outlined_exit] with error handling.
227+ fn gen_outlined_exit ( & mut self , exit_pc : * mut VALUE , ctx : & Context ) -> Option < CodePtr > {
228+ let result = gen_outlined_exit ( exit_pc, self . num_locals ( ) , ctx, self . get_ocb ( ) ) ;
229+ if result. is_none ( ) {
230+ // When we can't have the exits, the code is incomplete and we have to bail.
231+ self . block_abandoned = true ;
232+ }
233+
234+ result
235+ }
236+
226237 /// Return true if the current ISEQ could escape an environment.
227238 ///
228239 /// As of vm_push_frame(), EP is always equal to BP. However, after pushing
@@ -879,6 +890,10 @@ fn gen_exit(exit_pc: *mut VALUE, asm: &mut Assembler) {
879890/// moment, so there is one unique side exit for each context. Note that
880891/// it's incorrect to jump to the side exit after any ctx stack push operations
881892/// since they change the logic required for reconstructing interpreter state.
893+ ///
894+ /// If you're in [the codegen module][self], use [JITState::gen_outlined_exit]
895+ /// instead of calling this directly.
896+ #[ must_use]
882897pub fn gen_outlined_exit ( exit_pc : * mut VALUE , num_locals : u32 , ctx : & Context , ocb : & mut OutlinedCb ) -> Option < CodePtr > {
883898 let mut cb = ocb. unwrap ( ) ;
884899 let mut asm = Assembler :: new ( num_locals) ;
@@ -943,7 +958,7 @@ pub fn jit_ensure_block_entry_exit(jit: &mut JITState, asm: &mut Assembler) -> O
943958 jit. block_entry_exit = Some ( entry_exit?) ;
944959 } else {
945960 let block_entry_pc = unsafe { rb_iseq_pc_at_idx ( jit. iseq , jit. starting_insn_idx . into ( ) ) } ;
946- jit. block_entry_exit = Some ( gen_outlined_exit ( block_entry_pc, jit . num_locals ( ) , block_starting_context, jit . get_ocb ( ) ) ?) ;
961+ jit. block_entry_exit = Some ( jit . gen_outlined_exit ( block_entry_pc, block_starting_context) ?) ;
947962 }
948963
949964 Some ( ( ) )
@@ -1201,7 +1216,7 @@ fn end_block_with_jump(
12011216 if jit. record_boundary_patch_point {
12021217 jit. record_boundary_patch_point = false ;
12031218 let exit_pc = unsafe { rb_iseq_pc_at_idx ( jit. iseq , continuation_insn_idx. into ( ) ) } ;
1204- let exit_pos = gen_outlined_exit ( exit_pc, jit . num_locals ( ) , & reset_depth, jit . get_ocb ( ) ) ;
1219+ let exit_pos = jit . gen_outlined_exit ( exit_pc, & reset_depth) ;
12051220 record_global_inval_patch ( asm, exit_pos?) ;
12061221 }
12071222
@@ -1310,7 +1325,7 @@ pub fn gen_single_block(
13101325 // If previous instruction requested to record the boundary
13111326 if jit. record_boundary_patch_point {
13121327 // Generate an exit to this instruction and record it
1313- let exit_pos = gen_outlined_exit ( jit. pc , jit . num_locals ( ) , & asm. ctx , jit . get_ocb ( ) ) . ok_or ( ( ) ) ?;
1328+ let exit_pos = jit . gen_outlined_exit ( jit. pc , & asm. ctx ) . ok_or ( ( ) ) ?;
13141329 record_global_inval_patch ( & mut asm, exit_pos) ;
13151330 jit. record_boundary_patch_point = false ;
13161331 }
0 commit comments