diff options
author | John Hawthorn <[email protected]> | 2021-08-26 11:45:05 -0700 |
---|---|---|
committer | Alan Wu <[email protected]> | 2021-10-20 18:19:39 -0400 |
commit | 812597676ba2b1e3c41c50e9da624441e0c40a6b (patch) | |
tree | 42faa784fca02f8efab59803c89cc3c5847efc0e | |
parent | 54db64f7a59f1f14b280a80491336a128f792b42 (diff) |
Avoid immediate side exits in checktype
Previously checktype only supported heap objects, however it's not
uncommon to receive an immediate, for example when string interpolating
a Symbol or Integer.
-rw-r--r-- | test/ruby/test_yjit.rb | 10 | ||||
-rw-r--r-- | yjit_codegen.c | 22 |
2 files changed, 21 insertions, 11 deletions
diff --git a/test/ruby/test_yjit.rb b/test/ruby/test_yjit.rb index 1f5f99f9a8..04502f925c 100644 --- a/test/ruby/test_yjit.rb +++ b/test/ruby/test_yjit.rb @@ -152,6 +152,16 @@ class TestYJIT < Test::Unit::TestCase RUBY end + def test_string_interpolation_cast + assert_compiles(<<~'RUBY', insns: %i[checktype concatstrings tostring], result: "123") + def make_str(foo, bar) + "#{foo}#{bar}" + end + + make_str(1, 23) + RUBY + end + def test_fib_recursion assert_compiles(<<~'RUBY', insns: %i[opt_le opt_minus opt_plus opt_send_without_block], result: 34) def fib(n) diff --git a/yjit_codegen.c b/yjit_codegen.c index db0694523e..0e2bbf2fa3 100644 --- a/yjit_codegen.c +++ b/yjit_codegen.c @@ -1758,9 +1758,6 @@ gen_defined(jitstate_t* jit, ctx_t* ctx) static codegen_status_t gen_checktype(jitstate_t* jit, ctx_t* ctx) { - // TODO: could we specialize on the type we detect - uint8_t* side_exit = yjit_side_exit(jit, ctx); - enum ruby_value_type type_val = (enum ruby_value_type)jit_get_arg(jit, 0); // Only three types are emitted by compile.c if (type_val == T_STRING || type_val == T_ARRAY || type_val == T_HASH) { @@ -1785,16 +1782,17 @@ gen_checktype(jitstate_t* jit, ctx_t* ctx) } mov(cb, REG0, val); + mov(cb, REG1, imm_opnd(Qfalse)); + + uint32_t ret = cb_new_label(cb, "ret"); if (!val_type.is_heap) { // if (SPECIAL_CONST_P(val)) { - // Bail if receiver is not a heap object + // Return Qfalse via REG1 if not on heap test(cb, REG0, imm_opnd(RUBY_IMMEDIATE_MASK)); - jnz_ptr(cb, side_exit); - cmp(cb, REG0, imm_opnd(Qfalse)); - je_ptr(cb, side_exit); + jnz_label(cb, ret); cmp(cb, REG0, imm_opnd(Qnil)); - je_ptr(cb, side_exit); + jbe_label(cb, ret); } // Check type on object @@ -1802,11 +1800,13 @@ gen_checktype(jitstate_t* jit, ctx_t* ctx) and(cb, REG0, imm_opnd(RUBY_T_MASK)); cmp(cb, REG0, imm_opnd(type_val)); mov(cb, REG0, imm_opnd(Qtrue)); - mov(cb, REG1, imm_opnd(Qfalse)); - cmovne(cb, REG0, REG1); + // REG1 contains Qfalse from above + cmove(cb, REG1, REG0); + cb_write_label(cb, ret); stack_ret = ctx_stack_push(ctx, TYPE_IMM); - mov(cb, stack_ret, REG0); + mov(cb, stack_ret, REG1); + cb_link_labels(cb); return YJIT_KEEP_COMPILING; } else { |