RJIT: Implement throw insn
This commit is contained in:
parent
39cd74d2a0
commit
45a17013aa
@ -18,7 +18,7 @@ module RubyVM::RJIT
|
|||||||
asm.incr_counter(:rjit_insns_count)
|
asm.incr_counter(:rjit_insns_count)
|
||||||
asm.comment("Insn: #{insn.name}")
|
asm.comment("Insn: #{insn.name}")
|
||||||
|
|
||||||
# 74/102
|
# 75/102
|
||||||
case insn.name
|
case insn.name
|
||||||
when :nop then nop(jit, ctx, asm)
|
when :nop then nop(jit, ctx, asm)
|
||||||
when :getlocal then getlocal(jit, ctx, asm)
|
when :getlocal then getlocal(jit, ctx, asm)
|
||||||
@ -82,7 +82,7 @@ module RubyVM::RJIT
|
|||||||
when :invokesuper then invokesuper(jit, ctx, asm)
|
when :invokesuper then invokesuper(jit, ctx, asm)
|
||||||
when :invokeblock then invokeblock(jit, ctx, asm)
|
when :invokeblock then invokeblock(jit, ctx, asm)
|
||||||
when :leave then leave(jit, ctx, asm)
|
when :leave then leave(jit, ctx, asm)
|
||||||
# throw
|
when :throw then throw(jit, ctx, asm)
|
||||||
when :jump then jump(jit, ctx, asm)
|
when :jump then jump(jit, ctx, asm)
|
||||||
when :branchif then branchif(jit, ctx, asm)
|
when :branchif then branchif(jit, ctx, asm)
|
||||||
when :branchunless then branchunless(jit, ctx, asm)
|
when :branchunless then branchunless(jit, ctx, asm)
|
||||||
@ -1308,7 +1308,37 @@ module RubyVM::RJIT
|
|||||||
EndBlock
|
EndBlock
|
||||||
end
|
end
|
||||||
|
|
||||||
# throw
|
# @param jit [RubyVM::RJIT::JITState]
|
||||||
|
# @param ctx [RubyVM::RJIT::Context]
|
||||||
|
# @param asm [RubyVM::RJIT::Assembler]
|
||||||
|
def throw(jit, ctx, asm)
|
||||||
|
throw_state = jit.operand(0)
|
||||||
|
asm.mov(:rcx, ctx.stack_pop(1)) # throwobj
|
||||||
|
|
||||||
|
# THROW_DATA_NEW allocates. Save SP for GC and PC for allocation tracing as
|
||||||
|
# well as handling the catch table. However, not using jit_prepare_routine_call
|
||||||
|
# since we don't need a patch point for this implementation.
|
||||||
|
jit_save_pc(jit, asm) # clobbers rax
|
||||||
|
jit_save_sp(ctx, asm)
|
||||||
|
|
||||||
|
# rb_vm_throw verifies it's a valid throw, sets ec->tag->state, and returns throw
|
||||||
|
# data, which is throwobj or a vm_throw_data wrapping it. When ec->tag->state is
|
||||||
|
# set, JIT code callers will handle the throw with vm_exec_handle_exception.
|
||||||
|
asm.mov(C_ARGS[0], EC)
|
||||||
|
asm.mov(C_ARGS[1], CFP)
|
||||||
|
asm.mov(C_ARGS[2], throw_state)
|
||||||
|
# asm.mov(C_ARGS[3], :rcx) # same reg
|
||||||
|
asm.call(C.rb_vm_throw)
|
||||||
|
|
||||||
|
asm.comment('exit from throw')
|
||||||
|
asm.pop(SP)
|
||||||
|
asm.pop(EC)
|
||||||
|
asm.pop(CFP)
|
||||||
|
|
||||||
|
# return C_RET as C_RET
|
||||||
|
asm.ret
|
||||||
|
EndBlock
|
||||||
|
end
|
||||||
|
|
||||||
# @param jit [RubyVM::RJIT::JITState]
|
# @param jit [RubyVM::RJIT::JITState]
|
||||||
# @param ctx [RubyVM::RJIT::Context]
|
# @param ctx [RubyVM::RJIT::Context]
|
||||||
@ -2810,10 +2840,10 @@ module RubyVM::RJIT
|
|||||||
def jit_prepare_routine_call(jit, ctx, asm)
|
def jit_prepare_routine_call(jit, ctx, asm)
|
||||||
jit.record_boundary_patch_point = true
|
jit.record_boundary_patch_point = true
|
||||||
jit_save_pc(jit, asm)
|
jit_save_pc(jit, asm)
|
||||||
jit_save_sp(jit, ctx, asm)
|
jit_save_sp(ctx, asm)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Note: This clobbers :rax
|
# NOTE: This clobbers :rax
|
||||||
# @param jit [RubyVM::RJIT::JITState]
|
# @param jit [RubyVM::RJIT::JITState]
|
||||||
# @param asm [RubyVM::RJIT::Assembler]
|
# @param asm [RubyVM::RJIT::Assembler]
|
||||||
def jit_save_pc(jit, asm, comment: 'save PC to CFP')
|
def jit_save_pc(jit, asm, comment: 'save PC to CFP')
|
||||||
@ -2823,10 +2853,9 @@ module RubyVM::RJIT
|
|||||||
asm.mov([CFP, C.rb_control_frame_t.offsetof(:pc)], :rax)
|
asm.mov([CFP, C.rb_control_frame_t.offsetof(:pc)], :rax)
|
||||||
end
|
end
|
||||||
|
|
||||||
# @param jit [RubyVM::RJIT::JITState]
|
|
||||||
# @param ctx [RubyVM::RJIT::Context]
|
# @param ctx [RubyVM::RJIT::Context]
|
||||||
# @param asm [RubyVM::RJIT::Assembler]
|
# @param asm [RubyVM::RJIT::Assembler]
|
||||||
def jit_save_sp(jit, ctx, asm)
|
def jit_save_sp(ctx, asm)
|
||||||
if ctx.sp_offset != 0
|
if ctx.sp_offset != 0
|
||||||
asm.comment('save SP to CFP')
|
asm.comment('save SP to CFP')
|
||||||
asm.lea(SP, ctx.sp_opnd)
|
asm.lea(SP, ctx.sp_opnd)
|
||||||
|
1
rjit_c.c
1
rjit_c.c
@ -494,6 +494,7 @@ extern bool rb_vm_defined(rb_execution_context_t *ec, rb_control_frame_t *reg_cf
|
|||||||
extern bool rb_vm_ic_hit_p(IC ic, const VALUE *reg_ep);
|
extern bool rb_vm_ic_hit_p(IC ic, const VALUE *reg_ep);
|
||||||
extern rb_event_flag_t rb_rjit_global_events;
|
extern rb_event_flag_t rb_rjit_global_events;
|
||||||
extern void rb_vm_setinstancevariable(const rb_iseq_t *iseq, VALUE obj, ID id, VALUE val, IVC ic);
|
extern void rb_vm_setinstancevariable(const rb_iseq_t *iseq, VALUE obj, ID id, VALUE val, IVC ic);
|
||||||
|
extern VALUE rb_vm_throw(const rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, rb_num_t throw_state, VALUE throwobj);
|
||||||
|
|
||||||
#include "rjit_c.rbinc"
|
#include "rjit_c.rbinc"
|
||||||
|
|
||||||
|
@ -580,6 +580,10 @@ module RubyVM::RJIT # :nodoc: all
|
|||||||
Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_vm_splat_array) }
|
Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_vm_splat_array) }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def C.rb_vm_throw
|
||||||
|
Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_vm_throw) }
|
||||||
|
end
|
||||||
|
|
||||||
def C.rjit_full_cfunc_return
|
def C.rjit_full_cfunc_return
|
||||||
Primitive.cexpr! %q{ SIZET2NUM((size_t)rjit_full_cfunc_return) }
|
Primitive.cexpr! %q{ SIZET2NUM((size_t)rjit_full_cfunc_return) }
|
||||||
end
|
end
|
||||||
|
@ -515,6 +515,7 @@ generator = BindingGenerator.new(
|
|||||||
rjit_str_neq_internal
|
rjit_str_neq_internal
|
||||||
rjit_record_exit_stack
|
rjit_record_exit_stack
|
||||||
rb_ivar_defined
|
rb_ivar_defined
|
||||||
|
rb_vm_throw
|
||||||
],
|
],
|
||||||
types: %w[
|
types: %w[
|
||||||
CALL_DATA
|
CALL_DATA
|
||||||
|
Loading…
x
Reference in New Issue
Block a user