diff options
author | Takashi Kokubun <[email protected]> | 2023-04-01 21:23:36 -0700 |
---|---|---|
committer | Takashi Kokubun <[email protected]> | 2023-04-01 21:30:42 -0700 |
commit | e45ed2da5046f7ee2a82f332d211ddbd7108fc22 (patch) | |
tree | e65ce9898be564eb21f234351b7c4b77f283b266 /lib/ruby_vm/rjit/insn_compiler.rb | |
parent | 90cdc5b8ba5421bfd183c2bfba16c1fd3ca7e0f5 (diff) |
RJIT: Rewind stack_size on CantCompile and side exits
so that we can take an exit whenever we want.
As a starter, this commit also pops blockarg earlier than some
CantCompile exits.
Diffstat (limited to 'lib/ruby_vm/rjit/insn_compiler.rb')
-rw-r--r-- | lib/ruby_vm/rjit/insn_compiler.rb | 23 |
1 files changed, 12 insertions, 11 deletions
diff --git a/lib/ruby_vm/rjit/insn_compiler.rb b/lib/ruby_vm/rjit/insn_compiler.rb index 62074eafaf..27031dc0e3 100644 --- a/lib/ruby_vm/rjit/insn_compiler.rb +++ b/lib/ruby_vm/rjit/insn_compiler.rb @@ -4237,7 +4237,10 @@ module RubyVM::RJIT # Number of locals that are not parameters num_locals = iseq.body.local_table_size - num_params - # blockarg is currently popped later + # Pop blockarg after all side exits + if flags & C::VM_CALL_ARGS_BLOCKARG != 0 + ctx.stack_pop(1) + end if block_handler == C::VM_BLOCK_HANDLER_NONE && iseq.body.builtin_attrs & C::BUILTIN_ATTR_LEAF != 0 if jit_leaf_builtin_func(jit, ctx, asm, flags, iseq) @@ -4290,11 +4293,6 @@ module RubyVM::RJIT return CantCompile end - # Pop blockarg after all side exits - if flags & C::VM_CALL_ARGS_BLOCKARG != 0 - ctx.stack_pop(1) - end - # Setup the new frame frame_type ||= C::VM_FRAME_MAGIC_METHOD | C::VM_ENV_FLAG_LOCAL jit_push_frame( @@ -5187,12 +5185,15 @@ module RubyVM::RJIT # @param jit [RubyVM::RJIT::JITState] # @param ctx [RubyVM::RJIT::Context] def side_exit(jit, ctx) - if side_exit = jit.side_exits[jit.pc] - return side_exit + # We use the latest ctx.sp_offset to generate a side exit to tolerate sp_offset changes by jit_save_sp. + # However, we want to simulate an old stack_size when we take a side exit. We do that by adjusting the + # sp_offset because gen_outlined_exit uses ctx.sp_offset to move SP. + ctx = ctx.with_stack_size(jit.stack_size_for_pc) + + jit.side_exit_for_pc[ctx.sp_offset] ||= Assembler.new.then do |asm| + @exit_compiler.compile_side_exit(jit.pc, ctx, asm) + @ocb.write(asm) end - asm = Assembler.new - @exit_compiler.compile_side_exit(jit.pc, ctx, asm) - jit.side_exits[jit.pc] = @ocb.write(asm) end def counted_exit(side_exit, name) |