diff options
author | Takashi Kokubun <[email protected]> | 2023-03-19 23:19:58 -0700 |
---|---|---|
committer | Takashi Kokubun <[email protected]> | 2023-03-19 23:32:07 -0700 |
commit | 59b86da82c7e175b1a479c82bffe32d6fe394ecb (patch) | |
tree | fe9e655e40853505144712ac03595a560d7bea85 | |
parent | 47f7ec1c9f9e409ddea0c763b79c4fc9b71da84b (diff) |
RJIT: Implement ifunc invokeblock
-rw-r--r-- | lib/ruby_vm/rjit/insn_compiler.rb | 43 | ||||
-rw-r--r-- | rjit_c.c | 1 | ||||
-rw-r--r-- | rjit_c.h | 3 | ||||
-rw-r--r-- | rjit_c.rb | 7 | ||||
-rwxr-xr-x | tool/rjit/bindgen.rb | 1 |
5 files changed, 51 insertions, 4 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 @@ -505,6 +505,7 @@ extern VALUE rb_reg_new_ary(VALUE ary, int opt); extern void rb_vm_setclassvariable(const rb_iseq_t *iseq, const rb_control_frame_t *cfp, ID id, VALUE val, ICVARC ic); extern VALUE rb_str_bytesize(VALUE str); extern const rb_callable_method_entry_t *rb_callable_method_entry_or_negative(VALUE klass, ID mid); +extern VALUE rb_vm_yield_with_cfunc(rb_execution_context_t *ec, const struct rb_captured_block *captured, int argc, const VALUE *argv); #include "rjit_c.rbinc" @@ -84,13 +84,14 @@ RJIT_RUNTIME_COUNTERS( invokesuper_same_me, invokeblock_none, - invokeblock_ifunc, invokeblock_symbol, invokeblock_proc, invokeblock_tag_changed, invokeblock_iseq_block_changed, invokeblock_iseq_arity, invokeblock_iseq_arg0_splat, + invokeblock_ifunc_args_splat, + invokeblock_ifunc_kw_splat, getivar_megamorphic, getivar_not_heap, @@ -701,6 +701,10 @@ module RubyVM::RJIT # :nodoc: all Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_vm_throw) } end + def C.rb_vm_yield_with_cfunc + Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_vm_yield_with_cfunc) } + end + def C.rjit_full_cfunc_return Primitive.cexpr! %q{ SIZET2NUM((size_t)rjit_full_cfunc_return) } end @@ -1316,13 +1320,14 @@ module RubyVM::RJIT # :nodoc: all invokesuper_me_changed: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), invokesuper_me_changed)")], invokesuper_same_me: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), invokesuper_same_me)")], invokeblock_none: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), invokeblock_none)")], - invokeblock_ifunc: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), invokeblock_ifunc)")], invokeblock_symbol: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), invokeblock_symbol)")], invokeblock_proc: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), invokeblock_proc)")], invokeblock_tag_changed: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), invokeblock_tag_changed)")], invokeblock_iseq_block_changed: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), invokeblock_iseq_block_changed)")], invokeblock_iseq_arity: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), invokeblock_iseq_arity)")], invokeblock_iseq_arg0_splat: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), invokeblock_iseq_arg0_splat)")], + invokeblock_ifunc_args_splat: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), invokeblock_ifunc_args_splat)")], + invokeblock_ifunc_kw_splat: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), invokeblock_ifunc_kw_splat)")], getivar_megamorphic: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), getivar_megamorphic)")], getivar_not_heap: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), getivar_not_heap)")], getivar_special_const: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), getivar_special_const)")], diff --git a/tool/rjit/bindgen.rb b/tool/rjit/bindgen.rb index 9916ebe0d0..cd8502a2a7 100755 --- a/tool/rjit/bindgen.rb +++ b/tool/rjit/bindgen.rb @@ -553,6 +553,7 @@ generator = BindingGenerator.new( rjit_str_simple_append rb_str_buf_append rb_str_dup + rb_vm_yield_with_cfunc ], types: %w[ CALL_DATA |