@@ -1693,12 +1693,50 @@ gen_opt_empty_p(jitstate_t* jit, ctx_t* ctx)
16931693static codegen_status_t
16941694gen_opt_not (jitstate_t * jit , ctx_t * ctx )
16951695{
1696- // TODO: can we implement a fast path?
1697- // Most likely, almost every input to opt_not is true/false/nil?
1696+ // Defer compilation so we can specialize type of argument
1697+ if (!jit_at_current_insn (jit )) {
1698+ defer_compilation (jit -> block , jit -> insn_idx , ctx );
1699+ return YJIT_END_BLOCK ;
1700+ }
16981701
1699- // NOTE: we can't really delegate to OSWB because we currently
1700- // don't support calls to methods on true/false/nil
1701- return YJIT_CANT_COMPILE ;
1702+ uint8_t * side_exit = yjit_side_exit (jit , ctx );
1703+
1704+ VALUE comptime_val = jit_peek_at_stack (jit , ctx , 0 );
1705+
1706+ // For the true/false case
1707+ if (comptime_val == Qtrue || comptime_val == Qfalse ) {
1708+
1709+ // Get the operand from the stack
1710+ x86opnd_t arg = ctx_stack_pop (ctx , 1 );
1711+
1712+ uint32_t DONE = cb_new_label (cb , "DONE" );
1713+
1714+ // Qtrue => Qfalse
1715+ mov (cb , REG0 , imm_opnd (Qfalse ));
1716+ cmp (cb , arg , imm_opnd (Qtrue ));
1717+ je_label (cb , DONE );
1718+
1719+ // Qfalse => Qtrue
1720+ mov (cb , REG0 , imm_opnd (Qtrue ));
1721+ cmp (cb , arg , imm_opnd (Qfalse ));
1722+ je_label (cb , DONE );
1723+
1724+ // For any other values, we side-exit
1725+ // This never happens in railsbench
1726+ jmp_ptr (cb , side_exit );
1727+
1728+ cb_write_label (cb , DONE );
1729+ cb_link_labels (cb );
1730+
1731+ // Push the return value onto the stack
1732+ x86opnd_t stack_ret = ctx_stack_push (ctx , TYPE_IMM );
1733+ mov (cb , stack_ret , REG0 );
1734+
1735+ return YJIT_KEEP_COMPILING ;
1736+ }
1737+
1738+ // Delegate to send, call the method on the recv
1739+ return gen_opt_send_without_block (jit , ctx );
17021740}
17031741
17041742void
0 commit comments