summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTakashi Kokubun <[email protected]>2023-02-16 00:11:38 -0800
committerTakashi Kokubun <[email protected]>2023-03-05 23:28:59 -0800
commita4bf1c661b47840f49ab1081f37fe677f7de09cd (patch)
tree2bf78c73544cb6bd0fd620e04920c013c23e9a07
parent7b78fd0df216002303f8b44a701866be1c9db2f9 (diff)
Implement opt_invokebuiltin_delegate
Notes
Notes: Merged: https://github.com/ruby/ruby/pull/7448
-rw-r--r--lib/ruby_vm/mjit/insn_compiler.rb54
-rw-r--r--mjit_c.rb4
-rwxr-xr-xtool/mjit/bindgen.rb5
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]
diff --git a/mjit_c.rb b/mjit_c.rb
index 9dc64eb118..ef515f5bea 100644
--- a/mjit_c.rb
+++ b/mjit_c.rb
@@ -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