@@ -20,6 +20,7 @@ use crate::hir::{iseq_to_hir, Block, BlockId, BranchEdge, Invariant, RangeType,
2020use crate :: hir:: { Const , FrameState , Function , Insn , InsnId } ;
2121use crate :: hir_type:: { types, Type } ;
2222use crate :: options:: get_option;
23+ use crate :: cast:: IntoUsize ;
2324
2425/// Ephemeral code generation state
2526struct JITState {
@@ -1042,6 +1043,19 @@ fn gen_send_without_block_direct(
10421043 args : Vec < Opnd > ,
10431044 state : & FrameState ,
10441045) -> lir:: Opnd {
1046+ let local_size = unsafe { get_iseq_body_local_table_size ( iseq) } . as_usize ( ) ;
1047+ // Stack overflow check: fails if CFP<=SP at any point in the callee.
1048+ asm_comment ! ( asm, "stack overflow check" ) ;
1049+ let stack_growth = state. stack_size ( ) + local_size + unsafe { get_iseq_body_stack_max ( iseq) } . as_usize ( ) ;
1050+ // vm_push_frame() checks it against a decremented cfp, and CHECK_VM_STACK_OVERFLOW0
1051+ // adds to the margin another control frame with `&bounds[1]`.
1052+ const { assert ! ( RUBY_SIZEOF_CONTROL_FRAME % SIZEOF_VALUE == 0 , "sizeof(rb_control_frame_t) is a multiple of sizeof(VALUE)" ) ; }
1053+ let cfp_growth = 2 * ( RUBY_SIZEOF_CONTROL_FRAME / SIZEOF_VALUE ) ;
1054+ let peak_offset = SIZEOF_VALUE * ( stack_growth + cfp_growth) ;
1055+ let stack_limit = asm. add ( SP , peak_offset. into ( ) ) ;
1056+ asm. cmp ( CFP , stack_limit) ;
1057+ asm. jbe ( side_exit ( jit, state, StackOverflow ) ) ;
1058+
10451059 // Save cfp->pc and cfp->sp for the caller frame
10461060 gen_prepare_call_with_gc ( asm, state) ;
10471061 gen_save_sp ( asm, state. stack ( ) . len ( ) - args. len ( ) - 1 ) ; // -1 for receiver
@@ -1059,8 +1073,7 @@ fn gen_send_without_block_direct(
10591073 } ) ;
10601074
10611075 asm_comment ! ( asm, "switch to new SP register" ) ;
1062- let local_size = unsafe { get_iseq_body_local_table_size ( iseq) } as usize ;
1063- let sp_offset = ( state. stack ( ) . len ( ) + local_size - args. len ( ) + VM_ENV_DATA_SIZE as usize ) * SIZEOF_VALUE ;
1076+ let sp_offset = ( state. stack ( ) . len ( ) + local_size - args. len ( ) + VM_ENV_DATA_SIZE . as_usize ( ) ) * SIZEOF_VALUE ;
10641077 let new_sp = asm. add ( SP , sp_offset. into ( ) ) ;
10651078 asm. mov ( SP , new_sp) ;
10661079
0 commit comments