@@ -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+
769839void
770840gen_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