ruby-changes:69016
From: John <ko1@a...>
Date: Thu, 21 Oct 2021 08:20:12 +0900 (JST)
Subject: [ruby-changes:69016] dfc5e5e35b (master): Support guards against symbols and integers
https://git.ruby-lang.org/ruby.git/commit/?id=dfc5e5e35b From dfc5e5e35b927bcfc26af0b59d4952e97bdfb0f7 Mon Sep 17 00:00:00 2001 From: John Hawthorn <john@h...> Date: Tue, 22 Jun 2021 19:22:30 -0700 Subject: Support guards against symbols and integers This adds guards --- bootstraptest/test_yjit.rb | 52 ++++++++++++++++++++++++++++++++++++++++++++++ yjit_codegen.c | 26 ++++++++++++++++++++--- yjit_core.h | 1 + 3 files changed, 76 insertions(+), 3 deletions(-) diff --git a/bootstraptest/test_yjit.rb b/bootstraptest/test_yjit.rb index fc0b693ec2..db494b7911 100644 --- a/bootstraptest/test_yjit.rb +++ b/bootstraptest/test_yjit.rb @@ -1295,3 +1295,55 @@ assert_equal '[:B, [:B, :m]]', %q{ https://github.com/ruby/ruby/blob/trunk/bootstraptest/test_yjit.rb#L1295 ins.singleton_class.define_method(:bar, B.instance_method(:foo)) ins.bar } + +# Call to fixnum +assert_equal '[true, false]', %q{ + def is_odd(obj) + obj.odd? + end + + is_odd(1) + is_odd(1) + + [is_odd(123), is_odd(456)] +} + +# Call to bignum +assert_equal '[true, false]', %q{ + def is_odd(obj) + obj.odd? + end + + bignum = 99999999999999999999 + is_odd(bignum) + is_odd(bignum) + + [is_odd(bignum), is_odd(bignum+1)] +} + +# Call to fixnum and bignum +assert_equal '[true, false, true, false]', %q{ + def is_odd(obj) + obj.odd? + end + + bignum = 99999999999999999999 + is_odd(bignum) + is_odd(bignum) + is_odd(123) + is_odd(123) + + [is_odd(123), is_odd(456), is_odd(bignum), is_odd(bignum+1)] +} + +# Call to static and dynamic symbol +assert_equal 'bar', %q{ + def to_string(obj) + obj.to_s + end + + to_string(:foo) + to_string(:foo) + to_string((-"bar").to_sym) + to_string((-"bar").to_sym) +} diff --git a/yjit_codegen.c b/yjit_codegen.c index b5edf86460..0def2f9402 100644 --- a/yjit_codegen.c +++ b/yjit_codegen.c @@ -2250,9 +2250,29 @@ jit_guard_known_klass(jitstate_t *jit, ctx_t *ctx, VALUE known_klass, insn_opnd_ https://github.com/ruby/ruby/blob/trunk/yjit_codegen.c#L2250 ctx_set_opnd_type(ctx, insn_opnd, TYPE_FALSE); } } - else if (known_klass == rb_cInteger || - known_klass == rb_cSymbol || - known_klass == rb_cFloat) { + else if (known_klass == rb_cInteger && FIXNUM_P(sample_instance)) { + // We will guard FIXNUM and BIGNUM as though they were separate classes + // BIGNUM can be handled by the general else case below + if (val_type.type != ETYPE_FIXNUM || !val_type.is_imm) { + ADD_COMMENT(cb, "guard object is fixnum"); + test(cb, REG0, imm_opnd(RUBY_FIXNUM_FLAG)); + jit_chain_guard(JCC_JZ, jit, ctx, max_chain_depth, side_exit); + ctx_set_opnd_type(ctx, insn_opnd, TYPE_FIXNUM); + } + } + else if (known_klass == rb_cSymbol && STATIC_SYM_P(sample_instance)) { + // We will guard STATIC vs DYNAMIC as though they were separate classes + // DYNAMIC symbols can be handled by the general else case below + if (val_type.type != ETYPE_SYMBOL || !val_type.is_imm) { + ADD_COMMENT(cb, "guard object is static symbol"); + STATIC_ASSERT(special_shift_is_8, RUBY_SPECIAL_SHIFT == 8); + cmp(cb, REG0_8, imm_opnd(RUBY_SYMBOL_FLAG)); + jit_chain_guard(JCC_JNE, jit, ctx, max_chain_depth, side_exit); + + ctx_set_opnd_type(ctx, insn_opnd, TYPE_STATIC_SYMBOL); + } + } + else if (known_klass == rb_cFloat) { // Can't guard for for these classes because they can have both // immediate (special const) instances and instances on the heap. Can // remove this by adding appropriate dynamic checks. diff --git a/yjit_core.h b/yjit_core.h index a2436e6eb3..5939f5b74b 100644 --- a/yjit_core.h +++ b/yjit_core.h @@ -69,6 +69,7 @@ STATIC_ASSERT(val_type_size, sizeof(val_type_t) == 1); https://github.com/ruby/ruby/blob/trunk/yjit_core.h#L69 #define TYPE_TRUE ( (val_type_t){ .is_imm = 1, .type = ETYPE_TRUE } ) #define TYPE_FALSE ( (val_type_t){ .is_imm = 1, .type = ETYPE_FALSE } ) #define TYPE_FIXNUM ( (val_type_t){ .is_imm = 1, .type = ETYPE_FIXNUM } ) +#define TYPE_STATIC_SYMBOL ( (val_type_t){ .is_imm = 1, .type = ETYPE_SYMBOL } ) #define TYPE_ARRAY ( (val_type_t){ .is_heap = 1, .type = ETYPE_ARRAY } ) #define TYPE_HASH ( (val_type_t){ .is_heap = 1, .type = ETYPE_HASH } ) #define TYPE_STRING ( (val_type_t){ .is_heap = 1, .type = ETYPE_STRING } ) -- cgit v1.2.1 -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/