@@ -1172,6 +1172,51 @@ gen_setinstancevariable(jitstate_t* jit, ctx_t* ctx)
11721172 */
11731173}
11741174
1175+ bool rb_vm_defined (rb_execution_context_t * ec , rb_control_frame_t * reg_cfp , rb_num_t op_type , VALUE obj , VALUE v );
1176+
1177+ static codegen_status_t
1178+ gen_defined (jitstate_t * jit , ctx_t * ctx )
1179+ {
1180+ rb_num_t op_type = (rb_num_t )jit_get_arg (jit , 0 );
1181+ VALUE obj = (VALUE )jit_get_arg (jit , 1 );
1182+ VALUE pushval = (VALUE )jit_get_arg (jit , 2 );
1183+
1184+ // Save the PC and SP because the callee may allocate
1185+ // Note that this modifies REG_SP, which is why we do it first
1186+ jit_save_pc (jit , REG0 );
1187+ jit_save_sp (jit , ctx );
1188+
1189+ // Get the operands from the stack
1190+ x86opnd_t v_opnd = ctx_stack_pop (ctx , 1 );
1191+
1192+ // Call vm_defined(ec, reg_cfp, op_type, obj, v)
1193+ // Out of order because we're going to corrupt REG_SP and REG_CFP
1194+ yjit_save_regs (cb );
1195+ mov (cb , R9 , REG_CFP );
1196+ mov (cb , C_ARG_REGS [0 ], REG_EC );
1197+ mov (cb , C_ARG_REGS [1 ], R9 );
1198+ mov (cb , C_ARG_REGS [4 ], v_opnd ); // depends on REG_SP
1199+ mov (cb , C_ARG_REGS [2 ], imm_opnd (op_type )); // clobers REG_SP
1200+ jit_mov_gc_ptr (jit , cb , C_ARG_REGS [3 ], (VALUE )obj );
1201+ call_ptr (cb , REG0 , (void * )rb_vm_defined );
1202+ yjit_load_regs (cb );
1203+
1204+ // if (vm_defined(ec, GET_CFP(), op_type, obj, v)) {
1205+ // val = pushval;
1206+ // }
1207+ jit_mov_gc_ptr (jit , cb , REG1 , (VALUE )pushval );
1208+ cmp (cb , AL , imm_opnd (0 ));
1209+ mov (cb , RAX , imm_opnd (Qnil ));
1210+ cmovnz (cb , RAX , REG1 );
1211+
1212+ // Push the return value onto the stack
1213+ val_type_t out_type = SPECIAL_CONST_P (pushval )? TYPE_IMM :TYPE_UNKNOWN ;
1214+ x86opnd_t stack_ret = ctx_stack_push (ctx , out_type );
1215+ mov (cb , stack_ret , RAX );
1216+
1217+ return YJIT_KEEP_COMPILING ;
1218+ }
1219+
11751220static void
11761221guard_two_fixnums (ctx_t * ctx , uint8_t * side_exit )
11771222{
@@ -2672,6 +2717,7 @@ yjit_init_codegen(void)
26722717 yjit_reg_op (BIN (setlocal_WC_0 ), gen_setlocal_wc0 );
26732718 yjit_reg_op (BIN (getinstancevariable ), gen_getinstancevariable );
26742719 yjit_reg_op (BIN (setinstancevariable ), gen_setinstancevariable );
2720+ yjit_reg_op (BIN (defined ), gen_defined );
26752721 yjit_reg_op (BIN (opt_lt ), gen_opt_lt );
26762722 yjit_reg_op (BIN (opt_le ), gen_opt_le );
26772723 yjit_reg_op (BIN (opt_ge ), gen_opt_ge );
0 commit comments