summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorTakashi Kokubun <takashikkbn@gmail.com>2023-03-19 23:19:58 -0700
committerTakashi Kokubun <takashikkbn@gmail.com>2023-03-19 23:32:07 -0700
commit59b86da82c7e175b1a479c82bffe32d6fe394ecb (patch)
treefe9e655e40853505144712ac03595a560d7bea85 /lib
parent47f7ec1c9f9e409ddea0c763b79c4fc9b71da84b (diff)
RJIT: Implement ifunc invokeblock
Diffstat (limited to 'lib')
-rw-r--r--lib/ruby_vm/rjit/insn_compiler.rb43
1 files changed, 41 insertions, 2 deletions
diff --git a/lib/ruby_vm/rjit/insn_compiler.rb b/lib/ruby_vm/rjit/insn_compiler.rb
index 058195a62b..013f961829 100644
--- a/lib/ruby_vm/rjit/insn_compiler.rb
+++ b/lib/ruby_vm/rjit/insn_compiler.rb
@@ -1536,8 +1536,47 @@ module RubyVM::RJIT
send_shift: 0, frame_type: C::VM_FRAME_MAGIC_BLOCK,
)
elsif comptime_handler & 0x3 == 0x3 # VM_BH_IFUNC_P
- asm.incr_counter(:invokeblock_ifunc)
- CantCompile
+ # We aren't handling CALLER_SETUP_ARG and CALLER_REMOVE_EMPTY_KW_SPLAT yet.
+ if calling.flags & C::VM_CALL_ARGS_SPLAT != 0
+ asm.incr_counter(:invokeblock_ifunc_args_splat)
+ return CantCompile
+ end
+ if calling.flags & C::VM_CALL_KW_SPLAT != 0
+ asm.incr_counter(:invokeblock_ifunc_kw_splat)
+ return CantCompile
+ end
+
+ asm.comment('get local EP')
+ jit_get_lep(jit, asm, reg: :rax)
+ asm.mov(:rcx, [:rax, C.VALUE.size * C::VM_ENV_DATA_INDEX_SPECVAL]) # block_handler_opnd
+
+ asm.comment('guard block_handler type');
+ side_exit = side_exit(jit, ctx)
+ asm.mov(:rax, :rcx) # block_handler_opnd
+ asm.and(:rax, 0x3) # tag_opnd: block_handler is a tagged pointer
+ asm.cmp(:rax, 0x3) # VM_BH_IFUNC_P
+ tag_changed_exit = counted_exit(side_exit, :invokeblock_tag_changed)
+ jit_chain_guard(:jne, jit, ctx, asm, tag_changed_exit)
+
+ # The cfunc may not be leaf
+ jit_prepare_routine_call(jit, ctx, asm) # clobbers :rax
+
+ asm.comment('call ifunc')
+ asm.and(:rcx, ~0x3) # captured_opnd
+ asm.lea(:rax, ctx.sp_opnd(-calling.argc * C.VALUE.size)) # argv
+ asm.mov(C_ARGS[0], EC)
+ asm.mov(C_ARGS[1], :rcx) # captured_opnd
+ asm.mov(C_ARGS[2], calling.argc)
+ asm.mov(C_ARGS[3], :rax) # argv
+ asm.call(C.rb_vm_yield_with_cfunc)
+
+ ctx.stack_pop(calling.argc)
+ stack_ret = ctx.stack_push
+ asm.mov(stack_ret, C_RET)
+
+ # Share the successor with other chains
+ jump_to_next_insn(jit, ctx, asm)
+ EndBlock
elsif symbol?(comptime_handler)
asm.incr_counter(:invokeblock_symbol)
CantCompile