зеркало из https://github.com/github/ruby.git
RJIT: Support has_opt ISEQs
This commit is contained in:
Родитель
ad2b719fc2
Коммит
4fc336127e
|
@ -53,13 +53,11 @@ module RubyVM::RJIT
|
|||
# @param iseq `RubyVM::RJIT::CPointer::Struct_rb_iseq_t`
|
||||
# @param cfp `RubyVM::RJIT::CPointer::Struct_rb_control_frame_t`
|
||||
def compile(iseq, cfp)
|
||||
# TODO: Support has_opt
|
||||
return if iseq.body.param.flags.has_opt
|
||||
|
||||
pc = cfp.pc.to_i
|
||||
jit = JITState.new(iseq:, cfp:)
|
||||
asm = Assembler.new
|
||||
compile_prologue(asm)
|
||||
compile_block(asm, jit:)
|
||||
compile_prologue(asm, iseq, pc)
|
||||
compile_block(asm, jit:, pc:)
|
||||
iseq.body.jit_func = @cb.write(asm)
|
||||
rescue Exception => e
|
||||
$stderr.puts e.full_message
|
||||
|
@ -186,7 +184,7 @@ module RubyVM::RJIT
|
|||
# Caller-saved: rax, rdi, rsi, rdx, rcx, r8, r9, r10, r11
|
||||
#
|
||||
# @param asm [RubyVM::RJIT::Assembler]
|
||||
def compile_prologue(asm)
|
||||
def compile_prologue(asm, iseq, pc)
|
||||
asm.comment('RJIT entry point')
|
||||
|
||||
# Save callee-saved registers used by JITed code
|
||||
|
@ -204,10 +202,42 @@ module RubyVM::RJIT
|
|||
# Setup cfp->jit_return
|
||||
asm.mov(:rax, leave_exit)
|
||||
asm.mov([CFP, C.rb_control_frame_t.offsetof(:jit_return)], :rax)
|
||||
|
||||
# We're compiling iseqs that we *expect* to start at `insn_idx`. But in
|
||||
# the case of optional parameters, the interpreter can set the pc to a
|
||||
# different location depending on the optional parameters. If an iseq
|
||||
# has optional parameters, we'll add a runtime check that the PC we've
|
||||
# compiled for is the same PC that the interpreter wants us to run with.
|
||||
# If they don't match, then we'll take a side exit.
|
||||
if iseq.body.param.flags.has_opt
|
||||
compile_pc_guard(asm, iseq, pc)
|
||||
end
|
||||
end
|
||||
|
||||
def compile_pc_guard(asm, iseq, pc)
|
||||
asm.comment('guard expected PC')
|
||||
asm.mov(:rax, pc)
|
||||
asm.cmp([CFP, C.rb_control_frame_t.offsetof(:pc)], :rax)
|
||||
|
||||
pc_match = asm.new_label('pc_match')
|
||||
asm.je(pc_match)
|
||||
|
||||
# We're not starting at the first PC, so we need to exit.
|
||||
asm.incr_counter(:leave_start_pc_non_zero)
|
||||
|
||||
asm.pop(SP)
|
||||
asm.pop(EC)
|
||||
asm.pop(CFP)
|
||||
|
||||
asm.mov(:rax, Qundef)
|
||||
asm.ret
|
||||
|
||||
# PC should match the expected insn_idx
|
||||
asm.write_label(pc_match)
|
||||
end
|
||||
|
||||
# @param asm [RubyVM::RJIT::Assembler]
|
||||
def compile_block(asm, jit:, pc: jit.iseq.body.iseq_encoded.to_i, ctx: Context.new)
|
||||
def compile_block(asm, jit:, pc:, ctx: Context.new)
|
||||
# Mark the block start address and prepare an exit code storage
|
||||
block = Block.new(iseq: jit.iseq, pc:, ctx: ctx.dup)
|
||||
jit.block = block
|
||||
|
|
|
@ -40,6 +40,7 @@ module RubyVM::RJIT
|
|||
print_counters(stats, prefix: 'send_', prompt: 'method call exit reasons')
|
||||
print_counters(stats, prefix: 'invokeblock_', prompt: 'invokeblock exit reasons')
|
||||
print_counters(stats, prefix: 'invokesuper_', prompt: 'invokesuper exit reasons')
|
||||
print_counters(stats, prefix: 'leave_', prompt: 'leave exit reasons')
|
||||
print_counters(stats, prefix: 'getblockpp_', prompt: 'getblockparamproxy exit reasons')
|
||||
print_counters(stats, prefix: 'getivar_', prompt: 'getinstancevariable exit reasons')
|
||||
print_counters(stats, prefix: 'setivar_', prompt: 'setinstancevariable exit reasons')
|
||||
|
|
3
rjit_c.h
3
rjit_c.h
|
@ -78,6 +78,7 @@ RJIT_RUNTIME_COUNTERS(
|
|||
send_iseq_kwargs_mismatch,
|
||||
send_iseq_splat_with_kw,
|
||||
send_iseq_splat_arity_error,
|
||||
send_iseq_has_rest_and_splat_not_equal,
|
||||
|
||||
send_cfunc_variadic,
|
||||
send_cfunc_too_many_args,
|
||||
|
@ -156,6 +157,8 @@ RJIT_RUNTIME_COUNTERS(
|
|||
getblockpp_not_gc_guarded,
|
||||
getblockpp_not_iseq_block,
|
||||
|
||||
leave_start_pc_non_zero,
|
||||
|
||||
compiled_block_count
|
||||
)
|
||||
#undef RJIT_RUNTIME_COUNTERS
|
||||
|
|
|
@ -1372,6 +1372,7 @@ module RubyVM::RJIT # :nodoc: all
|
|||
send_iseq_kwargs_mismatch: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_iseq_kwargs_mismatch)")],
|
||||
send_iseq_splat_with_kw: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_iseq_splat_with_kw)")],
|
||||
send_iseq_splat_arity_error: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_iseq_splat_arity_error)")],
|
||||
send_iseq_has_rest_and_splat_not_equal: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_iseq_has_rest_and_splat_not_equal)")],
|
||||
send_cfunc_variadic: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_cfunc_variadic)")],
|
||||
send_cfunc_too_many_args: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_cfunc_too_many_args)")],
|
||||
send_cfunc_ruby_array_varg: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_cfunc_ruby_array_varg)")],
|
||||
|
@ -1435,6 +1436,7 @@ module RubyVM::RJIT # :nodoc: all
|
|||
getblockpp_block_handler_none: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), getblockpp_block_handler_none)")],
|
||||
getblockpp_not_gc_guarded: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), getblockpp_not_gc_guarded)")],
|
||||
getblockpp_not_iseq_block: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), getblockpp_not_iseq_block)")],
|
||||
leave_start_pc_non_zero: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), leave_start_pc_non_zero)")],
|
||||
compiled_block_count: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), compiled_block_count)")],
|
||||
)
|
||||
end
|
||||
|
|
Загрузка…
Ссылка в новой задаче