diff options
author | Nobuyoshi Nakada <[email protected]> | 2025-02-13 15:59:16 +0900 |
---|---|---|
committer | Nobuyoshi Nakada <[email protected]> | 2025-02-13 18:01:03 +0900 |
commit | 4a67ef09ccd703047552b740431cfe15e32451f4 (patch) | |
tree | 1092e15836655fde8935c7788eb0a411e8c9ca42 /lib/ruby_vm/rjit/exit_compiler.rb | |
parent | d35cc0cc772b48c5aaba354e7084278da68f44e4 (diff) |
[Feature #21116] Extract RJIT as a third-party gem
Notes
Notes:
Merged: https://github.com/ruby/ruby/pull/12740
Diffstat (limited to 'lib/ruby_vm/rjit/exit_compiler.rb')
-rw-r--r-- | lib/ruby_vm/rjit/exit_compiler.rb | 164 |
1 files changed, 0 insertions, 164 deletions
diff --git a/lib/ruby_vm/rjit/exit_compiler.rb b/lib/ruby_vm/rjit/exit_compiler.rb deleted file mode 100644 index 1ced2141a4..0000000000 --- a/lib/ruby_vm/rjit/exit_compiler.rb +++ /dev/null @@ -1,164 +0,0 @@ -module RubyVM::RJIT - class ExitCompiler - def initialize = freeze - - # Used for invalidating a block on entry. - # @param pc [Integer] - # @param asm [RubyVM::RJIT::Assembler] - def compile_entry_exit(pc, ctx, asm, cause:) - # Fix pc/sp offsets for the interpreter - save_pc_and_sp(pc, ctx, asm, reset_sp_offset: false) - - # Increment per-insn exit counter - count_insn_exit(pc, asm) - - # Restore callee-saved registers - asm.comment("#{cause}: entry exit") - asm.pop(SP) - asm.pop(EC) - asm.pop(CFP) - - asm.mov(C_RET, Qundef) - asm.ret - end - - # Set to cfp->jit_return by default for leave insn - # @param asm [RubyVM::RJIT::Assembler] - def compile_leave_exit(asm) - asm.comment('default cfp->jit_return') - - # Restore callee-saved registers - asm.pop(SP) - asm.pop(EC) - asm.pop(CFP) - - # :rax is written by #leave - asm.ret - end - - # Fire cfunc events on invalidation by TracePoint - # @param asm [RubyVM::RJIT::Assembler] - def compile_full_cfunc_return(asm) - # This chunk of code expects REG_EC to be filled properly and - # RAX to contain the return value of the C method. - - asm.comment('full cfunc return') - asm.mov(C_ARGS[0], EC) - asm.mov(C_ARGS[1], :rax) - asm.call(C.rjit_full_cfunc_return) - - # TODO: count the exit - - # Restore callee-saved registers - asm.pop(SP) - asm.pop(EC) - asm.pop(CFP) - - asm.mov(C_RET, Qundef) - asm.ret - end - - # @param jit [RubyVM::RJIT::JITState] - # @param ctx [RubyVM::RJIT::Context] - # @param asm [RubyVM::RJIT::Assembler] - def compile_side_exit(pc, ctx, asm) - # Fix pc/sp offsets for the interpreter - save_pc_and_sp(pc, ctx.dup, asm) # dup to avoid sp_offset update - - # Increment per-insn exit counter - count_insn_exit(pc, asm) - - # Restore callee-saved registers - asm.comment("exit to interpreter on #{pc_to_insn(pc).name}") - asm.pop(SP) - asm.pop(EC) - asm.pop(CFP) - - asm.mov(C_RET, Qundef) - asm.ret - end - - # @param asm [RubyVM::RJIT::Assembler] - # @param entry_stub [RubyVM::RJIT::EntryStub] - def compile_entry_stub(asm, entry_stub) - # Call rb_rjit_entry_stub_hit - asm.comment('entry stub hit') - asm.mov(C_ARGS[0], to_value(entry_stub)) - asm.call(C.rb_rjit_entry_stub_hit) - - # Jump to the address returned by rb_rjit_entry_stub_hit - asm.jmp(:rax) - end - - # @param ctx [RubyVM::RJIT::Context] - # @param asm [RubyVM::RJIT::Assembler] - # @param branch_stub [RubyVM::RJIT::BranchStub] - # @param target0_p [TrueClass,FalseClass] - def compile_branch_stub(ctx, asm, branch_stub, target0_p) - # Call rb_rjit_branch_stub_hit - iseq = branch_stub.iseq - if C.rjit_opts.dump_disasm && C.imemo_type_p(iseq, C.imemo_iseq) # Guard against ISEQ GC at random moments - asm.comment("branch stub hit: #{iseq.body.location.label}@#{C.rb_iseq_path(iseq)}:#{iseq_lineno(iseq, target0_p ? branch_stub.target0.pc : branch_stub.target1.pc)}") - end - asm.mov(:rdi, to_value(branch_stub)) - asm.mov(:esi, ctx.sp_offset) - asm.mov(:edx, target0_p ? 1 : 0) - asm.call(C.rb_rjit_branch_stub_hit) - - # Jump to the address returned by rb_rjit_branch_stub_hit - asm.jmp(:rax) - end - - private - - def pc_to_insn(pc) - Compiler.decode_insn(C.VALUE.new(pc).*) - end - - # @param pc [Integer] - # @param asm [RubyVM::RJIT::Assembler] - def count_insn_exit(pc, asm) - if C.rjit_opts.stats - insn = Compiler.decode_insn(C.VALUE.new(pc).*) - asm.comment("increment insn exit: #{insn.name}") - asm.mov(:rax, (C.rjit_insn_exits + insn.bin).to_i) - asm.add([:rax], 1) # TODO: lock - end - if C.rjit_opts.trace_exits - asm.comment('rjit_record_exit_stack') - asm.mov(C_ARGS[0], pc) - asm.call(C.rjit_record_exit_stack) - end - end - - # @param jit [RubyVM::RJIT::JITState] - # @param ctx [RubyVM::RJIT::Context] - # @param asm [RubyVM::RJIT::Assembler] - def save_pc_and_sp(pc, ctx, asm, reset_sp_offset: true) - # Update pc (TODO: manage PC offset?) - asm.comment("save PC#{' and SP' if ctx.sp_offset != 0} to CFP") - asm.mov(:rax, pc) # rax = jit.pc - asm.mov([CFP, C.rb_control_frame_t.offsetof(:pc)], :rax) # cfp->pc = rax - - # Update sp - if ctx.sp_offset != 0 - asm.add(SP, C.VALUE.size * ctx.sp_offset) # sp += stack_size - asm.mov([CFP, C.rb_control_frame_t.offsetof(:sp)], SP) # cfp->sp = sp - if reset_sp_offset - ctx.sp_offset = 0 - end - end - end - - def to_value(obj) - GC_REFS << obj - C.to_value(obj) - end - - def iseq_lineno(iseq, pc) - C.rb_iseq_line_no(iseq, (pc - iseq.body.iseq_encoded.to_i) / C.VALUE.size) - rescue RangeError # bignum too big to convert into `unsigned long long' (RangeError) - -1 - end - end -end |