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