aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorTakashi Kokubun <takashikkbn@gmail.com>2022-11-27 21:41:53 -0800
committerTakashi Kokubun <takashikkbn@gmail.com>2022-11-27 21:44:28 -0800
commita22c684c5940210515d295684e016cd834b2b53f (patch)
tree08d8ecf5e9b9b6061121fad80cc5308ddaf07e50 /lib
parent6844bcc6b4cdc50def1c0d30d4e8b5045fb43443 (diff)
downloadruby-a22c684c5940210515d295684e016cd834b2b53f.tar.gz
MJIT: Refactor invokebuiltin_delegate_leave
You shouldn't assume bf->compiler is always non-zero. While struct aref/aset is no longer a builtin function since https://github.com/ruby/ruby/pull/5131, it seems like you could still load such an iseq binary. The refactored code fallbacks to compile_insn_default correctly when bf->compiler is zero.
Diffstat (limited to 'lib')
-rw-r--r--lib/mjit/compiler.rb52
1 files changed, 25 insertions, 27 deletions
diff --git a/lib/mjit/compiler.rb b/lib/mjit/compiler.rb
index 07a5646542..e0bd5e85b9 100644
--- a/lib/mjit/compiler.rb
+++ b/lib/mjit/compiler.rb
@@ -202,40 +202,23 @@ module RubyVM::MJIT
if src = compile_ivar(insn.name, stack_size, pos, status, operands, body)
return src, next_pos, finish_p, compile_insns
end
- when :invokebuiltin, :opt_invokebuiltin_delegate
- if src = compile_invokebuiltin(insn, stack_size, sp_inc, body, operands)
- return src, next_pos, finish_p, compile_insns
- end
when :opt_getconstant_path
if src = compile_getconstant_path(stack_size, pos, insn_len, operands, status)
return src, next_pos, finish_p, compile_insns
end
- when :leave, :opt_invokebuiltin_delegate_leave
- src = +''
-
- # opt_invokebuiltin_delegate_leave also implements leave insn. We need to handle it here for inlining.
- if insn.name == :opt_invokebuiltin_delegate_leave
- if invokebuiltin_src = compile_invokebuiltin(insn, stack_size, sp_inc, body, operands)
- src << invokebuiltin_src
- end
- else
- if stack_size != 1
- $stderr.puts "MJIT warning: Unexpected JIT stack_size on leave: #{stack_size}" # TODO: check mjit_opts?
- return nil
+ when :invokebuiltin, :opt_invokebuiltin_delegate, :opt_invokebuiltin_delegate_leave
+ if src = compile_invokebuiltin(insn, stack_size, sp_inc, body, operands)
+ if insn.name == :opt_invokebuiltin_delegate_leave
+ src << compile_leave(stack_size, pos, inlined_iseq_p)
+ finish_p = true
end
+ return src, next_pos, finish_p, compile_insns
end
-
- # Skip vm_pop_frame for inlined call
- unless inlined_iseq_p
- # Cancel on interrupts to make leave insn leaf
- src << " if (UNLIKELY(RUBY_VM_INTERRUPTED_ANY(ec))) {\n"
- src << " reg_cfp->sp = vm_base_ptr(reg_cfp) + #{stack_size};\n"
- src << " reg_cfp->pc = original_body_iseq + #{pos};\n"
- src << " rb_threadptr_execute_interrupts(rb_ec_thread_ptr(ec), 0);\n"
- src << " }\n"
- src << " ec->cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(reg_cfp);\n" # vm_pop_frame
+ when :leave
+ if stack_size != 1
+ raise "Unexpected JIT stack_size on leave: #{stack_size}"
end
- src << " return stack[0];\n"
+ src = compile_leave(stack_size, pos, inlined_iseq_p)
finish_p = true
return src, next_pos, finish_p, compile_insns
end
@@ -424,6 +407,21 @@ module RubyVM::MJIT
end
end
+ def compile_leave(stack_size, pos, inlined_iseq_p)
+ src = +''
+ # Skip vm_pop_frame for inlined call
+ unless inlined_iseq_p
+ # Cancel on interrupts to make leave insn leaf
+ src << " if (UNLIKELY(RUBY_VM_INTERRUPTED_ANY(ec))) {\n"
+ src << " reg_cfp->sp = vm_base_ptr(reg_cfp) + #{stack_size};\n"
+ src << " reg_cfp->pc = original_body_iseq + #{pos};\n"
+ src << " rb_threadptr_execute_interrupts(rb_ec_thread_ptr(ec), 0);\n"
+ src << " }\n"
+ src << " ec->cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(reg_cfp);\n" # vm_pop_frame
+ end
+ src << " return stack[0];\n"
+ end
+
def compile_getconstant_path(stack_size, pos, insn_len, operands, status)
ice = C.IC.new(operands[0]).entry
if !status.compile_info.disable_const_cache && ice