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