aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTakashi Kokubun <takashikkbn@gmail.com>2023-04-01 21:03:10 -0700
committerTakashi Kokubun <takashikkbn@gmail.com>2023-04-01 21:03:10 -0700
commit28db75af66f7b8cbbc040a91394b86282702f32c (patch)
tree3a354c7562f97c14db458272b7db91b3bf7b8762
parent249fe18e8f48d289e83aefbe9dc3de0b52b55357 (diff)
downloadruby-28db75af66f7b8cbbc040a91394b86282702f32c.tar.gz
RJIT: Check stackoverflow earlier for ISEQ
-rw-r--r--lib/ruby_vm/rjit/insn_compiler.rb23
1 files changed, 17 insertions, 6 deletions
diff --git a/lib/ruby_vm/rjit/insn_compiler.rb b/lib/ruby_vm/rjit/insn_compiler.rb
index da9797eb21..4836d9a169 100644
--- a/lib/ruby_vm/rjit/insn_compiler.rb
+++ b/lib/ruby_vm/rjit/insn_compiler.rb
@@ -4245,6 +4245,15 @@ module RubyVM::RJIT
end
end
+ # Stack overflow check
+ # Note that vm_push_frame checks it against a decremented cfp, hence the multiply by 2.
+ # #define CHECK_VM_STACK_OVERFLOW0(cfp, sp, margin)
+ asm.comment('stack overflow check')
+ locals_offs = C.VALUE.size * (num_locals + iseq.body.stack_max) + 2 * C.rb_control_frame_t.size
+ asm.lea(:rax, ctx.sp_opnd(locals_offs))
+ asm.cmp(CFP, :rax)
+ asm.jbe(counted_exit(side_exit(jit, ctx), :send_stackoverflow))
+
# Check if we need the arg0 splat handling of vm_callee_setup_block_arg
arg_setup_block = (block_handler == :captured) # arg_setup_type: arg_setup_block (invokeblock)
block_arg0_splat = arg_setup_block && argc == 1 &&
@@ -4438,6 +4447,14 @@ module RubyVM::RJIT
# Check interrupts before SP motion to safely side-exit with the original SP.
jit_check_ints(jit, ctx, asm)
+ # Stack overflow check
+ # #define CHECK_VM_STACK_OVERFLOW0(cfp, sp, margin)
+ # REG_CFP <= REG_SP + 4 * SIZEOF_VALUE + sizeof(rb_control_frame_t)
+ asm.comment('stack overflow check')
+ asm.lea(:rax, ctx.sp_opnd(C.VALUE.size * 4 + 2 * C.rb_control_frame_t.size))
+ asm.cmp(CFP, :rax)
+ asm.jbe(counted_exit(side_exit(jit, ctx), :send_stackoverflow))
+
# Push a callee frame. SP register and ctx are not modified inside this.
jit_push_frame(jit, ctx, asm, cme, flags, argc, frame_type, block_handler)
@@ -4835,12 +4852,6 @@ module RubyVM::RJIT
# @param ctx [RubyVM::RJIT::Context]
# @param asm [RubyVM::RJIT::Assembler]
def jit_push_frame(jit, ctx, asm, cme, flags, argc, frame_type, block_handler, iseq: nil, local_size: 0, stack_max: 0, prev_ep: nil)
- # CHECK_VM_STACK_OVERFLOW0: next_cfp <= sp + (local_size + stack_max)
- asm.comment('stack overflow check')
- asm.lea(:rax, ctx.sp_opnd(C.rb_control_frame_t.size + C.VALUE.size * (local_size + stack_max)))
- asm.cmp(CFP, :rax)
- asm.jbe(counted_exit(side_exit(jit, ctx), :send_stackoverflow))
-
# Save caller SP and PC before pushing a callee frame for backtrace and side exits
asm.comment('save SP to caller CFP')
recv_idx = argc + (flags & C::VM_CALL_ARGS_BLOCKARG != 0 ? 1 : 0) # blockarg is not popped yet