Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement opt_aref #34

Merged
merged 1 commit into from
Feb 4, 2021
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 74 additions & 0 deletions ujit_codegen.c
Original file line number Diff line number Diff line change
Expand Up @@ -766,6 +766,79 @@ gen_opt_plus(jitstate_t* jit, ctx_t* ctx)
return true;
}

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) {
tenderlove marked this conversation as resolved.
Show resolved Hide resolved
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_opnd(ctx, argc);

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));
tenderlove marked this conversation as resolved.
Show resolved Hide resolved
cmp(cb, REG0, REG1);
jne_ptr(cb, side_exit);

// Bail if arg0 is *not* an FIXNUM
x86opnd_t operand = ctx_stack_opnd(ctx, 0);
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;
}

void
gen_branchif_branch(codeblock_t* cb, uint8_t* target0, uint8_t* target1, uint8_t shape)
{
Expand Down Expand Up @@ -1398,4 +1471,5 @@ ujit_init_codegen(void)
ujit_reg_op(BIN(jump), gen_jump, true);
ujit_reg_op(BIN(opt_send_without_block), gen_opt_send_without_block, true);
ujit_reg_op(BIN(leave), gen_leave, true);
ujit_reg_op(BIN(opt_aref), gen_opt_aref, false);
}