diff options
author | Takashi Kokubun <[email protected]> | 2023-02-16 00:11:38 -0800 |
---|---|---|
committer | Takashi Kokubun <[email protected]> | 2023-03-05 23:28:59 -0800 |
commit | a4bf1c661b47840f49ab1081f37fe677f7de09cd (patch) | |
tree | 2bf78c73544cb6bd0fd620e04920c013c23e9a07 | |
parent | 7b78fd0df216002303f8b44a701866be1c9db2f9 (diff) |
Implement opt_invokebuiltin_delegate
Notes
Notes:
Merged: https://github.com/ruby/ruby/pull/7448
-rw-r--r-- | lib/ruby_vm/mjit/insn_compiler.rb | 54 | ||||
-rw-r--r-- | mjit_c.rb | 4 | ||||
-rwxr-xr-x | tool/mjit/bindgen.rb | 5 |
3 files changed, 56 insertions, 7 deletions
diff --git a/lib/ruby_vm/mjit/insn_compiler.rb b/lib/ruby_vm/mjit/insn_compiler.rb index bc65216a4d..110e0a8961 100644 --- a/lib/ruby_vm/mjit/insn_compiler.rb +++ b/lib/ruby_vm/mjit/insn_compiler.rb @@ -23,7 +23,7 @@ module RubyVM::MJIT asm.incr_counter(:mjit_insns_count) asm.comment("Insn: #{insn.name}") - # 49/101 + # 51/101 case insn.name when :nop then nop(jit, ctx, asm) when :getlocal then getlocal(jit, ctx, asm) @@ -118,8 +118,8 @@ module RubyVM::MJIT when :opt_not then opt_not(jit, ctx, asm) when :opt_regexpmatch2 then opt_regexpmatch2(jit, ctx, asm) # invokebuiltin - # opt_invokebuiltin_delegate - # opt_invokebuiltin_delegate_leave + when :opt_invokebuiltin_delegate then opt_invokebuiltin_delegate(jit, ctx, asm) + when :opt_invokebuiltin_delegate_leave then opt_invokebuiltin_delegate_leave(jit, ctx, asm) when :getlocal_WC_0 then getlocal_WC_0(jit, ctx, asm) when :getlocal_WC_1 then getlocal_WC_1(jit, ctx, asm) when :setlocal_WC_0 then setlocal_WC_0(jit, ctx, asm) @@ -1164,8 +1164,52 @@ module RubyVM::MJIT end # invokebuiltin - # opt_invokebuiltin_delegate - # opt_invokebuiltin_delegate_leave + + def opt_invokebuiltin_delegate(jit, ctx, asm) + bf = C.rb_builtin_function.new(jit.operand(0)) + bf_argc = bf.argc + start_index = jit.operand(1) + + # ec, self, and arguments + if bf_argc + 2 > C_ARGS.size + return CantCompile + end + + # If the calls don't allocate, do they need up to date PC, SP? + jit_prepare_routine_call(jit, ctx, asm) + + # Call the builtin func (ec, recv, arg1, arg2, ...) + asm.comment('call builtin func') + asm.mov(C_ARGS[0], EC) + asm.mov(C_ARGS[1], [CFP, C.rb_control_frame_t.offsetof(:self)]) + + # Copy arguments from locals + if bf_argc > 0 + # Load environment pointer EP from CFP + asm.mov(:rax, [CFP, C.rb_control_frame_t.offsetof(:ep)]) + + bf_argc.times do |i| + table_size = jit.iseq.body.local_table_size + offs = -table_size - C.VM_ENV_DATA_SIZE + 1 + start_index + i + asm.mov(C_ARGS[2 + i], [:rax, offs * C.VALUE.size]) + end + end + asm.call(bf.func_ptr) + + # Push the return value + stack_ret = ctx.stack_push + asm.mov(stack_ret, C_RET) + + KeepCompiling + end + + # @param jit [RubyVM::MJIT::JITState] + # @param ctx [RubyVM::MJIT::Context] + # @param asm [RubyVM::MJIT::Assembler] + def opt_invokebuiltin_delegate_leave(jit, ctx, asm) + opt_invokebuiltin_delegate(jit, ctx, asm) + # opt_invokebuiltin_delegate is always followed by leave insn + end # @param jit [RubyVM::MJIT::JITState] # @param ctx [RubyVM::MJIT::Context] @@ -833,7 +833,7 @@ module RubyVM::MJIT # :nodoc: all def C.rb_builtin_function @rb_builtin_function ||= CType::Struct.new( "rb_builtin_function", Primitive.cexpr!("SIZEOF(struct rb_builtin_function)"), - func_ptr: [CType::Pointer.new { CType::Immediate.parse("void") }, Primitive.cexpr!("OFFSETOF((*((struct rb_builtin_function *)NULL)), func_ptr)")], + func_ptr: [CType::Immediate.parse("void *"), Primitive.cexpr!("OFFSETOF((*((struct rb_builtin_function *)NULL)), func_ptr)")], argc: [CType::Immediate.parse("int"), Primitive.cexpr!("OFFSETOF((*((struct rb_builtin_function *)NULL)), argc)")], index: [CType::Immediate.parse("int"), Primitive.cexpr!("OFFSETOF((*((struct rb_builtin_function *)NULL)), index)")], name: [CType::Pointer.new { CType::Immediate.parse("char") }, Primitive.cexpr!("OFFSETOF((*((struct rb_builtin_function *)NULL)), name)")], @@ -898,7 +898,7 @@ module RubyVM::MJIT # :nodoc: all iseq: [CType::Pointer.new { self.rb_iseq_t }, Primitive.cexpr!("OFFSETOF((*((struct rb_control_frame_struct *)NULL)), iseq)")], self: [self.VALUE, Primitive.cexpr!("OFFSETOF((*((struct rb_control_frame_struct *)NULL)), self)")], ep: [CType::Pointer.new { self.VALUE }, Primitive.cexpr!("OFFSETOF((*((struct rb_control_frame_struct *)NULL)), ep)")], - block_code: [CType::Pointer.new { CType::Immediate.parse("void") }, Primitive.cexpr!("OFFSETOF((*((struct rb_control_frame_struct *)NULL)), block_code)")], + block_code: [CType::Immediate.parse("void *"), Primitive.cexpr!("OFFSETOF((*((struct rb_control_frame_struct *)NULL)), block_code)")], __bp__: [CType::Pointer.new { self.VALUE }, Primitive.cexpr!("OFFSETOF((*((struct rb_control_frame_struct *)NULL)), __bp__)")], jit_return: [CType::Pointer.new { CType::Immediate.parse("void") }, Primitive.cexpr!("OFFSETOF((*((struct rb_control_frame_struct *)NULL)), jit_return)")], ) diff --git a/tool/mjit/bindgen.rb b/tool/mjit/bindgen.rb index 29abef9f87..dc2e76dd68 100755 --- a/tool/mjit/bindgen.rb +++ b/tool/mjit/bindgen.rb @@ -270,6 +270,11 @@ class BindingGenerator end type = type.delete_suffix('const') if type.end_with?('*') + if type == 'const void *' + # `CType::Pointer.new { CType::Immediate.parse("void") }` is never useful, + # so specially handle that case here. + return 'CType::Immediate.parse("void *")' + end return "CType::Pointer.new { #{generate_type(type.delete_suffix('*').rstrip)} }" end |