summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Hawthorn <[email protected]>2021-08-26 11:45:05 -0700
committerAlan Wu <[email protected]>2021-10-20 18:19:39 -0400
commit812597676ba2b1e3c41c50e9da624441e0c40a6b (patch)
tree42faa784fca02f8efab59803c89cc3c5847efc0e
parent54db64f7a59f1f14b280a80491336a128f792b42 (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.rb10
-rw-r--r--yjit_codegen.c22
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 {