Pop stack operands in opt_aref
This commit is contained in:
parent
a391684159
commit
0f53c216d2
@ -636,6 +636,78 @@ gen_opt_ge(jitstate_t* jit, ctx_t* ctx)
|
|||||||
return gen_fixnum_cmp(jit, ctx, cmovge);
|
return gen_fixnum_cmp(jit, ctx, cmovge);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
gen_opt_aref(jitstate_t* jit, ctx_t* ctx)
|
||||||
|
{
|
||||||
|
struct rb_call_data * cd = (struct rb_call_data *)jit_get_arg(jit, 0);
|
||||||
|
int32_t argc = (int32_t)vm_ci_argc(cd->ci);
|
||||||
|
|
||||||
|
// Only JIT one arg calls like `ary[6]`
|
||||||
|
if (argc != 1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const rb_callable_method_entry_t *cme = vm_cc_cme(cd->cc);
|
||||||
|
|
||||||
|
// Bail if the inline cache has been filled. Currently, certain types
|
||||||
|
// (including arrays) don't use the inline cache, so if the inline cache
|
||||||
|
// has an entry, then this must be used by some other type.
|
||||||
|
if (cme) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a size-exit to fall back to the interpreter
|
||||||
|
uint8_t* side_exit = ujit_side_exit(jit, ctx);
|
||||||
|
|
||||||
|
x86opnd_t recv = ctx_stack_pop(ctx, 1);
|
||||||
|
mov(cb, REG0, recv);
|
||||||
|
|
||||||
|
// if (SPECIAL_CONST_P(recv)) {
|
||||||
|
// Bail if it's not a heap object
|
||||||
|
test(cb, REG0, imm_opnd(RUBY_IMMEDIATE_MASK));
|
||||||
|
jnz_ptr(cb, side_exit);
|
||||||
|
cmp(cb, REG0, imm_opnd(Qfalse));
|
||||||
|
je_ptr(cb, side_exit);
|
||||||
|
cmp(cb, REG0, imm_opnd(Qnil));
|
||||||
|
je_ptr(cb, side_exit);
|
||||||
|
|
||||||
|
// Bail if recv is *not* an array
|
||||||
|
x86opnd_t klass_opnd = mem_opnd(64, REG0, offsetof(struct RBasic, klass));
|
||||||
|
mov(cb, REG0, klass_opnd);
|
||||||
|
mov(cb, REG1, const_ptr_opnd((void *)rb_cArray));
|
||||||
|
cmp(cb, REG0, REG1);
|
||||||
|
jne_ptr(cb, side_exit);
|
||||||
|
|
||||||
|
// Bail if arg0 is *not* an FIXNUM
|
||||||
|
x86opnd_t operand = ctx_stack_pop(ctx, 1);
|
||||||
|
mov(cb, REG1, operand);
|
||||||
|
test(cb, REG1, imm_opnd(RUBY_FIXNUM_FLAG));
|
||||||
|
jz_ptr(cb, side_exit);
|
||||||
|
|
||||||
|
// Save MicroJIT registers
|
||||||
|
push(cb, REG_CFP);
|
||||||
|
push(cb, REG_EC);
|
||||||
|
push(cb, REG_SP);
|
||||||
|
// Maintain 16-byte RSP alignment
|
||||||
|
sub(cb, RSP, imm_opnd(8));
|
||||||
|
|
||||||
|
mov(cb, RDI, recv);
|
||||||
|
sar(cb, REG1, imm_opnd(1)); // Convert fixnum to int
|
||||||
|
mov(cb, RSI, REG1);
|
||||||
|
call_ptr(cb, REG0, (void *)rb_ary_entry_internal);
|
||||||
|
|
||||||
|
// Restore registers
|
||||||
|
add(cb, RSP, imm_opnd(8));
|
||||||
|
pop(cb, REG_SP);
|
||||||
|
pop(cb, REG_EC);
|
||||||
|
pop(cb, REG_CFP);
|
||||||
|
|
||||||
|
x86opnd_t stack_ret = ctx_stack_push(ctx, T_NONE);
|
||||||
|
mov(cb, stack_ret, RAX);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
gen_opt_and(jitstate_t* jit, ctx_t* ctx)
|
gen_opt_and(jitstate_t* jit, ctx_t* ctx)
|
||||||
{
|
{
|
||||||
@ -1192,7 +1264,7 @@ gen_opt_swb_iseq(jitstate_t* jit, ctx_t* ctx, struct rb_call_data * cd, const rb
|
|||||||
lea(cb, REG0, ctx_sp_opnd(ctx, sizeof(VALUE) * (3 + num_locals)));
|
lea(cb, REG0, ctx_sp_opnd(ctx, sizeof(VALUE) * (3 + num_locals)));
|
||||||
|
|
||||||
// Initialize local variables to Qnil
|
// Initialize local variables to Qnil
|
||||||
for (int i=0; i < num_locals; i++) {
|
for (int i = 0; i < num_locals; i++) {
|
||||||
mov(cb, mem_opnd(64, REG0, sizeof(VALUE) * (i - num_locals - 3)), imm_opnd(Qnil));
|
mov(cb, mem_opnd(64, REG0, sizeof(VALUE) * (i - num_locals - 3)), imm_opnd(Qnil));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1390,6 +1462,7 @@ ujit_init_codegen(void)
|
|||||||
ujit_reg_op(BIN(opt_lt), gen_opt_lt, false);
|
ujit_reg_op(BIN(opt_lt), gen_opt_lt, false);
|
||||||
ujit_reg_op(BIN(opt_le), gen_opt_le, false);
|
ujit_reg_op(BIN(opt_le), gen_opt_le, false);
|
||||||
ujit_reg_op(BIN(opt_ge), gen_opt_ge, false);
|
ujit_reg_op(BIN(opt_ge), gen_opt_ge, false);
|
||||||
|
ujit_reg_op(BIN(opt_aref), gen_opt_aref, false);
|
||||||
ujit_reg_op(BIN(opt_and), gen_opt_and, false);
|
ujit_reg_op(BIN(opt_and), gen_opt_and, false);
|
||||||
ujit_reg_op(BIN(opt_minus), gen_opt_minus, false);
|
ujit_reg_op(BIN(opt_minus), gen_opt_minus, false);
|
||||||
ujit_reg_op(BIN(opt_plus), gen_opt_plus, false);
|
ujit_reg_op(BIN(opt_plus), gen_opt_plus, false);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user