This commit is contained in:
Takashi Kokubun 2023-03-03 21:29:20 -08:00
Родитель f81c7a6747
Коммит 7456b10c33
6 изменённых файлов: 109 добавлений и 3 удалений

Просмотреть файл

@ -24,14 +24,14 @@ module RubyVM::MJIT
asm.incr_counter(:mjit_insns_count)
asm.comment("Insn: #{insn.name}")
# 63/101
# 64/101
case insn.name
when :nop then nop(jit, ctx, asm)
when :getlocal then getlocal(jit, ctx, asm)
when :setlocal then setlocal(jit, ctx, asm)
# getblockparam
# setblockparam
# getblockparamproxy
when :getblockparamproxy then getblockparamproxy(jit, ctx, asm)
# getspecial
# setspecial
when :getinstancevariable then getinstancevariable(jit, ctx, asm)
@ -165,7 +165,77 @@ module RubyVM::MJIT
# getblockparam
# setblockparam
# getblockparamproxy
# @param jit [RubyVM::MJIT::JITState]
# @param ctx [RubyVM::MJIT::Context]
# @param asm [RubyVM::MJIT::Assembler]
def getblockparamproxy(jit, ctx, asm)
# To get block_handler
unless jit.at_current_insn?
defer_compilation(jit, ctx, asm)
return EndBlock
end
starting_context = ctx.dup # make a copy for use with jit_chain_guard
# A mirror of the interpreter code. Checking for the case
# where it's pushing rb_block_param_proxy.
side_exit = side_exit(jit, ctx)
# EP level
level = jit.operand(1)
# Peek at the block handler so we can check whether it's nil
comptime_handler = jit.peek_at_block_handler(level)
# When a block handler is present, it should always be a GC-guarded
# pointer (VM_BH_ISEQ_BLOCK_P)
if comptime_handler != 0 && comptime_handler & 0x3 != 0x1
asm.incr_counter(:getblockpp_not_gc_guarded)
return CantCompile
end
# Load environment pointer EP from CFP
ep_reg = :rax
jit_get_ep(asm, level, reg: ep_reg)
# Bail when VM_ENV_FLAGS(ep, VM_FRAME_FLAG_MODIFIED_BLOCK_PARAM) is non zero
asm.test([ep_reg, C.VALUE.size * C.VM_ENV_DATA_INDEX_FLAGS], C.VM_FRAME_FLAG_MODIFIED_BLOCK_PARAM)
asm.jnz(counted_exit(side_exit, :getblockpp_block_param_modified))
# Load the block handler for the current frame
# note, VM_ASSERT(VM_ENV_LOCAL_P(ep))
block_handler = :rax
asm.mov(block_handler, [ep_reg, C.VALUE.size * C.VM_ENV_DATA_INDEX_SPECVAL])
# Specialize compilation for the case where no block handler is present
if comptime_handler == 0
# Bail if there is a block handler
asm.cmp(block_handler, 0)
jit_chain_guard(:jnz, jit, starting_context, asm, counted_exit(side_exit, :getblockpp_block_handler_none))
putobject(jit, ctx, asm, val: Qnil)
else
# Block handler is a tagged pointer. Look at the tag. 0x03 is from VM_BH_ISEQ_BLOCK_P().
asm.and(block_handler, 0x3)
# Bail unless VM_BH_ISEQ_BLOCK_P(bh). This also checks for null.
asm.cmp(block_handler, 0x1)
jit_chain_guard(:jnz, jit, starting_context, asm, counted_exit(side_exit, :getblockpp_not_iseq_block))
# Push rb_block_param_proxy. It's a root, so no need to use jit_mov_gc_ptr.
top = ctx.stack_push
asm.mov(:rax, C.rb_block_param_proxy)
asm.mov(top, :rax)
end
jump_to_next_insn(jit, ctx, asm)
EndBlock
end
# getspecial
# setspecial

Просмотреть файл

@ -37,5 +37,21 @@ module RubyVM::MJIT
def peek_at_self
C.to_ruby(cfp.self)
end
def peek_at_block_handler(level)
ep = ep_at_level(cfp, level:)
ep[C.VM_ENV_DATA_INDEX_SPECVAL]
end
private
def ep_at_level(cfp, level:)
ep = cfp.ep
level.times do
# VM_ENV_PREV_EP
ep = C.VALUE.new(ep[C.VM_ENV_DATA_INDEX_SPECVAL] & ~0x03)
end
ep
end
end
end

Просмотреть файл

@ -36,6 +36,7 @@ module RubyVM::MJIT
print_counters(stats, prefix: 'send_', prompt: 'method call exit reasons')
print_counters(stats, prefix: 'invokesuper_', prompt: 'invokesuper 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')
print_counters(stats, prefix: 'optaref_', prompt: 'opt_aref exit reasons')

Просмотреть файл

@ -190,6 +190,11 @@ MJIT_RUNTIME_COUNTERS(
expandarray_not_array,
expandarray_rhs_too_small,
getblockpp_block_param_modified,
getblockpp_block_handler_none,
getblockpp_not_gc_guarded,
getblockpp_not_iseq_block,
compiled_block_count
)
#undef MJIT_RUNTIME_COUNTERS

Просмотреть файл

@ -702,6 +702,10 @@ module RubyVM::MJIT # :nodoc: all
Primitive.cexpr! %q{ UINT2NUM(VM_FRAME_FLAG_CFRAME_KW) }
end
def C.VM_FRAME_FLAG_MODIFIED_BLOCK_PARAM
Primitive.cexpr! %q{ UINT2NUM(VM_FRAME_FLAG_MODIFIED_BLOCK_PARAM) }
end
def C.VM_FRAME_MAGIC_CFUNC
Primitive.cexpr! %q{ UINT2NUM(VM_FRAME_MAGIC_CFUNC) }
end
@ -826,6 +830,10 @@ module RubyVM::MJIT # :nodoc: all
Primitive.cexpr! %q{ ULONG2NUM(SHAPE_MASK) }
end
def C.rb_block_param_proxy
Primitive.cexpr! %q{ PTR2NUM(rb_block_param_proxy) }
end
def C.rb_cFalseClass
Primitive.cexpr! %q{ PTR2NUM(rb_cFalseClass) }
end
@ -1408,6 +1416,10 @@ module RubyVM::MJIT # :nodoc: all
expandarray_postarg: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_mjit_runtime_counters *)NULL)), expandarray_postarg)")],
expandarray_not_array: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_mjit_runtime_counters *)NULL)), expandarray_not_array)")],
expandarray_rhs_too_small: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_mjit_runtime_counters *)NULL)), expandarray_rhs_too_small)")],
getblockpp_block_param_modified: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_mjit_runtime_counters *)NULL)), getblockpp_block_param_modified)")],
getblockpp_block_handler_none: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_mjit_runtime_counters *)NULL)), getblockpp_block_handler_none)")],
getblockpp_not_gc_guarded: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_mjit_runtime_counters *)NULL)), getblockpp_not_gc_guarded)")],
getblockpp_not_iseq_block: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_mjit_runtime_counters *)NULL)), getblockpp_not_iseq_block)")],
compiled_block_count: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_mjit_runtime_counters *)NULL)), compiled_block_count)")],
)
end

Просмотреть файл

@ -408,6 +408,7 @@ generator = BindingGenerator.new(
VM_FRAME_MAGIC_CFUNC
VM_FRAME_FLAG_CFRAME
VM_FRAME_FLAG_CFRAME_KW
VM_FRAME_FLAG_MODIFIED_BLOCK_PARAM
VM_METHOD_TYPE_ISEQ
VM_METHOD_TYPE_NOTIMPLEMENTED
VM_METHOD_TYPE_CFUNC
@ -447,6 +448,7 @@ generator = BindingGenerator.new(
rb_cNilClass
rb_cSymbol
rb_cTrueClass
rb_block_param_proxy
],
},
types: %w[