RJIT: Implement getspecial insn

This commit is contained in:
Takashi Kokubun 2023-03-18 00:00:18 -07:00
Родитель 93e05aaa74
Коммит dc28ccbb6d
3 изменённых файлов: 98 добавлений и 3 удалений

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

@ -18,7 +18,7 @@ module RubyVM::RJIT
asm.incr_counter(:rjit_insns_count)
asm.comment("Insn: #{insn.name}")
# 76/102
# 77/102
case insn.name
when :nop then nop(jit, ctx, asm)
when :getlocal then getlocal(jit, ctx, asm)
@ -26,7 +26,7 @@ module RubyVM::RJIT
when :getblockparam then getblockparam(jit, ctx, asm)
# setblockparam
when :getblockparamproxy then getblockparamproxy(jit, ctx, asm)
# getspecial
when :getspecial then getspecial(jit, ctx, asm)
# setspecial
when :getinstancevariable then getinstancevariable(jit, ctx, asm)
when :setinstancevariable then setinstancevariable(jit, ctx, asm)
@ -301,7 +301,72 @@ module RubyVM::RJIT
EndBlock
end
# getspecial
# @param jit [RubyVM::RJIT::JITState]
# @param ctx [RubyVM::RJIT::Context]
# @param asm [RubyVM::RJIT::Assembler]
def getspecial(jit, ctx, asm)
# This takes two arguments, key and type
# key is only used when type == 0
# A non-zero type determines which type of backref to fetch
#rb_num_t key = jit.jit_get_arg(0);
rtype = jit.operand(1)
if rtype == 0
# not yet implemented
return CantCompile;
elsif rtype & 0x01 != 0
# Fetch a "special" backref based on a char encoded by shifting by 1
# Can raise if matchdata uninitialized
jit_prepare_routine_call(jit, ctx, asm)
# call rb_backref_get()
asm.comment('rb_backref_get')
asm.call(C.rb_backref_get)
asm.mov(C_ARGS[0], C_RET) # backref
case [rtype >> 1].pack('c')
in ?&
asm.comment("rb_reg_last_match")
asm.call(C.rb_reg_last_match)
in ?`
asm.comment("rb_reg_match_pre")
asm.call(C.rb_reg_match_pre)
in ?'
asm.comment("rb_reg_match_post")
asm.call(C.rb_reg_match_post)
in ?+
asm.comment("rb_reg_match_last")
asm.call(C.rb_reg_match_last)
end
stack_ret = ctx.stack_push
asm.mov(stack_ret, C_RET)
KeepCompiling
else
# Fetch the N-th match from the last backref based on type shifted by 1
# Can raise if matchdata uninitialized
jit_prepare_routine_call(jit, ctx, asm)
# call rb_backref_get()
asm.comment('rb_backref_get')
asm.call(C.rb_backref_get)
# rb_reg_nth_match((int)(type >> 1), backref);
asm.comment('rb_reg_nth_match')
asm.mov(C_ARGS[0], rtype >> 1)
asm.mov(C_ARGS[1], C_RET) # backref
asm.call(C.rb_reg_nth_match)
stack_ret = ctx.stack_push
asm.mov(stack_ret, C_RET)
KeepCompiling
end
end
# setspecial
# @param jit [RubyVM::RJIT::JITState]

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

@ -465,6 +465,10 @@ module RubyVM::RJIT # :nodoc: all
Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_ary_store) }
end
def C.rb_backref_get
Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_backref_get) }
end
def C.rb_ec_ary_new_from_values
Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_ec_ary_new_from_values) }
end
@ -537,6 +541,26 @@ module RubyVM::RJIT # :nodoc: all
Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_obj_is_kind_of) }
end
def C.rb_reg_last_match
Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_reg_last_match) }
end
def C.rb_reg_match_last
Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_reg_match_last) }
end
def C.rb_reg_match_post
Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_reg_match_post) }
end
def C.rb_reg_match_pre
Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_reg_match_pre) }
end
def C.rb_reg_nth_match
Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_reg_nth_match) }
end
def C.rb_str_concat_literals
Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_str_concat_literals) }
end

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

@ -518,6 +518,12 @@ generator = BindingGenerator.new(
rjit_record_exit_stack
rb_ivar_defined
rb_vm_throw
rb_backref_get
rb_reg_last_match
rb_reg_match_pre
rb_reg_match_post
rb_reg_match_last
rb_reg_nth_match
],
types: %w[
CALL_DATA