Skip to content

Commit 0fc92a1

Browse files
committed
Implement opt_aref
This patch implements opt_aref, but only when the receiver is an array and when the parameter is a single fixnum. Any other types exit.
1 parent a73b9cd commit 0fc92a1

1 file changed

Lines changed: 71 additions & 0 deletions

File tree

ujit_codegen.c

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -766,6 +766,76 @@ gen_opt_plus(jitstate_t* jit, ctx_t* ctx)
766766
return true;
767767
}
768768

769+
static bool
770+
gen_opt_aref(jitstate_t* jit, ctx_t* ctx)
771+
{
772+
struct rb_call_data * cd = (struct rb_call_data *)jit_get_arg(jit, 0);
773+
int32_t argc = (int32_t)vm_ci_argc(cd->ci);
774+
775+
// Only JIT one arg calls like `ary[6]`
776+
if (argc != 1) {
777+
return false;
778+
}
779+
780+
const rb_callable_method_entry_t *cme = vm_cc_cme(cd->cc);
781+
782+
if (cme) {
783+
return false;
784+
}
785+
786+
// Create a size-exit to fall back to the interpreter
787+
uint8_t* side_exit = ujit_side_exit(jit, ctx);
788+
789+
x86opnd_t recv = ctx_stack_opnd(ctx, argc);
790+
791+
mov(cb, REG0, recv);
792+
793+
// if (SPECIAL_CONST_P(recv)) {
794+
// Bail if it's not a heap object
795+
test(cb, REG0, imm_opnd(RUBY_IMMEDIATE_MASK));
796+
jnz_ptr(cb, side_exit);
797+
cmp(cb, REG0, imm_opnd(Qfalse));
798+
je_ptr(cb, side_exit);
799+
cmp(cb, REG0, imm_opnd(Qnil));
800+
je_ptr(cb, side_exit);
801+
802+
// Bail if recv is *not* an array
803+
x86opnd_t klass_opnd = mem_opnd(64, REG0, offsetof(struct RBasic, klass));
804+
mov(cb, REG0, klass_opnd);
805+
mov(cb, REG1, const_ptr_opnd((void *)rb_cArray));
806+
cmp(cb, REG0, REG1);
807+
jne_ptr(cb, side_exit);
808+
809+
// Bail if arg0 is *not* an FIXNUM
810+
x86opnd_t operand = ctx_stack_opnd(ctx, 0);
811+
mov(cb, REG1, operand);
812+
test(cb, REG1, imm_opnd(RUBY_FIXNUM_FLAG));
813+
jz_ptr(cb, side_exit);
814+
815+
// Save MicroJIT registers
816+
push(cb, REG_CFP);
817+
push(cb, REG_EC);
818+
push(cb, REG_SP);
819+
// Maintain 16-byte RSP alignment
820+
sub(cb, RSP, imm_opnd(8));
821+
822+
mov(cb, RDI, recv);
823+
sar(cb, REG1, imm_opnd(1)); // Convert fixnum to int
824+
mov(cb, RSI, REG1);
825+
call_ptr(cb, REG0, (void *)rb_ary_entry_internal);
826+
827+
// Restore registers
828+
add(cb, RSP, imm_opnd(8));
829+
pop(cb, REG_SP);
830+
pop(cb, REG_EC);
831+
pop(cb, REG_CFP);
832+
833+
x86opnd_t stack_ret = ctx_stack_push(ctx, T_NONE);
834+
mov(cb, stack_ret, RAX);
835+
836+
return true;
837+
}
838+
769839
void
770840
gen_branchif_branch(codeblock_t* cb, uint8_t* target0, uint8_t* target1, uint8_t shape)
771841
{
@@ -1398,4 +1468,5 @@ ujit_init_codegen(void)
13981468
ujit_reg_op(BIN(jump), gen_jump, true);
13991469
ujit_reg_op(BIN(opt_send_without_block), gen_opt_send_without_block, true);
14001470
ujit_reg_op(BIN(leave), gen_leave, true);
1471+
ujit_reg_op(BIN(opt_aref), gen_opt_aref, false);
14011472
}

0 commit comments

Comments
 (0)