@@ -1693,12 +1693,50 @@ gen_opt_empty_p(jitstate_t* jit, ctx_t* ctx)
1693
1693
static codegen_status_t
1694
1694
gen_opt_not (jitstate_t * jit , ctx_t * ctx )
1695
1695
{
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
+ }
1698
1701
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 );
1702
1740
}
1703
1741
1704
1742
void
0 commit comments