8000 Implement opt_aref · github/ruby@09f3bec · GitHub
[go: up one dir, main page]

Skip to content

Commit 09f3bec

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 09f3bec

File tree

1 file changed

+74
-0
lines changed

1 file changed

+74
-0
lines changed

ujit_codegen.c

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -766,6 +766,79 @@ 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+
// Bail if the inline cache has been filled. Currently, certain types
783+
// (including arrays) don't use the inline cache, so if the inline cache
784+
// has an entry, then this must be used by some other type.
785+
if (cme) {
786+
return false;
787+
}
788+
789+
// Create a size-exit to fall back to the interpreter
790+
uint8_t* side_exit = ujit_side_exit(jit, ctx);
791+
792+
x86opnd_t recv = ctx_stack_opnd(ctx, argc);
793+
794+
mov(cb, REG0, recv);
795+
796+
// if (SPECIAL_CONST_P(recv)) {
797+
// Bail if it's not a heap object
798+
test(cb, REG0, imm_opnd(RUBY_IMMEDIATE_MASK));
799+
jnz_ptr(cb, side_exit);
800+
cmp(cb, REG0, imm_opnd(Qfalse));
801+
je_ptr(cb, side_exit);
802+
cmp(cb, REG0, imm_opnd(Qnil));
803+
je_ptr(cb, side_exit);
804+
805+
// Bail if recv is *not* an array
806+
x86opnd_t klass_opnd = mem_opnd(64, REG0, offsetof(struct RBasic, klass));
807+
mov(cb, REG0, klass_opnd);
808+
mov(cb, REG1, const_ptr_opnd((void *)rb_cArray));
809+
cmp(cb, REG0, REG1);
810+
jne_ptr(cb, side_exit);
811+
812+
// Bail if arg0 is *not* an FIXNUM
813+
x86opnd_t operand = ctx_stack_opnd(ctx, 0);
814+
mov(cb, REG1, operand);
815+
test(cb, REG1, imm_opnd(RUBY_FIXNUM_FLAG));
816+
jz_ptr(cb, side_exit);
817+
818+
// Save MicroJIT registers
819+
push(cb, REG_CFP);
820+
push(cb, REG_EC);
821+
push(cb, REG_SP);
822+
// Maintain 16-byte RSP alignment
823+
sub(cb, RSP, imm_opnd(8));
824+
825+
mov(cb, RDI, recv);
826+
sar(cb, REG1, imm_opnd(1)); // Convert fixnum to int
827+
mov(cb, RSI, REG1);
828+
call_ptr(cb, REG0, (void *)rb_ary_entry_internal);
829+
830+
// Restore registers
831+
add(cb, RSP, imm_opnd(8));
832+
pop(cb, REG_SP);
833+
pop(cb, REG_EC);
834+
pop(cb, REG_CFP);
835+
836+
x86opnd_t stack_ret = ctx_stack_push(ctx, T_NONE);
837+
mov(cb, stack_ret, RAX);
838+
839+
return true;
840+
}
841+
769842
void
770843
gen_branchif_branch(codeblock_t* cb, uint8_t* target0, uint8_t* target1, uint8_t shape)
771844
{
@@ -1398,4 +1471,5 @@ ujit_init_codegen(void)
13981471
ujit_reg_op(BIN(jump), gen_jump, true);
13991472
ujit_reg_op(BIN(opt_send_without_block), gen_opt_send_without_block, true);
14001473
ujit_reg_op(BIN(leave), gen_leave, true);
1474+
ujit_reg_op(BIN(opt_aref), gen_opt_aref, false);
14011475
}

0 commit comments

Comments
 (0)
0