mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
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.
This commit is contained in:
parent
54db64f7a5
commit
812597676b
2 changed files with 21 additions and 11 deletions
|
@ -152,6 +152,16 @@ class TestYJIT < Test::Unit::TestCase
|
||||||
RUBY
|
RUBY
|
||||||
end
|
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
|
def test_fib_recursion
|
||||||
assert_compiles(<<~'RUBY', insns: %i[opt_le opt_minus opt_plus opt_send_without_block], result: 34)
|
assert_compiles(<<~'RUBY', insns: %i[opt_le opt_minus opt_plus opt_send_without_block], result: 34)
|
||||||
def fib(n)
|
def fib(n)
|
||||||
|
|
|
@ -1758,9 +1758,6 @@ gen_defined(jitstate_t* jit, ctx_t* ctx)
|
||||||
static codegen_status_t
|
static codegen_status_t
|
||||||
gen_checktype(jitstate_t* jit, ctx_t* ctx)
|
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);
|
enum ruby_value_type type_val = (enum ruby_value_type)jit_get_arg(jit, 0);
|
||||||
// Only three types are emitted by compile.c
|
// Only three types are emitted by compile.c
|
||||||
if (type_val == T_STRING || type_val == T_ARRAY || type_val == T_HASH) {
|
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, REG0, val);
|
||||||
|
mov(cb, REG1, imm_opnd(Qfalse));
|
||||||
|
|
||||||
|
uint32_t ret = cb_new_label(cb, "ret");
|
||||||
|
|
||||||
if (!val_type.is_heap) {
|
if (!val_type.is_heap) {
|
||||||
// if (SPECIAL_CONST_P(val)) {
|
// 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));
|
test(cb, REG0, imm_opnd(RUBY_IMMEDIATE_MASK));
|
||||||
jnz_ptr(cb, side_exit);
|
jnz_label(cb, ret);
|
||||||
cmp(cb, REG0, imm_opnd(Qfalse));
|
|
||||||
je_ptr(cb, side_exit);
|
|
||||||
cmp(cb, REG0, imm_opnd(Qnil));
|
cmp(cb, REG0, imm_opnd(Qnil));
|
||||||
je_ptr(cb, side_exit);
|
jbe_label(cb, ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check type on object
|
// Check type on object
|
||||||
|
@ -1802,11 +1800,13 @@ gen_checktype(jitstate_t* jit, ctx_t* ctx)
|
||||||
and(cb, REG0, imm_opnd(RUBY_T_MASK));
|
and(cb, REG0, imm_opnd(RUBY_T_MASK));
|
||||||
cmp(cb, REG0, imm_opnd(type_val));
|
cmp(cb, REG0, imm_opnd(type_val));
|
||||||
mov(cb, REG0, imm_opnd(Qtrue));
|
mov(cb, REG0, imm_opnd(Qtrue));
|
||||||
mov(cb, REG1, imm_opnd(Qfalse));
|
// REG1 contains Qfalse from above
|
||||||
cmovne(cb, REG0, REG1);
|
cmove(cb, REG1, REG0);
|
||||||
|
|
||||||
|
cb_write_label(cb, ret);
|
||||||
stack_ret = ctx_stack_push(ctx, TYPE_IMM);
|
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;
|
return YJIT_KEEP_COMPILING;
|
||||||
} else {
|
} else {
|
||||||
|
|
Loading…
Add table
Reference in a new issue