@@ -766,6 +766,79 @@ gen_opt_plus(jitstate_t* jit, ctx_t* ctx)
766
766
return true;
767
767
}
768
768
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
+
769
842
void
770
843
gen_branchif_branch (codeblock_t * cb , uint8_t * target0 , uint8_t * target1 , uint8_t shape )
771
844
{
@@ -1429,4 +1502,5 @@ ujit_init_codegen(void)
1429
1502
ujit_reg_op (BIN (jump ), gen_jump , true);
1430
1503
ujit_reg_op (BIN (opt_send_without_block ), gen_opt_send_without_block , true);
1431
1504
ujit_reg_op (BIN (leave ), gen_leave , true);
1505
+ ujit_reg_op (BIN (opt_aref ), gen_opt_aref , false);
1432
1506
}
0 commit comments