ruby-changes:68978
From: Maxime <ko1@a...>
Date: Thu, 21 Oct 2021 08:19:33 +0900 (JST)
Subject: [ruby-changes:68978] 54fe43b45c (master): Implement defined bytecode (#39)
https://git.ruby-lang.org/ruby.git/commit/?id=54fe43b45c From 54fe43b45ce65f0e2cde4d4e950303893a721ebd Mon Sep 17 00:00:00 2001 From: Maxime Chevalier-Boisvert <maximechevalierb@g...> Date: Tue, 11 May 2021 16:06:07 -0400 Subject: Implement defined bytecode (#39) --- vm_insnhelper.c | 6 ++++++ yjit_codegen.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+) diff --git a/vm_insnhelper.c b/vm_insnhelper.c index d41bfeb66c..c9c4744b23 100644 --- a/vm_insnhelper.c +++ b/vm_insnhelper.c @@ -4188,6 +4188,12 @@ vm_defined(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, rb_num_t op_ https://github.com/ruby/ruby/blob/trunk/vm_insnhelper.c#L4188 return false; } +bool +rb_vm_defined(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, rb_num_t op_type, VALUE obj, VALUE v) +{ + return vm_defined(ec, reg_cfp, op_type, obj, v); +} + static const VALUE * vm_get_ep(const VALUE *const reg_ep, rb_num_t lv) { diff --git a/yjit_codegen.c b/yjit_codegen.c index 00a69942df..3e75bbc788 100644 --- a/yjit_codegen.c +++ b/yjit_codegen.c @@ -1174,6 +1174,51 @@ gen_setinstancevariable(jitstate_t* jit, ctx_t* ctx) https://github.com/ruby/ruby/blob/trunk/yjit_codegen.c#L1174 */ } +bool rb_vm_defined(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, rb_num_t op_type, VALUE obj, VALUE v); + +static codegen_status_t +gen_defined(jitstate_t* jit, ctx_t* ctx) +{ + rb_num_t op_type = (rb_num_t)jit_get_arg(jit, 0); + VALUE obj = (VALUE)jit_get_arg(jit, 1); + VALUE pushval = (VALUE)jit_get_arg(jit, 2); + + // Save the PC and SP because the callee may allocate + // Note that this modifies REG_SP, which is why we do it first + jit_save_pc(jit, REG0); + jit_save_sp(jit, ctx); + + // Get the operands from the stack + x86opnd_t v_opnd = ctx_stack_pop(ctx, 1); + + // Call vm_defined(ec, reg_cfp, op_type, obj, v) + // Out of order because we're going to corrupt REG_SP and REG_CFP + yjit_save_regs(cb); + mov(cb, R9, REG_CFP); + mov(cb, C_ARG_REGS[0], REG_EC); + mov(cb, C_ARG_REGS[1], R9); + mov(cb, C_ARG_REGS[4], v_opnd); // depends on REG_SP + mov(cb, C_ARG_REGS[2], imm_opnd(op_type)); // clobers REG_SP + jit_mov_gc_ptr(jit, cb, C_ARG_REGS[3], (VALUE)obj); + call_ptr(cb, REG0, (void *)rb_vm_defined); + yjit_load_regs(cb); + + // if (vm_defined(ec, GET_CFP(), op_type, obj, v)) { + // val = pushval; + // } + jit_mov_gc_ptr(jit, cb, REG1, (VALUE)pushval); + cmp(cb, AL, imm_opnd(0)); + mov(cb, RAX, imm_opnd(Qnil)); + cmovnz(cb, RAX, REG1); + + // Push the return value onto the stack + val_type_t out_type = SPECIAL_CONST_P(pushval)? TYPE_IMM:TYPE_UNKNOWN; + x86opnd_t stack_ret = ctx_stack_push(ctx, out_type); + mov(cb, stack_ret, RAX); + + return YJIT_KEEP_COMPILING; +} + static void guard_two_fixnums(ctx_t* ctx, uint8_t* side_exit) { @@ -2673,6 +2718,7 @@ yjit_init_codegen(void) https://github.com/ruby/ruby/blob/trunk/yjit_codegen.c#L2718 yjit_reg_op(BIN(setlocal_WC_0), gen_setlocal_wc0); yjit_reg_op(BIN(getinstancevariable), gen_getinstancevariable); yjit_reg_op(BIN(setinstancevariable), gen_setinstancevariable); + yjit_reg_op(BIN(defined), gen_defined); yjit_reg_op(BIN(opt_lt), gen_opt_lt); yjit_reg_op(BIN(opt_le), gen_opt_le); yjit_reg_op(BIN(opt_ge), gen_opt_ge); -- cgit v1.2.1 -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/