88#include "internal/compile.h"
99#include "internal/class.h"
1010#include "internal/object.h"
11+ #include "internal/string.h"
1112#include "insns_info.inc"
1213#include "yjit.h"
1314#include "yjit_iface.h"
@@ -1317,6 +1318,89 @@ gen_defined(jitstate_t* jit, ctx_t* ctx)
13171318 return YJIT_KEEP_COMPILING ;
13181319}
13191320
1321+ static codegen_status_t
1322+ gen_checktype (jitstate_t * jit , ctx_t * ctx )
1323+ {
1324+ // TODO: could we specialize on the type we detect
1325+ uint8_t * side_exit = yjit_side_exit (jit , ctx );
1326+
1327+ enum ruby_value_type type_val = (enum ruby_value_type )jit_get_arg (jit , 0 );
1328+ // Only three types are emitted by compile.c
1329+ if (type_val == T_STRING || type_val == T_ARRAY || type_val == T_HASH ) {
1330+ val_type_t val_type = ctx_get_opnd_type (ctx , OPND_STACK (0 ));
1331+ x86opnd_t val = ctx_stack_pop (ctx , 1 );
1332+
1333+ x86opnd_t stack_ret ;
1334+
1335+ // Check if we know from type information
1336+ if ((type_val == T_STRING && val_type .type == ETYPE_STRING ) ||
1337+ (type_val == T_ARRAY && val_type .type == ETYPE_ARRAY ) ||
1338+ (type_val == T_HASH && val_type .type == ETYPE_HASH )) {
1339+ // guaranteed type match
1340+ stack_ret = ctx_stack_push (ctx , TYPE_TRUE );
1341+ mov (cb , stack_ret , imm_opnd (Qtrue ));
1342+ return YJIT_KEEP_COMPILING ;
1343+ } else if (val_type .is_imm || val_type .type != ETYPE_UNKNOWN ) {
1344+ // guaranteed not to match T_STRING/T_ARRAY/T_HASH
1345+ stack_ret = ctx_stack_push (ctx , TYPE_FALSE );
1346+ mov (cb , stack_ret , imm_opnd (Qfalse ));
1347+ return YJIT_KEEP_COMPILING ;
1348+ }
1349+
1350+ mov (cb , REG0 , val );
1351+
1352+ if (!val_type .is_heap ) {
1353+ // if (SPECIAL_CONST_P(val)) {
1354+ // Bail if receiver is not a heap object
1355+ test (cb , REG0 , imm_opnd (RUBY_IMMEDIATE_MASK ));
1356+ jnz_ptr (cb , side_exit );
1357+ cmp (cb , REG0 , imm_opnd (Qfalse ));
1358+ je_ptr (cb , side_exit );
1359+ cmp (cb , REG0 , imm_opnd (Qnil ));
1360+ je_ptr (cb , side_exit );
1361+ }
1362+
1363+ // Check type on object
1364+ mov (cb , REG0 , mem_opnd (64 , REG0 , offsetof(struct RBasic , flags )));
1365+ and (cb , REG0 , imm_opnd (RUBY_T_MASK ));
1366+ cmp (cb , REG0 , imm_opnd (type_val ));
1367+ mov (cb , REG1 , imm_opnd (Qfalse ));
1368+ cmovne (cb , REG0 , REG1 );
1369+
1370+ stack_ret = ctx_stack_push (ctx , TYPE_IMM );
1371+ mov (cb , stack_ret , REG0 );
1372+
1373+ return YJIT_KEEP_COMPILING ;
1374+ } else {
1375+ return YJIT_CANT_COMPILE ;
1376+ }
1377+ }
1378+
1379+ static codegen_status_t
1380+ gen_concatstrings (jitstate_t * jit , ctx_t * ctx )
1381+ {
1382+ rb_num_t n = (rb_num_t )jit_get_arg (jit , 0 );
1383+
1384+ // Save the PC and SP because we are allocating
1385+ jit_save_pc (jit , REG0 );
1386+ jit_save_sp (jit , ctx );
1387+
1388+ x86opnd_t values_ptr = ctx_sp_opnd (ctx , - (sizeof (VALUE ) * (uint32_t )n ));
1389+
1390+ // call rb_str_concat_literals(long n, const VALUE *strings);
1391+ yjit_save_regs (cb );
1392+ mov (cb , C_ARG_REGS [0 ], imm_opnd (n ));
1393+ lea (cb , C_ARG_REGS [1 ], values_ptr );
1394+ call_ptr (cb , REG0 , (void * )rb_str_concat_literals );
1395+ yjit_load_regs (cb );
1396+
1397+ ctx_stack_pop (ctx , n );
1398+ x86opnd_t stack_ret = ctx_stack_push (ctx , TYPE_STRING );
1399+ mov (cb , stack_ret , RAX );
1400+
1401+ return YJIT_KEEP_COMPILING ;
1402+ }
1403+
13201404static void
13211405guard_two_fixnums (ctx_t * ctx , uint8_t * side_exit )
13221406{
@@ -2902,6 +2986,7 @@ yjit_init_codegen(void)
29022986 yjit_reg_op (BIN (adjuststack ), gen_adjuststack );
29032987 yjit_reg_op (BIN (newarray ), gen_newarray );
29042988 yjit_reg_op (BIN (newhash ), gen_newhash );
2989+ yjit_reg_op (BIN (concatstrings ), gen_concatstrings );
29052990 yjit_reg_op (BIN (putnil ), gen_putnil );
29062991 yjit_reg_op (BIN (putobject ), gen_putobject );
29072992 yjit_reg_op (BIN (putobject_INT2FIX_0_ ), gen_putobject_int2fix );
@@ -2913,6 +2998,7 @@ yjit_init_codegen(void)
29132998 yjit_reg_op (BIN (getinstancevariable ), gen_getinstancevariable );
29142999 yjit_reg_op (BIN (setinstancevariable ), gen_setinstancevariable );
29153000 yjit_reg_op (BIN (defined ), gen_defined );
3001+ yjit_reg_op (BIN (checktype ), gen_checktype );
29163002 yjit_reg_op (BIN (opt_lt ), gen_opt_lt );
29173003 yjit_reg_op (BIN (opt_le ), gen_opt_le );
29183004 yjit_reg_op (BIN (opt_ge ), gen_opt_ge );
0 commit comments