ruby-changes:69051
From: John <ko1@a...>
Date: Thu, 21 Oct 2021 08:20:39 +0900 (JST)
Subject: [ruby-changes:69051] 812597676b (master): Avoid immediate side exits in checktype
https://git.ruby-lang.org/ruby.git/commit/?id=812597676b From 812597676ba2b1e3c41c50e9da624441e0c40a6b Mon Sep 17 00:00:00 2001 From: John Hawthorn <john@h...> Date: Thu, 26 Aug 2021 11:45:05 -0700 Subject: 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. --- test/ruby/test_yjit.rb | 10 ++++++++++ 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 https://github.com/ruby/ruby/blob/trunk/test/ruby/test_yjit.rb#L152 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) https://github.com/ruby/ruby/blob/trunk/yjit_codegen.c#L1758 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) https://github.com/ruby/ruby/blob/trunk/yjit_codegen.c#L1782 } 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) https://github.com/ruby/ruby/blob/trunk/yjit_codegen.c#L1800 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 { -- cgit v1.2.1 -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/